src: split BlobSerializer/BlobDeserializer

This patch splits BlobSerializer and BlobDeserializer out of
SnapshotSerializer and SnapshotDeserializer. The child classes
can implement serialization methods for custom types on top
of BlobSerializer/BlobDeserializer for conversions between
native types and binary blobs. This allows us to reuse the
classes for other cases (e.g. SEA blobs).

PR-URL: https://github.com/nodejs/node/pull/47458
Reviewed-By: Darshan Sen <raisinten@gmail.com>
This commit is contained in:
Joyee Cheung
2023-04-07 02:17:47 +02:00
parent ab3a54f2ee
commit 2e44a14cfb
2 changed files with 169 additions and 100 deletions

View File

@@ -534,6 +534,7 @@ struct SnapshotData {
bool Check() const;
static bool FromFile(SnapshotData* out, FILE* in);
static bool FromBlob(SnapshotData* out, const std::vector<char>& in);
static bool FromBlob(SnapshotData* out, std::string_view in);
static const SnapshotData* FromEmbedderWrapper(
const EmbedderSnapshotData* data);
EmbedderSnapshotData::Pointer AsEmbedderWrapper() const;

View File

@@ -140,16 +140,15 @@ std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) {
return output;
}
class SnapshotSerializerDeserializer {
class BlobSerializerDeserializer {
public:
SnapshotSerializerDeserializer()
: is_debug(per_process::enabled_debug_list.enabled(
DebugCategory::MKSNAPSHOT)) {}
explicit BlobSerializerDeserializer(bool is_debug_v) : is_debug(is_debug_v) {}
template <typename... Args>
void Debug(const char* format, Args&&... args) const {
per_process::Debug(
DebugCategory::MKSNAPSHOT, format, std::forward<Args>(args)...);
if (is_debug) {
FPrintF(stderr, format, std::forward<Args>(args)...);
}
}
template <typename T>
@@ -185,18 +184,28 @@ class SnapshotSerializerDeserializer {
bool is_debug = false;
};
class SnapshotDeserializer : public SnapshotSerializerDeserializer {
// TODO(joyeecheung): move it to the separate header file.
// Child classes are expected to implement T Read<T>() where
// !std::is_arithmetic_v<T> && !std::is_same_v<T, std::string>
template <typename Impl>
class BlobDeserializer : public BlobSerializerDeserializer {
public:
explicit SnapshotDeserializer(const std::vector<char>& s)
: SnapshotSerializerDeserializer(), sink(s) {}
~SnapshotDeserializer() {}
explicit BlobDeserializer(bool is_debug_v, std::string_view s)
: BlobSerializerDeserializer(is_debug_v), sink(s) {}
~BlobDeserializer() {}
size_t read_total = 0;
std::string_view sink;
Impl* impl() { return static_cast<Impl*>(this); }
const Impl* impl() const { return static_cast<const Impl*>(this); }
// Helper for reading numeric types.
template <typename T>
T Read() {
T ReadArithmetic() {
static_assert(std::is_arithmetic_v<T>, "Not an arithmetic type");
T result;
Read(&result, 1);
ReadArithmetic(&result, 1);
return result;
}
@@ -209,14 +218,19 @@ class SnapshotDeserializer : public SnapshotSerializerDeserializer {
std::string name = GetName<T>();
Debug("\nReadVector<%s>()(%d-byte)\n", name.c_str(), sizeof(T));
}
size_t count = static_cast<size_t>(Read<size_t>());
size_t count = static_cast<size_t>(ReadArithmetic<size_t>());
if (count == 0) {
return std::vector<T>();
}
if (is_debug) {
Debug("Reading %d vector elements...\n", count);
}
std::vector<T> result = ReadVector<T>(count, std::is_arithmetic<T>{});
std::vector<T> result;
if constexpr (std::is_arithmetic_v<T>) {
result = ReadArithmeticVector<T>(count);
} else {
result = ReadNonArithmeticVector<T>(count);
}
if (is_debug) {
std::string str = std::is_arithmetic_v<T> ? "" : ToStr(result);
std::string name = GetName<T>();
@@ -226,7 +240,7 @@ class SnapshotDeserializer : public SnapshotSerializerDeserializer {
}
std::string ReadString() {
size_t length = Read<size_t>();
size_t length = ReadArithmetic<size_t>();
if (is_debug) {
Debug("ReadString(), length=%d: ", length);
@@ -245,13 +259,9 @@ class SnapshotDeserializer : public SnapshotSerializerDeserializer {
return result;
}
size_t read_total = 0;
const std::vector<char>& sink;
private:
// Helper for reading an array of numeric types.
template <typename T>
void Read(T* out, size_t count) {
void ReadArithmetic(T* out, size_t count) {
static_assert(std::is_arithmetic_v<T>, "Not an arithmetic type");
DCHECK_GT(count, 0); // Should not read contents for vectors of size 0.
if (is_debug) {
@@ -272,17 +282,18 @@ class SnapshotDeserializer : public SnapshotSerializerDeserializer {
// Helper for reading numeric vectors.
template <typename Number>
std::vector<Number> ReadVector(size_t count, std::true_type) {
std::vector<Number> ReadArithmeticVector(size_t count) {
static_assert(std::is_arithmetic_v<Number>, "Not an arithmetic type");
DCHECK_GT(count, 0); // Should not read contents for vectors of size 0.
std::vector<Number> result(count);
Read(result.data(), count);
ReadArithmetic(result.data(), count);
return result;
}
private:
// Helper for reading non-numeric vectors.
template <typename T>
std::vector<T> ReadVector(size_t count, std::false_type) {
std::vector<T> ReadNonArithmeticVector(size_t count) {
static_assert(!std::is_arithmetic_v<T>, "Arithmetic type");
DCHECK_GT(count, 0); // Should not read contents for vectors of size 0.
std::vector<T> result;
@@ -293,29 +304,49 @@ class SnapshotDeserializer : public SnapshotSerializerDeserializer {
if (is_debug) {
Debug("\n[%d] ", i);
}
result.push_back(Read<T>());
result.push_back(ReadElement<T>());
}
is_debug = original_is_debug;
return result;
}
template <typename T>
T ReadElement() {
if constexpr (std::is_arithmetic_v<T>) {
return ReadArithmetic<T>();
} else if constexpr (std::is_same_v<T, std::string>) {
return ReadString();
} else {
return impl()->template Read<T>();
}
}
};
class SnapshotSerializer : public SnapshotSerializerDeserializer {
// TODO(joyeecheung): move it to the separate header file.
// Child classes are expected to implement size_t Write<T>(const T&) where
// !std::is_arithmetic_v<T> && !std::is_same_v<T, std::string>
template <typename Impl>
class BlobSerializer : public BlobSerializerDeserializer {
public:
SnapshotSerializer() : SnapshotSerializerDeserializer() {
explicit BlobSerializer(bool is_debug_v)
: BlobSerializerDeserializer(is_debug_v) {
// Currently the snapshot blob built with an empty script is around 4MB.
// So use that as the default sink size.
sink.reserve(4 * 1024 * 1024);
}
~SnapshotSerializer() {}
~BlobSerializer() {}
Impl* impl() { return static_cast<Impl*>(this); }
const Impl* impl() const { return static_cast<const Impl*>(this); }
std::vector<char> sink;
// Helper for writing numeric types.
template <typename T>
size_t Write(const T& data) {
size_t WriteArithmetic(const T& data) {
static_assert(std::is_arithmetic_v<T>, "Not an arithmetic type");
return Write(&data, 1);
return WriteArithmetic(&data, 1);
}
// Layout of vectors:
@@ -333,11 +364,16 @@ class SnapshotSerializer : public SnapshotSerializerDeserializer {
str.c_str());
}
size_t written_total = Write<size_t>(data.size());
size_t written_total = WriteArithmetic<size_t>(data.size());
if (data.size() == 0) {
return written_total;
}
written_total += WriteVector<T>(data, std::is_arithmetic<T>{});
if constexpr (std::is_arithmetic_v<T>) {
written_total += WriteArithmeticVector<T>(data);
} else {
written_total += WriteNonArithmeticVector<T>(data);
}
if (is_debug) {
std::string name = GetName<T>();
@@ -352,7 +388,7 @@ class SnapshotSerializer : public SnapshotSerializerDeserializer {
// [ |length| bytes ] contents
size_t WriteString(const std::string& data) {
CHECK_GT(data.size(), 0); // No empty strings should be written.
size_t written_total = Write<size_t>(data.size());
size_t written_total = WriteArithmetic<size_t>(data.size());
if (is_debug) {
std::string str = ToStr(data);
Debug("WriteString(), length=%zu: \"%s\"\n", data.size(), data.c_str());
@@ -370,10 +406,10 @@ class SnapshotSerializer : public SnapshotSerializerDeserializer {
return written_total;
}
private:
// Helper for writing an array of numeric types.
template <typename T>
size_t Write(const T* data, size_t count) {
size_t WriteArithmetic(const T* data, size_t count) {
static_assert(std::is_arithmetic_v<T>, "Arithmetic type");
DCHECK_GT(count, 0); // Should not write contents for vectors of size 0.
if (is_debug) {
std::string str =
@@ -398,13 +434,16 @@ class SnapshotSerializer : public SnapshotSerializerDeserializer {
// Helper for writing numeric vectors.
template <typename Number>
size_t WriteVector(const std::vector<Number>& data, std::true_type) {
return Write(data.data(), data.size());
size_t WriteArithmeticVector(const std::vector<Number>& data) {
static_assert(std::is_arithmetic_v<Number>, "Arithmetic type");
return WriteArithmetic(data.data(), data.size());
}
private:
// Helper for writing non-numeric vectors.
template <typename T>
size_t WriteVector(const std::vector<T>& data, std::false_type) {
size_t WriteNonArithmeticVector(const std::vector<T>& data) {
static_assert(!std::is_arithmetic_v<T>, "Arithmetic type");
DCHECK_GT(data.size(),
0); // Should not write contents for vectors of size 0.
size_t written_total = 0;
@@ -414,25 +453,50 @@ class SnapshotSerializer : public SnapshotSerializerDeserializer {
if (is_debug) {
Debug("\n[%d] ", i);
}
written_total += Write<T>(data[i]);
written_total += WriteElement<T>(data[i]);
}
is_debug = original_is_debug;
return written_total;
}
template <typename T>
size_t WriteElement(const T& data) {
if constexpr (std::is_arithmetic_v<T>) {
return WriteArithmetic<T>(data);
} else if constexpr (std::is_same_v<T, std::string>) {
return WriteString(data);
} else {
return impl()->template Write<T>(data);
}
}
};
// Layout of serialized std::string:
// [ 4/8 bytes ] length
// [ |length| bytes ] contents
template <>
std::string SnapshotDeserializer::Read() {
return ReadString();
}
template <>
size_t SnapshotSerializer::Write(const std::string& data) {
return WriteString(data);
}
class SnapshotDeserializer : public BlobDeserializer<SnapshotDeserializer> {
public:
explicit SnapshotDeserializer(std::string_view v)
: BlobDeserializer<SnapshotDeserializer>(
per_process::enabled_debug_list.enabled(DebugCategory::MKSNAPSHOT),
v) {}
template <typename T,
std::enable_if_t<!std::is_same<T, std::string>::value>* = nullptr,
std::enable_if_t<!std::is_arithmetic<T>::value>* = nullptr>
T Read();
};
class SnapshotSerializer : public BlobSerializer<SnapshotSerializer> {
public:
SnapshotSerializer()
: BlobSerializer<SnapshotSerializer>(
per_process::enabled_debug_list.enabled(
DebugCategory::MKSNAPSHOT)) {}
template <typename T,
std::enable_if_t<!std::is_same<T, std::string>::value>* = nullptr,
std::enable_if_t<!std::is_arithmetic<T>::value>* = nullptr>
size_t Write(const T& data);
};
// Layout of v8::StartupData
// [ 4/8 bytes ] raw_size
@@ -441,13 +505,13 @@ template <>
v8::StartupData SnapshotDeserializer::Read() {
Debug("Read<v8::StartupData>()\n");
int raw_size = Read<int>();
int raw_size = ReadArithmetic<int>();
Debug("size=%d\n", raw_size);
CHECK_GT(raw_size, 0); // There should be no startup data of size 0.
// The data pointer of v8::StartupData would be deleted so it must be new'ed.
std::unique_ptr<char> buf = std::unique_ptr<char>(new char[raw_size]);
Read<char>(buf.get(), raw_size);
ReadArithmetic<char>(buf.get(), raw_size);
return v8::StartupData{buf.release(), raw_size};
}
@@ -457,8 +521,9 @@ size_t SnapshotSerializer::Write(const v8::StartupData& data) {
Debug("\nWrite<v8::StartupData>() size=%d\n", data.raw_size);
CHECK_GT(data.raw_size, 0); // There should be no startup data of size 0.
size_t written_total = Write<int>(data.raw_size);
written_total += Write<char>(data.data, static_cast<size_t>(data.raw_size));
size_t written_total = WriteArithmetic<int>(data.raw_size);
written_total +=
WriteArithmetic<char>(data.data, static_cast<size_t>(data.raw_size));
Debug("Write<v8::StartupData>() wrote %d bytes\n\n", written_total);
return written_total;
@@ -508,8 +573,8 @@ PropInfo SnapshotDeserializer::Read() {
PropInfo result;
result.name = ReadString();
result.id = Read<uint32_t>();
result.index = Read<SnapshotIndex>();
result.id = ReadArithmetic<uint32_t>();
result.index = ReadArithmetic<SnapshotIndex>();
if (is_debug) {
std::string str = ToStr(result);
@@ -527,8 +592,8 @@ size_t SnapshotSerializer::Write(const PropInfo& data) {
}
size_t written_total = WriteString(data.name);
written_total += Write<uint32_t>(data.id);
written_total += Write<SnapshotIndex>(data.index);
written_total += WriteArithmetic<uint32_t>(data.id);
written_total += WriteArithmetic<SnapshotIndex>(data.index);
Debug("Write<PropInfo>() wrote %d bytes\n", written_total);
return written_total;
@@ -547,10 +612,10 @@ AsyncHooks::SerializeInfo SnapshotDeserializer::Read() {
Debug("Read<AsyncHooks::SerializeInfo>()\n");
AsyncHooks::SerializeInfo result;
result.async_ids_stack = Read<AliasedBufferIndex>();
result.fields = Read<AliasedBufferIndex>();
result.async_id_fields = Read<AliasedBufferIndex>();
result.js_execution_async_resources = Read<SnapshotIndex>();
result.async_ids_stack = ReadArithmetic<AliasedBufferIndex>();
result.fields = ReadArithmetic<AliasedBufferIndex>();
result.async_id_fields = ReadArithmetic<AliasedBufferIndex>();
result.js_execution_async_resources = ReadArithmetic<SnapshotIndex>();
result.native_execution_async_resources = ReadVector<SnapshotIndex>();
if (is_debug) {
@@ -567,10 +632,12 @@ size_t SnapshotSerializer::Write(const AsyncHooks::SerializeInfo& data) {
Debug("Write<AsyncHooks::SerializeInfo>() %s\n", str.c_str());
}
size_t written_total = Write<AliasedBufferIndex>(data.async_ids_stack);
written_total += Write<AliasedBufferIndex>(data.fields);
written_total += Write<AliasedBufferIndex>(data.async_id_fields);
written_total += Write<SnapshotIndex>(data.js_execution_async_resources);
size_t written_total =
WriteArithmetic<AliasedBufferIndex>(data.async_ids_stack);
written_total += WriteArithmetic<AliasedBufferIndex>(data.fields);
written_total += WriteArithmetic<AliasedBufferIndex>(data.async_id_fields);
written_total +=
WriteArithmetic<SnapshotIndex>(data.js_execution_async_resources);
written_total +=
WriteVector<SnapshotIndex>(data.native_execution_async_resources);
@@ -585,7 +652,7 @@ TickInfo::SerializeInfo SnapshotDeserializer::Read() {
Debug("Read<TickInfo::SerializeInfo>()\n");
TickInfo::SerializeInfo result;
result.fields = Read<AliasedBufferIndex>();
result.fields = ReadArithmetic<AliasedBufferIndex>();
if (is_debug) {
std::string str = ToStr(result);
@@ -602,7 +669,7 @@ size_t SnapshotSerializer::Write(const TickInfo::SerializeInfo& data) {
Debug("Write<TickInfo::SerializeInfo>() %s\n", str.c_str());
}
size_t written_total = Write<AliasedBufferIndex>(data.fields);
size_t written_total = WriteArithmetic<AliasedBufferIndex>(data.fields);
Debug("Write<TickInfo::SerializeInfo>() wrote %d bytes\n", written_total);
return written_total;
@@ -612,11 +679,10 @@ size_t SnapshotSerializer::Write(const TickInfo::SerializeInfo& data) {
// [ 4/8 bytes ] snapshot index of fields
template <>
ImmediateInfo::SerializeInfo SnapshotDeserializer::Read() {
per_process::Debug(DebugCategory::MKSNAPSHOT,
"Read<ImmediateInfo::SerializeInfo>()\n");
Debug("Read<ImmediateInfo::SerializeInfo>()\n");
ImmediateInfo::SerializeInfo result;
result.fields = Read<AliasedBufferIndex>();
result.fields = ReadArithmetic<AliasedBufferIndex>();
if (is_debug) {
std::string str = ToStr(result);
Debug("Read<ImmediateInfo::SerializeInfo>() %s\n", str.c_str());
@@ -631,7 +697,7 @@ size_t SnapshotSerializer::Write(const ImmediateInfo::SerializeInfo& data) {
Debug("Write<ImmediateInfo::SerializeInfo>() %s\n", str.c_str());
}
size_t written_total = Write<AliasedBufferIndex>(data.fields);
size_t written_total = WriteArithmetic<AliasedBufferIndex>(data.fields);
Debug("Write<ImmediateInfo::SerializeInfo>() wrote %d bytes\n",
written_total);
@@ -644,13 +710,12 @@ size_t SnapshotSerializer::Write(const ImmediateInfo::SerializeInfo& data) {
// [ 4/8 bytes ] snapshot index of observers
template <>
performance::PerformanceState::SerializeInfo SnapshotDeserializer::Read() {
per_process::Debug(DebugCategory::MKSNAPSHOT,
"Read<PerformanceState::SerializeInfo>()\n");
Debug("Read<PerformanceState::SerializeInfo>()\n");
performance::PerformanceState::SerializeInfo result;
result.root = Read<AliasedBufferIndex>();
result.milestones = Read<AliasedBufferIndex>();
result.observers = Read<AliasedBufferIndex>();
result.root = ReadArithmetic<AliasedBufferIndex>();
result.milestones = ReadArithmetic<AliasedBufferIndex>();
result.observers = ReadArithmetic<AliasedBufferIndex>();
if (is_debug) {
std::string str = ToStr(result);
Debug("Read<PerformanceState::SerializeInfo>() %s\n", str.c_str());
@@ -666,9 +731,9 @@ size_t SnapshotSerializer::Write(
Debug("Write<PerformanceState::SerializeInfo>() %s\n", str.c_str());
}
size_t written_total = Write<AliasedBufferIndex>(data.root);
written_total += Write<AliasedBufferIndex>(data.milestones);
written_total += Write<AliasedBufferIndex>(data.observers);
size_t written_total = WriteArithmetic<AliasedBufferIndex>(data.root);
written_total += WriteArithmetic<AliasedBufferIndex>(data.milestones);
written_total += WriteArithmetic<AliasedBufferIndex>(data.observers);
Debug("Write<PerformanceState::SerializeInfo>() wrote %d bytes\n",
written_total);
@@ -682,8 +747,7 @@ size_t SnapshotSerializer::Write(
// [ ... ] |length| of PropInfo data
template <>
IsolateDataSerializeInfo SnapshotDeserializer::Read() {
per_process::Debug(DebugCategory::MKSNAPSHOT,
"Read<IsolateDataSerializeInfo>()\n");
Debug("Read<IsolateDataSerializeInfo>()\n");
IsolateDataSerializeInfo result;
result.primitive_values = ReadVector<SnapshotIndex>();
@@ -711,12 +775,12 @@ size_t SnapshotSerializer::Write(const IsolateDataSerializeInfo& data) {
template <>
RealmSerializeInfo SnapshotDeserializer::Read() {
per_process::Debug(DebugCategory::MKSNAPSHOT, "Read<RealmSerializeInfo>()\n");
Debug("Read<RealmSerializeInfo>()\n");
RealmSerializeInfo result;
result.builtins = ReadVector<std::string>();
result.persistent_values = ReadVector<PropInfo>();
result.native_objects = ReadVector<PropInfo>();
result.context = Read<SnapshotIndex>();
result.context = ReadArithmetic<SnapshotIndex>();
return result;
}
@@ -731,7 +795,7 @@ size_t SnapshotSerializer::Write(const RealmSerializeInfo& data) {
size_t written_total = WriteVector<std::string>(data.builtins);
written_total += WriteVector<PropInfo>(data.persistent_values);
written_total += WriteVector<PropInfo>(data.native_objects);
written_total += Write<SnapshotIndex>(data.context);
written_total += WriteArithmetic<SnapshotIndex>(data.context);
Debug("Write<RealmSerializeInfo>() wrote %d bytes\n", written_total);
return written_total;
@@ -739,17 +803,17 @@ size_t SnapshotSerializer::Write(const RealmSerializeInfo& data) {
template <>
EnvSerializeInfo SnapshotDeserializer::Read() {
per_process::Debug(DebugCategory::MKSNAPSHOT, "Read<EnvSerializeInfo>()\n");
Debug("Read<EnvSerializeInfo>()\n");
EnvSerializeInfo result;
result.async_hooks = Read<AsyncHooks::SerializeInfo>();
result.tick_info = Read<TickInfo::SerializeInfo>();
result.immediate_info = Read<ImmediateInfo::SerializeInfo>();
result.timeout_info = Read<AliasedBufferIndex>();
result.timeout_info = ReadArithmetic<AliasedBufferIndex>();
result.performance_state =
Read<performance::PerformanceState::SerializeInfo>();
result.exit_info = Read<AliasedBufferIndex>();
result.stream_base_state = Read<AliasedBufferIndex>();
result.should_abort_on_uncaught_toggle = Read<AliasedBufferIndex>();
result.exit_info = ReadArithmetic<AliasedBufferIndex>();
result.stream_base_state = ReadArithmetic<AliasedBufferIndex>();
result.should_abort_on_uncaught_toggle = ReadArithmetic<AliasedBufferIndex>();
result.principal_realm = Read<RealmSerializeInfo>();
return result;
}
@@ -765,13 +829,13 @@ size_t SnapshotSerializer::Write(const EnvSerializeInfo& data) {
size_t written_total = Write<AsyncHooks::SerializeInfo>(data.async_hooks);
written_total += Write<TickInfo::SerializeInfo>(data.tick_info);
written_total += Write<ImmediateInfo::SerializeInfo>(data.immediate_info);
written_total += Write<AliasedBufferIndex>(data.timeout_info);
written_total += WriteArithmetic<AliasedBufferIndex>(data.timeout_info);
written_total += Write<performance::PerformanceState::SerializeInfo>(
data.performance_state);
written_total += Write<AliasedBufferIndex>(data.exit_info);
written_total += Write<AliasedBufferIndex>(data.stream_base_state);
written_total += WriteArithmetic<AliasedBufferIndex>(data.exit_info);
written_total += WriteArithmetic<AliasedBufferIndex>(data.stream_base_state);
written_total +=
Write<AliasedBufferIndex>(data.should_abort_on_uncaught_toggle);
WriteArithmetic<AliasedBufferIndex>(data.should_abort_on_uncaught_toggle);
written_total += Write<RealmSerializeInfo>(data.principal_realm);
Debug("Write<EnvSerializeInfo>() wrote %d bytes\n", written_total);
@@ -789,14 +853,14 @@ size_t SnapshotSerializer::Write(const EnvSerializeInfo& data) {
// [ 4 bytes ] v8 cache version tag
template <>
SnapshotMetadata SnapshotDeserializer::Read() {
per_process::Debug(DebugCategory::MKSNAPSHOT, "Read<SnapshotMetadata>()\n");
Debug("Read<SnapshotMetadata>()\n");
SnapshotMetadata result;
result.type = static_cast<SnapshotMetadata::Type>(Read<uint8_t>());
result.type = static_cast<SnapshotMetadata::Type>(ReadArithmetic<uint8_t>());
result.node_version = ReadString();
result.node_arch = ReadString();
result.node_platform = ReadString();
result.v8_cache_version_tag = Read<uint32_t>();
result.v8_cache_version_tag = ReadArithmetic<uint32_t>();
if (is_debug) {
std::string str = ToStr(result);
@@ -816,7 +880,7 @@ size_t SnapshotSerializer::Write(const SnapshotMetadata& data) {
// Node.js may perform synchronizations that are platform-specific and they
// can be changed in semver-patches.
Debug("Write snapshot type %" PRIu8 "\n", static_cast<uint8_t>(data.type));
written_total += Write<uint8_t>(static_cast<uint8_t>(data.type));
written_total += WriteArithmetic<uint8_t>(static_cast<uint8_t>(data.type));
Debug("Write Node.js version %s\n", data.node_version.c_str());
written_total += WriteString(data.node_version);
Debug("Write Node.js arch %s\n", data.node_arch);
@@ -825,7 +889,7 @@ size_t SnapshotSerializer::Write(const SnapshotMetadata& data) {
written_total += WriteString(data.node_platform);
Debug("Write V8 cached data version tag %" PRIx32 "\n",
data.v8_cache_version_tag);
written_total += Write<uint32_t>(data.v8_cache_version_tag);
written_total += WriteArithmetic<uint32_t>(data.v8_cache_version_tag);
return written_total;
}
@@ -848,7 +912,7 @@ std::vector<char> SnapshotData::ToBlob() const {
// Metadata
w.Debug("Write magic %" PRIx32 "\n", kMagic);
written_total += w.Write<uint32_t>(kMagic);
written_total += w.WriteArithmetic<uint32_t>(kMagic);
w.Debug("Write metadata\n");
written_total += w.Write<SnapshotMetadata>(metadata);
@@ -883,13 +947,17 @@ bool SnapshotData::FromFile(SnapshotData* out, FILE* in) {
}
bool SnapshotData::FromBlob(SnapshotData* out, const std::vector<char>& in) {
return FromBlob(out, std::string_view(in.data(), in.size()));
}
bool SnapshotData::FromBlob(SnapshotData* out, std::string_view in) {
SnapshotDeserializer r(in);
r.Debug("SnapshotData::FromBlob()\n");
DCHECK_EQ(out->data_ownership, SnapshotData::DataOwnership::kOwned);
// Metadata
uint32_t magic = r.Read<uint32_t>();
uint32_t magic = r.ReadArithmetic<uint32_t>();
r.Debug("Read magic %" PRIx32 "\n", magic);
CHECK_EQ(magic, kMagic);
out->metadata = r.Read<SnapshotMetadata>();