diff --git a/src/README.md b/src/README.md index 1b2b8a951d88..58718935820a 100644 --- a/src/README.md +++ b/src/README.md @@ -482,7 +482,7 @@ Which explains that the unregistered external reference is Some internal bindings, such as the HTTP parser, maintain internal state that only affects that particular binding. In that case, one common way to store -that state is through the use of `Environment::AddBindingData`, which gives +that state is through the use of `Realm::AddBindingData`, which gives binding functions access to an object for storing such state. That object is always a [`BaseObject`][]. @@ -507,7 +507,7 @@ class BindingData : public BaseObject { // Available for binding functions, e.g. the HTTP Parser constructor: static void New(const FunctionCallbackInfo& args) { - BindingData* binding_data = Environment::GetBindingData(args); + BindingData* binding_data = Realm::GetBindingData(args); new Parser(binding_data, args.This()); } @@ -517,12 +517,12 @@ void InitializeHttpParser(Local target, Local unused, Local context, void* priv) { - Environment* env = Environment::GetCurrent(context); + Realm* realm = Realm::GetCurrent(context); BindingData* const binding_data = - env->AddBindingData(context, target); + realm->AddBindingData(context, target); if (binding_data == nullptr) return; - Local t = env->NewFunctionTemplate(Parser::New); + Local t = NewFunctionTemplate(realm->isolate(), Parser::New); ... } ``` diff --git a/src/base_object-inl.h b/src/base_object-inl.h index 675a472dab48..f003f1390b86 100644 --- a/src/base_object-inl.h +++ b/src/base_object-inl.h @@ -33,7 +33,10 @@ namespace node { BaseObject::BaseObject(Environment* env, v8::Local object) - : BaseObject(env->principal_realm(), object) {} + : BaseObject(env->principal_realm(), object) { + // TODO(legendecas): Check the shorthand is only used in the principal realm + // while allowing to create a BaseObject in a vm context. +} // static v8::Local BaseObject::GetConstructorTemplate( diff --git a/src/dataqueue/queue.cc b/src/dataqueue/queue.cc index a39314e23e13..7cf066a71859 100644 --- a/src/dataqueue/queue.cc +++ b/src/dataqueue/queue.cc @@ -874,14 +874,14 @@ class FdEntry final : public EntryImpl { uv_fs_close(nullptr, &req, file, nullptr); return nullptr; } + Realm* realm = entry->env()->principal_realm(); return std::make_shared( - BaseObjectPtr( - fs::FileHandle::New(entry->env()->GetBindingData( - entry->env()->context()), - file, - Local(), - entry->start_, - entry->end_)), + BaseObjectPtr(fs::FileHandle::New( + realm->GetBindingData(realm->context()), + file, + Local(), + entry->start_, + entry->end_)), entry); } diff --git a/src/env-inl.h b/src/env-inl.h index 0ca495bd58df..d84d28c70658 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -201,48 +201,6 @@ inline Environment* Environment::GetCurrent( return GetCurrent(info.GetIsolate()->GetCurrentContext()); } -template -inline T* Environment::GetBindingData(const v8::PropertyCallbackInfo& info) { - return GetBindingData(info.GetIsolate()->GetCurrentContext()); -} - -template -inline T* Environment::GetBindingData( - const v8::FunctionCallbackInfo& info) { - return GetBindingData(info.GetIsolate()->GetCurrentContext()); -} - -template -inline T* Environment::GetBindingData(v8::Local context) { - BindingDataStore* map = static_cast( - context->GetAlignedPointerFromEmbedderData( - ContextEmbedderIndex::kBindingListIndex)); - DCHECK_NOT_NULL(map); - auto it = map->find(T::type_name); - if (UNLIKELY(it == map->end())) return nullptr; - T* result = static_cast(it->second.get()); - DCHECK_NOT_NULL(result); - DCHECK_EQ(result->env(), GetCurrent(context)); - return result; -} - -template -inline T* Environment::AddBindingData( - v8::Local context, - v8::Local target) { - DCHECK_EQ(GetCurrent(context), this); - // This won't compile if T is not a BaseObject subclass. - BaseObjectPtr item = MakeDetachedBaseObject(this, target); - BindingDataStore* map = static_cast( - context->GetAlignedPointerFromEmbedderData( - ContextEmbedderIndex::kBindingListIndex)); - DCHECK_NOT_NULL(map); - auto result = map->emplace(T::type_name, item); - CHECK(result.second); - DCHECK_EQ(GetBindingData(context), item.get()); - return item.get(); -} - inline v8::Isolate* Environment::isolate() const { return isolate_; } diff --git a/src/env.cc b/src/env.cc index 172386993dbd..e315e41cedff 100644 --- a/src/env.cc +++ b/src/env.cc @@ -545,7 +545,8 @@ void Environment::AssignToContext(Local context, context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kRealm, realm); // Used to retrieve bindings context->SetAlignedPointerInEmbedderData( - ContextEmbedderIndex::kBindingListIndex, &(this->bindings_)); + ContextEmbedderIndex::kBindingDataStoreIndex, + realm->binding_data_store()); // ContextifyContexts will update this to a pointer to the native object. context->SetAlignedPointerInEmbedderData( @@ -1019,7 +1020,6 @@ MaybeLocal Environment::RunSnapshotDeserializeMain() const { void Environment::RunCleanup() { started_cleanup_ = true; TRACE_EVENT0(TRACING_CATEGORY_NODE1(environment), "RunCleanup"); - bindings_.clear(); // Only BaseObject's cleanups are registered as per-realm cleanup hooks now. // Defer the BaseObject cleanup after handles are cleaned up. CleanupHandles(); diff --git a/src/env.h b/src/env.h index 31f4a10b11b7..677c03d952d0 100644 --- a/src/env.h +++ b/src/env.h @@ -587,25 +587,6 @@ class Environment : public MemoryRetainer { static inline Environment* GetCurrent( const v8::PropertyCallbackInfo& info); - // Methods created using SetMethod(), SetPrototypeMethod(), etc. inside - // this scope can access the created T* object using - // GetBindingData(args) later. - template - T* AddBindingData(v8::Local context, - v8::Local target); - template - static inline T* GetBindingData(const v8::PropertyCallbackInfo& info); - template - static inline T* GetBindingData( - const v8::FunctionCallbackInfo& info); - template - static inline T* GetBindingData(v8::Local context); - - typedef std::unordered_map< - FastStringKey, - BaseObjectPtr, - FastStringKey::Hash> BindingDataStore; - // Create an Environment without initializing a main Context. Use // InitializeMainContext() to initialize a main context for it. Environment(IsolateData* isolate_data, @@ -1134,8 +1115,6 @@ class Environment : public MemoryRetainer { void RequestInterruptFromV8(); static void CheckImmediate(uv_check_t* handle); - BindingDataStore bindings_; - CleanupQueue cleanup_queue_; bool started_cleanup_ = false; diff --git a/src/node_blob.cc b/src/node_blob.cc index 884e9d61c9b9..b2fc527b3b50 100644 --- a/src/node_blob.cc +++ b/src/node_blob.cc @@ -110,10 +110,10 @@ void Blob::Initialize( Local unused, Local context, void* priv) { - Environment* env = Environment::GetCurrent(context); + Realm* realm = Realm::GetCurrent(context); BlobBindingData* const binding_data = - env->AddBindingData(context, target); + realm->AddBindingData(context, target); if (binding_data == nullptr) return; SetMethod(context, target, "createBlob", New); @@ -394,8 +394,7 @@ std::unique_ptr Blob::CloneForMessaging() const { void Blob::StoreDataObject(const v8::FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - BlobBindingData* binding_data = - Environment::GetBindingData(args); + BlobBindingData* binding_data = Realm::GetBindingData(args); CHECK(args[0]->IsString()); // ID key CHECK(Blob::HasInstance(env, args[1])); // Blob @@ -418,8 +417,7 @@ void Blob::StoreDataObject(const v8::FunctionCallbackInfo& args) { } void Blob::RevokeDataObject(const v8::FunctionCallbackInfo& args) { - BlobBindingData* binding_data = - Environment::GetBindingData(args); + BlobBindingData* binding_data = Realm::GetBindingData(args); Environment* env = Environment::GetCurrent(args); CHECK(args[0]->IsString()); // ID key @@ -430,8 +428,7 @@ void Blob::RevokeDataObject(const v8::FunctionCallbackInfo& args) { } void Blob::GetDataObject(const v8::FunctionCallbackInfo& args) { - BlobBindingData* binding_data = - Environment::GetBindingData(args); + BlobBindingData* binding_data = Realm::GetBindingData(args); Environment* env = Environment::GetCurrent(args); CHECK(args[0]->IsString()); @@ -477,8 +474,8 @@ BlobBindingData::StoredDataObject::StoredDataObject( length(length_), type(type_) {} -BlobBindingData::BlobBindingData(Environment* env, Local wrap) - : SnapshotableObject(env, wrap, type_int) { +BlobBindingData::BlobBindingData(Realm* realm, Local wrap) + : SnapshotableObject(realm, wrap, type_int) { MakeWeak(); } @@ -516,9 +513,9 @@ void BlobBindingData::Deserialize(Local context, InternalFieldInfoBase* info) { DCHECK_EQ(index, BaseObject::kEmbedderType); HandleScope scope(context->GetIsolate()); - Environment* env = Environment::GetCurrent(context); + Realm* realm = Realm::GetCurrent(context); BlobBindingData* binding = - env->AddBindingData(context, holder); + realm->AddBindingData(context, holder); CHECK_NOT_NULL(binding); } diff --git a/src/node_blob.h b/src/node_blob.h index e56627cf35cf..f6d5ad89f697 100644 --- a/src/node_blob.h +++ b/src/node_blob.h @@ -111,7 +111,7 @@ class Blob : public BaseObject { class BlobBindingData : public SnapshotableObject { public: - explicit BlobBindingData(Environment* env, v8::Local wrap); + explicit BlobBindingData(Realm* realm, v8::Local wrap); using InternalFieldInfo = InternalFieldInfoBase; diff --git a/src/node_context_data.h b/src/node_context_data.h index 4278a17f4b6a..009d46c34dc4 100644 --- a/src/node_context_data.h +++ b/src/node_context_data.h @@ -24,8 +24,8 @@ namespace node { #define NODE_CONTEXT_ALLOW_WASM_CODE_GENERATION_INDEX 34 #endif -#ifndef NODE_BINDING_LIST -#define NODE_BINDING_LIST_INDEX 35 +#ifndef NODE_BINDING_DATA_STORE_INDEX +#define NODE_BINDING_DATA_STORE_INDEX 35 #endif #ifndef NODE_CONTEXT_ALLOW_CODE_GENERATION_FROM_STRINGS_INDEX @@ -51,7 +51,7 @@ enum ContextEmbedderIndex { kEnvironment = NODE_CONTEXT_EMBEDDER_DATA_INDEX, kSandboxObject = NODE_CONTEXT_SANDBOX_OBJECT_INDEX, kAllowWasmCodeGeneration = NODE_CONTEXT_ALLOW_WASM_CODE_GENERATION_INDEX, - kBindingListIndex = NODE_BINDING_LIST_INDEX, + kBindingDataStoreIndex = NODE_BINDING_DATA_STORE_INDEX, kAllowCodeGenerationFromStrings = NODE_CONTEXT_ALLOW_CODE_GENERATION_FROM_STRINGS_INDEX, kContextifyContext = NODE_CONTEXT_CONTEXTIFY_CONTEXT_INDEX, diff --git a/src/node_file-inl.h b/src/node_file-inl.h index adce4cab53eb..2ba5906d614f 100644 --- a/src/node_file-inl.h +++ b/src/node_file-inl.h @@ -277,7 +277,7 @@ FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo& args, return Unwrap(value.As()); } - BindingData* binding_data = Environment::GetBindingData(args); + BindingData* binding_data = Realm::GetBindingData(args); Environment* env = binding_data->env(); if (value->StrictEquals(env->fs_use_promises_symbol())) { if (use_bigint) { diff --git a/src/node_file.cc b/src/node_file.cc index 673d67e2d3c0..388d9bf32c34 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -259,7 +259,7 @@ FileHandle* FileHandle::New(BindingData* binding_data, } void FileHandle::New(const FunctionCallbackInfo& args) { - BindingData* binding_data = Environment::GetBindingData(args); + BindingData* binding_data = Realm::GetBindingData(args); Environment* env = binding_data->env(); CHECK(args.IsConstructCall()); CHECK(args[0]->IsInt32()); @@ -324,7 +324,7 @@ BaseObjectPtr FileHandle::TransferData::Deserialize( Environment* env, v8::Local context, std::unique_ptr self) { - BindingData* bd = Environment::GetBindingData(context); + BindingData* bd = Realm::GetBindingData(context); if (bd == nullptr) return {}; int fd = fd_; @@ -724,7 +724,7 @@ void FSReqCallback::SetReturnValue(const FunctionCallbackInfo& args) { void NewFSReqCallback(const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); - BindingData* binding_data = Environment::GetBindingData(args); + BindingData* binding_data = Realm::GetBindingData(args); new FSReqCallback(binding_data, args.This(), args[0]->IsTrue()); } @@ -1131,7 +1131,7 @@ static void InternalModuleStat(const FunctionCallbackInfo& args) { } static void Stat(const FunctionCallbackInfo& args) { - BindingData* binding_data = Environment::GetBindingData(args); + BindingData* binding_data = Realm::GetBindingData(args); Environment* env = binding_data->env(); const int argc = args.Length(); @@ -1164,7 +1164,7 @@ static void Stat(const FunctionCallbackInfo& args) { } static void LStat(const FunctionCallbackInfo& args) { - BindingData* binding_data = Environment::GetBindingData(args); + BindingData* binding_data = Realm::GetBindingData(args); Environment* env = binding_data->env(); const int argc = args.Length(); @@ -1198,7 +1198,7 @@ static void LStat(const FunctionCallbackInfo& args) { } static void FStat(const FunctionCallbackInfo& args) { - BindingData* binding_data = Environment::GetBindingData(args); + BindingData* binding_data = Realm::GetBindingData(args); Environment* env = binding_data->env(); const int argc = args.Length(); @@ -1230,7 +1230,7 @@ static void FStat(const FunctionCallbackInfo& args) { } static void StatFs(const FunctionCallbackInfo& args) { - BindingData* binding_data = Environment::GetBindingData(args); + BindingData* binding_data = Realm::GetBindingData(args); Environment* env = binding_data->env(); const int argc = args.Length(); @@ -1945,7 +1945,7 @@ static void Open(const FunctionCallbackInfo& args) { } static void OpenFileHandle(const FunctionCallbackInfo& args) { - BindingData* binding_data = Environment::GetBindingData(args); + BindingData* binding_data = Realm::GetBindingData(args); Environment* env = binding_data->env(); Isolate* isolate = env->isolate(); @@ -2635,29 +2635,31 @@ void BindingData::MemoryInfo(MemoryTracker* tracker) const { file_handle_read_wrap_freelist); } -BindingData::BindingData(Environment* env, v8::Local wrap) - : SnapshotableObject(env, wrap, type_int), - stats_field_array(env->isolate(), kFsStatsBufferLength), - stats_field_bigint_array(env->isolate(), kFsStatsBufferLength), - statfs_field_array(env->isolate(), kFsStatFsBufferLength), - statfs_field_bigint_array(env->isolate(), kFsStatFsBufferLength) { - wrap->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "statValues"), +BindingData::BindingData(Realm* realm, v8::Local wrap) + : SnapshotableObject(realm, wrap, type_int), + stats_field_array(realm->isolate(), kFsStatsBufferLength), + stats_field_bigint_array(realm->isolate(), kFsStatsBufferLength), + statfs_field_array(realm->isolate(), kFsStatFsBufferLength), + statfs_field_bigint_array(realm->isolate(), kFsStatFsBufferLength) { + Isolate* isolate = realm->isolate(); + Local context = realm->context(); + wrap->Set(context, + FIXED_ONE_BYTE_STRING(isolate, "statValues"), stats_field_array.GetJSArray()) .Check(); - wrap->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "bigintStatValues"), + wrap->Set(context, + FIXED_ONE_BYTE_STRING(isolate, "bigintStatValues"), stats_field_bigint_array.GetJSArray()) .Check(); - wrap->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "statFsValues"), + wrap->Set(context, + FIXED_ONE_BYTE_STRING(isolate, "statFsValues"), statfs_field_array.GetJSArray()) .Check(); - wrap->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "bigintStatFsValues"), + wrap->Set(context, + FIXED_ONE_BYTE_STRING(isolate, "bigintStatFsValues"), statfs_field_bigint_array.GetJSArray()) .Check(); } @@ -2668,8 +2670,8 @@ void BindingData::Deserialize(Local context, InternalFieldInfoBase* info) { DCHECK_EQ(index, BaseObject::kEmbedderType); HandleScope scope(context->GetIsolate()); - Environment* env = Environment::GetCurrent(context); - BindingData* binding = env->AddBindingData(context, holder); + Realm* realm = Realm::GetCurrent(context); + BindingData* binding = realm->AddBindingData(context, holder); CHECK_NOT_NULL(binding); } @@ -2698,10 +2700,11 @@ void Initialize(Local target, Local unused, Local context, void* priv) { - Environment* env = Environment::GetCurrent(context); + Realm* realm = Realm::GetCurrent(context); + Environment* env = realm->env(); Isolate* isolate = env->isolate(); BindingData* const binding_data = - env->AddBindingData(context, target); + realm->AddBindingData(context, target); if (binding_data == nullptr) return; SetMethod(context, target, "access", Access); diff --git a/src/node_file.h b/src/node_file.h index 28c62bef799f..e44b58c94ff7 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -57,7 +57,7 @@ constexpr size_t kFsStatFsBufferLength = class BindingData : public SnapshotableObject { public: - explicit BindingData(Environment* env, v8::Local wrap); + explicit BindingData(Realm* realm, v8::Local wrap); AliasedFloat64Array stats_field_array; AliasedBigInt64Array stats_field_bigint_array; diff --git a/src/node_http2.cc b/src/node_http2.cc index 4209a1e1910d..7e8e04f440ae 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -2568,7 +2568,7 @@ void HttpErrorString(const FunctionCallbackInfo& args) { // would be suitable, for instance, for creating the Base64 // output for an HTTP2-Settings header field. void PackSettings(const FunctionCallbackInfo& args) { - Http2State* state = Environment::GetBindingData(args); + Http2State* state = Realm::GetBindingData(args); args.GetReturnValue().Set(Http2Settings::Pack(state)); } @@ -2576,7 +2576,7 @@ void PackSettings(const FunctionCallbackInfo& args) { // default SETTINGS. RefreshDefaultSettings updates that TypedArray with the // default values. void RefreshDefaultSettings(const FunctionCallbackInfo& args) { - Http2State* state = Environment::GetBindingData(args); + Http2State* state = Realm::GetBindingData(args); Http2Settings::RefreshDefaults(state); } @@ -2659,7 +2659,7 @@ void Http2Session::RefreshState(const FunctionCallbackInfo& args) { // Constructor for new Http2Session instances. void Http2Session::New(const FunctionCallbackInfo& args) { - Http2State* state = Environment::GetBindingData(args); + Http2State* state = Realm::GetBindingData(args); Environment* env = state->env(); CHECK(args.IsConstructCall()); SessionType type = @@ -3187,11 +3187,12 @@ void Initialize(Local target, Local unused, Local context, void* priv) { - Environment* env = Environment::GetCurrent(context); + Realm* realm = Realm::GetCurrent(context); + Environment* env = realm->env(); Isolate* isolate = env->isolate(); HandleScope handle_scope(isolate); - Http2State* const state = env->AddBindingData(context, target); + Http2State* const state = realm->AddBindingData(context, target); if (state == nullptr) return; #define SET_STATE_TYPEDARRAY(name, field) \ diff --git a/src/node_http2_state.h b/src/node_http2_state.h index 7cf40ff1017c..75a98bf476b2 100644 --- a/src/node_http2_state.h +++ b/src/node_http2_state.h @@ -83,34 +83,32 @@ namespace http2 { class Http2State : public BaseObject { public: - Http2State(Environment* env, v8::Local obj) - : BaseObject(env, obj), - root_buffer(env->isolate(), sizeof(http2_state_internal)), + Http2State(Realm* realm, v8::Local obj) + : BaseObject(realm, obj), + root_buffer(realm->isolate(), sizeof(http2_state_internal)), session_state_buffer( - env->isolate(), + realm->isolate(), offsetof(http2_state_internal, session_state_buffer), IDX_SESSION_STATE_COUNT, root_buffer), - stream_state_buffer( - env->isolate(), - offsetof(http2_state_internal, stream_state_buffer), - IDX_STREAM_STATE_COUNT, - root_buffer), - stream_stats_buffer( - env->isolate(), - offsetof(http2_state_internal, stream_stats_buffer), - IDX_STREAM_STATS_COUNT, - root_buffer), + stream_state_buffer(realm->isolate(), + offsetof(http2_state_internal, stream_state_buffer), + IDX_STREAM_STATE_COUNT, + root_buffer), + stream_stats_buffer(realm->isolate(), + offsetof(http2_state_internal, stream_stats_buffer), + IDX_STREAM_STATS_COUNT, + root_buffer), session_stats_buffer( - env->isolate(), + realm->isolate(), offsetof(http2_state_internal, session_stats_buffer), IDX_SESSION_STATS_COUNT, root_buffer), - options_buffer(env->isolate(), - offsetof(http2_state_internal, options_buffer), - IDX_OPTIONS_FLAGS + 1, - root_buffer), - settings_buffer(env->isolate(), + options_buffer(realm->isolate(), + offsetof(http2_state_internal, options_buffer), + IDX_OPTIONS_FLAGS + 1, + root_buffer), + settings_buffer(realm->isolate(), offsetof(http2_state_internal, settings_buffer), IDX_SETTINGS_COUNT + 1, root_buffer) {} diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index bb2019c74457..a502fa0ccd90 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -93,8 +93,7 @@ inline bool IsOWS(char c) { class BindingData : public BaseObject { public: - BindingData(Environment* env, Local obj) - : BaseObject(env, obj) {} + BindingData(Realm* realm, Local obj) : BaseObject(realm, obj) {} static constexpr FastStringKey type_name { "http_parser" }; @@ -531,7 +530,7 @@ class Parser : public AsyncWrap, public StreamListener { } static void New(const FunctionCallbackInfo& args) { - BindingData* binding_data = Environment::GetBindingData(args); + BindingData* binding_data = Realm::GetBindingData(args); new Parser(binding_data, args.This()); } @@ -1190,10 +1189,11 @@ void InitializeHttpParser(Local target, Local unused, Local context, void* priv) { - Environment* env = Environment::GetCurrent(context); + Realm* realm = Realm::GetCurrent(context); + Environment* env = realm->env(); Isolate* isolate = env->isolate(); BindingData* const binding_data = - env->AddBindingData(context, target); + realm->AddBindingData(context, target); if (binding_data == nullptr) return; Local t = NewFunctionTemplate(isolate, Parser::New); diff --git a/src/node_process.h b/src/node_process.h index 806537896088..30f655dfc71f 100644 --- a/src/node_process.h +++ b/src/node_process.h @@ -58,7 +58,7 @@ class BindingData : public SnapshotableObject { static constexpr EmbedderObjectType type_int = EmbedderObjectType::k_process_binding_data; - BindingData(Environment* env, v8::Local object); + BindingData(Realm* realm, v8::Local object); void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(BindingData) diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc index 778e4cd9dd96..93657860379f 100644 --- a/src/node_process_methods.cc +++ b/src/node_process_methods.cc @@ -464,14 +464,13 @@ static void ReallyExit(const FunctionCallbackInfo& args) { namespace process { -BindingData::BindingData(Environment* env, v8::Local object) - : SnapshotableObject(env, object, type_int) { - Local ab = ArrayBuffer::New(env->isolate(), kBufferSize); - array_buffer_.Reset(env->isolate(), ab); - object - ->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "hrtimeBuffer"), - ab) +BindingData::BindingData(Realm* realm, v8::Local object) + : SnapshotableObject(realm, object, type_int) { + Isolate* isolate = realm->isolate(); + Local context = realm->context(); + Local ab = ArrayBuffer::New(isolate, kBufferSize); + array_buffer_.Reset(isolate, ab); + object->Set(context, FIXED_ONE_BYTE_STRING(isolate, "hrtimeBuffer"), ab) .ToChecked(); backing_store_ = ab->GetBackingStore(); } @@ -564,9 +563,9 @@ void BindingData::Deserialize(Local context, InternalFieldInfoBase* info) { DCHECK_EQ(index, BaseObject::kEmbedderType); v8::HandleScope scope(context->GetIsolate()); - Environment* env = Environment::GetCurrent(context); + Realm* realm = Realm::GetCurrent(context); // Recreate the buffer in the constructor. - BindingData* binding = env->AddBindingData(context, holder); + BindingData* binding = realm->AddBindingData(context, holder); CHECK_NOT_NULL(binding); } @@ -574,9 +573,10 @@ static void Initialize(Local target, Local unused, Local context, void* priv) { - Environment* env = Environment::GetCurrent(context); + Realm* realm = Realm::GetCurrent(context); + Environment* env = realm->env(); BindingData* const binding_data = - env->AddBindingData(context, target); + realm->AddBindingData(context, target); if (binding_data == nullptr) return; binding_data->AddMethods(); diff --git a/src/node_realm-inl.h b/src/node_realm-inl.h index 95a09dafac76..01aca9382eeb 100644 --- a/src/node_realm-inl.h +++ b/src/node_realm-inl.h @@ -46,6 +46,54 @@ inline bool Realm::has_run_bootstrapping_code() const { return has_run_bootstrapping_code_; } +// static +template +inline T* Realm::GetBindingData(const v8::PropertyCallbackInfo& info) { + return GetBindingData(info.GetIsolate()->GetCurrentContext()); +} + +// static +template +inline T* Realm::GetBindingData( + const v8::FunctionCallbackInfo& info) { + return GetBindingData(info.GetIsolate()->GetCurrentContext()); +} + +// static +template +inline T* Realm::GetBindingData(v8::Local context) { + BindingDataStore* map = + static_cast(context->GetAlignedPointerFromEmbedderData( + ContextEmbedderIndex::kBindingDataStoreIndex)); + DCHECK_NOT_NULL(map); + auto it = map->find(T::type_name); + if (UNLIKELY(it == map->end())) return nullptr; + T* result = static_cast(it->second.get()); + DCHECK_NOT_NULL(result); + DCHECK_EQ(result->realm(), GetCurrent(context)); + return result; +} + +template +inline T* Realm::AddBindingData(v8::Local context, + v8::Local target) { + DCHECK_EQ(GetCurrent(context), this); + // This won't compile if T is not a BaseObject subclass. + BaseObjectPtr item = MakeDetachedBaseObject(this, target); + BindingDataStore* map = + static_cast(context->GetAlignedPointerFromEmbedderData( + ContextEmbedderIndex::kBindingDataStoreIndex)); + DCHECK_NOT_NULL(map); + auto result = map->emplace(T::type_name, item); + CHECK(result.second); + DCHECK_EQ(GetBindingData(context), item.get()); + return item.get(); +} + +inline BindingDataStore* Realm::binding_data_store() { + return &binding_data_store_; +} + template void Realm::ForEachBaseObject(T&& iterator) const { cleanup_queue_.ForEachBaseObject(std::forward(iterator)); diff --git a/src/node_realm.cc b/src/node_realm.cc index e0fcd3a07759..9452e336ea78 100644 --- a/src/node_realm.cc +++ b/src/node_realm.cc @@ -302,6 +302,7 @@ void Realm::DoneBootstrapping() { void Realm::RunCleanup() { TRACE_EVENT0(TRACING_CATEGORY_NODE1(realm), "RunCleanup"); + binding_data_store_.clear(); cleanup_queue_.Drain(); } diff --git a/src/node_realm.h b/src/node_realm.h index c97a3a3e9ae0..cf37fe31bdd6 100644 --- a/src/node_realm.h +++ b/src/node_realm.h @@ -4,6 +4,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include +#include #include "cleanup_queue.h" #include "env_properties.h" #include "memory_tracker.h" @@ -20,6 +21,10 @@ struct RealmSerializeInfo { friend std::ostream& operator<<(std::ostream& o, const RealmSerializeInfo& i); }; +using BindingDataStore = std::unordered_map, + FastStringKey::Hash>; + /** * node::Realm is a container for a set of JavaScript objects and functions * that associated with a particular global environment. @@ -85,6 +90,21 @@ class Realm : public MemoryRetainer { inline v8::Local context() const; inline bool has_run_bootstrapping_code() const; + // Methods created using SetMethod(), SetPrototypeMethod(), etc. inside + // this scope can access the created T* object using + // GetBindingData(args) later. + template + T* AddBindingData(v8::Local context, + v8::Local target); + template + static inline T* GetBindingData(const v8::PropertyCallbackInfo& info); + template + static inline T* GetBindingData( + const v8::FunctionCallbackInfo& info); + template + static inline T* GetBindingData(v8::Local context); + inline BindingDataStore* binding_data_store(); + // The BaseObject count is a debugging helper that makes sure that there are // no memory leaks caused by BaseObjects staying alive longer than expected // (in particular, no circular BaseObjectPtr references). @@ -121,6 +141,8 @@ class Realm : public MemoryRetainer { int64_t base_object_count_ = 0; int64_t base_object_created_by_bootstrap_ = 0; + BindingDataStore binding_data_store_; + CleanupQueue cleanup_queue_; #define V(PropertyName, TypeName) v8::Global PropertyName##_; diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index d4f45bf31019..e1ceb78adce0 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -1284,11 +1284,10 @@ ExitCode SnapshotBuilder::Generate(std::ostream& out, return exit_code; } -SnapshotableObject::SnapshotableObject(Environment* env, +SnapshotableObject::SnapshotableObject(Realm* realm, Local wrap, EmbedderObjectType type) - : BaseObject(env, wrap), type_(type) { -} + : BaseObject(realm, wrap), type_(type) {} std::string_view SnapshotableObject::GetTypeName() const { switch (type_) { diff --git a/src/node_snapshotable.h b/src/node_snapshotable.h index a825350806bf..3f4d0780131e 100644 --- a/src/node_snapshotable.h +++ b/src/node_snapshotable.h @@ -98,7 +98,7 @@ struct InternalFieldInfoBase { // in the object. class SnapshotableObject : public BaseObject { public: - SnapshotableObject(Environment* env, + SnapshotableObject(Realm* realm, v8::Local wrap, EmbedderObjectType type); std::string_view GetTypeName() const; diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index de8c099ca585..83b96e9dd203 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -97,8 +97,7 @@ void StatWatcher::Callback(uv_fs_poll_t* handle, void StatWatcher::New(const FunctionCallbackInfo& args) { CHECK(args.IsConstructCall()); - fs::BindingData* binding_data = - Environment::GetBindingData(args); + fs::BindingData* binding_data = Realm::GetBindingData(args); new StatWatcher(binding_data, args.This(), args[0]->IsTrue()); } diff --git a/src/node_util.cc b/src/node_util.cc index 39660130ba4d..0ce3af33c824 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -179,20 +179,20 @@ void ArrayBufferViewHasBuffer(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(args[0].As()->HasBuffer()); } -WeakReference::WeakReference(Environment* env, +WeakReference::WeakReference(Realm* realm, Local object, Local target) - : WeakReference(env, object, target, 0) {} + : WeakReference(realm, object, target, 0) {} -WeakReference::WeakReference(Environment* env, +WeakReference::WeakReference(Realm* realm, Local object, Local target, uint64_t reference_count) - : SnapshotableObject(env, object, type_int), + : SnapshotableObject(realm, object, type_int), reference_count_(reference_count) { MakeWeak(); if (!target.IsEmpty()) { - target_.Reset(env->isolate(), target); + target_.Reset(realm->isolate(), target); if (reference_count_ == 0) { target_.SetWeak(); } @@ -245,17 +245,15 @@ void WeakReference::Deserialize(Local context, target = context->GetDataFromSnapshotOnce(weak_info->target) .ToLocalChecked(); } - new WeakReference(Environment::GetCurrent(context), - holder, - target, - weak_info->reference_count); + new WeakReference( + Realm::GetCurrent(context), holder, target, weak_info->reference_count); } void WeakReference::New(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); + Realm* realm = Realm::GetCurrent(args); CHECK(args.IsConstructCall()); CHECK(args[0]->IsObject()); - new WeakReference(env, args.This(), args[0].As()); + new WeakReference(realm, args.This(), args[0].As()); } void WeakReference::Get(const FunctionCallbackInfo& args) { diff --git a/src/node_util.h b/src/node_util.h index 9590842ae476..7192e080f2b0 100644 --- a/src/node_util.h +++ b/src/node_util.h @@ -18,7 +18,7 @@ class WeakReference : public SnapshotableObject { static constexpr EmbedderObjectType type_int = EmbedderObjectType::k_util_weak_reference; - WeakReference(Environment* env, + WeakReference(Realm* realm, v8::Local object, v8::Local target); static void New(const v8::FunctionCallbackInfo& args); @@ -37,7 +37,7 @@ class WeakReference : public SnapshotableObject { }; private: - WeakReference(Environment* env, + WeakReference(Realm* realm, v8::Local object, v8::Local target, uint64_t reference_count); diff --git a/src/node_v8.cc b/src/node_v8.cc index 890f59eea673..f4900328cfe5 100644 --- a/src/node_v8.cc +++ b/src/node_v8.cc @@ -91,23 +91,24 @@ static const size_t kHeapCodeStatisticsPropertiesCount = HEAP_CODE_STATISTICS_PROPERTIES(V); #undef V -BindingData::BindingData(Environment* env, Local obj) - : SnapshotableObject(env, obj, type_int), - heap_statistics_buffer(env->isolate(), kHeapStatisticsPropertiesCount), - heap_space_statistics_buffer(env->isolate(), +BindingData::BindingData(Realm* realm, Local obj) + : SnapshotableObject(realm, obj, type_int), + heap_statistics_buffer(realm->isolate(), kHeapStatisticsPropertiesCount), + heap_space_statistics_buffer(realm->isolate(), kHeapSpaceStatisticsPropertiesCount), - heap_code_statistics_buffer(env->isolate(), + heap_code_statistics_buffer(realm->isolate(), kHeapCodeStatisticsPropertiesCount) { - obj->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "heapStatisticsBuffer"), + Local context = realm->context(); + obj->Set(context, + FIXED_ONE_BYTE_STRING(realm->isolate(), "heapStatisticsBuffer"), heap_statistics_buffer.GetJSArray()) .Check(); - obj->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "heapCodeStatisticsBuffer"), + obj->Set(context, + FIXED_ONE_BYTE_STRING(realm->isolate(), "heapCodeStatisticsBuffer"), heap_code_statistics_buffer.GetJSArray()) .Check(); - obj->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "heapSpaceStatisticsBuffer"), + obj->Set(context, + FIXED_ONE_BYTE_STRING(realm->isolate(), "heapSpaceStatisticsBuffer"), heap_space_statistics_buffer.GetJSArray()) .Check(); } @@ -130,8 +131,8 @@ void BindingData::Deserialize(Local context, InternalFieldInfoBase* info) { DCHECK_EQ(index, BaseObject::kEmbedderType); HandleScope scope(context->GetIsolate()); - Environment* env = Environment::GetCurrent(context); - BindingData* binding = env->AddBindingData(context, holder); + Realm* realm = Realm::GetCurrent(context); + BindingData* binding = realm->AddBindingData(context, holder); CHECK_NOT_NULL(binding); } @@ -168,7 +169,7 @@ void SetHeapSnapshotNearHeapLimit(const FunctionCallbackInfo& args) { } void UpdateHeapStatisticsBuffer(const FunctionCallbackInfo& args) { - BindingData* data = Environment::GetBindingData(args); + BindingData* data = Realm::GetBindingData(args); HeapStatistics s; args.GetIsolate()->GetHeapStatistics(&s); AliasedFloat64Array& buffer = data->heap_statistics_buffer; @@ -179,7 +180,7 @@ void UpdateHeapStatisticsBuffer(const FunctionCallbackInfo& args) { void UpdateHeapSpaceStatisticsBuffer(const FunctionCallbackInfo& args) { - BindingData* data = Environment::GetBindingData(args); + BindingData* data = Realm::GetBindingData(args); HeapSpaceStatistics s; Isolate* const isolate = args.GetIsolate(); CHECK(args[0]->IsUint32()); @@ -194,7 +195,7 @@ void UpdateHeapSpaceStatisticsBuffer(const FunctionCallbackInfo& args) { } void UpdateHeapCodeStatisticsBuffer(const FunctionCallbackInfo& args) { - BindingData* data = Environment::GetBindingData(args); + BindingData* data = Realm::GetBindingData(args); HeapCodeStatistics s; args.GetIsolate()->GetHeapCodeAndMetadataStatistics(&s); AliasedFloat64Array& buffer = data->heap_code_statistics_buffer; @@ -393,9 +394,10 @@ void Initialize(Local target, Local unused, Local context, void* priv) { - Environment* env = Environment::GetCurrent(context); + Realm* realm = Realm::GetCurrent(context); + Environment* env = realm->env(); BindingData* const binding_data = - env->AddBindingData(context, target); + realm->AddBindingData(context, target); if (binding_data == nullptr) return; SetMethodNoSideEffect( diff --git a/src/node_v8.h b/src/node_v8.h index ecab454603b3..2d95002bcfc4 100644 --- a/src/node_v8.h +++ b/src/node_v8.h @@ -18,7 +18,7 @@ struct InternalFieldInfoBase; namespace v8_utils { class BindingData : public SnapshotableObject { public: - BindingData(Environment* env, v8::Local obj); + BindingData(Realm* realm, v8::Local obj); using InternalFieldInfo = InternalFieldInfoBase;