-
Notifications
You must be signed in to change notification settings - Fork 30k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
src: support serialization of binding data
This patch adds the SnapshotableObject interface. Native objects supporting serialization can inherit from it, implementing PrepareForSerialization(), Serialize() and Deserialize() to control how the native states should be serialized and deserialized. See doc: https://docs.google.com/document/d/15bu038I36oILq5t4Qju1sS2nKudVB6NSGWz00oD48Q8/edit PR-URL: #36943 Fixes: #35930 Refs: #35711 Reviewed-By: James M Snell <jasnell@gmail.com>
- Loading branch information
1 parent
dc3c299
commit e400f8c
Showing
7 changed files
with
283 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,134 @@ | ||
|
||
#include "node_snapshotable.h" | ||
#include "base_object-inl.h" | ||
#include "debug_utils-inl.h" | ||
#include "node_file.h" | ||
#include "node_v8.h" | ||
|
||
namespace node { | ||
|
||
using v8::Local; | ||
using v8::Object; | ||
using v8::SnapshotCreator; | ||
using v8::StartupData; | ||
|
||
SnapshotableObject::SnapshotableObject(Environment* env, | ||
Local<Object> wrap, | ||
EmbedderObjectType type) | ||
: BaseObject(env, wrap), type_(type) { | ||
set_is_snapshotable(true); | ||
} | ||
|
||
const char* SnapshotableObject::GetTypeNameChars() const { | ||
switch (type_) { | ||
#define V(PropertyName, NativeTypeName) \ | ||
case EmbedderObjectType::k_##PropertyName: { \ | ||
return NativeTypeName::type_name.c_str(); \ | ||
} | ||
SERIALIZABLE_OBJECT_TYPES(V) | ||
#undef V | ||
default: { UNREACHABLE(); } | ||
} | ||
} | ||
|
||
bool IsSnapshotableType(FastStringKey key) { | ||
#define V(PropertyName, NativeTypeName) \ | ||
if (key == NativeTypeName::type_name) { \ | ||
return true; \ | ||
} | ||
SERIALIZABLE_OBJECT_TYPES(V) | ||
#undef V | ||
|
||
return false; | ||
} | ||
|
||
void DeserializeNodeInternalFields(Local<Object> holder, | ||
int index, | ||
v8::StartupData payload, | ||
StartupData payload, | ||
void* env) { | ||
per_process::Debug(DebugCategory::MKSNAPSHOT, | ||
"Deserialize internal field %d of %p, size=%d\n", | ||
static_cast<int>(index), | ||
(*holder), | ||
static_cast<int>(payload.raw_size)); | ||
if (payload.raw_size == 0) { | ||
holder->SetAlignedPointerInInternalField(index, nullptr); | ||
return; | ||
} | ||
// No embedder object in the builtin snapshot yet. | ||
UNREACHABLE(); | ||
|
||
Environment* env_ptr = static_cast<Environment*>(env); | ||
const InternalFieldInfo* info = | ||
reinterpret_cast<const InternalFieldInfo*>(payload.data); | ||
|
||
switch (info->type) { | ||
#define V(PropertyName, NativeTypeName) \ | ||
case EmbedderObjectType::k_##PropertyName: { \ | ||
per_process::Debug(DebugCategory::MKSNAPSHOT, \ | ||
"Object %p is %s\n", \ | ||
(*holder), \ | ||
NativeTypeName::type_name.c_str()); \ | ||
env_ptr->EnqueueDeserializeRequest( \ | ||
NativeTypeName::Deserialize, holder, index, info->Copy()); \ | ||
break; \ | ||
} | ||
SERIALIZABLE_OBJECT_TYPES(V) | ||
#undef V | ||
default: { UNREACHABLE(); } | ||
} | ||
} | ||
|
||
StartupData SerializeNodeContextInternalFields(Local<Object> holder, | ||
int index, | ||
void* env) { | ||
void* ptr = holder->GetAlignedPointerFromInternalField(index); | ||
if (ptr == nullptr || ptr == env) { | ||
return StartupData{nullptr, 0}; | ||
} | ||
if (ptr == env && index == ContextEmbedderIndex::kEnvironment) { | ||
per_process::Debug(DebugCategory::MKSNAPSHOT, | ||
"Serialize internal field, index=%d, holder=%p\n", | ||
static_cast<int>(index), | ||
*holder); | ||
void* ptr = holder->GetAlignedPointerFromInternalField(BaseObject::kSlot); | ||
if (ptr == nullptr) { | ||
return StartupData{nullptr, 0}; | ||
} | ||
|
||
// No embedder objects in the builtin snapshot yet. | ||
UNREACHABLE(); | ||
return StartupData{nullptr, 0}; | ||
DCHECK(static_cast<BaseObject*>(ptr)->is_snapshotable()); | ||
SnapshotableObject* obj = static_cast<SnapshotableObject*>(ptr); | ||
per_process::Debug(DebugCategory::MKSNAPSHOT, | ||
"Object %p is %s, ", | ||
*holder, | ||
obj->GetTypeNameChars()); | ||
InternalFieldInfo* info = obj->Serialize(index); | ||
per_process::Debug(DebugCategory::MKSNAPSHOT, | ||
"payload size=%d\n", | ||
static_cast<int>(info->length)); | ||
return StartupData{reinterpret_cast<const char*>(info), | ||
static_cast<int>(info->length)}; | ||
} | ||
|
||
void SerializeBindingData(Environment* env, | ||
SnapshotCreator* creator, | ||
EnvSerializeInfo* info) { | ||
size_t i = 0; | ||
env->ForEachBindingData([&](FastStringKey key, | ||
BaseObjectPtr<BaseObject> binding) { | ||
per_process::Debug(DebugCategory::MKSNAPSHOT, | ||
"Serialize binding %i, %p, type=%s\n", | ||
static_cast<int>(i), | ||
*(binding->object()), | ||
key.c_str()); | ||
|
||
if (IsSnapshotableType(key)) { | ||
size_t index = creator->AddData(env->context(), binding->object()); | ||
per_process::Debug(DebugCategory::MKSNAPSHOT, | ||
"Serialized with index=%d\n", | ||
static_cast<int>(index)); | ||
info->bindings.push_back({key.c_str(), i, index}); | ||
SnapshotableObject* ptr = static_cast<SnapshotableObject*>(binding.get()); | ||
ptr->PrepareForSerialization(env->context(), creator); | ||
} else { | ||
UNREACHABLE(); | ||
} | ||
|
||
i++; | ||
}); | ||
} | ||
|
||
} // namespace node |
Oops, something went wrong.