diff --git a/js/public/HashTable.h b/js/public/HashTable.h index 5fb5012c4a..36f37d6852 100644 --- a/js/public/HashTable.h +++ b/js/public/HashTable.h @@ -13,6 +13,7 @@ #include "mozilla/Casting.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Move.h" +#include "mozilla/Opaque.h" #include "mozilla/PodOperations.h" #include "mozilla/ReentrancyGuard.h" #include "mozilla/TemplateLib.h" @@ -32,6 +33,8 @@ namespace detail { /*****************************************************************************/ +using Generation = mozilla::Opaque; + // A JS-friendly, STL-like container providing a hash-based map from keys to // values. In particular, HashMap calls constructors and destructors of all // objects added so non-PODs may be used safely. @@ -205,7 +208,9 @@ class HashMap // If |generation()| is the same before and after a HashMap operation, // pointers into the table remain valid. - uint32_t generation() const { return impl.generation(); } + Generation generation() const { + return impl.generation(); + } /************************************************** Shorthand operations */ @@ -436,7 +441,9 @@ class HashSet // If |generation()| is the same before and after a HashSet operation, // pointers into the table remain valid. - uint32_t generation() const { return impl.generation(); } + Generation generation() const { + return impl.generation(); + } /************************************************** Shorthand operations */ @@ -771,7 +778,7 @@ class HashTable : private AllocPolicy Entry* entry_; #ifdef JS_DEBUG const HashTable* table_; - uint32_t generation; + Generation generation; #endif protected: @@ -878,7 +885,7 @@ class HashTable : private AllocPolicy #ifdef JS_DEBUG const HashTable* table_; uint64_t mutationCount; - uint32_t generation; + Generation generation; bool validEntry; #endif @@ -1017,8 +1024,8 @@ class HashTable : private AllocPolicy static const size_t CAP_BITS = 24; public: - Entry* table; // entry storage - uint32_t gen; // entry storage generation number + uint64_t gen; // entry storage generation number + Entry* table; // entry storage uint32_t entryCount; // number of entries in table uint32_t removedCount:CAP_BITS; // removed entry sentinels in table uint32_t hashShift:8; // multiplicative hash shift @@ -1102,8 +1109,8 @@ class HashTable : private AllocPolicy public: explicit HashTable(AllocPolicy ap) : AllocPolicy(ap) - , table(nullptr) , gen(0) + , table(nullptr) , entryCount(0) , removedCount(0) , hashShift(sHashBits) @@ -1529,10 +1536,10 @@ class HashTable : private AllocPolicy return JS_BIT(sHashBits - hashShift); } - uint32_t generation() const + Generation generation() const { MOZ_ASSERT(table); - return gen; + return Generation(gen); } size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 609b77c2e8..9b641c2ad4 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -275,10 +275,6 @@ class AutoHashMapRooter : protected AutoGCRooter return map.sizeOfIncludingThis(mallocSizeOf); } - uint32_t generation() const { - return map.generation(); - } - /************************************************** Shorthand operations */ bool has(const Lookup& l) const { @@ -390,10 +386,6 @@ class AutoHashSetRooter : protected AutoGCRooter return set.sizeOfIncludingThis(mallocSizeOf); } - uint32_t generation() const { - return set.generation(); - } - /************************************************** Shorthand operations */ bool has(const Lookup& l) const { diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 7a46270d7c..f5e38d3b56 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -35,11 +35,11 @@ typedef HashSet ShapeSet; /* Detects cycles when traversing an object graph. */ class AutoCycleDetector { + Generation hashsetGenerationAtInit; JSContext* cx; RootedObject obj; - bool cyclic; - uint32_t hashsetGenerationAtInit; ObjectSet::AddPtr hashsetAddPointer; + bool cyclic; MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER public: diff --git a/js/src/jswatchpoint.cpp b/js/src/jswatchpoint.cpp index 4de64410dc..1861204c8a 100644 --- a/js/src/jswatchpoint.cpp +++ b/js/src/jswatchpoint.cpp @@ -27,15 +27,15 @@ namespace { class AutoEntryHolder { typedef WatchpointMap::Map Map; + Generation gen; Map& map; Map::Ptr p; - uint32_t gen; RootedObject obj; RootedId id; public: AutoEntryHolder(JSContext* cx, Map& map, Map::Ptr p) - : map(map), p(p), gen(map.generation()), obj(cx, p->key().object), id(cx, p->key().id) + : gen(map.generation()), map(map), p(p), obj(cx, p->key().object), id(cx, p->key().id) { MOZ_ASSERT(!p->value().held); p->value().held = true; diff --git a/js/src/shell/jsheaptools.cpp b/js/src/shell/jsheaptools.cpp index 6859796f8d..7c3261b66b 100644 --- a/js/src/shell/jsheaptools.cpp +++ b/js/src/shell/jsheaptools.cpp @@ -272,7 +272,7 @@ HeapReverser::traverseEdge(void* cell, JSGCTraceKind kind) * visited from the main loop. */ Node n(kind); - uint32_t generation = map.generation(); + Generation generation = map.generation(); if (!map.add(a, cell, Move(n)) || !work.append(Child(cell, kind))) return false; diff --git a/mfbt/Opaque.h b/mfbt/Opaque.h new file mode 100644 index 0000000000..d7239ee7c2 --- /dev/null +++ b/mfbt/Opaque.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* An opaque integral type supporting only comparison operators. */ + +#ifndef mozilla_Opaque_h +#define mozilla_Opaque_h + +#include "mozilla/TypeTraits.h" + +namespace mozilla { + +/** + * Opaque is a replacement for integral T in cases where only comparisons + * must be supported, and it's desirable to prevent accidental dependency on + * exact values. + */ +template +class Opaque final +{ + static_assert(mozilla::IsIntegral::value, + "mozilla::Opaque only supports integral types"); + + T mValue; + +public: + Opaque() {} + explicit Opaque(T aValue) : mValue(aValue) {} + + bool operator==(const Opaque& aOther) const { + return mValue == aOther.mValue; + } + + bool operator!=(const Opaque& aOther) const { + return !(*this == aOther); + } +}; + +} // namespace mozilla + +#endif /* mozilla_Opaque_h */ diff --git a/mfbt/moz.build b/mfbt/moz.build index 82b7e7e7fb..51736cf7ed 100644 --- a/mfbt/moz.build +++ b/mfbt/moz.build @@ -53,6 +53,7 @@ EXPORTS.mozilla = [ 'Move.h', 'NullPtr.h', 'NumericLimits.h', + 'Opaque.h', 'Pair.h', 'PodOperations.h', 'Poison.h',