|
1 | 1 |
|
2 | 2 | #include "node_snapshotable.h"
|
3 | 3 | #include "base_object-inl.h"
|
| 4 | +#include "debug_utils-inl.h" |
| 5 | +#include "node_file.h" |
| 6 | +#include "node_v8.h" |
4 | 7 |
|
5 | 8 | namespace node {
|
6 | 9 |
|
7 | 10 | using v8::Local;
|
8 | 11 | using v8::Object;
|
| 12 | +using v8::SnapshotCreator; |
9 | 13 | using v8::StartupData;
|
10 | 14 |
|
| 15 | +SnapshotableObject::SnapshotableObject(Environment* env, |
| 16 | + Local<Object> wrap, |
| 17 | + EmbedderObjectType type) |
| 18 | + : BaseObject(env, wrap), type_(type) { |
| 19 | + set_is_snapshotable(true); |
| 20 | +} |
| 21 | + |
| 22 | +const char* SnapshotableObject::GetTypeNameChars() const { |
| 23 | + switch (type_) { |
| 24 | +#define V(PropertyName, NativeTypeName) \ |
| 25 | + case EmbedderObjectType::k_##PropertyName: { \ |
| 26 | + return NativeTypeName::type_name.c_str(); \ |
| 27 | + } |
| 28 | + SERIALIZABLE_OBJECT_TYPES(V) |
| 29 | +#undef V |
| 30 | + default: { UNREACHABLE(); } |
| 31 | + } |
| 32 | +} |
| 33 | + |
| 34 | +bool IsSnapshotableType(FastStringKey key) { |
| 35 | +#define V(PropertyName, NativeTypeName) \ |
| 36 | + if (key == NativeTypeName::type_name) { \ |
| 37 | + return true; \ |
| 38 | + } |
| 39 | + SERIALIZABLE_OBJECT_TYPES(V) |
| 40 | +#undef V |
| 41 | + |
| 42 | + return false; |
| 43 | +} |
| 44 | + |
11 | 45 | void DeserializeNodeInternalFields(Local<Object> holder,
|
12 | 46 | int index,
|
13 |
| - v8::StartupData payload, |
| 47 | + StartupData payload, |
14 | 48 | void* env) {
|
| 49 | + per_process::Debug(DebugCategory::MKSNAPSHOT, |
| 50 | + "Deserialize internal field %d of %p, size=%d\n", |
| 51 | + static_cast<int>(index), |
| 52 | + (*holder), |
| 53 | + static_cast<int>(payload.raw_size)); |
15 | 54 | if (payload.raw_size == 0) {
|
16 | 55 | holder->SetAlignedPointerInInternalField(index, nullptr);
|
17 | 56 | return;
|
18 | 57 | }
|
19 |
| - // No embedder object in the builtin snapshot yet. |
20 |
| - UNREACHABLE(); |
| 58 | + |
| 59 | + Environment* env_ptr = static_cast<Environment*>(env); |
| 60 | + const InternalFieldInfo* info = |
| 61 | + reinterpret_cast<const InternalFieldInfo*>(payload.data); |
| 62 | + |
| 63 | + switch (info->type) { |
| 64 | +#define V(PropertyName, NativeTypeName) \ |
| 65 | + case EmbedderObjectType::k_##PropertyName: { \ |
| 66 | + per_process::Debug(DebugCategory::MKSNAPSHOT, \ |
| 67 | + "Object %p is %s\n", \ |
| 68 | + (*holder), \ |
| 69 | + NativeTypeName::type_name.c_str()); \ |
| 70 | + env_ptr->EnqueueDeserializeRequest( \ |
| 71 | + NativeTypeName::Deserialize, holder, index, info->Copy()); \ |
| 72 | + break; \ |
| 73 | + } |
| 74 | + SERIALIZABLE_OBJECT_TYPES(V) |
| 75 | +#undef V |
| 76 | + default: { UNREACHABLE(); } |
| 77 | + } |
21 | 78 | }
|
22 | 79 |
|
23 | 80 | StartupData SerializeNodeContextInternalFields(Local<Object> holder,
|
24 | 81 | int index,
|
25 | 82 | void* env) {
|
26 |
| - void* ptr = holder->GetAlignedPointerFromInternalField(index); |
27 |
| - if (ptr == nullptr || ptr == env) { |
28 |
| - return StartupData{nullptr, 0}; |
29 |
| - } |
30 |
| - if (ptr == env && index == ContextEmbedderIndex::kEnvironment) { |
| 83 | + per_process::Debug(DebugCategory::MKSNAPSHOT, |
| 84 | + "Serialize internal field, index=%d, holder=%p\n", |
| 85 | + static_cast<int>(index), |
| 86 | + *holder); |
| 87 | + void* ptr = holder->GetAlignedPointerFromInternalField(BaseObject::kSlot); |
| 88 | + if (ptr == nullptr) { |
31 | 89 | return StartupData{nullptr, 0};
|
32 | 90 | }
|
33 | 91 |
|
34 |
| - // No embedder objects in the builtin snapshot yet. |
35 |
| - UNREACHABLE(); |
36 |
| - return StartupData{nullptr, 0}; |
| 92 | + DCHECK(static_cast<BaseObject*>(ptr)->is_snapshotable()); |
| 93 | + SnapshotableObject* obj = static_cast<SnapshotableObject*>(ptr); |
| 94 | + per_process::Debug(DebugCategory::MKSNAPSHOT, |
| 95 | + "Object %p is %s, ", |
| 96 | + *holder, |
| 97 | + obj->GetTypeNameChars()); |
| 98 | + InternalFieldInfo* info = obj->Serialize(index); |
| 99 | + per_process::Debug(DebugCategory::MKSNAPSHOT, |
| 100 | + "payload size=%d\n", |
| 101 | + static_cast<int>(info->length)); |
| 102 | + return StartupData{reinterpret_cast<const char*>(info), |
| 103 | + static_cast<int>(info->length)}; |
| 104 | +} |
| 105 | + |
| 106 | +void SerializeBindingData(Environment* env, |
| 107 | + SnapshotCreator* creator, |
| 108 | + EnvSerializeInfo* info) { |
| 109 | + size_t i = 0; |
| 110 | + env->ForEachBindingData([&](FastStringKey key, |
| 111 | + BaseObjectPtr<BaseObject> binding) { |
| 112 | + per_process::Debug(DebugCategory::MKSNAPSHOT, |
| 113 | + "Serialize binding %i, %p, type=%s\n", |
| 114 | + static_cast<int>(i), |
| 115 | + *(binding->object()), |
| 116 | + key.c_str()); |
| 117 | + |
| 118 | + if (IsSnapshotableType(key)) { |
| 119 | + size_t index = creator->AddData(env->context(), binding->object()); |
| 120 | + per_process::Debug(DebugCategory::MKSNAPSHOT, |
| 121 | + "Serialized with index=%d\n", |
| 122 | + static_cast<int>(index)); |
| 123 | + info->bindings.push_back({key.c_str(), i, index}); |
| 124 | + SnapshotableObject* ptr = static_cast<SnapshotableObject*>(binding.get()); |
| 125 | + ptr->PrepareForSerialization(env->context(), creator); |
| 126 | + } else { |
| 127 | + UNREACHABLE(); |
| 128 | + } |
| 129 | + |
| 130 | + i++; |
| 131 | + }); |
37 | 132 | }
|
38 | 133 |
|
39 | 134 | } // namespace node
|
0 commit comments