Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e04b976
deps: update V8 to 13.6.233.8
targos Apr 29, 2025
038c3f2
build: reset embedder string to "-node.0"
targos Apr 29, 2025
045507c
src: update NODE_MODULE_VERSION to 137
targos Apr 29, 2025
2b27576
deps: patch V8 to avoid duplicated zlib symbol
targos Sep 16, 2023
d6837f1
deps: fix FP16 bitcasts.h
StefanStojanovic May 28, 2024
8a9baf6
deps: define V8_PRESERVE_MOST as no-op on Windows
StefanStojanovic Dec 16, 2024
1f9cf1d
deps: remove problematic comment from v8-internal
targos Mar 19, 2025
3deb96e
deps: patch V8 for illumos
danmcd Apr 18, 2025
ee7ad80
deps: use std::map in MSVC STL for EphemeronRememberedSet
joyeecheung Apr 28, 2025
567d78c
deps: disable V8 concurrent sparkplug compilation
targos Apr 6, 2023
ca3fffb
deps: always define V8_EXPORT_PRIVATE as no-op
targos Sep 21, 2022
eabc4fb
deps: patch V8 to support compilation with MSVC
StefanStojanovic Apr 21, 2024
36ee451
deps: V8: backport 954187bb1b87
joyeecheung Apr 24, 2025
840fbbb
build: remove support for s390 32-bit
richardlau Sep 18, 2024
eb26ca3
build: enable shared RO heap with ptr compression
targos Sep 21, 2024
c08834a
tools: update V8 gypfiles for 13.1
targos Sep 25, 2024
0c4f35c
tools: update V8 gypfiles for 13.2
targos Oct 28, 2024
d7d2b59
build,src,tools: adapt build config for V8 13.3
targos Dec 19, 2024
9afc83f
tools: update V8 gypfiles for 13.4
targos Jan 20, 2025
f552e07
build: add `/bigobj` to compile V8 on Windows
targos Feb 5, 2025
b247c98
src: replace uses of FastApiTypedArray
targos Feb 8, 2025
38be4b8
Revert "test: disable fast API call count checks"
targos Jan 31, 2025
3e314b4
test: update test-linux-perf-logger
targos Feb 4, 2025
34b439a
test: adapt assert tests to stack trace changes
targos Dec 20, 2024
9297f92
test: handle explicit resource management globals
targos Dec 21, 2024
50db68a
deps: remove deps/simdutf
targos Jan 29, 2025
e7504c7
tools: update license-builder and LICENSE for V8 deps
targos Jan 29, 2025
6b6add6
src: use `v8::ExternalMemoryAccounter`
targos Feb 15, 2025
9c9f865
src,test: add V8 API to test the hash seed
targos Feb 20, 2025
07cdd3b
build: pass `-fPIC` to linker as well for shared builds
targos Apr 2, 2025
adc9675
build: fix V8 TLS config for shared lib builds
targos Apr 3, 2025
773a8c6
tools: update V8 gypfiles for 13.5
targos Feb 25, 2025
2e71fb7
tools: update V8 gypfiles for 13.6
targos Apr 5, 2025
8a3e8f3
build: update list of installed cppgc headers
targos Apr 6, 2025
6f16029
test: fix test-fs-write for V8 13.6
targos Apr 9, 2025
1780962
src: use V8-owned CppHeap
joyeecheung May 29, 2024
05054d2
src: use non-deprecated Utf8LengthV2() method
anonrig Apr 17, 2025
c21b0e7
src: use non-deprecated WriteUtf8V2() method
anonrig Apr 17, 2025
fb09a88
src,test: unregister the isolate after disposal and before freeing
joyeecheung Apr 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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().
  • Loading branch information
joyeecheung authored and targos committed May 1, 2025
commit 17809622ccdbbd567e9b371aeaf7258fb494073e
12 changes: 8 additions & 4 deletions src/api/embed_helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -234,14 +234,18 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
}

bool platform_finished = false;
impl_->platform->AddIsolateFinishedCallback(isolate, [](void* data) {
*static_cast<bool*>(data) = true;
}, &platform_finished);
impl_->platform->UnregisterIsolate(isolate);
impl_->platform->AddIsolateFinishedCallback(
isolate,
[](void* data) {
bool* ptr = static_cast<bool*>(data);
*ptr = true;
},
&platform_finished);
if (impl_->snapshot_creator.has_value()) {
impl_->snapshot_creator.reset();
}
isolate->Dispose();
impl_->platform->UnregisterIsolate(isolate);

// Wait until the platform has cleaned up all relevant resources.
while (!platform_finished)
Expand Down
11 changes: 11 additions & 0 deletions src/api/environment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@
#if HAVE_INSPECTOR
#include "inspector/worker_inspector.h" // ParentInspectorHandle
#endif
#include "v8-cppgc.h"

