Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: revamp internal field count tracking #31960

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 12 additions & 10 deletions src/async_wrap.cc
Expand Up @@ -176,6 +176,10 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) {

class PromiseWrap : public AsyncWrap {
public:
enum InternalFields {
kIsChainedPromiseField = AsyncWrap::kInternalFieldCount,
kInternalFieldCount
};
PromiseWrap(Environment* env, Local<Object> object, bool silent)
: AsyncWrap(env, object, PROVIDER_PROMISE, kInvalidAsyncId, silent) {
MakeWeak();
Expand All @@ -185,9 +189,6 @@ class PromiseWrap : public AsyncWrap {
SET_MEMORY_INFO_NAME(PromiseWrap)
SET_SELF_SIZE(PromiseWrap)

static constexpr int kIsChainedPromiseField = 1;
static constexpr int kInternalFieldCount = 2;

static PromiseWrap* New(Environment* env,
Local<Promise> promise,
PromiseWrap* parent_wrap,
Expand All @@ -214,15 +215,16 @@ PromiseWrap* PromiseWrap::New(Environment* env,
void PromiseWrap::getIsChainedPromise(Local<String> property,
const PropertyCallbackInfo<Value>& info) {
info.GetReturnValue().Set(
info.Holder()->GetInternalField(kIsChainedPromiseField));
info.Holder()->GetInternalField(PromiseWrap::kIsChainedPromiseField));
}

static PromiseWrap* extractPromiseWrap(Local<Promise> promise) {
Local<Value> resource_object_value = promise->GetInternalField(0);
if (resource_object_value->IsObject()) {
return Unwrap<PromiseWrap>(resource_object_value.As<Object>());
}
return nullptr;
// This check is imperfect. If the internal field is set, it should
// be an object. If it's not, we just ignore it. Ideally v8 would
// have had GetInternalField returning a MaybeLocal but this works
// for now.
Local<Value> obj = promise->GetInternalField(0);
return obj->IsObject() ? Unwrap<PromiseWrap>(obj.As<Object>()) : nullptr;
}

static void PromiseHook(PromiseHookType type, Local<Promise> promise,
Expand Down Expand Up @@ -560,7 +562,7 @@ void AsyncWrap::Initialize(Local<Object> target,
function_template->SetClassName(class_name);
function_template->Inherit(AsyncWrap::GetConstructorTemplate(env));
auto instance_template = function_template->InstanceTemplate();
instance_template->SetInternalFieldCount(1);
instance_template->SetInternalFieldCount(AsyncWrap::kInternalFieldCount);
auto function =
function_template->GetFunction(env->context()).ToLocalChecked();
target->Set(env->context(), class_name, function).Check();
Expand Down
14 changes: 9 additions & 5 deletions src/base_object-inl.h
Expand Up @@ -43,7 +43,9 @@ BaseObject::BaseObject(Environment* env, v8::Local<v8::Object> object)
: persistent_handle_(env->isolate(), object), env_(env) {
CHECK_EQ(false, object.IsEmpty());
CHECK_GT(object->InternalFieldCount(), 0);
object->SetAlignedPointerInInternalField(0, static_cast<void*>(this));
object->SetAlignedPointerInInternalField(
BaseObject::kSlot,
static_cast<void*>(this));
env->AddCleanupHook(DeleteMe, static_cast<void*>(this));
env->modify_base_object_count(1);
}
Expand All @@ -67,7 +69,7 @@ BaseObject::~BaseObject() {

{
v8::HandleScope handle_scope(env()->isolate());
object()->SetAlignedPointerInInternalField(0, nullptr);
object()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr);
}
}

Expand Down Expand Up @@ -100,7 +102,8 @@ Environment* BaseObject::env() const {

BaseObject* BaseObject::FromJSObject(v8::Local<v8::Object> obj) {
CHECK_GT(obj->InternalFieldCount(), 0);
return static_cast<BaseObject*>(obj->GetAlignedPointerFromInternalField(0));
return static_cast<BaseObject*>(
obj->GetAlignedPointerFromInternalField(BaseObject::kSlot));
}


Expand Down Expand Up @@ -148,11 +151,12 @@ BaseObject::MakeLazilyInitializedJSTemplate(Environment* env) {
auto constructor = [](const v8::FunctionCallbackInfo<v8::Value>& args) {
DCHECK(args.IsConstructCall());
DCHECK_GT(args.This()->InternalFieldCount(), 0);
args.This()->SetAlignedPointerInInternalField(0, nullptr);
args.This()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr);
};

v8::Local<v8::FunctionTemplate> t = env->NewFunctionTemplate(constructor);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(
BaseObject::kInternalFieldCount);
return t;
}

Expand Down
2 changes: 2 additions & 0 deletions src/base_object.h
Expand Up @@ -36,6 +36,8 @@ class BaseObjectPtrImpl;

class BaseObject : public MemoryRetainer {
public:
enum InternalFields { kSlot, kInternalFieldCount };

// Associates this object with `object`. It uses the 0th internal field for
// that, and in particular aborts if there is no such field.
inline BaseObject(Environment* env, v8::Local<v8::Object> object);
Expand Down
3 changes: 2 additions & 1 deletion src/cares_wrap.cc
Expand Up @@ -2223,7 +2223,8 @@ void Initialize(Local<Object> target,

Local<FunctionTemplate> channel_wrap =
env->NewFunctionTemplate(ChannelWrap::New);
channel_wrap->InstanceTemplate()->SetInternalFieldCount(1);
channel_wrap->InstanceTemplate()->SetInternalFieldCount(
ChannelWrap::kInternalFieldCount);
channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));

env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
Expand Down
3 changes: 2 additions & 1 deletion src/fs_event_wrap.cc
Expand Up @@ -97,7 +97,8 @@ void FSEventWrap::Initialize(Local<Object> target,

auto fsevent_string = FIXED_ONE_BYTE_STRING(env->isolate(), "FSEvent");
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(
FSEventWrap::kInternalFieldCount);
t->SetClassName(fsevent_string);

t->Inherit(AsyncWrap::GetConstructorTemplate(env));
Expand Down
2 changes: 1 addition & 1 deletion src/heap_utils.cc
Expand Up @@ -341,7 +341,7 @@ BaseObjectPtr<AsyncWrap> CreateHeapSnapshotStream(
Local<FunctionTemplate> os = FunctionTemplate::New(env->isolate());
os->Inherit(AsyncWrap::GetConstructorTemplate(env));
Local<ObjectTemplate> ost = os->InstanceTemplate();
ost->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount);
ost->SetInternalFieldCount(StreamBase::kInternalFieldCount);
os->SetClassName(
FIXED_ONE_BYTE_STRING(env->isolate(), "HeapSnapshotStream"));
StreamBase::AddMethods(env, os);
Expand Down
3 changes: 2 additions & 1 deletion src/inspector_js_api.cc
Expand Up @@ -105,7 +105,8 @@ class JSBindingsConnection : public AsyncWrap {
Local<String> class_name = ConnectionType::GetClassName(env);
Local<FunctionTemplate> tmpl =
env->NewFunctionTemplate(JSBindingsConnection::New);
tmpl->InstanceTemplate()->SetInternalFieldCount(1);
tmpl->InstanceTemplate()->SetInternalFieldCount(
JSBindingsConnection::kInternalFieldCount);
tmpl->SetClassName(class_name);
tmpl->Inherit(AsyncWrap::GetConstructorTemplate(env));
env->SetProtoMethod(tmpl, "dispatch", JSBindingsConnection::Dispatch);
Expand Down
2 changes: 1 addition & 1 deletion src/js_stream.cc
Expand Up @@ -204,7 +204,7 @@ void JSStream::Initialize(Local<Object> target,
FIXED_ONE_BYTE_STRING(env->isolate(), "JSStream");
t->SetClassName(jsStreamString);
t->InstanceTemplate()
->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount);
->SetInternalFieldCount(StreamBase::kInternalFieldCount);
t->Inherit(AsyncWrap::GetConstructorTemplate(env));

env->SetProtoMethod(t, "finishWrite", Finish<WriteWrap>);
Expand Down
3 changes: 2 additions & 1 deletion src/module_wrap.cc
Expand Up @@ -1639,7 +1639,8 @@ void ModuleWrap::Initialize(Local<Object> target,

Local<FunctionTemplate> tpl = env->NewFunctionTemplate(New);
tpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "ModuleWrap"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
tpl->InstanceTemplate()->SetInternalFieldCount(
ModuleWrap::kInternalFieldCount);

env->SetProtoMethod(tpl, "link", Link);
env->SetProtoMethod(tpl, "instantiate", Instantiate);
Expand Down
14 changes: 9 additions & 5 deletions src/node_contextify.cc
Expand Up @@ -142,7 +142,7 @@ MaybeLocal<Object> ContextifyContext::CreateDataWrapper(Environment* env) {
return MaybeLocal<Object>();
}

wrapper->SetAlignedPointerInInternalField(0, this);
wrapper->SetAlignedPointerInInternalField(ContextifyContext::kSlot, this);
return wrapper;
}

Expand Down Expand Up @@ -229,7 +229,8 @@ MaybeLocal<Context> ContextifyContext::CreateV8Context(
void ContextifyContext::Init(Environment* env, Local<Object> target) {
Local<FunctionTemplate> function_template =
FunctionTemplate::New(env->isolate());
function_template->InstanceTemplate()->SetInternalFieldCount(1);
function_template->InstanceTemplate()->SetInternalFieldCount(
ContextifyContext::kInternalFieldCount);
env->set_script_data_constructor_function(
function_template->GetFunction(env->context()).ToLocalChecked());

Expand Down Expand Up @@ -328,7 +329,8 @@ template <typename T>
ContextifyContext* ContextifyContext::Get(const PropertyCallbackInfo<T>& args) {
Local<Value> data = args.Data();
return static_cast<ContextifyContext*>(
data.As<Object>()->GetAlignedPointerFromInternalField(0));
data.As<Object>()->GetAlignedPointerFromInternalField(
ContextifyContext::kSlot));
}

// static
Expand Down Expand Up @@ -625,7 +627,8 @@ void ContextifyScript::Init(Environment* env, Local<Object> target) {
FIXED_ONE_BYTE_STRING(env->isolate(), "ContextifyScript");

Local<FunctionTemplate> script_tmpl = env->NewFunctionTemplate(New);
script_tmpl->InstanceTemplate()->SetInternalFieldCount(1);
script_tmpl->InstanceTemplate()->SetInternalFieldCount(
ContextifyScript::kInternalFieldCount);
script_tmpl->SetClassName(class_name);
env->SetProtoMethod(script_tmpl, "createCachedData", CreateCachedData);
env->SetProtoMethod(script_tmpl, "runInContext", RunInContext);
Expand Down Expand Up @@ -1220,7 +1223,8 @@ void Initialize(Local<Object> target,
{
Local<FunctionTemplate> tpl = FunctionTemplate::New(env->isolate());
tpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "CompiledFnEntry"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
tpl->InstanceTemplate()->SetInternalFieldCount(
CompiledFnEntry::kInternalFieldCount);

env->set_compiled_fn_entry_template(tpl->InstanceTemplate());
}
Expand Down
1 change: 1 addition & 0 deletions src/node_contextify.h
Expand Up @@ -19,6 +19,7 @@ struct ContextOptions {

class ContextifyContext {
public:
enum InternalFields { kSlot, kInternalFieldCount };
ContextifyContext(Environment* env,
v8::Local<v8::Object> sandbox_obj,
const ContextOptions& options);
Expand Down
26 changes: 17 additions & 9 deletions src/node_crypto.cc
Expand Up @@ -464,7 +464,8 @@ static T* MallocOpenSSL(size_t count) {

void SecureContext::Initialize(Environment* env, Local<Object> target) {
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(
SecureContext::kInternalFieldCount);
Local<String> secureContextString =
FIXED_ONE_BYTE_STRING(env->isolate(), "SecureContext");
t->SetClassName(secureContextString);
Expand Down Expand Up @@ -3807,7 +3808,8 @@ EVP_PKEY* ManagedEVPPKey::get() const {

Local<Function> KeyObject::Initialize(Environment* env, Local<Object> target) {
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(
KeyObject::kInternalFieldCount);

env->SetProtoMethod(t, "init", Init);
env->SetProtoMethodNoSideEffect(t, "getSymmetricKeySize",
Expand Down Expand Up @@ -4040,7 +4042,8 @@ CipherBase::CipherBase(Environment* env,
void CipherBase::Initialize(Environment* env, Local<Object> target) {
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);

t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(
CipherBase::kInternalFieldCount);

env->SetProtoMethod(t, "init", Init);
env->SetProtoMethod(t, "initiv", InitIv);
Expand Down Expand Up @@ -4667,7 +4670,8 @@ Hmac::Hmac(Environment* env, v8::Local<v8::Object> wrap)
void Hmac::Initialize(Environment* env, Local<Object> target) {
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);

t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(
Hmac::kInternalFieldCount);

env->SetProtoMethod(t, "init", HmacInit);
env->SetProtoMethod(t, "update", HmacUpdate);
Expand Down Expand Up @@ -4793,7 +4797,8 @@ Hash::Hash(Environment* env, v8::Local<v8::Object> wrap)
void Hash::Initialize(Environment* env, Local<Object> target) {
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);

t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(
Hash::kInternalFieldCount);

env->SetProtoMethod(t, "update", HashUpdate);
env->SetProtoMethod(t, "digest", HashDigest);
Expand Down Expand Up @@ -5065,7 +5070,8 @@ Sign::Sign(Environment* env, v8::Local<v8::Object> wrap) : SignBase(env, wrap) {
void Sign::Initialize(Environment* env, Local<Object> target) {
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);

t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(
SignBase::kInternalFieldCount);

env->SetProtoMethod(t, "init", SignInit);
env->SetProtoMethod(t, "update", SignUpdate);
Expand Down Expand Up @@ -5389,7 +5395,8 @@ Verify::Verify(Environment* env, v8::Local<v8::Object> wrap) :
void Verify::Initialize(Environment* env, Local<Object> target) {
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);

t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(
SignBase::kInternalFieldCount);

env->SetProtoMethod(t, "init", VerifyInit);
env->SetProtoMethod(t, "update", VerifyUpdate);
Expand Down Expand Up @@ -5701,7 +5708,8 @@ void DiffieHellman::Initialize(Environment* env, Local<Object> target) {
const PropertyAttribute attributes =
static_cast<PropertyAttribute>(ReadOnly | DontDelete);

t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(
DiffieHellman::kInternalFieldCount);

env->SetProtoMethod(t, "generateKeys", GenerateKeys);
env->SetProtoMethod(t, "computeSecret", ComputeSecret);
Expand Down Expand Up @@ -6048,7 +6056,7 @@ void ECDH::Initialize(Environment* env, Local<Object> target) {

Local<FunctionTemplate> t = env->NewFunctionTemplate(New);

t->InstanceTemplate()->SetInternalFieldCount(1);
t->InstanceTemplate()->SetInternalFieldCount(ECDH::kInternalFieldCount);

env->SetProtoMethod(t, "generateKeys", GenerateKeys);
env->SetProtoMethod(t, "computeSecret", ComputeSecret);
Expand Down
2 changes: 1 addition & 1 deletion src/node_dir.cc
Expand Up @@ -358,7 +358,7 @@ void Initialize(Local<Object> target,
env->SetProtoMethod(dir, "read", DirHandle::Read);
env->SetProtoMethod(dir, "close", DirHandle::Close);
Local<ObjectTemplate> dirt = dir->InstanceTemplate();
dirt->SetInternalFieldCount(DirHandle::kDirHandleFieldCount);
dirt->SetInternalFieldCount(DirHandle::kInternalFieldCount);
Local<String> handleString =
FIXED_ONE_BYTE_STRING(isolate, "DirHandle");
dir->SetClassName(handleString);
Expand Down
2 changes: 0 additions & 2 deletions src/node_dir.h
Expand Up @@ -12,8 +12,6 @@ namespace fs_dir {
// Needed to propagate `uv_dir_t`.
class DirHandle : public AsyncWrap {
public:
static constexpr int kDirHandleFieldCount = 1;

static DirHandle* New(Environment* env, uv_dir_t* dir);
~DirHandle() override;

Expand Down
12 changes: 7 additions & 5 deletions src/node_file.cc
Expand Up @@ -2290,7 +2290,8 @@ void Initialize(Local<Object> target,

// Create FunctionTemplate for FSReqCallback
Local<FunctionTemplate> fst = env->NewFunctionTemplate(NewFSReqCallback);
fst->InstanceTemplate()->SetInternalFieldCount(1);
fst->InstanceTemplate()->SetInternalFieldCount(
FSReqBase::kInternalFieldCount);
fst->Inherit(AsyncWrap::GetConstructorTemplate(env));
Local<String> wrapString =
FIXED_ONE_BYTE_STRING(isolate, "FSReqCallback");
Expand All @@ -2303,7 +2304,8 @@ void Initialize(Local<Object> target,
// Create FunctionTemplate for FileHandleReadWrap. There’s no need
// to do anything in the constructor, so we only store the instance template.
Local<FunctionTemplate> fh_rw = FunctionTemplate::New(isolate);
fh_rw->InstanceTemplate()->SetInternalFieldCount(1);
fh_rw->InstanceTemplate()->SetInternalFieldCount(
FSReqBase::kInternalFieldCount);
fh_rw->Inherit(AsyncWrap::GetConstructorTemplate(env));
Local<String> fhWrapString =
FIXED_ONE_BYTE_STRING(isolate, "FileHandleReqWrap");
Expand All @@ -2318,7 +2320,7 @@ void Initialize(Local<Object> target,
FIXED_ONE_BYTE_STRING(isolate, "FSReqPromise");
fpt->SetClassName(promiseString);
Local<ObjectTemplate> fpo = fpt->InstanceTemplate();
fpo->SetInternalFieldCount(1);
fpo->SetInternalFieldCount(FSReqBase::kInternalFieldCount);
env->set_fsreqpromise_constructor_template(fpo);

// Create FunctionTemplate for FileHandle
Expand All @@ -2327,7 +2329,7 @@ void Initialize(Local<Object> target,
env->SetProtoMethod(fd, "close", FileHandle::Close);
env->SetProtoMethod(fd, "releaseFD", FileHandle::ReleaseFD);
Local<ObjectTemplate> fdt = fd->InstanceTemplate();
fdt->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount);
fdt->SetInternalFieldCount(StreamBase::kInternalFieldCount);
Local<String> handleString =
FIXED_ONE_BYTE_STRING(isolate, "FileHandle");
fd->SetClassName(handleString);
Expand All @@ -2344,7 +2346,7 @@ void Initialize(Local<Object> target,
"FileHandleCloseReq"));
fdclose->Inherit(AsyncWrap::GetConstructorTemplate(env));
Local<ObjectTemplate> fdcloset = fdclose->InstanceTemplate();
fdcloset->SetInternalFieldCount(1);
fdcloset->SetInternalFieldCount(FSReqBase::kInternalFieldCount);
env->set_fdclose_constructor_template(fdcloset);

Local<Symbol> use_promises_symbol =
Expand Down