Skip to content

Commit c32efba

Browse files
committed
vm: avoid unnecessary property getter interceptor calls
Access to the global object from within a vm context is intercepted so it's slow, therefore we should try to avoid unnecessary access to it during the initialization of vm contexts. - Remove the Atomics.wake deletion as V8 now does not install it anymore. - Move the Intl.v8BreakIterator deletion into the snapshot. - Do not query the Object prototype if --disable-proto is not set. This should speed up the creation of vm contexts by about ~12%.
1 parent fd7af82 commit c32efba

File tree

3 files changed

+44
-53
lines changed

3 files changed

+44
-53
lines changed

src/api/environment.cc

Lines changed: 33 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -555,50 +555,8 @@ Maybe<bool> InitializeContextRuntime(Local<Context> context) {
555555
Isolate* isolate = context->GetIsolate();
556556
HandleScope handle_scope(isolate);
557557

558-
// Delete `Intl.v8BreakIterator`
559-
// https://github.com/nodejs/node/issues/14909
560-
{
561-
Local<String> intl_string =
562-
FIXED_ONE_BYTE_STRING(isolate, "Intl");
563-
Local<String> break_iter_string =
564-
FIXED_ONE_BYTE_STRING(isolate, "v8BreakIterator");
565-
566-
Local<Value> intl_v;
567-
if (!context->Global()
568-
->Get(context, intl_string)
569-
.ToLocal(&intl_v)) {
570-
return Nothing<bool>();
571-
}
572-
573-
if (intl_v->IsObject() &&
574-
intl_v.As<Object>()
575-
->Delete(context, break_iter_string)
576-
.IsNothing()) {
577-
return Nothing<bool>();
578-
}
579-
}
580-
581-
// Delete `Atomics.wake`
582-
// https://github.com/nodejs/node/issues/21219
583-
{
584-
Local<String> atomics_string =
585-
FIXED_ONE_BYTE_STRING(isolate, "Atomics");
586-
Local<String> wake_string =
587-
FIXED_ONE_BYTE_STRING(isolate, "wake");
588-
589-
Local<Value> atomics_v;
590-
if (!context->Global()
591-
->Get(context, atomics_string)
592-
.ToLocal(&atomics_v)) {
593-
return Nothing<bool>();
594-
}
595-
596-
if (atomics_v->IsObject() &&
597-
atomics_v.As<Object>()
598-
->Delete(context, wake_string)
599-
.IsNothing()) {
600-
return Nothing<bool>();
601-
}
558+
if (per_process::cli_options->disable_proto == "") {
559+
return Just(true);
602560
}
603561

604562
// Remove __proto__
@@ -660,7 +618,32 @@ Maybe<bool> InitializeContextRuntime(Local<Context> context) {
660618
return Just(true);
661619
}
662620

663-
Maybe<bool> InitializeContextForSnapshot(Local<Context> context) {
621+
Maybe<bool> InitializeBaseContextForSnapshot(Local<Context> context) {
622+
Isolate* isolate = context->GetIsolate();
623+
HandleScope handle_scope(isolate);
624+
625+
// Delete `Intl.v8BreakIterator`
626+
// https://github.com/nodejs/node/issues/14909
627+
{
628+
Context::Scope context_scope(context);
629+
Local<String> intl_string = FIXED_ONE_BYTE_STRING(isolate, "Intl");
630+
Local<String> break_iter_string =
631+
FIXED_ONE_BYTE_STRING(isolate, "v8BreakIterator");
632+
633+
Local<Value> intl_v;
634+
if (!context->Global()->Get(context, intl_string).ToLocal(&intl_v)) {
635+
return Nothing<bool>();
636+
}
637+
638+
if (intl_v->IsObject() &&
639+
intl_v.As<Object>()->Delete(context, break_iter_string).IsNothing()) {
640+
return Nothing<bool>();
641+
}
642+
}
643+
return Just(true);
644+
}
645+
646+
Maybe<bool> InitializeMainContextForSnapshot(Local<Context> context) {
664647
Isolate* isolate = context->GetIsolate();
665648
HandleScope handle_scope(isolate);
666649

@@ -670,6 +653,9 @@ Maybe<bool> InitializeContextForSnapshot(Local<Context> context) {
670653
context->SetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration,
671654
True(isolate));
672655

656+
if (InitializeBaseContextForSnapshot(context).IsNothing()) {
657+
return Nothing<bool>();
658+
}
673659
return InitializePrimordials(context);
674660
}
675661

@@ -716,8 +702,9 @@ Maybe<bool> InitializePrimordials(Local<Context> context) {
716702
return Just(true);
717703
}
718704

705+
// This initializes the main context (i.e. vm contexts are not included).
719706
Maybe<bool> InitializeContext(Local<Context> context) {
720-
if (InitializeContextForSnapshot(context).IsNothing()) {
707+
if (InitializeMainContextForSnapshot(context).IsNothing()) {
721708
return Nothing<bool>();
722709
}
723710

src/node_contextify.cc

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,16 @@ MaybeLocal<Context> ContextifyContext::CreateV8Context(
206206
{}, // global object
207207
{}, // deserialization callback
208208
queue);
209-
if (ctx.IsEmpty()) return MaybeLocal<Context>();
209+
if (ctx.IsEmpty() || InitializeBaseContextForSnapshot(ctx).IsNothing()) {
210+
return MaybeLocal<Context>();
211+
}
210212
} else if (!Context::FromSnapshot(isolate,
211-
SnapshotData::kNodeVMContextIndex,
212-
{}, // deserialization callback
213-
nullptr, // extensions
214-
{}, // global object
215-
queue)
216-
.ToLocal(&ctx)) {
213+
SnapshotData::kNodeVMContextIndex,
214+
{}, // deserialization callback
215+
nullptr, // extensions
216+
{}, // global object
217+
queue)
218+
.ToLocal(&ctx)) {
217219
return MaybeLocal<Context>();
218220
}
219221
return scope.Escape(ctx);

src/node_internals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ void SignalExit(int signal, siginfo_t* info, void* ucontext);
9292
std::string GetProcessTitle(const char* default_title);
9393
std::string GetHumanReadableProcessName();
9494

95+
v8::Maybe<bool> InitializeBaseContextForSnapshot(
96+
v8::Local<v8::Context> context);
9597
v8::Maybe<bool> InitializeContextRuntime(v8::Local<v8::Context> context);
9698
v8::Maybe<bool> InitializePrimordials(v8::Local<v8::Context> context);
9799

0 commit comments

Comments
 (0)