11cb0ef41Sopenharmony_ci 21cb0ef41Sopenharmony_ci#include "node_snapshotable.h" 31cb0ef41Sopenharmony_ci#include <iostream> 41cb0ef41Sopenharmony_ci#include <sstream> 51cb0ef41Sopenharmony_ci#include <vector> 61cb0ef41Sopenharmony_ci#include "base_object-inl.h" 71cb0ef41Sopenharmony_ci#include "blob_serializer_deserializer-inl.h" 81cb0ef41Sopenharmony_ci#include "debug_utils-inl.h" 91cb0ef41Sopenharmony_ci#include "env-inl.h" 101cb0ef41Sopenharmony_ci#include "node_blob.h" 111cb0ef41Sopenharmony_ci#include "node_builtins.h" 121cb0ef41Sopenharmony_ci#include "node_contextify.h" 131cb0ef41Sopenharmony_ci#include "node_errors.h" 141cb0ef41Sopenharmony_ci#include "node_external_reference.h" 151cb0ef41Sopenharmony_ci#include "node_file.h" 161cb0ef41Sopenharmony_ci#include "node_internals.h" 171cb0ef41Sopenharmony_ci#include "node_main_instance.h" 181cb0ef41Sopenharmony_ci#include "node_metadata.h" 191cb0ef41Sopenharmony_ci#include "node_process.h" 201cb0ef41Sopenharmony_ci#include "node_snapshot_builder.h" 211cb0ef41Sopenharmony_ci#include "node_url.h" 221cb0ef41Sopenharmony_ci#include "node_util.h" 231cb0ef41Sopenharmony_ci#include "node_v8.h" 241cb0ef41Sopenharmony_ci#include "node_v8_platform-inl.h" 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci#if HAVE_INSPECTOR 271cb0ef41Sopenharmony_ci#include "inspector/worker_inspector.h" // ParentInspectorHandle 281cb0ef41Sopenharmony_ci#endif 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_cinamespace node { 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ciusing v8::Context; 331cb0ef41Sopenharmony_ciusing v8::Function; 341cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo; 351cb0ef41Sopenharmony_ciusing v8::HandleScope; 361cb0ef41Sopenharmony_ciusing v8::Isolate; 371cb0ef41Sopenharmony_ciusing v8::Local; 381cb0ef41Sopenharmony_ciusing v8::Object; 391cb0ef41Sopenharmony_ciusing v8::ObjectTemplate; 401cb0ef41Sopenharmony_ciusing v8::ScriptCompiler; 411cb0ef41Sopenharmony_ciusing v8::ScriptOrigin; 421cb0ef41Sopenharmony_ciusing v8::SnapshotCreator; 431cb0ef41Sopenharmony_ciusing v8::StartupData; 441cb0ef41Sopenharmony_ciusing v8::String; 451cb0ef41Sopenharmony_ciusing v8::TryCatch; 461cb0ef41Sopenharmony_ciusing v8::Value; 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ciconst uint32_t SnapshotData::kMagic; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, 511cb0ef41Sopenharmony_ci const builtins::CodeCacheInfo& info) { 521cb0ef41Sopenharmony_ci output << "<builtins::CodeCacheInfo id=" << info.id 531cb0ef41Sopenharmony_ci << ", size=" << info.data.size() << ">\n"; 541cb0ef41Sopenharmony_ci return output; 551cb0ef41Sopenharmony_ci} 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, 581cb0ef41Sopenharmony_ci const std::vector<builtins::CodeCacheInfo>& vec) { 591cb0ef41Sopenharmony_ci output << "{\n"; 601cb0ef41Sopenharmony_ci for (const auto& info : vec) { 611cb0ef41Sopenharmony_ci output << info; 621cb0ef41Sopenharmony_ci } 631cb0ef41Sopenharmony_ci output << "}\n"; 641cb0ef41Sopenharmony_ci return output; 651cb0ef41Sopenharmony_ci} 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, 681cb0ef41Sopenharmony_ci const std::vector<uint8_t>& vec) { 691cb0ef41Sopenharmony_ci output << "{\n"; 701cb0ef41Sopenharmony_ci for (const auto& i : vec) { 711cb0ef41Sopenharmony_ci output << i << ","; 721cb0ef41Sopenharmony_ci } 731cb0ef41Sopenharmony_ci output << "}"; 741cb0ef41Sopenharmony_ci return output; 751cb0ef41Sopenharmony_ci} 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, 781cb0ef41Sopenharmony_ci const std::vector<PropInfo>& vec) { 791cb0ef41Sopenharmony_ci output << "{\n"; 801cb0ef41Sopenharmony_ci for (const auto& info : vec) { 811cb0ef41Sopenharmony_ci output << " " << info << ",\n"; 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci output << "}"; 841cb0ef41Sopenharmony_ci return output; 851cb0ef41Sopenharmony_ci} 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, const PropInfo& info) { 881cb0ef41Sopenharmony_ci output << "{ \"" << info.name << "\", " << std::to_string(info.id) << ", " 891cb0ef41Sopenharmony_ci << std::to_string(info.index) << " }"; 901cb0ef41Sopenharmony_ci return output; 911cb0ef41Sopenharmony_ci} 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, 941cb0ef41Sopenharmony_ci const std::vector<std::string>& vec) { 951cb0ef41Sopenharmony_ci output << "{\n"; 961cb0ef41Sopenharmony_ci for (const auto& info : vec) { 971cb0ef41Sopenharmony_ci output << " \"" << info << "\",\n"; 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci output << "}"; 1001cb0ef41Sopenharmony_ci return output; 1011cb0ef41Sopenharmony_ci} 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, const RealmSerializeInfo& i) { 1041cb0ef41Sopenharmony_ci output << "{\n" 1051cb0ef41Sopenharmony_ci << "// -- builtins begins --\n" 1061cb0ef41Sopenharmony_ci << i.builtins << ",\n" 1071cb0ef41Sopenharmony_ci << "// -- builtins ends --\n" 1081cb0ef41Sopenharmony_ci << "// -- persistent_values begins --\n" 1091cb0ef41Sopenharmony_ci << i.persistent_values << ",\n" 1101cb0ef41Sopenharmony_ci << "// -- persistent_values ends --\n" 1111cb0ef41Sopenharmony_ci << "// -- native_objects begins --\n" 1121cb0ef41Sopenharmony_ci << i.native_objects << ",\n" 1131cb0ef41Sopenharmony_ci << "// -- native_objects ends --\n" 1141cb0ef41Sopenharmony_ci << i.context << ", // context\n" 1151cb0ef41Sopenharmony_ci << "}"; 1161cb0ef41Sopenharmony_ci return output; 1171cb0ef41Sopenharmony_ci} 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) { 1201cb0ef41Sopenharmony_ci output << "{\n" 1211cb0ef41Sopenharmony_ci << "// -- async_hooks begins --\n" 1221cb0ef41Sopenharmony_ci << i.async_hooks << ",\n" 1231cb0ef41Sopenharmony_ci << "// -- async_hooks ends --\n" 1241cb0ef41Sopenharmony_ci << i.tick_info << ", // tick_info\n" 1251cb0ef41Sopenharmony_ci << i.immediate_info << ", // immediate_info\n" 1261cb0ef41Sopenharmony_ci << i.timeout_info << ", // timeout_info\n" 1271cb0ef41Sopenharmony_ci << "// -- performance_state begins --\n" 1281cb0ef41Sopenharmony_ci << i.performance_state << ",\n" 1291cb0ef41Sopenharmony_ci << "// -- performance_state ends --\n" 1301cb0ef41Sopenharmony_ci << i.exiting << ", // exiting\n" 1311cb0ef41Sopenharmony_ci << i.stream_base_state << ", // stream_base_state\n" 1321cb0ef41Sopenharmony_ci << i.should_abort_on_uncaught_toggle 1331cb0ef41Sopenharmony_ci << ", // should_abort_on_uncaught_toggle\n" 1341cb0ef41Sopenharmony_ci << "// -- principal_realm begins --\n" 1351cb0ef41Sopenharmony_ci << i.principal_realm << ",\n" 1361cb0ef41Sopenharmony_ci << "// -- principal_realm ends --\n" 1371cb0ef41Sopenharmony_ci << "}"; 1381cb0ef41Sopenharmony_ci return output; 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ciclass SnapshotSerializerDeserializer { 1421cb0ef41Sopenharmony_ci public: 1431cb0ef41Sopenharmony_ci SnapshotSerializerDeserializer() 1441cb0ef41Sopenharmony_ci : is_debug(per_process::enabled_debug_list.enabled( 1451cb0ef41Sopenharmony_ci DebugCategory::MKSNAPSHOT)) {} 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci template <typename... Args> 1481cb0ef41Sopenharmony_ci void Debug(const char* format, Args&&... args) const { 1491cb0ef41Sopenharmony_ci per_process::Debug( 1501cb0ef41Sopenharmony_ci DebugCategory::MKSNAPSHOT, format, std::forward<Args>(args)...); 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci template <typename T> 1541cb0ef41Sopenharmony_ci std::string ToStr(const T& arg) const { 1551cb0ef41Sopenharmony_ci std::stringstream ss; 1561cb0ef41Sopenharmony_ci ss << arg; 1571cb0ef41Sopenharmony_ci return ss.str(); 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci template <typename T> 1611cb0ef41Sopenharmony_ci std::string GetName() const { 1621cb0ef41Sopenharmony_ci#define TYPE_LIST(V) \ 1631cb0ef41Sopenharmony_ci V(builtins::CodeCacheInfo) \ 1641cb0ef41Sopenharmony_ci V(PropInfo) \ 1651cb0ef41Sopenharmony_ci V(std::string) 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci#define V(TypeName) \ 1681cb0ef41Sopenharmony_ci if constexpr (std::is_same_v<T, TypeName>) { \ 1691cb0ef41Sopenharmony_ci return #TypeName; \ 1701cb0ef41Sopenharmony_ci } else // NOLINT(readability/braces) 1711cb0ef41Sopenharmony_ci TYPE_LIST(V) 1721cb0ef41Sopenharmony_ci#undef V 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci if constexpr (std::is_arithmetic_v<T>) { 1751cb0ef41Sopenharmony_ci return (std::is_unsigned_v<T> ? "uint" 1761cb0ef41Sopenharmony_ci : std::is_integral_v<T> ? "int" 1771cb0ef41Sopenharmony_ci : "float") + 1781cb0ef41Sopenharmony_ci std::to_string(sizeof(T) * 8) + "_t"; 1791cb0ef41Sopenharmony_ci } 1801cb0ef41Sopenharmony_ci return ""; 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci bool is_debug = false; 1841cb0ef41Sopenharmony_ci}; 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ciclass SnapshotDeserializer : public SnapshotSerializerDeserializer { 1871cb0ef41Sopenharmony_ci public: 1881cb0ef41Sopenharmony_ci explicit SnapshotDeserializer(const std::vector<char>& s) 1891cb0ef41Sopenharmony_ci : SnapshotSerializerDeserializer(), sink(s) {} 1901cb0ef41Sopenharmony_ci ~SnapshotDeserializer() {} 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci // Helper for reading numeric types. 1931cb0ef41Sopenharmony_ci template <typename T> 1941cb0ef41Sopenharmony_ci T Read() { 1951cb0ef41Sopenharmony_ci static_assert(std::is_arithmetic_v<T>, "Not an arithmetic type"); 1961cb0ef41Sopenharmony_ci T result; 1971cb0ef41Sopenharmony_ci Read(&result, 1); 1981cb0ef41Sopenharmony_ci return result; 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci // Layout of vectors: 2021cb0ef41Sopenharmony_ci // [ 4/8 bytes ] count 2031cb0ef41Sopenharmony_ci // [ ... ] contents (count * size of individual elements) 2041cb0ef41Sopenharmony_ci template <typename T> 2051cb0ef41Sopenharmony_ci std::vector<T> ReadVector() { 2061cb0ef41Sopenharmony_ci if (is_debug) { 2071cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 2081cb0ef41Sopenharmony_ci Debug("\nReadVector<%s>()(%d-byte)\n", name.c_str(), sizeof(T)); 2091cb0ef41Sopenharmony_ci } 2101cb0ef41Sopenharmony_ci size_t count = static_cast<size_t>(Read<size_t>()); 2111cb0ef41Sopenharmony_ci if (count == 0) { 2121cb0ef41Sopenharmony_ci return std::vector<T>(); 2131cb0ef41Sopenharmony_ci } 2141cb0ef41Sopenharmony_ci if (is_debug) { 2151cb0ef41Sopenharmony_ci Debug("Reading %d vector elements...\n", count); 2161cb0ef41Sopenharmony_ci } 2171cb0ef41Sopenharmony_ci std::vector<T> result = ReadVector<T>(count, std::is_arithmetic<T>{}); 2181cb0ef41Sopenharmony_ci if (is_debug) { 2191cb0ef41Sopenharmony_ci std::string str = std::is_arithmetic_v<T> ? "" : ToStr(result); 2201cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 2211cb0ef41Sopenharmony_ci Debug("ReadVector<%s>() read %s\n", name.c_str(), str.c_str()); 2221cb0ef41Sopenharmony_ci } 2231cb0ef41Sopenharmony_ci return result; 2241cb0ef41Sopenharmony_ci } 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci std::string ReadString() { 2271cb0ef41Sopenharmony_ci size_t length = Read<size_t>(); 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci if (is_debug) { 2301cb0ef41Sopenharmony_ci Debug("ReadString(), length=%d: ", length); 2311cb0ef41Sopenharmony_ci } 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci CHECK_GT(length, 0); // There should be no empty strings. 2341cb0ef41Sopenharmony_ci MallocedBuffer<char> buf(length + 1); 2351cb0ef41Sopenharmony_ci memcpy(buf.data, sink.data() + read_total, length + 1); 2361cb0ef41Sopenharmony_ci std::string result(buf.data, length); // This creates a copy of buf.data. 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_ci if (is_debug) { 2391cb0ef41Sopenharmony_ci Debug("\"%s\", read %zu bytes\n", result.c_str(), length + 1); 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci read_total += length + 1; 2431cb0ef41Sopenharmony_ci return result; 2441cb0ef41Sopenharmony_ci } 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci size_t read_total = 0; 2471cb0ef41Sopenharmony_ci const std::vector<char>& sink; 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci private: 2501cb0ef41Sopenharmony_ci // Helper for reading an array of numeric types. 2511cb0ef41Sopenharmony_ci template <typename T> 2521cb0ef41Sopenharmony_ci void Read(T* out, size_t count) { 2531cb0ef41Sopenharmony_ci static_assert(std::is_arithmetic_v<T>, "Not an arithmetic type"); 2541cb0ef41Sopenharmony_ci DCHECK_GT(count, 0); // Should not read contents for vectors of size 0. 2551cb0ef41Sopenharmony_ci if (is_debug) { 2561cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 2571cb0ef41Sopenharmony_ci Debug("Read<%s>()(%d-byte), count=%d: ", name.c_str(), sizeof(T), count); 2581cb0ef41Sopenharmony_ci } 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci size_t size = sizeof(T) * count; 2611cb0ef41Sopenharmony_ci memcpy(out, sink.data() + read_total, size); 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci if (is_debug) { 2641cb0ef41Sopenharmony_ci std::string str = 2651cb0ef41Sopenharmony_ci "{ " + std::to_string(out[0]) + (count > 1 ? ", ... }" : " }"); 2661cb0ef41Sopenharmony_ci Debug("%s, read %zu bytes\n", str.c_str(), size); 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci read_total += size; 2691cb0ef41Sopenharmony_ci } 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_ci // Helper for reading numeric vectors. 2721cb0ef41Sopenharmony_ci template <typename Number> 2731cb0ef41Sopenharmony_ci std::vector<Number> ReadVector(size_t count, std::true_type) { 2741cb0ef41Sopenharmony_ci static_assert(std::is_arithmetic_v<Number>, "Not an arithmetic type"); 2751cb0ef41Sopenharmony_ci DCHECK_GT(count, 0); // Should not read contents for vectors of size 0. 2761cb0ef41Sopenharmony_ci std::vector<Number> result(count); 2771cb0ef41Sopenharmony_ci Read(result.data(), count); 2781cb0ef41Sopenharmony_ci return result; 2791cb0ef41Sopenharmony_ci } 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci // Helper for reading non-numeric vectors. 2821cb0ef41Sopenharmony_ci template <typename T> 2831cb0ef41Sopenharmony_ci std::vector<T> ReadVector(size_t count, std::false_type) { 2841cb0ef41Sopenharmony_ci static_assert(!std::is_arithmetic_v<T>, "Arithmetic type"); 2851cb0ef41Sopenharmony_ci DCHECK_GT(count, 0); // Should not read contents for vectors of size 0. 2861cb0ef41Sopenharmony_ci std::vector<T> result; 2871cb0ef41Sopenharmony_ci result.reserve(count); 2881cb0ef41Sopenharmony_ci bool original_is_debug = is_debug; 2891cb0ef41Sopenharmony_ci is_debug = original_is_debug && !std::is_same_v<T, std::string>; 2901cb0ef41Sopenharmony_ci for (size_t i = 0; i < count; ++i) { 2911cb0ef41Sopenharmony_ci if (is_debug) { 2921cb0ef41Sopenharmony_ci Debug("\n[%d] ", i); 2931cb0ef41Sopenharmony_ci } 2941cb0ef41Sopenharmony_ci result.push_back(Read<T>()); 2951cb0ef41Sopenharmony_ci } 2961cb0ef41Sopenharmony_ci is_debug = original_is_debug; 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci return result; 2991cb0ef41Sopenharmony_ci } 3001cb0ef41Sopenharmony_ci}; 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ciclass SnapshotSerializer : public SnapshotSerializerDeserializer { 3031cb0ef41Sopenharmony_ci public: 3041cb0ef41Sopenharmony_ci SnapshotSerializer() : SnapshotSerializerDeserializer() { 3051cb0ef41Sopenharmony_ci // Currently the snapshot blob built with an empty script is around 4MB. 3061cb0ef41Sopenharmony_ci // So use that as the default sink size. 3071cb0ef41Sopenharmony_ci sink.reserve(4 * 1024 * 1024); 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci ~SnapshotSerializer() {} 3101cb0ef41Sopenharmony_ci std::vector<char> sink; 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci // Helper for writing numeric types. 3131cb0ef41Sopenharmony_ci template <typename T> 3141cb0ef41Sopenharmony_ci size_t Write(const T& data) { 3151cb0ef41Sopenharmony_ci static_assert(std::is_arithmetic_v<T>, "Not an arithmetic type"); 3161cb0ef41Sopenharmony_ci return Write(&data, 1); 3171cb0ef41Sopenharmony_ci } 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci // Layout of vectors: 3201cb0ef41Sopenharmony_ci // [ 4/8 bytes ] count 3211cb0ef41Sopenharmony_ci // [ ... ] contents (count * size of individual elements) 3221cb0ef41Sopenharmony_ci template <typename T> 3231cb0ef41Sopenharmony_ci size_t WriteVector(const std::vector<T>& data) { 3241cb0ef41Sopenharmony_ci if (is_debug) { 3251cb0ef41Sopenharmony_ci std::string str = std::is_arithmetic_v<T> ? "" : ToStr(data); 3261cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 3271cb0ef41Sopenharmony_ci Debug("\nWriteVector<%s>() (%d-byte), count=%d: %s\n", 3281cb0ef41Sopenharmony_ci name.c_str(), 3291cb0ef41Sopenharmony_ci sizeof(T), 3301cb0ef41Sopenharmony_ci data.size(), 3311cb0ef41Sopenharmony_ci str.c_str()); 3321cb0ef41Sopenharmony_ci } 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci size_t written_total = Write<size_t>(data.size()); 3351cb0ef41Sopenharmony_ci if (data.size() == 0) { 3361cb0ef41Sopenharmony_ci return written_total; 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci written_total += WriteVector<T>(data, std::is_arithmetic<T>{}); 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci if (is_debug) { 3411cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 3421cb0ef41Sopenharmony_ci Debug("WriteVector<%s>() wrote %d bytes\n", name.c_str(), written_total); 3431cb0ef41Sopenharmony_ci } 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_ci return written_total; 3461cb0ef41Sopenharmony_ci } 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci // The layout of a written string: 3491cb0ef41Sopenharmony_ci // [ 4/8 bytes ] length 3501cb0ef41Sopenharmony_ci // [ |length| bytes ] contents 3511cb0ef41Sopenharmony_ci size_t WriteString(const std::string& data) { 3521cb0ef41Sopenharmony_ci CHECK_GT(data.size(), 0); // No empty strings should be written. 3531cb0ef41Sopenharmony_ci size_t written_total = Write<size_t>(data.size()); 3541cb0ef41Sopenharmony_ci if (is_debug) { 3551cb0ef41Sopenharmony_ci std::string str = ToStr(data); 3561cb0ef41Sopenharmony_ci Debug("WriteString(), length=%zu: \"%s\"\n", data.size(), data.c_str()); 3571cb0ef41Sopenharmony_ci } 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci // Write the null-terminated string. 3601cb0ef41Sopenharmony_ci size_t length = data.size() + 1; 3611cb0ef41Sopenharmony_ci sink.insert(sink.end(), data.c_str(), data.c_str() + length); 3621cb0ef41Sopenharmony_ci written_total += length; 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ci if (is_debug) { 3651cb0ef41Sopenharmony_ci Debug("WriteString() wrote %zu bytes\n", written_total); 3661cb0ef41Sopenharmony_ci } 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ci return written_total; 3691cb0ef41Sopenharmony_ci } 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci private: 3721cb0ef41Sopenharmony_ci // Helper for writing an array of numeric types. 3731cb0ef41Sopenharmony_ci template <typename T> 3741cb0ef41Sopenharmony_ci size_t Write(const T* data, size_t count) { 3751cb0ef41Sopenharmony_ci DCHECK_GT(count, 0); // Should not write contents for vectors of size 0. 3761cb0ef41Sopenharmony_ci if (is_debug) { 3771cb0ef41Sopenharmony_ci std::string str = 3781cb0ef41Sopenharmony_ci "{ " + std::to_string(data[0]) + (count > 1 ? ", ... }" : " }"); 3791cb0ef41Sopenharmony_ci std::string name = GetName<T>(); 3801cb0ef41Sopenharmony_ci Debug("Write<%s>() (%zu-byte), count=%zu: %s", 3811cb0ef41Sopenharmony_ci name.c_str(), 3821cb0ef41Sopenharmony_ci sizeof(T), 3831cb0ef41Sopenharmony_ci count, 3841cb0ef41Sopenharmony_ci str.c_str()); 3851cb0ef41Sopenharmony_ci } 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci size_t size = sizeof(T) * count; 3881cb0ef41Sopenharmony_ci const char* pos = reinterpret_cast<const char*>(data); 3891cb0ef41Sopenharmony_ci sink.insert(sink.end(), pos, pos + size); 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci if (is_debug) { 3921cb0ef41Sopenharmony_ci Debug(", wrote %zu bytes\n", size); 3931cb0ef41Sopenharmony_ci } 3941cb0ef41Sopenharmony_ci return size; 3951cb0ef41Sopenharmony_ci } 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ci // Helper for writing numeric vectors. 3981cb0ef41Sopenharmony_ci template <typename Number> 3991cb0ef41Sopenharmony_ci size_t WriteVector(const std::vector<Number>& data, std::true_type) { 4001cb0ef41Sopenharmony_ci return Write(data.data(), data.size()); 4011cb0ef41Sopenharmony_ci } 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci // Helper for writing non-numeric vectors. 4041cb0ef41Sopenharmony_ci template <typename T> 4051cb0ef41Sopenharmony_ci size_t WriteVector(const std::vector<T>& data, std::false_type) { 4061cb0ef41Sopenharmony_ci DCHECK_GT(data.size(), 4071cb0ef41Sopenharmony_ci 0); // Should not write contents for vectors of size 0. 4081cb0ef41Sopenharmony_ci size_t written_total = 0; 4091cb0ef41Sopenharmony_ci bool original_is_debug = is_debug; 4101cb0ef41Sopenharmony_ci is_debug = original_is_debug && !std::is_same_v<T, std::string>; 4111cb0ef41Sopenharmony_ci for (size_t i = 0; i < data.size(); ++i) { 4121cb0ef41Sopenharmony_ci if (is_debug) { 4131cb0ef41Sopenharmony_ci Debug("\n[%d] ", i); 4141cb0ef41Sopenharmony_ci } 4151cb0ef41Sopenharmony_ci written_total += Write<T>(data[i]); 4161cb0ef41Sopenharmony_ci } 4171cb0ef41Sopenharmony_ci is_debug = original_is_debug; 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci return written_total; 4201cb0ef41Sopenharmony_ci } 4211cb0ef41Sopenharmony_ci}; 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci// Layout of serialized std::string: 4241cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length 4251cb0ef41Sopenharmony_ci// [ |length| bytes ] contents 4261cb0ef41Sopenharmony_citemplate <> 4271cb0ef41Sopenharmony_cistd::string SnapshotDeserializer::Read() { 4281cb0ef41Sopenharmony_ci return ReadString(); 4291cb0ef41Sopenharmony_ci} 4301cb0ef41Sopenharmony_citemplate <> 4311cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const std::string& data) { 4321cb0ef41Sopenharmony_ci return WriteString(data); 4331cb0ef41Sopenharmony_ci} 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci// Layout of v8::StartupData 4361cb0ef41Sopenharmony_ci// [ 4/8 bytes ] raw_size 4371cb0ef41Sopenharmony_ci// [ |raw_size| bytes ] contents 4381cb0ef41Sopenharmony_citemplate <> 4391cb0ef41Sopenharmony_civ8::StartupData SnapshotDeserializer::Read() { 4401cb0ef41Sopenharmony_ci Debug("Read<v8::StartupData>()\n"); 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ci int raw_size = Read<int>(); 4431cb0ef41Sopenharmony_ci Debug("size=%d\n", raw_size); 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ci CHECK_GT(raw_size, 0); // There should be no startup data of size 0. 4461cb0ef41Sopenharmony_ci // The data pointer of v8::StartupData would be deleted so it must be new'ed. 4471cb0ef41Sopenharmony_ci std::unique_ptr<char> buf = std::unique_ptr<char>(new char[raw_size]); 4481cb0ef41Sopenharmony_ci Read<char>(buf.get(), raw_size); 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ci return v8::StartupData{buf.release(), raw_size}; 4511cb0ef41Sopenharmony_ci} 4521cb0ef41Sopenharmony_ci 4531cb0ef41Sopenharmony_citemplate <> 4541cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const v8::StartupData& data) { 4551cb0ef41Sopenharmony_ci Debug("\nWrite<v8::StartupData>() size=%d\n", data.raw_size); 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_ci CHECK_GT(data.raw_size, 0); // There should be no startup data of size 0. 4581cb0ef41Sopenharmony_ci size_t written_total = Write<int>(data.raw_size); 4591cb0ef41Sopenharmony_ci written_total += Write<char>(data.data, static_cast<size_t>(data.raw_size)); 4601cb0ef41Sopenharmony_ci 4611cb0ef41Sopenharmony_ci Debug("Write<v8::StartupData>() wrote %d bytes\n\n", written_total); 4621cb0ef41Sopenharmony_ci return written_total; 4631cb0ef41Sopenharmony_ci} 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci// Layout of builtins::CodeCacheInfo 4661cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of the module id string 4671cb0ef41Sopenharmony_ci// [ ... ] |length| bytes of module id 4681cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of module code cache 4691cb0ef41Sopenharmony_ci// [ ... ] |length| bytes of module code cache 4701cb0ef41Sopenharmony_citemplate <> 4711cb0ef41Sopenharmony_cibuiltins::CodeCacheInfo SnapshotDeserializer::Read() { 4721cb0ef41Sopenharmony_ci Debug("Read<builtins::CodeCacheInfo>()\n"); 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci builtins::CodeCacheInfo result{ReadString(), ReadVector<uint8_t>()}; 4751cb0ef41Sopenharmony_ci 4761cb0ef41Sopenharmony_ci if (is_debug) { 4771cb0ef41Sopenharmony_ci std::string str = ToStr(result); 4781cb0ef41Sopenharmony_ci Debug("Read<builtins::CodeCacheInfo>() %s\n", str.c_str()); 4791cb0ef41Sopenharmony_ci } 4801cb0ef41Sopenharmony_ci return result; 4811cb0ef41Sopenharmony_ci} 4821cb0ef41Sopenharmony_ci 4831cb0ef41Sopenharmony_citemplate <> 4841cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const builtins::CodeCacheInfo& data) { 4851cb0ef41Sopenharmony_ci Debug("\nWrite<builtins::CodeCacheInfo>() id = %s" 4861cb0ef41Sopenharmony_ci ", size=%d\n", 4871cb0ef41Sopenharmony_ci data.id.c_str(), 4881cb0ef41Sopenharmony_ci data.data.size()); 4891cb0ef41Sopenharmony_ci 4901cb0ef41Sopenharmony_ci size_t written_total = WriteString(data.id); 4911cb0ef41Sopenharmony_ci written_total += WriteVector<uint8_t>(data.data); 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci Debug("Write<builtins::CodeCacheInfo>() wrote %d bytes\n", written_total); 4941cb0ef41Sopenharmony_ci return written_total; 4951cb0ef41Sopenharmony_ci} 4961cb0ef41Sopenharmony_ci 4971cb0ef41Sopenharmony_ci// Layout of PropInfo 4981cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of the data name string 4991cb0ef41Sopenharmony_ci// [ ... ] |length| bytes of data name 5001cb0ef41Sopenharmony_ci// [ 4 bytes ] index in the PropInfo vector 5011cb0ef41Sopenharmony_ci// [ 4/8 bytes ] index in the snapshot blob, can be used with 5021cb0ef41Sopenharmony_ci// GetDataFromSnapshotOnce(). 5031cb0ef41Sopenharmony_citemplate <> 5041cb0ef41Sopenharmony_ciPropInfo SnapshotDeserializer::Read() { 5051cb0ef41Sopenharmony_ci Debug("Read<PropInfo>()\n"); 5061cb0ef41Sopenharmony_ci 5071cb0ef41Sopenharmony_ci PropInfo result; 5081cb0ef41Sopenharmony_ci result.name = ReadString(); 5091cb0ef41Sopenharmony_ci result.id = Read<uint32_t>(); 5101cb0ef41Sopenharmony_ci result.index = Read<SnapshotIndex>(); 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ci if (is_debug) { 5131cb0ef41Sopenharmony_ci std::string str = ToStr(result); 5141cb0ef41Sopenharmony_ci Debug("Read<PropInfo>() %s\n", str.c_str()); 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci return result; 5181cb0ef41Sopenharmony_ci} 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_citemplate <> 5211cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const PropInfo& data) { 5221cb0ef41Sopenharmony_ci if (is_debug) { 5231cb0ef41Sopenharmony_ci std::string str = ToStr(data); 5241cb0ef41Sopenharmony_ci Debug("Write<PropInfo>() %s\n", str.c_str()); 5251cb0ef41Sopenharmony_ci } 5261cb0ef41Sopenharmony_ci 5271cb0ef41Sopenharmony_ci size_t written_total = WriteString(data.name); 5281cb0ef41Sopenharmony_ci written_total += Write<uint32_t>(data.id); 5291cb0ef41Sopenharmony_ci written_total += Write<SnapshotIndex>(data.index); 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci Debug("Write<PropInfo>() wrote %d bytes\n", written_total); 5321cb0ef41Sopenharmony_ci return written_total; 5331cb0ef41Sopenharmony_ci} 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_ci// Layout of AsyncHooks::SerializeInfo 5361cb0ef41Sopenharmony_ci// [ 4/8 bytes ] snapshot index of async_ids_stack 5371cb0ef41Sopenharmony_ci// [ 4/8 bytes ] snapshot index of fields 5381cb0ef41Sopenharmony_ci// [ 4/8 bytes ] snapshot index of async_id_fields 5391cb0ef41Sopenharmony_ci// [ 4/8 bytes ] snapshot index of js_execution_async_resources 5401cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of native_execution_async_resources 5411cb0ef41Sopenharmony_ci// [ ... ] snapshot indices of each element in 5421cb0ef41Sopenharmony_ci// native_execution_async_resources 5431cb0ef41Sopenharmony_citemplate <> 5441cb0ef41Sopenharmony_ciAsyncHooks::SerializeInfo SnapshotDeserializer::Read() { 5451cb0ef41Sopenharmony_ci Debug("Read<AsyncHooks::SerializeInfo>()\n"); 5461cb0ef41Sopenharmony_ci 5471cb0ef41Sopenharmony_ci AsyncHooks::SerializeInfo result; 5481cb0ef41Sopenharmony_ci result.async_ids_stack = Read<AliasedBufferIndex>(); 5491cb0ef41Sopenharmony_ci result.fields = Read<AliasedBufferIndex>(); 5501cb0ef41Sopenharmony_ci result.async_id_fields = Read<AliasedBufferIndex>(); 5511cb0ef41Sopenharmony_ci result.js_execution_async_resources = Read<SnapshotIndex>(); 5521cb0ef41Sopenharmony_ci result.native_execution_async_resources = ReadVector<SnapshotIndex>(); 5531cb0ef41Sopenharmony_ci 5541cb0ef41Sopenharmony_ci if (is_debug) { 5551cb0ef41Sopenharmony_ci std::string str = ToStr(result); 5561cb0ef41Sopenharmony_ci Debug("Read<AsyncHooks::SerializeInfo>() %s\n", str.c_str()); 5571cb0ef41Sopenharmony_ci } 5581cb0ef41Sopenharmony_ci 5591cb0ef41Sopenharmony_ci return result; 5601cb0ef41Sopenharmony_ci} 5611cb0ef41Sopenharmony_citemplate <> 5621cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const AsyncHooks::SerializeInfo& data) { 5631cb0ef41Sopenharmony_ci if (is_debug) { 5641cb0ef41Sopenharmony_ci std::string str = ToStr(data); 5651cb0ef41Sopenharmony_ci Debug("Write<AsyncHooks::SerializeInfo>() %s\n", str.c_str()); 5661cb0ef41Sopenharmony_ci } 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_ci size_t written_total = Write<AliasedBufferIndex>(data.async_ids_stack); 5691cb0ef41Sopenharmony_ci written_total += Write<AliasedBufferIndex>(data.fields); 5701cb0ef41Sopenharmony_ci written_total += Write<AliasedBufferIndex>(data.async_id_fields); 5711cb0ef41Sopenharmony_ci written_total += Write<SnapshotIndex>(data.js_execution_async_resources); 5721cb0ef41Sopenharmony_ci written_total += 5731cb0ef41Sopenharmony_ci WriteVector<SnapshotIndex>(data.native_execution_async_resources); 5741cb0ef41Sopenharmony_ci 5751cb0ef41Sopenharmony_ci Debug("Write<AsyncHooks::SerializeInfo>() wrote %d bytes\n", written_total); 5761cb0ef41Sopenharmony_ci return written_total; 5771cb0ef41Sopenharmony_ci} 5781cb0ef41Sopenharmony_ci 5791cb0ef41Sopenharmony_ci// Layout of TickInfo::SerializeInfo 5801cb0ef41Sopenharmony_ci// [ 4/8 bytes ] snapshot index of fields 5811cb0ef41Sopenharmony_citemplate <> 5821cb0ef41Sopenharmony_ciTickInfo::SerializeInfo SnapshotDeserializer::Read() { 5831cb0ef41Sopenharmony_ci Debug("Read<TickInfo::SerializeInfo>()\n"); 5841cb0ef41Sopenharmony_ci 5851cb0ef41Sopenharmony_ci TickInfo::SerializeInfo result; 5861cb0ef41Sopenharmony_ci result.fields = Read<AliasedBufferIndex>(); 5871cb0ef41Sopenharmony_ci 5881cb0ef41Sopenharmony_ci if (is_debug) { 5891cb0ef41Sopenharmony_ci std::string str = ToStr(result); 5901cb0ef41Sopenharmony_ci Debug("Read<TickInfo::SerializeInfo>() %s\n", str.c_str()); 5911cb0ef41Sopenharmony_ci } 5921cb0ef41Sopenharmony_ci 5931cb0ef41Sopenharmony_ci return result; 5941cb0ef41Sopenharmony_ci} 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_citemplate <> 5971cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const TickInfo::SerializeInfo& data) { 5981cb0ef41Sopenharmony_ci if (is_debug) { 5991cb0ef41Sopenharmony_ci std::string str = ToStr(data); 6001cb0ef41Sopenharmony_ci Debug("Write<TickInfo::SerializeInfo>() %s\n", str.c_str()); 6011cb0ef41Sopenharmony_ci } 6021cb0ef41Sopenharmony_ci 6031cb0ef41Sopenharmony_ci size_t written_total = Write<AliasedBufferIndex>(data.fields); 6041cb0ef41Sopenharmony_ci 6051cb0ef41Sopenharmony_ci Debug("Write<TickInfo::SerializeInfo>() wrote %d bytes\n", written_total); 6061cb0ef41Sopenharmony_ci return written_total; 6071cb0ef41Sopenharmony_ci} 6081cb0ef41Sopenharmony_ci 6091cb0ef41Sopenharmony_ci// Layout of TickInfo::SerializeInfo 6101cb0ef41Sopenharmony_ci// [ 4/8 bytes ] snapshot index of fields 6111cb0ef41Sopenharmony_citemplate <> 6121cb0ef41Sopenharmony_ciImmediateInfo::SerializeInfo SnapshotDeserializer::Read() { 6131cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, 6141cb0ef41Sopenharmony_ci "Read<ImmediateInfo::SerializeInfo>()\n"); 6151cb0ef41Sopenharmony_ci 6161cb0ef41Sopenharmony_ci ImmediateInfo::SerializeInfo result; 6171cb0ef41Sopenharmony_ci result.fields = Read<AliasedBufferIndex>(); 6181cb0ef41Sopenharmony_ci if (is_debug) { 6191cb0ef41Sopenharmony_ci std::string str = ToStr(result); 6201cb0ef41Sopenharmony_ci Debug("Read<ImmediateInfo::SerializeInfo>() %s\n", str.c_str()); 6211cb0ef41Sopenharmony_ci } 6221cb0ef41Sopenharmony_ci return result; 6231cb0ef41Sopenharmony_ci} 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_citemplate <> 6261cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const ImmediateInfo::SerializeInfo& data) { 6271cb0ef41Sopenharmony_ci if (is_debug) { 6281cb0ef41Sopenharmony_ci std::string str = ToStr(data); 6291cb0ef41Sopenharmony_ci Debug("Write<ImmediateInfo::SerializeInfo>() %s\n", str.c_str()); 6301cb0ef41Sopenharmony_ci } 6311cb0ef41Sopenharmony_ci 6321cb0ef41Sopenharmony_ci size_t written_total = Write<AliasedBufferIndex>(data.fields); 6331cb0ef41Sopenharmony_ci 6341cb0ef41Sopenharmony_ci Debug("Write<ImmediateInfo::SerializeInfo>() wrote %d bytes\n", 6351cb0ef41Sopenharmony_ci written_total); 6361cb0ef41Sopenharmony_ci return written_total; 6371cb0ef41Sopenharmony_ci} 6381cb0ef41Sopenharmony_ci 6391cb0ef41Sopenharmony_ci// Layout of PerformanceState::SerializeInfo 6401cb0ef41Sopenharmony_ci// [ 4/8 bytes ] snapshot index of root 6411cb0ef41Sopenharmony_ci// [ 4/8 bytes ] snapshot index of milestones 6421cb0ef41Sopenharmony_ci// [ 4/8 bytes ] snapshot index of observers 6431cb0ef41Sopenharmony_citemplate <> 6441cb0ef41Sopenharmony_ciperformance::PerformanceState::SerializeInfo SnapshotDeserializer::Read() { 6451cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, 6461cb0ef41Sopenharmony_ci "Read<PerformanceState::SerializeInfo>()\n"); 6471cb0ef41Sopenharmony_ci 6481cb0ef41Sopenharmony_ci performance::PerformanceState::SerializeInfo result; 6491cb0ef41Sopenharmony_ci result.root = Read<AliasedBufferIndex>(); 6501cb0ef41Sopenharmony_ci result.milestones = Read<AliasedBufferIndex>(); 6511cb0ef41Sopenharmony_ci result.observers = Read<AliasedBufferIndex>(); 6521cb0ef41Sopenharmony_ci if (is_debug) { 6531cb0ef41Sopenharmony_ci std::string str = ToStr(result); 6541cb0ef41Sopenharmony_ci Debug("Read<PerformanceState::SerializeInfo>() %s\n", str.c_str()); 6551cb0ef41Sopenharmony_ci } 6561cb0ef41Sopenharmony_ci return result; 6571cb0ef41Sopenharmony_ci} 6581cb0ef41Sopenharmony_ci 6591cb0ef41Sopenharmony_citemplate <> 6601cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write( 6611cb0ef41Sopenharmony_ci const performance::PerformanceState::SerializeInfo& data) { 6621cb0ef41Sopenharmony_ci if (is_debug) { 6631cb0ef41Sopenharmony_ci std::string str = ToStr(data); 6641cb0ef41Sopenharmony_ci Debug("Write<PerformanceState::SerializeInfo>() %s\n", str.c_str()); 6651cb0ef41Sopenharmony_ci } 6661cb0ef41Sopenharmony_ci 6671cb0ef41Sopenharmony_ci size_t written_total = Write<AliasedBufferIndex>(data.root); 6681cb0ef41Sopenharmony_ci written_total += Write<AliasedBufferIndex>(data.milestones); 6691cb0ef41Sopenharmony_ci written_total += Write<AliasedBufferIndex>(data.observers); 6701cb0ef41Sopenharmony_ci 6711cb0ef41Sopenharmony_ci Debug("Write<PerformanceState::SerializeInfo>() wrote %d bytes\n", 6721cb0ef41Sopenharmony_ci written_total); 6731cb0ef41Sopenharmony_ci return written_total; 6741cb0ef41Sopenharmony_ci} 6751cb0ef41Sopenharmony_ci 6761cb0ef41Sopenharmony_ci// Layout of IsolateDataSerializeInfo 6771cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of primitive_values vector 6781cb0ef41Sopenharmony_ci// [ ... ] |length| of primitive_values indices 6791cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of template_values vector 6801cb0ef41Sopenharmony_ci// [ ... ] |length| of PropInfo data 6811cb0ef41Sopenharmony_citemplate <> 6821cb0ef41Sopenharmony_ciIsolateDataSerializeInfo SnapshotDeserializer::Read() { 6831cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, 6841cb0ef41Sopenharmony_ci "Read<IsolateDataSerializeInfo>()\n"); 6851cb0ef41Sopenharmony_ci 6861cb0ef41Sopenharmony_ci IsolateDataSerializeInfo result; 6871cb0ef41Sopenharmony_ci result.primitive_values = ReadVector<SnapshotIndex>(); 6881cb0ef41Sopenharmony_ci result.template_values = ReadVector<PropInfo>(); 6891cb0ef41Sopenharmony_ci if (is_debug) { 6901cb0ef41Sopenharmony_ci std::string str = ToStr(result); 6911cb0ef41Sopenharmony_ci Debug("Read<IsolateDataSerializeInfo>() %s\n", str.c_str()); 6921cb0ef41Sopenharmony_ci } 6931cb0ef41Sopenharmony_ci return result; 6941cb0ef41Sopenharmony_ci} 6951cb0ef41Sopenharmony_ci 6961cb0ef41Sopenharmony_citemplate <> 6971cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const IsolateDataSerializeInfo& data) { 6981cb0ef41Sopenharmony_ci if (is_debug) { 6991cb0ef41Sopenharmony_ci std::string str = ToStr(data); 7001cb0ef41Sopenharmony_ci Debug("Write<IsolateDataSerializeInfo>() %s\n", str.c_str()); 7011cb0ef41Sopenharmony_ci } 7021cb0ef41Sopenharmony_ci 7031cb0ef41Sopenharmony_ci size_t written_total = WriteVector<SnapshotIndex>(data.primitive_values); 7041cb0ef41Sopenharmony_ci written_total += WriteVector<PropInfo>(data.template_values); 7051cb0ef41Sopenharmony_ci 7061cb0ef41Sopenharmony_ci Debug("Write<IsolateDataSerializeInfo>() wrote %d bytes\n", written_total); 7071cb0ef41Sopenharmony_ci return written_total; 7081cb0ef41Sopenharmony_ci} 7091cb0ef41Sopenharmony_ci 7101cb0ef41Sopenharmony_citemplate <> 7111cb0ef41Sopenharmony_ciRealmSerializeInfo SnapshotDeserializer::Read() { 7121cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, "Read<RealmSerializeInfo>()\n"); 7131cb0ef41Sopenharmony_ci RealmSerializeInfo result; 7141cb0ef41Sopenharmony_ci result.builtins = ReadVector<std::string>(); 7151cb0ef41Sopenharmony_ci result.persistent_values = ReadVector<PropInfo>(); 7161cb0ef41Sopenharmony_ci result.native_objects = ReadVector<PropInfo>(); 7171cb0ef41Sopenharmony_ci result.context = Read<SnapshotIndex>(); 7181cb0ef41Sopenharmony_ci return result; 7191cb0ef41Sopenharmony_ci} 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_citemplate <> 7221cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const RealmSerializeInfo& data) { 7231cb0ef41Sopenharmony_ci if (is_debug) { 7241cb0ef41Sopenharmony_ci std::string str = ToStr(data); 7251cb0ef41Sopenharmony_ci Debug("\nWrite<RealmSerializeInfo>() %s\n", str.c_str()); 7261cb0ef41Sopenharmony_ci } 7271cb0ef41Sopenharmony_ci 7281cb0ef41Sopenharmony_ci // Use += here to ensure order of evaluation. 7291cb0ef41Sopenharmony_ci size_t written_total = WriteVector<std::string>(data.builtins); 7301cb0ef41Sopenharmony_ci written_total += WriteVector<PropInfo>(data.persistent_values); 7311cb0ef41Sopenharmony_ci written_total += WriteVector<PropInfo>(data.native_objects); 7321cb0ef41Sopenharmony_ci written_total += Write<SnapshotIndex>(data.context); 7331cb0ef41Sopenharmony_ci 7341cb0ef41Sopenharmony_ci Debug("Write<RealmSerializeInfo>() wrote %d bytes\n", written_total); 7351cb0ef41Sopenharmony_ci return written_total; 7361cb0ef41Sopenharmony_ci} 7371cb0ef41Sopenharmony_ci 7381cb0ef41Sopenharmony_citemplate <> 7391cb0ef41Sopenharmony_ciEnvSerializeInfo SnapshotDeserializer::Read() { 7401cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, "Read<EnvSerializeInfo>()\n"); 7411cb0ef41Sopenharmony_ci EnvSerializeInfo result; 7421cb0ef41Sopenharmony_ci result.async_hooks = Read<AsyncHooks::SerializeInfo>(); 7431cb0ef41Sopenharmony_ci result.tick_info = Read<TickInfo::SerializeInfo>(); 7441cb0ef41Sopenharmony_ci result.immediate_info = Read<ImmediateInfo::SerializeInfo>(); 7451cb0ef41Sopenharmony_ci result.timeout_info = Read<AliasedBufferIndex>(); 7461cb0ef41Sopenharmony_ci result.performance_state = 7471cb0ef41Sopenharmony_ci Read<performance::PerformanceState::SerializeInfo>(); 7481cb0ef41Sopenharmony_ci result.exiting = Read<AliasedBufferIndex>(); 7491cb0ef41Sopenharmony_ci result.stream_base_state = Read<AliasedBufferIndex>(); 7501cb0ef41Sopenharmony_ci result.should_abort_on_uncaught_toggle = Read<AliasedBufferIndex>(); 7511cb0ef41Sopenharmony_ci result.principal_realm = Read<RealmSerializeInfo>(); 7521cb0ef41Sopenharmony_ci return result; 7531cb0ef41Sopenharmony_ci} 7541cb0ef41Sopenharmony_ci 7551cb0ef41Sopenharmony_citemplate <> 7561cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const EnvSerializeInfo& data) { 7571cb0ef41Sopenharmony_ci if (is_debug) { 7581cb0ef41Sopenharmony_ci std::string str = ToStr(data); 7591cb0ef41Sopenharmony_ci Debug("\nWrite<EnvSerializeInfo>() %s\n", str.c_str()); 7601cb0ef41Sopenharmony_ci } 7611cb0ef41Sopenharmony_ci 7621cb0ef41Sopenharmony_ci // Use += here to ensure order of evaluation. 7631cb0ef41Sopenharmony_ci size_t written_total = Write<AsyncHooks::SerializeInfo>(data.async_hooks); 7641cb0ef41Sopenharmony_ci written_total += Write<TickInfo::SerializeInfo>(data.tick_info); 7651cb0ef41Sopenharmony_ci written_total += Write<ImmediateInfo::SerializeInfo>(data.immediate_info); 7661cb0ef41Sopenharmony_ci written_total += Write<AliasedBufferIndex>(data.timeout_info); 7671cb0ef41Sopenharmony_ci written_total += Write<performance::PerformanceState::SerializeInfo>( 7681cb0ef41Sopenharmony_ci data.performance_state); 7691cb0ef41Sopenharmony_ci written_total += Write<AliasedBufferIndex>(data.exiting); 7701cb0ef41Sopenharmony_ci written_total += Write<AliasedBufferIndex>(data.stream_base_state); 7711cb0ef41Sopenharmony_ci written_total += 7721cb0ef41Sopenharmony_ci Write<AliasedBufferIndex>(data.should_abort_on_uncaught_toggle); 7731cb0ef41Sopenharmony_ci written_total += Write<RealmSerializeInfo>(data.principal_realm); 7741cb0ef41Sopenharmony_ci 7751cb0ef41Sopenharmony_ci Debug("Write<EnvSerializeInfo>() wrote %d bytes\n", written_total); 7761cb0ef41Sopenharmony_ci return written_total; 7771cb0ef41Sopenharmony_ci} 7781cb0ef41Sopenharmony_ci 7791cb0ef41Sopenharmony_ci// Layout of SnapshotMetadata 7801cb0ef41Sopenharmony_ci// [ 1 byte ] type of the snapshot 7811cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of the node version string 7821cb0ef41Sopenharmony_ci// [ ... ] |length| bytes of node version 7831cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of the node arch string 7841cb0ef41Sopenharmony_ci// [ ... ] |length| bytes of node arch 7851cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of the node platform string 7861cb0ef41Sopenharmony_ci// [ ... ] |length| bytes of node platform 7871cb0ef41Sopenharmony_ci// [ 4 bytes ] v8 cache version tag 7881cb0ef41Sopenharmony_citemplate <> 7891cb0ef41Sopenharmony_ciSnapshotMetadata SnapshotDeserializer::Read() { 7901cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, "Read<SnapshotMetadata>()\n"); 7911cb0ef41Sopenharmony_ci 7921cb0ef41Sopenharmony_ci SnapshotMetadata result; 7931cb0ef41Sopenharmony_ci result.type = static_cast<SnapshotMetadata::Type>(Read<uint8_t>()); 7941cb0ef41Sopenharmony_ci result.node_version = ReadString(); 7951cb0ef41Sopenharmony_ci result.node_arch = ReadString(); 7961cb0ef41Sopenharmony_ci result.node_platform = ReadString(); 7971cb0ef41Sopenharmony_ci result.v8_cache_version_tag = Read<uint32_t>(); 7981cb0ef41Sopenharmony_ci 7991cb0ef41Sopenharmony_ci if (is_debug) { 8001cb0ef41Sopenharmony_ci std::string str = ToStr(result); 8011cb0ef41Sopenharmony_ci Debug("Read<SnapshotMetadata>() %s\n", str.c_str()); 8021cb0ef41Sopenharmony_ci } 8031cb0ef41Sopenharmony_ci return result; 8041cb0ef41Sopenharmony_ci} 8051cb0ef41Sopenharmony_ci 8061cb0ef41Sopenharmony_citemplate <> 8071cb0ef41Sopenharmony_cisize_t SnapshotSerializer::Write(const SnapshotMetadata& data) { 8081cb0ef41Sopenharmony_ci if (is_debug) { 8091cb0ef41Sopenharmony_ci std::string str = ToStr(data); 8101cb0ef41Sopenharmony_ci Debug("\nWrite<SnapshotMetadata>() %s\n", str.c_str()); 8111cb0ef41Sopenharmony_ci } 8121cb0ef41Sopenharmony_ci size_t written_total = 0; 8131cb0ef41Sopenharmony_ci // We need the Node.js version, platform and arch to match because 8141cb0ef41Sopenharmony_ci // Node.js may perform synchronizations that are platform-specific and they 8151cb0ef41Sopenharmony_ci // can be changed in semver-patches. 8161cb0ef41Sopenharmony_ci Debug("Write snapshot type %" PRIu8 "\n", static_cast<uint8_t>(data.type)); 8171cb0ef41Sopenharmony_ci written_total += Write<uint8_t>(static_cast<uint8_t>(data.type)); 8181cb0ef41Sopenharmony_ci Debug("Write Node.js version %s\n", data.node_version.c_str()); 8191cb0ef41Sopenharmony_ci written_total += WriteString(data.node_version); 8201cb0ef41Sopenharmony_ci Debug("Write Node.js arch %s\n", data.node_arch); 8211cb0ef41Sopenharmony_ci written_total += WriteString(data.node_arch); 8221cb0ef41Sopenharmony_ci Debug("Write Node.js platform %s\n", data.node_platform); 8231cb0ef41Sopenharmony_ci written_total += WriteString(data.node_platform); 8241cb0ef41Sopenharmony_ci Debug("Write V8 cached data version tag %" PRIx32 "\n", 8251cb0ef41Sopenharmony_ci data.v8_cache_version_tag); 8261cb0ef41Sopenharmony_ci written_total += Write<uint32_t>(data.v8_cache_version_tag); 8271cb0ef41Sopenharmony_ci return written_total; 8281cb0ef41Sopenharmony_ci} 8291cb0ef41Sopenharmony_ci 8301cb0ef41Sopenharmony_ci// Layout of the snapshot blob 8311cb0ef41Sopenharmony_ci// [ 4 bytes ] kMagic 8321cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of Node.js version string 8331cb0ef41Sopenharmony_ci// [ ... ] contents of Node.js version string 8341cb0ef41Sopenharmony_ci// [ 4/8 bytes ] length of Node.js arch string 8351cb0ef41Sopenharmony_ci// [ ... ] contents of Node.js arch string 8361cb0ef41Sopenharmony_ci// [ ... ] v8_snapshot_blob_data from SnapshotCreator::CreateBlob() 8371cb0ef41Sopenharmony_ci// [ ... ] isolate_data_info 8381cb0ef41Sopenharmony_ci// [ ... ] env_info 8391cb0ef41Sopenharmony_ci// [ ... ] code_cache 8401cb0ef41Sopenharmony_ci 8411cb0ef41Sopenharmony_civoid SnapshotData::ToBlob(FILE* out) const { 8421cb0ef41Sopenharmony_ci SnapshotSerializer w; 8431cb0ef41Sopenharmony_ci w.Debug("SnapshotData::ToBlob()\n"); 8441cb0ef41Sopenharmony_ci 8451cb0ef41Sopenharmony_ci size_t written_total = 0; 8461cb0ef41Sopenharmony_ci 8471cb0ef41Sopenharmony_ci // Metadata 8481cb0ef41Sopenharmony_ci w.Debug("Write magic %" PRIx32 "\n", kMagic); 8491cb0ef41Sopenharmony_ci written_total += w.Write<uint32_t>(kMagic); 8501cb0ef41Sopenharmony_ci w.Debug("Write metadata\n"); 8511cb0ef41Sopenharmony_ci written_total += w.Write<SnapshotMetadata>(metadata); 8521cb0ef41Sopenharmony_ci 8531cb0ef41Sopenharmony_ci written_total += w.Write<v8::StartupData>(v8_snapshot_blob_data); 8541cb0ef41Sopenharmony_ci w.Debug("Write isolate_data_indices\n"); 8551cb0ef41Sopenharmony_ci written_total += w.Write<IsolateDataSerializeInfo>(isolate_data_info); 8561cb0ef41Sopenharmony_ci written_total += w.Write<EnvSerializeInfo>(env_info); 8571cb0ef41Sopenharmony_ci w.Debug("Write code_cache\n"); 8581cb0ef41Sopenharmony_ci written_total += w.WriteVector<builtins::CodeCacheInfo>(code_cache); 8591cb0ef41Sopenharmony_ci size_t num_written = fwrite(w.sink.data(), w.sink.size(), 1, out); 8601cb0ef41Sopenharmony_ci CHECK_EQ(num_written, 1); 8611cb0ef41Sopenharmony_ci w.Debug("SnapshotData::ToBlob() Wrote %d bytes\n", written_total); 8621cb0ef41Sopenharmony_ci CHECK_EQ(fflush(out), 0); 8631cb0ef41Sopenharmony_ci} 8641cb0ef41Sopenharmony_ci 8651cb0ef41Sopenharmony_cibool SnapshotData::FromBlob(SnapshotData* out, FILE* in) { 8661cb0ef41Sopenharmony_ci CHECK_EQ(ftell(in), 0); 8671cb0ef41Sopenharmony_ci int err = fseek(in, 0, SEEK_END); 8681cb0ef41Sopenharmony_ci CHECK_EQ(err, 0); 8691cb0ef41Sopenharmony_ci size_t size = ftell(in); 8701cb0ef41Sopenharmony_ci CHECK_NE(size, static_cast<size_t>(-1L)); 8711cb0ef41Sopenharmony_ci err = fseek(in, 0, SEEK_SET); 8721cb0ef41Sopenharmony_ci CHECK_EQ(err, 0); 8731cb0ef41Sopenharmony_ci 8741cb0ef41Sopenharmony_ci std::vector<char> sink(size); 8751cb0ef41Sopenharmony_ci size_t num_read = fread(sink.data(), size, 1, in); 8761cb0ef41Sopenharmony_ci CHECK_EQ(num_read, 1); 8771cb0ef41Sopenharmony_ci 8781cb0ef41Sopenharmony_ci SnapshotDeserializer r(sink); 8791cb0ef41Sopenharmony_ci r.Debug("SnapshotData::FromBlob()\n"); 8801cb0ef41Sopenharmony_ci 8811cb0ef41Sopenharmony_ci DCHECK_EQ(out->data_ownership, SnapshotData::DataOwnership::kOwned); 8821cb0ef41Sopenharmony_ci 8831cb0ef41Sopenharmony_ci // Metadata 8841cb0ef41Sopenharmony_ci uint32_t magic = r.Read<uint32_t>(); 8851cb0ef41Sopenharmony_ci r.Debug("Read magic %" PRIx32 "\n", magic); 8861cb0ef41Sopenharmony_ci CHECK_EQ(magic, kMagic); 8871cb0ef41Sopenharmony_ci out->metadata = r.Read<SnapshotMetadata>(); 8881cb0ef41Sopenharmony_ci r.Debug("Read metadata\n"); 8891cb0ef41Sopenharmony_ci if (!out->Check()) { 8901cb0ef41Sopenharmony_ci return false; 8911cb0ef41Sopenharmony_ci } 8921cb0ef41Sopenharmony_ci 8931cb0ef41Sopenharmony_ci out->v8_snapshot_blob_data = r.Read<v8::StartupData>(); 8941cb0ef41Sopenharmony_ci r.Debug("Read isolate_data_info\n"); 8951cb0ef41Sopenharmony_ci out->isolate_data_info = r.Read<IsolateDataSerializeInfo>(); 8961cb0ef41Sopenharmony_ci out->env_info = r.Read<EnvSerializeInfo>(); 8971cb0ef41Sopenharmony_ci r.Debug("Read code_cache\n"); 8981cb0ef41Sopenharmony_ci out->code_cache = r.ReadVector<builtins::CodeCacheInfo>(); 8991cb0ef41Sopenharmony_ci 9001cb0ef41Sopenharmony_ci r.Debug("SnapshotData::FromBlob() read %d bytes\n", r.read_total); 9011cb0ef41Sopenharmony_ci return true; 9021cb0ef41Sopenharmony_ci} 9031cb0ef41Sopenharmony_ci 9041cb0ef41Sopenharmony_cibool SnapshotData::Check() const { 9051cb0ef41Sopenharmony_ci if (metadata.node_version != per_process::metadata.versions.node) { 9061cb0ef41Sopenharmony_ci fprintf(stderr, 9071cb0ef41Sopenharmony_ci "Failed to load the startup snapshot because it was built with" 9081cb0ef41Sopenharmony_ci "Node.js version %s and the current Node.js version is %s.\n", 9091cb0ef41Sopenharmony_ci metadata.node_version.c_str(), 9101cb0ef41Sopenharmony_ci NODE_VERSION); 9111cb0ef41Sopenharmony_ci return false; 9121cb0ef41Sopenharmony_ci } 9131cb0ef41Sopenharmony_ci 9141cb0ef41Sopenharmony_ci if (metadata.node_arch != per_process::metadata.arch) { 9151cb0ef41Sopenharmony_ci fprintf(stderr, 9161cb0ef41Sopenharmony_ci "Failed to load the startup snapshot because it was built with" 9171cb0ef41Sopenharmony_ci "architecture %s and the architecture is %s.\n", 9181cb0ef41Sopenharmony_ci metadata.node_arch.c_str(), 9191cb0ef41Sopenharmony_ci NODE_ARCH); 9201cb0ef41Sopenharmony_ci return false; 9211cb0ef41Sopenharmony_ci } 9221cb0ef41Sopenharmony_ci 9231cb0ef41Sopenharmony_ci if (metadata.node_platform != per_process::metadata.platform) { 9241cb0ef41Sopenharmony_ci fprintf(stderr, 9251cb0ef41Sopenharmony_ci "Failed to load the startup snapshot because it was built with" 9261cb0ef41Sopenharmony_ci "platform %s and the current platform is %s.\n", 9271cb0ef41Sopenharmony_ci metadata.node_platform.c_str(), 9281cb0ef41Sopenharmony_ci NODE_PLATFORM); 9291cb0ef41Sopenharmony_ci return false; 9301cb0ef41Sopenharmony_ci } 9311cb0ef41Sopenharmony_ci 9321cb0ef41Sopenharmony_ci uint32_t current_cache_version = v8::ScriptCompiler::CachedDataVersionTag(); 9331cb0ef41Sopenharmony_ci if (metadata.v8_cache_version_tag != current_cache_version && 9341cb0ef41Sopenharmony_ci metadata.type == SnapshotMetadata::Type::kFullyCustomized) { 9351cb0ef41Sopenharmony_ci // For now we only do this check for the customized snapshots - we know 9361cb0ef41Sopenharmony_ci // that the flags we use in the default snapshot are limited and safe 9371cb0ef41Sopenharmony_ci // enough so we can relax the constraints for it. 9381cb0ef41Sopenharmony_ci fprintf(stderr, 9391cb0ef41Sopenharmony_ci "Failed to load the startup snapshot because it was built with " 9401cb0ef41Sopenharmony_ci "a different version of V8 or with different V8 configurations.\n" 9411cb0ef41Sopenharmony_ci "Expected tag %" PRIx32 ", read %" PRIx32 "\n", 9421cb0ef41Sopenharmony_ci current_cache_version, 9431cb0ef41Sopenharmony_ci metadata.v8_cache_version_tag); 9441cb0ef41Sopenharmony_ci return false; 9451cb0ef41Sopenharmony_ci } 9461cb0ef41Sopenharmony_ci 9471cb0ef41Sopenharmony_ci // TODO(joyeecheung): check incompatible Node.js flags. 9481cb0ef41Sopenharmony_ci return true; 9491cb0ef41Sopenharmony_ci} 9501cb0ef41Sopenharmony_ci 9511cb0ef41Sopenharmony_ciSnapshotData::~SnapshotData() { 9521cb0ef41Sopenharmony_ci if (data_ownership == DataOwnership::kOwned && 9531cb0ef41Sopenharmony_ci v8_snapshot_blob_data.data != nullptr) { 9541cb0ef41Sopenharmony_ci delete[] v8_snapshot_blob_data.data; 9551cb0ef41Sopenharmony_ci } 9561cb0ef41Sopenharmony_ci} 9571cb0ef41Sopenharmony_ci 9581cb0ef41Sopenharmony_citemplate <typename T> 9591cb0ef41Sopenharmony_civoid WriteVector(std::ostream* ss, const T* vec, size_t size) { 9601cb0ef41Sopenharmony_ci for (size_t i = 0; i < size; i++) { 9611cb0ef41Sopenharmony_ci *ss << std::to_string(vec[i]) << (i == size - 1 ? '\n' : ','); 9621cb0ef41Sopenharmony_ci } 9631cb0ef41Sopenharmony_ci} 9641cb0ef41Sopenharmony_ci 9651cb0ef41Sopenharmony_cistatic std::string GetCodeCacheDefName(const std::string& id) { 9661cb0ef41Sopenharmony_ci char buf[64] = {0}; 9671cb0ef41Sopenharmony_ci size_t size = id.size(); 9681cb0ef41Sopenharmony_ci CHECK_LT(size, sizeof(buf)); 9691cb0ef41Sopenharmony_ci for (size_t i = 0; i < size; ++i) { 9701cb0ef41Sopenharmony_ci char ch = id[i]; 9711cb0ef41Sopenharmony_ci buf[i] = (ch == '-' || ch == '/') ? '_' : ch; 9721cb0ef41Sopenharmony_ci } 9731cb0ef41Sopenharmony_ci return std::string(buf) + std::string("_cache_data"); 9741cb0ef41Sopenharmony_ci} 9751cb0ef41Sopenharmony_ci 9761cb0ef41Sopenharmony_cistatic std::string FormatSize(size_t size) { 9771cb0ef41Sopenharmony_ci char buf[64] = {0}; 9781cb0ef41Sopenharmony_ci if (size < 1024) { 9791cb0ef41Sopenharmony_ci snprintf(buf, sizeof(buf), "%.2fB", static_cast<double>(size)); 9801cb0ef41Sopenharmony_ci } else if (size < 1024 * 1024) { 9811cb0ef41Sopenharmony_ci snprintf(buf, sizeof(buf), "%.2fKB", static_cast<double>(size / 1024)); 9821cb0ef41Sopenharmony_ci } else { 9831cb0ef41Sopenharmony_ci snprintf( 9841cb0ef41Sopenharmony_ci buf, sizeof(buf), "%.2fMB", static_cast<double>(size / 1024 / 1024)); 9851cb0ef41Sopenharmony_ci } 9861cb0ef41Sopenharmony_ci return buf; 9871cb0ef41Sopenharmony_ci} 9881cb0ef41Sopenharmony_ci 9891cb0ef41Sopenharmony_cistatic void WriteStaticCodeCacheData(std::ostream* ss, 9901cb0ef41Sopenharmony_ci const builtins::CodeCacheInfo& info) { 9911cb0ef41Sopenharmony_ci *ss << "static const uint8_t " << GetCodeCacheDefName(info.id) << "[] = {\n"; 9921cb0ef41Sopenharmony_ci WriteVector(ss, info.data.data(), info.data.size()); 9931cb0ef41Sopenharmony_ci *ss << "};"; 9941cb0ef41Sopenharmony_ci} 9951cb0ef41Sopenharmony_ci 9961cb0ef41Sopenharmony_cistatic void WriteCodeCacheInitializer(std::ostream* ss, const std::string& id) { 9971cb0ef41Sopenharmony_ci std::string def_name = GetCodeCacheDefName(id); 9981cb0ef41Sopenharmony_ci *ss << " { \"" << id << "\",\n"; 9991cb0ef41Sopenharmony_ci *ss << " {" << def_name << ",\n"; 10001cb0ef41Sopenharmony_ci *ss << " " << def_name << " + arraysize(" << def_name << "),\n"; 10011cb0ef41Sopenharmony_ci *ss << " }\n"; 10021cb0ef41Sopenharmony_ci *ss << " },\n"; 10031cb0ef41Sopenharmony_ci} 10041cb0ef41Sopenharmony_ci 10051cb0ef41Sopenharmony_civoid FormatBlob(std::ostream& ss, const SnapshotData* data) { 10061cb0ef41Sopenharmony_ci ss << R"(#include <cstddef> 10071cb0ef41Sopenharmony_ci#include "env.h" 10081cb0ef41Sopenharmony_ci#include "node_snapshot_builder.h" 10091cb0ef41Sopenharmony_ci#include "v8.h" 10101cb0ef41Sopenharmony_ci 10111cb0ef41Sopenharmony_ci// This file is generated by tools/snapshot. Do not edit. 10121cb0ef41Sopenharmony_ci 10131cb0ef41Sopenharmony_cinamespace node { 10141cb0ef41Sopenharmony_ci 10151cb0ef41Sopenharmony_cistatic const char v8_snapshot_blob_data[] = { 10161cb0ef41Sopenharmony_ci)"; 10171cb0ef41Sopenharmony_ci WriteVector(&ss, 10181cb0ef41Sopenharmony_ci data->v8_snapshot_blob_data.data, 10191cb0ef41Sopenharmony_ci data->v8_snapshot_blob_data.raw_size); 10201cb0ef41Sopenharmony_ci ss << R"(}; 10211cb0ef41Sopenharmony_ci 10221cb0ef41Sopenharmony_cistatic const int v8_snapshot_blob_size = )" 10231cb0ef41Sopenharmony_ci << data->v8_snapshot_blob_data.raw_size << ";"; 10241cb0ef41Sopenharmony_ci 10251cb0ef41Sopenharmony_ci // Windows can't deal with too many large vector initializers. 10261cb0ef41Sopenharmony_ci // Store the data into static arrays first. 10271cb0ef41Sopenharmony_ci for (const auto& item : data->code_cache) { 10281cb0ef41Sopenharmony_ci WriteStaticCodeCacheData(&ss, item); 10291cb0ef41Sopenharmony_ci } 10301cb0ef41Sopenharmony_ci 10311cb0ef41Sopenharmony_ci ss << R"(const SnapshotData snapshot_data { 10321cb0ef41Sopenharmony_ci // -- data_ownership begins -- 10331cb0ef41Sopenharmony_ci SnapshotData::DataOwnership::kNotOwned, 10341cb0ef41Sopenharmony_ci // -- data_ownership ends -- 10351cb0ef41Sopenharmony_ci // -- metadata begins -- 10361cb0ef41Sopenharmony_ci)" << data->metadata 10371cb0ef41Sopenharmony_ci << R"(, 10381cb0ef41Sopenharmony_ci // -- metadata ends -- 10391cb0ef41Sopenharmony_ci // -- v8_snapshot_blob_data begins -- 10401cb0ef41Sopenharmony_ci { v8_snapshot_blob_data, v8_snapshot_blob_size }, 10411cb0ef41Sopenharmony_ci // -- v8_snapshot_blob_data ends -- 10421cb0ef41Sopenharmony_ci // -- isolate_data_info begins -- 10431cb0ef41Sopenharmony_ci)" << data->isolate_data_info 10441cb0ef41Sopenharmony_ci << R"( 10451cb0ef41Sopenharmony_ci // -- isolate_data_info ends -- 10461cb0ef41Sopenharmony_ci , 10471cb0ef41Sopenharmony_ci // -- env_info begins -- 10481cb0ef41Sopenharmony_ci)" << data->env_info 10491cb0ef41Sopenharmony_ci << R"( 10501cb0ef41Sopenharmony_ci // -- env_info ends -- 10511cb0ef41Sopenharmony_ci , 10521cb0ef41Sopenharmony_ci // -- code_cache begins -- 10531cb0ef41Sopenharmony_ci {)"; 10541cb0ef41Sopenharmony_ci for (const auto& item : data->code_cache) { 10551cb0ef41Sopenharmony_ci WriteCodeCacheInitializer(&ss, item.id); 10561cb0ef41Sopenharmony_ci } 10571cb0ef41Sopenharmony_ci ss << R"( 10581cb0ef41Sopenharmony_ci } 10591cb0ef41Sopenharmony_ci // -- code_cache ends -- 10601cb0ef41Sopenharmony_ci}; 10611cb0ef41Sopenharmony_ci 10621cb0ef41Sopenharmony_ciconst SnapshotData* SnapshotBuilder::GetEmbeddedSnapshotData() { 10631cb0ef41Sopenharmony_ci return &snapshot_data; 10641cb0ef41Sopenharmony_ci} 10651cb0ef41Sopenharmony_ci} // namespace node 10661cb0ef41Sopenharmony_ci)"; 10671cb0ef41Sopenharmony_ci} 10681cb0ef41Sopenharmony_ci 10691cb0ef41Sopenharmony_ci// Reset context settings that need to be initialized again after 10701cb0ef41Sopenharmony_ci// deserialization. 10711cb0ef41Sopenharmony_cistatic void ResetContextSettingsBeforeSnapshot(Local<Context> context) { 10721cb0ef41Sopenharmony_ci // Reset the AllowCodeGenerationFromStrings flag to true (default value) so 10731cb0ef41Sopenharmony_ci // that it can be re-initialized with v8 flag 10741cb0ef41Sopenharmony_ci // --disallow-code-generation-from-strings and recognized in 10751cb0ef41Sopenharmony_ci // node::InitializeContextRuntime. 10761cb0ef41Sopenharmony_ci context->AllowCodeGenerationFromStrings(true); 10771cb0ef41Sopenharmony_ci} 10781cb0ef41Sopenharmony_ci 10791cb0ef41Sopenharmony_ciconst std::vector<intptr_t>& SnapshotBuilder::CollectExternalReferences() { 10801cb0ef41Sopenharmony_ci static auto registry = std::make_unique<ExternalReferenceRegistry>(); 10811cb0ef41Sopenharmony_ci return registry->external_references(); 10821cb0ef41Sopenharmony_ci} 10831cb0ef41Sopenharmony_ci 10841cb0ef41Sopenharmony_civoid SnapshotBuilder::InitializeIsolateParams(const SnapshotData* data, 10851cb0ef41Sopenharmony_ci Isolate::CreateParams* params) { 10861cb0ef41Sopenharmony_ci params->external_references = CollectExternalReferences().data(); 10871cb0ef41Sopenharmony_ci params->snapshot_blob = 10881cb0ef41Sopenharmony_ci const_cast<v8::StartupData*>(&(data->v8_snapshot_blob_data)); 10891cb0ef41Sopenharmony_ci} 10901cb0ef41Sopenharmony_ci 10911cb0ef41Sopenharmony_ci// TODO(joyeecheung): share these exit code constants across the code base. 10921cb0ef41Sopenharmony_ciconstexpr int UNCAUGHT_EXCEPTION_ERROR = 1; 10931cb0ef41Sopenharmony_ciconstexpr int BOOTSTRAP_ERROR = 10; 10941cb0ef41Sopenharmony_ciconstexpr int SNAPSHOT_ERROR = 14; 10951cb0ef41Sopenharmony_ci 10961cb0ef41Sopenharmony_ciint SnapshotBuilder::Generate(SnapshotData* out, 10971cb0ef41Sopenharmony_ci const std::vector<std::string> args, 10981cb0ef41Sopenharmony_ci const std::vector<std::string> exec_args) { 10991cb0ef41Sopenharmony_ci const std::vector<intptr_t>& external_references = 11001cb0ef41Sopenharmony_ci CollectExternalReferences(); 11011cb0ef41Sopenharmony_ci Isolate* isolate = Isolate::Allocate(); 11021cb0ef41Sopenharmony_ci // Must be done before the SnapshotCreator creation so that the 11031cb0ef41Sopenharmony_ci // memory reducer can be initialized. 11041cb0ef41Sopenharmony_ci per_process::v8_platform.Platform()->RegisterIsolate(isolate, 11051cb0ef41Sopenharmony_ci uv_default_loop()); 11061cb0ef41Sopenharmony_ci 11071cb0ef41Sopenharmony_ci SnapshotCreator creator(isolate, external_references.data()); 11081cb0ef41Sopenharmony_ci 11091cb0ef41Sopenharmony_ci isolate->SetCaptureStackTraceForUncaughtExceptions( 11101cb0ef41Sopenharmony_ci true, 10, v8::StackTrace::StackTraceOptions::kDetailed); 11111cb0ef41Sopenharmony_ci 11121cb0ef41Sopenharmony_ci Environment* env = nullptr; 11131cb0ef41Sopenharmony_ci std::unique_ptr<NodeMainInstance> main_instance = 11141cb0ef41Sopenharmony_ci NodeMainInstance::Create(isolate, 11151cb0ef41Sopenharmony_ci uv_default_loop(), 11161cb0ef41Sopenharmony_ci per_process::v8_platform.Platform(), 11171cb0ef41Sopenharmony_ci args, 11181cb0ef41Sopenharmony_ci exec_args); 11191cb0ef41Sopenharmony_ci 11201cb0ef41Sopenharmony_ci // The cleanups should be done in case of an early exit due to errors. 11211cb0ef41Sopenharmony_ci auto cleanup = OnScopeLeave([&]() { 11221cb0ef41Sopenharmony_ci // Must be done while the snapshot creator isolate is entered i.e. the 11231cb0ef41Sopenharmony_ci // creator is still alive. The snapshot creator destructor will destroy 11241cb0ef41Sopenharmony_ci // the isolate. 11251cb0ef41Sopenharmony_ci if (env != nullptr) { 11261cb0ef41Sopenharmony_ci FreeEnvironment(env); 11271cb0ef41Sopenharmony_ci } 11281cb0ef41Sopenharmony_ci main_instance->Dispose(); 11291cb0ef41Sopenharmony_ci per_process::v8_platform.Platform()->UnregisterIsolate(isolate); 11301cb0ef41Sopenharmony_ci }); 11311cb0ef41Sopenharmony_ci 11321cb0ef41Sopenharmony_ci // It's only possible to be kDefault in node_mksnapshot. 11331cb0ef41Sopenharmony_ci SnapshotMetadata::Type snapshot_type = 11341cb0ef41Sopenharmony_ci per_process::cli_options->build_snapshot 11351cb0ef41Sopenharmony_ci ? SnapshotMetadata::Type::kFullyCustomized 11361cb0ef41Sopenharmony_ci : SnapshotMetadata::Type::kDefault; 11371cb0ef41Sopenharmony_ci 11381cb0ef41Sopenharmony_ci { 11391cb0ef41Sopenharmony_ci HandleScope scope(isolate); 11401cb0ef41Sopenharmony_ci TryCatch bootstrapCatch(isolate); 11411cb0ef41Sopenharmony_ci 11421cb0ef41Sopenharmony_ci auto print_Exception = OnScopeLeave([&]() { 11431cb0ef41Sopenharmony_ci if (bootstrapCatch.HasCaught()) { 11441cb0ef41Sopenharmony_ci PrintCaughtException( 11451cb0ef41Sopenharmony_ci isolate, isolate->GetCurrentContext(), bootstrapCatch); 11461cb0ef41Sopenharmony_ci } 11471cb0ef41Sopenharmony_ci }); 11481cb0ef41Sopenharmony_ci 11491cb0ef41Sopenharmony_ci // The default context with only things created by V8. 11501cb0ef41Sopenharmony_ci Local<Context> default_context = Context::New(isolate); 11511cb0ef41Sopenharmony_ci 11521cb0ef41Sopenharmony_ci // The context used by the vm module. 11531cb0ef41Sopenharmony_ci Local<Context> vm_context; 11541cb0ef41Sopenharmony_ci { 11551cb0ef41Sopenharmony_ci Local<ObjectTemplate> global_template = 11561cb0ef41Sopenharmony_ci main_instance->isolate_data()->contextify_global_template(); 11571cb0ef41Sopenharmony_ci CHECK(!global_template.IsEmpty()); 11581cb0ef41Sopenharmony_ci if (!contextify::ContextifyContext::CreateV8Context( 11591cb0ef41Sopenharmony_ci isolate, global_template, nullptr, nullptr) 11601cb0ef41Sopenharmony_ci .ToLocal(&vm_context)) { 11611cb0ef41Sopenharmony_ci return SNAPSHOT_ERROR; 11621cb0ef41Sopenharmony_ci } 11631cb0ef41Sopenharmony_ci } 11641cb0ef41Sopenharmony_ci 11651cb0ef41Sopenharmony_ci // The Node.js-specific context with primodials, can be used by workers 11661cb0ef41Sopenharmony_ci // TODO(joyeecheung): investigate if this can be used by vm contexts 11671cb0ef41Sopenharmony_ci // without breaking compatibility. 11681cb0ef41Sopenharmony_ci Local<Context> base_context = NewContext(isolate); 11691cb0ef41Sopenharmony_ci if (base_context.IsEmpty()) { 11701cb0ef41Sopenharmony_ci return BOOTSTRAP_ERROR; 11711cb0ef41Sopenharmony_ci } 11721cb0ef41Sopenharmony_ci ResetContextSettingsBeforeSnapshot(base_context); 11731cb0ef41Sopenharmony_ci 11741cb0ef41Sopenharmony_ci Local<Context> main_context = NewContext(isolate); 11751cb0ef41Sopenharmony_ci if (main_context.IsEmpty()) { 11761cb0ef41Sopenharmony_ci return BOOTSTRAP_ERROR; 11771cb0ef41Sopenharmony_ci } 11781cb0ef41Sopenharmony_ci // Initialize the main instance context. 11791cb0ef41Sopenharmony_ci { 11801cb0ef41Sopenharmony_ci Context::Scope context_scope(main_context); 11811cb0ef41Sopenharmony_ci 11821cb0ef41Sopenharmony_ci // Create the environment. 11831cb0ef41Sopenharmony_ci // It's not guaranteed that a context that goes through 11841cb0ef41Sopenharmony_ci // v8_inspector::V8Inspector::contextCreated() is runtime-independent, 11851cb0ef41Sopenharmony_ci // so do not start the inspector on the main context when building 11861cb0ef41Sopenharmony_ci // the default snapshot. 11871cb0ef41Sopenharmony_ci uint64_t env_flags = EnvironmentFlags::kDefaultFlags | 11881cb0ef41Sopenharmony_ci EnvironmentFlags::kNoCreateInspector; 11891cb0ef41Sopenharmony_ci 11901cb0ef41Sopenharmony_ci env = CreateEnvironment(main_instance->isolate_data(), 11911cb0ef41Sopenharmony_ci main_context, 11921cb0ef41Sopenharmony_ci args, 11931cb0ef41Sopenharmony_ci exec_args, 11941cb0ef41Sopenharmony_ci static_cast<EnvironmentFlags::Flags>(env_flags)); 11951cb0ef41Sopenharmony_ci 11961cb0ef41Sopenharmony_ci // This already ran scripts in lib/internal/bootstrap/, if it fails return 11971cb0ef41Sopenharmony_ci if (env == nullptr) { 11981cb0ef41Sopenharmony_ci return BOOTSTRAP_ERROR; 11991cb0ef41Sopenharmony_ci } 12001cb0ef41Sopenharmony_ci // If --build-snapshot is true, lib/internal/main/mksnapshot.js would be 12011cb0ef41Sopenharmony_ci // loaded via LoadEnvironment() to execute process.argv[1] as the entry 12021cb0ef41Sopenharmony_ci // point (we currently only support this kind of entry point, but we 12031cb0ef41Sopenharmony_ci // could also explore snapshotting other kinds of execution modes 12041cb0ef41Sopenharmony_ci // in the future). 12051cb0ef41Sopenharmony_ci if (snapshot_type == SnapshotMetadata::Type::kFullyCustomized) { 12061cb0ef41Sopenharmony_ci#if HAVE_INSPECTOR 12071cb0ef41Sopenharmony_ci // TODO(joyeecheung): move this before RunBootstrapping(). 12081cb0ef41Sopenharmony_ci env->InitializeInspector({}); 12091cb0ef41Sopenharmony_ci#endif 12101cb0ef41Sopenharmony_ci if (LoadEnvironment(env, StartExecutionCallback{}).IsEmpty()) { 12111cb0ef41Sopenharmony_ci return UNCAUGHT_EXCEPTION_ERROR; 12121cb0ef41Sopenharmony_ci } 12131cb0ef41Sopenharmony_ci // FIXME(joyeecheung): right now running the loop in the snapshot 12141cb0ef41Sopenharmony_ci // builder seems to introduces inconsistencies in JS land that need to 12151cb0ef41Sopenharmony_ci // be synchronized again after snapshot restoration. 12161cb0ef41Sopenharmony_ci int exit_code = SpinEventLoop(env).FromMaybe(UNCAUGHT_EXCEPTION_ERROR); 12171cb0ef41Sopenharmony_ci if (exit_code != 0) { 12181cb0ef41Sopenharmony_ci return exit_code; 12191cb0ef41Sopenharmony_ci } 12201cb0ef41Sopenharmony_ci } 12211cb0ef41Sopenharmony_ci 12221cb0ef41Sopenharmony_ci if (per_process::enabled_debug_list.enabled(DebugCategory::MKSNAPSHOT)) { 12231cb0ef41Sopenharmony_ci env->ForEachRealm([](Realm* realm) { realm->PrintInfoForSnapshot(); }); 12241cb0ef41Sopenharmony_ci printf("Environment = %p\n", env); 12251cb0ef41Sopenharmony_ci } 12261cb0ef41Sopenharmony_ci 12271cb0ef41Sopenharmony_ci // Serialize the native states 12281cb0ef41Sopenharmony_ci out->isolate_data_info = 12291cb0ef41Sopenharmony_ci main_instance->isolate_data()->Serialize(&creator); 12301cb0ef41Sopenharmony_ci out->env_info = env->Serialize(&creator); 12311cb0ef41Sopenharmony_ci 12321cb0ef41Sopenharmony_ci#ifdef NODE_USE_NODE_CODE_CACHE 12331cb0ef41Sopenharmony_ci // Regenerate all the code cache. 12341cb0ef41Sopenharmony_ci if (!env->builtin_loader()->CompileAllBuiltins(main_context)) { 12351cb0ef41Sopenharmony_ci return UNCAUGHT_EXCEPTION_ERROR; 12361cb0ef41Sopenharmony_ci } 12371cb0ef41Sopenharmony_ci env->builtin_loader()->CopyCodeCache(&(out->code_cache)); 12381cb0ef41Sopenharmony_ci for (const auto& item : out->code_cache) { 12391cb0ef41Sopenharmony_ci std::string size_str = FormatSize(item.data.size()); 12401cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, 12411cb0ef41Sopenharmony_ci "Generated code cache for %d: %s\n", 12421cb0ef41Sopenharmony_ci item.id.c_str(), 12431cb0ef41Sopenharmony_ci size_str.c_str()); 12441cb0ef41Sopenharmony_ci } 12451cb0ef41Sopenharmony_ci#endif 12461cb0ef41Sopenharmony_ci 12471cb0ef41Sopenharmony_ci ResetContextSettingsBeforeSnapshot(main_context); 12481cb0ef41Sopenharmony_ci } 12491cb0ef41Sopenharmony_ci 12501cb0ef41Sopenharmony_ci // Global handles to the contexts can't be disposed before the 12511cb0ef41Sopenharmony_ci // blob is created. So initialize all the contexts before adding them. 12521cb0ef41Sopenharmony_ci // TODO(joyeecheung): figure out how to remove this restriction. 12531cb0ef41Sopenharmony_ci creator.SetDefaultContext(default_context); 12541cb0ef41Sopenharmony_ci size_t index = creator.AddContext(vm_context); 12551cb0ef41Sopenharmony_ci CHECK_EQ(index, SnapshotData::kNodeVMContextIndex); 12561cb0ef41Sopenharmony_ci index = creator.AddContext(base_context); 12571cb0ef41Sopenharmony_ci CHECK_EQ(index, SnapshotData::kNodeBaseContextIndex); 12581cb0ef41Sopenharmony_ci index = creator.AddContext(main_context, 12591cb0ef41Sopenharmony_ci {SerializeNodeContextInternalFields, env}); 12601cb0ef41Sopenharmony_ci CHECK_EQ(index, SnapshotData::kNodeMainContextIndex); 12611cb0ef41Sopenharmony_ci } 12621cb0ef41Sopenharmony_ci 12631cb0ef41Sopenharmony_ci // Must be out of HandleScope 12641cb0ef41Sopenharmony_ci out->v8_snapshot_blob_data = 12651cb0ef41Sopenharmony_ci creator.CreateBlob(SnapshotCreator::FunctionCodeHandling::kKeep); 12661cb0ef41Sopenharmony_ci 12671cb0ef41Sopenharmony_ci // We must be able to rehash the blob when we restore it or otherwise 12681cb0ef41Sopenharmony_ci // the hash seed would be fixed by V8, introducing a vulnerability. 12691cb0ef41Sopenharmony_ci if (!out->v8_snapshot_blob_data.CanBeRehashed()) { 12701cb0ef41Sopenharmony_ci return SNAPSHOT_ERROR; 12711cb0ef41Sopenharmony_ci } 12721cb0ef41Sopenharmony_ci 12731cb0ef41Sopenharmony_ci out->metadata = SnapshotMetadata{snapshot_type, 12741cb0ef41Sopenharmony_ci per_process::metadata.versions.node, 12751cb0ef41Sopenharmony_ci per_process::metadata.arch, 12761cb0ef41Sopenharmony_ci per_process::metadata.platform, 12771cb0ef41Sopenharmony_ci v8::ScriptCompiler::CachedDataVersionTag()}; 12781cb0ef41Sopenharmony_ci 12791cb0ef41Sopenharmony_ci // We cannot resurrect the handles from the snapshot, so make sure that 12801cb0ef41Sopenharmony_ci // no handles are left open in the environment after the blob is created 12811cb0ef41Sopenharmony_ci // (which should trigger a GC and close all handles that can be closed). 12821cb0ef41Sopenharmony_ci bool queues_are_empty = 12831cb0ef41Sopenharmony_ci env->req_wrap_queue()->IsEmpty() && env->handle_wrap_queue()->IsEmpty(); 12841cb0ef41Sopenharmony_ci if (!queues_are_empty || 12851cb0ef41Sopenharmony_ci per_process::enabled_debug_list.enabled(DebugCategory::MKSNAPSHOT)) { 12861cb0ef41Sopenharmony_ci PrintLibuvHandleInformation(env->event_loop(), stderr); 12871cb0ef41Sopenharmony_ci } 12881cb0ef41Sopenharmony_ci if (!queues_are_empty) { 12891cb0ef41Sopenharmony_ci return SNAPSHOT_ERROR; 12901cb0ef41Sopenharmony_ci } 12911cb0ef41Sopenharmony_ci return 0; 12921cb0ef41Sopenharmony_ci} 12931cb0ef41Sopenharmony_ci 12941cb0ef41Sopenharmony_ciint SnapshotBuilder::Generate(std::ostream& out, 12951cb0ef41Sopenharmony_ci const std::vector<std::string> args, 12961cb0ef41Sopenharmony_ci const std::vector<std::string> exec_args) { 12971cb0ef41Sopenharmony_ci SnapshotData data; 12981cb0ef41Sopenharmony_ci int exit_code = Generate(&data, args, exec_args); 12991cb0ef41Sopenharmony_ci if (exit_code != 0) { 13001cb0ef41Sopenharmony_ci return exit_code; 13011cb0ef41Sopenharmony_ci } 13021cb0ef41Sopenharmony_ci FormatBlob(out, &data); 13031cb0ef41Sopenharmony_ci return exit_code; 13041cb0ef41Sopenharmony_ci} 13051cb0ef41Sopenharmony_ci 13061cb0ef41Sopenharmony_ciSnapshotableObject::SnapshotableObject(Realm* realm, 13071cb0ef41Sopenharmony_ci Local<Object> wrap, 13081cb0ef41Sopenharmony_ci EmbedderObjectType type) 13091cb0ef41Sopenharmony_ci : BaseObject(realm, wrap), type_(type) {} 13101cb0ef41Sopenharmony_ci 13111cb0ef41Sopenharmony_cistd::string SnapshotableObject::GetTypeName() const { 13121cb0ef41Sopenharmony_ci switch (type_) { 13131cb0ef41Sopenharmony_ci#define V(PropertyName, NativeTypeName) \ 13141cb0ef41Sopenharmony_ci case EmbedderObjectType::k_##PropertyName: { \ 13151cb0ef41Sopenharmony_ci return #NativeTypeName; \ 13161cb0ef41Sopenharmony_ci } 13171cb0ef41Sopenharmony_ci SERIALIZABLE_OBJECT_TYPES(V) 13181cb0ef41Sopenharmony_ci#undef V 13191cb0ef41Sopenharmony_ci default: { UNREACHABLE(); } 13201cb0ef41Sopenharmony_ci } 13211cb0ef41Sopenharmony_ci} 13221cb0ef41Sopenharmony_ci 13231cb0ef41Sopenharmony_civoid DeserializeNodeInternalFields(Local<Object> holder, 13241cb0ef41Sopenharmony_ci int index, 13251cb0ef41Sopenharmony_ci StartupData payload, 13261cb0ef41Sopenharmony_ci void* env) { 13271cb0ef41Sopenharmony_ci if (payload.raw_size == 0) { 13281cb0ef41Sopenharmony_ci holder->SetAlignedPointerInInternalField(index, nullptr); 13291cb0ef41Sopenharmony_ci return; 13301cb0ef41Sopenharmony_ci } 13311cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, 13321cb0ef41Sopenharmony_ci "Deserialize internal field %d of %p, size=%d\n", 13331cb0ef41Sopenharmony_ci static_cast<int>(index), 13341cb0ef41Sopenharmony_ci (*holder), 13351cb0ef41Sopenharmony_ci static_cast<int>(payload.raw_size)); 13361cb0ef41Sopenharmony_ci 13371cb0ef41Sopenharmony_ci if (payload.raw_size == 0) { 13381cb0ef41Sopenharmony_ci holder->SetAlignedPointerInInternalField(index, nullptr); 13391cb0ef41Sopenharmony_ci return; 13401cb0ef41Sopenharmony_ci } 13411cb0ef41Sopenharmony_ci 13421cb0ef41Sopenharmony_ci DCHECK_EQ(index, BaseObject::kEmbedderType); 13431cb0ef41Sopenharmony_ci 13441cb0ef41Sopenharmony_ci Environment* env_ptr = static_cast<Environment*>(env); 13451cb0ef41Sopenharmony_ci const InternalFieldInfoBase* info = 13461cb0ef41Sopenharmony_ci reinterpret_cast<const InternalFieldInfoBase*>(payload.data); 13471cb0ef41Sopenharmony_ci // TODO(joyeecheung): we can add a constant kNodeEmbedderId to the 13481cb0ef41Sopenharmony_ci // beginning of every InternalFieldInfoBase to ensure that we don't 13491cb0ef41Sopenharmony_ci // step on payloads that were not serialized by Node.js. 13501cb0ef41Sopenharmony_ci switch (info->type) { 13511cb0ef41Sopenharmony_ci#define V(PropertyName, NativeTypeName) \ 13521cb0ef41Sopenharmony_ci case EmbedderObjectType::k_##PropertyName: { \ 13531cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, \ 13541cb0ef41Sopenharmony_ci "Object %p is %s\n", \ 13551cb0ef41Sopenharmony_ci (*holder), \ 13561cb0ef41Sopenharmony_ci #NativeTypeName); \ 13571cb0ef41Sopenharmony_ci env_ptr->EnqueueDeserializeRequest( \ 13581cb0ef41Sopenharmony_ci NativeTypeName::Deserialize, \ 13591cb0ef41Sopenharmony_ci holder, \ 13601cb0ef41Sopenharmony_ci index, \ 13611cb0ef41Sopenharmony_ci info->Copy<NativeTypeName::InternalFieldInfo>()); \ 13621cb0ef41Sopenharmony_ci break; \ 13631cb0ef41Sopenharmony_ci } 13641cb0ef41Sopenharmony_ci SERIALIZABLE_OBJECT_TYPES(V) 13651cb0ef41Sopenharmony_ci#undef V 13661cb0ef41Sopenharmony_ci default: { 13671cb0ef41Sopenharmony_ci // This should only be reachable during development when trying to 13681cb0ef41Sopenharmony_ci // deserialize a snapshot blob built by a version of Node.js that 13691cb0ef41Sopenharmony_ci // has more recognizable EmbedderObjectTypes than the deserializing 13701cb0ef41Sopenharmony_ci // Node.js binary. 13711cb0ef41Sopenharmony_ci fprintf(stderr, 13721cb0ef41Sopenharmony_ci "Unknown embedder object type %" PRIu8 ", possibly caused by " 13731cb0ef41Sopenharmony_ci "mismatched Node.js versions\n", 13741cb0ef41Sopenharmony_ci static_cast<uint8_t>(info->type)); 13751cb0ef41Sopenharmony_ci ABORT(); 13761cb0ef41Sopenharmony_ci } 13771cb0ef41Sopenharmony_ci } 13781cb0ef41Sopenharmony_ci} 13791cb0ef41Sopenharmony_ci 13801cb0ef41Sopenharmony_ciStartupData SerializeNodeContextInternalFields(Local<Object> holder, 13811cb0ef41Sopenharmony_ci int index, 13821cb0ef41Sopenharmony_ci void* env) { 13831cb0ef41Sopenharmony_ci // We only do one serialization for the kEmbedderType slot, the result 13841cb0ef41Sopenharmony_ci // contains everything necessary for deserializing the entire object, 13851cb0ef41Sopenharmony_ci // including the fields whose index is bigger than kEmbedderType 13861cb0ef41Sopenharmony_ci // (most importantly, BaseObject::kSlot). 13871cb0ef41Sopenharmony_ci // For Node.js this design is enough for all the native binding that are 13881cb0ef41Sopenharmony_ci // serializable. 13891cb0ef41Sopenharmony_ci if (index != BaseObject::kEmbedderType) { 13901cb0ef41Sopenharmony_ci return StartupData{nullptr, 0}; 13911cb0ef41Sopenharmony_ci } 13921cb0ef41Sopenharmony_ci 13931cb0ef41Sopenharmony_ci void* type_ptr = holder->GetAlignedPointerFromInternalField(index); 13941cb0ef41Sopenharmony_ci if (type_ptr == nullptr) { 13951cb0ef41Sopenharmony_ci return StartupData{nullptr, 0}; 13961cb0ef41Sopenharmony_ci } 13971cb0ef41Sopenharmony_ci 13981cb0ef41Sopenharmony_ci uint16_t type = *(static_cast<uint16_t*>(type_ptr)); 13991cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, "type = 0x%x\n", type); 14001cb0ef41Sopenharmony_ci if (type != kNodeEmbedderId) { 14011cb0ef41Sopenharmony_ci return StartupData{nullptr, 0}; 14021cb0ef41Sopenharmony_ci } 14031cb0ef41Sopenharmony_ci 14041cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, 14051cb0ef41Sopenharmony_ci "Serialize internal field, index=%d, holder=%p\n", 14061cb0ef41Sopenharmony_ci static_cast<int>(index), 14071cb0ef41Sopenharmony_ci *holder); 14081cb0ef41Sopenharmony_ci 14091cb0ef41Sopenharmony_ci void* native_ptr = 14101cb0ef41Sopenharmony_ci holder->GetAlignedPointerFromInternalField(BaseObject::kSlot); 14111cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, "native = %p\n", native_ptr); 14121cb0ef41Sopenharmony_ci DCHECK(static_cast<BaseObject*>(native_ptr)->is_snapshotable()); 14131cb0ef41Sopenharmony_ci SnapshotableObject* obj = static_cast<SnapshotableObject*>(native_ptr); 14141cb0ef41Sopenharmony_ci 14151cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, 14161cb0ef41Sopenharmony_ci "Object %p is %s, ", 14171cb0ef41Sopenharmony_ci *holder, 14181cb0ef41Sopenharmony_ci obj->GetTypeName()); 14191cb0ef41Sopenharmony_ci InternalFieldInfoBase* info = obj->Serialize(index); 14201cb0ef41Sopenharmony_ci 14211cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, 14221cb0ef41Sopenharmony_ci "payload size=%d\n", 14231cb0ef41Sopenharmony_ci static_cast<int>(info->length)); 14241cb0ef41Sopenharmony_ci return StartupData{reinterpret_cast<const char*>(info), 14251cb0ef41Sopenharmony_ci static_cast<int>(info->length)}; 14261cb0ef41Sopenharmony_ci} 14271cb0ef41Sopenharmony_ci 14281cb0ef41Sopenharmony_civoid SerializeSnapshotableObjects(Realm* realm, 14291cb0ef41Sopenharmony_ci SnapshotCreator* creator, 14301cb0ef41Sopenharmony_ci RealmSerializeInfo* info) { 14311cb0ef41Sopenharmony_ci HandleScope scope(realm->isolate()); 14321cb0ef41Sopenharmony_ci Local<Context> context = realm->context(); 14331cb0ef41Sopenharmony_ci uint32_t i = 0; 14341cb0ef41Sopenharmony_ci realm->ForEachBaseObject([&](BaseObject* obj) { 14351cb0ef41Sopenharmony_ci // If there are any BaseObjects that are not snapshotable left 14361cb0ef41Sopenharmony_ci // during context serialization, V8 would crash due to unregistered 14371cb0ef41Sopenharmony_ci // global handles and print detailed information about them. 14381cb0ef41Sopenharmony_ci if (!obj->is_snapshotable()) { 14391cb0ef41Sopenharmony_ci return; 14401cb0ef41Sopenharmony_ci } 14411cb0ef41Sopenharmony_ci SnapshotableObject* ptr = static_cast<SnapshotableObject*>(obj); 14421cb0ef41Sopenharmony_ci 14431cb0ef41Sopenharmony_ci std::string type_name = ptr->GetTypeName(); 14441cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, 14451cb0ef41Sopenharmony_ci "Serialize snapshotable object %i (%p), " 14461cb0ef41Sopenharmony_ci "object=%p, type=%s\n", 14471cb0ef41Sopenharmony_ci static_cast<int>(i), 14481cb0ef41Sopenharmony_ci ptr, 14491cb0ef41Sopenharmony_ci *(ptr->object()), 14501cb0ef41Sopenharmony_ci type_name); 14511cb0ef41Sopenharmony_ci 14521cb0ef41Sopenharmony_ci if (ptr->PrepareForSerialization(context, creator)) { 14531cb0ef41Sopenharmony_ci SnapshotIndex index = creator->AddData(context, obj->object()); 14541cb0ef41Sopenharmony_ci per_process::Debug(DebugCategory::MKSNAPSHOT, 14551cb0ef41Sopenharmony_ci "Serialized with index=%d\n", 14561cb0ef41Sopenharmony_ci static_cast<int>(index)); 14571cb0ef41Sopenharmony_ci info->native_objects.push_back({type_name, i, index}); 14581cb0ef41Sopenharmony_ci } 14591cb0ef41Sopenharmony_ci i++; 14601cb0ef41Sopenharmony_ci }); 14611cb0ef41Sopenharmony_ci} 14621cb0ef41Sopenharmony_ci 14631cb0ef41Sopenharmony_cinamespace mksnapshot { 14641cb0ef41Sopenharmony_ci 14651cb0ef41Sopenharmony_civoid CompileSerializeMain(const FunctionCallbackInfo<Value>& args) { 14661cb0ef41Sopenharmony_ci CHECK(args[0]->IsString()); 14671cb0ef41Sopenharmony_ci Local<String> filename = args[0].As<String>(); 14681cb0ef41Sopenharmony_ci Local<String> source = args[1].As<String>(); 14691cb0ef41Sopenharmony_ci Isolate* isolate = args.GetIsolate(); 14701cb0ef41Sopenharmony_ci Local<Context> context = isolate->GetCurrentContext(); 14711cb0ef41Sopenharmony_ci ScriptOrigin origin(isolate, filename, 0, 0, true); 14721cb0ef41Sopenharmony_ci // TODO(joyeecheung): do we need all of these? Maybe we would want a less 14731cb0ef41Sopenharmony_ci // internal version of them. 14741cb0ef41Sopenharmony_ci std::vector<Local<String>> parameters = { 14751cb0ef41Sopenharmony_ci FIXED_ONE_BYTE_STRING(isolate, "require"), 14761cb0ef41Sopenharmony_ci FIXED_ONE_BYTE_STRING(isolate, "__filename"), 14771cb0ef41Sopenharmony_ci FIXED_ONE_BYTE_STRING(isolate, "__dirname"), 14781cb0ef41Sopenharmony_ci }; 14791cb0ef41Sopenharmony_ci ScriptCompiler::Source script_source(source, origin); 14801cb0ef41Sopenharmony_ci Local<Function> fn; 14811cb0ef41Sopenharmony_ci if (ScriptCompiler::CompileFunction(context, 14821cb0ef41Sopenharmony_ci &script_source, 14831cb0ef41Sopenharmony_ci parameters.size(), 14841cb0ef41Sopenharmony_ci parameters.data(), 14851cb0ef41Sopenharmony_ci 0, 14861cb0ef41Sopenharmony_ci nullptr, 14871cb0ef41Sopenharmony_ci ScriptCompiler::kNoCompileOptions) 14881cb0ef41Sopenharmony_ci .ToLocal(&fn)) { 14891cb0ef41Sopenharmony_ci args.GetReturnValue().Set(fn); 14901cb0ef41Sopenharmony_ci } 14911cb0ef41Sopenharmony_ci} 14921cb0ef41Sopenharmony_ci 14931cb0ef41Sopenharmony_civoid SetSerializeCallback(const FunctionCallbackInfo<Value>& args) { 14941cb0ef41Sopenharmony_ci Environment* env = Environment::GetCurrent(args); 14951cb0ef41Sopenharmony_ci CHECK(env->snapshot_serialize_callback().IsEmpty()); 14961cb0ef41Sopenharmony_ci CHECK(args[0]->IsFunction()); 14971cb0ef41Sopenharmony_ci env->set_snapshot_serialize_callback(args[0].As<Function>()); 14981cb0ef41Sopenharmony_ci} 14991cb0ef41Sopenharmony_ci 15001cb0ef41Sopenharmony_civoid SetDeserializeCallback(const FunctionCallbackInfo<Value>& args) { 15011cb0ef41Sopenharmony_ci Environment* env = Environment::GetCurrent(args); 15021cb0ef41Sopenharmony_ci CHECK(env->snapshot_deserialize_callback().IsEmpty()); 15031cb0ef41Sopenharmony_ci CHECK(args[0]->IsFunction()); 15041cb0ef41Sopenharmony_ci env->set_snapshot_deserialize_callback(args[0].As<Function>()); 15051cb0ef41Sopenharmony_ci} 15061cb0ef41Sopenharmony_ci 15071cb0ef41Sopenharmony_civoid SetDeserializeMainFunction(const FunctionCallbackInfo<Value>& args) { 15081cb0ef41Sopenharmony_ci Environment* env = Environment::GetCurrent(args); 15091cb0ef41Sopenharmony_ci CHECK(env->snapshot_deserialize_main().IsEmpty()); 15101cb0ef41Sopenharmony_ci CHECK(args[0]->IsFunction()); 15111cb0ef41Sopenharmony_ci env->set_snapshot_deserialize_main(args[0].As<Function>()); 15121cb0ef41Sopenharmony_ci} 15131cb0ef41Sopenharmony_ci 15141cb0ef41Sopenharmony_civoid Initialize(Local<Object> target, 15151cb0ef41Sopenharmony_ci Local<Value> unused, 15161cb0ef41Sopenharmony_ci Local<Context> context, 15171cb0ef41Sopenharmony_ci void* priv) { 15181cb0ef41Sopenharmony_ci SetMethod(context, target, "compileSerializeMain", CompileSerializeMain); 15191cb0ef41Sopenharmony_ci SetMethod(context, target, "setSerializeCallback", SetSerializeCallback); 15201cb0ef41Sopenharmony_ci SetMethod(context, target, "setDeserializeCallback", SetDeserializeCallback); 15211cb0ef41Sopenharmony_ci SetMethod(context, 15221cb0ef41Sopenharmony_ci target, 15231cb0ef41Sopenharmony_ci "setDeserializeMainFunction", 15241cb0ef41Sopenharmony_ci SetDeserializeMainFunction); 15251cb0ef41Sopenharmony_ci} 15261cb0ef41Sopenharmony_ci 15271cb0ef41Sopenharmony_civoid RegisterExternalReferences(ExternalReferenceRegistry* registry) { 15281cb0ef41Sopenharmony_ci registry->Register(CompileSerializeMain); 15291cb0ef41Sopenharmony_ci registry->Register(SetSerializeCallback); 15301cb0ef41Sopenharmony_ci registry->Register(SetDeserializeCallback); 15311cb0ef41Sopenharmony_ci registry->Register(SetDeserializeMainFunction); 15321cb0ef41Sopenharmony_ci} 15331cb0ef41Sopenharmony_ci} // namespace mksnapshot 15341cb0ef41Sopenharmony_ci} // namespace node 15351cb0ef41Sopenharmony_ci 15361cb0ef41Sopenharmony_ciNODE_BINDING_CONTEXT_AWARE_INTERNAL(mksnapshot, node::mksnapshot::Initialize) 15371cb0ef41Sopenharmony_ciNODE_BINDING_EXTERNAL_REFERENCE(mksnapshot, 15381cb0ef41Sopenharmony_ci node::mksnapshot::RegisterExternalReferences) 1539