Skip to content

Commit

Permalink
bootstrap: initialize per-isolate properties of bindings separately
Browse files Browse the repository at this point in the history
This patch moves the initialization of per-isolate properties of
the bindings that are in the embedded snapshot separate from the
initialization of their per-context properties. This is necessary
for workers to share the isolate snapshot with the main thread
and deserialize these properties instead of creating them from
scratch.
  • Loading branch information
joyeecheung committed May 1, 2023
1 parent 0b6a2f5 commit 827f713
Show file tree
Hide file tree
Showing 22 changed files with 384 additions and 289 deletions.
42 changes: 26 additions & 16 deletions src/async_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ using v8::MaybeLocal;
using v8::Nothing;
using v8::Number;
using v8::Object;
using v8::ObjectTemplate;
using v8::PropertyAttribute;
using v8::ReadOnly;
using v8::String;
Expand Down Expand Up @@ -351,24 +352,31 @@ Local<FunctionTemplate> AsyncWrap::GetConstructorTemplate(
return tmpl;
}

void AsyncWrap::Initialize(Local<Object> target,
Local<Value> unused,
Local<Context> context,
void* priv) {
void AsyncWrap::CreatePerIsolateProperties(IsolateData* isolate_data,
Local<FunctionTemplate> ctor) {
Isolate* isolate = isolate_data->isolate();
Local<ObjectTemplate> target = ctor->InstanceTemplate();

SetMethod(isolate, target, "setupHooks", SetupHooks);
SetMethod(isolate, target, "setCallbackTrampoline", SetCallbackTrampoline);
SetMethod(isolate, target, "pushAsyncContext", PushAsyncContext);
SetMethod(isolate, target, "popAsyncContext", PopAsyncContext);
SetMethod(isolate, target, "executionAsyncResource", ExecutionAsyncResource);
SetMethod(isolate, target, "clearAsyncIdStack", ClearAsyncIdStack);
SetMethod(isolate, target, "queueDestroyAsyncId", QueueDestroyAsyncId);
SetMethod(isolate, target, "setPromiseHooks", SetPromiseHooks);
SetMethod(isolate, target, "registerDestroyHook", RegisterDestroyHook);
AsyncWrap::GetConstructorTemplate(isolate_data);
}

void AsyncWrap::CreatePerContextProperties(Local<Object> target,
Local<Value> unused,
Local<Context> context,
void* priv) {
Environment* env = Environment::GetCurrent(context);
Isolate* isolate = env->isolate();
HandleScope scope(isolate);

SetMethod(context, target, "setupHooks", SetupHooks);
SetMethod(context, target, "setCallbackTrampoline", SetCallbackTrampoline);
SetMethod(context, target, "pushAsyncContext", PushAsyncContext);
SetMethod(context, target, "popAsyncContext", PopAsyncContext);
SetMethod(context, target, "executionAsyncResource", ExecutionAsyncResource);
SetMethod(context, target, "clearAsyncIdStack", ClearAsyncIdStack);
SetMethod(context, target, "queueDestroyAsyncId", QueueDestroyAsyncId);
SetMethod(context, target, "setPromiseHooks", SetPromiseHooks);
SetMethod(context, target, "registerDestroyHook", RegisterDestroyHook);

PropertyAttribute ReadOnlyDontDelete =
static_cast<PropertyAttribute>(ReadOnly | DontDelete);

Expand Down Expand Up @@ -625,7 +633,6 @@ void AsyncWrap::AsyncReset(Local<Object> resource, double execution_async_id,
async_id_, trigger_async_id_);
}


void AsyncWrap::EmitAsyncInit(Environment* env,
Local<Object> object,
Local<String> type,
Expand Down Expand Up @@ -710,6 +717,9 @@ Local<Object> AsyncWrap::GetOwner(Environment* env, Local<Object> obj) {

} // namespace node

NODE_BINDING_CONTEXT_AWARE_INTERNAL(async_wrap, node::AsyncWrap::Initialize)
NODE_BINDING_CONTEXT_AWARE_INTERNAL(async_wrap,
node::AsyncWrap::CreatePerContextProperties)
NODE_BINDING_PER_ISOLATE_INIT(async_wrap,
node::AsyncWrap::CreatePerIsolateProperties)
NODE_BINDING_EXTERNAL_REFERENCE(async_wrap,
node::AsyncWrap::RegisterExternalReferences)
10 changes: 6 additions & 4 deletions src/async_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,12 @@ class AsyncWrap : public BaseObject {
Environment* env);

static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
static void Initialize(v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv);
static void CreatePerContextProperties(v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv);
static void CreatePerIsolateProperties(
IsolateData* isolate_data, v8::Local<v8::FunctionTemplate> target);

static void GetAsyncId(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PushAsyncContext(const v8::FunctionCallbackInfo<v8::Value>& args);
Expand Down
37 changes: 23 additions & 14 deletions src/encoding_binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ using v8::ArrayBuffer;
using v8::BackingStore;
using v8::Context;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::MaybeLocal;
using v8::Object;
using v8::ObjectTemplate;
using v8::String;
using v8::Uint8Array;
using v8::Value;
Expand Down Expand Up @@ -216,20 +218,23 @@ void BindingData::ToUnicode(const v8::FunctionCallbackInfo<v8::Value>& args) {
String::NewFromUtf8(env->isolate(), out.c_str()).ToLocalChecked());
}

void BindingData::Initialize(Local<Object> target,
Local<Value> unused,
Local<Context> context,
void* priv) {
void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
Local<FunctionTemplate> ctor) {
Isolate* isolate = isolate_data->isolate();
Local<ObjectTemplate> target = ctor->InstanceTemplate();
SetMethod(isolate, target, "encodeInto", EncodeInto);
SetMethodNoSideEffect(isolate, target, "encodeUtf8String", EncodeUtf8String);
SetMethodNoSideEffect(isolate, target, "decodeUTF8", DecodeUTF8);
SetMethodNoSideEffect(isolate, target, "toASCII", ToASCII);
SetMethodNoSideEffect(isolate, target, "toUnicode", ToUnicode);
}

void BindingData::CreatePerContextProperties(Local<Object> target,
Local<Value> unused,
Local<Context> context,
void* priv) {
Realm* realm = Realm::GetCurrent(context);
BindingData* const binding_data =
realm->AddBindingData<BindingData>(context, target);
if (binding_data == nullptr) return;

SetMethod(context, target, "encodeInto", EncodeInto);
SetMethodNoSideEffect(context, target, "encodeUtf8String", EncodeUtf8String);
SetMethodNoSideEffect(context, target, "decodeUTF8", DecodeUTF8);
SetMethodNoSideEffect(context, target, "toASCII", ToASCII);
SetMethodNoSideEffect(context, target, "toUnicode", ToUnicode);
realm->AddBindingData<BindingData>(context, target);
}

void BindingData::RegisterTimerExternalReferences(
Expand All @@ -245,7 +250,11 @@ void BindingData::RegisterTimerExternalReferences(
} // namespace node

NODE_BINDING_CONTEXT_AWARE_INTERNAL(
encoding_binding, node::encoding_binding::BindingData::Initialize)
encoding_binding,
node::encoding_binding::BindingData::CreatePerContextProperties)
NODE_BINDING_PER_ISOLATE_INIT(
encoding_binding,
node::encoding_binding::BindingData::CreatePerIsolateProperties)
NODE_BINDING_EXTERNAL_REFERENCE(
encoding_binding,
node::encoding_binding::BindingData::RegisterTimerExternalReferences)
10 changes: 6 additions & 4 deletions src/encoding_binding.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ class BindingData : public SnapshotableObject {
static void ToASCII(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ToUnicode(const v8::FunctionCallbackInfo<v8::Value>& args);

static void Initialize(v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv);
static void CreatePerIsolateProperties(IsolateData* isolate_data,
v8::Local<v8::FunctionTemplate> ctor);
static void CreatePerContextProperties(v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv);
static void RegisterTimerExternalReferences(
ExternalReferenceRegistry* registry);

Expand Down
17 changes: 11 additions & 6 deletions src/handle_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,19 +154,24 @@ void HandleWrap::OnClose(uv_handle_t* handle) {
wrap->MakeCallback(env->handle_onclose_symbol(), 0, nullptr);
}
}

Local<FunctionTemplate> HandleWrap::GetConstructorTemplate(Environment* env) {
Local<FunctionTemplate> tmpl = env->handle_wrap_ctor_template();
return GetConstructorTemplate(env->isolate_data());
}

Local<FunctionTemplate> HandleWrap::GetConstructorTemplate(
IsolateData* isolate_data) {
Local<FunctionTemplate> tmpl = isolate_data->handle_wrap_ctor_template();
if (tmpl.IsEmpty()) {
Isolate* isolate = env->isolate();
Isolate* isolate = isolate_data->isolate();
tmpl = NewFunctionTemplate(isolate, nullptr);
tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "HandleWrap"));
tmpl->Inherit(AsyncWrap::GetConstructorTemplate(env));
tmpl->SetClassName(
FIXED_ONE_BYTE_STRING(isolate_data->isolate(), "HandleWrap"));
tmpl->Inherit(AsyncWrap::GetConstructorTemplate(isolate_data));
SetProtoMethod(isolate, tmpl, "close", HandleWrap::Close);
SetProtoMethodNoSideEffect(isolate, tmpl, "hasRef", HandleWrap::HasRef);
SetProtoMethod(isolate, tmpl, "ref", HandleWrap::Ref);
SetProtoMethod(isolate, tmpl, "unref", HandleWrap::Unref);
env->set_handle_wrap_ctor_template(tmpl);
isolate_data->set_handle_wrap_ctor_template(tmpl);
}
return tmpl;
}
Expand Down
2 changes: 2 additions & 0 deletions src/handle_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ class HandleWrap : public AsyncWrap {
virtual void Close(
v8::Local<v8::Value> close_callback = v8::Local<v8::Value>());

static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
IsolateData* isolate_data);
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
Environment* env);
static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
Expand Down
8 changes: 8 additions & 0 deletions src/node_binding.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,16 @@ static_assert(static_cast<int>(NM_F_LINKED) ==
#endif

#define NODE_BINDINGS_WITH_PER_ISOLATE_INIT(V) \
V(async_wrap) \
V(blob) \
V(builtins) \
V(contextify) \
V(encoding_binding) \
V(fs) \
V(timers) \
V(process_methods) \
V(performance) \
V(url) \
V(worker) \
NODE_BUILTIN_ICU_BINDINGS(V)

Expand Down
37 changes: 21 additions & 16 deletions src/node_blob.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ using v8::Int32;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::ObjectTemplate;
using v8::String;
using v8::Uint32;
using v8::Undefined;
Expand Down Expand Up @@ -107,23 +108,25 @@ void BlobFromFilePath(const FunctionCallbackInfo<Value>& args) {
}
} // namespace

