author | Jeff Walden <[email protected]> |
Wed, 16 May 2018 13:29:52 -0700 | |
changeset 418910 | 233871244d8029b262685a7e35a5bb330b34ac9d |
parent 418909 | 3239e0d823ff6fc85adda2b0c036f8b53c866fbf |
child 418911 | 353d2ee295913b9d6660f0b8da2102a54c8133bf |
push id | 103419 |
push user | [email protected] |
push date | Fri, 18 May 2018 19:33:51 +0000 |
treeherder | mozilla-inbound@7658d2d1e0d7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 1462261 |
milestone | 62.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/public/HashTable.h +++ b/js/public/HashTable.h @@ -2,17 +2,16 @@ * vim: set ts=8 sts=4 et sw=4 tw=99: * 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/. */ #ifndef js_HashTable_h #define js_HashTable_h -#include "mozilla/Alignment.h" #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" #include "mozilla/Casting.h" #include "mozilla/HashFunctions.h" #include "mozilla/MemoryChecking.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Move.h" #include "mozilla/Opaque.h" @@ -25,17 +24,17 @@ #include "js/Utility.h" namespace js { class TempAllocPolicy; template <class> struct DefaultHasher; template <class, class> class HashMapEntry; namespace detail { - template <class T> class HashTableEntry; + template <typename T> class HashTableEntry; template <class T, class HashPolicy, class AllocPolicy> class HashTable; } // namespace detail /*****************************************************************************/ // The "generation" of a hash table is an opaque value indicating the state of // modification of the hash table through its lifetime. If the generation of // a hash table compares equal at times T1 and T2, then lookups in the hash @@ -785,41 +784,53 @@ struct IsPod<js::HashMapEntry<K, V> > namespace js { namespace detail { template <class T, class HashPolicy, class AllocPolicy> class HashTable; -template <class T> +template <typename T> class HashTableEntry { - template <class, class, class> friend class HashTable; - typedef typename mozilla::RemoveConst<T>::Type NonConstT; + private: + using NonConstT = typename mozilla::RemoveConst<T>::Type; HashNumber keyHash; - mozilla::AlignedStorage2<NonConstT> mem; + alignas(NonConstT) unsigned char valueData_[sizeof(NonConstT)]; + + private: + template <class, class, class> friend class HashTable; + + // Some versions of GCC treat it as a -Wstrict-aliasing violation (ergo a + // -Werror compile error) to reinterpret_cast<> |valueData_| to |T*|, even + // through |void*|. Placing the latter cast in these separate functions + // breaks the chain such that affected GCC versions no longer warn/error. + void* rawValuePtr() { return valueData_; } static const HashNumber sFreeKey = 0; static const HashNumber sRemovedKey = 1; static const HashNumber sCollisionBit = 1; static bool isLiveHash(HashNumber hash) { return hash > sRemovedKey; } HashTableEntry(const HashTableEntry&) = delete; void operator=(const HashTableEntry&) = delete; ~HashTableEntry() = delete; + NonConstT* valuePtr() { return reinterpret_cast<NonConstT*>(rawValuePtr()); } + void destroyStoredT() { - mem.addr()->~T(); - MOZ_MAKE_MEM_UNDEFINED(mem.addr(), sizeof(*mem.addr())); + NonConstT* ptr = valuePtr(); + ptr->~T(); + MOZ_MAKE_MEM_UNDEFINED(ptr, sizeof(*ptr)); } public: // NB: HashTableEntry is treated as a POD: no constructor or destructor calls. void destroyIfLive() { if (isLive()) destroyStoredT(); @@ -830,32 +841,32 @@ class HashTableEntry destroyStoredT(); } void swap(HashTableEntry* other) { if (this == other) return; MOZ_ASSERT(isLive()); if (other->isLive()) { - mozilla::Swap(*mem.addr(), *other->mem.addr()); + mozilla::Swap(*valuePtr(), *other->valuePtr()); } else { - *other->mem.addr() = mozilla::Move(*mem.addr()); + *other->valuePtr() = mozilla::Move(*valuePtr()); destroy(); } mozilla::Swap(keyHash, other->keyHash); } T& get() { MOZ_ASSERT(isLive()); - return *mem.addr(); + return *valuePtr(); } NonConstT& getMutable() { MOZ_ASSERT(isLive()); - return *mem.addr(); + return *valuePtr(); } bool isFree() const { return keyHash == sFreeKey; } void clearLive() { MOZ_ASSERT(isLive()); @@ -906,32 +917,32 @@ class HashTableEntry return keyHash & ~sCollisionBit; } template <typename... Args> void setLive(HashNumber hn, Args&&... args) { MOZ_ASSERT(!isLive()); keyHash = hn; - new(mem.addr()) T(mozilla::Forward<Args>(args)...); + new (valuePtr()) T(mozilla::Forward<Args>(args)...); MOZ_ASSERT(isLive()); } }; template <class T, class HashPolicy, class AllocPolicy> class HashTable : private AllocPolicy { friend class mozilla::ReentrancyGuard; typedef typename mozilla::RemoveConst<T>::Type NonConstT; typedef typename HashPolicy::KeyType Key; typedef typename HashPolicy::Lookup Lookup; public: - typedef HashTableEntry<T> Entry; + using Entry = HashTableEntry<T>; // A nullable pointer to a hash table element. A Ptr |p| can be tested // either explicitly |if (p.found()) p->...| or using boolean conversion // |if (p) p->...|. Ptr objects must not be used after any mutating hash // table operations unless |generation()| is tested. class Ptr { friend class HashTable;