Bug 1325406 - Refactor rooting base class templates r=sfink r=mccr8

This commit is contained in:
Jon Coppeard 2017-01-10 10:12:14 +00:00
parent cb3a0e0f43
commit ca898ea355
24 changed files with 239 additions and 512 deletions

View File

@ -51,21 +51,12 @@ struct GCPolicy<mozilla::OwningNonNull<T>>
} // namespace JS
namespace js {
template<typename T>
struct RootedBase<mozilla::OwningNonNull<T>>
template<typename T, typename Wrapper>
struct WrappedPtrOperations<mozilla::OwningNonNull<T>, Wrapper>
{
typedef mozilla::OwningNonNull<T> SmartPtrType;
operator SmartPtrType& () const
{
auto& self = *static_cast<const JS::Rooted<SmartPtrType>*>(this);
return self.get();
}
operator T& () const
{
auto& self = *static_cast<const JS::Rooted<SmartPtrType>*>(this);
return self.get();
return static_cast<const Wrapper*>(this)->get();
}
};
} // namespace js

View File

@ -39,19 +39,12 @@ struct GCPolicy<RefPtr<T>>
} // namespace JS
namespace js {
template<typename T>
struct RootedBase<RefPtr<T>>
template<typename T, typename Wrapper>
struct WrappedPtrOperations<RefPtr<T>, Wrapper>
{
operator RefPtr<T>& () const
{
auto& self = *static_cast<const JS::Rooted<RefPtr<T>>*>(this);
return self.get();
}
operator T*() const
{
auto& self = *static_cast<const JS::Rooted<RefPtr<T>>*>(this);
return self.get();
return static_cast<const Wrapper*>(this)->get();
}
};
} // namespace js

View File

@ -127,15 +127,15 @@ struct IsHeapConstructibleType<nsXBLMaybeCompiled<T>>
static constexpr bool value = true;
};
template <class UncompiledT>
class HeapBase<nsXBLMaybeCompiled<UncompiledT>>
template <class UncompiledT, class Wrapper>
class HeapBase<nsXBLMaybeCompiled<UncompiledT>, Wrapper>
{
const JS::Heap<nsXBLMaybeCompiled<UncompiledT>>& wrapper() const {
return *static_cast<const JS::Heap<nsXBLMaybeCompiled<UncompiledT>>*>(this);
const Wrapper& wrapper() const {
return *static_cast<const Wrapper*>(this);
}
JS::Heap<nsXBLMaybeCompiled<UncompiledT>>& wrapper() {
return *static_cast<JS::Heap<nsXBLMaybeCompiled<UncompiledT>>*>(this);
Wrapper& wrapper() {
return *static_cast<Wrapper*>(this);
}
const nsXBLMaybeCompiled<UncompiledT>* extract() const {

View File

@ -134,13 +134,13 @@ class GCRekeyableHashMap : public JS::GCHashMap<Key, Value, HashPolicy, AllocPol
}
};
template <typename Outer, typename... Args>
class GCHashMapOperations
template <typename Wrapper, typename... Args>
class WrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper>
{
using Map = JS::GCHashMap<Args...>;
using Lookup = typename Map::Lookup;
const Map& map() const { return static_cast<const Outer*>(this)->get(); }
const Map& map() const { return static_cast<const Wrapper*>(this)->get(); }
public:
using AddPtr = typename Map::AddPtr;
@ -163,18 +163,18 @@ class GCHashMapOperations
}
};
template <typename Outer, typename... Args>
class MutableGCHashMapOperations
: public GCHashMapOperations<Outer, Args...>
template <typename Wrapper, typename... Args>
class MutableWrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper>
: public WrappedPtrOperations<JS::GCHashMap<Args...>, Wrapper>
{
using Map = JS::GCHashMap<Args...>;
using Lookup = typename Map::Lookup;
Map& map() { return static_cast<Outer*>(this)->get(); }
Map& map() { return static_cast<Wrapper*>(this)->get(); }
public:
using AddPtr = typename Map::AddPtr;
struct Enum : public Map::Enum { explicit Enum(Outer& o) : Map::Enum(o.map()) {} };
struct Enum : public Map::Enum { explicit Enum(Wrapper& o) : Map::Enum(o.map()) {} };
using Ptr = typename Map::Ptr;
using Range = typename Map::Range;
@ -211,26 +211,6 @@ class MutableGCHashMapOperations
}
};
template <typename A, typename B, typename C, typename D, typename E>
class RootedBase<JS::GCHashMap<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>
class HandleBase<JS::GCHashMap<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>
class WeakCacheBase<JS::GCHashMap<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 {
@ -292,13 +272,13 @@ class GCHashSet : public js::HashSet<T, HashPolicy, AllocPolicy>
namespace js {
template <typename Outer, typename... Args>
class GCHashSetOperations
template <typename Wrapper, typename... Args>
class WrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper>
{
using Set = JS::GCHashSet<Args...>;
using Lookup = typename Set::Lookup;
const Set& set() const { return static_cast<const Outer*>(this)->get(); }
const Set& set() const { return static_cast<const Wrapper*>(this)->get(); }
public:
using AddPtr = typename Set::AddPtr;
@ -322,19 +302,19 @@ class GCHashSetOperations
}
};
template <typename Outer, typename... Args>
class MutableGCHashSetOperations
: public GCHashSetOperations<Outer, Args...>
template <typename Wrapper, typename... Args>
class MutableWrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper>
: public WrappedPtrOperations<JS::GCHashSet<Args...>, Wrapper>
{
using Set = JS::GCHashSet<Args...>;
using Lookup = typename Set::Lookup;
Set& set() { return static_cast<Outer*>(this)->get(); }
Set& set() { return static_cast<Wrapper*>(this)->get(); }
public:
using AddPtr = typename Set::AddPtr;
using Entry = typename Set::Entry;
struct Enum : public Set::Enum { explicit Enum(Outer& o) : Set::Enum(o.set()) {} };
struct Enum : public Set::Enum { explicit Enum(Wrapper& o) : Set::Enum(o.set()) {} };
using Ptr = typename Set::Ptr;
using Range = typename Set::Range;
@ -370,30 +350,6 @@ class MutableGCHashSetOperations
}
};
template <typename T, typename HP, typename AP>
class RootedBase<JS::GCHashSet<T, HP, AP>>
: public MutableGCHashSetOperations<JS::Rooted<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
{
};
template <typename T, typename HP, typename AP>
class MutableHandleBase<JS::GCHashSet<T, HP, AP>>
: public MutableGCHashSetOperations<JS::MutableHandle<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
{
};
template <typename T, typename HP, typename AP>
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>
class WeakCacheBase<JS::GCHashSet<T, HP, AP>>
: public MutableGCHashSetOperations<JS::WeakCache<JS::GCHashSet<T, HP, AP>>, T, HP, AP>
{
};
} /* namespace js */
#endif /* GCHashTable_h */

