From f11b40c3ab4a5a766b0b71ab1e9a6199b23bbfeb Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Sun, 29 May 2022 00:47:25 -0500 Subject: [JS:Engine] Remove the use of tagged shape pointers --- js/public/Class.h | 113 ++++++++++++++++++- js/public/GCHashTable.h | 76 +++---------- js/public/GCVariant.h | 36 ++---- js/public/GCVector.h | 36 ++---- js/public/RootingAPI.h | 283 ++++++++++++++++++++++++++++++++++++++---------- js/public/SweepingAPI.h | 7 +- js/public/Value.h | 52 +++------ 7 files changed, 384 insertions(+), 219 deletions(-) (limited to 'js/public') diff --git a/js/public/Class.h b/js/public/Class.h index 6f1960a30..1dd03a182 100644 --- a/js/public/Class.h +++ b/js/public/Class.h @@ -271,8 +271,119 @@ class ObjectOpResult } }; +class PropertyResult +{ + union { + js::Shape* shape_; + uintptr_t bits_; + }; + + static const uintptr_t NotFound = 0; + static const uintptr_t NonNativeProperty = 1; + static const uintptr_t DenseOrTypedArrayElement = 1; + + public: + PropertyResult() : bits_(NotFound) {} + + explicit PropertyResult(js::Shape* propertyShape) + : shape_(propertyShape) + { + MOZ_ASSERT(!isFound() || isNativeProperty()); + } + + explicit operator bool() const { + return isFound(); + } + + bool isFound() const { + return bits_ != NotFound; + } + + bool isNonNativeProperty() const { + return bits_ == NonNativeProperty; + } + + bool isDenseOrTypedArrayElement() const { + return bits_ == DenseOrTypedArrayElement; + } + + bool isNativeProperty() const { + return isFound() && !isNonNativeProperty(); + } + + js::Shape* maybeShape() const { + MOZ_ASSERT(!isNonNativeProperty()); + return isFound() ? shape_ : nullptr; + } + + js::Shape* shape() const { + MOZ_ASSERT(isNativeProperty()); + return shape_; + } + + void setNotFound() { + bits_ = NotFound; + } + + void setNativeProperty(js::Shape* propertyShape) { + shape_ = propertyShape; + MOZ_ASSERT(isNativeProperty()); + } + + void setNonNativeProperty() { + bits_ = NonNativeProperty; + } + + void setDenseOrTypedArrayElement() { + bits_ = DenseOrTypedArrayElement; + } + + void trace(JSTracer* trc); +}; + } // namespace JS +namespace js { + +template +class WrappedPtrOperations +{ + const JS::PropertyResult& value() const { return static_cast(this)->get(); } + + public: + bool isFound() const { return value().isFound(); } + explicit operator bool() const { return bool(value()); } + js::Shape* maybeShape() const { return value().maybeShape(); } + js::Shape* shape() const { return value().shape(); } + bool isNativeProperty() const { return value().isNativeProperty(); } + bool isNonNativeProperty() const { return value().isNonNativeProperty(); } + bool isDenseOrTypedArrayElement() const { return value().isDenseOrTypedArrayElement(); } + js::Shape* asTaggedShape() const { return value().asTaggedShape(); } +}; + +template +class MutableWrappedPtrOperations + : public WrappedPtrOperations +{ + JS::PropertyResult& value() { return static_cast(this)->get(); } + + public: + void setNotFound() { + value().setNotFound(); + } + void setNativeProperty(js::Shape* shape) { + value().setNativeProperty(shape); + } + void setNonNativeProperty() { + value().setNonNativeProperty(); + } + void setDenseOrTypedArrayElement() { + value().setDenseOrTypedArrayElement(); + } +}; + +} // namespace js + // JSClass operation signatures. /** @@ -428,7 +539,7 @@ namespace js { typedef bool (* LookupPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, - JS::MutableHandleObject objp, JS::MutableHandle propp); + JS::MutableHandleObject objp, JS::MutableHandle propp); typedef bool (* DefinePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::Handle desc, diff --git a/js/public/GCHashTable.h b/js/public/GCHashTable.h index 4de1c39a8..3e647ed10 100644 --- a/js/public/GCHashTable.h +++ b/js/public/GCHashTable.h @@ -133,13 +133,13 @@ class GCRekeyableHashMap : public JS::GCHashMap -class GCHashMapOperations +template +class WrappedPtrOperations, Wrapper> { using Map = JS::GCHashMap; using Lookup = typename Map::Lookup; - const Map& map() const { return static_cast(this)->get(); } + const Map& map() const { return static_cast(this)->get(); } public: using AddPtr = typename Map::AddPtr; @@ -162,18 +162,18 @@ class GCHashMapOperations } }; -template -class MutableGCHashMapOperations - : public GCHashMapOperations +template +class MutableWrappedPtrOperations, Wrapper> + : public WrappedPtrOperations, Wrapper> { using Map = JS::GCHashMap; using Lookup = typename Map::Lookup; - Map& map() { return static_cast(this)->get(); } + Map& map() { return static_cast(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; @@ -210,26 +210,6 @@ class MutableGCHashMapOperations } }; -template -class RootedBase> - : public MutableGCHashMapOperations>, A,B,C,D,E> -{}; - -template -class MutableHandleBase> - : public MutableGCHashMapOperations>, A,B,C,D,E> -{}; - -template -class HandleBase> - : public GCHashMapOperations>, A,B,C,D,E> -{}; - -template -class WeakCacheBase> - : public MutableGCHashMapOperations>, A,B,C,D,E> -{}; - } // namespace js namespace JS { @@ -291,13 +271,13 @@ class GCHashSet : public js::HashSet namespace js { -template -class GCHashSetOperations +template +class WrappedPtrOperations, Wrapper> { using Set = JS::GCHashSet; using Lookup = typename Set::Lookup; - const Set& set() const { return static_cast(this)->get(); } + const Set& set() const { return static_cast(this)->get(); } public: using AddPtr = typename Set::AddPtr; @@ -321,19 +301,19 @@ class GCHashSetOperations } }; -template -class MutableGCHashSetOperations - : public GCHashSetOperations +template +class MutableWrappedPtrOperations, Wrapper> + : public WrappedPtrOperations, Wrapper> { using Set = JS::GCHashSet; using Lookup = typename Set::Lookup; - Set& set() { return static_cast(this)->get(); } + Set& set() { return static_cast(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; @@ -369,30 +349,6 @@ class MutableGCHashSetOperations } }; -template -class RootedBase> - : public MutableGCHashSetOperations>, T, HP, AP> -{ -}; - -template -class MutableHandleBase> - : public MutableGCHashSetOperations>, T, HP, AP> -{ -}; - -template -class HandleBase> - : public GCHashSetOperations>, T, HP, AP> -{ -}; - -template -class WeakCacheBase> - : public MutableGCHashSetOperations>, T, HP, AP> -{ -}; - } /* namespace js */ #endif /* GCHashTable_h */ diff --git a/js/public/GCVariant.h b/js/public/GCVariant.h index 43f2957fe..3ec40df5c 100644 --- a/js/public/GCVariant.h +++ b/js/public/GCVariant.h @@ -123,13 +123,13 @@ struct GCPolicy> namespace js { -template -class GCVariantOperations +template +class WrappedPtrOperations, Wrapper> { using Impl = JS::detail::GCVariantImplementation; using Variant = mozilla::Variant; - const Variant& variant() const { return static_cast(this)->get(); } + const Variant& variant() const { return static_cast(this)->get(); } public: template @@ -149,15 +149,15 @@ class GCVariantOperations } }; -template -class MutableGCVariantOperations - : public GCVariantOperations +template +class MutableWrappedPtrOperations, Wrapper> + : public WrappedPtrOperations, Wrapper> { using Impl = JS::detail::GCVariantImplementation; using Variant = mozilla::Variant; - const Variant& variant() const { return static_cast(this)->get(); } - Variant& variant() { return static_cast(this)->get(); } + const Variant& variant() const { return static_cast(this)->get(); } + Variant& variant() { return static_cast(this)->get(); } public: template @@ -172,26 +172,6 @@ class MutableGCVariantOperations } }; -template -class RootedBase> - : public MutableGCVariantOperations>, Ts...> -{ }; - -template -class MutableHandleBase> - : public MutableGCVariantOperations>, Ts...> -{ }; - -template -class HandleBase> - : public GCVariantOperations>, Ts...> -{ }; - -template -class PersistentRootedBase> - : public MutableGCVariantOperations>, Ts...> -{ }; - } // namespace js #endif // js_GCVariant_h diff --git a/js/public/GCVector.h b/js/public/GCVector.h index 1c9925261..4acf0d1fc 100644 --- a/js/public/GCVector.h +++ b/js/public/GCVector.h @@ -134,11 +134,11 @@ class GCVector namespace js { -template -class GCVectorOperations +template +class WrappedPtrOperations, Wrapper> { using Vec = JS::GCVector; - const Vec& vec() const { return static_cast(this)->get(); } + const Vec& vec() const { return static_cast(this)->get(); } public: const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); } @@ -154,13 +154,13 @@ class GCVectorOperations } }; -template -class MutableGCVectorOperations - : public GCVectorOperations +template +class MutableWrappedPtrOperations, Wrapper> + : public WrappedPtrOperations, Wrapper> { using Vec = JS::GCVector; - const Vec& vec() const { return static_cast(this)->get(); } - Vec& vec() { return static_cast(this)->get(); } + const Vec& vec() const { return static_cast(this)->get(); } + Vec& vec() { return static_cast(this)->get(); } public: const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); } @@ -223,26 +223,6 @@ class MutableGCVectorOperations void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); } }; -template -class RootedBase> - : public MutableGCVectorOperations>, T,N,AP> -{}; - -template -class MutableHandleBase> - : public MutableGCVectorOperations>, T,N,AP> -{}; - -template -class HandleBase> - : public GCVectorOperations>, T,N,AP> -{}; - -template -class PersistentRootedBase> - : public MutableGCVectorOperations>, T,N,AP> -{}; - } // namespace js #endif // js_GCVector_h diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index 5f0740d53..aec25b0ff 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -112,17 +112,23 @@ template struct BarrierMethods { }; -template -class RootedBase {}; +template +class WrappedPtrOperations {}; -template -class HandleBase {}; +template +class MutableWrappedPtrOperations : public WrappedPtrOperations {}; -template -class MutableHandleBase {}; +template +class RootedBase : public MutableWrappedPtrOperations {}; -template -class HeapBase {}; +template +class HandleBase : public WrappedPtrOperations {}; + +template +class MutableHandleBase : public MutableWrappedPtrOperations {}; + +template +class HeapBase : public MutableWrappedPtrOperations {}; // Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many macros into scope template struct IsHeapConstructibleType { static constexpr bool value = false; }; @@ -132,8 +138,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 -class PersistentRootedBase {}; +template +class PersistentRootedBase : public MutableWrappedPtrOperations {}; static void* const ConstNullValue = nullptr; @@ -143,10 +149,6 @@ template struct PersistentRootedMarker; } /* namespace gc */ -#define DECLARE_POINTER_COMPARISON_OPS(T) \ - bool operator==(const T& other) const { return get() == other; } \ - bool operator!=(const T& other) const { return get() != other; } - // Important: Return a reference so passing a Rooted, etc. to // something that takes a |const T&| is not a GC hazard. #define DECLARE_POINTER_CONSTREF_OPS(T) \ @@ -230,12 +232,14 @@ AssertGCThingIsNotAnObjectSubclass(js::gc::Cell* cell) {} * Type T must be a public GC pointer type. */ template -class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase +class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase> { // Please note: this can actually also be used by nsXBLMaybeCompiled, for legacy reasons. static_assert(js::IsHeapConstructibleType::value, "Type T must be a public GC pointer type"); public: + using ElementType = T; + Heap() { static_assert(sizeof(T) == sizeof(Heap), "Heap must be binary compatible with T."); @@ -367,9 +371,11 @@ ScriptIsMarkedGray(const Heap& script) * - It is not possible to store flag bits in a Heap. */ template -class TenuredHeap : public js::HeapBase +class TenuredHeap : public js::HeapBase> { public: + using ElementType = T; + TenuredHeap() : bits(0) { static_assert(sizeof(T) == sizeof(TenuredHeap), "TenuredHeap must be binary compatible with T."); @@ -377,9 +383,6 @@ class TenuredHeap : public js::HeapBase explicit TenuredHeap(T p) : bits(0) { setPtr(p); } explicit TenuredHeap(const TenuredHeap& p) : bits(0) { setPtr(p.getPtr()); } - bool operator==(const TenuredHeap& other) { return bits == other.bits; } - bool operator!=(const TenuredHeap& other) { return bits != other.bits; } - void setPtr(T newPtr) { MOZ_ASSERT((reinterpret_cast(newPtr) & flagsMask) == 0); if (newPtr) @@ -451,11 +454,13 @@ class TenuredHeap : public js::HeapBase * specialization, define a HandleBase specialization containing them. */ template -class MOZ_NONHEAP_CLASS Handle : public js::HandleBase +class MOZ_NONHEAP_CLASS Handle : public js::HandleBase> { friend class JS::MutableHandle; public: + using ElementType = T; + /* Creates a handle from a handle of a type convertible to T. */ template MOZ_IMPLICIT Handle(Handle handle, @@ -516,7 +521,6 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase MOZ_IMPLICIT Handle(MutableHandle& root, typename mozilla::EnableIf::value, int>::Type dummy = 0); - DECLARE_POINTER_COMPARISON_OPS(T); DECLARE_POINTER_CONSTREF_OPS(T); DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr); @@ -540,9 +544,11 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase * them. */ template -class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase +class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase> { public: + using ElementType = T; + inline MOZ_IMPLICIT MutableHandle(Rooted* root); inline MOZ_IMPLICIT MutableHandle(PersistentRooted* root); @@ -753,7 +759,7 @@ namespace JS { * specialization, define a RootedBase specialization containing them. */ template -class MOZ_RAII Rooted : public js::RootedBase +class MOZ_RAII Rooted : public js::RootedBase> { inline void registerWithRootLists(js::RootedListHeads& roots) { this->stack = &roots[JS::MapTypeToRootKind::kind]; @@ -775,6 +781,8 @@ class MOZ_RAII Rooted : public js::RootedBase } public: + using ElementType = T; + template explicit Rooted(const RootingContext& cx) : ptr(GCPolicy::initial()) @@ -807,7 +815,6 @@ class MOZ_RAII Rooted : public js::RootedBase ptr = mozilla::Move(value); } - DECLARE_POINTER_COMPARISON_OPS(T); DECLARE_POINTER_CONSTREF_OPS(T); DECLARE_POINTER_ASSIGN_OPS(Rooted, T); DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr); @@ -853,8 +860,8 @@ namespace js { * Rooted rooted(cx, &obj->as()); * Handle h = rooted; */ -template <> -class RootedBase +template +class RootedBase : public MutableWrappedPtrOperations { public: template @@ -871,8 +878,8 @@ class RootedBase * Rooted rooted(cx, &obj->as()); * Handle h = rooted; */ -template <> -class HandleBase +template +class HandleBase : public WrappedPtrOperations { public: template @@ -881,16 +888,17 @@ class HandleBase /** Interface substitute for Rooted which does not root the variable's memory. */ template -class MOZ_RAII FakeRooted : public RootedBase +class MOZ_RAII FakeRooted : public RootedBase> { public: + using ElementType = T; + template explicit FakeRooted(CX* cx) : ptr(JS::GCPolicy::initial()) {} template FakeRooted(CX* cx, T initial) : ptr(initial) {} - DECLARE_POINTER_COMPARISON_OPS(T); DECLARE_POINTER_CONSTREF_OPS(T); DECLARE_POINTER_ASSIGN_OPS(FakeRooted, T); DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr); @@ -908,9 +916,11 @@ class MOZ_RAII FakeRooted : public RootedBase /** Interface substitute for MutableHandle which is not required to point to rooted memory. */ template -class FakeMutableHandle : public js::MutableHandleBase +class FakeMutableHandle : public js::MutableHandleBase> { public: + using ElementType = T; + MOZ_IMPLICIT FakeMutableHandle(T* t) { ptr = t; } @@ -1075,7 +1085,7 @@ MutableHandle::MutableHandle(PersistentRooted* root) * marked when the object itself is marked. */ template -class PersistentRooted : public js::PersistentRootedBase, +class PersistentRooted : public js::RootedBase>, private mozilla::LinkedListElement> { using ListBase = mozilla::LinkedListElement>; @@ -1101,6 +1111,8 @@ class PersistentRooted : public js::PersistentRootedBase, js::RootLists& rootLists(js::ContextFriendFields* cx) = delete; public: + using ElementType = T; + PersistentRooted() : ptr(GCPolicy::initial()) {} template @@ -1154,7 +1166,6 @@ class PersistentRooted : public js::PersistentRootedBase, } } - DECLARE_POINTER_COMPARISON_OPS(T); DECLARE_POINTER_CONSTREF_OPS(T); DECLARE_POINTER_ASSIGN_OPS(PersistentRooted, T); DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr); @@ -1191,6 +1202,8 @@ class JS_PUBLIC_API(ObjectPtr) Heap value; public: + using ElementType = JSObject*; + ObjectPtr() : value(nullptr) {} explicit ObjectPtr(JSObject* obj) : value(obj) {} @@ -1240,10 +1253,10 @@ class JS_PUBLIC_API(ObjectPtr) namespace js { -template -class UniquePtrOperations +template +class WrappedPtrOperations, Container> { - const UniquePtr& uniquePtr() const { return static_cast(this)->get(); } + const UniquePtr& uniquePtr() const { return static_cast(this)->get(); } public: explicit operator bool() const { return !!uniquePtr(); } @@ -1252,36 +1265,17 @@ class UniquePtrOperations T& operator*() const { return *uniquePtr(); } }; -template -class MutableUniquePtrOperations : public UniquePtrOperations +template +class MutableWrappedPtrOperations, Container> + : public WrappedPtrOperations, Container> { - UniquePtr& uniquePtr() { return static_cast(this)->get(); } + UniquePtr& uniquePtr() { return static_cast(this)->get(); } public: MOZ_MUST_USE typename UniquePtr::Pointer release() { return uniquePtr().release(); } void reset(T* ptr = T()) { uniquePtr().reset(ptr); } }; -template -class RootedBase> - : public MutableUniquePtrOperations>, T, D> -{ }; - -template -class MutableHandleBase> - : public MutableUniquePtrOperations>, T, D> -{ }; - -template -class HandleBase> - : public UniquePtrOperations>, T, D> -{ }; - -template -class PersistentRootedBase> - : public MutableUniquePtrOperations>, T, D> -{ }; - namespace gc { template @@ -1324,6 +1318,177 @@ Swap(JS::TenuredHeap& aX, JS::TenuredHeap& aY) } /* namespace mozilla */ +namespace js { +namespace detail { + +// DefineComparisonOps is a trait which selects which wrapper classes to define +// operator== and operator!= for. It supplies a getter function to extract the +// value to compare. This is used to avoid triggering the automatic read +// barriers where appropriate. +// +// If DefineComparisonOps is not specialized for a particular wrapper you may +// get errors such as 'invalid operands to binary expression' or 'no match for +// operator==' when trying to compare against instances of the wrapper. + +template +struct DefineComparisonOps : mozilla::FalseType {}; + +template +struct DefineComparisonOps> : mozilla::TrueType { + static const T& get(const JS::Heap& v) { return v.unbarrieredGet(); } +}; + +template +struct DefineComparisonOps> : mozilla::TrueType { + static const T get(const JS::TenuredHeap& v) { return v.unbarrieredGetPtr(); } +}; + +template <> +struct DefineComparisonOps : mozilla::TrueType { + static const JSObject* get(const JS::ObjectPtr& v) { return v.unbarrieredGet(); } +}; + +template +struct DefineComparisonOps> : mozilla::TrueType { + static const T& get(const JS::Rooted& v) { return v.get(); } +}; + +template +struct DefineComparisonOps> : mozilla::TrueType { + static const T& get(const JS::Handle& v) { return v.get(); } +}; + +template +struct DefineComparisonOps> : mozilla::TrueType { + static const T& get(const JS::MutableHandle& v) { return v.get(); } +}; + +template +struct DefineComparisonOps> : mozilla::TrueType { + static const T& get(const JS::PersistentRooted& v) { return v.get(); } +}; + +template +struct DefineComparisonOps> : mozilla::TrueType { + static const T& get(const js::FakeRooted& v) { return v.get(); } +}; + +template +struct DefineComparisonOps> : mozilla::TrueType { + static const T& get(const js::FakeMutableHandle& v) { return v.get(); } +}; + +} /* namespace detail */ +} /* namespace js */ + +// Overload operator== and operator!= for all types with the DefineComparisonOps +// trait using the supplied getter. +// +// There are four cases: + +// Case 1: comparison between two wrapper objects. + +template +typename mozilla::EnableIf::value && + js::detail::DefineComparisonOps::value, bool>::Type +operator==(const T& a, const U& b) { + return js::detail::DefineComparisonOps::get(a) == js::detail::DefineComparisonOps::get(b); +} + +template +typename mozilla::EnableIf::value && + js::detail::DefineComparisonOps::value, bool>::Type +operator!=(const T& a, const U& b) { + return !(a == b); +} + +// Case 2: comparison between a wrapper object and its unwrapped element type. + +template +typename mozilla::EnableIf::value, bool>::Type +operator==(const T& a, const typename T::ElementType& b) { + return js::detail::DefineComparisonOps::get(a) == b; +} + +template +typename mozilla::EnableIf::value, bool>::Type +operator!=(const T& a, const typename T::ElementType& b) { + return !(a == b); +} + +template +typename mozilla::EnableIf::value, bool>::Type +operator==(const typename T::ElementType& a, const T& b) { + return a == js::detail::DefineComparisonOps::get(b); +} + +template +typename mozilla::EnableIf::value, bool>::Type +operator!=(const typename T::ElementType& a, const T& b) { + return !(a == b); +} + +// Case 3: For pointer wrappers, comparison between the wrapper and a const +// element pointer. + +template +typename mozilla::EnableIf::value && + mozilla::IsPointer::value, bool>::Type +operator==(const typename mozilla::RemovePointer::Type* a, const T& b) { + return a == js::detail::DefineComparisonOps::get(b); +} + +template +typename mozilla::EnableIf::value && + mozilla::IsPointer::value, bool>::Type +operator!=(const typename mozilla::RemovePointer::Type* a, const T& b) { + return !(a == b); +} + +template +typename mozilla::EnableIf::value && + mozilla::IsPointer::value, bool>::Type +operator==(const T& a, const typename mozilla::RemovePointer::Type* b) { + return js::detail::DefineComparisonOps::get(a) == b; +} + +template +typename mozilla::EnableIf::value && + mozilla::IsPointer::value, bool>::Type +operator!=(const T& a, const typename mozilla::RemovePointer::Type* b) { + return !(a == b); +} + +// Case 4: For pointer wrappers, comparison between the wrapper and nullptr. + +template +typename mozilla::EnableIf::value && + mozilla::IsPointer::value, bool>::Type +operator==(std::nullptr_t a, const T& b) { + return a == js::detail::DefineComparisonOps::get(b); +} + +template +typename mozilla::EnableIf::value && + mozilla::IsPointer::value, bool>::Type +operator!=(std::nullptr_t a, const T& b) { + return !(a == b); +} + +template +typename mozilla::EnableIf::value && + mozilla::IsPointer::value, bool>::Type +operator==(const T& a, std::nullptr_t b) { + return js::detail::DefineComparisonOps::get(a) == b; +} + +template +typename mozilla::EnableIf::value && + mozilla::IsPointer::value, bool>::Type +operator!=(const T& a, std::nullptr_t b) { + return !(a == b); +} + #undef DELETE_ASSIGNMENT_OPS #endif /* js_RootingAPI_h */ diff --git a/js/public/SweepingAPI.h b/js/public/SweepingAPI.h index 39abb0fc0..bbc1ec279 100644 --- a/js/public/SweepingAPI.h +++ b/js/public/SweepingAPI.h @@ -8,11 +8,6 @@ #include "js/HeapAPI.h" -namespace js { -template -class WeakCacheBase {}; -} // namespace js - namespace JS { template class WeakCache; @@ -24,7 +19,7 @@ RegisterWeakCache(JS::Zone* zone, JS::WeakCache* cachep); // A WeakCache stores the given Sweepable container and links itself into a // list of such caches that are swept during each GC. template -class WeakCache : public js::WeakCacheBase, +class WeakCache : public js::MutableWrappedPtrOperations>, private mozilla::LinkedListElement> { friend class mozilla::LinkedListElement>; diff --git a/js/public/Value.h b/js/public/Value.h index 087d178ef..c645f0773 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -1340,20 +1340,18 @@ struct BarrierMethods } }; -template class MutableValueOperations; +template 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 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 with a visible get() method returning a const + * reference to the Value abstracted by Wrapper. */ -template -class ValueOperations +template +class WrappedPtrOperations { - friend class MutableValueOperations; - - const JS::Value& value() const { return static_cast(this)->get(); } + const JS::Value& value() const { return static_cast(this)->get(); } public: bool isUndefined() const { return value().isUndefined(); } @@ -1398,17 +1396,17 @@ 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 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 with visible get() methods returning const and + * non-const references to the Value abstracted by Wrapper. */ -template -class MutableValueOperations : public ValueOperations +template +class MutableWrappedPtrOperations : public WrappedPtrOperations { protected: void set(const JS::Value& v) { // Call Outer::set to trigger any barriers. - static_cast(this)->set(v); + static_cast(this)->set(v); } public: @@ -1434,13 +1432,9 @@ class MutableValueOperations : public ValueOperations * Augment the generic Heap interface when T = Value with * type-querying, value-extracting, and mutating operations. */ -template <> -class HeapBase : public MutableValueOperations > +template +class HeapBase : public MutableWrappedPtrOperations { - typedef JS::Heap Outer; - - friend class ValueOperations; - public: void setNumber(uint32_t ui) { if (ui > JSVAL_INT_MAX) { @@ -1460,22 +1454,6 @@ class HeapBase : public MutableValueOperations > } }; -template <> -class HandleBase : public ValueOperations > -{}; - -template <> -class MutableHandleBase : public MutableValueOperations > -{}; - -template <> -class RootedBase : public MutableValueOperations > -{}; - -template <> -class PersistentRootedBase : public MutableValueOperations> -{}; - /* * 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. -- cgit v1.2.3