Skip to content

Commit a86cb0e

Browse files
joyeecheungcodebytere
authored andcommittedFeb 27, 2020
vm: lazily initialize primordials for vm contexts
Lazily initialize primordials when cross-context support for builtins is needed to fix the performance regression in context creation. PR-URL: #31738 Fixes: #29842 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: David Carlier <devnexen@gmail.com>
1 parent 94a471a commit a86cb0e

File tree

3 files changed

+49
-43
lines changed

3 files changed

+49
-43
lines changed
 

‎src/api/environment.cc

+43-41
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,8 @@ MaybeLocal<Object> GetPerContextExports(Local<Context> context) {
411411
return handle_scope.Escape(existing_value.As<Object>());
412412

413413
Local<Object> exports = Object::New(isolate);
414-
if (context->Global()->SetPrivate(context, key, exports).IsNothing())
414+
if (context->Global()->SetPrivate(context, key, exports).IsNothing() ||
415+
!InitializePrimordials(context))
415416
return MaybeLocal<Object>();
416417
return handle_scope.Escape(exports);
417418
}
@@ -467,49 +468,50 @@ bool InitializeContextForSnapshot(Local<Context> context) {
467468

468469
context->SetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration,
469470
True(isolate));
471+
return InitializePrimordials(context);
472+
}
473+
474+
bool InitializePrimordials(Local<Context> context) {
475+
// Run per-context JS files.
476+
Isolate* isolate = context->GetIsolate();
477+
Context::Scope context_scope(context);
478+
Local<Object> exports;
479+
480+
Local<String> primordials_string =
481+
FIXED_ONE_BYTE_STRING(isolate, "primordials");
482+
Local<String> global_string = FIXED_ONE_BYTE_STRING(isolate, "global");
483+
Local<String> exports_string = FIXED_ONE_BYTE_STRING(isolate, "exports");
484+
485+
// Create primordials first and make it available to per-context scripts.
486+
Local<Object> primordials = Object::New(isolate);
487+
if (!primordials->SetPrototype(context, Null(isolate)).FromJust() ||
488+
!GetPerContextExports(context).ToLocal(&exports) ||
489+
!exports->Set(context, primordials_string, primordials).FromJust()) {
490+
return false;
491+
}
470492

471-
{
472-
// Run per-context JS files.
473-
Context::Scope context_scope(context);
474-
Local<Object> exports;
475-
476-
Local<String> primordials_string =
477-
FIXED_ONE_BYTE_STRING(isolate, "primordials");
478-
Local<String> global_string = FIXED_ONE_BYTE_STRING(isolate, "global");
479-
Local<String> exports_string = FIXED_ONE_BYTE_STRING(isolate, "exports");
480-
481-
// Create primordials first and make it available to per-context scripts.
482-
Local<Object> primordials = Object::New(isolate);
483-
if (!primordials->SetPrototype(context, Null(isolate)).FromJust() ||
484-
!GetPerContextExports(context).ToLocal(&exports) ||
485-
!exports->Set(context, primordials_string, primordials).FromJust()) {
493+
static const char* context_files[] = {"internal/per_context/primordials",
494+
"internal/per_context/domexception",
495+
"internal/per_context/messageport",
496+
nullptr};
497+
498+
for (const char** module = context_files; *module != nullptr; module++) {
499+
std::vector<Local<String>> parameters = {
500+
global_string, exports_string, primordials_string};
501+
Local<Value> arguments[] = {context->Global(), exports, primordials};
502+
MaybeLocal<Function> maybe_fn =
503+
native_module::NativeModuleEnv::LookupAndCompile(
504+
context, *module, &parameters, nullptr);
505+
if (maybe_fn.IsEmpty()) {
486506
return false;
487507
}
488-
489-
static const char* context_files[] = {"internal/per_context/primordials",
490-
"internal/per_context/domexception",
491-
"internal/per_context/messageport",
492-
nullptr};
493-
494-
for (const char** module = context_files; *module != nullptr; module++) {
495-
std::vector<Local<String>> parameters = {
496-
global_string, exports_string, primordials_string};
497-
Local<Value> arguments[] = {context->Global(), exports, primordials};
498-
MaybeLocal<Function> maybe_fn =
499-
native_module::NativeModuleEnv::LookupAndCompile(
500-
context, *module, &parameters, nullptr);
501-
if (maybe_fn.IsEmpty()) {
502-
return false;
503-
}
504-
Local<Function> fn = maybe_fn.ToLocalChecked();
505-
MaybeLocal<Value> result =
506-
fn->Call(context, Undefined(isolate),
507-
arraysize(arguments), arguments);
508-
// Execution failed during context creation.
509-
// TODO(joyeecheung): deprecate this signature and return a MaybeLocal.
510-
if (result.IsEmpty()) {
511-
return false;
512-
}
508+
Local<Function> fn = maybe_fn.ToLocalChecked();
509+
MaybeLocal<Value> result =
510+
fn->Call(context, Undefined(isolate), arraysize(arguments), arguments);
511+
// Execution failed during context creation.
512+
// TODO(joyeecheung): deprecate this signature and return a MaybeLocal.
513+
if (result.IsEmpty()) {
514+
return false;
513515
}
514516
}
515517

‎src/node_contextify.cc

+5-2
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,11 @@ MaybeLocal<Context> ContextifyContext::CreateV8Context(
185185

186186
object_template->SetHandler(config);
187187
object_template->SetHandler(indexed_config);
188-
189-
Local<Context> ctx = NewContext(env->isolate(), object_template);
188+
Local<Context> ctx = Context::New(env->isolate(), nullptr, object_template);
189+
if (ctx.IsEmpty()) return MaybeLocal<Context>();
190+
// Only partially initialize the context - the primordials are left out
191+
// and only initialized when necessary.
192+
InitializeContextRuntime(ctx);
190193

191194
if (ctx.IsEmpty()) {
192195
return MaybeLocal<Context>();

‎src/node_internals.h

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ std::string GetProcessTitle(const char* default_title);
9999
std::string GetHumanReadableProcessName();
100100

101101
void InitializeContextRuntime(v8::Local<v8::Context>);
102+
bool InitializePrimordials(v8::Local<v8::Context> context);
102103

103104
namespace task_queue {
104105
void PromiseRejectCallback(v8::PromiseRejectMessage message);

0 commit comments

Comments
 (0)
Please sign in to comment.