1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef gc_FinalizationObservers_h 8 #define gc_FinalizationObservers_h 9 10 #include "gc/Barrier.h" 11 #include "gc/WeakMap.h" 12 #include "gc/ZoneAllocator.h" 13 #include "js/GCHashTable.h" 14 #include "js/GCVector.h" 15 16 namespace js { 17 18 class FinalizationRegistryObject; 19 class FinalizationRecordObject; 20 class WeakRefObject; 21 22 namespace gc { 23 24 // Per-zone data structures to support FinalizationRegistry and WeakRef. 25 class FinalizationObservers { 26 Zone* const zone; 27 28 // The set of all finalization registries in the associated zone. These are 29 // direct pointers and are not wrapped. 30 using RegistrySet = GCHashSet<HeapPtrObject, MovableCellHasher<HeapPtrObject>, 31 ZoneAllocPolicy>; 32 RegistrySet registries; 33 34 // A vector of FinalizationRecord objects, or CCWs to them. 35 using RecordVector = GCVector<HeapPtrObject, 1, ZoneAllocPolicy>; 36 37 // A map from finalization registry targets to a vector of finalization 38 // records representing registries that the target is registered with and 39 // their associated held values. The records may be in other zones and are 40 // wrapped appropriately. 41 using RecordMap = 42 GCHashMap<HeapPtrObject, RecordVector, MovableCellHasher<HeapPtrObject>, 43 ZoneAllocPolicy>; 44 RecordMap recordMap; 45 46 // A weak map used as a set of cross-zone wrappers. This is used for both 47 // finalization registries and weak refs. For the former it has wrappers to 48 // finalization record objects and for the latter wrappers to weak refs. 49 // 50 // The weak map marking rules keep the wrappers alive while their targets are 51 // alive and ensure that they are both swept in the same sweep group. 52 using WrapperWeakSet = ObjectValueWeakMap; 53 WrapperWeakSet crossZoneRecords; 54 55 // A map of weak ref targets to a vector of weak refs that are observing the 56 // target. The weak refs may be in other zones and are wrapped appropriately. 57 using WeakRefHeapPtrVector = 58 GCVector<js::HeapPtrObject, 1, js::ZoneAllocPolicy>; 59 using WeakRefMap = 60 GCHashMap<HeapPtrObject, WeakRefHeapPtrVector, 61 MovableCellHasher<HeapPtrObject>, ZoneAllocPolicy>; 62 WeakRefMap weakRefMap; 63 64 // A weak map used as a set of cross-zone weak refs wrappers. 65 WrapperWeakSet crossZoneWeakRefs; 66 67 public: 68 explicit FinalizationObservers(Zone* zone); 69 ~FinalizationObservers(); 70 71 // FinalizationRegistry support: 72 bool addRegistry(Handle<FinalizationRegistryObject*> registry); 73 bool addRecord(HandleObject target, HandleObject record); 74 void clearRecords(); 75 76 void updateForRemovedRecord(JSObject* wrapper, 77 FinalizationRecordObject* record); 78 79 // WeakRef support: 80 bool addWeakRefTarget(HandleObject target, HandleObject weakRef); 81 82 void unregisterWeakRefWrapper(JSObject* wrapper, WeakRefObject* weakRef); 83 84 void traceRoots(JSTracer* trc); 85 void traceWeakEdges(JSTracer* trc); 86 87 #ifdef DEBUG 88 void checkTables() const; 89 #endif 90 91 private: 92 bool addCrossZoneWrapper(WrapperWeakSet& weakSet, JSObject* wrapper); 93 void removeCrossZoneWrapper(WrapperWeakSet& weakSet, JSObject* wrapper); 94 95 void updateForRemovedWeakRef(JSObject* wrapper, WeakRefObject* weakRef); 96 97 void traceWeakFinalizationRegistryEdges(JSTracer* trc); 98 void traceWeakWeakRefEdges(JSTracer* trc); 99 void traceWeakWeakRefVector(JSTracer* trc, WeakRefHeapPtrVector& weakRefs, 100 JSObject* target); 101 102 static bool shouldRemoveRecord(FinalizationRecordObject* record); 103 }; 104 105 // Per-global data structures to support FinalizationRegistry. 106 class FinalizationRegistryGlobalData { 107 // Set of finalization records for finalization registries in this 108 // realm. These are traced as part of the realm's global. 109 using RecordSet = GCHashSet<HeapPtrObject, MovableCellHasher<HeapPtrObject>, 110 ZoneAllocPolicy>; 111 RecordSet recordSet; 112 113 public: 114 explicit FinalizationRegistryGlobalData(Zone* zone); 115 116 bool addRecord(FinalizationRecordObject* record); 117 void removeRecord(FinalizationRecordObject* record); 118 119 void trace(JSTracer* trc); 120 }; 121 122 } // namespace gc 123 } // namespace js 124 125 #endif // gc_FinalizationObservers_h 126