-
Notifications
You must be signed in to change notification settings - Fork 29.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This patch: - Initializes cppgc in InitializeOncePerProcess() when kNoInitializeCppgc is not set - Create a CppHeap and attach it to the Isolate when there isn't one already during IsolateData initialization. The CppHeap is detached and terminated when IsolateData is freed. - Publishes the cppgc headers in the tarball. This allows C++ addons to start using cppgc to manage objects. A helper node::SetCppgcReference() is also added to help addons enable cppgc tracing in a user-defined object. Co-authored-by: Joyee Cheung <[email protected]> Refs: #40786 PR-URL: #45704 Refs: https://docs.google.com/document/d/1ny2Qz_EsUnXGKJRGxoA-FXIE2xpLgaMAN6jD7eAkqFQ/edit Reviewed-By: Stephen Belanger <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]>
- Loading branch information
1 parent
7bbcb29
commit 7f2c810
Showing
11 changed files
with
290 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#include <cppgc/allocation.h> | ||
#include <cppgc/garbage-collected.h> | ||
#include <cppgc/heap.h> | ||
#include <node.h> | ||
#include <v8-cppgc.h> | ||
#include <v8.h> | ||
#include <algorithm> | ||
|
||
class CppGCed : public cppgc::GarbageCollected<CppGCed> { | ||
public: | ||
static uint16_t states[2]; | ||
static constexpr int kDestructCount = 0; | ||
static constexpr int kTraceCount = 1; | ||
|
||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args) { | ||
v8::Isolate* isolate = args.GetIsolate(); | ||
v8::Local<v8::Object> js_object = args.This(); | ||
CppGCed* gc_object = cppgc::MakeGarbageCollected<CppGCed>( | ||
isolate->GetCppHeap()->GetAllocationHandle()); | ||
node::SetCppgcReference(isolate, js_object, gc_object); | ||
args.GetReturnValue().Set(js_object); | ||
} | ||
|
||
static v8::Local<v8::Function> GetConstructor( | ||
v8::Local<v8::Context> context) { | ||
auto ft = v8::FunctionTemplate::New(context->GetIsolate(), New); | ||
auto ot = ft->InstanceTemplate(); | ||
v8::WrapperDescriptor descriptor = | ||
context->GetIsolate()->GetCppHeap()->wrapper_descriptor(); | ||
uint16_t required_size = std::max(descriptor.wrappable_instance_index, | ||
descriptor.wrappable_type_index); | ||
ot->SetInternalFieldCount(required_size + 1); | ||
return ft->GetFunction(context).ToLocalChecked(); | ||
} | ||
|
||
CppGCed() = default; | ||
|
||
~CppGCed() { states[kDestructCount]++; } | ||
|
||
void Trace(cppgc::Visitor* visitor) const { states[kTraceCount]++; } | ||
}; | ||
|
||
uint16_t CppGCed::states[] = {0, 0}; | ||
|
||
void InitModule(v8::Local<v8::Object> exports) { | ||
v8::Isolate* isolate = v8::Isolate::GetCurrent(); | ||
auto context = isolate->GetCurrentContext(); | ||
|
||
auto store = v8::ArrayBuffer::NewBackingStore( | ||
CppGCed::states, | ||
sizeof(uint16_t) * 2, | ||
[](void*, size_t, void*) {}, | ||
nullptr); | ||
auto ab = v8::ArrayBuffer::New(isolate, std::move(store)); | ||
|
||
exports | ||
->Set(context, | ||
v8::String::NewFromUtf8(isolate, "CppGCed").ToLocalChecked(), | ||
CppGCed::GetConstructor(context)) | ||
.FromJust(); | ||
exports | ||
->Set(context, | ||
v8::String::NewFromUtf8(isolate, "states").ToLocalChecked(), | ||
v8::Uint16Array::New(ab, 0, 2)) | ||
.FromJust(); | ||
exports | ||
->Set(context, | ||
v8::String::NewFromUtf8(isolate, "kDestructCount").ToLocalChecked(), | ||
v8::Integer::New(isolate, CppGCed::kDestructCount)) | ||
.FromJust(); | ||
exports | ||
->Set(context, | ||
v8::String::NewFromUtf8(isolate, "kTraceCount").ToLocalChecked(), | ||
v8::Integer::New(isolate, CppGCed::kTraceCount)) | ||
.FromJust(); | ||
} | ||
|
||
NODE_MODULE(NODE_GYP_MODULE_NAME, InitModule) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
'targets': [ | ||
{ | ||
'target_name': 'binding', | ||
'sources': [ 'binding.cc' ], | ||
'includes': ['../common.gypi'], | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
'use strict'; | ||
|
||
// Flags: --expose-gc | ||
|
||
const common = require('../../common'); | ||
|
||
// Verify that addons can create GarbageCollected objects and | ||
// have them traced properly. | ||
|
||
const assert = require('assert'); | ||
const { | ||
CppGCed, states, kDestructCount, kTraceCount, | ||
} = require(`./build/${common.buildType}/binding`); | ||
|
||
assert.strictEqual(states[kDestructCount], 0); | ||
assert.strictEqual(states[kTraceCount], 0); | ||
|
||
let array = []; | ||
const count = 100; | ||
for (let i = 0; i < count; ++i) { | ||
array.push(new CppGCed()); | ||
} | ||
|
||
globalThis.gc(); | ||
|
||
setTimeout(async function() { | ||
// GC should have invoked Trace() on at least some of the CppGCed objects, | ||
// but they should all be alive at this point. | ||
assert.strictEqual(states[kDestructCount], 0); | ||
assert.notStrictEqual(states[kTraceCount], 0); | ||
|
||
// Replace the old CppGCed objects with new ones, after GC we should have | ||
// destructed all the old ones and called Trace() on the | ||
// new ones. | ||
for (let i = 0; i < count; ++i) { | ||
array[i] = new CppGCed(); | ||
} | ||
await common.gcUntil( | ||
'All old CppGCed are destroyed', | ||
() => states[kDestructCount] === count, | ||
); | ||
// Release all the CppGCed objects, after GC we should have destructed | ||
// all of them. | ||
array = null; | ||
globalThis.gc(); | ||
|
||
await common.gcUntil( | ||
'All old CppGCed are destroyed', | ||
() => states[kDestructCount] === count * 2, | ||
); | ||
}, 1); |
Oops, something went wrong.