Skip to content

Commit 39d25ce

Browse files
committed
src: use V8-owned CppHeap
As V8 is moving towards built-in CppHeap creation, change the management so that the automatic CppHeap creation on Node.js's end is also enforced at Isolate creation time. 1. If embedder uses NewIsolate(), either they use IsolateSettings::cpp_heap to specify a CppHeap that will be owned by V8, or if it's not configured, Node.js will create a CppHeap that will be owned by V8. 2. If the embedder uses SetIsolateUpForNode(), IsolateSettings::cpp_heap will be ignored (as V8 has deprecated attaching CppHeap post-isolate-creation). The embedders need to ensure that the v8::Isolate has a CppHeap attached while it's still used by Node.js, preferably using v8::CreateParams. See https://issues.chromium.org/issues/42203693 for details. In future version of V8, this CppHeap will be created by V8 if not provided, and we can remove our own "if no CppHeap provided, create one" code in NewIsolate().
1 parent d4eb77c commit 39d25ce

File tree

9 files changed

+42
-48
lines changed

9 files changed

+42
-48
lines changed

src/api/embed_helpers.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,11 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
232232
impl_->platform->AddIsolateFinishedCallback(isolate, [](void* data) {
233233
*static_cast<bool*>(data) = true;
234234
}, &platform_finished);
235-
impl_->platform->UnregisterIsolate(isolate);
236235
if (impl_->snapshot_creator.has_value())
237236
impl_->snapshot_creator.reset();
238237
else
239238
isolate->Dispose();
239+
impl_->platform->UnregisterIsolate(isolate);
240240

241241
// Wait until the platform has cleaned up all relevant resources.
242242
while (!platform_finished)

src/api/environment.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@
1919
#if HAVE_INSPECTOR
2020
#include "inspector/worker_inspector.h" // ParentInspectorHandle
2121
#endif
22+
#include "v8-cppgc.h"
2223