void Blob::Initialize(
Local<Object> target,
Local<Value> unused,
Local<Context> context,
void* priv) {
Realm* realm = Realm::GetCurrent(context);
void Blob::CreatePerIsolateProperties(IsolateData* isolate_data,
Local<FunctionTemplate> ctor) {
Isolate* isolate = isolate_data->isolate();
Local<ObjectTemplate> target = ctor->InstanceTemplate();

BlobBindingData* const binding_data =
realm->AddBindingData<BlobBindingData>(context, target);
if (binding_data == nullptr) return;
SetMethod(isolate, target, "createBlob", New);
SetMethod(isolate, target, "storeDataObject", StoreDataObject);
SetMethod(isolate, target, "getDataObject", GetDataObject);
SetMethod(isolate, target, "revokeObjectURL", RevokeObjectURL);
SetMethod(isolate, target, "concat", Concat);
SetMethod(isolate, target, "createBlobFromFilePath", BlobFromFilePath);
}

SetMethod(context, target, "createBlob", New);
SetMethod(context, target, "storeDataObject", StoreDataObject);
SetMethod(context, target, "getDataObject", GetDataObject);
SetMethod(context, target, "revokeObjectURL", RevokeObjectURL);
SetMethod(context, target, "concat", Concat);
SetMethod(context, target, "createBlobFromFilePath", BlobFromFilePath);
void Blob::CreatePerContextProperties(Local<Object> target,
Local<Value> unused,
Local<Context> context,
void* priv) {
Realm* realm = Realm::GetCurrent(context);
realm->AddBindingData<BlobBindingData>(context, target);
}

Local<FunctionTemplate> Blob::GetConstructorTemplate(Environment* env) {
Expand Down Expand Up @@ -562,5 +565,7 @@ void Blob::RegisterExternalReferences(ExternalReferenceRegistry* registry) {

} // namespace node

NODE_BINDING_CONTEXT_AWARE_INTERNAL(blob, node::Blob::Initialize)
NODE_BINDING_CONTEXT_AWARE_INTERNAL(blob,
node::Blob::CreatePerContextProperties)
NODE_BINDING_PER_ISOLATE_INIT(blob, node::Blob::CreatePerIsolateProperties)
NODE_BINDING_EXTERNAL_REFERENCE(blob, node::Blob::RegisterExternalReferences)
11 changes: 6 additions & 5 deletions src/node_blob.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ class Blob : public BaseObject {
static void RegisterExternalReferences(
ExternalReferenceRegistry* registry);

static void Initialize(
v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv);
static void CreatePerIsolateProperties(IsolateData* isolate_data,
v8::Local<v8::FunctionTemplate> ctor);
static void CreatePerContextProperties(v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv);

static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetReader(const v8::FunctionCallbackInfo<v8::Value>& args);
Expand Down
Loading

0 comments on commit 827f713

Please sign in to comment.