View File

@ -124,13 +124,13 @@ struct GCPolicy<mozilla::Variant<Ts...>>
namespace js {
template <typename Outer, typename... Ts>
class GCVariantOperations
template <typename Wrapper, typename... Ts>
class WrappedPtrOperations<mozilla::Variant<Ts...>, Wrapper>
{
using Impl = JS::detail::GCVariantImplementation<Ts...>;
using Variant = mozilla::Variant<Ts...>;
const Variant& variant() const { return static_cast<const Outer*>(this)->get(); }
const Variant& variant() const { return static_cast<const Wrapper*>(this)->get(); }
public:
template <typename T>
@ -150,15 +150,15 @@ class GCVariantOperations
}
};
template <typename Outer, typename... Ts>
class MutableGCVariantOperations
: public GCVariantOperations<Outer, Ts...>
template <typename Wrapper, typename... Ts>
class MutableWrappedPtrOperations<mozilla::Variant<Ts...>, Wrapper>
: public WrappedPtrOperations<mozilla::Variant<Ts...>, Wrapper>
{
using Impl = JS::detail::GCVariantImplementation<Ts...>;
using Variant = mozilla::Variant<Ts...>;
const Variant& variant() const { return static_cast<const Outer*>(this)->get(); }
Variant& variant() { return static_cast<Outer*>(this)->get(); }
const Variant& variant() const { return static_cast<const Wrapper*>(this)->get(); }
Variant& variant() { return static_cast<Wrapper*>(this)->get(); }
public:
template <typename T>
@ -173,26 +173,6 @@ class MutableGCVariantOperations
}
};
template <typename... Ts>
class RootedBase<mozilla::Variant<Ts...>>
: public MutableGCVariantOperations<JS::Rooted<mozilla::Variant<Ts...>>, Ts...>
{ };
template <typename... Ts>
class MutableHandleBase<mozilla::Variant<Ts...>>
: public MutableGCVariantOperations<JS::MutableHandle<mozilla::Variant<Ts...>>, Ts...>
{ };
template <typename... Ts>
class HandleBase<mozilla::Variant<Ts...>>
: public GCVariantOperations<JS::Handle<mozilla::Variant<Ts...>>, Ts...>
{ };
template <typename... Ts>
class PersistentRootedBase<mozilla::Variant<Ts...>>
: public MutableGCVariantOperations<JS::PersistentRooted<mozilla::Variant<Ts...>>, Ts...>
{ };
} // namespace js
#endif // js_GCVariant_h

View File

@ -135,11 +135,11 @@ class GCVector
namespace js {
template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
class GCVectorOperations
template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
class WrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper>
{
using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
const Vec& vec() const { return static_cast<const Wrapper*>(this)->get(); }
public:
const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
@ -155,13 +155,13 @@ class GCVectorOperations
}
};
template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
class MutableGCVectorOperations
: public GCVectorOperations<Outer, T, Capacity, AllocPolicy>
template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
class MutableWrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper>
: public WrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper>
{
using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
Vec& vec() { return static_cast<Outer*>(this)->get(); }
const Vec& vec() const { return static_cast<const Wrapper*>(this)->get(); }
Vec& vec() { return static_cast<Wrapper*>(this)->get(); }
public:
const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
@ -224,26 +224,6 @@ class MutableGCVectorOperations
void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); }
};
template <typename T, size_t N, typename AP>
class RootedBase<JS::GCVector<T,N,AP>>
: public MutableGCVectorOperations<JS::Rooted<JS::GCVector<T,N,AP>>, T,N,AP>
{};
template <typename T, size_t N, typename AP>
class MutableHandleBase<JS::GCVector<T,N,AP>>
: public MutableGCVectorOperations<JS::MutableHandle<JS::GCVector<T,N,AP>>, T,N,AP>
{};
template <typename T, size_t N, typename AP>
class HandleBase<JS::GCVector<T,N,AP>>
: public GCVectorOperations<JS::Handle<JS::GCVector<T,N,AP>>, T,N,AP>
{};
template <typename T, size_t N, typename AP>
class PersistentRootedBase<JS::GCVector<T,N,AP>>
: public MutableGCVectorOperations<JS::PersistentRooted<JS::GCVector<T,N,AP>>, T,N,AP>
{};
} // namespace js
#endif // js_GCVector_h

View File

