Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite483cda

Browse files
legendecasjoyeecheung
authored andcommitted
src: create BaseObject with node::Realm
BaseObject is a wrapper around JS objects. These objects should becreated in a node::Realm and destroyed when their associated realm iscleaning up.PR-URL:#44348Refs:#42528Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
1 parent67054e3 commite483cda

15 files changed

+381
-288
lines changed

‎node.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@
477477
'src/api/hooks.cc',
478478
'src/api/utils.cc',
479479
'src/async_wrap.cc',
480+
'src/base_object.cc',
480481
'src/cares_wrap.cc',
481482
'src/cleanup_queue.cc',
482483
'src/connect_wrap.cc',

‎src/api/embed_helpers.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Maybe<int> SpinEventLoop(Environment* env) {
6868
env->set_snapshot_serialize_callback(Local<Function>());
6969

7070
env->PrintInfoForSnapshotIfDebug();
71-
env->VerifyNoStrongBaseObjects();
71+
env->ForEachRealm([](Realm* realm) { realm->VerifyNoStrongBaseObjects(); });
7272
returnEmitProcessExit(env);
7373
}
7474

‎src/base_object-inl.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232

3333
namespacenode {
3434

35+
BaseObject::BaseObject(Environment* env, v8::Local<v8::Object> object)
36+
: BaseObject(env->principal_realm(), object) {}
37+
3538
// static
3639
v8::Local<v8::FunctionTemplate>BaseObject::GetConstructorTemplate(
3740
Environment* env) {
@@ -63,7 +66,11 @@ v8::Local<v8::Object> BaseObject::object(v8::Isolate* isolate) const {
6366
}
6467

6568
Environment*BaseObject::env()const {
66-
return env_;
69+
return realm_->env();
70+
}
71+
72+
Realm*BaseObject::realm()const {
73+
return realm_;
6774
}
6875

6976
BaseObject*BaseObject::FromJSObject(v8::Local<v8::Value> value) {

‎src/base_object.cc

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#include"base_object.h"
2+
#include"env-inl.h"
3+
#include"node_realm-inl.h"
4+
5+
namespacenode {
6+
7+
using v8::FunctionCallbackInfo;
8+
using v8::FunctionTemplate;
9+
using v8::HandleScope;
10+
using v8::Local;
11+
using v8::Object;
12+
using v8::Value;
13+
using v8::WeakCallbackInfo;
14+
using v8::WeakCallbackType;
15+
16+
BaseObject::BaseObject(Realm* realm, Local<Object> object)
17+
: persistent_handle_(realm->isolate(), object), realm_(realm) {
18+
CHECK_EQ(false, object.IsEmpty());
19+
CHECK_GE(object->InternalFieldCount(), BaseObject::kInternalFieldCount);
20+
object->SetAlignedPointerInInternalField(BaseObject::kEmbedderType,
21+
&kNodeEmbedderId);
22+
object->SetAlignedPointerInInternalField(BaseObject::kSlot,
23+
static_cast<void*>(this));
24+
realm->AddCleanupHook(DeleteMe,static_cast<void*>(this));
25+
realm->modify_base_object_count(1);
26+
}
27+
28+
BaseObject::~BaseObject() {
29+
realm()->modify_base_object_count(-1);
30+
realm()->RemoveCleanupHook(DeleteMe,static_cast<void*>(this));
31+
32+
if (UNLIKELY(has_pointer_data())) {
33+
PointerData* metadata =pointer_data();
34+
CHECK_EQ(metadata->strong_ptr_count,0);
35+
metadata->self =nullptr;
36+
if (metadata->weak_ptr_count ==0)delete metadata;
37+
}
38+
39+
if (persistent_handle_.IsEmpty()) {
40+
// This most likely happened because the weak callback below cleared it.
41+
return;
42+
}
43+
44+
{
45+
HandleScopehandle_scope(realm()->isolate());
46+
object()->SetAlignedPointerInInternalField(BaseObject::kSlot,nullptr);
47+
}
48+
}
49+
50+
voidBaseObject::MakeWeak() {
51+
if (has_pointer_data()) {
52+
pointer_data()->wants_weak_jsobj =true;
53+
if (pointer_data()->strong_ptr_count >0)return;
54+
}
55+
56+
persistent_handle_.SetWeak(
57+
this,
58+
[](const WeakCallbackInfo<BaseObject>& data) {
59+
BaseObject* obj = data.GetParameter();
60+
// Clear the persistent handle so that ~BaseObject() doesn't attempt
61+
// to mess with internal fields, since the JS object may have
62+
// transitioned into an invalid state.
63+
// Refs: https://github.com/nodejs/node/issues/18897
64+
obj->persistent_handle_.Reset();
65+
CHECK_IMPLIES(obj->has_pointer_data(),
66+
obj->pointer_data()->strong_ptr_count ==0);
67+
obj->OnGCCollect();
68+
},
69+
WeakCallbackType::kParameter);
70+
}
71+
72+
// This just has to be different from the Chromium ones:
73+
// https://source.chromium.org/chromium/chromium/src/+/main:gin/public/gin_embedders.h;l=18-23;drc=5a758a97032f0b656c3c36a3497560762495501a
74+
// Otherwise, when Node is loaded in an isolate which uses cppgc, cppgc will
75+
// misinterpret the data stored in the embedder fields and try to garbage
76+
// collect them.
77+
uint16_tkNodeEmbedderId =0x90de;
78+
79+
voidBaseObject::LazilyInitializedJSTemplateConstructor(
80+
const FunctionCallbackInfo<Value>& args) {
81+
DCHECK(args.IsConstructCall());
82+
CHECK_GE(args.This()->InternalFieldCount(), BaseObject::kInternalFieldCount);
83+
args.This()->SetAlignedPointerInInternalField(BaseObject::kEmbedderType,
84+
&kNodeEmbedderId);
85+
args.This()->SetAlignedPointerInInternalField(BaseObject::kSlot,nullptr);
86+
}
87+
88+
Local<FunctionTemplate>BaseObject::MakeLazilyInitializedJSTemplate(
89+
Environment* env) {
90+
Local<FunctionTemplate> t =NewFunctionTemplate(
91+
env->isolate(), LazilyInitializedJSTemplateConstructor);
92+
t->Inherit(BaseObject::GetConstructorTemplate(env));
93+
t->InstanceTemplate()->SetInternalFieldCount(BaseObject::kInternalFieldCount);
94+
return t;
95+
}
96+
97+
BaseObject::PointerData*BaseObject::pointer_data() {
98+
if (!has_pointer_data()) {
99+
PointerData* metadata =newPointerData();
100+
metadata->wants_weak_jsobj = persistent_handle_.IsWeak();
101+
metadata->self =this;
102+
pointer_data_ = metadata;
103+
}
104+
CHECK(has_pointer_data());
105+
return pointer_data_;
106+
}
107+
108+
voidBaseObject::decrease_refcount() {
109+
CHECK(has_pointer_data());
110+
PointerData* metadata =pointer_data();
111+
CHECK_GT(metadata->strong_ptr_count,0);
112+
unsignedint new_refcount = --metadata->strong_ptr_count;
113+
if (new_refcount ==0) {
114+
if (metadata->is_detached) {
115+
OnGCCollect();
116+
}elseif (metadata->wants_weak_jsobj && !persistent_handle_.IsEmpty()) {
117+
MakeWeak();
118+
}
119+
}
120+
}
121+
122+
voidBaseObject::increase_refcount() {
123+
unsignedint prev_refcount =pointer_data()->strong_ptr_count++;
124+
if (prev_refcount ==0 && !persistent_handle_.IsEmpty())
125+
persistent_handle_.ClearWeak();
126+
}
127+
128+
voidBaseObject::DeleteMe(void* data) {
129+
BaseObject* self =static_cast<BaseObject*>(data);
130+
if (self->has_pointer_data() && self->pointer_data()->strong_ptr_count >0) {
131+
return self->Detach();
132+
}
133+
delete self;
134+
}
135+
136+
boolBaseObject::IsDoneInitializing()const {
137+
returntrue;
138+
}
139+
140+
Local<Object>BaseObject::WrappedObject()const {
141+
returnobject();
142+
}
143+
144+
boolBaseObject::IsRootNode()const {
145+
return !persistent_handle_.IsWeak();
146+
}
147+
148+
Local<FunctionTemplate>BaseObject::GetConstructorTemplate(
149+
IsolateData* isolate_data) {
150+
Local<FunctionTemplate> tmpl = isolate_data->base_object_ctor_template();
151+
if (tmpl.IsEmpty()) {
152+
tmpl =NewFunctionTemplate(isolate_data->isolate(),nullptr);
153+
tmpl->SetClassName(
154+
FIXED_ONE_BYTE_STRING(isolate_data->isolate(),"BaseObject"));
155+
isolate_data->set_base_object_ctor_template(tmpl);
156+
}
157+
return tmpl;
158+
}
159+
160+
boolBaseObject::IsNotIndicativeOfMemoryLeakAtExit()const {
161+
returnIsWeakOrDetached();
162+
}
163+
164+
}// namespace node

‎src/base_object.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace node {
3232

3333
classEnvironment;
3434
classIsolateData;
35+
classRealm;
3536
template<typename T,boolkIsWeak>
3637
classBaseObjectPtrImpl;
3738

@@ -47,7 +48,10 @@ class BaseObject : public MemoryRetainer {
4748

4849
// Associates this object with `object`. It uses the 1st internal field for
4950
// that, and in particular aborts if there is no such field.
50-
BaseObject(Environment* env, v8::Local<v8::Object> object);
51+
// This is the designated constructor.
52+
BaseObject(Realm* realm, v8::Local<v8::Object> object);
53+
// Convenient constructor for constructing BaseObject in the principal realm.
54+
inlineBaseObject(Environment* env, v8::Local<v8::Object> object);
5155
~BaseObject()override;
5256

5357
BaseObject() =delete;
@@ -63,6 +67,7 @@ class BaseObject : public MemoryRetainer {
6367
inline v8::Global<v8::Object>&persistent();
6468

6569
inline Environment*env()const;
70+
inline Realm*realm()const;
6671

6772
// Get a BaseObject* pointer, or subclass pointer, for the JS object that
6873
// was also passed to the `BaseObject()` constructor initially.
@@ -93,6 +98,7 @@ class BaseObject : public MemoryRetainer {
9398
// Utility to create a FunctionTemplate with one internal field (used for
9499
// the `BaseObject*` pointer) and a constructor that initializes that field
95100
// to `nullptr`.
101+
// TODO(legendecas): Disentangle template with env.
96102
static v8::Local<v8::FunctionTemplate>MakeLazilyInitializedJSTemplate(
97103
Environment* env);
98104

@@ -215,7 +221,7 @@ class BaseObject : public MemoryRetainer {
215221
voiddecrease_refcount();
216222
voidincrease_refcount();
217223

218-
Environment* env_;
224+
Realm* realm_;
219225
PointerData* pointer_data_ =nullptr;
220226
};
221227

‎src/env-inl.h

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,12 @@ inline IsolateData* Environment::isolate_data() const {
745745
return isolate_data_;
746746
}
747747

748+
template<typename T>
749+
inlinevoidEnvironment::ForEachRealm(T&& iterator)const {
750+
// TODO(legendecas): iterate over more realms bound to the environment.
751+
iterator(principal_realm());
752+
}
753+
748754
inlinevoidEnvironment::ThrowError(constchar* errmsg) {
749755
ThrowError(v8::Exception::Error, errmsg);
750756
}
@@ -789,27 +795,6 @@ void Environment::RemoveCleanupHook(CleanupQueue::Callback fn, void* arg) {
789795
cleanup_queue_.Remove(fn, arg);
790796
}
791797

792-
template<typename T>
793-
voidEnvironment::ForEachBaseObject(T&& iterator) {
794-
cleanup_queue_.ForEachBaseObject(std::forward<T>(iterator));
795-
}
796-
797-
voidEnvironment::modify_base_object_count(int64_t delta) {
798-
base_object_count_ += delta;
799-
}
800-
801-
int64_tEnvironment::base_object_count()const {
802-
return base_object_count_;
803-
}
804-
805-
inlinevoidEnvironment::set_base_object_created_by_bootstrap(int64_t count) {
806-
base_object_created_by_bootstrap_ = base_object_count_;
807-
}
808-
809-
int64_tEnvironment::base_object_created_after_bootstrap()const {
810-
return base_object_count_ - base_object_created_by_bootstrap_;
811-
}
812-
813798
voidEnvironment::set_main_utf16(std::unique_ptr<v8::String::Value> str) {
814799
CHECK(!main_utf16_);
815800
main_utf16_ =std::move(str);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp