From c4a45a93f335de089701c740b9fd657af0def3de Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 17 Aug 2022 15:48:46 +0800 Subject: [PATCH] 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%. PR-URL: https://github.com/nodejs/node/pull/44252 Refs: https://github.com/nodejs/node/issues/44014 Refs: https://github.com/nodejs/node/issues/37476 Reviewed-By: Chengzhong Wu --- src/api/environment.cc | 79 ++++++++++++++++++------------------------ src/node_contextify.cc | 16 +++++---- src/node_internals.h | 2 ++ 3 files changed, 44 insertions(+), 53 deletions(-) diff --git a/src/api/environment.cc b/src/api/environment.cc index 90360c19587a9f..17aba6665ad05c 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -549,50 +549,8 @@ Maybe InitializeContextRuntime(Local context) { Isolate* isolate = context->GetIsolate(); HandleScope handle_scope(isolate); - // Delete `Intl.v8BreakIterator` - // https://github.com/nodejs/node/issues/14909 - { - Local intl_string = - FIXED_ONE_BYTE_STRING(isolate, "Intl"); - Local break_iter_string = - FIXED_ONE_BYTE_STRING(isolate, "v8BreakIterator"); - - Local intl_v; - if (!context->Global() - ->Get(context, intl_string) - .ToLocal(&intl_v)) { - return Nothing(); - } - - if (intl_v->IsObject() && - intl_v.As() - ->Delete(context, break_iter_string) - .IsNothing()) { - return Nothing(); - } - } - - // Delete `Atomics.wake` - // https://github.com/nodejs/node/issues/21219 - { - Local atomics_string = - FIXED_ONE_BYTE_STRING(isolate, "Atomics"); - Local wake_string = - FIXED_ONE_BYTE_STRING(isolate, "wake"); - - Local atomics_v; - if (!context->Global() - ->Get(context, atomics_string) - .ToLocal(&atomics_v)) { - return Nothing(); - } - - if (atomics_v->IsObject() && - atomics_v.As() - ->Delete(context, wake_string) - .IsNothing()) { - return Nothing(); - } + if (per_process::cli_options->disable_proto == "") { + return Just(true); } // Remove __proto__ @@ -654,7 +612,32 @@ Maybe InitializeContextRuntime(Local context) { return Just(true); } -Maybe InitializeContextForSnapshot(Local context) { +Maybe InitializeBaseContextForSnapshot(Local context) { + Isolate* isolate = context->GetIsolate(); + HandleScope handle_scope(isolate); + + // Delete `Intl.v8BreakIterator` + // https://github.com/nodejs/node/issues/14909 + { + Context::Scope context_scope(context); + Local intl_string = FIXED_ONE_BYTE_STRING(isolate, "Intl"); + Local break_iter_string = + FIXED_ONE_BYTE_STRING(isolate, "v8BreakIterator"); + + Local intl_v; + if (!context->Global()->Get(context, intl_string).ToLocal(&intl_v)) { + return Nothing(); + } + + if (intl_v->IsObject() && + intl_v.As()->Delete(context, break_iter_string).IsNothing()) { + return Nothing(); + } + } + return Just(true); +} + +Maybe InitializeMainContextForSnapshot(Local context) { Isolate* isolate = context->GetIsolate(); HandleScope handle_scope(isolate); @@ -664,6 +647,9 @@ Maybe InitializeContextForSnapshot(Local context) { context->SetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration, True(isolate)); + if (InitializeBaseContextForSnapshot(context).IsNothing()) { + return Nothing(); + } return InitializePrimordials(context); } @@ -710,8 +696,9 @@ Maybe InitializePrimordials(Local context) { return Just(true); } +// This initializes the main context (i.e. vm contexts are not included). Maybe InitializeContext(Local context) { - if (InitializeContextForSnapshot(context).IsNothing()) { + if (InitializeMainContextForSnapshot(context).IsNothing()) { return Nothing(); } diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 0e24b32404846a..6c7412c10ae469 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -206,14 +206,16 @@ MaybeLocal ContextifyContext::CreateV8Context( {}, // global object {}, // deserialization callback queue); - if (ctx.IsEmpty()) return MaybeLocal(); + if (ctx.IsEmpty() || InitializeBaseContextForSnapshot(ctx).IsNothing()) { + return MaybeLocal(); + } } else if (!Context::FromSnapshot(isolate, - SnapshotData::kNodeVMContextIndex, - {}, // deserialization callback - nullptr, // extensions - {}, // global object - queue) - .ToLocal(&ctx)) { + SnapshotData::kNodeVMContextIndex, + {}, // deserialization callback + nullptr, // extensions + {}, // global object + queue) + .ToLocal(&ctx)) { return MaybeLocal(); } return scope.Escape(ctx); diff --git a/src/node_internals.h b/src/node_internals.h index e12c77bdaf4b80..1449d2acd327b9 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -92,6 +92,8 @@ void SignalExit(int signal, siginfo_t* info, void* ucontext); std::string GetProcessTitle(const char* default_title); std::string GetHumanReadableProcessName(); +v8::Maybe InitializeBaseContextForSnapshot( + v8::Local context); v8::Maybe InitializeContextRuntime(v8::Local context); v8::Maybe InitializePrimordials(v8::Local context);