2324
namespace node {
2425
using errors::TryCatchScope;
2526
using v8::Array;
2627
using v8::Boolean;
2728
using v8::Context;
29+
using v8::CppHeap;
30+
using v8::CppHeapCreateParams;
2831
using v8::EscapableHandleScope;
2932
using v8::Function;
3033
using v8::FunctionCallbackInfo;
@@ -354,6 +357,14 @@ Isolate* NewIsolate(Isolate::CreateParams* params,
354357
// so that the isolate can access the platform during initialization.
355358
platform->RegisterIsolate(isolate, event_loop);
356359

360+
// Ensure that there is always a CppHeap.
361+
if (settings.cpp_heap == nullptr) {
362+
params->cpp_heap =
363+
CppHeap::Create(platform, CppHeapCreateParams{{}}).release();
364+
} else {
365+
params->cpp_heap = settings.cpp_heap;
366+
}
367+
357368
SetIsolateCreateParamsForNode(params);
358369
Isolate::Initialize(isolate, *params);
359370

src/env.cc

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ using errors::TryCatchScope;
4141
using v8::Array;
4242
using v8::Boolean;
4343
using v8::Context;
44-
using v8::CppHeap;
45-
using v8::CppHeapCreateParams;
4644
using v8::EmbedderGraph;
4745
using v8::EscapableHandleScope;
4846
using v8::Function;
@@ -546,19 +544,11 @@ IsolateData::IsolateData(Isolate* isolate,
546544
snapshot_data_(snapshot_data) {
547545
options_.reset(
548546
new PerIsolateOptions(*(per_process::cli_options->per_isolate)));
549-
v8::CppHeap* cpp_heap = isolate->GetCppHeap();
550547

551548
uint16_t cppgc_id = kDefaultCppGCEmebdderID;
552549
// We do not care about overflow since we just want this to be different
553550
// from the cppgc id.
554551
uint16_t non_cppgc_id = cppgc_id + 1;
555-
if (cpp_heap == nullptr) {
556-
cpp_heap_ = CppHeap::Create(platform, v8::CppHeapCreateParams{{}});
557-
// TODO(joyeecheung): pass it into v8::Isolate::CreateParams and let V8
558-
// own it when we can keep the isolate registered/task runner discoverable
559-
// during isolate disposal.
560-
isolate->AttachCppHeap(cpp_heap_.get());
561-
}
562552

563553
{
564554
// GC could still be run after the IsolateData is destroyed, so we store
@@ -582,13 +572,7 @@ IsolateData::IsolateData(Isolate* isolate,
582572
}
583573
}
584574

585-
IsolateData::~IsolateData() {
586-
if (cpp_heap_ != nullptr) {
587-
// The CppHeap must be detached before being terminated.
588-
isolate_->DetachCppHeap();
589-
cpp_heap_->Terminate();
590-
}
591-
}
575+
IsolateData::~IsolateData() {}
592576

593577
// Deprecated API, embedders should use v8::Object::Wrap() directly instead.
594578
void SetCppgcReference(Isolate* isolate,

src/env.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,6 @@
6767
#include <unordered_set>
6868
#include <vector>
6969

70-
namespace v8 {
71-
class CppHeap;
72-
}
73-
7470
namespace node {
7571

7672
namespace shadow_realm {
@@ -249,7 +245,6 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer {
249245
const SnapshotData* snapshot_data_;
250246
std::optional<SnapshotConfig> snapshot_config_;
251247

252-
std::unique_ptr<v8::CppHeap> cpp_heap_;
253248
std::shared_ptr<PerIsolateOptions> options_;
254249
worker::Worker* worker_context_ = nullptr;
255250
PerIsolateWrapperData* wrapper_data_;

src/node.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ class NODE_EXTERN MultiIsolatePlatform : public v8::Platform {
450450

451451
// This function may only be called once per `Isolate`, and discard any
452452
// pending delayed tasks scheduled for that isolate.
453-
// This needs to be called right before calling `Isolate::Dispose()`.
453+
// This needs to be called right after calling `Isolate::Dispose()`.
454454
virtual void UnregisterIsolate(v8::Isolate* isolate) = 0;
455455

456456
// The platform should call the passed function once all state associated
@@ -491,6 +491,21 @@ struct IsolateSettings {
491491
allow_wasm_code_generation_callback = nullptr;
492492
v8::ModifyCodeGenerationFromStringsCallback2
493493
modify_code_generation_from_strings_callback = nullptr;
494+
495+
// When the settings is passed to NewIsolate():
496+
// - If cpp_heap is not nullptr, this CppHeap will be used to create
497+
// the isolate and its ownership will be passed to V8.
498+
// - If this is nullptr, Node.js will create a CppHeap that will be
499+
// owned by V8.
500+
//
501+
// When the settings is passed to SetIsolateUpForNode():
502+
// cpp_heap will be ignored. Embedders must ensure that the
503+
// v8::Isolate has a CppHeap attached while it's still used by
504+
// Node.js, for example using v8::CreateParams.
505+
//
506+
// See https://issues.chromium.org/issues/42203693. In future version
507+
// of V8, this CppHeap will be created by V8 if not provided.
508+
v8::CppHeap* cpp_heap = nullptr;
494509
};
495510

496511
// Represents a startup snapshot blob, e.g. created by passing
@@ -1548,10 +1563,9 @@ void RegisterSignalHandler(int signal,
15481563
bool reset_handler = false);
15491564
#endif // _WIN32
15501565

1551-
// This is kept as a compatibility layer for addons to wrap cppgc-managed
1552-
// objects on Node.js versions without v8::Object::Wrap(). Addons created to
1553-
// work with only Node.js versions with v8::Object::Wrap() should use that
1554-
// instead.
1566+
// This is kept as a compatibility layer for addons to wrap cppgc-managed objects
1567+
// on Node.js versions without v8::Object::Wrap(). Addons created to work with
1568+
// only Node.js versions with v8::Object::Wrap() should use that instead.
15551569
NODE_DEPRECATED("Use v8::Object::Wrap()",
15561570
NODE_EXTERN void SetCppgcReference(v8::Isolate* isolate,
15571571
v8::Local<v8::Object> object,

src/node_main_instance.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,10 @@ NodeMainInstance::~NodeMainInstance() {
8181
// This should only be done on a main instance that owns its isolate.
8282
// IsolateData must be freed before UnregisterIsolate() is called.
8383
isolate_data_.reset();
84+
isolate_->Dispose();
8485
platform_->UnregisterIsolate(isolate_);
86+
// TODO(joyeecheung): split Isolate::Free() here?
8587
}
86-
isolate_->Dispose();
8788
}
8889

8990
ExitCode NodeMainInstance::Run() {

src/node_worker.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ class WorkerThreadData {
234234
// new Isolate at the same address can successfully be registered with
235235
// the platform.
236236
// (Refs: https://github.com/nodejs/node/issues/30846)
237-
w_->platform_->UnregisterIsolate(isolate);
238237
isolate->Dispose();
238+
w_->platform_->UnregisterIsolate(isolate);
239239

240240
// Wait until the platform has cleaned up all relevant resources.
241241
while (!platform_finished) {

src/util.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,8 +724,8 @@ RAIIIsolateWithoutEntering::RAIIIsolateWithoutEntering(const SnapshotData* data)
724724
}
725725

726726
RAIIIsolateWithoutEntering::~RAIIIsolateWithoutEntering() {
727-
per_process::v8_platform.Platform()->UnregisterIsolate(isolate_);
728727
isolate_->Dispose();
728+
per_process::v8_platform.Platform()->UnregisterIsolate(isolate_);
729729
}
730730

731731
RAIIIsolate::RAIIIsolate(const SnapshotData* data)

test/cctest/test_cppgc.cc

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,12 @@ int CppGCed::kDestructCount = 0;
4646
int CppGCed::kTraceCount = 0;
4747

4848
TEST_F(NodeZeroIsolateTestFixture, ExistingCppHeapTest) {
49-
v8::Isolate* isolate =
50-
node::NewIsolate(allocator.get(), &current_loop, platform.get());
51-
52-
// Create and attach the CppHeap before we set up the IsolateData so that
53-
// it recognizes the existing heap.
54-
std::unique_ptr<v8::CppHeap> cpp_heap =
55-
v8::CppHeap::Create(platform.get(), v8::CppHeapCreateParams{{}});
56-
57-
// TODO(joyeecheung): pass it into v8::Isolate::CreateParams and let V8
58-
// own it when we can keep the isolate registered/task runner discoverable
59-
// during isolate disposal.
60-
isolate->AttachCppHeap(cpp_heap.get());
49+
node::IsolateSettings settings;
50+
settings.cpp_heap =
51+
v8::CppHeap::Create(platform.get(), v8::CppHeapCreateParams{{}})
52+
.release();
53+
v8::Isolate* isolate = node::NewIsolate(
54+
allocator.get(), &current_loop, platform.get(), nullptr, settings);
6155

6256
// Try creating Context + IsolateData + Environment.
6357
{
@@ -100,11 +94,6 @@ TEST_F(NodeZeroIsolateTestFixture, ExistingCppHeapTest) {
10094
}
10195

10296
platform->DrainTasks(isolate);
103-
104-
// Cleanup.
105-
isolate->DetachCppHeap();
106-
cpp_heap->Terminate();
107-
platform->DrainTasks(isolate);
10897
}
10998

11099
platform->UnregisterIsolate(isolate);

0 commit comments

Comments
 (0)