mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
Use a virtual function in order to save space (8 bytes per instance on 64-bit platforms) and in order to be consistent with the other methods on BaseObject. PR-URL: https://github.com/nodejs/node/pull/37539 Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
134 lines
4.9 KiB
C++
134 lines
4.9 KiB
C++
|
|
#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) {
|
|
}
|
|
|
|
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,
|
|
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;
|
|
}
|
|
|
|
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) {
|
|
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};
|
|
}
|
|
|
|
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
|