namespace node {
using errors::TryCatchScope;
using v8::Array;
using v8::Boolean;
using v8::Context;
using v8::CppHeap;
using v8::CppHeapCreateParams;
using v8::EscapableHandleScope;
using v8::Function;
using v8::FunctionCallbackInfo;
Expand Down Expand Up @@ -326,6 +329,14 @@ Isolate* NewIsolate(Isolate::CreateParams* params,
// so that the isolate can access the platform during initialization.
platform->RegisterIsolate(isolate, event_loop);

// Ensure that there is always a CppHeap.
if (settings.cpp_heap == nullptr) {
params->cpp_heap =
CppHeap::Create(platform, CppHeapCreateParams{{}}).release();
} else {
params->cpp_heap = settings.cpp_heap;
}

SetIsolateCreateParamsForNode(params);
Isolate::Initialize(isolate, *params);

Expand Down
20 changes: 1 addition & 19 deletions src/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ using v8::BackingStore;
using v8::BackingStoreInitializationMode;
using v8::Boolean;
using v8::Context;
using v8::CppHeap;
using v8::CppHeapCreateParams;
using v8::EmbedderGraph;
using v8::EscapableHandleScope;
using v8::ExternalMemoryAccounter;
Expand Down Expand Up @@ -580,19 +578,10 @@ IsolateData::IsolateData(Isolate* isolate,
platform_(platform),
snapshot_data_(snapshot_data),
options_(std::move(options)) {
v8::CppHeap* cpp_heap = isolate->GetCppHeap();

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

{
// GC could still be run after the IsolateData is destroyed, so we store
Expand All @@ -616,14 +605,7 @@ IsolateData::IsolateData(Isolate* isolate,
}
}

IsolateData::~IsolateData() {
if (cpp_heap_ != nullptr) {
v8::Locker locker(isolate_);
// The CppHeap must be detached before being terminated.
isolate_->DetachCppHeap();
cpp_heap_->Terminate();
}
}
IsolateData::~IsolateData() {}

// Deprecated API, embedders should use v8::Object::Wrap() directly instead.
void SetCppgcReference(Isolate* isolate,
Expand Down
5 changes: 0 additions & 5 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,6 @@
#include <unordered_set>
#include <vector>

namespace v8 {
class CppHeap;
}

namespace node {

namespace shadow_realm {
Expand Down Expand Up @@ -246,7 +242,6 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer {
const SnapshotData* snapshot_data_;
std::optional<SnapshotConfig> snapshot_config_;

std::unique_ptr<v8::CppHeap> cpp_heap_;
std::shared_ptr<PerIsolateOptions> options_;
worker::Worker* worker_context_ = nullptr;
PerIsolateWrapperData* wrapper_data_;
Expand Down
16 changes: 8 additions & 8 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,14 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,
result->platform_ = per_process::v8_platform.Platform();
}

if (!(flags & ProcessInitializationFlags::kNoInitializeCppgc)) {
v8::PageAllocator* allocator = nullptr;
if (result->platform_ != nullptr) {
allocator = result->platform_->GetPageAllocator();
}
cppgc::InitializeProcess(allocator);
}

if (!(flags & ProcessInitializationFlags::kNoInitializeV8)) {
V8::Initialize();

Expand All @@ -1220,14 +1228,6 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kIgnore);
}

if (!(flags & ProcessInitializationFlags::kNoInitializeCppgc)) {
v8::PageAllocator* allocator = nullptr;
if (result->platform_ != nullptr) {
allocator = result->platform_->GetPageAllocator();
}
cppgc::InitializeProcess(allocator);
}

#if NODE_USE_V8_WASM_TRAP_HANDLER
bool use_wasm_trap_handler =
!per_process::cli_options->disable_wasm_trap_handler;
Expand Down
17 changes: 16 additions & 1 deletion src/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ class NODE_EXTERN MultiIsolatePlatform : public v8::Platform {

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

// The platform should call the passed function once all state associated
Expand Down Expand Up @@ -489,6 +489,21 @@ struct IsolateSettings {
allow_wasm_code_generation_callback = nullptr;
v8::ModifyCodeGenerationFromStringsCallback2
modify_code_generation_from_strings_callback = nullptr;

// When the settings is passed to NewIsolate():
// - If cpp_heap is not nullptr, this CppHeap will be used to create
// the isolate and its ownership will be passed to V8.
// - If this is nullptr, Node.js will create a CppHeap that will be
// owned by V8.
//
// When the settings is passed to SetIsolateUpForNode():
// cpp_heap will be ignored. Embedders must ensure that the
// v8::Isolate has a CppHeap attached while it's still used by
// Node.js, for example using v8::CreateParams.
//
// See https://issues.chromium.org/issues/42203693. In future version
// of V8, this CppHeap will be created by V8 if not provided.
v8::CppHeap* cpp_heap = nullptr;
};

// Represents a startup snapshot blob, e.g. created by passing
Expand Down
3 changes: 2 additions & 1 deletion src/node_contextify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ ContextifyContext* ContextifyContext::New(Local<Context> v8_context,
.ToLocal(&wrapper)) {
return {};
}

DCHECK_NOT_NULL(env->isolate()->GetCppHeap());
result = cppgc::MakeGarbageCollected<ContextifyContext>(
env->isolate()->GetCppHeap()->GetAllocationHandle(),
env,
Expand Down Expand Up @@ -975,6 +975,7 @@ void ContextifyScript::RegisterExternalReferences(

ContextifyScript* ContextifyScript::New(Environment* env,
Local<Object> object) {
DCHECK_NOT_NULL(env->isolate()->GetCppHeap());
return cppgc::MakeGarbageCollected<ContextifyScript>(
env->isolate()->GetCppHeap()->GetAllocationHandle(), env, object);
}
Expand Down
3 changes: 2 additions & 1 deletion src/node_main_instance.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ NodeMainInstance::~NodeMainInstance() {
// This should only be done on a main instance that owns its isolate.
// IsolateData must be freed before UnregisterIsolate() is called.
isolate_data_.reset();
platform_->UnregisterIsolate(isolate_);
}
// TODO(joyeecheung): split Isolate::Free() here?
isolate_->Dispose();
platform_->UnregisterIsolate(isolate_);
}

ExitCode NodeMainInstance::Run() {
Expand Down
8 changes: 7 additions & 1 deletion src/node_worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,14 @@ class WorkerThreadData {
// new Isolate at the same address can successfully be registered with
// the platform.
// (Refs: https://github.com/nodejs/node/issues/30846)
w_->platform_->UnregisterIsolate(isolate);
// TODO(joyeecheung): we reversed the order because the task runner has
// to be available to handle GC tasks posted during isolate disposal.
// If this flakes comes back again, try splitting Isolate::Delete out
// so that the pointer is still available as map key after disposal
// and we delete it after unregistration.
// Refs: https://github.com/nodejs/node/pull/53086#issuecomment-2128056793
isolate->Dispose();
w_->platform_->UnregisterIsolate(isolate);

// Wait until the platform has cleaned up all relevant resources.
while (!platform_finished) {
Expand Down
5 changes: 4 additions & 1 deletion src/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -726,12 +726,15 @@ RAIIIsolateWithoutEntering::RAIIIsolateWithoutEntering(const SnapshotData* data)
SnapshotBuilder::InitializeIsolateParams(data, &params);
}
params.array_buffer_allocator = allocator_.get();
params.cpp_heap = v8::CppHeap::Create(per_process::v8_platform.Platform(),
v8::CppHeapCreateParams{{}})
.release();
Isolate::Initialize(isolate_, params);
}

RAIIIsolateWithoutEntering::~RAIIIsolateWithoutEntering() {
per_process::v8_platform.Platform()->UnregisterIsolate(isolate_);
isolate_->Dispose();
per_process::v8_platform.Platform()->UnregisterIsolate(isolate_);
}

RAIIIsolate::RAIIIsolate(const SnapshotData* data)
Expand Down
2 changes: 1 addition & 1 deletion test/cctest/node_test_fixture.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ class NodeTestFixture : public NodeZeroIsolateTestFixture {
void TearDown() override {
platform->DrainTasks(isolate_);
isolate_->Exit();
platform->UnregisterIsolate(isolate_);
isolate_->Dispose();
platform->UnregisterIsolate(isolate_);
isolate_ = nullptr;
NodeZeroIsolateTestFixture::TearDown();
}
Expand Down
25 changes: 7 additions & 18 deletions test/cctest/test_cppgc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,12 @@ int CppGCed::kDestructCount = 0;
int CppGCed::kTraceCount = 0;

TEST_F(NodeZeroIsolateTestFixture, ExistingCppHeapTest) {
v8::Isolate* isolate =
node::NewIsolate(allocator.get(), &current_loop, platform.get());

// Create and attach the CppHeap before we set up the IsolateData so that
// it recognizes the existing heap.
std::unique_ptr<v8::CppHeap> cpp_heap =
v8::CppHeap::Create(platform.get(), v8::CppHeapCreateParams{{}});

// TODO(joyeecheung): pass it into v8::Isolate::CreateParams and let V8
// own it when we can keep the isolate registered/task runner discoverable
// during isolate disposal.
isolate->AttachCppHeap(cpp_heap.get());
node::IsolateSettings settings;
settings.cpp_heap =
v8::CppHeap::Create(platform.get(), v8::CppHeapCreateParams{{}})
.release();
v8::Isolate* isolate = node::NewIsolate(
allocator.get(), &current_loop, platform.get(), nullptr, settings);

// Try creating Context + IsolateData + Environment.
{
Expand Down Expand Up @@ -100,15 +94,10 @@ TEST_F(NodeZeroIsolateTestFixture, ExistingCppHeapTest) {
}

platform->DrainTasks(isolate);

// Cleanup.
isolate->DetachCppHeap();
cpp_heap->Terminate();
platform->DrainTasks(isolate);
}

platform->UnregisterIsolate(isolate);
isolate->Dispose();
platform->UnregisterIsolate(isolate);

// Check that all the objects are created and destroyed properly.
EXPECT_EQ(CppGCed::kConstructCount, 100);
Expand Down
7 changes: 5 additions & 2 deletions test/cctest/test_environment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -544,8 +544,8 @@ TEST_F(EnvironmentTest, InspectorMultipleEmbeddedEnvironments) {
node::FreeIsolateData(isolate_data);
}

data->platform->UnregisterIsolate(isolate);
isolate->Dispose();
data->platform->UnregisterIsolate(isolate);
uv_run(&loop, UV_RUN_DEFAULT);
CHECK_EQ(uv_loop_close(&loop), 0);

Expand Down Expand Up @@ -625,6 +625,9 @@ TEST_F(NodeZeroIsolateTestFixture, CtrlCWithOnlySafeTerminationTest) {
// Allocate and initialize Isolate.
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = allocator.get();
create_params.cpp_heap =
v8::CppHeap::Create(platform.get(), v8::CppHeapCreateParams{{}})
.release();
v8::Isolate* isolate = v8::Isolate::Allocate();
CHECK_NOT_NULL(isolate);
platform->RegisterIsolate(isolate, &current_loop);
Expand Down Expand Up @@ -675,8 +678,8 @@ TEST_F(NodeZeroIsolateTestFixture, CtrlCWithOnlySafeTerminationTest) {
}

// Cleanup.
platform->UnregisterIsolate(isolate);
isolate->Dispose();
platform->UnregisterIsolate(isolate);
}
#endif // _WIN32

Expand Down
5 changes: 4 additions & 1 deletion test/cctest/test_platform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ TEST_F(NodeZeroIsolateTestFixture, IsolatePlatformDelegateTest) {
// Allocate isolate
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = allocator.get();
create_params.cpp_heap =
v8::CppHeap::Create(platform.get(), v8::CppHeapCreateParams{{}})
.release();
auto isolate = v8::Isolate::Allocate();
CHECK_NOT_NULL(isolate);

Expand Down Expand Up @@ -104,8 +107,8 @@ TEST_F(NodeZeroIsolateTestFixture, IsolatePlatformDelegateTest) {

// Graceful shutdown
delegate->Shutdown();
platform->UnregisterIsolate(isolate);
isolate->Dispose();
platform->UnregisterIsolate(isolate);
}

TEST_F(PlatformTest, TracingControllerNullptr) {
Expand Down
3 changes: 3 additions & 0 deletions test/embedding/embedtest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#undef NDEBUG
#endif
#include <assert.h>
#include "cppgc/platform.h"
#include "executable_wrapper.h"
#include "node.h"

Expand Down Expand Up @@ -43,6 +44,7 @@ NODE_MAIN(int argc, node::argv_type raw_argv[]) {
// support in the future, split this configuration out as a
// command line option.
node::ProcessInitializationFlags::kDisableNodeOptionsEnv,
node::ProcessInitializationFlags::kNoInitializeCppgc,
});

for (const std::string& error : result->errors())
Expand All @@ -54,6 +56,7 @@ NODE_MAIN(int argc, node::argv_type raw_argv[]) {
std::unique_ptr<MultiIsolatePlatform> platform =
MultiIsolatePlatform::Create(4);
V8::InitializePlatform(platform.get());
cppgc::InitializeProcess(platform->GetPageAllocator());
V8::Initialize();

int ret =
Expand Down
2 changes: 1 addition & 1 deletion test/fuzzers/fuzz_env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ class FuzzerFixtureHelper {
void Teardown() {
platform->DrainTasks(isolate_);
isolate_->Exit();
platform->UnregisterIsolate(isolate_);
isolate_->Dispose();
platform->UnregisterIsolate(isolate_);
isolate_ = nullptr;
}
};
Expand Down
2 changes: 1 addition & 1 deletion test/fuzzers/fuzz_strings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ class FuzzerFixtureHelper {
void Teardown() {
platform->DrainTasks(isolate_);
isolate_->Exit();
platform->UnregisterIsolate(isolate_);
isolate_->Dispose();
platform->UnregisterIsolate(isolate_);
isolate_ = nullptr;
}
};
Expand Down