Skip to content

Commit 3b0617d

Browse files
joyeecheungnodejs-github-bot
authored andcommitted
vm: migrate ContextifyScript to cppgc
This patch migrates ContextifyScript to cppgc-based memory management using CppgcMixin. PR-URL: #52295 Refs: #40786 Refs: https://docs.google.com/document/d/1ny2Qz_EsUnXGKJRGxoA-FXIE2xpLgaMAN6jD7eAkqFQ/edit Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
1 parent 849db10 commit 3b0617d

5 files changed

+60
-54
lines changed

benchmark/vm/compile-script-in-isolate-cache.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
const common = require('../common.js');
66
const fs = require('fs');
77
const vm = require('vm');
8-
const fixtures = require('../../test/common/fixtures.js');
9-
const scriptPath = fixtures.path('snapshot', 'typescript.js');
8+
const path = require('path');
109

1110
const bench = common.createBenchmark(main, {
1211
type: ['with-dynamic-import-callback', 'without-dynamic-import-callback'],
13-
n: [100],
12+
filename: ['test/fixtures/snapshot/typescript.js', 'test/fixtures/syntax/good_syntax.js'],
13+
n: [1000],
1414
});
1515

16-
const scriptSource = fs.readFileSync(scriptPath, 'utf8');
17-
18-
function main({ n, type }) {
16+
function main({ n, type, filename }) {
17+
const scriptPath = path.resolve(__dirname, '..', '..', filename);
18+
const scriptSource = fs.readFileSync(scriptPath, 'utf8');
1919
let script;
2020
bench.start();
2121
const options = {};

src/node_contextify.cc

+30-18
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "node_contextify.h"
2323

2424
#include "base_object-inl.h"
25+
#include "cppgc/allocation.h"
2526
#include "memory_tracker-inl.h"
2627
#include "module_wrap.h"
2728
#include "node_context_data.h"
@@ -960,6 +961,12 @@ void ContextifyScript::RegisterExternalReferences(
960961
registry->Register(RunInContext);
961962
}
962963

964+
ContextifyScript* ContextifyScript::New(Environment* env,
965+
Local<Object> object) {
966+
return cppgc::MakeGarbageCollected<ContextifyScript>(
967+
env->isolate()->GetCppHeap()->GetAllocationHandle(), env, object);
968+
}
969+
963970
void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
964971
Environment* env = Environment::GetCurrent(args);
965972
Isolate* isolate = env->isolate();
@@ -1010,8 +1017,7 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
10101017
id_symbol = args[7].As<Symbol>();
10111018
}
10121019

1013-
ContextifyScript* contextify_script =
1014-
new ContextifyScript(env, args.This());
1020+
ContextifyScript* contextify_script = New(env, args.This());
10151021

10161022
if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
10171023
TRACING_CATEGORY_NODE2(vm, script)) != 0) {
@@ -1069,9 +1075,7 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
10691075
return;
10701076
}
10711077

1072-
contextify_script->script_.Reset(isolate, v8_script);
1073-
contextify_script->script_.SetWeak();
1074-
contextify_script->object()->SetInternalField(kUnboundScriptSlot, v8_script);
1078+
contextify_script->set_unbound_script(v8_script);
10751079

