src: use the internal field to determine if an object is a BaseObject

Instead of storing the function template of BaseObject for checking
if an object is BaseObject by calling HasInstance, simply checks
the first internal field of the object, which is always set in the
BaseObject constructor. This is simpler and faster
(there is now no need to iterate over the inheritance for the check).

PR-URL: https://github.com/nodejs/node/pull/47217
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
This commit is contained in:
Joyee Cheung 2023-04-06 02:24:48 +02:00 committed by GitHub
parent d1eaeecc8b
commit 5c86f223ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 27 additions and 79 deletions

View file

@ -342,7 +342,6 @@ Local<FunctionTemplate> AsyncWrap::GetConstructorTemplate(
tmpl = NewFunctionTemplate(isolate, nullptr);
tmpl->SetClassName(
FIXED_ONE_BYTE_STRING(isolate_data->isolate(), "AsyncWrap"));
tmpl->Inherit(BaseObject::GetConstructorTemplate(isolate_data));
SetProtoMethod(isolate, tmpl, "getAsyncId", AsyncWrap::GetAsyncId);
SetProtoMethod(isolate, tmpl, "asyncReset", AsyncWrap::AsyncReset);
SetProtoMethod(

View file

@ -38,12 +38,6 @@ BaseObject::BaseObject(Environment* env, v8::Local<v8::Object> object)
// while allowing to create a BaseObject in a vm context.
}
// static
v8::Local<v8::FunctionTemplate> BaseObject::GetConstructorTemplate(
Environment* env) {
return BaseObject::GetConstructorTemplate(env->isolate_data());
}
void BaseObject::Detach() {
CHECK_GT(pointer_data()->strong_ptr_count, 0);
pointer_data()->is_detached = true;
@ -76,14 +70,23 @@ Realm* BaseObject::realm() const {
return realm_;
}
void BaseObject::TagNodeObject(v8::Local<v8::Object> object) {
bool BaseObject::IsBaseObject(v8::Local<v8::Object> obj) {
if (obj->InternalFieldCount() < BaseObject::kInternalFieldCount) {
return false;
}
void* ptr =
obj->GetAlignedPointerFromInternalField(BaseObject::kEmbedderType);
return ptr == &kNodeEmbedderId;
}
void BaseObject::TagBaseObject(v8::Local<v8::Object> object) {
DCHECK_GE(object->InternalFieldCount(), BaseObject::kInternalFieldCount);
object->SetAlignedPointerInInternalField(BaseObject::kEmbedderType,
&kNodeEmbedderId);
}
void BaseObject::SetInternalFields(v8::Local<v8::Object> object, void* slot) {
TagNodeObject(object);
TagBaseObject(object);
object->SetAlignedPointerInInternalField(BaseObject::kSlot, slot);
}

View file

@ -89,7 +89,6 @@ Local<FunctionTemplate> BaseObject::MakeLazilyInitializedJSTemplate(
IsolateData* isolate_data) {
Local<FunctionTemplate> t = NewFunctionTemplate(
isolate_data->isolate(), LazilyInitializedJSTemplateConstructor);
t->Inherit(BaseObject::GetConstructorTemplate(isolate_data));
t->InstanceTemplate()->SetInternalFieldCount(BaseObject::kInternalFieldCount);
return t;
}
@ -145,18 +144,6 @@ bool BaseObject::IsRootNode() const {
return !persistent_handle_.IsWeak();
}
Local<FunctionTemplate> BaseObject::GetConstructorTemplate(
IsolateData* isolate_data) {
Local<FunctionTemplate> tmpl = isolate_data->base_object_ctor_template();
if (tmpl.IsEmpty()) {
tmpl = NewFunctionTemplate(isolate_data->isolate(), nullptr);
tmpl->SetClassName(
FIXED_ONE_BYTE_STRING(isolate_data->isolate(), "BaseObject"));
isolate_data->set_base_object_ctor_template(tmpl);
}
return tmpl;
}
bool BaseObject::IsNotIndicativeOfMemoryLeakAtExit() const {
return IsWeakOrDetached();
}

View file

@ -76,7 +76,8 @@ class BaseObject : public MemoryRetainer {
// e.g. when the JS object used `MakeLazilyInitializedJSTemplate`.
static inline void SetInternalFields(v8::Local<v8::Object> object,
void* slot);
static inline void TagNodeObject(v8::Local<v8::Object> object);
static inline bool IsBaseObject(v8::Local<v8::Object> object);
static inline void TagBaseObject(v8::Local<v8::Object> object);
static void LazilyInitializedJSTemplateConstructor(
const v8::FunctionCallbackInfo<v8::Value>& args);
static inline BaseObject* FromJSObject(v8::Local<v8::Value> object);

View file

@ -277,9 +277,7 @@ void CipherBase::Initialize(Environment* env, Local<Object> target) {
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
t->InstanceTemplate()->SetInternalFieldCount(
CipherBase::kInternalFieldCount);
t->Inherit(BaseObject::GetConstructorTemplate(env));
t->InstanceTemplate()->SetInternalFieldCount(CipherBase::kInternalFieldCount);
SetProtoMethod(isolate, t, "init", Init);
SetProtoMethod(isolate, t, "initiv", InitIv);

View file

@ -268,7 +268,6 @@ Local<FunctionTemplate> SecureContext::GetConstructorTemplate(
tmpl = NewFunctionTemplate(isolate, New);
tmpl->InstanceTemplate()->SetInternalFieldCount(
SecureContext::kInternalFieldCount);
tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SecureContext"));
SetProtoMethod(isolate, tmpl, "init", Init);

View file

@ -69,7 +69,6 @@ void DiffieHellman::Initialize(Environment* env, Local<Object> target) {
t->InstanceTemplate()->SetInternalFieldCount(
DiffieHellman::kInternalFieldCount);
t->Inherit(BaseObject::GetConstructorTemplate(env));
SetProtoMethod(isolate, t, "generateKeys", GenerateKeys);
SetProtoMethod(isolate, t, "computeSecret", ComputeSecret);

View file

@ -66,7 +66,6 @@ void ECDH::Initialize(Environment* env, Local<Object> target) {
Local<Context> context = env->context();
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
t->Inherit(BaseObject::GetConstructorTemplate(env));
t->InstanceTemplate()->SetInternalFieldCount(ECDH::kInternalFieldCount);

View file

@ -57,9 +57,7 @@ void Hash::Initialize(Environment* env, Local<Object> target) {
Local<Context> context = env->context();
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
t->InstanceTemplate()->SetInternalFieldCount(
Hash::kInternalFieldCount);
t->Inherit(BaseObject::GetConstructorTemplate(env));
t->InstanceTemplate()->SetInternalFieldCount(Hash::kInternalFieldCount);
SetProtoMethod(isolate, t, "update", HashUpdate);
SetProtoMethod(isolate, t, "digest", HashDigest);

View file

@ -41,9 +41,7 @@ void Hmac::Initialize(Environment* env, Local<Object> target) {
Isolate* isolate = env->isolate();
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
t->InstanceTemplate()->SetInternalFieldCount(
Hmac::kInternalFieldCount);
t->Inherit(BaseObject::GetConstructorTemplate(env));
t->InstanceTemplate()->SetInternalFieldCount(Hmac::kInternalFieldCount);
SetProtoMethod(isolate, t, "init", HmacInit);
SetProtoMethod(isolate, t, "update", HmacUpdate);

View file

@ -901,7 +901,6 @@ v8::Local<v8::Function> KeyObjectHandle::Initialize(Environment* env) {
templ = NewFunctionTemplate(isolate, New);
templ->InstanceTemplate()->SetInternalFieldCount(
KeyObjectHandle::kInternalFieldCount);
templ->Inherit(BaseObject::GetConstructorTemplate(env));
SetProtoMethod(isolate, templ, "init", Init);
SetProtoMethodNoSideEffect(
@ -1342,7 +1341,6 @@ void NativeKeyObject::CreateNativeKeyObjectClass(
NewFunctionTemplate(isolate, NativeKeyObject::New);
t->InstanceTemplate()->SetInternalFieldCount(
KeyObjectHandle::kInternalFieldCount);
t->Inherit(BaseObject::GetConstructorTemplate(env));
Local<Value> ctor;
if (!t->GetFunction(env->context()).ToLocal(&ctor))

View file

@ -329,9 +329,7 @@ void Sign::Initialize(Environment* env, Local<Object> target) {
Isolate* isolate = env->isolate();
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
t->InstanceTemplate()->SetInternalFieldCount(
SignBase::kInternalFieldCount);
t->Inherit(BaseObject::GetConstructorTemplate(env));
t->InstanceTemplate()->SetInternalFieldCount(SignBase::kInternalFieldCount);
SetProtoMethod(isolate, t, "init", SignInit);
SetProtoMethod(isolate, t, "update", SignUpdate);
@ -459,9 +457,7 @@ void Verify::Initialize(Environment* env, Local<Object> target) {
Isolate* isolate = env->isolate();
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
t->InstanceTemplate()->SetInternalFieldCount(
SignBase::kInternalFieldCount);
t->Inherit(BaseObject::GetConstructorTemplate(env));
t->InstanceTemplate()->SetInternalFieldCount(SignBase::kInternalFieldCount);
SetProtoMethod(isolate, t, "init", VerifyInit);
SetProtoMethod(isolate, t, "update", VerifyUpdate);

View file

@ -59,7 +59,6 @@ Local<FunctionTemplate> X509Certificate::GetConstructorTemplate(
tmpl = NewFunctionTemplate(isolate, nullptr);
tmpl->InstanceTemplate()->SetInternalFieldCount(
BaseObject::kInternalFieldCount);
tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
tmpl->SetClassName(
FIXED_ONE_BYTE_STRING(env->isolate(), "X509Certificate"));
SetProtoMethod(isolate, tmpl, "subject", Subject);

View file

@ -480,7 +480,6 @@ void IsolateData::CreateProperties() {
Local<FunctionTemplate> templ = FunctionTemplate::New(isolate());
templ->InstanceTemplate()->SetInternalFieldCount(
BaseObject::kInternalFieldCount);
templ->Inherit(BaseObject::GetConstructorTemplate(this));
set_binding_data_ctor_template(templ);
binding::CreateInternalBindingTemplates(this);

View file

@ -330,7 +330,6 @@
#define PER_ISOLATE_TEMPLATE_PROPERTIES(V) \
V(async_wrap_ctor_template, v8::FunctionTemplate) \
V(async_wrap_object_ctor_template, v8::FunctionTemplate) \
V(base_object_ctor_template, v8::FunctionTemplate) \
V(binding_data_ctor_template, v8::FunctionTemplate) \
V(blob_constructor_template, v8::FunctionTemplate) \
V(blob_reader_constructor_template, v8::FunctionTemplate) \

View file

@ -288,7 +288,6 @@ Local<FunctionTemplate> HistogramBase::GetConstructorTemplate(
tmpl = NewFunctionTemplate(isolate, New);
Local<String> classname = FIXED_ONE_BYTE_STRING(isolate, "Histogram");
tmpl->SetClassName(classname);
tmpl->Inherit(BaseObject::GetConstructorTemplate(isolate_data));
tmpl->InstanceTemplate()->SetInternalFieldCount(
HistogramBase::kInternalFieldCount);

View file

@ -768,7 +768,6 @@ void ModuleWrap::Initialize(Local<Object> target,
Local<FunctionTemplate> tpl = NewFunctionTemplate(isolate, New);
tpl->InstanceTemplate()->SetInternalFieldCount(
ModuleWrap::kInternalFieldCount);
tpl->Inherit(BaseObject::GetConstructorTemplate(env));
SetProtoMethod(isolate, tpl, "link", Link);
SetProtoMethod(isolate, tpl, "instantiate", Instantiate);

View file

@ -565,7 +565,6 @@ void CreateInternalBindingTemplates(IsolateData* isolate_data) {
FunctionTemplate::New(isolate_data->isolate()); \
templ->InstanceTemplate()->SetInternalFieldCount( \
BaseObject::kInternalFieldCount); \
templ->Inherit(BaseObject::GetConstructorTemplate(isolate_data)); \
_register_isolate_##modname(isolate_data, templ); \
isolate_data->set_##modname##_binding(templ); \
} while (0);

View file

@ -131,7 +131,6 @@ Local<FunctionTemplate> Blob::GetConstructorTemplate(Environment* env) {
tmpl = NewFunctionTemplate(isolate, nullptr);
tmpl->InstanceTemplate()->SetInternalFieldCount(
BaseObject::kInternalFieldCount);
tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
tmpl->SetClassName(
FIXED_ONE_BYTE_STRING(env->isolate(), "Blob"));
SetProtoMethod(isolate, tmpl, "getReader", GetReader);
@ -281,7 +280,6 @@ Local<FunctionTemplate> Blob::Reader::GetConstructorTemplate(Environment* env) {
tmpl = NewFunctionTemplate(isolate, nullptr);
tmpl->InstanceTemplate()->SetInternalFieldCount(
BaseObject::kInternalFieldCount);
tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "BlobReader"));
SetProtoMethod(env->isolate(), tmpl, "pull", Pull);
env->set_blob_reader_constructor_template(tmpl);

View file

@ -875,7 +875,6 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,
// ConverterObject
{
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, nullptr);
t->Inherit(BaseObject::GetConstructorTemplate(isolate_data));
t->InstanceTemplate()->SetInternalFieldCount(
ConverterObject::kInternalFieldCount);
Local<String> converter_string =

View file

@ -301,7 +301,7 @@ class SerializerDelegate : public ValueSerializer::Delegate {
}
Maybe<bool> WriteHostObject(Isolate* isolate, Local<Object> object) override {
if (env_->base_object_ctor_template()->HasInstance(object)) {
if (BaseObject::IsBaseObject(object)) {
return WriteHostObject(
BaseObjectPtr<BaseObject> { Unwrap<BaseObject>(object) });
}
@ -490,7 +490,8 @@ Maybe<bool> Message::Serialize(Environment* env,
array_buffers.push_back(ab);
serializer.TransferArrayBuffer(id, ab);
continue;
} else if (env->base_object_ctor_template()->HasInstance(entry)) {
} else if (entry->IsObject() &&
BaseObject::IsBaseObject(entry.As<Object>())) {
// Check if the source MessagePort is being transferred.
if (!source_port.IsEmpty() && entry == source_port) {
ThrowDataCloneException(
@ -1257,7 +1258,7 @@ JSTransferable::NestedTransferables() const {
Local<Value> value;
if (!list->Get(context, i).ToLocal(&value))
return Nothing<BaseObjectList>();
if (env()->base_object_ctor_template()->HasInstance(value))
if (value->IsObject() && BaseObject::IsBaseObject(value.As<Object>()))
ret.emplace_back(Unwrap<BaseObject>(value));
}
return Just(ret);
@ -1309,9 +1310,10 @@ BaseObjectPtr<BaseObject> JSTransferable::Data::Deserialize(
Local<Value> ret;
CHECK(!env->messaging_deserialize_create_object().IsEmpty());
if (!env->messaging_deserialize_create_object()->Call(
context, Null(env->isolate()), 1, &info).ToLocal(&ret) ||
!env->base_object_ctor_template()->HasInstance(ret)) {
if (!env->messaging_deserialize_create_object()
->Call(context, Null(env->isolate()), 1, &info)
.ToLocal(&ret) ||
!ret->IsObject() || !BaseObject::IsBaseObject(ret.As<Object>())) {
return {};
}
@ -1492,7 +1494,6 @@ static void InitMessaging(Local<Object> target,
{
Local<FunctionTemplate> t =
NewFunctionTemplate(isolate, JSTransferable::New);
t->Inherit(BaseObject::GetConstructorTemplate(env));
t->InstanceTemplate()->SetInternalFieldCount(
JSTransferable::kInternalFieldCount);
SetConstructorFunction(context, target, "JSTransferable", t);

View file

@ -462,7 +462,6 @@ void Initialize(Local<Object> target,
ser->InstanceTemplate()->SetInternalFieldCount(
SerializerContext::kInternalFieldCount);
ser->Inherit(BaseObject::GetConstructorTemplate(env));
SetProtoMethod(isolate, ser, "writeHeader", SerializerContext::WriteHeader);
SetProtoMethod(isolate, ser, "writeValue", SerializerContext::WriteValue);
@ -490,7 +489,6 @@ void Initialize(Local<Object> target,
des->InstanceTemplate()->SetInternalFieldCount(
DeserializerContext::kInternalFieldCount);
des->Inherit(BaseObject::GetConstructorTemplate(env));
SetProtoMethod(isolate, des, "readHeader", DeserializerContext::ReadHeader);
SetProtoMethod(isolate, des, "readValue", DeserializerContext::ReadValue);

View file

@ -1367,18 +1367,7 @@ StartupData SerializeNodeContextInternalFields(Local<Object> holder,
// (most importantly, BaseObject::kSlot).
// For Node.js this design is enough for all the native binding that are
// serializable.
if (index != BaseObject::kEmbedderType) {
return StartupData{nullptr, 0};
}
void* type_ptr = holder->GetAlignedPointerFromInternalField(index);
if (type_ptr == nullptr) {
return StartupData{nullptr, 0};
}
uint16_t type = *(static_cast<uint16_t*>(type_ptr));
per_process::Debug(DebugCategory::MKSNAPSHOT, "type = 0x%x\n", type);
if (type != kNodeEmbedderId) {
if (index != BaseObject::kEmbedderType || !BaseObject::IsBaseObject(holder)) {
return StartupData{nullptr, 0};
}

View file

@ -701,7 +701,6 @@ Local<FunctionTemplate> SocketAddressBlockListWrap::GetConstructorTemplate(
Isolate* isolate = env->isolate();
tmpl = NewFunctionTemplate(isolate, SocketAddressBlockListWrap::New);
tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "BlockList"));
tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
tmpl->InstanceTemplate()->SetInternalFieldCount(kInternalFieldCount);
SetProtoMethod(isolate, tmpl, "addAddress", AddAddress);
SetProtoMethod(isolate, tmpl, "addRange", AddRange);
@ -757,7 +756,6 @@ Local<FunctionTemplate> SocketAddressBase::GetConstructorTemplate(
tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SocketAddress"));
tmpl->InstanceTemplate()->SetInternalFieldCount(
SocketAddressBase::kInternalFieldCount);
tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
SetProtoMethod(isolate, tmpl, "detail", Detail);
SetProtoMethod(isolate, tmpl, "legacyDetail", LegacyDetail);
SetProtoMethodNoSideEffect(isolate, tmpl, "flowlabel", GetFlowLabel);

View file

@ -137,7 +137,6 @@ void NodeCategorySet::Initialize(Local<Object> target,
NewFunctionTemplate(isolate, NodeCategorySet::New);
category_set->InstanceTemplate()->SetInternalFieldCount(
NodeCategorySet::kInternalFieldCount);
category_set->Inherit(BaseObject::GetConstructorTemplate(env));
SetProtoMethod(isolate, category_set, "enable", NodeCategorySet::Enable);
SetProtoMethod(isolate, category_set, "disable", NodeCategorySet::Disable);

View file

@ -464,7 +464,6 @@ void Initialize(Local<Object> target,
NewFunctionTemplate(isolate, WeakReference::New);
weak_ref->InstanceTemplate()->SetInternalFieldCount(
WeakReference::kInternalFieldCount);
weak_ref->Inherit(BaseObject::GetConstructorTemplate(env));
SetProtoMethod(isolate, weak_ref, "get", WeakReference::Get);
SetProtoMethod(isolate, weak_ref, "incRef", WeakReference::IncRef);
SetProtoMethod(isolate, weak_ref, "decRef", WeakReference::DecRef);

View file

@ -1271,7 +1271,6 @@ static void InitializePreview1(Local<Object> target,
Local<FunctionTemplate> tmpl = NewFunctionTemplate(isolate, WASI::New);
tmpl->InstanceTemplate()->SetInternalFieldCount(WASI::kInternalFieldCount);
tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
#define V(F, name) \
SetFunction<decltype(&WASI::F), WASI::F>(WASI::F, env, name, tmpl);

View file

@ -28,7 +28,6 @@ Local<Function> WasmStreamingObject::Initialize(Environment* env) {
Isolate* isolate = env->isolate();
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
t->Inherit(BaseObject::GetConstructorTemplate(env));
t->InstanceTemplate()->SetInternalFieldCount(
WasmStreamingObject::kInternalFieldCount);