Skip to content

Commit bfb4ca8

Browse files
committed
bootstrap: use SnapshotData to pass snapshot data around
Instead of passing the snapshot blob, the per-isolate data indices and the EnvSerializeInfo separately, use the aggregate type Snapshot to carry these around, and refactor NodeMainInstance so that it owns the v8::Isolate::CreateParams when it owns its isolate. This also gets rid of the owns_isolate_ and deserialize_mode_ booleans in NodeMainInstance since NodeMainInstance can compute these by just checking if it has pointers to the CreateParams or the SnapshotData. PR-URL: #42360 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Darshan Sen <[email protected]>
1 parent c37fdac commit bfb4ca8

7 files changed

+72
-95
lines changed

src/env.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "node_binding.h"
3737
#include "node_external_reference.h"
3838
#include "node_main_instance.h"
39+
#include "node_native_module.h"
3940
#include "node_options.h"
4041
#include "node_perf_common.h"
4142
#include "node_snapshotable.h"
@@ -972,7 +973,6 @@ struct EnvSerializeInfo {
972973
};
973974

974975
struct SnapshotData {
975-
SnapshotData() { blob.data = nullptr; }
976976
v8::StartupData blob;
977977
std::vector<size_t> isolate_data_indices;
978978
EnvSerializeInfo env_info;

src/node.cc

+6-15
Original file line numberDiff line numberDiff line change
@@ -1154,28 +1154,19 @@ int Start(int argc, char** argv) {
11541154
}
11551155

11561156
{
1157-
Isolate::CreateParams params;
1158-
const std::vector<size_t>* indices = nullptr;
1159-
const EnvSerializeInfo* env_info = nullptr;
11601157
bool use_node_snapshot =
11611158
per_process::cli_options->per_isolate->node_snapshot;
1162-
if (use_node_snapshot) {
1163-
v8::StartupData* blob = NodeMainInstance::GetEmbeddedSnapshotBlob();
1164-
if (blob != nullptr) {
1165-
params.snapshot_blob = blob;
1166-
indices = NodeMainInstance::GetIsolateDataIndices();
1167-
env_info = NodeMainInstance::GetEnvSerializeInfo();
1168-
}
1169-
}
1159+
const SnapshotData* snapshot_data =
1160+
use_node_snapshot ? NodeMainInstance::GetEmbeddedSnapshotData()
1161+
: nullptr;
11701162
uv_loop_configure(uv_default_loop(), UV_METRICS_IDLE_TIME);
11711163

1172-
NodeMainInstance main_instance(&params,
1164+
NodeMainInstance main_instance(snapshot_data,
11731165
uv_default_loop(),
11741166
per_process::v8_platform.Platform(),
11751167
result.args,
1176-
result.exec_args,
1177-
indices);
1178-
result.exit_code = main_instance.Run(env_info);
1168+
result.exec_args);
1169+
result.exit_code = main_instance.Run();
11791170
}
11801171

11811172
TearDownOncePerProcess();

src/node_main_instance.cc

+36-35
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ NodeMainInstance::NodeMainInstance(Isolate* isolate,
3939
isolate_(isolate),
4040
platform_(platform),
4141
isolate_data_(nullptr),
42-
owns_isolate_(false),
43-
deserialize_mode_(false) {
42+
snapshot_data_(nullptr) {
4443
isolate_data_ =
4544
std::make_unique<IsolateData>(isolate_, event_loop, platform, nullptr);
4645

@@ -64,77 +63,81 @@ std::unique_ptr<NodeMainInstance> NodeMainInstance::Create(
6463
new NodeMainInstance(isolate, event_loop, platform, args, exec_args));
6564
}
6665

67-
NodeMainInstance::NodeMainInstance(
68-
Isolate::CreateParams* params,
69-
uv_loop_t* event_loop,
70-
MultiIsolatePlatform* platform,
71-
const std::vector<std::string>& args,
72-
const std::vector<std::string>& exec_args,
73-
const std::vector<size_t>* per_isolate_data_indexes)
66+
NodeMainInstance::NodeMainInstance(const SnapshotData* snapshot_data,
67+
uv_loop_t* event_loop,
68+
MultiIsolatePlatform* platform,
69+
const std::vector<std::string>& args,
70+
const std::vector<std::string>& exec_args)
7471
: args_(args),
7572
exec_args_(exec_args),
7673
array_buffer_allocator_(ArrayBufferAllocator::Create()),
7774
isolate_(nullptr),
7875
platform_(platform),
79-
isolate_data_(nullptr),
80-
owns_isolate_(true) {
81-
params->array_buffer_allocator = array_buffer_allocator_.get();
82-
deserialize_mode_ = per_isolate_data_indexes != nullptr;
83-
if (deserialize_mode_) {
76+
isolate_data_(),
77+
isolate_params_(std::make_unique<Isolate::CreateParams>()),
78+
snapshot_data_(snapshot_data) {
79+
isolate_params_->array_buffer_allocator = array_buffer_allocator_.get();
80+
if (snapshot_data != nullptr) {
8481
// TODO(joyeecheung): collect external references and set it in
8582
// params.external_references.
8683
const std::vector<intptr_t>& external_references =
8784
CollectExternalReferences();
88-
params->external_references = external_references.data();
85+
isolate_params_->external_references = external_references.data();
86+
isolate_params_->snapshot_blob =
87+
const_cast<v8::StartupData*>(&(snapshot_data->blob));
8988
}
9089

9190
isolate_ = Isolate::Allocate();
9291
CHECK_NOT_NULL(isolate_);
9392
// Register the isolate on the platform before the isolate gets initialized,
9493
// so that the isolate can access the platform during initialization.
9594
platform->RegisterIsolate(isolate_, event_loop);
96-
SetIsolateCreateParamsForNode(params);
97-
Isolate::Initialize(isolate_, *params);
95+
SetIsolateCreateParamsForNode(isolate_params_.get());
96+
Isolate::Initialize(isolate_, *isolate_params_);
9897

9998
// If the indexes are not nullptr, we are not deserializing
100-
CHECK_IMPLIES(deserialize_mode_, params->external_references != nullptr);
101-
isolate_data_ = std::make_unique<IsolateData>(isolate_,
102-
event_loop,
103-
platform,
104-
array_buffer_allocator_.get(),
105-
per_isolate_data_indexes);
99+
isolate_data_ = std::make_unique<IsolateData>(
100+
isolate_,
101+
event_loop,
102+
platform,
103+
array_buffer_allocator_.get(),
104+
snapshot_data == nullptr ? nullptr
105+
: &(snapshot_data->isolate_data_indices));
106106
IsolateSettings s;
107107
SetIsolateMiscHandlers(isolate_, s);
108-
if (!deserialize_mode_) {
108+
if (snapshot_data == nullptr) {
109109
// If in deserialize mode, delay until after the deserialization is
110110
// complete.
111111
SetIsolateErrorHandlers(isolate_, s);
112112
}
113113
isolate_data_->max_young_gen_size =
114-
params->constraints.max_young_generation_size_in_bytes();
114+
isolate_params_->constraints.max_young_generation_size_in_bytes();
115115
}
116116

117117
void NodeMainInstance::Dispose() {
118-
CHECK(!owns_isolate_);
118+
// This should only be called on a main instance that does not own its
119+
// isolate.
120+
CHECK_NULL(isolate_params_);
119121
platform_->DrainTasks(isolate_);
120122
}
121123

122124
NodeMainInstance::~NodeMainInstance() {
123-
if (!owns_isolate_) {
125+
if (isolate_params_ == nullptr) {
124126
return;
125127
}
128+
// This should only be done on a main instance that owns its isolate.
126129
platform_->UnregisterIsolate(isolate_);
127130
isolate_->Dispose();
128131
}
129132

130-
int NodeMainInstance::Run(const EnvSerializeInfo* env_info) {
133+
int NodeMainInstance::Run() {
131134
Locker locker(isolate_);
132135
Isolate::Scope isolate_scope(isolate_);
133136
HandleScope handle_scope(isolate_);
134137

135138
int exit_code = 0;
136139
DeleteFnPtr<Environment, FreeEnvironment> env =
137-
CreateMainEnvironment(&exit_code, env_info);
140+
CreateMainEnvironment(&exit_code);
138141
CHECK_NOT_NULL(env);
139142

140143
Context::Scope context_scope(env->context());
@@ -170,8 +173,7 @@ void NodeMainInstance::Run(int* exit_code, Environment* env) {
170173
}
171174

172175
DeleteFnPtr<Environment, FreeEnvironment>
173-
NodeMainInstance::CreateMainEnvironment(int* exit_code,
174-
const EnvSerializeInfo* env_info) {
176+
NodeMainInstance::CreateMainEnvironment(int* exit_code) {
175177
*exit_code = 0; // Reset the exit code to 0
176178

177179
HandleScope handle_scope(isolate_);
@@ -182,16 +184,15 @@ NodeMainInstance::CreateMainEnvironment(int* exit_code,
182184
isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
183185
}
184186

185-
CHECK_IMPLIES(deserialize_mode_, env_info != nullptr);
186187
Local<Context> context;
187188
DeleteFnPtr<Environment, FreeEnvironment> env;
188189

189-
if (deserialize_mode_) {
190+
if (snapshot_data_ != nullptr) {
190191
env.reset(new Environment(isolate_data_.get(),
191192
isolate_,
192193
args_,
193194
exec_args_,
194-
env_info,
195+
&(snapshot_data_->env_info),
195196
EnvironmentFlags::kDefaultFlags,
196197
{}));
197198
context = Context::FromSnapshot(isolate_,
@@ -203,7 +204,7 @@ NodeMainInstance::CreateMainEnvironment(int* exit_code,
203204
Context::Scope context_scope(context);
204205
CHECK(InitializeContextRuntime(context).IsJust());
205206
SetIsolateErrorHandlers(isolate_, {});
206-
env->InitializeMainContext(context, env_info);
207+
env->InitializeMainContext(context, &(snapshot_data_->env_info));
207208
#if HAVE_INSPECTOR
208209
env->InitializeInspector({});
209210
#endif

src/node_main_instance.h

+11-14
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace node {
1515

1616
class ExternalReferenceRegistry;
1717
struct EnvSerializeInfo;
18+
struct SnapshotData;
1819

1920
// TODO(joyeecheung): align this with the Worker/WorkerThreadData class.
2021
// We may be able to create an abstract class to reuse some of the routines.
@@ -48,29 +49,25 @@ class NodeMainInstance {
4849
void Dispose();
4950

5051
// Create a main instance that owns the isolate
51-
NodeMainInstance(
52-
v8::Isolate::CreateParams* params,
53-
uv_loop_t* event_loop,
54-
MultiIsolatePlatform* platform,
55-
const std::vector<std::string>& args,
56-
const std::vector<std::string>& exec_args,
57-
const std::vector<size_t>* per_isolate_data_indexes = nullptr);
52+
NodeMainInstance(const SnapshotData* snapshot_data,
53+
uv_loop_t* event_loop,
54+
MultiIsolatePlatform* platform,
55+
const std::vector<std::string>& args,
56+
const std::vector<std::string>& exec_args);
5857
~NodeMainInstance();
5958

6059
// Start running the Node.js instances, return the exit code when finished.
61-
int Run(const EnvSerializeInfo* env_info);
60+
int Run();
6261
void Run(int* exit_code, Environment* env);
6362

6463
IsolateData* isolate_data() { return isolate_data_.get(); }
6564

6665
DeleteFnPtr<Environment, FreeEnvironment> CreateMainEnvironment(
67-
int* exit_code, const EnvSerializeInfo* env_info);
66+
int* exit_code);
6867

6968
// If nullptr is returned, the binary is not built with embedded
7069
// snapshot.
71-
static const std::vector<size_t>* GetIsolateDataIndices();
72-
static v8::StartupData* GetEmbeddedSnapshotBlob();
73-
static const EnvSerializeInfo* GetEnvSerializeInfo();
70+
static const SnapshotData* GetEmbeddedSnapshotData();
7471
static const std::vector<intptr_t>& CollectExternalReferences();
7572

7673
static const size_t kNodeContextIndex = 0;
@@ -93,8 +90,8 @@ class NodeMainInstance {
9390
v8::Isolate* isolate_;
9491
MultiIsolatePlatform* platform_;
9592
std::unique_ptr<IsolateData> isolate_data_;
96-
bool owns_isolate_ = false;
97-
bool deserialize_mode_ = false;
93+
std::unique_ptr<v8::Isolate::CreateParams> isolate_params_;
94+
const SnapshotData* snapshot_data_ = nullptr;
9895
};
9996

10097
} // namespace node

src/node_snapshot_stub.cc

+1-9
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,7 @@
66

77
namespace node {
88

9-
v8::StartupData* NodeMainInstance::GetEmbeddedSnapshotBlob() {
10-
return nullptr;
11-
}
12-
13-
const std::vector<size_t>* NodeMainInstance::GetIsolateDataIndices() {
14-
return nullptr;
15-
}
16-
17-
const EnvSerializeInfo* NodeMainInstance::GetEnvSerializeInfo() {
9+
const SnapshotData* NodeMainInstance::GetEmbeddedSnapshotData() {
1810
return nullptr;
1911
}
2012

src/node_snapshotable.cc

+16-19
Original file line numberDiff line numberDiff line change
@@ -53,31 +53,28 @@ static const char blob_data[] = {
5353
5454
static const int blob_size = )"
5555
<< data->blob.raw_size << R"(;
56-
static v8::StartupData blob = { blob_data, blob_size };
57-
)";
58-
59-
ss << R"(v8::StartupData* NodeMainInstance::GetEmbeddedSnapshotBlob() {
60-
return &blob;
61-
}
6256
63-
static const std::vector<size_t> isolate_data_indices {
57+
SnapshotData snapshot_data {
58+
// -- blob begins --
59+
{ blob_data, blob_size },
60+
// -- blob ends --
61+
// -- isolate_data_indices begins --
62+
{
6463
)";
6564
WriteVector(&ss,
6665
data->isolate_data_indices.data(),
6766
data->isolate_data_indices.size());
68-
ss << R"(};
69-
70-
const std::vector<size_t>* NodeMainInstance::GetIsolateDataIndices() {
71-
return &isolate_data_indices;
67+
ss << R"(},
68+
// -- isolate_data_indices ends --
69+
// -- env_info begins --
70+
)" << data->env_info
71+
<< R"(
72+
// -- env_info ends --
73+
};
74+
75+
const SnapshotData* NodeMainInstance::GetEmbeddedSnapshotData() {
76+
return &snapshot_data;
7277
}
73-
74-
static const EnvSerializeInfo env_info )"
75-
<< data->env_info << R"(;
76-
77-
const EnvSerializeInfo* NodeMainInstance::GetEnvSerializeInfo() {
78-
return &env_info;
79-
}
80-
8178
} // namespace node
8279
)";
8380

tools/snapshot/README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ In the default build of the Node.js executable, to embed a V8 startup snapshot
2222
into the Node.js executable, `libnode` is first built with these unresolved
2323
symbols:
2424

25-
- `node::NodeMainInstance::GetEmbeddedSnapshotBlob`
26-
- `node::NodeMainInstance::GetIsolateDataIndices`
25+
- `node::NodeMainInstance::GetEmbeddedSnapshotData`
2726

2827
Then the `node_mksnapshot` executable is built with C++ files in this
2928
directory, as well as `src/node_snapshot_stub.cc` which defines the unresolved

0 commit comments

Comments
 (0)