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