tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 4f9e513a488d238d7c090e3ecbd09e51b54631c2
parent beee3e9ab8ff427d25aafb6cfa55bc23a4590ef0
Author: Jon Coppeard <jcoppeard@mozilla.com>
Date:   Mon, 13 Oct 2025 13:35:09 +0000

Bug 1993183 - Part 2: Add WeakMap alloc policy template parameter r=sfink

Differential Revision: https://phabricator.services.mozilla.com/D267938

Diffstat:
Mjs/src/builtin/WeakMapObject.h | 2+-
Mjs/src/debugger/DebugScript.h | 3++-
Mjs/src/debugger/Debugger.h | 4++--
Mjs/src/gc/WeakMap-inl.h | 63+++++++++++++++++++++++++++++++++------------------------------
Mjs/src/gc/WeakMap.cpp | 2+-
Mjs/src/gc/WeakMap.h | 8++++----
Mjs/src/gc/WeakMapPtr.cpp | 2+-
Mjs/src/jsapi-tests/testGCGrayMarking.cpp | 5+++--
Mjs/src/vm/EnvironmentObject.h | 2+-
Mjs/src/vm/Realm.h | 5+++--
10 files changed, 51 insertions(+), 45 deletions(-)

diff --git a/js/src/builtin/WeakMapObject.h b/js/src/builtin/WeakMapObject.h @@ -17,7 +17,7 @@ class WeakCollectionObject : public NativeObject { public: enum { DataSlot, SlotCount }; - using Map = WeakMap<Value, Value>; + using Map = WeakMap<Value, Value, ZoneAllocPolicy>; Map* getMap() { return maybePtrFromReservedSlot<Map>(DataSlot); } size_t sizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf); diff --git a/js/src/debugger/DebugScript.h b/js/src/debugger/DebugScript.h @@ -150,7 +150,8 @@ class DebugScriptObject : public NativeObject { }; // A weak map from JSScripts to DebugScriptObjects. -class DebugScriptMap : public WeakMap<JSScript*, DebugScriptObject*> { +class DebugScriptMap + : public WeakMap<JSScript*, DebugScriptObject*, ZoneAllocPolicy> { public: explicit DebugScriptMap(JSContext* cx) : WeakMap(cx) {} }; diff --git a/js/src/debugger/Debugger.h b/js/src/debugger/Debugger.h @@ -336,7 +336,7 @@ extern void CheckDebuggeeThing(JSObject* obj, bool invisibleOk); * beacomes a debuggee again later, new Frame objects are created.) */ template <class Referent, class Wrapper, bool InvisibleKeysOk = false> -class DebuggerWeakMap : private WeakMap<Referent*, Wrapper*> { +class DebuggerWeakMap : private WeakMap<Referent*, Wrapper*, ZoneAllocPolicy> { private: using Key = Referent*; using Value = Wrapper*; @@ -344,7 +344,7 @@ class DebuggerWeakMap : private WeakMap<Referent*, Wrapper*> { JS::Compartment* compartment; public: - using Base = WeakMap<Key, Value>; + using Base = WeakMap<Key, Value, ZoneAllocPolicy>; using ReferentType = Referent; using WrapperType = Wrapper; diff --git a/js/src/gc/WeakMap-inl.h b/js/src/gc/WeakMap-inl.h @@ -92,8 +92,8 @@ static inline JSObject* GetDelegate(const T& key) { // were in different zones, then we could have a case where the map zone is not // collecting but the value zone is, and incorrectly free a value that is // reachable solely through weakmaps. -template <class K, class V> -void WeakMap<K, V>::assertMapIsSameZoneWithValue(const BarrieredValue& v) { +template <class K, class V, class AP> +void WeakMap<K, V, AP>::assertMapIsSameZoneWithValue(const BarrieredValue& v) { #ifdef DEBUG gc::Cell* cell = gc::ToMarkable(v); if (cell) { @@ -103,12 +103,12 @@ void WeakMap<K, V>::assertMapIsSameZoneWithValue(const BarrieredValue& v) { #endif } -template <class K, class V> -WeakMap<K, V>::WeakMap(JSContext* cx, JSObject* memOf) +template <class K, class V, class AP> +WeakMap<K, V, AP>::WeakMap(JSContext* cx, JSObject* memOf) : WeakMap(cx->zone(), memOf) {} -template <class K, class V> -WeakMap<K, V>::WeakMap(JS::Zone* zone, JSObject* memOf) +template <class K, class V, class AP> +WeakMap<K, V, AP>::WeakMap(JS::Zone* zone, JSObject* memOf) : WeakMapBase(memOf, zone), map_(zone) { static_assert(std::is_same_v<typename RemoveBarrier<K>::Type, K>); static_assert(std::is_same_v<typename RemoveBarrier<V>::Type, V>); @@ -129,8 +129,8 @@ WeakMap<K, V>::WeakMap(JS::Zone* zone, JSObject* memOf) } } -template <class K, class V> -WeakMap<K, V>::~WeakMap() { +template <class K, class V, class AP> +WeakMap<K, V, AP>::~WeakMap() { #ifdef DEBUG // Weak maps store their data in an unbarriered map (|map_|) meaning that no // barriers are run on destruction. This is safe because: @@ -162,10 +162,10 @@ WeakMap<K, V>::~WeakMap() { // Optionally adds edges to the ephemeron edges table for any keys (or // delegates) where future changes to their mark color would require marking the // value (or the key). -template <class K, class V> -bool WeakMap<K, V>::markEntry(GCMarker* marker, gc::CellColor mapColor, - BarrieredKey& key, BarrieredValue& value, - bool populateWeakKeysTable) { +template <class K, class V, class AP> +bool WeakMap<K, V, AP>::markEntry(GCMarker* marker, gc::CellColor mapColor, + BarrieredKey& key, BarrieredValue& value, + bool populateWeakKeysTable) { #ifdef DEBUG MOZ_ASSERT(IsMarked(mapColor)); if (marker->isParallelMarking()) { @@ -253,8 +253,8 @@ bool WeakMap<K, V>::markEntry(GCMarker* marker, gc::CellColor mapColor, return marked; } -template <class K, class V> -void WeakMap<K, V>::trace(JSTracer* trc) { +template <class K, class V, class AP> +void WeakMap<K, V, AP>::trace(JSTracer* trc) { MOZ_ASSERT(isInList()); TraceNullableEdge(trc, &memberOf, "WeakMap owner"); @@ -286,8 +286,8 @@ void WeakMap<K, V>::trace(JSTracer* trc) { } } -template <class K, class V> -bool WeakMap<K, V>::markEntries(GCMarker* marker) { +template <class K, class V, class AP> +bool WeakMap<K, V, AP>::markEntries(GCMarker* marker) { // This method is called whenever the map's mark color changes. Mark values // (and keys with delegates) as required for the new color and populate the // ephemeron edges if we're in incremental marking mode. @@ -321,8 +321,10 @@ bool WeakMap<K, V>::markEntries(GCMarker* marker) { return markedAny; } -template <class K, class V> -void WeakMap<K, V>::traceWeakEdges(JSTracer* trc) { +template <class K, class V, class AP> +void WeakMap<K, V, AP>::traceWeakEdges(JSTracer* trc) { + MOZ_ASSERT(zone()->isGCSweeping()); + // Scan the map, removing all entries whose keys remain unmarked. Rebuild // cached key state at the same time. mayHaveSymbolKeys = false; @@ -343,8 +345,8 @@ void WeakMap<K, V>::traceWeakEdges(JSTracer* trc) { } // memberOf can be nullptr, which means that the map is not part of a JSObject. -template <class K, class V> -void WeakMap<K, V>::traceMappings(WeakMapTracer* tracer) { +template <class K, class V, class AP> +void WeakMap<K, V, AP>::traceMappings(WeakMapTracer* tracer) { for (Range r = all(); !r.empty(); r.popFront()) { gc::Cell* key = gc::ToMarkable(r.front().key()); gc::Cell* value = gc::ToMarkable(r.front().value()); @@ -355,8 +357,8 @@ void WeakMap<K, V>::traceMappings(WeakMapTracer* tracer) { } } -template <class K, class V> -bool WeakMap<K, V>::findSweepGroupEdges(Zone* atomsZone) { +template <class K, class V, class AP> +bool WeakMap<K, V, AP>::findSweepGroupEdges(Zone* atomsZone) { // For weakmap keys with delegates in a different zone, add a zone edge to // ensure that the delegate zone finishes marking before the key zone. @@ -404,14 +406,15 @@ bool WeakMap<K, V>::findSweepGroupEdges(Zone* atomsZone) { return true; } -template <class K, class V> -size_t WeakMap<K, V>::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) { +template <class K, class V, class AP> +size_t WeakMap<K, V, AP>::sizeOfIncludingThis( + mozilla::MallocSizeOf mallocSizeOf) { return mallocSizeOf(this) + shallowSizeOfExcludingThis(mallocSizeOf); } #if DEBUG -template <class K, class V> -void WeakMap<K, V>::assertEntriesNotAboutToBeFinalized() { +template <class K, class V, class AP> +void WeakMap<K, V, AP>::assertEntriesNotAboutToBeFinalized() { for (Range r = all(); !r.empty(); r.popFront()) { K k = r.front().key(); MOZ_ASSERT(!gc::IsAboutToBeFinalizedUnbarriered(k)); @@ -426,8 +429,8 @@ void WeakMap<K, V>::assertEntriesNotAboutToBeFinalized() { #endif #ifdef JS_GC_ZEAL -template <class K, class V> -bool WeakMap<K, V>::checkMarking() const { +template <class K, class V, class AP> +bool WeakMap<K, V, AP>::checkMarking() const { bool ok = true; for (Range r = all(); !r.empty(); r.popFront()) { gc::Cell* key = gc::ToMarkable(r.front().key()); @@ -442,8 +445,8 @@ bool WeakMap<K, V>::checkMarking() const { #endif #ifdef JSGC_HASH_TABLE_CHECKS -template <class K, class V> -void WeakMap<K, V>::checkAfterMovingGC() const { +template <class K, class V, class AP> +void WeakMap<K, V, AP>::checkAfterMovingGC() const { for (Range r = all(); !r.empty(); r.popFront()) { gc::Cell* key = gc::ToMarkable(r.front().key()); gc::Cell* value = gc::ToMarkable(r.front().value()); diff --git a/js/src/gc/WeakMap.cpp b/js/src/gc/WeakMap.cpp @@ -188,5 +188,5 @@ void WeakMapBase::restoreMarkedWeakMaps(WeakMapColors& markedWeakMaps) { } namespace js { -template class WeakMap<JSObject*, JSObject*>; +template class WeakMap<JSObject*, JSObject*, ZoneAllocPolicy>; } // namespace js diff --git a/js/src/gc/WeakMap.h b/js/src/gc/WeakMap.h @@ -203,15 +203,15 @@ class WeakMapBase : public mozilla::LinkedListElement<WeakMapBase> { template <typename Key> struct WeakMapKeyHasher : public StableCellHasher<HeapPtr<Key>> {}; -template <class Key, class Value> +template <class Key, class Value, class AllocPolicy> class WeakMap : public WeakMapBase { using BarrieredKey = HeapPtr<Key>; using BarrieredValue = HeapPtr<Value>; - using Map = HashMap<HeapPtr<Key>, HeapPtr<Value>, WeakMapKeyHasher<Key>, - ZoneAllocPolicy>; + using Map = + HashMap<HeapPtr<Key>, HeapPtr<Value>, WeakMapKeyHasher<Key>, AllocPolicy>; using UnbarrieredMap = - HashMap<Key, Value, StableCellHasher<Key>, ZoneAllocPolicy>; + HashMap<Key, Value, StableCellHasher<Key>, AllocPolicy>; UnbarrieredMap map_; // Barriers are added by |map()| accessor. diff --git a/js/src/gc/WeakMapPtr.cpp b/js/src/gc/WeakMapPtr.cpp @@ -34,7 +34,7 @@ template <typename K, typename V> struct Utils { using KeyType = K; using ValueType = V; - using Type = WeakMap<KeyType, ValueType>; + using Type = WeakMap<KeyType, ValueType, ZoneAllocPolicy>; using PtrType = Type*; static PtrType cast(void* ptr) { return static_cast<PtrType>(ptr); } }; diff --git a/js/src/jsapi-tests/testGCGrayMarking.cpp b/js/src/jsapi-tests/testGCGrayMarking.cpp @@ -26,8 +26,9 @@ static constexpr CellColor MarkedCellColors[] = {CellColor::Gray, namespace js { -struct GCManagedObjectWeakMap : public WeakMap<JSObject*, JSObject*> { - using Base = WeakMap<JSObject*, JSObject*>; +struct GCManagedObjectWeakMap + : public WeakMap<JSObject*, JSObject*, ZoneAllocPolicy> { + using Base = WeakMap<JSObject*, JSObject*, ZoneAllocPolicy>; using Base::Base; }; diff --git a/js/src/vm/EnvironmentObject.h b/js/src/vm/EnvironmentObject.h @@ -1470,7 +1470,7 @@ class DebugEnvironments { Zone* zone_; /* The map from (non-debug) environments to debug environments. */ - using ProxiedEnvironmentsMap = WeakMap<JSObject*, JSObject*>; + using ProxiedEnvironmentsMap = WeakMap<JSObject*, JSObject*, ZoneAllocPolicy>; ProxiedEnvironmentsMap proxiedEnvs; /* diff --git a/js/src/vm/Realm.h b/js/src/vm/Realm.h @@ -240,7 +240,8 @@ class ObjectRealm { // All non-syntactic lexical environments in the realm. These are kept in a // map because when loading scripts into a non-syntactic environment, we // need to use the same lexical environment to persist lexical bindings. - using NonSyntacticLexialEnvironmentsMap = WeakMap<JSObject*, JSObject*>; + using NonSyntacticLexialEnvironmentsMap = + WeakMap<JSObject*, JSObject*, ZoneAllocPolicy>; js::UniquePtr<NonSyntacticLexialEnvironmentsMap> nonSyntacticLexicalEnvironments_; @@ -253,7 +254,7 @@ class ObjectRealm { // Keep track of the metadata objects which can be associated with each JS // object. Both keys and values are in this realm. - using ObjectMetadataTable = WeakMap<JSObject*, JSObject*>; + using ObjectMetadataTable = WeakMap<JSObject*, JSObject*, ZoneAllocPolicy>; js::UniquePtr<ObjectMetadataTable> objectMetadataTable; using IteratorCache =