Differential D3143 Diff 14286 ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCHashTable.h
Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/libraries/source/spidermonkey/include-win32-debug/js/GCHashTable.h
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- | ||||
* vim: set ts=8 sts=4 et sw=4 tw=99: | * vim: set ts=8 sts=2 et sw=2 tw=80: | ||||
* This Source Code Form is subject to the terms of the Mozilla Public | * 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 | * 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/. */ | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||||
#ifndef GCHashTable_h | #ifndef GCHashTable_h | ||||
#define GCHashTable_h | #define GCHashTable_h | ||||
#include "mozilla/Maybe.h" | #include "mozilla/Maybe.h" | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | template <typename Key, typename Value, | ||||
typename HashPolicy = js::DefaultHasher<Key>, | typename HashPolicy = js::DefaultHasher<Key>, | ||||
typename AllocPolicy = js::TempAllocPolicy, | typename AllocPolicy = js::TempAllocPolicy, | ||||
typename MapSweepPolicy = DefaultMapSweepPolicy<Key, Value>> | typename MapSweepPolicy = DefaultMapSweepPolicy<Key, Value>> | ||||
class GCHashMap : public js::HashMap<Key, Value, HashPolicy, AllocPolicy> { | class GCHashMap : public js::HashMap<Key, Value, HashPolicy, AllocPolicy> { | ||||
using Base = js::HashMap<Key, Value, HashPolicy, AllocPolicy>; | using Base = js::HashMap<Key, Value, HashPolicy, AllocPolicy>; | ||||
public: | public: | ||||
explicit GCHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {} | explicit GCHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {} | ||||
explicit GCHashMap(size_t length) : Base(length) {} | |||||
GCHashMap(AllocPolicy a, size_t length) : Base(a, length) {} | |||||
static void trace(GCHashMap* map, JSTracer* trc) { map->trace(trc); } | static void trace(GCHashMap* map, JSTracer* trc) { map->trace(trc); } | ||||
void trace(JSTracer* trc) { | void trace(JSTracer* trc) { | ||||
if (!this->initialized()) return; | |||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | ||||
GCPolicy<Value>::trace(trc, &e.front().value(), "hashmap value"); | GCPolicy<Value>::trace(trc, &e.front().value(), "hashmap value"); | ||||
GCPolicy<Key>::trace(trc, &e.front().mutableKey(), "hashmap key"); | GCPolicy<Key>::trace(trc, &e.front().mutableKey(), "hashmap key"); | ||||
} | } | ||||
} | } | ||||
bool needsSweep() const { return this->initialized() && !this->empty(); } | bool needsSweep() const { return !this->empty(); } | ||||
void sweep() { | void sweep() { | ||||
if (!this->initialized()) return; | |||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | ||||
if (MapSweepPolicy::needsSweep(&e.front().mutableKey(), | if (MapSweepPolicy::needsSweep(&e.front().mutableKey(), | ||||
&e.front().value())) | &e.front().value())) { | ||||
e.removeFront(); | e.removeFront(); | ||||
} | } | ||||
} | } | ||||
} | |||||
// GCHashMap is movable | // GCHashMap is movable | ||||
GCHashMap(GCHashMap&& rhs) : Base(mozilla::Move(rhs)) {} | GCHashMap(GCHashMap&& rhs) : Base(std::move(rhs)) {} | ||||
void operator=(GCHashMap&& rhs) { | void operator=(GCHashMap&& rhs) { | ||||
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); | MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); | ||||
Base::operator=(mozilla::Move(rhs)); | Base::operator=(std::move(rhs)); | ||||
} | } | ||||
private: | private: | ||||
// GCHashMap is not copyable or assignable | // GCHashMap is not copyable or assignable | ||||
GCHashMap(const GCHashMap& hm) = delete; | GCHashMap(const GCHashMap& hm) = delete; | ||||
GCHashMap& operator=(const GCHashMap& hm) = delete; | GCHashMap& operator=(const GCHashMap& hm) = delete; | ||||
}; | } MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS; | ||||
} // namespace JS | } // namespace JS | ||||
namespace js { | namespace js { | ||||
// HashMap that supports rekeying. | // HashMap that supports rekeying. | ||||
// | // | ||||
// If your keys are pointers to something like JSObject that can be tenured or | // If your keys are pointers to something like JSObject that can be tenured or | ||||
// compacted, prefer to use GCHashMap with MovableCellHasher, which takes | // compacted, prefer to use GCHashMap with MovableCellHasher, which takes | ||||
// advantage of the Zone's stable id table to make rekeying unnecessary. | // advantage of the Zone's stable id table to make rekeying unnecessary. | ||||
template <typename Key, typename Value, | template <typename Key, typename Value, | ||||
typename HashPolicy = DefaultHasher<Key>, | typename HashPolicy = DefaultHasher<Key>, | ||||
typename AllocPolicy = TempAllocPolicy, | typename AllocPolicy = TempAllocPolicy, | ||||
typename MapSweepPolicy = JS::DefaultMapSweepPolicy<Key, Value>> | typename MapSweepPolicy = JS::DefaultMapSweepPolicy<Key, Value>> | ||||
class GCRekeyableHashMap : public JS::GCHashMap<Key, Value, HashPolicy, | class GCRekeyableHashMap : public JS::GCHashMap<Key, Value, HashPolicy, | ||||
AllocPolicy, MapSweepPolicy> { | AllocPolicy, MapSweepPolicy> { | ||||
using Base = JS::GCHashMap<Key, Value, HashPolicy, AllocPolicy>; | using Base = JS::GCHashMap<Key, Value, HashPolicy, AllocPolicy>; | ||||
public: | public: | ||||
explicit GCRekeyableHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {} | explicit GCRekeyableHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {} | ||||
explicit GCRekeyableHashMap(size_t length) : Base(length) {} | |||||
GCRekeyableHashMap(AllocPolicy a, size_t length) : Base(a, length) {} | |||||
void sweep() { | void sweep() { | ||||
if (!this->initialized()) return; | |||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | ||||
Key key(e.front().key()); | Key key(e.front().key()); | ||||
if (MapSweepPolicy::needsSweep(&key, &e.front().value())) | if (MapSweepPolicy::needsSweep(&key, &e.front().value())) { | ||||
e.removeFront(); | e.removeFront(); | ||||
else if (!HashPolicy::match(key, e.front().key())) | } else if (!HashPolicy::match(key, e.front().key())) { | ||||
e.rekeyFront(key); | e.rekeyFront(key); | ||||
} | } | ||||
} | } | ||||
} | |||||
// GCRekeyableHashMap is movable | // GCRekeyableHashMap is movable | ||||
GCRekeyableHashMap(GCRekeyableHashMap&& rhs) : Base(mozilla::Move(rhs)) {} | GCRekeyableHashMap(GCRekeyableHashMap&& rhs) : Base(std::move(rhs)) {} | ||||
void operator=(GCRekeyableHashMap&& rhs) { | void operator=(GCRekeyableHashMap&& rhs) { | ||||
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); | MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); | ||||
Base::operator=(mozilla::Move(rhs)); | Base::operator=(std::move(rhs)); | ||||
} | } | ||||
}; | } MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS; | ||||
template <typename Wrapper, typename... Args> | template <typename Wrapper, typename... Args> | ||||
class WrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper> { | class WrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper> { | ||||
using Map = JS::GCHashMap<Args...>; | using Map = JS::GCHashMap<Args...>; | ||||
using Lookup = typename Map::Lookup; | using Lookup = typename Map::Lookup; | ||||
const Map& map() const { return static_cast<const Wrapper*>(this)->get(); } | const Map& map() const { return static_cast<const Wrapper*>(this)->get(); } | ||||
public: | public: | ||||
using AddPtr = typename Map::AddPtr; | using AddPtr = typename Map::AddPtr; | ||||
using Ptr = typename Map::Ptr; | using Ptr = typename Map::Ptr; | ||||
using Range = typename Map::Range; | using Range = typename Map::Range; | ||||
bool initialized() const { return map().initialized(); } | |||||
Ptr lookup(const Lookup& l) const { return map().lookup(l); } | Ptr lookup(const Lookup& l) const { return map().lookup(l); } | ||||
AddPtr lookupForAdd(const Lookup& l) const { return map().lookupForAdd(l); } | |||||
Range all() const { return map().all(); } | Range all() const { return map().all(); } | ||||
bool empty() const { return map().empty(); } | bool empty() const { return map().empty(); } | ||||
uint32_t count() const { return map().count(); } | uint32_t count() const { return map().count(); } | ||||
size_t capacity() const { return map().capacity(); } | size_t capacity() const { return map().capacity(); } | ||||
bool has(const Lookup& l) const { return map().lookup(l).found(); } | bool has(const Lookup& l) const { return map().lookup(l).found(); } | ||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | ||||
return map().sizeOfExcludingThis(mallocSizeOf); | return map().sizeOfExcludingThis(mallocSizeOf); | ||||
} | } | ||||
Show All 13 Lines | |||||
public: | public: | ||||
using AddPtr = typename Map::AddPtr; | using AddPtr = typename Map::AddPtr; | ||||
struct Enum : public Map::Enum { | struct Enum : public Map::Enum { | ||||
explicit Enum(Wrapper& o) : Map::Enum(o.map()) {} | explicit Enum(Wrapper& o) : Map::Enum(o.map()) {} | ||||
}; | }; | ||||
using Ptr = typename Map::Ptr; | using Ptr = typename Map::Ptr; | ||||
using Range = typename Map::Range; | using Range = typename Map::Range; | ||||
bool init(uint32_t len = 16) { return map().init(len); } | |||||
void clear() { map().clear(); } | void clear() { map().clear(); } | ||||
void finish() { map().finish(); } | void clearAndCompact() { map().clearAndCompact(); } | ||||
void remove(Ptr p) { map().remove(p); } | void remove(Ptr p) { map().remove(p); } | ||||
AddPtr lookupForAdd(const Lookup& l) { return map().lookupForAdd(l); } | |||||
template <typename KeyInput, typename ValueInput> | template <typename KeyInput, typename ValueInput> | ||||
bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) { | bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) { | ||||
return map().add(p, mozilla::Forward<KeyInput>(k), | return map().add(p, std::forward<KeyInput>(k), std::forward<ValueInput>(v)); | ||||
mozilla::Forward<ValueInput>(v)); | |||||
} | } | ||||
template <typename KeyInput> | template <typename KeyInput> | ||||
bool add(AddPtr& p, KeyInput&& k) { | bool add(AddPtr& p, KeyInput&& k) { | ||||
return map().add(p, mozilla::Forward<KeyInput>(k), Map::Value()); | return map().add(p, std::forward<KeyInput>(k), Map::Value()); | ||||
} | } | ||||
template <typename KeyInput, typename ValueInput> | template <typename KeyInput, typename ValueInput> | ||||
bool relookupOrAdd(AddPtr& p, KeyInput&& k, ValueInput&& v) { | bool relookupOrAdd(AddPtr& p, KeyInput&& k, ValueInput&& v) { | ||||
return map().relookupOrAdd(p, k, mozilla::Forward<KeyInput>(k), | return map().relookupOrAdd(p, k, std::forward<KeyInput>(k), | ||||
mozilla::Forward<ValueInput>(v)); | std::forward<ValueInput>(v)); | ||||
} | } | ||||
template <typename KeyInput, typename ValueInput> | template <typename KeyInput, typename ValueInput> | ||||
bool put(KeyInput&& k, ValueInput&& v) { | bool put(KeyInput&& k, ValueInput&& v) { | ||||
return map().put(mozilla::Forward<KeyInput>(k), | return map().put(std::forward<KeyInput>(k), std::forward<ValueInput>(v)); | ||||
mozilla::Forward<ValueInput>(v)); | |||||
} | } | ||||
template <typename KeyInput, typename ValueInput> | template <typename KeyInput, typename ValueInput> | ||||
bool putNew(KeyInput&& k, ValueInput&& v) { | bool putNew(KeyInput&& k, ValueInput&& v) { | ||||
return map().putNew(mozilla::Forward<KeyInput>(k), | return map().putNew(std::forward<KeyInput>(k), std::forward<ValueInput>(v)); | ||||
mozilla::Forward<ValueInput>(v)); | |||||
} | } | ||||
}; | }; | ||||
} // namespace js | } // namespace js | ||||
namespace JS { | namespace JS { | ||||
// A GCHashSet is a HashSet with an additional trace method that knows | // A GCHashSet is a HashSet with an additional trace method that knows | ||||
Show All 11 Lines | |||||
// manually. | // manually. | ||||
template <typename T, typename HashPolicy = js::DefaultHasher<T>, | template <typename T, typename HashPolicy = js::DefaultHasher<T>, | ||||
typename AllocPolicy = js::TempAllocPolicy> | typename AllocPolicy = js::TempAllocPolicy> | ||||
class GCHashSet : public js::HashSet<T, HashPolicy, AllocPolicy> { | class GCHashSet : public js::HashSet<T, HashPolicy, AllocPolicy> { | ||||
using Base = js::HashSet<T, HashPolicy, AllocPolicy>; | using Base = js::HashSet<T, HashPolicy, AllocPolicy>; | ||||
public: | public: | ||||
explicit GCHashSet(AllocPolicy a = AllocPolicy()) : Base(a) {} | explicit GCHashSet(AllocPolicy a = AllocPolicy()) : Base(a) {} | ||||
explicit GCHashSet(size_t length) : Base(length) {} | |||||
GCHashSet(AllocPolicy a, size_t length) : Base(a, length) {} | |||||
static void trace(GCHashSet* set, JSTracer* trc) { set->trace(trc); } | static void trace(GCHashSet* set, JSTracer* trc) { set->trace(trc); } | ||||
void trace(JSTracer* trc) { | void trace(JSTracer* trc) { | ||||
if (!this->initialized()) return; | for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | ||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) | |||||
GCPolicy<T>::trace(trc, &e.mutableFront(), "hashset element"); | GCPolicy<T>::trace(trc, &e.mutableFront(), "hashset element"); | ||||
} | } | ||||
} | |||||
bool needsSweep() const { return this->initialized() && !this->empty(); } | bool needsSweep() const { return !this->empty(); } | ||||
void sweep() { | void sweep() { | ||||
if (!this->initialized()) return; | |||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | ||||
if (GCPolicy<T>::needsSweep(&e.mutableFront())) e.removeFront(); | if (GCPolicy<T>::needsSweep(&e.mutableFront())) { | ||||
e.removeFront(); | |||||
} | |||||
} | } | ||||
} | } | ||||
// GCHashSet is movable | // GCHashSet is movable | ||||
GCHashSet(GCHashSet&& rhs) : Base(mozilla::Move(rhs)) {} | GCHashSet(GCHashSet&& rhs) : Base(std::move(rhs)) {} | ||||
void operator=(GCHashSet&& rhs) { | void operator=(GCHashSet&& rhs) { | ||||
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); | MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); | ||||
Base::operator=(mozilla::Move(rhs)); | Base::operator=(std::move(rhs)); | ||||
} | } | ||||
private: | private: | ||||
// GCHashSet is not copyable or assignable | // GCHashSet is not copyable or assignable | ||||
GCHashSet(const GCHashSet& hs) = delete; | GCHashSet(const GCHashSet& hs) = delete; | ||||
GCHashSet& operator=(const GCHashSet& hs) = delete; | GCHashSet& operator=(const GCHashSet& hs) = delete; | ||||
}; | } MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS; | ||||
} // namespace JS | } // namespace JS | ||||
namespace js { | namespace js { | ||||
template <typename Wrapper, typename... Args> | template <typename Wrapper, typename... Args> | ||||
class WrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper> { | class WrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper> { | ||||
using Set = JS::GCHashSet<Args...>; | using Set = JS::GCHashSet<Args...>; | ||||
const Set& set() const { return static_cast<const Wrapper*>(this)->get(); } | const Set& set() const { return static_cast<const Wrapper*>(this)->get(); } | ||||
public: | public: | ||||
using Lookup = typename Set::Lookup; | using Lookup = typename Set::Lookup; | ||||
using AddPtr = typename Set::AddPtr; | using AddPtr = typename Set::AddPtr; | ||||
using Entry = typename Set::Entry; | using Entry = typename Set::Entry; | ||||
using Ptr = typename Set::Ptr; | using Ptr = typename Set::Ptr; | ||||
using Range = typename Set::Range; | using Range = typename Set::Range; | ||||
bool initialized() const { return set().initialized(); } | |||||
Ptr lookup(const Lookup& l) const { return set().lookup(l); } | Ptr lookup(const Lookup& l) const { return set().lookup(l); } | ||||
AddPtr lookupForAdd(const Lookup& l) const { return set().lookupForAdd(l); } | |||||
Range all() const { return set().all(); } | Range all() const { return set().all(); } | ||||
bool empty() const { return set().empty(); } | bool empty() const { return set().empty(); } | ||||
uint32_t count() const { return set().count(); } | uint32_t count() const { return set().count(); } | ||||
size_t capacity() const { return set().capacity(); } | size_t capacity() const { return set().capacity(); } | ||||
bool has(const Lookup& l) const { return set().lookup(l).found(); } | bool has(const Lookup& l) const { return set().lookup(l).found(); } | ||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | ||||
return set().sizeOfExcludingThis(mallocSizeOf); | return set().sizeOfExcludingThis(mallocSizeOf); | ||||
} | } | ||||
Show All 14 Lines | public: | ||||
using AddPtr = typename Set::AddPtr; | using AddPtr = typename Set::AddPtr; | ||||
using Entry = typename Set::Entry; | using Entry = typename Set::Entry; | ||||
struct Enum : public Set::Enum { | struct Enum : public Set::Enum { | ||||
explicit Enum(Wrapper& o) : Set::Enum(o.set()) {} | explicit Enum(Wrapper& o) : Set::Enum(o.set()) {} | ||||
}; | }; | ||||
using Ptr = typename Set::Ptr; | using Ptr = typename Set::Ptr; | ||||
using Range = typename Set::Range; | using Range = typename Set::Range; | ||||
bool init(uint32_t len = 16) { return set().init(len); } | |||||
void clear() { set().clear(); } | void clear() { set().clear(); } | ||||
void finish() { set().finish(); } | void clearAndCompact() { set().clearAndCompact(); } | ||||
MOZ_MUST_USE bool reserve(uint32_t len) { return set().reserve(len); } | |||||
void remove(Ptr p) { set().remove(p); } | void remove(Ptr p) { set().remove(p); } | ||||
void remove(const Lookup& l) { set().remove(l); } | void remove(const Lookup& l) { set().remove(l); } | ||||
AddPtr lookupForAdd(const Lookup& l) { return set().lookupForAdd(l); } | |||||
template <typename TInput> | template <typename TInput> | ||||
bool add(AddPtr& p, TInput&& t) { | bool add(AddPtr& p, TInput&& t) { | ||||
return set().add(p, mozilla::Forward<TInput>(t)); | return set().add(p, std::forward<TInput>(t)); | ||||
} | } | ||||
template <typename TInput> | template <typename TInput> | ||||
bool relookupOrAdd(AddPtr& p, const Lookup& l, TInput&& t) { | bool relookupOrAdd(AddPtr& p, const Lookup& l, TInput&& t) { | ||||
return set().relookupOrAdd(p, l, mozilla::Forward<TInput>(t)); | return set().relookupOrAdd(p, l, std::forward<TInput>(t)); | ||||
} | } | ||||
template <typename TInput> | template <typename TInput> | ||||
bool put(TInput&& t) { | bool put(TInput&& t) { | ||||
return set().put(mozilla::Forward<TInput>(t)); | return set().put(std::forward<TInput>(t)); | ||||
} | } | ||||
template <typename TInput> | template <typename TInput> | ||||
bool putNew(TInput&& t) { | bool putNew(TInput&& t) { | ||||
return set().putNew(mozilla::Forward<TInput>(t)); | return set().putNew(std::forward<TInput>(t)); | ||||
} | } | ||||
template <typename TInput> | template <typename TInput> | ||||
bool putNew(const Lookup& l, TInput&& t) { | bool putNew(const Lookup& l, TInput&& t) { | ||||
return set().putNew(l, mozilla::Forward<TInput>(t)); | return set().putNew(l, std::forward<TInput>(t)); | ||||
} | } | ||||
}; | }; | ||||
} /* namespace js */ | } /* namespace js */ | ||||
namespace JS { | namespace JS { | ||||
// Specialize WeakCache for GCHashMap to provide a barriered map that does not | // Specialize WeakCache for GCHashMap to provide a barriered map that does not | ||||
// need to be swept immediately. | // need to be swept immediately. | ||||
template <typename Key, typename Value, typename HashPolicy, | template <typename Key, typename Value, typename HashPolicy, | ||||
typename AllocPolicy, typename MapSweepPolicy> | typename AllocPolicy, typename MapSweepPolicy> | ||||
class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>> | class WeakCache<GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>> | ||||
: protected detail::WeakCacheBase { | : protected detail::WeakCacheBase { | ||||
using Map = GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>; | using Map = GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy>; | ||||
using Self = WeakCache<Map>; | using Self = WeakCache<Map>; | ||||
Map map; | Map map; | ||||
bool needsBarrier; | bool needsBarrier; | ||||
public: | public: | ||||
template <typename... Args> | template <typename... Args> | ||||
explicit WeakCache(Zone* zone, Args&&... args) | explicit WeakCache(Zone* zone, Args&&... args) | ||||
: WeakCacheBase(zone), | : WeakCacheBase(zone), | ||||
map(mozilla::Forward<Args>(args)...), | map(std::forward<Args>(args)...), | ||||
needsBarrier(false) {} | needsBarrier(false) {} | ||||
template <typename... Args> | template <typename... Args> | ||||
explicit WeakCache(JSRuntime* rt, Args&&... args) | explicit WeakCache(JSRuntime* rt, Args&&... args) | ||||
: WeakCacheBase(rt), | : WeakCacheBase(rt), | ||||
map(mozilla::Forward<Args>(args)...), | map(std::forward<Args>(args)...), | ||||
needsBarrier(false) {} | needsBarrier(false) {} | ||||
~WeakCache() { MOZ_ASSERT(!needsBarrier); } | ~WeakCache() { MOZ_ASSERT(!needsBarrier); } | ||||
bool needsSweep() override { return map.needsSweep(); } | bool needsSweep() override { return map.needsSweep(); } | ||||
size_t sweep() override { | size_t sweep() override { | ||||
if (!this->initialized()) return 0; | |||||
size_t steps = map.count(); | size_t steps = map.count(); | ||||
map.sweep(); | map.sweep(); | ||||
return steps; | return steps; | ||||
} | } | ||||
bool setNeedsIncrementalBarrier(bool needs) override { | bool setNeedsIncrementalBarrier(bool needs) override { | ||||
MOZ_ASSERT(needsBarrier != needs); | MOZ_ASSERT(needsBarrier != needs); | ||||
needsBarrier = needs; | needsBarrier = needs; | ||||
Show All 30 Lines | void popFront() { | ||||
range.popFront(); | range.popFront(); | ||||
settle(); | settle(); | ||||
} | } | ||||
private: | private: | ||||
typename Map::Range range; | typename Map::Range range; | ||||
void settle() { | void settle() { | ||||
while (!empty() && entryNeedsSweep(front())) popFront(); | while (!empty() && entryNeedsSweep(front())) { | ||||
popFront(); | |||||
} | |||||
} | } | ||||
}; | }; | ||||
struct Enum : public Map::Enum { | struct Enum : public Map::Enum { | ||||
explicit Enum(Self& cache) : Map::Enum(cache.map) { | explicit Enum(Self& cache) : Map::Enum(cache.map) { | ||||
// This operation is not allowed while barriers are in place as we | // This operation is not allowed while barriers are in place as we | ||||
// may also need to enumerate the set for sweeping. | // may also need to enumerate the set for sweeping. | ||||
MOZ_ASSERT(!cache.needsBarrier); | MOZ_ASSERT(!cache.needsBarrier); | ||||
} | } | ||||
}; | }; | ||||
bool initialized() const { return map.initialized(); } | |||||
Ptr lookup(const Lookup& l) const { | Ptr lookup(const Lookup& l) const { | ||||
Ptr ptr = map.lookup(l); | Ptr ptr = map.lookup(l); | ||||
if (needsBarrier && ptr && entryNeedsSweep(*ptr)) { | if (needsBarrier && ptr && entryNeedsSweep(*ptr)) { | ||||
const_cast<Map&>(map).remove(ptr); | const_cast<Map&>(map).remove(ptr); | ||||
return Ptr(); | return Ptr(); | ||||
} | } | ||||
return ptr; | return ptr; | ||||
} | } | ||||
AddPtr lookupForAdd(const Lookup& l) const { | AddPtr lookupForAdd(const Lookup& l) { | ||||
AddPtr ptr = map.lookupForAdd(l); | AddPtr ptr = map.lookupForAdd(l); | ||||
if (needsBarrier && ptr && entryNeedsSweep(*ptr)) { | if (needsBarrier && ptr && entryNeedsSweep(*ptr)) { | ||||
const_cast<Map&>(map).remove(ptr); | const_cast<Map&>(map).remove(ptr); | ||||
return map.lookupForAdd(l); | return map.lookupForAdd(l); | ||||
} | } | ||||
return ptr; | return ptr; | ||||
} | } | ||||
Show All 18 Lines | public: | ||||
size_t capacity() const { return map.capacity(); } | size_t capacity() const { return map.capacity(); } | ||||
bool has(const Lookup& l) const { return lookup(l).found(); } | bool has(const Lookup& l) const { return lookup(l).found(); } | ||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | ||||
return map.sizeOfExcludingThis(mallocSizeOf); | return map.sizeOfExcludingThis(mallocSizeOf); | ||||
} | } | ||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | ||||
return mallocSizeOf(this) + map.sizeOfExcludingThis(mallocSizeOf); | return mallocSizeOf(this) + map.shallowSizeOfExcludingThis(mallocSizeOf); | ||||
} | |||||
bool init(uint32_t len = 16) { | |||||
MOZ_ASSERT(!needsBarrier); | |||||
return map.init(len); | |||||
} | } | ||||
void clear() { | void clear() { | ||||
// This operation is not currently allowed while barriers are in place | // This operation is not currently allowed while barriers are in place | ||||
// since it doesn't make sense to clear a cache while it is being swept. | // since it doesn't make sense to clear a cache while it is being swept. | ||||
MOZ_ASSERT(!needsBarrier); | MOZ_ASSERT(!needsBarrier); | ||||
map.clear(); | map.clear(); | ||||
} | } | ||||
void finish() { | void clearAndCompact() { | ||||
// This operation is not currently allowed while barriers are in place | // This operation is not currently allowed while barriers are in place | ||||
// since it doesn't make sense to destroy a cache while it is being swept. | // since it doesn't make sense to clear a cache while it is being swept. | ||||
MOZ_ASSERT(!needsBarrier); | MOZ_ASSERT(!needsBarrier); | ||||
map.finish(); | map.clearAndCompact(); | ||||
} | } | ||||
void remove(Ptr p) { | void remove(Ptr p) { | ||||
// This currently supports removing entries during incremental | // This currently supports removing entries during incremental | ||||
// sweeping. If we allow these tables to be swept incrementally this may | // sweeping. If we allow these tables to be swept incrementally this may | ||||
// no longer be possible. | // no longer be possible. | ||||
map.remove(p); | map.remove(p); | ||||
} | } | ||||
void remove(const Lookup& l) { | void remove(const Lookup& l) { | ||||
Ptr p = lookup(l); | Ptr p = lookup(l); | ||||
if (p) remove(p); | if (p) { | ||||
remove(p); | |||||
} | } | ||||
template <typename KeyInput> | |||||
bool add(AddPtr& p, KeyInput&& k) { | |||||
using mozilla::Forward; | |||||
return map.add(p, Forward<KeyInput>(k)); | |||||
} | } | ||||
template <typename KeyInput, typename ValueInput> | template <typename KeyInput, typename ValueInput> | ||||
bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) { | bool add(AddPtr& p, KeyInput&& k, ValueInput&& v) { | ||||
using mozilla::Forward; | return map.add(p, std::forward<KeyInput>(k), std::forward<ValueInput>(v)); | ||||
return map.add(p, Forward<KeyInput>(k), Forward<ValueInput>(v)); | |||||
} | } | ||||
template <typename KeyInput, typename ValueInput> | template <typename KeyInput, typename ValueInput> | ||||
bool relookupOrAdd(AddPtr& p, KeyInput&& k, ValueInput&& v) { | bool relookupOrAdd(AddPtr& p, KeyInput&& k, ValueInput&& v) { | ||||
using mozilla::Forward; | return map.relookupOrAdd(p, std::forward<KeyInput>(k), | ||||
return map.relookupOrAdd(p, Forward<KeyInput>(k), Forward<ValueInput>(v)); | std::forward<ValueInput>(v)); | ||||
} | } | ||||
template <typename KeyInput, typename ValueInput> | template <typename KeyInput, typename ValueInput> | ||||
bool put(KeyInput&& k, ValueInput&& v) { | bool put(KeyInput&& k, ValueInput&& v) { | ||||
using mozilla::Forward; | return map.put(std::forward<KeyInput>(k), std::forward<ValueInput>(v)); | ||||
return map.put(Forward<KeyInput>(k), Forward<ValueInput>(v)); | |||||
} | } | ||||
template <typename KeyInput, typename ValueInput> | template <typename KeyInput, typename ValueInput> | ||||
bool putNew(KeyInput&& k, ValueInput&& v) { | bool putNew(KeyInput&& k, ValueInput&& v) { | ||||
using mozilla::Forward; | return map.putNew(std::forward<KeyInput>(k), std::forward<ValueInput>(v)); | ||||
return map.putNew(Forward<KeyInput>(k), Forward<ValueInput>(v)); | |||||
} | } | ||||
}; | } JS_HAZ_NON_GC_POINTER; | ||||
// Specialize WeakCache for GCHashSet to provide a barriered set that does not | // Specialize WeakCache for GCHashSet to provide a barriered set that does not | ||||
// need to be swept immediately. | // need to be swept immediately. | ||||
template <typename T, typename HashPolicy, typename AllocPolicy> | template <typename T, typename HashPolicy, typename AllocPolicy> | ||||
class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>> | class WeakCache<GCHashSet<T, HashPolicy, AllocPolicy>> | ||||
: protected detail::WeakCacheBase { | : protected detail::WeakCacheBase { | ||||
using Set = GCHashSet<T, HashPolicy, AllocPolicy>; | using Set = GCHashSet<T, HashPolicy, AllocPolicy>; | ||||
using Self = WeakCache<Set>; | using Self = WeakCache<Set>; | ||||
Set set; | Set set; | ||||
bool needsBarrier; | bool needsBarrier; | ||||
public: | public: | ||||
using Entry = typename Set::Entry; | using Entry = typename Set::Entry; | ||||
template <typename... Args> | template <typename... Args> | ||||
explicit WeakCache(Zone* zone, Args&&... args) | explicit WeakCache(Zone* zone, Args&&... args) | ||||
: WeakCacheBase(zone), | : WeakCacheBase(zone), | ||||
set(mozilla::Forward<Args>(args)...), | set(std::forward<Args>(args)...), | ||||
needsBarrier(false) {} | needsBarrier(false) {} | ||||
template <typename... Args> | template <typename... Args> | ||||
explicit WeakCache(JSRuntime* rt, Args&&... args) | explicit WeakCache(JSRuntime* rt, Args&&... args) | ||||
: WeakCacheBase(rt), | : WeakCacheBase(rt), | ||||
set(mozilla::Forward<Args>(args)...), | set(std::forward<Args>(args)...), | ||||
needsBarrier(false) {} | needsBarrier(false) {} | ||||
size_t sweep() override { | size_t sweep() override { | ||||
if (!this->initialized()) return 0; | |||||
size_t steps = set.count(); | size_t steps = set.count(); | ||||
set.sweep(); | set.sweep(); | ||||
return steps; | return steps; | ||||
} | } | ||||
bool needsSweep() override { return set.needsSweep(); } | bool needsSweep() override { return set.needsSweep(); } | ||||
bool setNeedsIncrementalBarrier(bool needs) override { | bool setNeedsIncrementalBarrier(bool needs) override { | ||||
Show All 28 Lines | void popFront() { | ||||
range.popFront(); | range.popFront(); | ||||
settle(); | settle(); | ||||
} | } | ||||
private: | private: | ||||
typename Set::Range range; | typename Set::Range range; | ||||
void settle() { | void settle() { | ||||
while (!empty() && entryNeedsSweep(front())) popFront(); | while (!empty() && entryNeedsSweep(front())) { | ||||
popFront(); | |||||
} | |||||
} | } | ||||
}; | }; | ||||
struct Enum : public Set::Enum { | struct Enum : public Set::Enum { | ||||
explicit Enum(Self& cache) : Set::Enum(cache.set) { | explicit Enum(Self& cache) : Set::Enum(cache.set) { | ||||
// This operation is not allowed while barriers are in place as we | // This operation is not allowed while barriers are in place as we | ||||
// may also need to enumerate the set for sweeping. | // may also need to enumerate the set for sweeping. | ||||
MOZ_ASSERT(!cache.needsBarrier); | MOZ_ASSERT(!cache.needsBarrier); | ||||
} | } | ||||
}; | }; | ||||
bool initialized() const { return set.initialized(); } | |||||
Ptr lookup(const Lookup& l) const { | Ptr lookup(const Lookup& l) const { | ||||
Ptr ptr = set.lookup(l); | Ptr ptr = set.lookup(l); | ||||
if (needsBarrier && ptr && entryNeedsSweep(*ptr)) { | if (needsBarrier && ptr && entryNeedsSweep(*ptr)) { | ||||
const_cast<Set&>(set).remove(ptr); | const_cast<Set&>(set).remove(ptr); | ||||
return Ptr(); | return Ptr(); | ||||
} | } | ||||
return ptr; | return ptr; | ||||
} | } | ||||
AddPtr lookupForAdd(const Lookup& l) const { | AddPtr lookupForAdd(const Lookup& l) { | ||||
AddPtr ptr = set.lookupForAdd(l); | AddPtr ptr = set.lookupForAdd(l); | ||||
if (needsBarrier && ptr && entryNeedsSweep(*ptr)) { | if (needsBarrier && ptr && entryNeedsSweep(*ptr)) { | ||||
const_cast<Set&>(set).remove(ptr); | const_cast<Set&>(set).remove(ptr); | ||||
return set.lookupForAdd(l); | return set.lookupForAdd(l); | ||||
} | } | ||||
return ptr; | return ptr; | ||||
} | } | ||||
Show All 15 Lines | uint32_t count() const { | ||||
return set.count(); | return set.count(); | ||||
} | } | ||||
size_t capacity() const { return set.capacity(); } | size_t capacity() const { return set.capacity(); } | ||||
bool has(const Lookup& l) const { return lookup(l).found(); } | bool has(const Lookup& l) const { return lookup(l).found(); } | ||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | ||||
return set.sizeOfExcludingThis(mallocSizeOf); | return set.shallowSizeOfExcludingThis(mallocSizeOf); | ||||
} | } | ||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | ||||
return mallocSizeOf(this) + set.sizeOfExcludingThis(mallocSizeOf); | return mallocSizeOf(this) + set.shallowSizeOfExcludingThis(mallocSizeOf); | ||||
} | |||||
bool init(uint32_t len = 16) { | |||||
MOZ_ASSERT(!needsBarrier); | |||||
return set.init(len); | |||||
} | } | ||||
void clear() { | void clear() { | ||||
// This operation is not currently allowed while barriers are in place | // This operation is not currently allowed while barriers are in place | ||||
// since it doesn't make sense to clear a cache while it is being swept. | // since it doesn't make sense to clear a cache while it is being swept. | ||||
MOZ_ASSERT(!needsBarrier); | MOZ_ASSERT(!needsBarrier); | ||||
set.clear(); | set.clear(); | ||||
} | } | ||||
void finish() { | void clearAndCompact() { | ||||
// This operation is not currently allowed while barriers are in place | // This operation is not currently allowed while barriers are in place | ||||
// since it doesn't make sense to destroy a cache while it is being swept. | // since it doesn't make sense to clear a cache while it is being swept. | ||||
MOZ_ASSERT(!needsBarrier); | MOZ_ASSERT(!needsBarrier); | ||||
set.finish(); | set.clearAndCompact(); | ||||
} | } | ||||
void remove(Ptr p) { | void remove(Ptr p) { | ||||
// This currently supports removing entries during incremental | // This currently supports removing entries during incremental | ||||
// sweeping. If we allow these tables to be swept incrementally this may | // sweeping. If we allow these tables to be swept incrementally this may | ||||
// no longer be possible. | // no longer be possible. | ||||
set.remove(p); | set.remove(p); | ||||
} | } | ||||
void remove(const Lookup& l) { | void remove(const Lookup& l) { | ||||
Ptr p = lookup(l); | Ptr p = lookup(l); | ||||
if (p) remove(p); | if (p) { | ||||
remove(p); | |||||
} | |||||
} | } | ||||
template <typename TInput> | template <typename TInput> | ||||
bool add(AddPtr& p, TInput&& t) { | bool add(AddPtr& p, TInput&& t) { | ||||
return set.add(p, mozilla::Forward<TInput>(t)); | return set.add(p, std::forward<TInput>(t)); | ||||
} | } | ||||
template <typename TInput> | template <typename TInput> | ||||
bool relookupOrAdd(AddPtr& p, const Lookup& l, TInput&& t) { | bool relookupOrAdd(AddPtr& p, const Lookup& l, TInput&& t) { | ||||
return set.relookupOrAdd(p, l, mozilla::Forward<TInput>(t)); | return set.relookupOrAdd(p, l, std::forward<TInput>(t)); | ||||
} | } | ||||
template <typename TInput> | template <typename TInput> | ||||
bool put(TInput&& t) { | bool put(TInput&& t) { | ||||
return set.put(mozilla::Forward<TInput>(t)); | return set.put(std::forward<TInput>(t)); | ||||
} | } | ||||
template <typename TInput> | template <typename TInput> | ||||
bool putNew(TInput&& t) { | bool putNew(TInput&& t) { | ||||
return set.putNew(mozilla::Forward<TInput>(t)); | return set.putNew(std::forward<TInput>(t)); | ||||
} | } | ||||
template <typename TInput> | template <typename TInput> | ||||
bool putNew(const Lookup& l, TInput&& t) { | bool putNew(const Lookup& l, TInput&& t) { | ||||
return set.putNew(l, mozilla::Forward<TInput>(t)); | return set.putNew(l, std::forward<TInput>(t)); | ||||
} | } | ||||
}; | } JS_HAZ_NON_GC_POINTER; | ||||
} // namespace JS | } // namespace JS | ||||
#endif /* GCHashTable_h */ | #endif /* GCHashTable_h */ |
Wildfire Games · Phabricator