Changeset View
Changeset View
Standalone View
Standalone View
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: 4 -*- | ||||
* vim: set ts=8 sts=4 et sw=4 tw=99: | * vim: set ts=8 sts=4 et sw=4 tw=99: | ||||
* 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 "js/GCPolicyAPI.h" | |||||
#include "js/HashTable.h" | #include "js/HashTable.h" | ||||
#include "js/RootingAPI.h" | #include "js/RootingAPI.h" | ||||
#include "js/SweepingAPI.h" | |||||
#include "js/TracingAPI.h" | #include "js/TracingAPI.h" | ||||
namespace js { | namespace JS { | ||||
// Define a reasonable default GC policy for GC-aware Maps. | // Define a reasonable default GC policy for GC-aware Maps. | ||||
template <typename Key, typename Value> | template <typename Key, typename Value> | ||||
struct DefaultMapGCPolicy { | struct DefaultMapSweepPolicy { | ||||
using KeyPolicy = DefaultGCPolicy<Key>; | |||||
using ValuePolicy = DefaultGCPolicy<Value>; | |||||
static bool needsSweep(Key* key, Value* value) { | static bool needsSweep(Key* key, Value* value) { | ||||
return KeyPolicy::needsSweep(key) || ValuePolicy::needsSweep(value); | return GCPolicy<Key>::needsSweep(key) || GCPolicy<Value>::needsSweep(value); | ||||
} | } | ||||
}; | }; | ||||
// A GCHashMap is a GC-aware HashMap, meaning that it has additional trace and | // A GCHashMap is a GC-aware HashMap, meaning that it has additional trace and | ||||
// sweep methods that know how to visit all keys and values in the table. | // sweep methods that know how to visit all keys and values in the table. | ||||
// HashMaps that contain GC pointers will generally want to use this GCHashMap | // HashMaps that contain GC pointers will generally want to use this GCHashMap | ||||
// specialization in lieu of HashMap, either because those pointers must be | // specialization instead of HashMap, because this conveniently supports tracing | ||||
// traced to be kept alive -- in which case, KeyPolicy and/or ValuePolicy | // keys and values, and cleaning up weak entries. | ||||
// should do the appropriate tracing -- or because those pointers are weak and | |||||
// must be swept during a GC -- in which case needsSweep should be set | |||||
// appropriately. | |||||
// | // | ||||
// Most types of GC pointers as keys and values can be traced with no extra | // GCHashMap::trace applies GCPolicy<T>::trace to each entry's key and value. | ||||
// infrastructure. For structs, the DefaultGCPolicy<T> will call a trace() | // Most types of GC pointers already have appropriate specializations of | ||||
// method on the struct. For other structs and non-gc-pointer members, ensure | // GCPolicy, so they should just work as keys and values. Any struct type with a | ||||
// that there is a specialization of DefaultGCPolicy<T> with an appropriate | // default constructor and trace and sweep functions should work as well. If you | ||||
// trace() static method available to handle the custom type. Generic helpers | // need to define your own GCPolicy specialization, generic helpers can be found | ||||
// can be found in js/public/TracingAPI.h. | // in js/public/TracingAPI.h. | ||||
// | // | ||||
// Note that this HashMap only knows *how* to trace and sweep (and the tracing | // The MapSweepPolicy template parameter controls how the table drops entries | ||||
// can handle keys that move), but it does not itself cause tracing or sweeping | // when swept. GCHashMap::sweep applies MapSweepPolicy::needsSweep to each table | ||||
// to be invoked. For tracing, it must be used with Rooted or PersistentRooted, | // entry; if it returns true, the entry is dropped. The default MapSweepPolicy | ||||
// or barriered and traced manually. For sweeping, currently it requires an | // drops the entry if either the key or value is about to be finalized, | ||||
// explicit call to <map>.sweep(). | // according to its GCPolicy<T>::needsSweep method. (This default is almost | ||||
// always fine: it's hard to imagine keeping such an entry around anyway.) | |||||
// | // | ||||
// Note that this HashMap only knows *how* to trace and sweep, but it does not | |||||
// itself cause tracing or sweeping to be invoked. For tracing, it must be used | |||||
// with Rooted or PersistentRooted, or barriered and traced manually. For | |||||
// sweeping, currently it requires an explicit call to <map>.sweep(). | |||||
template <typename Key, | template <typename Key, | ||||
typename Value, | typename Value, | ||||
typename HashPolicy = DefaultHasher<Key>, | typename HashPolicy = js::DefaultHasher<Key>, | ||||
typename AllocPolicy = TempAllocPolicy, | typename AllocPolicy = js::TempAllocPolicy, | ||||
typename GCPolicy = DefaultMapGCPolicy<Key, Value>> | typename MapSweepPolicy = DefaultMapSweepPolicy<Key, Value>> | ||||
class GCHashMap : public HashMap<Key, Value, HashPolicy, AllocPolicy>, | class GCHashMap : public js::HashMap<Key, Value, HashPolicy, AllocPolicy> | ||||
public JS::Traceable | |||||
{ | { | ||||
using Base = 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) {} | ||||
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()) | if (!this->initialized()) | ||||
return; | return; | ||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | ||||
GCPolicy::ValuePolicy::trace(trc, &e.front().value(), "hashmap value"); | GCPolicy<Value>::trace(trc, &e.front().value(), "hashmap value"); | ||||
GCPolicy::KeyPolicy::trace(trc, &e.front().mutableKey(), "hashmap key"); | GCPolicy<Key>::trace(trc, &e.front().mutableKey(), "hashmap key"); | ||||
} | } | ||||
} | } | ||||
void sweep() { | void sweep() { | ||||
if (!this->initialized()) | if (!this->initialized()) | ||||
return; | return; | ||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | ||||
if (GCPolicy::needsSweep(&e.front().mutableKey(), &e.front().value())) | if (MapSweepPolicy::needsSweep(&e.front().mutableKey(), &e.front().value())) | ||||
e.removeFront(); | e.removeFront(); | ||||
} | } | ||||
} | } | ||||
// GCHashMap is movable | // GCHashMap is movable | ||||
GCHashMap(GCHashMap&& rhs) : Base(mozilla::Forward<GCHashMap>(rhs)) {} | GCHashMap(GCHashMap&& rhs) : Base(mozilla::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::Forward<GCHashMap>(rhs)); | Base::operator=(mozilla::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; | ||||
}; | }; | ||||
} // namespace JS | |||||
namespace js { | |||||
// HashMap that supports rekeying. | |||||
// | |||||
// If your keys are pointers to something like JSObject that can be tenured or | |||||
// compacted, prefer to use GCHashMap with MovableCellHasher, which takes | |||||
// advantage of the Zone's stable id table to make rekeying unnecessary. | |||||
template <typename Key, | |||||
typename Value, | |||||
typename HashPolicy = DefaultHasher<Key>, | |||||
typename AllocPolicy = TempAllocPolicy, | |||||
typename MapSweepPolicy = JS::DefaultMapSweepPolicy<Key, Value>> | |||||
class GCRekeyableHashMap : public JS::GCHashMap<Key, Value, HashPolicy, AllocPolicy, MapSweepPolicy> | |||||
{ | |||||
using Base = JS::GCHashMap<Key, Value, HashPolicy, AllocPolicy>; | |||||
public: | |||||
explicit GCRekeyableHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {} | |||||
void sweep() { | |||||
if (!this->initialized()) | |||||
return; | |||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | |||||
Key key(e.front().key()); | |||||
if (MapSweepPolicy::needsSweep(&key, &e.front().value())) | |||||
e.removeFront(); | |||||
else if (!HashPolicy::match(key, e.front().key())) | |||||
e.rekeyFront(key); | |||||
} | |||||
} | |||||
// GCRekeyableHashMap is movable | |||||
GCRekeyableHashMap(GCRekeyableHashMap&& rhs) : Base(mozilla::Move(rhs)) {} | |||||
void operator=(GCRekeyableHashMap&& rhs) { | |||||
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited"); | |||||
Base::operator=(mozilla::Move(rhs)); | |||||
} | |||||
}; | |||||
template <typename Outer, typename... Args> | template <typename Outer, typename... Args> | ||||
class GCHashMapOperations | class GCHashMapOperations | ||||
{ | { | ||||
using Map = GCHashMap<Args...>; | using Map = JS::GCHashMap<Args...>; | ||||
using Lookup = typename Map::Lookup; | using Lookup = typename Map::Lookup; | ||||
using Ptr = typename Map::Ptr; | |||||
using AddPtr = typename Map::AddPtr; | |||||
using Range = typename Map::Range; | |||||
using Enum = typename Map::Enum; | |||||
const Map& map() const { return static_cast<const Outer*>(this)->get(); } | const Map& map() const { return static_cast<const Outer*>(this)->get(); } | ||||
public: | public: | ||||
using AddPtr = typename Map::AddPtr; | |||||
using Ptr = typename Map::Ptr; | |||||
using Range = typename Map::Range; | |||||
bool initialized() const { return map().initialized(); } | 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); } | 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 { | |||||
return map().sizeOfExcludingThis(mallocSizeOf); | |||||
} | |||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | |||||
return mallocSizeOf(this) + map().sizeOfExcludingThis(mallocSizeOf); | |||||
} | |||||
}; | }; | ||||
template <typename Outer, typename... Args> | template <typename Outer, typename... Args> | ||||
class MutableGCHashMapOperations | class MutableGCHashMapOperations | ||||
: public GCHashMapOperations<Outer, Args...> | : public GCHashMapOperations<Outer, Args...> | ||||
{ | { | ||||
using Map = GCHashMap<Args...>; | using Map = JS::GCHashMap<Args...>; | ||||
using Lookup = typename Map::Lookup; | using Lookup = typename Map::Lookup; | ||||
using Ptr = typename Map::Ptr; | |||||
using AddPtr = typename Map::AddPtr; | |||||
using Range = typename Map::Range; | |||||
using Enum = typename Map::Enum; | |||||
Map& map() { return static_cast<Outer*>(this)->get(); } | Map& map() { return static_cast<Outer*>(this)->get(); } | ||||
public: | public: | ||||
using AddPtr = typename Map::AddPtr; | |||||
struct Enum : public Map::Enum { explicit Enum(Outer& o) : Map::Enum(o.map()) {} }; | |||||
using Ptr = typename Map::Ptr; | |||||
using Range = typename Map::Range; | |||||
bool init(uint32_t len = 16) { return map().init(len); } | bool init(uint32_t len = 16) { return map().init(len); } | ||||
void clear() { map().clear(); } | void clear() { map().clear(); } | ||||
void finish() { map().finish(); } | void finish() { map().finish(); } | ||||
void remove(Ptr p) { map().remove(p); } | void remove(Ptr p) { map().remove(p); } | ||||
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), mozilla::Forward<ValueInput>(v)); | return map().add(p, mozilla::Forward<KeyInput>(k), mozilla::Forward<ValueInput>(v)); | ||||
Show All 18 Lines | public: | ||||
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), mozilla::Forward<ValueInput>(v)); | return map().putNew(mozilla::Forward<KeyInput>(k), mozilla::Forward<ValueInput>(v)); | ||||
} | } | ||||
}; | }; | ||||
template <typename A, typename B, typename C, typename D, typename E> | template <typename A, typename B, typename C, typename D, typename E> | ||||
class RootedBase<GCHashMap<A,B,C,D,E>> | class RootedBase<JS::GCHashMap<A,B,C,D,E>> | ||||
: public MutableGCHashMapOperations<JS::Rooted<GCHashMap<A,B,C,D,E>>, A,B,C,D,E> | : public MutableGCHashMapOperations<JS::Rooted<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E> | ||||
{}; | |||||
template <typename A, typename B, typename C, typename D, typename E> | |||||
class MutableHandleBase<JS::GCHashMap<A,B,C,D,E>> | |||||
: public MutableGCHashMapOperations<JS::MutableHandle<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E> | |||||
{}; | {}; | ||||
template <typename A, typename B, typename C, typename D, typename E> | template <typename A, typename B, typename C, typename D, typename E> | ||||
class MutableHandleBase<GCHashMap<A,B,C,D,E>> | class HandleBase<JS::GCHashMap<A,B,C,D,E>> | ||||
: public MutableGCHashMapOperations<JS::MutableHandle<GCHashMap<A,B,C,D,E>>, A,B,C,D,E> | : public GCHashMapOperations<JS::Handle<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E> | ||||
{}; | {}; | ||||
template <typename A, typename B, typename C, typename D, typename E> | template <typename A, typename B, typename C, typename D, typename E> | ||||
class HandleBase<GCHashMap<A,B,C,D,E>> | class WeakCacheBase<JS::GCHashMap<A,B,C,D,E>> | ||||
: public GCHashMapOperations<JS::Handle<GCHashMap<A,B,C,D,E>>, A,B,C,D,E> | : public MutableGCHashMapOperations<JS::WeakCache<JS::GCHashMap<A,B,C,D,E>>, A,B,C,D,E> | ||||
{}; | {}; | ||||
} // 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 | ||||
// be traced to be kept alive will generally want to use this GCHashSet | // be traced to be kept alive will generally want to use this GCHashSet | ||||
// specializeation in lieu of HashSet. | // specialization in lieu of HashSet. | ||||
// | // | ||||
// Most types of GC pointers can be traced with no extra infrastructure. For | // Most types of GC pointers can be traced with no extra infrastructure. For | ||||
// structs and non-gc-pointer members, ensure that there is a specialization of | // structs and non-gc-pointer members, ensure that there is a specialization of | ||||
// DefaultGCPolicy<T> with an appropriate trace method available to handle the | // GCPolicy<T> with an appropriate trace method available to handle the custom | ||||
// custom type. Generic helpers can be found in js/public/TracingAPI.h. | // type. Generic helpers can be found in js/public/TracingAPI.h. | ||||
// | // | ||||
// Note that although this HashSet's trace will deal correctly with moved | // Note that although this HashSet's trace will deal correctly with moved | ||||
// elements, it does not itself know when to barrier or trace elements. To | // elements, it does not itself know when to barrier or trace elements. To | ||||
// function properly it must either be used with Rooted or barriered and traced | // function properly it must either be used with Rooted or barriered and traced | ||||
// manually. | // manually. | ||||
template <typename T, | template <typename T, | ||||
typename HashPolicy = DefaultHasher<T>, | typename HashPolicy = js::DefaultHasher<T>, | ||||
typename AllocPolicy = TempAllocPolicy, | typename AllocPolicy = js::TempAllocPolicy> | ||||
typename GCPolicy = DefaultGCPolicy<T>> | class GCHashSet : public js::HashSet<T, HashPolicy, AllocPolicy> | ||||
class GCHashSet : public HashSet<T, HashPolicy, AllocPolicy>, | |||||
public JS::Traceable | |||||
{ | { | ||||
using Base = 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) {} | ||||
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()) | if (!this->initialized()) | ||||
return; | return; | ||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) | for (typename Base::Enum e(*this); !e.empty(); e.popFront()) | ||||
GCPolicy::trace(trc, &e.mutableFront(), "hashset element"); | GCPolicy<T>::trace(trc, &e.mutableFront(), "hashset element"); | ||||
} | } | ||||
void sweep() { | void sweep() { | ||||
if (!this->initialized()) | if (!this->initialized()) | ||||
return; | return; | ||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | for (typename Base::Enum e(*this); !e.empty(); e.popFront()) { | ||||
if (GCPolicy::needsSweep(&e.mutableFront())) | if (GCPolicy<T>::needsSweep(&e.mutableFront())) | ||||
e.removeFront(); | e.removeFront(); | ||||
} | } | ||||
} | } | ||||
// GCHashSet is movable | // GCHashSet is movable | ||||
GCHashSet(GCHashSet&& rhs) : Base(mozilla::Forward<GCHashSet>(rhs)) {} | GCHashSet(GCHashSet&& rhs) : Base(mozilla::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::Forward<GCHashSet>(rhs)); | Base::operator=(mozilla::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; | ||||
}; | }; | ||||
} // namespace JS | |||||
namespace js { | |||||
template <typename Outer, typename... Args> | template <typename Outer, typename... Args> | ||||
class GCHashSetOperations | class GCHashSetOperations | ||||
{ | { | ||||
using Set = GCHashSet<Args...>; | using Set = JS::GCHashSet<Args...>; | ||||
using Lookup = typename Set::Lookup; | using Lookup = typename Set::Lookup; | ||||
using Ptr = typename Set::Ptr; | |||||
using AddPtr = typename Set::AddPtr; | |||||
using Range = typename Set::Range; | |||||
using Enum = typename Set::Enum; | |||||
const Set& set() const { return static_cast<const Outer*>(this)->extract(); } | const Set& set() const { return static_cast<const Outer*>(this)->get(); } | ||||
public: | public: | ||||
using AddPtr = typename Set::AddPtr; | |||||
using Entry = typename Set::Entry; | |||||
using Ptr = typename Set::Ptr; | |||||
using Range = typename Set::Range; | |||||
bool initialized() const { return set().initialized(); } | 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); } | 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 { | |||||
return set().sizeOfExcludingThis(mallocSizeOf); | |||||
} | |||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { | |||||
return mallocSizeOf(this) + set().sizeOfExcludingThis(mallocSizeOf); | |||||
} | |||||
}; | }; | ||||
template <typename Outer, typename... Args> | template <typename Outer, typename... Args> | ||||
class MutableGCHashSetOperations | class MutableGCHashSetOperations | ||||
: public GCHashSetOperations<Outer, Args...> | : public GCHashSetOperations<Outer, Args...> | ||||
{ | { | ||||
using Set = GCHashSet<Args...>; | using Set = JS::GCHashSet<Args...>; | ||||
using Lookup = typename Set::Lookup; | using Lookup = typename Set::Lookup; | ||||
using Ptr = typename Set::Ptr; | |||||
using AddPtr = typename Set::AddPtr; | |||||
using Range = typename Set::Range; | |||||
using Enum = typename Set::Enum; | |||||
Set& set() { return static_cast<Outer*>(this)->extract(); } | Set& set() { return static_cast<Outer*>(this)->get(); } | ||||
public: | public: | ||||
using AddPtr = typename Set::AddPtr; | |||||
using Entry = typename Set::Entry; | |||||
struct Enum : public Set::Enum { explicit Enum(Outer& o) : Set::Enum(o.set()) {} }; | |||||
using Ptr = typename Set::Ptr; | |||||
using Range = typename Set::Range; | |||||
bool init(uint32_t len = 16) { return set().init(len); } | bool init(uint32_t len = 16) { return set().init(len); } | ||||
void clear() { set().clear(); } | void clear() { set().clear(); } | ||||
void finish() { set().finish(); } | void finish() { set().finish(); } | ||||
void remove(Ptr p) { set().remove(p); } | |||||
void remove(const Lookup& l) { set().remove(l); } | void remove(const Lookup& l) { set().remove(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, mozilla::Forward<TInput>(t)); | ||||
} | } | ||||
template<typename TInput> | template<typename TInput> | ||||
Show All 12 Lines | public: | ||||
} | } | ||||
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, mozilla::Forward<TInput>(t)); | ||||
} | } | ||||
}; | }; | ||||
template <typename T, typename HP, typename AP, typename GP> | template <typename T, typename HP, typename AP> | ||||
class RootedBase<GCHashSet<T, HP, AP, GP>> | class RootedBase<JS::GCHashSet<T, HP, AP>> | ||||
: public MutableGCHashSetOperations<JS::Rooted<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP> | : public MutableGCHashSetOperations<JS::Rooted<JS::GCHashSet<T, HP, AP>>, T, HP, AP> | ||||
{ | { | ||||
using Set = GCHashSet<T, HP, AP, GP>; | |||||
friend class GCHashSetOperations<JS::Rooted<Set>, T, HP, AP, GP>; | |||||
const Set& extract() const { return *static_cast<const JS::Rooted<Set>*>(this)->address(); } | |||||
friend class MutableGCHashSetOperations<JS::Rooted<Set>, T, HP, AP, GP>; | |||||
Set& extract() { return *static_cast<JS::Rooted<Set>*>(this)->address(); } | |||||
}; | }; | ||||
template <typename T, typename HP, typename AP, typename GP> | template <typename T, typename HP, typename AP> | ||||
class MutableHandleBase<GCHashSet<T, HP, AP, GP>> | class MutableHandleBase<JS::GCHashSet<T, HP, AP>> | ||||
: public MutableGCHashSetOperations<JS::MutableHandle<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP> | : public MutableGCHashSetOperations<JS::MutableHandle<JS::GCHashSet<T, HP, AP>>, T, HP, AP> | ||||
{ | { | ||||
using Set = GCHashSet<T, HP, AP, GP>; | }; | ||||
friend class GCHashSetOperations<JS::MutableHandle<Set>, T, HP, AP, GP>; | |||||
const Set& extract() const { | |||||
return *static_cast<const JS::MutableHandle<Set>*>(this)->address(); | |||||
} | |||||
friend class MutableGCHashSetOperations<JS::MutableHandle<Set>, T, HP, AP, GP>; | template <typename T, typename HP, typename AP> | ||||
Set& extract() { return *static_cast<JS::MutableHandle<Set>*>(this)->address(); } | class HandleBase<JS::GCHashSet<T, HP, AP>> | ||||
: public GCHashSetOperations<JS::Handle<JS::GCHashSet<T, HP, AP>>, T, HP, AP> | |||||
{ | |||||
}; | }; | ||||
template <typename T, typename HP, typename AP, typename GP> | template <typename T, typename HP, typename AP> | ||||
class HandleBase<GCHashSet<T, HP, AP, GP>> | class WeakCacheBase<JS::GCHashSet<T, HP, AP>> | ||||
: public GCHashSetOperations<JS::Handle<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP> | : public MutableGCHashSetOperations<JS::WeakCache<JS::GCHashSet<T, HP, AP>>, T, HP, AP> | ||||
{ | { | ||||
using Set = GCHashSet<T, HP, AP, GP>; | |||||
friend class GCHashSetOperations<JS::Handle<Set>, T, HP, AP, GP>; | |||||
const Set& extract() const { return *static_cast<const JS::Handle<Set>*>(this)->address(); } | |||||
}; | }; | ||||
} /* namespace js */ | } /* namespace js */ | ||||
#endif /* GCHashTable_h */ | #endif /* GCHashTable_h */ |
Wildfire Games · Phabricator