@@ -14,6 +14,7 @@ using v8::Locker;
14
14
using v8::Maybe;
15
15
using v8::Nothing;
16
16
using v8::SealHandleScope;
17
+ using v8::SnapshotCreator;
17
18
18
19
namespace node {
19
20
@@ -78,16 +79,18 @@ struct CommonEnvironmentSetup::Impl {
78
79
MultiIsolatePlatform* platform = nullptr ;
79
80
uv_loop_t loop;
80
81
std::shared_ptr<ArrayBufferAllocator> allocator;
82
+ std::optional<SnapshotCreator> snapshot_creator;
81
83
Isolate* isolate = nullptr ;
82
84
DeleteFnPtr<IsolateData, FreeIsolateData> isolate_data;
83
85
DeleteFnPtr<Environment, FreeEnvironment> env;
84
- Global<Context> context ;
86
+ Global<Context> main_context ;
85
87
};
86
88
87
89
CommonEnvironmentSetup::CommonEnvironmentSetup (
88
90
MultiIsolatePlatform* platform,
89
91
std::vector<std::string>* errors,
90
92
const EmbedderSnapshotData* snapshot_data,
93
+ bool is_snapshotting,
91
94
std::function<Environment*(const CommonEnvironmentSetup*)> make_env)
92
95
: impl_(new Impl()) {
93
96
CHECK_NOT_NULL (platform);
@@ -105,28 +108,42 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
105
108
}
106
109
loop->data = this ;
107
110
108
- impl_->allocator = ArrayBufferAllocator::Create ();
109
- impl_->isolate =
110
- NewIsolate (impl_->allocator , &impl_->loop , platform, snapshot_data);
111
- Isolate* isolate = impl_->isolate ;
111
+ Isolate* isolate;
112
+ if (is_snapshotting) {
113
+ const std::vector<intptr_t >& external_references =
114
+ SnapshotBuilder::CollectExternalReferences ();
115
+ isolate = impl_->isolate = Isolate::Allocate ();
116
+ // Must be done before the SnapshotCreator creation so that the
117
+ // memory reducer can be initialized.
118
+ platform->RegisterIsolate (isolate, loop);
119
+ impl_->snapshot_creator .emplace (isolate, external_references.data ());
120
+ isolate->SetCaptureStackTraceForUncaughtExceptions (
121
+ true , 10 , v8::StackTrace::StackTraceOptions::kDetailed );
122
+ SetIsolateMiscHandlers (isolate, {});
123
+ } else {
124
+ impl_->allocator = ArrayBufferAllocator::Create ();
125
+ isolate = impl_->isolate =
126
+ NewIsolate (impl_->allocator , &impl_->loop , platform, snapshot_data);
127
+ }
112
128
113
129
{
114
130
Locker locker (isolate);
115
131
Isolate::Scope isolate_scope (isolate);
116
132
impl_->isolate_data .reset (CreateIsolateData (
117
133
isolate, loop, platform, impl_->allocator .get (), snapshot_data));
134
+ impl_->isolate_data ->options ()->build_snapshot = is_snapshotting;
118
135
119
136
HandleScope handle_scope (isolate);
120
137
if (snapshot_data) {
121
138
impl_->env .reset (make_env (this ));
122
139
if (impl_->env ) {
123
- impl_->context .Reset (isolate, impl_->env ->context ());
140
+ impl_->main_context .Reset (isolate, impl_->env ->context ());
124
141
}
125
142
return ;
126
143
}
127
144
128
145
Local<Context> context = NewContext (isolate);
129
- impl_->context .Reset (isolate, context);
146
+ impl_->main_context .Reset (isolate, context);
130
147
if (context.IsEmpty ()) {
131
148
errors->push_back (" Failed to initialize V8 Context" );
132
149
return ;
@@ -141,7 +158,34 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
141
158
MultiIsolatePlatform* platform,
142
159
std::vector<std::string>* errors,
143
160
std::function<Environment*(const CommonEnvironmentSetup*)> make_env)
144
- : CommonEnvironmentSetup(platform, errors, nullptr , make_env) {}
161
+ : CommonEnvironmentSetup(platform, errors, nullptr , false , make_env) {}
162
+
163
+ std::unique_ptr<CommonEnvironmentSetup>
164
+ CommonEnvironmentSetup::CreateForSnapshotting (
165
+ MultiIsolatePlatform* platform,
166
+ std::vector<std::string>* errors,
167
+ const std::vector<std::string>& args,
168
+ const std::vector<std::string>& exec_args) {
169
+ // It's not guaranteed that a context that goes through
170
+ // v8_inspector::V8Inspector::contextCreated() is runtime-independent,
171
+ // so do not start the inspector on the main context when building
172
+ // the default snapshot.
173
+ uint64_t env_flags = EnvironmentFlags::kDefaultFlags |
174
+ EnvironmentFlags::kNoCreateInspector ;
175
+
176
+ auto ret = std::unique_ptr<CommonEnvironmentSetup>(new CommonEnvironmentSetup (
177
+ platform, errors, nullptr , true ,
178
+ [&](const CommonEnvironmentSetup* setup) -> Environment* {
179
+ return CreateEnvironment (
180
+ setup->isolate_data (),
181
+ setup->context (),
182
+ args,
183
+ exec_args,
184
+ static_cast <EnvironmentFlags::Flags>(env_flags));
185
+ }));
186
+ if (!errors->empty ()) ret.reset ();
187
+ return ret;
188
+ }
145
189
146
190
CommonEnvironmentSetup::~CommonEnvironmentSetup () {
147
191
if (impl_->isolate != nullptr ) {
@@ -150,7 +194,7 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
150
194
Locker locker (isolate);
151
195
Isolate::Scope isolate_scope (isolate);
152
196
153
- impl_->context .Reset ();
197
+ impl_->main_context .Reset ();
154
198
impl_->env .reset ();
155
199
impl_->isolate_data .reset ();
156
200
}
@@ -160,7 +204,10 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
160
204
*static_cast <bool *>(data) = true ;
161
205
}, &platform_finished);
162
206
impl_->platform ->UnregisterIsolate (isolate);
163
- isolate->Dispose ();
207
+ if (impl_->snapshot_creator .has_value ())
208
+ impl_->snapshot_creator .reset ();
209
+ else
210
+ isolate->Dispose ();
164
211
165
212
// Wait until the platform has cleaned up all relevant resources.
166
213
while (!platform_finished)
@@ -173,6 +220,20 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
173
220
delete impl_;
174
221
}
175
222
223
+ EmbedderSnapshotData::Pointer CommonEnvironmentSetup::CreateSnapshot () {
224
+ CHECK_NOT_NULL (snapshot_creator ());
225
+ SnapshotData* snapshot_data = new SnapshotData ();
226
+ EmbedderSnapshotData::Pointer result{
227
+ new EmbedderSnapshotData (snapshot_data, true )};
228
+
229
+ auto exit_code = SnapshotBuilder::CreateSnapshot (
230
+ snapshot_data, this ,
231
+ static_cast <uint8_t >(SnapshotMetadata::Type::kFullyCustomized ));
232
+ if (exit_code != ExitCode::kNoFailure ) return {};
233
+
234
+ return result;
235
+ }
236
+
176
237
Maybe<int > SpinEventLoop (Environment* env) {
177
238
Maybe<ExitCode> result = SpinEventLoopInternal (env);
178
239
if (result.IsNothing ()) {
@@ -203,7 +264,11 @@ Environment* CommonEnvironmentSetup::env() const {
203
264
}
204
265
205
266
v8::Local<v8::Context> CommonEnvironmentSetup::context () const {
206
- return impl_->context .Get (impl_->isolate );
267
+ return impl_->main_context .Get (impl_->isolate );
268
+ }
269
+
270
+ v8::SnapshotCreator* CommonEnvironmentSetup::snapshot_creator () {
271
+ return impl_->snapshot_creator ? &impl_->snapshot_creator .value () : nullptr ;
207
272
}
208
273
209
274
void EmbedderSnapshotData::DeleteSnapshotData::operator ()(
@@ -232,6 +297,10 @@ EmbedderSnapshotData::Pointer EmbedderSnapshotData::FromFile(FILE* in) {
232
297
return result;
233
298
}
234
299
300
+ void EmbedderSnapshotData::ToFile (FILE* out) const {
301
+ impl_->ToBlob (out);
302
+ }
303
+
235
304
EmbedderSnapshotData::EmbedderSnapshotData (const SnapshotData* impl,
236
305
bool owns_impl)
237
306
: impl_(impl), owns_impl_(owns_impl) {}
0 commit comments