Backed out 7 changesets (bug 1731218) for causing spidermonkey build bustages in RootingAPI. CLOSED TREE

Backed out changeset 0dfcae852026 (bug 1731218)
Backed out changeset e2c59b5af7ea (bug 1731218)
Backed out changeset 3e98b832dcc6 (bug 1731218)
Backed out changeset 57e60277e4ca (bug 1731218)
Backed out changeset 3b264a4bc67e (bug 1731218)
Backed out changeset 304f27af6b95 (bug 1731218)
Backed out changeset 06e7a1992de8 (bug 1731218)
This commit is contained in:
Sandor Molnar 2021-09-21 11:37:12 +03:00
parent 2a78d18891
commit 10773301cf
8 changed files with 179 additions and 135 deletions

View File

@ -125,17 +125,16 @@ class MutableWrappedPtrOperations
: public WrappedPtrOperations<Element, Wrapper> {}; : public WrappedPtrOperations<Element, Wrapper> {};
template <typename T, typename Wrapper> template <typename T, typename Wrapper>
class RootedOperations : public MutableWrappedPtrOperations<T, Wrapper> {}; class RootedBase : public MutableWrappedPtrOperations<T, Wrapper> {};
template <typename T, typename Wrapper> template <typename T, typename Wrapper>
class HandleOperations : public WrappedPtrOperations<T, Wrapper> {}; class HandleBase : public WrappedPtrOperations<T, Wrapper> {};
template <typename T, typename Wrapper> template <typename T, typename Wrapper>
class MutableHandleOperations : public MutableWrappedPtrOperations<T, Wrapper> { class MutableHandleBase : public MutableWrappedPtrOperations<T, Wrapper> {};
};
template <typename T, typename Wrapper> template <typename T, typename Wrapper>
class HeapOperations : public MutableWrappedPtrOperations<T, Wrapper> {}; class HeapBase : public MutableWrappedPtrOperations<T, Wrapper> {};
// Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many // Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many
// macros into scope // macros into scope
@ -290,7 +289,7 @@ inline void AssertGCThingIsNotNurseryAllocable(js::gc::Cell* cell) {}
* Type T must be a public GC pointer type. * Type T must be a public GC pointer type.
*/ */
template <typename T> template <typename T>
class MOZ_NON_MEMMOVABLE Heap : public js::HeapOperations<T, Heap<T>> { class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T, Heap<T>> {
// Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for // Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for
// legacy reasons. // legacy reasons.
static_assert(js::IsHeapConstructibleType<T>::value, static_assert(js::IsHeapConstructibleType<T>::value,
@ -450,7 +449,7 @@ inline void AssertObjectIsNotGray(const JS::Heap<JSObject*>& obj) {}
* - It is not possible to store flag bits in a Heap<T>. * - It is not possible to store flag bits in a Heap<T>.
*/ */
template <typename T> template <typename T>
class TenuredHeap : public js::HeapOperations<T, TenuredHeap<T>> { class TenuredHeap : public js::HeapBase<T, TenuredHeap<T>> {
public: public:
using ElementType = T; using ElementType = T;
@ -570,10 +569,10 @@ class PersistentRooted;
* rooted. See "Move GC Stack Rooting" above. * rooted. See "Move GC Stack Rooting" above.
* *
* If you want to add additional methods to Handle for a specific * If you want to add additional methods to Handle for a specific
* specialization, define a HandleOperations<T> specialization containing them. * specialization, define a HandleBase<T> specialization containing them.
*/ */
template <typename T> template <typename T>
class MOZ_NONHEAP_CLASS Handle : public js::HandleOperations<T, Handle<T>> { class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T, Handle<T>> {
friend class MutableHandle<T>; friend class MutableHandle<T>;
public: public:
@ -668,12 +667,12 @@ struct DefineComparisonOps<Handle<T>> : std::true_type {
* useful for outparams. * useful for outparams.
* *
* If you want to add additional methods to MutableHandle for a specific * If you want to add additional methods to MutableHandle for a specific
* specialization, define a MutableHandleOperations<T> specialization containing * specialization, define a MutableHandleBase<T> specialization containing
* them. * them.
*/ */
template <typename T> template <typename T>
class MOZ_STACK_CLASS MutableHandle class MOZ_STACK_CLASS MutableHandle
: public js::MutableHandleOperations<T, MutableHandle<T>> { : public js::MutableHandleBase<T, MutableHandle<T>> {
public: public:
using ElementType = T; using ElementType = T;
@ -878,64 +877,40 @@ struct VirtualTraceable {
virtual void trace(JSTracer* trc, const char* name) = 0; virtual void trace(JSTracer* trc, const char* name) = 0;
}; };
class StackRootedBase { template <typename T>
public: struct RootedTraceable final : public VirtualTraceable {
StackRootedBase* previous() { return prev; } static_assert(JS::MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
"RootedTraceable is intended only for usage with a Traceable");
protected: T ptr;
StackRootedBase** stack;
StackRootedBase* prev;
template <typename T> template <typename... CtorArgs>
auto* derived() { explicit RootedTraceable(std::in_place_t, CtorArgs... args)
return static_cast<JS::Rooted<T>*>(this); : ptr(std::forward<CtorArgs>(args)...) {}
}
};
class PersistentRootedBase template <typename U, typename = typename std::is_constructible<T, U>::type>
: protected mozilla::LinkedListElement<PersistentRootedBase> { MOZ_IMPLICIT RootedTraceable(U&& initial) : ptr(std::forward<U>(initial)) {}
protected:
friend class mozilla::LinkedList<PersistentRootedBase>;
friend class mozilla::LinkedListElement<PersistentRootedBase>;
template <typename T> operator T&() { return ptr; }
auto* derived() { operator const T&() const { return ptr; }
return static_cast<JS::PersistentRooted<T>*>(this);
}
};
struct StackRootedTraceableBase : public StackRootedBase,
public VirtualTraceable {};
class PersistentRootedTraceableBase : public PersistentRootedBase,
public VirtualTraceable {};
template <typename Base, typename T>
class TypedRootedGCThingBase : public Base {
public:
void trace(JSTracer* trc, const char* name);
};
template <typename Base, typename T>
class TypedRootedTraceableBase : public Base {
public:
void trace(JSTracer* trc, const char* name) override { void trace(JSTracer* trc, const char* name) override {
auto* self = this->template derived<T>(); JS::GCPolicy<T>::trace(trc, &ptr, name);
JS::GCPolicy<T>::trace(trc, self->address(), name);
} }
}; };
template <typename T> template <typename T>
struct RootedTraceableTraits { struct RootedTraceableTraits {
using StackRootedBase = TypedRootedTraceableBase<StackRootedTraceableBase, T>; static T* address(RootedTraceable<T>& self) { return &self.ptr; }
using PersistentRootedBase = static const T* address(const RootedTraceable<T>& self) { return &self.ptr; }
TypedRootedTraceableBase<PersistentRootedTraceableBase, T>; static void trace(JSTracer* trc, VirtualTraceable* thingp, const char* name);
}; };
template <typename T> template <typename T>
struct RootedGCThingTraits { struct RootedGCThingTraits {
using StackRootedBase = TypedRootedGCThingBase<StackRootedBase, T>; static T* address(T& self) { return &self; }
using PersistentRootedBase = TypedRootedGCThingBase<PersistentRootedBase, T>; static const T* address(const T& self) { return &self; }
static void trace(JSTracer* trc, T* thingp, const char* name);
}; };
} /* namespace js */ } /* namespace js */
@ -952,8 +927,29 @@ enum class AutoGCRooterKind : uint8_t {
Limit Limit
}; };
namespace detail {
// Dummy type to store root list entry pointers as. This code does not just use
// the actual type, because then eg JSObject* and JSFunction* would be assumed
// to never alias but they do (they are stored in the same list). Also, do not
// use `void*` so that `Rooted<void*>` is a compile error.
struct RootListEntry;
} // namespace detail
template <>
struct MapTypeToRootKind<detail::RootListEntry*> {
static const RootKind kind = RootKind::Traceable;
};
// Workaround MSVC issue where GCPolicy is needed even though this dummy type is
// never instantiated. Ideally, RootListEntry is removed in the future and an
// appropriate class hierarchy for the Rooted<T> types.
template <>
struct GCPolicy<detail::RootListEntry*>
: public IgnoreGCPolicy<detail::RootListEntry*> {};
using RootedListHeads = using RootedListHeads =
mozilla::EnumeratedArray<RootKind, RootKind::Limit, js::StackRootedBase*>; mozilla::EnumeratedArray<RootKind, RootKind::Limit,
Rooted<detail::RootListEntry*>*>;
using AutoRooterListHeads = using AutoRooterListHeads =
mozilla::EnumeratedArray<AutoGCRooterKind, AutoGCRooterKind::Limit, mozilla::EnumeratedArray<AutoGCRooterKind, AutoGCRooterKind::Limit,
@ -1090,6 +1086,10 @@ template <typename T>
constexpr bool IsTraceable_v = constexpr bool IsTraceable_v =
MapTypeToRootKind<T>::kind == JS::RootKind::Traceable; MapTypeToRootKind<T>::kind == JS::RootKind::Traceable;
template <typename T>
using RootedPtr =
std::conditional_t<IsTraceable_v<T>, js::RootedTraceable<T>, T>;
template <typename T> template <typename T>
using RootedPtrTraits = using RootedPtrTraits =
std::conditional_t<IsTraceable_v<T>, js::RootedTraceableTraits<T>, std::conditional_t<IsTraceable_v<T>, js::RootedTraceableTraits<T>,
@ -1103,17 +1103,17 @@ using RootedPtrTraits =
* function that requires a handle, e.g. Foo(Root<T>(cx, x)). * function that requires a handle, e.g. Foo(Root<T>(cx, x)).
* *
* If you want to add additional methods to Rooted for a specific * If you want to add additional methods to Rooted for a specific
* specialization, define a RootedOperations<T> specialization containing them. * specialization, define a RootedBase<T> specialization containing them.
*/ */
template <typename T> template <typename T>
class MOZ_RAII Rooted : public detail::RootedPtrTraits<T>::StackRootedBase, class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>> {
public js::RootedOperations<T, Rooted<T>> { using Ptr = detail::RootedPtr<T>;
using PtrTraits = detail::RootedPtrTraits<T>; using PtrTraits = detail::RootedPtrTraits<T>;
inline void registerWithRootLists(RootedListHeads& roots) { inline void registerWithRootLists(RootedListHeads& roots) {
this->stack = &roots[JS::MapTypeToRootKind<T>::kind]; this->stack = &roots[JS::MapTypeToRootKind<T>::kind];
this->prev = *this->stack; this->prev = *stack;
*this->stack = this; *stack = reinterpret_cast<Rooted<detail::RootListEntry*>*>(this);
} }
inline RootedListHeads& rootLists(RootingContext* cx) { inline RootedListHeads& rootLists(RootingContext* cx) {
@ -1141,7 +1141,8 @@ class MOZ_RAII Rooted : public detail::RootedPtrTraits<T>::StackRootedBase,
// Provide an initial value. Requires T to be constructible from the given // Provide an initial value. Requires T to be constructible from the given
// argument. // argument.
template <typename RootingContext, typename S> template <typename RootingContext, typename S,
typename = typename std::is_constructible<T, S>::type>
Rooted(const RootingContext& cx, S&& initial) Rooted(const RootingContext& cx, S&& initial)
: ptr(std::forward<S>(initial)) { : ptr(std::forward<S>(initial)) {
MOZ_ASSERT(GCPolicy<T>::isValid(ptr)); MOZ_ASSERT(GCPolicy<T>::isValid(ptr));
@ -1160,16 +1161,19 @@ class MOZ_RAII Rooted : public detail::RootedPtrTraits<T>::StackRootedBase,
typename RootingContext, typename... CtorArgs, typename RootingContext, typename... CtorArgs,
typename = std::enable_if_t<detail::IsTraceable_v<T>, RootingContext>> typename = std::enable_if_t<detail::IsTraceable_v<T>, RootingContext>>
explicit Rooted(const RootingContext& cx, CtorArgs... args) explicit Rooted(const RootingContext& cx, CtorArgs... args)
: ptr(std::forward<CtorArgs>(args)...) { : ptr(std::in_place, std::forward<CtorArgs>(args)...) {
MOZ_ASSERT(GCPolicy<T>::isValid(ptr)); MOZ_ASSERT(GCPolicy<T>::isValid(ptr));
registerWithRootLists(rootLists(cx)); registerWithRootLists(rootLists(cx));
} }
~Rooted() { ~Rooted() {
MOZ_ASSERT(*this->stack == this); MOZ_ASSERT(*stack ==
*this->stack = this->prev; reinterpret_cast<Rooted<detail::RootListEntry*>*>(this));
*stack = prev;
} }
Rooted<T>* previous() { return reinterpret_cast<Rooted<T>*>(prev); }
/* /*
* This method is public for Rooted so that Codegen.py can use a Rooted * This method is public for Rooted so that Codegen.py can use a Rooted
* interchangeably with a MutableHandleValue. * interchangeably with a MutableHandleValue.
@ -1189,11 +1193,21 @@ class MOZ_RAII Rooted : public detail::RootedPtrTraits<T>::StackRootedBase,
T& get() { return ptr; } T& get() { return ptr; }
const T& get() const { return ptr; } const T& get() const { return ptr; }
T* address() { return &ptr; } T* address() { return PtrTraits::address(ptr); }
const T* address() const { return &ptr; } const T* address() const { return PtrTraits::address(ptr); }
void trace(JSTracer* trc, const char* name);
private: private:
T ptr; /*
* These need to be templated on RootListEntry* to avoid aliasing issues
* between, for example, Rooted<JSObject*> and Rooted<JSFunction*>, which use
* the same stack head pointer for different classes.
*/
Rooted<detail::RootListEntry*>** stack;
Rooted<detail::RootListEntry*>* prev;
Ptr ptr;
Rooted(const Rooted&) = delete; Rooted(const Rooted&) = delete;
} JS_HAZ_ROOTED; } JS_HAZ_ROOTED;
@ -1253,7 +1267,7 @@ inline ProfilingStack* GetContextProfilingStackIfEnabled(JSContext* cx) {
* Handle<StringObject*> h = rooted; * Handle<StringObject*> h = rooted;
*/ */
template <typename Container> template <typename Container>
class RootedOperations<JSObject*, Container> class RootedBase<JSObject*, Container>
: public MutableWrappedPtrOperations<JSObject*, Container> { : public MutableWrappedPtrOperations<JSObject*, Container> {
public: public:
template <class U> template <class U>
@ -1271,7 +1285,7 @@ class RootedOperations<JSObject*, Container>
* Handle<StringObject*> h = rooted; * Handle<StringObject*> h = rooted;
*/ */
template <typename Container> template <typename Container>
class HandleOperations<JSObject*, Container> class HandleBase<JSObject*, Container>
: public WrappedPtrOperations<JSObject*, Container> { : public WrappedPtrOperations<JSObject*, Container> {
public: public:
template <class U> template <class U>
@ -1320,11 +1334,13 @@ inline MutableHandle<T>::MutableHandle(PersistentRooted<T>* root) {
ptr = root->address(); ptr = root->address();
} }
JS_PUBLIC_API void AddPersistentRoot(RootingContext* cx, RootKind kind, JS_PUBLIC_API void AddPersistentRoot(
js::PersistentRootedBase* root); RootingContext* cx, RootKind kind,
PersistentRooted<detail::RootListEntry*>* root);
JS_PUBLIC_API void AddPersistentRoot(JSRuntime* rt, RootKind kind, JS_PUBLIC_API void AddPersistentRoot(
js::PersistentRootedBase* root); JSRuntime* rt, RootKind kind,
PersistentRooted<detail::RootListEntry*>* root);
/** /**
* A copyable, assignable global GC root type with arbitrary lifetime, an * A copyable, assignable global GC root type with arbitrary lifetime, an
@ -1361,20 +1377,29 @@ JS_PUBLIC_API void AddPersistentRoot(JSRuntime* rt, RootKind kind,
*/ */
template <typename T> template <typename T>
class PersistentRooted class PersistentRooted
: public detail::RootedPtrTraits<T>::PersistentRootedBase, : public js::RootedBase<T, PersistentRooted<T>>,
public js::RootedOperations<T, PersistentRooted<T>> { private mozilla::LinkedListElement<PersistentRooted<T>> {
using ListBase = mozilla::LinkedListElement<PersistentRooted<T>>;
using Ptr = detail::RootedPtr<T>;
using PtrTraits = detail::RootedPtrTraits<T>; using PtrTraits = detail::RootedPtrTraits<T>;
friend class mozilla::LinkedList<PersistentRooted>;
friend class mozilla::LinkedListElement<PersistentRooted>;
void registerWithRootLists(RootingContext* cx) { void registerWithRootLists(RootingContext* cx) {
MOZ_ASSERT(!initialized()); MOZ_ASSERT(!initialized());
JS::RootKind kind = JS::MapTypeToRootKind<T>::kind; JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
AddPersistentRoot(cx, kind, this); AddPersistentRoot(
cx, kind,
reinterpret_cast<JS::PersistentRooted<detail::RootListEntry*>*>(this));
} }
void registerWithRootLists(JSRuntime* rt) { void registerWithRootLists(JSRuntime* rt) {
MOZ_ASSERT(!initialized()); MOZ_ASSERT(!initialized());
JS::RootKind kind = JS::MapTypeToRootKind<T>::kind; JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
AddPersistentRoot(rt, kind, this); AddPersistentRoot(
rt, kind,
reinterpret_cast<JS::PersistentRooted<detail::RootListEntry*>*>(this));
} }
// Used when JSContext type is incomplete and so it is not known to inherit // Used when JSContext type is incomplete and so it is not known to inherit
@ -1406,11 +1431,12 @@ class PersistentRooted
template <typename RootHolder, typename... CtorArgs, template <typename RootHolder, typename... CtorArgs,
typename = std::enable_if_t<detail::IsTraceable_v<T>, RootHolder>> typename = std::enable_if_t<detail::IsTraceable_v<T>, RootHolder>>
explicit PersistentRooted(const RootHolder& cx, CtorArgs... args) explicit PersistentRooted(const RootHolder& cx, CtorArgs... args)
: ptr(std::forward<CtorArgs>(args)...) { : ptr(std::in_place, std::forward<CtorArgs>(args)...) {
registerWithRootLists(cx); registerWithRootLists(cx);
} }
PersistentRooted(const PersistentRooted& rhs) : ptr(rhs.ptr) { PersistentRooted(const PersistentRooted& rhs)
: mozilla::LinkedListElement<PersistentRooted<T>>(), ptr(rhs.ptr) {
/* /*
* Copy construction takes advantage of the fact that the original * Copy construction takes advantage of the fact that the original
* is already inserted, and simply adds itself to whatever list the * is already inserted, and simply adds itself to whatever list the
@ -1422,7 +1448,7 @@ class PersistentRooted
const_cast<PersistentRooted&>(rhs).setNext(this); const_cast<PersistentRooted&>(rhs).setNext(this);
} }
bool initialized() const { return this->isInList(); } bool initialized() const { return ListBase::isInList(); }
void init(RootingContext* cx) { init(cx, SafelyInitialized<T>()); } void init(RootingContext* cx) { init(cx, SafelyInitialized<T>()); }
void init(JSContext* cx) { init(RootingContext::get(cx)); } void init(JSContext* cx) { init(RootingContext::get(cx)); }
@ -1441,7 +1467,7 @@ class PersistentRooted
void reset() { void reset() {
if (initialized()) { if (initialized()) {
set(SafelyInitialized<T>()); set(SafelyInitialized<T>());
this->remove(); ListBase::remove();
} }
} }
@ -1453,9 +1479,9 @@ class PersistentRooted
T* address() { T* address() {
MOZ_ASSERT(initialized()); MOZ_ASSERT(initialized());
return &ptr; return PtrTraits::address(ptr);
} }
const T* address() const { return &ptr; } const T* address() const { return PtrTraits::address(ptr); }
template <typename U> template <typename U>
void set(U&& value) { void set(U&& value) {
@ -1463,8 +1489,10 @@ class PersistentRooted
ptr = std::forward<U>(value); ptr = std::forward<U>(value);
} }
void trace(JSTracer* trc, const char* name);
private: private:
T ptr; Ptr ptr;
} JS_HAZ_ROOTED; } JS_HAZ_ROOTED;
namespace detail { namespace detail {

View File

@ -1217,7 +1217,7 @@ class MutableWrappedPtrOperations<JS::Value, Wrapper>
* type-querying, value-extracting, and mutating operations. * type-querying, value-extracting, and mutating operations.
*/ */
template <typename Wrapper> template <typename Wrapper>
class HeapOperations<JS::Value, Wrapper> class HeapBase<JS::Value, Wrapper>
: public MutableWrappedPtrOperations<JS::Value, Wrapper> {}; : public MutableWrappedPtrOperations<JS::Value, Wrapper> {};
MOZ_HAVE_NORETURN MOZ_COLD MOZ_NEVER_INLINE void ReportBadValueTypeAndCrash( MOZ_HAVE_NORETURN MOZ_COLD MOZ_NEVER_INLINE void ReportBadValueTypeAndCrash(

View File

@ -28,7 +28,7 @@ namespace js {
* memory. * memory.
*/ */
template <typename T> template <typename T>
class MOZ_RAII FakeRooted : public RootedOperations<T, FakeRooted<T>> { class MOZ_RAII FakeRooted : public RootedBase<T, FakeRooted<T>> {
public: public:
using ElementType = T; using ElementType = T;
@ -72,7 +72,7 @@ namespace js {
*/ */
template <typename T> template <typename T>
class FakeMutableHandle class FakeMutableHandle
: public js::MutableHandleOperations<T, FakeMutableHandle<T>> { : public js::MutableHandleBase<T, FakeMutableHandle<T>> {
public: public:
using ElementType = T; using ElementType = T;

View File

@ -40,30 +40,47 @@ using RootRange = RootedValueMap::Range;
using RootEntry = RootedValueMap::Entry; using RootEntry = RootedValueMap::Entry;
using RootEnum = RootedValueMap::Enum; using RootEnum = RootedValueMap::Enum;
template <typename Base, typename T> // For more detail see JS::Rooted::root and js::RootedTraceable.
inline void TypedRootedGCThingBase<Base, T>::trace(JSTracer* trc, //
const char* name) { // The JS::RootKind::Traceable list contains a bunch of totally disparate types,
auto* self = this->template derived<T>(); // but to refer to this list we need /something/ in the type field. We use the
TraceNullableRoot(trc, self->address(), name); // following type as a compatible stand-in. No actual methods from
// ConcreteTraceable type are actually used at runtime.
struct ConcreteTraceable {
ConcreteTraceable() = delete;
void trace(JSTracer*) = delete;
};
template <typename T>
inline void RootedGCThingTraits<T>::trace(JSTracer* trc, T* thingp,
const char* name) {
TraceNullableRoot(trc, thingp, name);
} }
template <typename T> template <typename T>
static inline void TraceExactStackRootList(JSTracer* trc, inline void RootedTraceableTraits<T>::trace(JSTracer* trc,
StackRootedBase* listHead, VirtualTraceable* thingp,
const char* name) { const char* name) {
// Check size of Rooted<T> does not increase. thingp->trace(trc, name);
static_assert(sizeof(Rooted<T>) == sizeof(T) + 2 * sizeof(uintptr_t));
for (StackRootedBase* root = listHead; root; root = root->previous()) {
static_cast<Rooted<T>*>(root)->trace(trc, name);
}
} }
static inline void TraceExactStackRootTraceableList(JSTracer* trc, template <typename T>
StackRootedBase* listHead, inline void JS::Rooted<T>::trace(JSTracer* trc, const char* name) {
const char* name) { PtrTraits::trace(trc, &ptr, name);
for (StackRootedBase* root = listHead; root; root = root->previous()) { }
static_cast<StackRootedTraceableBase*>(root)->trace(trc, name);
template <typename T>
inline void JS::PersistentRooted<T>::trace(JSTracer* trc, const char* name) {
PtrTraits::trace(trc, &ptr, name);
}
template <typename T>
static inline void TraceExactStackRootList(
JSTracer* trc, JS::Rooted<JS::detail::RootListEntry*>* listHead,
const char* name) {
auto* typedList = reinterpret_cast<JS::Rooted<T>*>(listHead);
for (JS::Rooted<T>* root = typedList; root; root = root->previous()) {
root->trace(trc, name);
} }
} }
@ -81,8 +98,8 @@ static inline void TraceStackRoots(JSTracer* trc,
// RootedTraceable uses virtual dispatch. // RootedTraceable uses virtual dispatch.
JS::AutoSuppressGCAnalysis nogc; JS::AutoSuppressGCAnalysis nogc;
TraceExactStackRootTraceableList(trc, stackRoots[JS::RootKind::Traceable], TraceExactStackRootList<ConcreteTraceable>(
"Traceable"); trc, stackRoots[JS::RootKind::Traceable], "Traceable");
} }
void JS::RootingContext::traceStackRoots(JSTracer* trc) { void JS::RootingContext::traceStackRoots(JSTracer* trc) {
@ -95,16 +112,12 @@ static void TraceExactStackRoots(JSContext* cx, JSTracer* trc) {
template <typename T> template <typename T>
static inline void TracePersistentRootedList( static inline void TracePersistentRootedList(
JSTracer* trc, LinkedList<PersistentRootedBase>& list, const char* name) { JSTracer* trc,
for (PersistentRootedBase* root : list) { LinkedList<PersistentRooted<JS::detail::RootListEntry*>>& list,
static_cast<PersistentRooted<T>*>(root)->trace(trc, name); const char* name) {
} auto& typedList = reinterpret_cast<LinkedList<PersistentRooted<T>>&>(list);
} for (PersistentRooted<T>* root : typedList) {
root->trace(trc, name);
static inline void TracePersistentRootedTraceableList(
JSTracer* trc, LinkedList<PersistentRootedBase>& list, const char* name) {
for (PersistentRootedBase* root : list) {
static_cast<PersistentRootedTraceableBase*>(root)->trace(trc, name);
} }
} }
@ -122,7 +135,7 @@ void JSRuntime::tracePersistentRoots(JSTracer* trc) {
// RootedTraceable uses virtual dispatch. // RootedTraceable uses virtual dispatch.
JS::AutoSuppressGCAnalysis nogc; JS::AutoSuppressGCAnalysis nogc;
TracePersistentRootedTraceableList( TracePersistentRootedList<ConcreteTraceable>(
trc, heapRoots.ref()[JS::RootKind::Traceable], "persistent-traceable"); trc, heapRoots.ref()[JS::RootKind::Traceable], "persistent-traceable");
} }
@ -132,9 +145,10 @@ static void TracePersistentRooted(JSRuntime* rt, JSTracer* trc) {
template <typename T> template <typename T>
static void FinishPersistentRootedChain( static void FinishPersistentRootedChain(
LinkedList<PersistentRootedBase>& list) { LinkedList<PersistentRooted<JS::detail::RootListEntry*>>& listArg) {
auto& list = reinterpret_cast<LinkedList<PersistentRooted<T>>&>(listArg);
while (!list.isEmpty()) { while (!list.isEmpty()) {
static_cast<PersistentRooted<T>*>(list.getFirst())->reset(); list.getFirst()->reset();
} }
} }
@ -454,13 +468,15 @@ void js::gc::GCRuntime::checkNoRuntimeRoots(AutoGCSession& session) {
#endif // DEBUG #endif // DEBUG
} }
JS_PUBLIC_API void JS::AddPersistentRoot(JS::RootingContext* cx, RootKind kind, JS_PUBLIC_API void JS::AddPersistentRoot(
PersistentRootedBase* root) { JS::RootingContext* cx, RootKind kind,
JSRuntime* rt = static_cast<JSContext*>(cx)->runtime(); PersistentRooted<JS::detail::RootListEntry*>* root) {
rt->heapRoots.ref()[kind].insertBack(root); static_cast<JSContext*>(cx)->runtime()->heapRoots.ref()[kind].insertBack(
root);
} }
JS_PUBLIC_API void JS::AddPersistentRoot(JSRuntime* rt, RootKind kind, JS_PUBLIC_API void JS::AddPersistentRoot(
PersistentRootedBase* root) { JSRuntime* rt, RootKind kind,
PersistentRooted<JS::detail::RootListEntry*>* root) {
rt->heapRoots.ref()[kind].insertBack(root); rt->heapRoots.ref()[kind].insertBack(root);
} }

View File

@ -123,7 +123,7 @@ BEGIN_TEST(testGCRootedStaticStructInternalStackStorageAugmented) {
JS::Rooted<Value> rv(cx); JS::Rooted<Value> rv(cx);
CHECK_EQUAL(r1.constructor(), 1); // direct SafelyInitialized<T> CHECK_EQUAL(r1.constructor(), 101); // copy of SafelyInitialized<T>
CHECK_EQUAL(r2.constructor(), 2); // direct MyContainer(3.4) CHECK_EQUAL(r2.constructor(), 2); // direct MyContainer(3.4)
CHECK_EQUAL(r3.constructor(), 103); // copy of MyContainer(cx) CHECK_EQUAL(r3.constructor(), 103); // copy of MyContainer(cx)
CHECK_EQUAL(r4.constructor(), 3); // direct MyContainer(cx) CHECK_EQUAL(r4.constructor(), 3); // direct MyContainer(cx)
@ -169,7 +169,7 @@ BEGIN_TEST(testGCRootedStaticStructInternalStackStorageAugmented) {
JS::PersistentRooted<MyContainer> cp3(cx, cx); JS::PersistentRooted<MyContainer> cp3(cx, cx);
JS::PersistentRooted<MyContainer> cp4(cx, cx, cx, cx); JS::PersistentRooted<MyContainer> cp4(cx, cx, cx, cx);
CHECK_EQUAL(cp1.constructor(), 1); // direct SafelyInitialized<T> CHECK_EQUAL(cp1.constructor(), 101); // copy of SafelyInitialized<T>
CHECK_EQUAL(cp2.constructor(), 2); // direct MyContainer(double) CHECK_EQUAL(cp2.constructor(), 2); // direct MyContainer(double)
CHECK_EQUAL(cp3.constructor(), 3); // direct MyContainer(cx) CHECK_EQUAL(cp3.constructor(), 3); // direct MyContainer(cx)
CHECK_EQUAL(cp4.constructor(), 4); // direct MyContainer(cx, cx, cx) CHECK_EQUAL(cp4.constructor(), 4); // direct MyContainer(cx, cx, cx)

View File

@ -1793,7 +1793,7 @@ static MOZ_ALWAYS_INLINE void InitElemArrayOperation(JSContext* cx,
*/ */
template <typename T> template <typename T>
class ReservedRooted : public RootedOperations<T, ReservedRooted<T>> { class ReservedRooted : public RootedBase<T, ReservedRooted<T>> {
Rooted<T>* savedRoot; Rooted<T>* savedRoot;
public: public:

View File

@ -564,7 +564,7 @@ inline bool JSObject::is<JSObject>() const {
template <typename Wrapper> template <typename Wrapper>
template <typename U> template <typename U>
MOZ_ALWAYS_INLINE JS::Handle<U*> js::RootedOperations<JSObject*, Wrapper>::as() MOZ_ALWAYS_INLINE JS::Handle<U*> js::RootedBase<JSObject*, Wrapper>::as()
const { const {
const Wrapper& self = *static_cast<const Wrapper*>(this); const Wrapper& self = *static_cast<const Wrapper*>(this);
MOZ_ASSERT(self->template is<U>()); MOZ_ASSERT(self->template is<U>());
@ -574,7 +574,7 @@ MOZ_ALWAYS_INLINE JS::Handle<U*> js::RootedOperations<JSObject*, Wrapper>::as()
template <typename Wrapper> template <typename Wrapper>
template <class U> template <class U>
MOZ_ALWAYS_INLINE JS::Handle<U*> js::HandleOperations<JSObject*, Wrapper>::as() MOZ_ALWAYS_INLINE JS::Handle<U*> js::HandleBase<JSObject*, Wrapper>::as()
const { const {
const JS::Handle<JSObject*>& self = const JS::Handle<JSObject*>& self =
*static_cast<const JS::Handle<JSObject*>*>(this); *static_cast<const JS::Handle<JSObject*>*>(this);

View File

@ -432,9 +432,9 @@ struct JSRuntime {
js::GeckoProfilerRuntime& geckoProfiler() { return geckoProfiler_.ref(); } js::GeckoProfilerRuntime& geckoProfiler() { return geckoProfiler_.ref(); }
// Heap GC roots for PersistentRooted pointers. // Heap GC roots for PersistentRooted pointers.
js::MainThreadData< js::MainThreadData<mozilla::EnumeratedArray<
mozilla::EnumeratedArray<JS::RootKind, JS::RootKind::Limit, JS::RootKind, JS::RootKind::Limit,
mozilla::LinkedList<js::PersistentRootedBase>>> mozilla::LinkedList<JS::PersistentRooted<JS::detail::RootListEntry*>>>>
heapRoots; heapRoots;
void tracePersistentRoots(JSTracer* trc); void tracePersistentRoots(JSTracer* trc);