10761080
std::unique_ptr<ScriptCompiler::CachedData> new_cached_data;
10771081
if (produce_cached_data) {
@@ -1174,11 +1178,9 @@ void ContextifyScript::CreateCachedData(
11741178
const FunctionCallbackInfo<Value>& args) {
11751179
Environment* env = Environment::GetCurrent(args);
11761180
ContextifyScript* wrapped_script;
1177-
ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.This());
1178-
Local<UnboundScript> unbound_script =
1179-
PersistentToLocal::Default(env->isolate(), wrapped_script->script_);
1181+
ASSIGN_OR_RETURN_UNWRAP_CPPGC(&wrapped_script, args.This());
11801182
std::unique_ptr<ScriptCompiler::CachedData> cached_data(
1181-
ScriptCompiler::CreateCodeCache(unbound_script));
1183+
ScriptCompiler::CreateCodeCache(wrapped_script->unbound_script()));
11821184
if (!cached_data) {
11831185
args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked());
11841186
} else {
@@ -1192,9 +1194,8 @@ void ContextifyScript::CreateCachedData(
11921194

11931195
void ContextifyScript::RunInContext(const FunctionCallbackInfo<Value>& args) {
11941196
Environment* env = Environment::GetCurrent(args);
1195-
11961197
ContextifyScript* wrapped_script;
1197-
ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.This());
1198+
ASSIGN_OR_RETURN_UNWRAP_CPPGC(&wrapped_script, args.This());
11981199

11991200
CHECK_EQ(args.Length(), 5);
12001201
CHECK(args[0]->IsObject() || args[0]->IsNull());
@@ -1264,10 +1265,9 @@ bool ContextifyScript::EvalMachine(Local<Context> context,
12641265

12651266
TryCatchScope try_catch(env);
12661267
ContextifyScript* wrapped_script;
1267-
ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.This(), false);
1268-
Local<UnboundScript> unbound_script =
1269-
PersistentToLocal::Default(env->isolate(), wrapped_script->script_);
1270-
Local<Script> script = unbound_script->BindToCurrentContext();
1268+
ASSIGN_OR_RETURN_UNWRAP_CPPGC(&wrapped_script, args.This(), false);
1269+
Local<Script> script =
1270+
wrapped_script->unbound_script()->BindToCurrentContext();
12711271

12721272
#if HAVE_INSPECTOR
12731273
if (break_on_first_line) {
@@ -1349,9 +1349,21 @@ bool ContextifyScript::EvalMachine(Local<Context> context,
13491349
return true;
13501350
}
13511351

1352-
ContextifyScript::ContextifyScript(Environment* env, Local<Object> object)
1353-
: BaseObject(env, object) {
1354-
MakeWeak();
1352+
Local<UnboundScript> ContextifyScript::unbound_script() const {
1353+
return script_.Get(env()->isolate());
1354+
}
1355+
1356+
void ContextifyScript::set_unbound_script(Local<UnboundScript> script) {
1357+
script_.Reset(env()->isolate(), script);
1358+
}
1359+
1360+
void ContextifyScript::Trace(cppgc::Visitor* visitor) const {
1361+
CppgcMixin::Trace(visitor);
1362+
visitor->Trace(script_);
1363+
}
1364+
1365+
ContextifyScript::ContextifyScript(Environment* env, Local<Object> object) {
1366+
CppgcMixin::Wrap(this, env, object);
13551367
}
13561368

13571369
ContextifyScript::~ContextifyScript() {}

src/node_contextify.h

+9-10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
55

66
#include "base_object-inl.h"
7+
#include "cppgc_helpers.h"
78
#include "node_context_data.h"
89
#include "node_errors.h"
910

@@ -143,23 +144,21 @@ class ContextifyContext : public BaseObject {
143144
std::unique_ptr<v8::MicrotaskQueue> microtask_queue_;
144145
};
145146

146-
class ContextifyScript : public BaseObject {
147+
class ContextifyScript final : CPPGC_MIXIN(ContextifyScript) {
147148
public:
148-
enum InternalFields {
149-
kUnboundScriptSlot = BaseObject::kInternalFieldCount,
150-
kInternalFieldCount
151-
};
152-
153-
SET_NO_MEMORY_INFO()
154-
SET_MEMORY_INFO_NAME(ContextifyScript)
155-
SET_SELF_SIZE(ContextifyScript)
149+
SET_CPPGC_NAME(ContextifyScript)
150+
void Trace(cppgc::Visitor* visitor) const final;
156151

157152
ContextifyScript(Environment* env, v8::Local<v8::Object> object);
158153
~ContextifyScript() override;
159154

155+
v8::Local<v8::UnboundScript> unbound_script() const;
156+
void set_unbound_script(v8::Local<v8::UnboundScript>);
157+
160158
static void CreatePerIsolateProperties(IsolateData* isolate_data,
161159
v8::Local<v8::ObjectTemplate> target);
162160
static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
161+
static ContextifyScript* New(Environment* env, v8::Local<v8::Object> object);
163162
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
164163
static bool InstanceOf(Environment* env, const v8::Local<v8::Value>& args);
165164
static void CreateCachedData(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -174,7 +173,7 @@ class ContextifyScript : public BaseObject {
174173
const v8::FunctionCallbackInfo<v8::Value>& args);
175174

176175
private:
177-
v8::Global<v8::UnboundScript> script_;
176+
v8::TracedReference<v8::UnboundScript> script_;
178177
};
179178

180179
v8::Maybe<bool> StoreCodeCacheResult(

test/pummel/test-heapdump-env.js

+2-20
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,12 @@
22
'use strict';
33

44
// This tests that Environment is tracked in heap snapshots.
5+
// Tests for BaseObject and cppgc-managed objects are done in other
6+
// test-heapdump-*.js files.
57

68
require('../common');
79
const { validateSnapshotNodes } = require('../common/heap');
810

9-
// This is just using ContextifyScript as an example here, it can be replaced
10-
// with any BaseObject that we can easily instantiate here and register in
11-
// cleanup hooks.
12-
// These can all be changed to reflect the status of how these objects
13-
// are captured in the snapshot.
14-
const context = require('vm').createScript('const foo = 123');
15-
1611
validateSnapshotNodes('Node / Environment', [{
1712
children: [
1813
{ node_name: 'Node / CleanupQueue', edge_name: 'cleanup_queue' },
@@ -21,21 +16,8 @@ validateSnapshotNodes('Node / Environment', [{
2116
],
2217
}]);
2318

24-
validateSnapshotNodes('Node / CleanupQueue', [
25-
// The first one is the cleanup_queue of the Environment.
26-
{},
27-
// The second one is the cleanup_queue of the principal realm.
28-
{
29-
children: [
30-
{ node_name: 'Node / ContextifyScript' },
31-
],
32-
},
33-
]);
34-
3519
validateSnapshotNodes('Node / PrincipalRealm', [{
3620
children: [
3721
{ node_name: 'process', edge_name: 'process_object' },
3822
],
3923
}]);
40-
41-
console.log(context); // Make sure it's not GC'ed
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
require('../common');
3+
const { findByRetainingPath } = require('../common/heap');
4+
const source = 'const foo = 123';
5+
const script = require('vm').createScript(source);
6+
7+
findByRetainingPath('Node / ContextifyScript', [
8+
{ node_name: '(shared function info)' }, // This is the UnboundScript referenced by ContextifyScript.
9+
{ edge_name: 'script' },
10+
{ edge_name: 'source', node_type: 'string', node_name: source },
11+
]);
12+
13+
console.log(script); // Keep the script alive.

0 commit comments

Comments
 (0)