From cb1329a8cf4a9bcf477307660bc5a19a1b3ec694 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 7 Jun 2024 13:36:51 +0200 Subject: [PATCH] src: use v8::(Des|S)erializeInternalFieldsCallback Previously V8 would just try to serialize the context data fields "verbatim" by copying the pointer values. This patch makes use of the new callbacks so that at serialization, the embedder data for the context can at least be serialized in a meaningful way (which are all reset to empty for now). Otherwise the upstream may have difficulties serializing these pointer values "verbatim" especially with the introduction of external pointer tables, even though the verbatim pointer values from a previous process is meaningless to Node.js. For Node.js the callback currently just checks that the slots are know. We will reassign the pointers with newly created native structures during deserialization and there isn't much we can reuse for now. PR-URL: https://github.com/nodejs/node/pull/53217 Refs: https://chromium-review.googlesource.com/c/v8/v8/+/5512712/comments/cfc2b28d_c921ac80?tab=comments Reviewed-By: Chengzhong Wu --- src/api/environment.cc | 8 +++++++- src/node_snapshotable.cc | 42 ++++++++++++++++++++++++++++++++++++++-- src/node_snapshotable.h | 7 +++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/api/environment.cc b/src/api/environment.cc index 2cc2108b4c0f1c..45fa330b599503 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -458,7 +458,13 @@ Environment* CreateEnvironment( if (use_snapshot) { context = Context::FromSnapshot(isolate, SnapshotData::kNodeMainContextIndex, - {DeserializeNodeInternalFields, env}) + v8::DeserializeInternalFieldsCallback( + DeserializeNodeInternalFields, env), + nullptr, + MaybeLocal(), + nullptr, + v8::DeserializeContextDataCallback( + DeserializeNodeContextData, env)) .ToLocalChecked(); CHECK(!context.IsEmpty()); diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index 683f36839e0de2..ec01c2d0d5ac18 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -1155,8 +1155,11 @@ ExitCode SnapshotBuilder::CreateSnapshot(SnapshotData* out, CHECK_EQ(index, SnapshotData::kNodeVMContextIndex); index = creator->AddContext(base_context); CHECK_EQ(index, SnapshotData::kNodeBaseContextIndex); - index = creator->AddContext(main_context, - {SerializeNodeContextInternalFields, env}); + index = creator->AddContext( + main_context, + v8::SerializeInternalFieldsCallback(SerializeNodeContextInternalFields, + env), + v8::SerializeContextDataCallback(SerializeNodeContextData, env)); CHECK_EQ(index, SnapshotData::kNodeMainContextIndex); } @@ -1255,6 +1258,41 @@ std::string SnapshotableObject::GetTypeName() const { } } +void DeserializeNodeContextData(Local holder, + int index, + StartupData payload, + void* callback_data) { + // This is unreachable for now. We will reset all the pointers in + // Environment::AssignToContext() via the realm constructor. + UNREACHABLE(); +} + +StartupData SerializeNodeContextData(Local holder, + int index, + void* callback_data) { + // For now we just reset all of them in Environment::AssignToContext(). + // We return empty data here to make sure that the embedder data serialized + // into the snapshot is reproducible and V8 doesn't have to try to serialize + // the pointer values that won't be useful during deserialization. + switch (index) { + case ContextEmbedderIndex::kEnvironment: + case ContextEmbedderIndex::kContextifyContext: + case ContextEmbedderIndex::kRealm: + case ContextEmbedderIndex::kContextTag: { + void* data = holder->GetAlignedPointerFromEmbedderData(index); + per_process::Debug( + DebugCategory::MKSNAPSHOT, + "Serialize context data, index=%d, holder=%p, ptr=%p\n", + static_cast(index), + *holder, + data); + return {nullptr, 0}; + } + default: + UNREACHABLE(); + } +} + void DeserializeNodeInternalFields(Local holder, int index, StartupData payload, diff --git a/src/node_snapshotable.h b/src/node_snapshotable.h index 5e281b8155c810..600e56c481be90 100644 --- a/src/node_snapshotable.h +++ b/src/node_snapshotable.h @@ -126,10 +126,17 @@ class SnapshotableObject : public BaseObject { v8::StartupData SerializeNodeContextInternalFields(v8::Local holder, int index, void* env); +v8::StartupData SerializeNodeContextData(v8::Local holder, + int index, + void* env); void DeserializeNodeInternalFields(v8::Local holder, int index, v8::StartupData payload, void* env); +void DeserializeNodeContextData(v8::Local holder, + int index, + v8::StartupData payload, + void* env); void SerializeSnapshotableObjects(Realm* realm, v8::SnapshotCreator* creator, RealmSerializeInfo* info);