diff --git a/src/README.md b/src/README.md index 847109950fab2a..ca683952e0f658 100644 --- a/src/README.md +++ b/src/README.md @@ -126,10 +126,10 @@ Typical ways of working with internal fields are: * `obj->GetInternalField(i)` to get a JavaScript value from an internal field. * `obj->SetInternalField(i, v)` to store a JavaScript value in an internal field. -* `obj->GetAlignedPointerFromInternalField(i)` to get a `void*` pointer from an - internal field. -* `obj->SetAlignedPointerInInternalField(i, p)` to store a `void*` pointer in an - internal field. +* `obj->GetAlignedPointerFromInternalField(i, EmbedderDataTag::kDefault)` to get + a `void*` pointer from an internal field. +* `obj->SetAlignedPointerInInternalField(i, p, EmbedderDataTag::kDefault)` to store + a `void*` pointer in an internal field. [`Context`][]s provide the same feature under the name “embedder data”. diff --git a/src/base_object-inl.h b/src/base_object-inl.h index 37d83e41b618a0..cc8a8b7f2965cf 100644 --- a/src/base_object-inl.h +++ b/src/base_object-inl.h @@ -74,8 +74,9 @@ bool BaseObject::IsBaseObject(IsolateData* isolate_data, return false; } - uint16_t* ptr = static_cast( - obj->GetAlignedPointerFromInternalField(BaseObject::kEmbedderType)); + uint16_t* ptr = + static_cast(obj->GetAlignedPointerFromInternalField( + BaseObject::kEmbedderType, EmbedderDataTag::kEmbedderType)); return ptr == isolate_data->embedder_id_for_non_cppgc(); } @@ -83,21 +84,24 @@ void BaseObject::TagBaseObject(IsolateData* isolate_data, v8::Local object) { DCHECK_GE(object->InternalFieldCount(), BaseObject::kInternalFieldCount); object->SetAlignedPointerInInternalField( - BaseObject::kEmbedderType, isolate_data->embedder_id_for_non_cppgc()); + BaseObject::kEmbedderType, + isolate_data->embedder_id_for_non_cppgc(), + EmbedderDataTag::kEmbedderType); } void BaseObject::SetInternalFields(IsolateData* isolate_data, v8::Local object, void* slot) { TagBaseObject(isolate_data, object); - object->SetAlignedPointerInInternalField(BaseObject::kSlot, slot); + object->SetAlignedPointerInInternalField( + BaseObject::kSlot, slot, EmbedderDataTag::kDefault); } BaseObject* BaseObject::FromJSObject(v8::Local value) { v8::Local obj = value.As(); DCHECK_GE(obj->InternalFieldCount(), BaseObject::kInternalFieldCount); - return static_cast( - obj->GetAlignedPointerFromInternalField(BaseObject::kSlot)); + return static_cast(obj->GetAlignedPointerFromInternalField( + BaseObject::kSlot, EmbedderDataTag::kDefault)); } template diff --git a/src/base_object.cc b/src/base_object.cc index 404e2aa8c88d0c..36e7ee5ffb5250 100644 --- a/src/base_object.cc +++ b/src/base_object.cc @@ -45,7 +45,8 @@ BaseObject::~BaseObject() { { HandleScope handle_scope(realm()->isolate()); - object()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr); + object()->SetAlignedPointerInInternalField( + BaseObject::kSlot, nullptr, EmbedderDataTag::kDefault); } } diff --git a/src/base_object.h b/src/base_object.h index ad5a3194007b0a..f838bc01036720 100644 --- a/src/base_object.h +++ b/src/base_object.h @@ -27,6 +27,7 @@ #include // std::remove_reference #include "base_object_types.h" #include "memory_tracker.h" +#include "node_v8_embedder.h" #include "util.h" #include "v8.h" diff --git a/src/cppgc_helpers-inl.h b/src/cppgc_helpers-inl.h index 330af7a383058c..26cf107602f3df 100644 --- a/src/cppgc_helpers-inl.h +++ b/src/cppgc_helpers-inl.h @@ -19,8 +19,10 @@ void CppgcMixin::Wrap(T* ptr, Realm* realm, v8::Local obj) { v8::Object::Wrap(isolate, obj, wrappable); // Keep the layout consistent with BaseObjects. obj->SetAlignedPointerInInternalField( - kEmbedderType, realm->isolate_data()->embedder_id_for_cppgc()); - obj->SetAlignedPointerInInternalField(kSlot, ptr); + kEmbedderType, + realm->isolate_data()->embedder_id_for_cppgc(), + EmbedderDataTag::kEmbedderType); + obj->SetAlignedPointerInInternalField(kSlot, ptr, EmbedderDataTag::kDefault); realm->TrackCppgcWrapper(ptr); } @@ -41,7 +43,8 @@ T* CppgcMixin::Unwrap(v8::Local obj) { if (obj->InternalFieldCount() != T::kInternalFieldCount) { return nullptr; } - T* ptr = static_cast(obj->GetAlignedPointerFromInternalField(T::kSlot)); + T* ptr = static_cast(obj->GetAlignedPointerFromInternalField( + T::kSlot, EmbedderDataTag::kDefault)); return ptr; } diff --git a/src/env-inl.h b/src/env-inl.h index adb5879532ce62..b6a85ce214e0ac 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -196,9 +196,8 @@ inline Environment* Environment::GetCurrent(v8::Local context) { if (!ContextEmbedderTag::IsNodeContext(context)) [[unlikely]] { return nullptr; } - return static_cast( - context->GetAlignedPointerFromEmbedderData( - ContextEmbedderIndex::kEnvironment)); + return static_cast(context->GetAlignedPointerFromEmbedderData( + ContextEmbedderIndex::kEnvironment, EmbedderDataTag::kPerContextData)); } inline Environment* Environment::GetCurrent( diff --git a/src/env.cc b/src/env.cc index f6aeb75933bd59..02d47601edbfd0 100644 --- a/src/env.cc +++ b/src/env.cc @@ -674,12 +674,16 @@ void Environment::AssignToContext(Local context, Realm* realm, const ContextInfo& info) { context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kEnvironment, - this); - context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kRealm, realm); + this, + EmbedderDataTag::kPerContextData); + context->SetAlignedPointerInEmbedderData( + ContextEmbedderIndex::kRealm, realm, EmbedderDataTag::kPerContextData); // ContextifyContexts will update this to a pointer to the native object. context->SetAlignedPointerInEmbedderData( - ContextEmbedderIndex::kContextifyContext, nullptr); + ContextEmbedderIndex::kContextifyContext, + nullptr, + EmbedderDataTag::kPerContextData); // This must not be done before other context fields are initialized. ContextEmbedderTag::TagNodeContext(context); @@ -695,11 +699,15 @@ void Environment::AssignToContext(Local context, void Environment::UnassignFromContext(Local context) { if (!context.IsEmpty()) { context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kEnvironment, - nullptr); + nullptr, + EmbedderDataTag::kPerContextData); context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kRealm, - nullptr); + nullptr, + EmbedderDataTag::kPerContextData); context->SetAlignedPointerInEmbedderData( - ContextEmbedderIndex::kContextifyContext, nullptr); + ContextEmbedderIndex::kContextifyContext, + nullptr, + EmbedderDataTag::kPerContextData); } UntrackContext(context); } diff --git a/src/histogram.cc b/src/histogram.cc index 836a51b0e5aa4b..a0edd77e671f8a 100644 --- a/src/histogram.cc +++ b/src/histogram.cc @@ -136,7 +136,8 @@ HistogramBase::HistogramBase( MakeWeak(); wrap->SetAlignedPointerInInternalField( HistogramImpl::InternalFields::kImplField, - static_cast(this)); + static_cast(this), + EmbedderDataTag::kDefault); } HistogramBase::HistogramBase( @@ -148,7 +149,8 @@ HistogramBase::HistogramBase( MakeWeak(); wrap->SetAlignedPointerInInternalField( HistogramImpl::InternalFields::kImplField, - static_cast(this)); + static_cast(this), + EmbedderDataTag::kDefault); } void HistogramBase::MemoryInfo(MemoryTracker* tracker) const { @@ -362,7 +364,8 @@ IntervalHistogram::IntervalHistogram( MakeWeak(); wrap->SetAlignedPointerInInternalField( HistogramImpl::InternalFields::kImplField, - static_cast(this)); + static_cast(this), + EmbedderDataTag::kDefault); uv_timer_init(env->event_loop(), &timer_); } @@ -600,8 +603,8 @@ double HistogramImpl::FastGetPercentile(Local receiver, HistogramImpl* HistogramImpl::FromJSObject(Local value) { auto obj = value.As(); DCHECK_GE(obj->InternalFieldCount(), HistogramImpl::kInternalFieldCount); - return static_cast( - obj->GetAlignedPointerFromInternalField(HistogramImpl::kImplField)); + return static_cast(obj->GetAlignedPointerFromInternalField( + HistogramImpl::kImplField, EmbedderDataTag::kDefault)); } std::unique_ptr diff --git a/src/js_udp_wrap.cc b/src/js_udp_wrap.cc index 51e4f8c45ffd38..1c038d56ade9b5 100644 --- a/src/js_udp_wrap.cc +++ b/src/js_udp_wrap.cc @@ -55,8 +55,9 @@ JSUDPWrap::JSUDPWrap(Environment* env, Local obj) : AsyncWrap(env, obj, PROVIDER_JSUDPWRAP) { MakeWeak(); - obj->SetAlignedPointerInInternalField( - kUDPWrapBaseField, static_cast(this)); + obj->SetAlignedPointerInInternalField(kUDPWrapBaseField, + static_cast(this), + EmbedderDataTag::kDefault); } int JSUDPWrap::RecvStart() { diff --git a/src/node_context_data.h b/src/node_context_data.h index d81c75daaae47b..02eae73cb2ca44 100644 --- a/src/node_context_data.h +++ b/src/node_context_data.h @@ -3,6 +3,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS +#include "node_v8_embedder.h" #include "util.h" #include "v8.h" @@ -135,7 +136,8 @@ class ContextEmbedderTag { // context. context->SetAlignedPointerInEmbedderData( ContextEmbedderIndex::kContextTag, - ContextEmbedderTag::kNodeContextTagPtr); + ContextEmbedderTag::kNodeContextTagPtr, + EmbedderDataTag::kPerContextData); } static inline bool IsNodeContext(v8::Local context) { @@ -147,7 +149,8 @@ class ContextEmbedderTag { return false; } if (context->GetAlignedPointerFromEmbedderData( - ContextEmbedderIndex::kContextTag) != + ContextEmbedderIndex::kContextTag, + EmbedderDataTag::kPerContextData) != ContextEmbedderTag::kNodeContextTagPtr) [[unlikely]] { return false; } diff --git a/src/node_contextify.cc b/src/node_contextify.cc index e66d4fcb0c064f..713b0777b875bd 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -164,9 +164,12 @@ ContextifyContext::ContextifyContext(Environment* env, // This should only be done after the initial initializations of the context // global object is finished. DCHECK_NULL(v8_context->GetAlignedPointerFromEmbedderData( - ContextEmbedderIndex::kContextifyContext)); + ContextEmbedderIndex::kContextifyContext, + EmbedderDataTag::kPerContextData)); v8_context->SetAlignedPointerInEmbedderData( - ContextEmbedderIndex::kContextifyContext, this); + ContextEmbedderIndex::kContextifyContext, + this, + EmbedderDataTag::kPerContextData); } void ContextifyContext::InitializeGlobalTemplates(IsolateData* isolate_data) { @@ -473,7 +476,8 @@ ContextifyContext* ContextifyContext::Get(Local object) { } return static_cast( context->GetAlignedPointerFromEmbedderData( - ContextEmbedderIndex::kContextifyContext)); + ContextEmbedderIndex::kContextifyContext, + EmbedderDataTag::kPerContextData)); } bool ContextifyContext::IsStillInitializing(const ContextifyContext* ctx) { diff --git a/src/node_object_wrap.h b/src/node_object_wrap.h index cb13d84388bcc6..cf8df3af48a12f 100644 --- a/src/node_object_wrap.h +++ b/src/node_object_wrap.h @@ -49,7 +49,8 @@ class ObjectWrap { assert(handle->InternalFieldCount() > 0); // Cast to ObjectWrap before casting to T. A direct cast from void // to T won't work right when T has more than one base class. - void* ptr = handle->GetAlignedPointerFromInternalField(0); + void* ptr = handle->GetAlignedPointerFromInternalField( + 0, v8::kEmbedderDataTypeTagDefault); ObjectWrap* wrap = static_cast(ptr); return static_cast(wrap); } @@ -75,7 +76,8 @@ class ObjectWrap { inline void Wrap(v8::Local handle) { assert(persistent().IsEmpty()); assert(handle->InternalFieldCount() > 0); - handle->SetAlignedPointerInInternalField(0, this); + handle->SetAlignedPointerInInternalField( + 0, this, v8::kEmbedderDataTypeTagDefault); persistent().Reset(v8::Isolate::GetCurrent(), handle); MakeWeak(); } diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc index fe4aad63bc877b..66c7c1cc713068 100644 --- a/src/node_process_methods.cc +++ b/src/node_process_methods.cc @@ -673,7 +673,8 @@ void BindingData::RegisterExternalReferences( BindingData* BindingData::FromV8Value(Local value) { Local v8_object = value.As(); return static_cast( - v8_object->GetAlignedPointerFromInternalField(BaseObject::kSlot)); + v8_object->GetAlignedPointerFromInternalField(BaseObject::kSlot, + EmbedderDataTag::kDefault)); } void BindingData::MemoryInfo(MemoryTracker* tracker) const { diff --git a/src/node_realm-inl.h b/src/node_realm-inl.h index f162d1506c990a..9d0510f42d5c0c 100644 --- a/src/node_realm-inl.h +++ b/src/node_realm-inl.h @@ -20,8 +20,8 @@ inline Realm* Realm::GetCurrent(v8::Local context) { if (!ContextEmbedderTag::IsNodeContext(context)) [[unlikely]] { return nullptr; } - return static_cast( - context->GetAlignedPointerFromEmbedderData(ContextEmbedderIndex::kRealm)); + return static_cast(context->GetAlignedPointerFromEmbedderData( + ContextEmbedderIndex::kRealm, EmbedderDataTag::kPerContextData)); } inline Realm* Realm::GetCurrent( diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index e34d24d51d5c09..4dc966264a4c04 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -1309,7 +1309,8 @@ StartupData SerializeNodeContextData(Local holder, case ContextEmbedderIndex::kContextifyContext: case ContextEmbedderIndex::kRealm: case ContextEmbedderIndex::kContextTag: { - void* data = holder->GetAlignedPointerFromEmbedderData(index); + void* data = holder->GetAlignedPointerFromEmbedderData( + index, EmbedderDataTag::kPerContextData); per_process::Debug( DebugCategory::MKSNAPSHOT, "Serialize context data, index=%d, holder=%p, ptr=%p\n", @@ -1400,7 +1401,8 @@ StartupData SerializeNodeContextInternalFields(Local holder, // For the moment we do not set any internal fields in ArrayBuffer // or ArrayBufferViews, so just return nullptr. if (holder->IsArrayBuffer() || holder->IsArrayBufferView()) { - CHECK_NULL(holder->GetAlignedPointerFromInternalField(index)); + CHECK_NULL(holder->GetAlignedPointerFromInternalField( + index, EmbedderDataTag::kDefault)); return StartupData{nullptr, 0}; } @@ -1419,8 +1421,9 @@ StartupData SerializeNodeContextInternalFields(Local holder, static_cast(index), *holder); - BaseObject* object_ptr = static_cast( - holder->GetAlignedPointerFromInternalField(BaseObject::kSlot)); + BaseObject* object_ptr = + static_cast(holder->GetAlignedPointerFromInternalField( + BaseObject::kSlot, EmbedderDataTag::kDefault)); // If the native object is already set to null, ignore it. if (object_ptr == nullptr) { return StartupData{nullptr, 0}; diff --git a/src/node_v8_embedder.h b/src/node_v8_embedder.h new file mode 100644 index 00000000000000..26a98bdb706fd8 --- /dev/null +++ b/src/node_v8_embedder.h @@ -0,0 +1,26 @@ +#ifndef SRC_NODE_V8_EMBEDDER_H_ +#define SRC_NODE_V8_EMBEDDER_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include + +namespace node { + +// Type tags for different kinds of embedder data stored in V8 aligned pointer +// slots. +enum EmbedderDataTag : uint16_t { + // kDefault is used in slots that don't use V8 type tagging. + kDefault = 0, + // kEmbedderType is used by BaseObject to store the kEmbedderType value. + kEmbedderType, + // kPerContextData is used to store data on a `v8::Context`, including + // slots indexed by ContextEmbedderIndex. + kPerContextData, +}; + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_NODE_V8_EMBEDDER_H_ diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h index 29a4c29f3d3822..98fd0bacf358bd 100644 --- a/src/stream_base-inl.h +++ b/src/stream_base-inl.h @@ -22,19 +22,19 @@ void StreamReq::AttachToObject(v8::Local req_wrap_obj) { StreamReq::kStreamReqField), nullptr); req_wrap_obj->SetAlignedPointerInInternalField( - StreamReq::kStreamReqField, this); + StreamReq::kStreamReqField, this, EmbedderDataTag::kDefault); } StreamReq* StreamReq::FromObject(v8::Local req_wrap_obj) { return static_cast( req_wrap_obj->GetAlignedPointerFromInternalField( - StreamReq::kStreamReqField)); + StreamReq::kStreamReqField, EmbedderDataTag::kDefault)); } void StreamReq::Dispose() { BaseObjectPtr destroy_me{GetAsyncWrap()}; object()->SetAlignedPointerInInternalField( - StreamReq::kStreamReqField, nullptr); + StreamReq::kStreamReqField, nullptr, EmbedderDataTag::kDefault); destroy_me->Detach(); } @@ -120,16 +120,16 @@ SimpleWriteWrap::SimpleWriteWrap( void StreamBase::AttachToObject(v8::Local obj) { obj->SetAlignedPointerInInternalField( - StreamBase::kStreamBaseField, this); + StreamBase::kStreamBaseField, this, EmbedderDataTag::kDefault); } StreamBase* StreamBase::FromObject(v8::Local obj) { - if (obj->GetAlignedPointerFromInternalField(StreamBase::kSlot) == nullptr) + if (obj->GetAlignedPointerFromInternalField( + StreamBase::kSlot, EmbedderDataTag::kDefault) == nullptr) return nullptr; - return static_cast( - obj->GetAlignedPointerFromInternalField( - StreamBase::kStreamBaseField)); + return static_cast(obj->GetAlignedPointerFromInternalField( + StreamBase::kStreamBaseField, EmbedderDataTag::kDefault)); } WriteWrap* WriteWrap::FromObject(v8::Local req_wrap_obj) { @@ -162,8 +162,10 @@ void WriteWrap::SetBackingStore(std::unique_ptr bs) { void StreamReq::ResetObject(v8::Local obj) { DCHECK_GT(obj->InternalFieldCount(), StreamReq::kStreamReqField); - obj->SetAlignedPointerInInternalField(StreamReq::kSlot, nullptr); - obj->SetAlignedPointerInInternalField(StreamReq::kStreamReqField, nullptr); + obj->SetAlignedPointerInInternalField( + StreamReq::kSlot, nullptr, EmbedderDataTag::kDefault); + obj->SetAlignedPointerInInternalField( + StreamReq::kStreamReqField, nullptr, EmbedderDataTag::kDefault); } } // namespace node diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 0821d07b5cde7c..2101a208917e8e 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -127,8 +127,8 @@ void UDPWrapBase::set_listener(UDPListener* listener) { UDPWrapBase* UDPWrapBase::FromObject(Local obj) { CHECK_GT(obj->InternalFieldCount(), UDPWrapBase::kUDPWrapBaseField); - return static_cast( - obj->GetAlignedPointerFromInternalField(UDPWrapBase::kUDPWrapBaseField)); + return static_cast(obj->GetAlignedPointerFromInternalField( + UDPWrapBase::kUDPWrapBaseField, EmbedderDataTag::kDefault)); } void UDPWrapBase::AddMethods(Environment* env, Local t) { @@ -147,8 +147,9 @@ UDPWrap::UDPWrap(Environment* env, Local object) object, reinterpret_cast(&handle_), AsyncWrap::PROVIDER_UDPWRAP) { - object->SetAlignedPointerInInternalField( - UDPWrapBase::kUDPWrapBaseField, static_cast(this)); + object->SetAlignedPointerInInternalField(UDPWrapBase::kUDPWrapBaseField, + static_cast(this), + EmbedderDataTag::kDefault); int r = uv_udp_init(env->event_loop(), &handle_); CHECK_EQ(r, 0); // can't fail anyway