@@ -26,11 +26,34 @@ using BindingDataStore =
2626 std::array<BaseObjectWeakPtr<BaseObject>,
2727 static_cast <size_t >(BindingDataType::kBindingDataTypeCount )>;
2828
29+ /* *
30+ * This is a wrapper around a weak persistent of CppgcMixin, used in the
31+ * CppgcWrapperList to avoid accessing already garbage collected CppgcMixins.
32+ */
33+ class CppgcWrapperListNode {
34+ public:
35+ explicit inline CppgcWrapperListNode (CppgcMixin* ptr);
36+ inline explicit operator bool () const { return !persistent; }
37+ inline CppgcMixin* operator ->() const { return persistent.Get (); }
38+ inline CppgcMixin* operator *() const { return persistent.Get (); }
39+
40+ cppgc::WeakPersistent<CppgcMixin> persistent;
41+ // Used by ContainerOf in the ListNode implementation for fast manipulation of
42+ // CppgcWrapperList.
43+ ListNode<CppgcWrapperListNode> wrapper_list_node;
44+ };
45+
46+ /* *
47+ * A per-realm list of weak persistent of cppgc wrappers, which implements
48+ * iterations that require iterate over cppgc wrappers created by Node.js.
49+ */
2950class CppgcWrapperList
30- : public ListHead<CppgcMixin, &CppgcMixin::wrapper_list_node_>,
51+ : public ListHead<CppgcWrapperListNode,
52+ &CppgcWrapperListNode::wrapper_list_node>,
3153 public MemoryRetainer {
3254 public:
3355 void Cleanup ();
56+ void PurgeEmpty ();
3457
3558 SET_MEMORY_INFO_NAME (CppgcWrapperList)
3659 SET_SELF_SIZE (CppgcWrapperList)
@@ -141,6 +164,14 @@ class Realm : public MemoryRetainer {
141164 // it's only used for tests.
142165 std::vector<std::string> builtins_in_snapshot;
143166
167+ // This used during the destruction of cppgc wrappers to inform a GC epilogue
168+ // callback to clean up the weak persistents used to track cppgc wrappers if
169+ // the wrappers are already garbage collected to prevent holding on to
170+ // excessive useless persistents.
171+ inline void set_should_purge_empty_cppgc_wrappers (bool value) {
172+ should_purge_empty_cppgc_wrappers_ = value;
173+ }
174+
144175 protected:
145176 ~Realm ();
146177
@@ -150,11 +181,17 @@ class Realm : public MemoryRetainer {
150181 // Shorthand for isolate pointer.
151182 v8::Isolate* isolate_;
152183 v8::Global<v8::Context> context_;
184+ bool should_purge_empty_cppgc_wrappers_ = false ;
153185
154186#define V (PropertyName, TypeName ) v8::Global<TypeName> PropertyName##_;
155187 PER_REALM_STRONG_PERSISTENT_VALUES (V)
156188#undef V
157189
190+ static void PurgeEmptyCppgcWrappers (v8::Isolate* isolate,
191+ v8::GCType type,
192+ v8::GCCallbackFlags flags,
193+ void * data);
194+
158195 private:
159196 void InitializeContext (v8::Local<v8::Context> context,
160197 const RealmSerializeInfo* realm_info);
0 commit comments