Skip to content

Commit c480559

Browse files
joyeecheungtargos
authored andcommitted
bootstrap: put is_building_snapshot state in IsolateData
Previously we modify the CLI options store to indicate whether the isolate is created for building snapshot, which is a bit hacky and makes it difficult to tell whether the snapshot is built from the command line or through other APIs. This patch adds is_building_snapshot to IsolateData and use this instead when we need to know whether the isolate is created for building snapshot (but do not care about where that request is coming from). PR-URL: #47887 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent 8d93af3 commit c480559

File tree

10 files changed

+131
-18
lines changed

10 files changed

+131
-18
lines changed

lib/internal/v8/startup_snapshot.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ const {
1414
setSerializeCallback,
1515
setDeserializeCallback,
1616
setDeserializeMainFunction: _setDeserializeMainFunction,
17+
isBuildingSnapshotBuffer
1718
} = internalBinding('mksnapshot');
1819

1920
function isBuildingSnapshot() {
20-
// For now this is the only way to build a snapshot.
21-
return require('internal/options').getOptionValue('--build-snapshot');
21+
return isBuildingSnapshotBuffer[0];
2222
}
2323

2424
function throwIfNotBuildingSnapshot() {

src/api/embed_helpers.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
142142

143143
impl_->isolate_data.reset(CreateIsolateData(
144144
isolate, loop, platform, impl_->allocator.get(), snapshot_data));
145-
impl_->isolate_data->options()->build_snapshot =
146-
impl_->snapshot_creator.has_value();
145+
impl_->isolate_data->set_is_building_snapshot(
146+
impl_->snapshot_creator.has_value());
147147

148148
if (snapshot_data) {
149149
impl_->env.reset(make_env(this));

src/base_object_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace node {
1212
#define SERIALIZABLE_BINDING_TYPES(V) \
1313
V(encoding_binding_data, encoding_binding::BindingData) \
1414
V(fs_binding_data, fs::BindingData) \
15+
V(mksnapshot_binding_data, mksnapshot::BindingData) \
1516
V(v8_binding_data, v8_utils::BindingData) \
1617
V(blob_binding_data, BlobBindingData) \
1718
V(process_binding_data, process::BindingData) \

src/env.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer {
136136
void MemoryInfo(MemoryTracker* tracker) const override;
137137
IsolateDataSerializeInfo Serialize(v8::SnapshotCreator* creator);
138138

139+
bool is_building_snapshot() const { return is_building_snapshot_; }
140+
void set_is_building_snapshot(bool value) { is_building_snapshot_ = value; }
141+
139142
inline uv_loop_t* event_loop() const;
140143
inline MultiIsolatePlatform* platform() const;
141144
inline const SnapshotData* snapshot_data() const;
@@ -219,6 +222,7 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer {
219222
const SnapshotData* snapshot_data_;
220223
std::shared_ptr<PerIsolateOptions> options_;
221224
worker::Worker* worker_context_ = nullptr;
225+
bool is_building_snapshot_ = false;
222226
};
223227

224228
struct ContextInfo {

src/node.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
283283
auto reset_entry_point =
284284
OnScopeLeave([&]() { env->set_embedder_entry_point({}); });
285285

286-
const char* entry = env->isolate_data()->options()->build_snapshot
286+
const char* entry = env->isolate_data()->is_building_snapshot()
287287
? "internal/main/mksnapshot"
288288
: "internal/main/embedding";
289289

@@ -311,7 +311,7 @@ MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
311311
return StartExecution(env, "internal/main/inspect");
312312
}
313313

314-
if (env->isolate_data()->options()->build_snapshot) {
314+
if (env->isolate_data()->is_building_snapshot()) {
315315
return StartExecution(env, "internal/main/mksnapshot");
316316
}
317317

src/node_binding.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ static_assert(static_cast<int>(NM_F_LINKED) ==
3737
V(contextify) \
3838
V(encoding_binding) \
3939
V(fs) \
40+
V(mksnapshot) \
4041
V(timers) \
4142
V(process_methods) \
4243
V(performance) \

src/node_main_instance.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ NodeMainInstance::NodeMainInstance(const SnapshotData* snapshot_data,
5656
platform,
5757
array_buffer_allocator_.get(),
5858
snapshot_data->AsEmbedderWrapper().get()));
59+
isolate_data_->set_is_building_snapshot(
60+
per_process::cli_options->per_isolate->build_snapshot);
5961

6062
isolate_data_->max_young_gen_size =
6163
isolate_params_->constraints.max_young_generation_size_in_bytes();

src/node_snapshotable.cc

Lines changed: 89 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <iostream>
44
#include <sstream>
55
#include <vector>
6+
#include "aliased_buffer-inl.h"
67
#include "base_object-inl.h"
78
#include "blob_serializer_deserializer-inl.h"
89
#include "debug_utils-inl.h"
@@ -34,6 +35,7 @@ namespace node {
3435
using v8::Context;
3536
using v8::Function;
3637
using v8::FunctionCallbackInfo;
38+
using v8::FunctionTemplate;
3739
using v8::HandleScope;
3840
using v8::Isolate;
3941
using v8::Local;
@@ -1177,8 +1179,6 @@ void SerializeSnapshotableObjects(Realm* realm,
11771179
});
11781180
}
11791181

1180-
namespace mksnapshot {
1181-
11821182
// NB: This is also used by the regular embedding codepath.
11831183
void GetEmbedderEntryFunction(const FunctionCallbackInfo<Value>& args) {
11841184
Environment* env = Environment::GetCurrent(args);
@@ -1251,16 +1251,89 @@ void SetDeserializeMainFunction(const FunctionCallbackInfo<Value>& args) {
12511251
env->set_snapshot_deserialize_main(args[0].As<Function>());
12521252
}
12531253

1254-
void Initialize(Local<Object> target,
1255-
Local<Value> unused,
1256-
Local<Context> context,
1257-
void* priv) {
1254+
namespace mksnapshot {
1255+
1256+
BindingData::BindingData(Realm* realm,
1257+
v8::Local<v8::Object> object,
1258+
InternalFieldInfo* info)
1259+
: SnapshotableObject(realm, object, type_int),
1260+
is_building_snapshot_buffer_(
1261+
realm->isolate(),
1262+
1,
1263+
MAYBE_FIELD_PTR(info, is_building_snapshot_buffer)) {
1264+
if (info == nullptr) {
1265+
object
1266+
->Set(
1267+
realm->context(),
1268+
FIXED_ONE_BYTE_STRING(realm->isolate(), "isBuildingSnapshotBuffer"),
1269+
is_building_snapshot_buffer_.GetJSArray())
1270+
.Check();
1271+
} else {
1272+
is_building_snapshot_buffer_.Deserialize(realm->context());
1273+
}
1274+
// Reset the status according to the current state of the realm.
1275+
bool is_building_snapshot = realm->isolate_data()->is_building_snapshot();
1276+
DCHECK_IMPLIES(is_building_snapshot,
1277+
realm->isolate_data()->snapshot_data() == nullptr);
1278+
is_building_snapshot_buffer_[0] = is_building_snapshot ? 1 : 0;
1279+
is_building_snapshot_buffer_.MakeWeak();
1280+
}
1281+
1282+
bool BindingData::PrepareForSerialization(Local<Context> context,
1283+
v8::SnapshotCreator* creator) {
1284+
DCHECK_NULL(internal_field_info_);
1285+
internal_field_info_ = InternalFieldInfoBase::New<InternalFieldInfo>(type());
1286+
internal_field_info_->is_building_snapshot_buffer =
1287+
is_building_snapshot_buffer_.Serialize(context, creator);
1288+
// Return true because we need to maintain the reference to the binding from
1289+
// JS land.
1290+
return true;
1291+
}
1292+
1293+
InternalFieldInfoBase* BindingData::Serialize(int index) {
1294+
DCHECK_EQ(index, BaseObject::kEmbedderType);
1295+
InternalFieldInfo* info = internal_field_info_;
1296+
internal_field_info_ = nullptr;
1297+
return info;
1298+
}
1299+
1300+
void BindingData::Deserialize(Local<Context> context,
1301+
Local<Object> holder,
1302+
int index,
1303+
InternalFieldInfoBase* info) {
1304+
DCHECK_EQ(index, BaseObject::kEmbedderType);
1305+
v8::HandleScope scope(context->GetIsolate());
1306+
Realm* realm = Realm::GetCurrent(context);
1307+
// Recreate the buffer in the constructor.
1308+
InternalFieldInfo* casted_info = static_cast<InternalFieldInfo*>(info);
1309+
BindingData* binding =
1310+
realm->AddBindingData<BindingData>(context, holder, casted_info);
1311+
CHECK_NOT_NULL(binding);
1312+
}
1313+
1314+
void BindingData::MemoryInfo(MemoryTracker* tracker) const {
1315+
tracker->TrackField("is_building_snapshot_buffer",
1316+
is_building_snapshot_buffer_);
1317+
}
1318+
1319+
void CreatePerContextProperties(Local<Object> target,
1320+
Local<Value> unused,
1321+
Local<Context> context,
1322+
void* priv) {
1323+
Realm* realm = Realm::GetCurrent(context);
1324+
realm->AddBindingData<BindingData>(context, target);
1325+
}
1326+
1327+
void CreatePerIsolateProperties(IsolateData* isolate_data,
1328+
Local<FunctionTemplate> ctor) {
1329+
Isolate* isolate = isolate_data->isolate();
1330+
Local<ObjectTemplate> target = ctor->PrototypeTemplate();
12581331
SetMethod(
1259-
context, target, "getEmbedderEntryFunction", GetEmbedderEntryFunction);
1260-
SetMethod(context, target, "compileSerializeMain", CompileSerializeMain);
1261-
SetMethod(context, target, "setSerializeCallback", SetSerializeCallback);
1262-
SetMethod(context, target, "setDeserializeCallback", SetDeserializeCallback);
1263-
SetMethod(context,
1332+
isolate, target, "getEmbedderEntryFunction", GetEmbedderEntryFunction);
1333+
SetMethod(isolate, target, "compileSerializeMain", CompileSerializeMain);
1334+
SetMethod(isolate, target, "setSerializeCallback", SetSerializeCallback);
1335+
SetMethod(isolate, target, "setDeserializeCallback", SetDeserializeCallback);
1336+
SetMethod(isolate,
12641337
target,
12651338
"setDeserializeMainFunction",
12661339
SetDeserializeMainFunction);
@@ -1274,8 +1347,12 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
12741347
registry->Register(SetDeserializeMainFunction);
12751348
}
12761349
} // namespace mksnapshot
1350+
12771351
} // namespace node
12781352

1279-
NODE_BINDING_CONTEXT_AWARE_INTERNAL(mksnapshot, node::mksnapshot::Initialize)
1353+
NODE_BINDING_CONTEXT_AWARE_INTERNAL(
1354+
mksnapshot, node::mksnapshot::CreatePerContextProperties)
1355+
NODE_BINDING_PER_ISOLATE_INIT(mksnapshot,
1356+
node::mksnapshot::CreatePerIsolateProperties)
12801357
NODE_BINDING_EXTERNAL_REFERENCE(mksnapshot,
12811358
node::mksnapshot::RegisterExternalReferences)

src/node_snapshotable.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
66

7+
#include "aliased_buffer.h"
78
#include "base_object.h"
89
#include "util.h"
910

@@ -121,6 +122,31 @@ void DeserializeNodeInternalFields(v8::Local<v8::Object> holder,
121122
void SerializeSnapshotableObjects(Realm* realm,
122123
v8::SnapshotCreator* creator,
123124
RealmSerializeInfo* info);
125+
126+
namespace mksnapshot {
127+
class BindingData : public SnapshotableObject {
128+
public:
129+
struct InternalFieldInfo : public node::InternalFieldInfoBase {
130+
AliasedBufferIndex is_building_snapshot_buffer;
131+
};
132+
133+
BindingData(Realm* realm,
134+
v8::Local<v8::Object> obj,
135+
InternalFieldInfo* info = nullptr);
136+
SET_BINDING_ID(mksnapshot_binding_data)
137+
SERIALIZABLE_OBJECT_METHODS()
138+
139+
void MemoryInfo(MemoryTracker* tracker) const override;
140+
SET_SELF_SIZE(BindingData)
141+
SET_MEMORY_INFO_NAME(BindingData)
142+
143+
private:
144+
AliasedUint8Array is_building_snapshot_buffer_;
145+
InternalFieldInfo* internal_field_info_ = nullptr;
146+
};
147+
148+
} // namespace mksnapshot
149+
124150
} // namespace node
125151

126152
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

src/node_worker.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ class WorkerThreadData {
186186
allocator.get(),
187187
w->snapshot_data()->AsEmbedderWrapper().get()));
188188
CHECK(isolate_data_);
189+
CHECK(!isolate_data_->is_building_snapshot());
189190
if (w_->per_isolate_opts_)
190191
isolate_data_->set_options(std::move(w_->per_isolate_opts_));
191192
isolate_data_->set_worker_context(w_);
@@ -481,6 +482,7 @@ void Worker::New(const FunctionCallbackInfo<Value>& args) {
481482
THROW_ERR_MISSING_PLATFORM_FOR_WORKER(env);
482483
return;
483484
}
485+
CHECK(!env->isolate_data()->is_building_snapshot());
484486

485487
std::string url;
486488
std::string name;

0 commit comments

Comments
 (0)