@ -113,17 +113,23 @@ template <typename T>
struct BarrierMethods {
};
template <typename T>
class RootedBase {};
template <typename Element, typename Wrapper>
class WrappedPtrOperations {};
template <typename T>
class HandleBase {};
template <typename Element, typename Wrapper>
class MutableWrappedPtrOperations : public WrappedPtrOperations<Element, Wrapper> {};
template <typename T>
class MutableHandleBase {};
template <typename T, typename Wrapper>
class RootedBase : public MutableWrappedPtrOperations<T, Wrapper> {};
template <typename T>
class HeapBase {};
template <typename T, typename Wrapper>
class HandleBase : public WrappedPtrOperations<T, Wrapper> {};
template <typename T, typename Wrapper>
class MutableHandleBase : public MutableWrappedPtrOperations<T, Wrapper> {};
template <typename T, typename Wrapper>
class HeapBase : public MutableWrappedPtrOperations<T, Wrapper> {};
// Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many macros into scope
template <typename T> struct IsHeapConstructibleType { static constexpr bool value = false; };
@ -133,8 +139,8 @@ FOR_EACH_PUBLIC_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
#undef DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE
template <typename T>
class PersistentRootedBase {};
template <typename T, typename Wrapper>
class PersistentRootedBase : public MutableWrappedPtrOperations<T, Wrapper> {};
static void* const ConstNullValue = nullptr;
@ -223,7 +229,7 @@ AssertGCThingIsNotAnObjectSubclass(js::gc::Cell* cell) {}
* Type T must be a public GC pointer type.
*/
template <typename T>
class Heap : public js::HeapBase<T>
class Heap : public js::HeapBase<T, Heap<T>>
{
// Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for legacy reasons.
static_assert(js::IsHeapConstructibleType<T>::value,
@ -362,7 +368,7 @@ ScriptIsMarkedGray(const Heap<JSScript*>& script)
* - It is not possible to store flag bits in a Heap<T>.
*/
template <typename T>
class TenuredHeap : public js::HeapBase<T>
class TenuredHeap : public js::HeapBase<T, TenuredHeap<T>>
{
public:
using ElementType = T;
@ -445,7 +451,7 @@ class TenuredHeap : public js::HeapBase<T>
* specialization, define a HandleBase<T> specialization containing them.
*/
template <typename T>
class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T, Handle<T>>
{
friend class JS::MutableHandle<T>;
@ -535,7 +541,7 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
* them.
*/
template <typename T>
class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T>
class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T, MutableHandle<T>>
{
public:
using ElementType = T;
@ -747,7 +753,7 @@ namespace JS {
* specialization, define a RootedBase<T> specialization containing them.
*/
template <typename T>
class MOZ_RAII Rooted : public js::RootedBase<T>
class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>>
{
inline void registerWithRootLists(js::RootedListHeads& roots) {
this->stack = &roots[JS::MapTypeToRootKind<T>::kind];
@ -845,8 +851,8 @@ namespace js {
* Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
* Handle<StringObject*> h = rooted;
*/
template <>
class RootedBase<JSObject*>
template <typename Container>
class RootedBase<JSObject*, Container> : public MutableWrappedPtrOperations<JSObject*, Container>
{
public:
template <class U>
@ -863,8 +869,8 @@ class RootedBase<JSObject*>
* Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
* Handle<StringObject*> h = rooted;
*/
template <>
class HandleBase<JSObject*>
template <typename Container>
class HandleBase<JSObject*, Container> : public WrappedPtrOperations<JSObject*, Container>
{
public:
template <class U>
@ -873,7 +879,7 @@ class HandleBase<JSObject*>
/** Interface substitute for Rooted<T> which does not root the variable's memory. */
template <typename T>
class MOZ_RAII FakeRooted : public RootedBase<T>
class MOZ_RAII FakeRooted : public RootedBase<T, FakeRooted<T>>
{
public:
using ElementType = T;
@ -901,7 +907,7 @@ class MOZ_RAII FakeRooted : public RootedBase<T>
/** Interface substitute for MutableHandle<T> which is not required to point to rooted memory. */
template <typename T>
class FakeMutableHandle : public js::MutableHandleBase<T>
class FakeMutableHandle : public js::MutableHandleBase<T, FakeMutableHandle<T>>
{
public:
using ElementType = T;
@ -1070,7 +1076,7 @@ MutableHandle<T>::MutableHandle(PersistentRooted<T>* root)
* marked when the object itself is marked.
*/
template<typename T>
class PersistentRooted : public js::PersistentRootedBase<T>,
class PersistentRooted : public js::RootedBase<T, PersistentRooted<T>>,
private mozilla::LinkedListElement<PersistentRooted<T>>
{
using ListBase = mozilla::LinkedListElement<PersistentRooted<T>>;
@ -1230,44 +1236,25 @@ class JS_PUBLIC_API(ObjectPtr)
namespace js {
template <typename Outer, typename T, typename D>
class UniquePtrOperations
template <typename T, typename D, typename Container>
class WrappedPtrOperations<UniquePtr<T, D>, Container>
{
const UniquePtr<T, D>& uniquePtr() const { return static_cast<const Outer*>(this)->get(); }
const UniquePtr<T, D>& uniquePtr() const { return static_cast<const Container*>(this)->get(); }
public:
explicit operator bool() const { return !!uniquePtr(); }
};
template <typename Outer, typename T, typename D>
class MutableUniquePtrOperations : public UniquePtrOperations<Outer, T, D>
template <typename T, typename D, typename Container>
class MutableWrappedPtrOperations<UniquePtr<T, D>, Container>
: public WrappedPtrOperations<UniquePtr<T, D>, Container>
{
UniquePtr<T, D>& uniquePtr() { return static_cast<Outer*>(this)->get(); }
UniquePtr<T, D>& uniquePtr() { return static_cast<Container*>(this)->get(); }
public:
MOZ_MUST_USE typename UniquePtr<T, D>::Pointer release() { return uniquePtr().release(); }
};
template <typename T, typename D>
class RootedBase<UniquePtr<T, D>>
: public MutableUniquePtrOperations<JS::Rooted<UniquePtr<T, D>>, T, D>
{ };
template <typename T, typename D>
class MutableHandleBase<UniquePtr<T, D>>
: public MutableUniquePtrOperations<JS::MutableHandle<UniquePtr<T, D>>, T, D>
{ };
template <typename T, typename D>
class HandleBase<UniquePtr<T, D>>
: public UniquePtrOperations<JS::Handle<UniquePtr<T, D>>, T, D>
{ };
template <typename T, typename D>
class PersistentRootedBase<UniquePtr<T, D>>
: public MutableUniquePtrOperations<JS::PersistentRooted<UniquePtr<T, D>>, T, D>
{ };
namespace gc {
template <typename T, typename TraceCallbacks>

View File

@ -9,11 +9,6 @@
#include "js/HeapAPI.h"
namespace js {
template <typename T>
class WeakCacheBase {};
} // namespace js
namespace JS {
template <typename T> class WeakCache;
@ -25,7 +20,7 @@ RegisterWeakCache(JS::Zone* zone, JS::WeakCache<void*>* cachep);
// A WeakCache stores the given Sweepable container and links itself into a
// list of such caches that are swept during each GC.
template <typename T>
class WeakCache : public js::WeakCacheBase<T>,
class WeakCache : public js::MutableWrappedPtrOperations<T, WeakCache<T>>,
private mozilla::LinkedListElement<WeakCache<T>>
{
friend class mozilla::LinkedListElement<WeakCache<T>>;

View File

@ -1288,20 +1288,18 @@ struct BarrierMethods<JS::Value>
}
};
template <class Outer> class MutableValueOperations;
template <class Wrapper> class MutableValueOperations;
/**
* A class designed for CRTP use in implementing the non-mutating parts of the
* Value interface in Value-like classes. Outer must be a class inheriting
* ValueOperations<Outer> with a visible get() method returning a const
* reference to the Value abstracted by Outer.
* Value interface in Value-like classes. Wrapper must be a class inheriting
* ValueOperations<Wrapper> with a visible get() method returning a const
* reference to the Value abstracted by Wrapper.
*/
template <class Outer>
class ValueOperations
template <class Wrapper>
class WrappedPtrOperations<JS::Value, Wrapper>
{
friend class MutableValueOperations<Outer>;
const JS::Value& value() const { return static_cast<const Outer*>(this)->get(); }
const JS::Value& value() const { return static_cast<const Wrapper*>(this)->get(); }
public:
bool isUndefined() const { return value().isUndefined(); }
@ -1346,14 +1344,14 @@ class ValueOperations
/**
* A class designed for CRTP use in implementing all the mutating parts of the
* Value interface in Value-like classes. Outer must be a class inheriting
* MutableValueOperations<Outer> with visible get() methods returning const and
* non-const references to the Value abstracted by Outer.
* Value interface in Value-like classes. Wrapper must be a class inheriting
* MutableWrappedPtrOperations<Wrapper> with visible get() methods returning const and
* non-const references to the Value abstracted by Wrapper.
*/
template <class Outer>
class MutableValueOperations : public ValueOperations<Outer>
template <class Wrapper>
class MutableWrappedPtrOperations<JS::Value, Wrapper> : public WrappedPtrOperations<JS::Value, Wrapper>
{
JS::Value& value() { return static_cast<Outer*>(this)->get(); }
JS::Value& value() { return static_cast<Wrapper*>(this)->get(); }
public:
void setNull() { value().setNull(); }
@ -1378,13 +1376,9 @@ class MutableValueOperations : public ValueOperations<Outer>
* Augment the generic Heap<T> interface when T = Value with
* type-querying, value-extracting, and mutating operations.
*/
template <>
class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
template <typename Wrapper>
class HeapBase<JS::Value, Wrapper> : public WrappedPtrOperations<JS::Value, Wrapper>
{
typedef JS::Heap<JS::Value> Outer;
friend class ValueOperations<Outer>;
void setBarriered(const JS::Value& v) {
*static_cast<JS::Heap<JS::Value>*>(this) = v;
}
@ -1431,22 +1425,6 @@ class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
}
};
template <>
class HandleBase<JS::Value> : public ValueOperations<JS::Handle<JS::Value> >
{};
template <>
class MutableHandleBase<JS::Value> : public MutableValueOperations<JS::MutableHandle<JS::Value> >
{};
template <>
class RootedBase<JS::Value> : public MutableValueOperations<JS::Rooted<JS::Value> >
{};
template <>
class PersistentRootedBase<JS::Value> : public MutableValueOperations<JS::PersistentRooted<JS::Value>>
{};
/*
* If the Value is a GC pointer type, convert to that type and call |f| with
* the pointer. If the Value is not a GC type, calls F::defaultValue.

View File

@ -53,14 +53,22 @@ class HashableValue
}
};
template <>
class RootedBase<HashableValue> {
template <typename Wrapper>
class WrappedPtrOperations<HashableValue, Wrapper>
{
public:
Value value() const {
return static_cast<const Wrapper*>(this)->get().get();
}
};
template <typename Wrapper>
class MutableWrappedPtrOperations<HashableValue, Wrapper>
: public WrappedPtrOperations<HashableValue, Wrapper>
{
public:
MOZ_MUST_USE bool setValue(JSContext* cx, HandleValue v) {
return static_cast<JS::Rooted<HashableValue>*>(this)->get().setValue(cx, v);
}
Value value() const {
return static_cast<const JS::Rooted<HashableValue>*>(this)->get().get();
return static_cast<Wrapper*>(this)->get().setValue(cx, v);
}
};

View File

@ -52,11 +52,11 @@ class TraceableFifo : public js::Fifo<T, MinInlineCapacity, AllocPolicy>
}
};
template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
class TraceableFifoOperations
template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
class WrappedPtrOperations<TraceableFifo<T, Capacity, AllocPolicy>, Wrapper>
{
using TF = TraceableFifo<T, Capacity, AllocPolicy>;
const TF& fifo() const { return static_cast<const Outer*>(this)->extract(); }
const TF& fifo() const { return static_cast<const Wrapper*>(this)->get(); }
public:
size_t length() const { return fifo().length(); }
@ -64,12 +64,12 @@ class TraceableFifoOperations
const T& front() const { return fifo().front(); }
};
template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
class MutableTraceableFifoOperations
: public TraceableFifoOperations<Outer, T, Capacity, AllocPolicy>
template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
class MutableWrappedPtrOperations<TraceableFifo<T, Capacity, AllocPolicy>, Wrapper>
: public WrappedPtrOperations<TraceableFifo<T, Capacity, AllocPolicy>, Wrapper>
{
using TF = TraceableFifo<T, Capacity, AllocPolicy>;
TF& fifo() { return static_cast<Outer*>(this)->extract(); }
TF& fifo() { return static_cast<Wrapper*>(this)->get(); }
public:
T& front() { return fifo().front(); }
@ -83,46 +83,6 @@ class MutableTraceableFifoOperations
void clear() { fifo().clear(); }
};
template <typename A, size_t B, typename C>
class RootedBase<TraceableFifo<A,B,C>>
: public MutableTraceableFifoOperations<JS::Rooted<TraceableFifo<A,B,C>>, A,B,C>
{
using TF = TraceableFifo<A,B,C>;
friend class TraceableFifoOperations<JS::Rooted<TF>, A,B,C>;
const TF& extract() const { return *static_cast<const JS::Rooted<TF>*>(this)->address(); }
friend class MutableTraceableFifoOperations<JS::Rooted<TF>, A,B,C>;
TF& extract() { return *static_cast<JS::Rooted<TF>*>(this)->address(); }
};
template <typename A, size_t B, typename C>
class MutableHandleBase<TraceableFifo<A,B,C>>
: public MutableTraceableFifoOperations<JS::MutableHandle<TraceableFifo<A,B,C>>, A,B,C>
{
using TF = TraceableFifo<A,B,C>;
friend class TraceableFifoOperations<JS::MutableHandle<TF>, A,B,C>;
const TF& extract() const {
return *static_cast<const JS::MutableHandle<TF>*>(this)->address();
}
friend class MutableTraceableFifoOperations<JS::MutableHandle<TF>, A,B,C>;
TF& extract() { return *static_cast<JS::MutableHandle<TF>*>(this)->address(); }
};
template <typename A, size_t B, typename C>
class HandleBase<TraceableFifo<A,B,C>>
: public TraceableFifoOperations<JS::Handle<TraceableFifo<A,B,C>>, A,B,C>
{
using TF = TraceableFifo<A,B,C>;
friend class TraceableFifoOperations<JS::Handle<TF>, A,B,C>;
const TF& extract() const {
return *static_cast<const JS::Handle<TF>*>(this)->address();
}
};
} // namespace js
#endif // js_TraceableFifo_h

View File

@ -316,15 +316,9 @@ struct InternalBarrierMethods<jsid>
static void postBarrier(jsid* idp, jsid prev, jsid next) {}
};
// Barrier classes can use Mixins to add methods to a set of barrier
// instantiations, to make the barriered thing look and feel more like the
// thing itself.
template <typename T>
class BarrieredBaseMixins {};
// Base class of all barrier types.
template <typename T>
class BarrieredBase : public BarrieredBaseMixins<T>
class BarrieredBase
{
protected:
// BarrieredBase is not directly instantiable.
@ -345,9 +339,12 @@ class BarrieredBase : public BarrieredBaseMixins<T>
// Base class for barriered pointer types that intercept only writes.
template <class T>
class WriteBarrieredBase : public BarrieredBase<T>
class WriteBarrieredBase : public BarrieredBase<T>,
public WrappedPtrOperations<T, WriteBarrieredBase<T>>
{
protected:
using BarrieredBase<T>::value;
// WriteBarrieredBase is not directly instantiable.
explicit WriteBarrieredBase(const T& v) : BarrieredBase<T>(v) {}
@ -566,8 +563,12 @@ class ReadBarrieredBase : public BarrieredBase<T>
// insert manual post-barriers on the table for rekeying if the key is based in
// any way on the address of the object.
template <typename T>
class ReadBarriered : public ReadBarrieredBase<T>
class ReadBarriered : public ReadBarrieredBase<T>,
public WrappedPtrOperations<T, ReadBarriered<T>>
{
protected:
using ReadBarrieredBase<T>::value;
public:
ReadBarriered() : ReadBarrieredBase<T>(JS::GCPolicy<T>::initial()) {}
@ -634,12 +635,6 @@ class ReadBarriered : public ReadBarrieredBase<T>
template <typename T>
using WeakRef = ReadBarriered<T>;
// Add Value operations to all Barrier types. Note, this must be defined before
// HeapSlot for HeapSlot's base to get these operations.
template <>
class BarrieredBaseMixins<JS::Value> : public ValueOperations<WriteBarrieredBase<JS::Value>>
{};
// A pre- and post-barriered Value that is specialized to be aware that it
// resides in a slots or elements vector. This allows it to be relocated in
// memory, but with substantially less overhead than a HeapPtr.

View File

@ -57,19 +57,10 @@ struct MyContainer
};
namespace js {
template <>
struct RootedBase<MyContainer> {
HeapPtr<JSObject*>& obj() { return static_cast<Rooted<MyContainer>*>(this)->get().obj; }
HeapPtr<JSString*>& str() { return static_cast<Rooted<MyContainer>*>(this)->get().str; }
};
template <>
struct PersistentRootedBase<MyContainer> {
HeapPtr<JSObject*>& obj() {
return static_cast<PersistentRooted<MyContainer>*>(this)->get().obj;
}
HeapPtr<JSString*>& str() {
return static_cast<PersistentRooted<MyContainer>*>(this)->get().str;
}
template <typename Wrapper>
struct MutableWrappedPtrOperations<MyContainer, Wrapper> {
HeapPtr<JSObject*>& obj() { return static_cast<Wrapper*>(this)->get().obj; }
HeapPtr<JSString*>& str() { return static_cast<Wrapper*>(this)->get().str; }
};
} // namespace js

View File

@ -2569,10 +2569,14 @@ struct JS_PUBLIC_API(PropertyDescriptor) {
void trace(JSTracer* trc);
};
template <typename Outer>
class PropertyDescriptorOperations
} // namespace JS
namespace js {
template <typename Wrapper>
class WrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
{
const PropertyDescriptor& desc() const { return static_cast<const Outer*>(this)->get(); }
const JS::PropertyDescriptor& desc() const { return static_cast<const Wrapper*>(this)->get(); }
bool has(unsigned bit) const {
MOZ_ASSERT(bit != 0);
@ -2701,10 +2705,11 @@ class PropertyDescriptorOperations
}
};
template <typename Outer>
class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<Outer>
template <typename Wrapper>
class MutableWrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
: public js::WrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
{
PropertyDescriptor& desc() { return static_cast<Outer*>(this)->get(); }
JS::PropertyDescriptor& desc() { return static_cast<Wrapper*>(this)->get(); }
public:
void clear() {
@ -2715,7 +2720,7 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
value().setUndefined();
}
void initFields(HandleObject obj, HandleValue v, unsigned attrs,
void initFields(JS::HandleObject obj, JS::HandleValue v, unsigned attrs,
JSGetterOp getterOp, JSSetterOp setterOp) {
MOZ_ASSERT(getterOp != JS_PropertyStub);
MOZ_ASSERT(setterOp != JS_StrictPropertyStub);
@ -2727,7 +2732,7 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
setSetter(setterOp);
}
void assign(PropertyDescriptor& other) {
void assign(JS::PropertyDescriptor& other) {
object().set(other.obj);
setAttributes(other.attrs);
setGetter(other.getter);
@ -2735,7 +2740,7 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
value().set(other.value);
}
void setDataDescriptor(HandleValue v, unsigned attrs) {
void setDataDescriptor(JS::HandleValue v, unsigned attrs) {
MOZ_ASSERT((attrs & ~(JSPROP_ENUMERATE |
JSPROP_PERMANENT |
JSPROP_READONLY |
@ -2810,26 +2815,7 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
}
};
} /* namespace JS */
namespace js {
template <>
class RootedBase<JS::PropertyDescriptor>
: public JS::MutablePropertyDescriptorOperations<JS::Rooted<JS::PropertyDescriptor>>
{};
template <>
class HandleBase<JS::PropertyDescriptor>
: public JS::PropertyDescriptorOperations<JS::Handle<JS::PropertyDescriptor>>
{};
template <>
class MutableHandleBase<JS::PropertyDescriptor>
: public JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JS::PropertyDescriptor>>
{};
} /* namespace js */
} // namespace js
namespace JS {

View File

@ -720,8 +720,9 @@ JSCompartment::sweepAfterMinorGC(JSTracer* trc)
{
globalWriteBarriered = 0;
if (innerViews.needsSweepAfterMinorGC())
innerViews.sweepAfterMinorGC();
InnerViewTable& table = innerViews.get();
if (table.needsSweepAfterMinorGC())
table.sweepAfterMinorGC();
crossCompartmentWrappers.sweepAfterMinorGC(trc);
}

View File

@ -592,21 +592,23 @@ class JSObject : public js::gc::Cell
void operator=(const JSObject& other) = delete;
};
template <class U>
template <typename Wrapper>
template <typename U>
MOZ_ALWAYS_INLINE JS::Handle<U*>
js::RootedBase<JSObject*>::as() const
js::RootedBase<JSObject*, Wrapper>::as() const
{
const JS::Rooted<JSObject*>& self = *static_cast<const JS::Rooted<JSObject*>*>(this);
MOZ_ASSERT(self->is<U>());
const Wrapper& self = *static_cast<const Wrapper*>(this);
MOZ_ASSERT(self->template is<U>());
return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
}
template <typename Wrapper>
template <class U>
MOZ_ALWAYS_INLINE JS::Handle<U*>
js::HandleBase<JSObject*>::as() const
js::HandleBase<JSObject*, Wrapper>::as() const
{
const JS::Handle<JSObject*>& self = *static_cast<const JS::Handle<JSObject*>*>(this);
MOZ_ASSERT(self->is<U>());
MOZ_ASSERT(self->template is<U>());
return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
}

View File

@ -350,7 +350,7 @@ ArrayBufferObject::detach(JSContext* cx, Handle<ArrayBufferObject*> buffer,
// Update all views of the buffer to account for the buffer having been
// detached, and clear the buffer's data and list of views.
auto& innerViews = cx->compartment()->innerViews;
auto& innerViews = cx->compartment()->innerViews.get();
if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(buffer)) {
for (size_t i = 0; i < views->length(); i++)
NoteViewBufferWasDetached((*views)[i], newContents, cx);
@ -425,7 +425,7 @@ ArrayBufferObject::changeContents(JSContext* cx, BufferContents newContents,
setNewData(cx->runtime()->defaultFreeOp(), newContents, ownsState);
// Update all views.
auto& innerViews = cx->compartment()->innerViews;
auto& innerViews = cx->compartment()->innerViews.get();
if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(this)) {
for (size_t i = 0; i < views->length(); i++)
changeViewContents(cx, (*views)[i], oldDataPointer, newContents);

View File

@ -555,7 +555,6 @@ class InnerViewTable
typedef Vector<ArrayBufferViewObject*, 1, SystemAllocPolicy> ViewVector;
friend class ArrayBufferObject;
friend class WeakCacheBase<InnerViewTable>;
private:
struct MapGCPolicy {
@ -616,23 +615,15 @@ class InnerViewTable
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
};
template <>
class WeakCacheBase<InnerViewTable>
template <typename Wrapper>
class MutableWrappedPtrOperations<InnerViewTable, Wrapper>
: public WrappedPtrOperations<InnerViewTable, Wrapper>
{
InnerViewTable& table() {
return static_cast<JS::WeakCache<InnerViewTable>*>(this)->get();
}
const InnerViewTable& table() const {
return static_cast<const JS::WeakCache<InnerViewTable>*>(this)->get();
return static_cast<Wrapper*>(this)->get();
}
public:
InnerViewTable::ViewVector* maybeViewsUnbarriered(ArrayBufferObject* obj) {
return table().maybeViewsUnbarriered(obj);
}
void removeViews(ArrayBufferObject* obj) { table().removeViews(obj); }
void sweepAfterMinorGC() { table().sweepAfterMinorGC(); }
bool needsSweepAfterMinorGC() const { return table().needsSweepAfterMinorGC(); }
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
return table().sizeOfExcludingThis(mallocSizeOf);
}

View File

@ -1535,11 +1535,7 @@ GetSuperEnvFunction(JSContext* cx, InterpreterRegs& regs)
*/
template<typename T>
class ReservedRootedBase {
};
template<typename T>
class ReservedRooted : public ReservedRootedBase<T>
class ReservedRooted : public RootedBase<T, ReservedRooted<T>>
{
Rooted<T>* savedRoot;
@ -1567,14 +1563,6 @@ class ReservedRooted : public ReservedRootedBase<T>
DECLARE_POINTER_ASSIGN_OPS(ReservedRooted, T)
};
template <>
class ReservedRootedBase<Value> : public ValueOperations<ReservedRooted<Value>>
{};
template <>
class ReservedRootedBase<Scope*> : public ScopeCastOperation<ReservedRooted<Scope*>>
{};
static MOZ_NEVER_INLINE bool
Interpret(JSContext* cx, RunState& state)
{

View File

@ -256,10 +256,13 @@ class MOZ_STACK_CLASS JSONParser : public JSONParserBase
void operator=(const JSONParser& other) = delete;
};
template <typename CharT>
struct RootedBase<JSONParser<CharT>> {
template <typename CharT, typename Wrapper>
class MutableWrappedPtrOperations<JSONParser<CharT>, Wrapper>
: public WrappedPtrOperations<JSONParser<CharT>, Wrapper>
{
public:
bool parse(MutableHandleValue vp) {
return static_cast<Rooted<JSONParser<CharT>>*>(this)->get().parse(vp);
return static_cast<Wrapper*>(this)->get().parse(vp);
}
};

View File

@ -266,24 +266,6 @@ class SavedStacks {
uint32_t column;
};
template <typename Outer>
struct LocationValueOperations {
JSAtom* source() const { return loc().source; }
size_t line() const { return loc().line; }
uint32_t column() const { return loc().column; }
private:
const LocationValue& loc() const { return static_cast<const Outer*>(this)->get(); }
};
template <typename Outer>
struct MutableLocationValueOperations : public LocationValueOperations<Outer> {
void setSource(JSAtom* v) { loc().source = v; }
void setLine(size_t v) { loc().line = v; }
void setColumn(uint32_t v) { loc().column = v; }
private:
LocationValue& loc() { return static_cast<Outer*>(this)->get(); }
};
private:
struct PCLocationHasher : public DefaultHasher<PCKey> {
using ScriptPtrHasher = DefaultHasher<JSScript*>;
@ -314,15 +296,32 @@ class SavedStacks {
MutableHandle<LocationValue> locationp);
};
template <>
class RootedBase<SavedStacks::LocationValue>
: public SavedStacks::MutableLocationValueOperations<JS::Rooted<SavedStacks::LocationValue>>
{};
template <typename Wrapper>
struct WrappedPtrOperations<SavedStacks::LocationValue, Wrapper>
{
JSAtom* source() const { return loc().source; }
size_t line() const { return loc().line; }
uint32_t column() const { return loc().column; }
template <>
class MutableHandleBase<SavedStacks::LocationValue>
: public SavedStacks::MutableLocationValueOperations<JS::MutableHandle<SavedStacks::LocationValue>>
{};
private:
const SavedStacks::LocationValue& loc() const {
return static_cast<const Wrapper*>(this)->get();
}
};
template <typename Wrapper>
struct MutableWrappedPtrOperations<SavedStacks::LocationValue, Wrapper>
: public WrappedPtrOperations<SavedStacks::LocationValue, Wrapper>
{
void setSource(JSAtom* v) { loc().source = v; }
void setLine(size_t v) { loc().line = v; }
void setColumn(uint32_t v) { loc().column = v; }
private:
SavedStacks::LocationValue& loc() {
return static_cast<Wrapper*>(this)->get();
}
};
UTF8CharsZ
BuildUTF8StackString(JSContext* cx, HandleObject stack);

View File

@ -22,6 +22,7 @@
namespace js {
class ModuleObject;
class Scope;
enum class BindingKind : uint8_t
{
@ -182,6 +183,21 @@ class BindingLocation
}
};
//
// Allow using is<T> and as<T> on Rooted<Scope*> and Handle<Scope*>.
//
template <typename Wrapper>
class WrappedPtrOperations<Scope*, Wrapper>
{
public:
template <class U>
JS::Handle<U*> as() const {
const Wrapper& self = *static_cast<const Wrapper*>(this);
MOZ_ASSERT_IF(self, self->template is<U>());
return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
}
};
//
// The base class of all Scopes.
//
@ -1269,10 +1285,10 @@ class MOZ_STACK_CLASS ScopeIter
// Specializations of Rooted containers for the iterators.
//
template <typename Outer>
class BindingIterOperations
template <typename Wrapper>
class WrappedPtrOperations<BindingIter, Wrapper>
{
const BindingIter& iter() const { return static_cast<const Outer*>(this)->get(); }
const BindingIter& iter() const { return static_cast<const Wrapper*>(this)->get(); }
public:
bool done() const { return iter().done(); }
@ -1292,19 +1308,20 @@ class BindingIterOperations
uint32_t nextEnvironmentSlot() const { return iter().nextEnvironmentSlot(); }
};
template <typename Outer>
class MutableBindingIterOperations : public BindingIterOperations<Outer>
template <typename Wrapper>
class MutableWrappedPtrOperations<BindingIter, Wrapper>
: public WrappedPtrOperations<BindingIter, Wrapper>
{
BindingIter& iter() { return static_cast<Outer*>(this)->get(); }
BindingIter& iter() { return static_cast<Wrapper*>(this)->get(); }
public:
void operator++(int) { iter().operator++(1); }
};
template <typename Outer>
class ScopeIterOperations
template <typename Wrapper>
class WrappedPtrOperations<ScopeIter, Wrapper>
{
const ScopeIter& iter() const { return static_cast<const Outer*>(this)->get(); }
const ScopeIter& iter() const { return static_cast<const Wrapper*>(this)->get(); }
public:
bool done() const { return iter().done(); }
@ -1315,69 +1332,16 @@ class ScopeIterOperations
bool hasSyntacticEnvironment() const { return iter().hasSyntacticEnvironment(); }
};
template <typename Outer>
class MutableScopeIterOperations : public ScopeIterOperations<Outer>
template <typename Wrapper>
class MutableWrappedPtrOperations<ScopeIter, Wrapper>
: public WrappedPtrOperations<ScopeIter, Wrapper>
{
ScopeIter& iter() { return static_cast<Outer*>(this)->get(); }
ScopeIter& iter() { return static_cast<Wrapper*>(this)->get(); }
public:
void operator++(int) { iter().operator++(1); }
};
#define SPECIALIZE_ROOTING_CONTAINERS(Iter, BaseIter) \
template <> \
class RootedBase<Iter> \
: public Mutable##BaseIter##Operations<JS::Rooted<Iter>> \
{ }; \
\
template <> \
class MutableHandleBase<Iter> \
: public Mutable##BaseIter##Operations<JS::MutableHandle<Iter>> \
{ }; \
\
template <> \
class HandleBase<Iter> \
: public BaseIter##Operations<JS::Handle<Iter>> \
{ }; \
\
template <> \
class PersistentRootedBase<Iter> \
: public Mutable##BaseIter##Operations<JS::PersistentRooted<Iter>> \
{ }
SPECIALIZE_ROOTING_CONTAINERS(BindingIter, BindingIter);
SPECIALIZE_ROOTING_CONTAINERS(PositionalFormalParameterIter, BindingIter);
SPECIALIZE_ROOTING_CONTAINERS(ScopeIter, ScopeIter);
#undef SPECIALIZE_ROOTING_CONTAINERS
//
// Allow using is<T> and as<T> on Rooted<Scope*> and Handle<Scope*>.
//
template <typename Outer>
struct ScopeCastOperation
{
template <class U>
JS::Handle<U*> as() const {
const Outer& self = *static_cast<const Outer*>(this);
MOZ_ASSERT_IF(self, self->template is<U>());
return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
}
};
template <>
class RootedBase<Scope*> : public ScopeCastOperation<JS::Rooted<Scope*>>
{ };
template <>
class HandleBase<Scope*> : public ScopeCastOperation<JS::Handle<Scope*>>
{ };
template <>
class MutableHandleBase<Scope*> : public ScopeCastOperation<JS::MutableHandle<Scope*>>
{ };
} // namespace js
namespace JS {

View File

@ -1242,9 +1242,10 @@ struct InitialShapeEntry
bool needsSweep() {
Shape* ushape = shape.unbarrieredGet();
JSObject* protoObj = proto.proto().raw();
TaggedProto uproto = proto.proto().unbarrieredGet();
JSObject* protoObj = uproto.raw();
return (gc::IsAboutToBeFinalizedUnbarriered(&ushape) ||
(proto.proto().isObject() && gc::IsAboutToBeFinalizedUnbarriered(&protoObj)));
(uproto.isObject() && gc::IsAboutToBeFinalizedUnbarriered(&protoObj)));
}
};
@ -1334,9 +1335,10 @@ struct StackShape
void trace(JSTracer* trc);
};
template <typename Outer>
class StackShapeOperations {
const StackShape& ss() const { return static_cast<const Outer*>(this)->get(); }
template <typename Wrapper>
class WrappedPtrOperations<StackShape, Wrapper>
{
const StackShape& ss() const { return static_cast<const Wrapper*>(this)->get(); }
public:
bool hasSlot() const { return ss().hasSlot(); }
@ -1348,9 +1350,11 @@ class StackShapeOperations {
uint8_t attrs() const { return ss().attrs; }
};
template <typename Outer>
class MutableStackShapeOperations : public StackShapeOperations<Outer> {
StackShape& ss() { return static_cast<Outer*>(this)->get(); }
template <typename Wrapper>
class MutableWrappedPtrOperations<StackShape, Wrapper>
: public WrappedPtrOperations<StackShape, Wrapper>
{
StackShape& ss() { return static_cast<Wrapper*>(this)->get(); }
public:
void updateGetterSetter(GetterOp rawGetter, SetterOp rawSetter) {
@ -1361,19 +1365,6 @@ class MutableStackShapeOperations : public StackShapeOperations<Outer> {
void setAttrs(uint8_t attrs) { ss().attrs = attrs; }
};
template <>
class RootedBase<StackShape> : public MutableStackShapeOperations<JS::Rooted<StackShape>>
{};
template <>
class HandleBase<StackShape> : public StackShapeOperations<JS::Handle<StackShape>>
{};
template <>
class MutableHandleBase<StackShape>
: public MutableStackShapeOperations<JS::MutableHandle<StackShape>>
{};
inline
Shape::Shape(const StackShape& other, uint32_t nfixed)
: base_(other.base),

View File

@ -78,11 +78,11 @@ struct InternalBarrierMethods<TaggedProto>
}
};
template<class Outer>
class TaggedProtoOperations
template <class Wrapper>
class WrappedPtrOperations<TaggedProto, Wrapper>
{
const TaggedProto& value() const {
return static_cast<const Outer*>(this)->get();
return static_cast<const Wrapper*>(this)->get();
}
public:
@ -96,18 +96,6 @@ class TaggedProtoOperations
uint64_t uniqueId() const { return value().uniqueId(); }
};
template <>
class HandleBase<TaggedProto> : public TaggedProtoOperations<Handle<TaggedProto>>
{};
template <>
class RootedBase<TaggedProto> : public TaggedProtoOperations<Rooted<TaggedProto>>
{};
template <>
class BarrieredBaseMixins<TaggedProto> : public TaggedProtoOperations<GCPtr<TaggedProto>>
{};
// If the TaggedProto is a JSObject pointer, convert to that type and call |f|
// with the pointer. If the TaggedProto is lazy, calls F::defaultValue.
template <typename F, typename... Args>