19
19
#include " tracing/agent.h"
20
20
#include " tracing/traced_value.h"
21
21
#include " util-inl.h"
22
+ #include " v8-cppgc.h"
22
23
#include " v8-profiler.h"
23
24
24
25
#include < algorithm>
28
29
#include < iostream>
29
30
#include < limits>
30
31
#include < memory>
32
+ #include < unordered_map>
31
33
32
34
namespace node {
33
35
@@ -497,6 +499,11 @@ void IsolateData::CreateProperties() {
497
499
contextify::ContextifyContext::InitializeGlobalTemplates (this );
498
500
}
499
501
502
+ constexpr uint16_t kDefaultCppGCEmebdderID = 0x90de ;
503
+ Mutex IsolateData::isolate_data_mutex_;
504
+ std::unordered_map<uint16_t , std::unique_ptr<PerIsolateWrapperData>>
505
+ IsolateData::wrapper_data_map_;
506
+
500
507
IsolateData::IsolateData (Isolate* isolate,
501
508
uv_loop_t * event_loop,
502
509
MultiIsolatePlatform* platform,
@@ -510,6 +517,46 @@ IsolateData::IsolateData(Isolate* isolate,
510
517
snapshot_data_(snapshot_data) {
511
518
options_.reset (
512
519
new PerIsolateOptions (*(per_process::cli_options->per_isolate )));
520
+ v8::CppHeap* cpp_heap = isolate->GetCppHeap ();
521
+
522
+ uint16_t cppgc_id = kDefaultCppGCEmebdderID ;
523
+ if (cpp_heap != nullptr ) {
524
+ // The general convention of the wrappable layout for cppgc in the
525
+ // ecosystem is:
526
+ // [ 0 ] -> embedder id
527
+ // [ 1 ] -> wrappable instance
528
+ // If the Isolate includes a CppHeap attached by another embedder,
529
+ // And if they also use the field 0 for the ID, we DCHECK that
530
+ // the layout matches our layout, and record the embedder ID for cppgc
531
+ // to avoid accidentally enabling cppgc on non-cppgc-managed wrappers .
532
+ v8::WrapperDescriptor descriptor = cpp_heap->wrapper_descriptor ();
533
+ if (descriptor.wrappable_type_index == BaseObject::kEmbedderType ) {
534
+ cppgc_id = descriptor.embedder_id_for_garbage_collected ;
535
+ DCHECK_EQ (descriptor.wrappable_instance_index , BaseObject::kSlot );
536
+ }
537
+ // If the CppHeap uses the slot we use to put non-cppgc-traced BaseObject
538
+ // for embedder ID, V8 could accidentally enable cppgc on them. So
539
+ // safe guard against this.
540
+ DCHECK_NE (descriptor.wrappable_type_index , BaseObject::kSlot );
541
+ }
542
+ // We do not care about overflow since we just want this to be different
543
+ // from the cppgc id.
544
+ uint16_t non_cppgc_id = cppgc_id + 1 ;
545
+
546
+ {
547
+ // GC could still be run after the IsolateData is destroyed, so we store
548
+ // the ids in a static map to ensure pointers to them are still valid
549
+ // then. In practice there should be very few variants of the cppgc id
550
+ // in one process so the size of this map should be very small.
551
+ node::Mutex::ScopedLock lock (isolate_data_mutex_);
552
+ auto it = wrapper_data_map_.find (cppgc_id);
553
+ if (it == wrapper_data_map_.end ()) {
554
+ auto pair = wrapper_data_map_.emplace (
555
+ cppgc_id, new PerIsolateWrapperData{cppgc_id, non_cppgc_id});
556
+ it = pair.first ;
557
+ }
558
+ wrapper_data_ = it->second .get ();
559
+ }
513
560
514
561
if (snapshot_data == nullptr ) {
515
562
CreateProperties ();
0 commit comments