1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef js_RootingAPI_h
8 #define js_RootingAPI_h
10 #include "mozilla/Attributes.h"
11 #include "mozilla/DebugOnly.h"
12 #include "mozilla/EnumeratedArray.h"
13 #include "mozilla/LinkedList.h"
14 #include "mozilla/Maybe.h"
16 #include <type_traits>
21 #include "js/ComparisonOperators.h" // JS::detail::DefineComparisonOps
22 #include "js/GCAnnotations.h"
23 #include "js/GCPolicyAPI.h"
24 #include "js/GCTypeMacros.h" // JS_FOR_EACH_PUBLIC_{,TAGGED_}GC_POINTER_TYPE
25 #include "js/HashTable.h"
26 #include "js/HeapAPI.h" // StackKindCount
27 #include "js/ProfilingStack.h"
29 #include "js/Stack.h" // JS::NativeStackLimit
30 #include "js/TypeDecls.h"
31 #include "js/UniquePtr.h"
34 * [SMDOC] Stack Rooting
36 * Moving GC Stack Rooting
38 * A moving GC may change the physical location of GC allocated things, even
39 * when they are rooted, updating all pointers to the thing to refer to its new
40 * location. The GC must therefore know about all live pointers to a thing,
41 * not just one of them, in order to behave correctly.
43 * The |Rooted| and |Handle| classes below are used to root stack locations
44 * whose value may be held live across a call that can trigger GC. For a
45 * code fragment such as:
47 * JSObject* obj = NewObject(cx);
49 * ... = obj->lastProperty();
51 * If |DoSomething()| can trigger a GC, the stack location of |obj| must be
52 * rooted to ensure that the GC does not move the JSObject referred to by
53 * |obj| without updating |obj|'s location itself. This rooting must happen
54 * regardless of whether there are other roots which ensure that the object
55 * itself will not be collected.
57 * If |DoSomething()| cannot trigger a GC, and the same holds for all other
58 * calls made between |obj|'s definitions and its last uses, then no rooting
61 * SpiderMonkey can trigger a GC at almost any time and in ways that are not
62 * always clear. For example, the following innocuous-looking actions can
63 * cause a GC: allocation of any new GC thing; JSObject::hasProperty;
64 * JS_ReportError and friends; and ToNumber, among many others. The following
65 * dangerous-looking actions cannot trigger a GC: js_malloc, cx->malloc_,
66 * rt->malloc_, and friends and JS_ReportOutOfMemory.
68 * The following family of three classes will exactly root a stack location.
69 * Incorrect usage of these classes will result in a compile error in almost
70 * all cases. Therefore, it is very hard to be incorrectly rooted if you use
71 * these classes exclusively. These classes are all templated on the type T of
72 * the value being rooted.
74 * - Rooted<T> declares a variable of type T, whose value is always rooted.
75 * Rooted<T> may be automatically coerced to a Handle<T>, below. Rooted<T>
76 * should be used whenever a local variable's value may be held live across a
77 * call which can trigger a GC.
79 * - Handle<T> is a const reference to a Rooted<T>. Functions which take GC
80 * things or values as arguments and need to root those arguments should
81 * generally use handles for those arguments and avoid any explicit rooting.
82 * This has two benefits. First, when several such functions call each other
83 * then redundant rooting of multiple copies of the GC thing can be avoided.
84 * Second, if the caller does not pass a rooted value a compile error will be
85 * generated, which is quicker and easier to fix than when relying on a
86 * separate rooting analysis.
88 * - MutableHandle<T> is a non-const reference to Rooted<T>. It is used in the
89 * same way as Handle<T> and includes a |set(const T& v)| method to allow
90 * updating the value of the referenced Rooted<T>. A MutableHandle<T> can be
91 * created with an implicit cast from a Rooted<T>*.
93 * In some cases the small performance overhead of exact rooting (measured to
94 * be a few nanoseconds on desktop) is too much. In these cases, try the
97 * - Move all Rooted<T> above inner loops: this allows you to re-use the root
98 * on each iteration of the loop.
100 * - Pass Handle<T> through your hot call stack to avoid re-rooting costs at
103 * The following diagram explains the list of supported, implicit type
104 * conversions between classes of this family:
106 * Rooted<T> ----> Handle<T>
110 * +---> MutableHandle<T>
113 * All of these types have an implicit conversion to raw pointers.
120 // The defaulted Enable parameter for the following two types is for restricting
121 // specializations with std::enable_if.
122 template <typename T
, typename Enable
= void>
123 struct BarrierMethods
{};
125 template <typename Element
, typename Wrapper
, typename Enable
= void>
126 class WrappedPtrOperations
{};
128 template <typename Element
, typename Wrapper
>
129 class MutableWrappedPtrOperations
130 : public WrappedPtrOperations
<Element
, Wrapper
> {};
132 template <typename T
, typename Wrapper
>
133 class RootedOperations
: public MutableWrappedPtrOperations
<T
, Wrapper
> {};
135 template <typename T
, typename Wrapper
>
136 class HandleOperations
: public WrappedPtrOperations
<T
, Wrapper
> {};
138 template <typename T
, typename Wrapper
>
139 class MutableHandleOperations
: public MutableWrappedPtrOperations
<T
, Wrapper
> {
142 template <typename T
, typename Wrapper
>
143 class HeapOperations
: public MutableWrappedPtrOperations
<T
, Wrapper
> {};
145 // Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many
148 // Add a 2nd template parameter to allow conditionally enabling partial
149 // specializations via std::enable_if.
150 template <typename T
, typename Enable
= void>
151 struct IsHeapConstructibleType
: public std::false_type
{};
153 #define JS_DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE(T) \
155 struct IsHeapConstructibleType<T> : public std::true_type {};
156 JS_FOR_EACH_PUBLIC_GC_POINTER_TYPE(JS_DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE
)
157 JS_FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(JS_DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE
)
158 // Note that JS_DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE is left defined, to allow
159 // declaring other types (eg from js/public/experimental/TypedData.h) to
160 // be used with Heap<>.
166 // Important: Return a reference so passing a Rooted<T>, etc. to
167 // something that takes a |const T&| is not a GC hazard.
168 #define DECLARE_POINTER_CONSTREF_OPS(T) \
169 operator const T&() const { return get(); } \
170 const T& operator->() const { return get(); }
172 // Assignment operators on a base class are hidden by the implicitly defined
173 // operator= on the derived class. Thus, define the operator= directly on the
174 // class as we would need to manually pass it through anyway.
175 #define DECLARE_POINTER_ASSIGN_OPS(Wrapper, T) \
176 Wrapper<T>& operator=(const T& p) { \
180 Wrapper<T>& operator=(T&& p) { \
184 Wrapper<T>& operator=(const Wrapper<T>& other) { \
189 #define DELETE_ASSIGNMENT_OPS(Wrapper, T) \
190 template <typename S> \
191 Wrapper<T>& operator=(S) = delete; \
192 Wrapper<T>& operator=(const Wrapper<T>&) = delete;
194 #define DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr) \
195 const T* address() const { return &(ptr); } \
196 const T& get() const { return (ptr); }
198 #define DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(ptr) \
199 T* address() { return &(ptr); } \
200 T& get() { return (ptr); }
206 JS_PUBLIC_API
void HeapObjectPostWriteBarrier(JSObject
** objp
, JSObject
* prev
,
208 JS_PUBLIC_API
void HeapStringPostWriteBarrier(JSString
** objp
, JSString
* prev
,
210 JS_PUBLIC_API
void HeapBigIntPostWriteBarrier(JS::BigInt
** bip
,
213 JS_PUBLIC_API
void HeapObjectWriteBarriers(JSObject
** objp
, JSObject
* prev
,
215 JS_PUBLIC_API
void HeapStringWriteBarriers(JSString
** objp
, JSString
* prev
,
217 JS_PUBLIC_API
void HeapBigIntWriteBarriers(JS::BigInt
** bip
, JS::BigInt
* prev
,
219 JS_PUBLIC_API
void HeapScriptWriteBarriers(JSScript
** objp
, JSScript
* prev
,
223 * SafelyInitialized<T>::create() creates a safely-initialized |T|, suitable for
224 * use as a default value in situations requiring a safe but arbitrary |T|
225 * value. Implemented as a static method of a struct to allow partial
226 * specialization for subclasses via the Enable template parameter.
228 template <typename T
, typename Enable
= void>
229 struct SafelyInitialized
{
231 // This function wants to presume that |T()| -- which value-initializes a
232 // |T| per C++11 [expr.type.conv]p2 -- will produce a safely-initialized,
233 // safely-usable T that it can return.
235 #if defined(XP_WIN) || defined(XP_MACOSX) || \
236 (defined(XP_UNIX) && !defined(__clang__))
238 // That presumption holds for pointers, where value initialization produces
240 constexpr bool IsPointer
= std::is_pointer_v
<T
>;
242 // For classes and unions we *assume* that if |T|'s default constructor is
243 // non-trivial it'll initialize correctly. (This is unideal, but C++
244 // doesn't offer a type trait indicating whether a class's constructor is
245 // user-defined, which better approximates our desired semantics.)
246 constexpr bool IsNonTriviallyDefaultConstructibleClassOrUnion
=
247 (std::is_class_v
<T
> ||
248 std::is_union_v
<T
>)&&!std::is_trivially_default_constructible_v
<T
>;
250 static_assert(IsPointer
|| IsNonTriviallyDefaultConstructibleClassOrUnion
,
251 "T() must evaluate to a safely-initialized T");
261 * For generational GC, assert that an object is in the tenured generation as
262 * opposed to being in the nursery.
264 extern JS_PUBLIC_API
void AssertGCThingMustBeTenured(JSObject
* obj
);
265 extern JS_PUBLIC_API
void AssertGCThingIsNotNurseryAllocable(
268 inline void AssertGCThingMustBeTenured(JSObject
* obj
) {}
269 inline void AssertGCThingIsNotNurseryAllocable(js::gc::Cell
* cell
) {}
273 * The Heap<T> class is a heap-stored reference to a JS GC thing for use outside
274 * the JS engine. All members of heap classes that refer to GC things should use
275 * Heap<T> (or possibly TenuredHeap<T>, described below).
277 * Heap<T> is an abstraction that hides some of the complexity required to
278 * maintain GC invariants for the contained reference. It uses operator
279 * overloading to provide a normal pointer interface, but adds barriers to
280 * notify the GC of changes.
282 * Heap<T> implements the following barriers:
284 * - Post-write barrier (necessary for generational GC).
285 * - Read barrier (necessary for incremental GC and cycle collector
288 * Note Heap<T> does not have a pre-write barrier as used internally in the
289 * engine. The read barrier is used to mark anything read from a Heap<T> during
292 * Heap<T> may be moved or destroyed outside of GC finalization and hence may be
293 * used in dynamic storage such as a Vector.
295 * Heap<T> instances must be traced when their containing object is traced to
296 * keep the pointed-to GC thing alive.
298 * Heap<T> objects should only be used on the heap. GC references stored on the
299 * C/C++ stack must use Rooted/Handle/MutableHandle instead.
301 * Type T must be a public GC pointer type.
303 template <typename T
>
304 class MOZ_NON_MEMMOVABLE Heap
: public js::HeapOperations
<T
, Heap
<T
>> {
305 // Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for
307 static_assert(js::IsHeapConstructibleType
<T
>::value
,
308 "Type T must be a public GC pointer type");
311 using ElementType
= T
;
313 Heap() : ptr(SafelyInitialized
<T
>::create()) {
314 // No barriers are required for initialization to the default value.
315 static_assert(sizeof(T
) == sizeof(Heap
<T
>),
316 "Heap<T> must be binary compatible with T.");
318 explicit Heap(const T
& p
) : ptr(p
) {
319 postWriteBarrier(SafelyInitialized
<T
>::create(), ptr
);
323 * For Heap, move semantics are equivalent to copy semantics. However, we want
324 * the copy constructor to be explicit, and an explicit move constructor
325 * breaks common usage of move semantics, so we need to define both, even
326 * though they are equivalent.
328 explicit Heap(const Heap
<T
>& other
) : ptr(other
.getWithoutExpose()) {
329 postWriteBarrier(SafelyInitialized
<T
>::create(), ptr
);
331 Heap(Heap
<T
>&& other
) : ptr(other
.getWithoutExpose()) {
332 postWriteBarrier(SafelyInitialized
<T
>::create(), ptr
);
335 Heap
& operator=(Heap
<T
>&& other
) {
336 set(other
.getWithoutExpose());
337 other
.set(SafelyInitialized
<T
>::create());
341 ~Heap() { postWriteBarrier(ptr
, SafelyInitialized
<T
>::create()); }
343 DECLARE_POINTER_CONSTREF_OPS(T
);
344 DECLARE_POINTER_ASSIGN_OPS(Heap
, T
);
346 const T
* address() const { return &ptr
; }
348 void exposeToActiveJS() const { js::BarrierMethods
<T
>::exposeToJS(ptr
); }
350 const T
& get() const {
354 const T
& getWithoutExpose() const {
355 js::BarrierMethods
<T
>::readBarrier(ptr
);
358 const T
& unbarrieredGet() const { return ptr
; }
360 void set(const T
& newPtr
) {
363 postWriteBarrier(tmp
, ptr
);
366 T
* unsafeGet() { return &ptr
; }
368 void unbarrieredSet(const T
& newPtr
) { ptr
= newPtr
; }
370 explicit operator bool() const {
371 return bool(js::BarrierMethods
<T
>::asGCThingOrNull(ptr
));
373 explicit operator bool() {
374 return bool(js::BarrierMethods
<T
>::asGCThingOrNull(ptr
));
378 void postWriteBarrier(const T
& prev
, const T
& next
) {
379 js::BarrierMethods
<T
>::postWriteBarrier(&ptr
, prev
, next
);
387 template <typename T
>
388 struct DefineComparisonOps
<Heap
<T
>> : std::true_type
{
389 static const T
& get(const Heap
<T
>& v
) { return v
.unbarrieredGet(); }
392 } // namespace detail
394 static MOZ_ALWAYS_INLINE
bool ObjectIsTenured(JSObject
* obj
) {
395 return !js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell
*>(obj
));
398 static MOZ_ALWAYS_INLINE
bool ObjectIsTenured(const Heap
<JSObject
*>& obj
) {
399 return ObjectIsTenured(obj
.unbarrieredGet());
402 static MOZ_ALWAYS_INLINE
bool ObjectIsMarkedGray(JSObject
* obj
) {
403 auto cell
= reinterpret_cast<js::gc::Cell
*>(obj
);
404 if (js::gc::IsInsideNursery(cell
)) {
408 auto tenuredCell
= reinterpret_cast<js::gc::TenuredCell
*>(cell
);
409 return js::gc::detail::CellIsMarkedGrayIfKnown(tenuredCell
);
412 static MOZ_ALWAYS_INLINE
bool ObjectIsMarkedGray(
413 const JS::Heap
<JSObject
*>& obj
) {
414 return ObjectIsMarkedGray(obj
.unbarrieredGet());
417 // The following *IsNotGray functions take account of the eventual
418 // gray marking state at the end of any ongoing incremental GC by
419 // delaying the checks if necessary.
423 inline void AssertCellIsNotGray(const js::gc::Cell
* maybeCell
) {
425 js::gc::detail::AssertCellIsNotGray(maybeCell
);
429 inline void AssertObjectIsNotGray(JSObject
* maybeObj
) {
430 AssertCellIsNotGray(reinterpret_cast<js::gc::Cell
*>(maybeObj
));
433 inline void AssertObjectIsNotGray(const JS::Heap
<JSObject
*>& obj
) {
434 AssertObjectIsNotGray(obj
.unbarrieredGet());
439 inline void AssertCellIsNotGray(js::gc::Cell
* maybeCell
) {}
440 inline void AssertObjectIsNotGray(JSObject
* maybeObj
) {}
441 inline void AssertObjectIsNotGray(const JS::Heap
<JSObject
*>& obj
) {}
446 * The TenuredHeap<T> class is similar to the Heap<T> class above in that it
447 * encapsulates the GC concerns of an on-heap reference to a JS object. However,
448 * it has two important differences:
450 * 1) Pointers which are statically known to only reference "tenured" objects
451 * can avoid the extra overhead of SpiderMonkey's write barriers.
453 * 2) Objects in the "tenured" heap have stronger alignment restrictions than
454 * those in the "nursery", so it is possible to store flags in the lower
455 * bits of pointers known to be tenured. TenuredHeap wraps a normal tagged
456 * pointer with a nice API for accessing the flag bits and adds various
457 * assertions to ensure that it is not mis-used.
459 * GC things are said to be "tenured" when they are located in the long-lived
460 * heap: e.g. they have gained tenure as an object by surviving past at least
461 * one GC. For performance, SpiderMonkey allocates some things which are known
462 * to normally be long lived directly into the tenured generation; for example,
463 * global objects. Additionally, SpiderMonkey does not visit individual objects
464 * when deleting non-tenured objects, so object with finalizers are also always
465 * tenured; for instance, this includes most DOM objects.
467 * The considerations to keep in mind when using a TenuredHeap<T> vs a normal
470 * - It is invalid for a TenuredHeap<T> to refer to a non-tenured thing.
471 * - It is however valid for a Heap<T> to refer to a tenured thing.
472 * - It is not possible to store flag bits in a Heap<T>.
474 template <typename T
>
475 class TenuredHeap
: public js::HeapOperations
<T
, TenuredHeap
<T
>> {
477 using ElementType
= T
;
479 TenuredHeap() : bits(0) {
480 static_assert(sizeof(T
) == sizeof(TenuredHeap
<T
>),
481 "TenuredHeap<T> must be binary compatible with T.");
483 explicit TenuredHeap(T p
) : bits(0) { setPtr(p
); }
484 explicit TenuredHeap(const TenuredHeap
<T
>& p
) : bits(0) {
488 void setPtr(T newPtr
) {
489 MOZ_ASSERT((reinterpret_cast<uintptr_t>(newPtr
) & flagsMask
) == 0);
490 MOZ_ASSERT(js::gc::IsCellPointerValidOrNull(newPtr
));
492 AssertGCThingMustBeTenured(newPtr
);
494 bits
= (bits
& flagsMask
) | reinterpret_cast<uintptr_t>(newPtr
);
497 void setFlags(uintptr_t flagsToSet
) {
498 MOZ_ASSERT((flagsToSet
& ~flagsMask
) == 0);
502 void unsetFlags(uintptr_t flagsToUnset
) {
503 MOZ_ASSERT((flagsToUnset
& ~flagsMask
) == 0);
504 bits
&= ~flagsToUnset
;
507 bool hasFlag(uintptr_t flag
) const {
508 MOZ_ASSERT((flag
& ~flagsMask
) == 0);
509 return (bits
& flag
) != 0;
512 T
unbarrieredGetPtr() const { return reinterpret_cast<T
>(bits
& ~flagsMask
); }
513 uintptr_t getFlags() const { return bits
& flagsMask
; }
515 void exposeToActiveJS() const {
516 js::BarrierMethods
<T
>::exposeToJS(unbarrieredGetPtr());
520 return unbarrieredGetPtr();
523 operator T() const { return getPtr(); }
524 T
operator->() const { return getPtr(); }
526 explicit operator bool() const {
527 return bool(js::BarrierMethods
<T
>::asGCThingOrNull(unbarrieredGetPtr()));
529 explicit operator bool() {
530 return bool(js::BarrierMethods
<T
>::asGCThingOrNull(unbarrieredGetPtr()));
533 TenuredHeap
<T
>& operator=(T p
) {
538 TenuredHeap
<T
>& operator=(const TenuredHeap
<T
>& other
) {
546 flagsMask
= (1 << maskBits
) - 1,
554 template <typename T
>
555 struct DefineComparisonOps
<TenuredHeap
<T
>> : std::true_type
{
556 static const T
get(const TenuredHeap
<T
>& v
) { return v
.unbarrieredGetPtr(); }
559 } // namespace detail
561 // std::swap uses a stack temporary, which prevents classes like Heap<T>
562 // from being declared MOZ_HEAP_CLASS.
563 template <typename T
>
564 void swap(TenuredHeap
<T
>& aX
, TenuredHeap
<T
>& aY
) {
570 template <typename T
>
571 void swap(Heap
<T
>& aX
, Heap
<T
>& aY
) {
577 static MOZ_ALWAYS_INLINE
bool ObjectIsMarkedGray(
578 const JS::TenuredHeap
<JSObject
*>& obj
) {
579 return ObjectIsMarkedGray(obj
.unbarrieredGetPtr());
582 template <typename T
>
584 template <typename T
>
586 template <typename T
>
587 class PersistentRooted
;
590 * Reference to a T that has been rooted elsewhere. This is most useful
591 * as a parameter type, which guarantees that the T lvalue is properly
592 * rooted. See "Move GC Stack Rooting" above.
594 * If you want to add additional methods to Handle for a specific
595 * specialization, define a HandleOperations<T> specialization containing them.
597 template <typename T
>
598 class MOZ_NONHEAP_CLASS Handle
: public js::HandleOperations
<T
, Handle
<T
>> {
599 friend class MutableHandle
<T
>;
602 using ElementType
= T
;
604 Handle(const Handle
<T
>&) = default;
606 /* Creates a handle from a handle of a type convertible to T. */
607 template <typename S
>
610 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
= 0) {
611 static_assert(sizeof(Handle
<T
>) == sizeof(T
*),
612 "Handle must be binary compatible with T*.");
613 ptr
= reinterpret_cast<const T
*>(handle
.address());
616 MOZ_IMPLICIT
Handle(decltype(nullptr)) {
617 static_assert(std::is_pointer_v
<T
>,
618 "nullptr_t overload not valid for non-pointer types");
619 static void* const ConstNullValue
= nullptr;
620 ptr
= reinterpret_cast<const T
*>(&ConstNullValue
);
623 MOZ_IMPLICIT
Handle(MutableHandle
<T
> handle
) { ptr
= handle
.address(); }
626 * Take care when calling this method!
628 * This creates a Handle from the raw location of a T.
630 * It should be called only if the following conditions hold:
632 * 1) the location of the T is guaranteed to be marked (for some reason
633 * other than being a Rooted), e.g., if it is guaranteed to be reachable
634 * from an implicit root.
636 * 2) the contents of the location are immutable, or at least cannot change
637 * for the lifetime of the handle, as its users may not expect its value
638 * to change underneath them.
640 static constexpr Handle
fromMarkedLocation(const T
* p
) {
641 return Handle(p
, DeliberatelyChoosingThisOverload
,
642 ImUsingThisOnlyInFromFromMarkedLocation
);
646 * Construct a handle from an explicitly rooted location. This is the
647 * normal way to create a handle, and normally happens implicitly.
649 template <typename S
>
650 inline MOZ_IMPLICIT
Handle(
651 const Rooted
<S
>& root
,
652 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
= 0);
654 template <typename S
>
655 inline MOZ_IMPLICIT
Handle(
656 const PersistentRooted
<S
>& root
,
657 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
= 0);
659 /* Construct a read only handle from a mutable handle. */
660 template <typename S
>
661 inline MOZ_IMPLICIT
Handle(
662 MutableHandle
<S
>& root
,
663 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
= 0);
665 DECLARE_POINTER_CONSTREF_OPS(T
);
666 DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr
);
670 DELETE_ASSIGNMENT_OPS(Handle
, T
);
672 enum Disambiguator
{ DeliberatelyChoosingThisOverload
= 42 };
673 enum CallerIdentity
{ ImUsingThisOnlyInFromFromMarkedLocation
= 17 };
674 constexpr Handle(const T
* p
, Disambiguator
, CallerIdentity
) : ptr(p
) {}
681 template <typename T
>
682 struct DefineComparisonOps
<Handle
<T
>> : std::true_type
{
683 static const T
& get(const Handle
<T
>& v
) { return v
.get(); }
686 } // namespace detail
689 * Similar to a handle, but the underlying storage can be changed. This is
690 * useful for outparams.
692 * If you want to add additional methods to MutableHandle for a specific
693 * specialization, define a MutableHandleOperations<T> specialization containing
696 template <typename T
>
697 class MOZ_STACK_CLASS MutableHandle
698 : public js::MutableHandleOperations
<T
, MutableHandle
<T
>> {
700 using ElementType
= T
;
702 inline MOZ_IMPLICIT
MutableHandle(Rooted
<T
>* root
);
703 inline MOZ_IMPLICIT
MutableHandle(PersistentRooted
<T
>* root
);
706 // Disallow nullptr for overloading purposes.
707 MutableHandle(decltype(nullptr)) = delete;
710 MutableHandle(const MutableHandle
<T
>&) = default;
711 void set(const T
& v
) {
713 MOZ_ASSERT(GCPolicy
<T
>::isValid(*ptr
));
717 MOZ_ASSERT(GCPolicy
<T
>::isValid(*ptr
));
721 * This may be called only if the location of the T is guaranteed
722 * to be marked (for some reason other than being a Rooted),
723 * e.g., if it is guaranteed to be reachable from an implicit root.
725 * Create a MutableHandle from a raw location of a T.
727 static MutableHandle
fromMarkedLocation(T
* p
) {
733 DECLARE_POINTER_CONSTREF_OPS(T
);
734 DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr
);
735 DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(*ptr
);
738 MutableHandle() = default;
739 DELETE_ASSIGNMENT_OPS(MutableHandle
, T
);
746 template <typename T
>
747 struct DefineComparisonOps
<MutableHandle
<T
>> : std::true_type
{
748 static const T
& get(const MutableHandle
<T
>& v
) { return v
.get(); }
751 } // namespace detail
759 // Default implementations for barrier methods on GC thing pointers.
760 template <typename T
>
761 struct PtrBarrierMethodsBase
{
762 static T
* initial() { return nullptr; }
763 static gc::Cell
* asGCThingOrNull(T
* v
) {
767 MOZ_ASSERT(uintptr_t(v
) > 32);
768 return reinterpret_cast<gc::Cell
*>(v
);
770 static void exposeToJS(T
* t
) {
772 js::gc::ExposeGCThingToActiveJS(JS::GCCellPtr(t
));
775 static void readBarrier(T
* t
) {
777 js::gc::IncrementalReadBarrier(JS::GCCellPtr(t
));
782 } // namespace detail
784 template <typename T
>
785 struct BarrierMethods
<T
*> : public detail::PtrBarrierMethodsBase
<T
> {
786 static void postWriteBarrier(T
** vp
, T
* prev
, T
* next
) {
788 JS::AssertGCThingIsNotNurseryAllocable(
789 reinterpret_cast<js::gc::Cell
*>(next
));
795 struct BarrierMethods
<JSObject
*>
796 : public detail::PtrBarrierMethodsBase
<JSObject
> {
797 static void postWriteBarrier(JSObject
** vp
, JSObject
* prev
, JSObject
* next
) {
798 JS::HeapObjectPostWriteBarrier(vp
, prev
, next
);
800 static void exposeToJS(JSObject
* obj
) {
802 JS::ExposeObjectToActiveJS(obj
);
808 struct BarrierMethods
<JSFunction
*>
809 : public detail::PtrBarrierMethodsBase
<JSFunction
> {
810 static void postWriteBarrier(JSFunction
** vp
, JSFunction
* prev
,
812 JS::HeapObjectPostWriteBarrier(reinterpret_cast<JSObject
**>(vp
),
813 reinterpret_cast<JSObject
*>(prev
),
814 reinterpret_cast<JSObject
*>(next
));
816 static void exposeToJS(JSFunction
* fun
) {
818 JS::ExposeObjectToActiveJS(reinterpret_cast<JSObject
*>(fun
));
824 struct BarrierMethods
<JSString
*>
825 : public detail::PtrBarrierMethodsBase
<JSString
> {
826 static void postWriteBarrier(JSString
** vp
, JSString
* prev
, JSString
* next
) {
827 JS::HeapStringPostWriteBarrier(vp
, prev
, next
);
832 struct BarrierMethods
<JS::BigInt
*>
833 : public detail::PtrBarrierMethodsBase
<JS::BigInt
> {
834 static void postWriteBarrier(JS::BigInt
** vp
, JS::BigInt
* prev
,
836 JS::HeapBigIntPostWriteBarrier(vp
, prev
, next
);
840 // Provide hash codes for Cell kinds that may be relocated and, thus, not have
841 // a stable address to use as the base for a hash code. Instead of the address,
842 // this hasher uses Cell::getUniqueId to provide exact matches and as a base
843 // for generating hash codes.
845 // Note: this hasher, like PointerHasher can "hash" a nullptr. While a nullptr
846 // would not likely be a useful key, there are some cases where being able to
847 // hash a nullptr is useful, either on purpose or because of bugs:
848 // (1) existence checks where the key may happen to be null and (2) some
849 // aggregate Lookup kinds embed a JSObject* that is frequently null and do not
850 // null test before dispatching to the hasher.
851 template <typename T
>
852 struct JS_PUBLIC_API StableCellHasher
{
856 static bool maybeGetHash(const Lookup
& l
, mozilla::HashNumber
* hashOut
);
857 static bool ensureHash(const Lookup
& l
, HashNumber
* hashOut
);
858 static HashNumber
hash(const Lookup
& l
);
859 static bool match(const Key
& k
, const Lookup
& l
);
860 // The rekey hash policy method is not provided since you dont't need to
861 // rekey any more when using this policy.
864 template <typename T
>
865 struct JS_PUBLIC_API StableCellHasher
<JS::Heap
<T
>> {
866 using Key
= JS::Heap
<T
>;
869 static bool maybeGetHash(const Lookup
& l
, HashNumber
* hashOut
) {
870 return StableCellHasher
<T
>::maybeGetHash(l
, hashOut
);
872 static bool ensureHash(const Lookup
& l
, HashNumber
* hashOut
) {
873 return StableCellHasher
<T
>::ensureHash(l
, hashOut
);
875 static HashNumber
hash(const Lookup
& l
) {
876 return StableCellHasher
<T
>::hash(l
);
878 static bool match(const Key
& k
, const Lookup
& l
) {
879 return StableCellHasher
<T
>::match(k
.unbarrieredGet(), l
);
887 template <typename T
>
888 struct FallibleHashMethods
<js::StableCellHasher
<T
>> {
889 template <typename Lookup
>
890 static bool maybeGetHash(Lookup
&& l
, HashNumber
* hashOut
) {
891 return js::StableCellHasher
<T
>::maybeGetHash(std::forward
<Lookup
>(l
),
894 template <typename Lookup
>
895 static bool ensureHash(Lookup
&& l
, HashNumber
* hashOut
) {
896 return js::StableCellHasher
<T
>::ensureHash(std::forward
<Lookup
>(l
),
901 } // namespace mozilla
905 struct VirtualTraceable
{
906 virtual ~VirtualTraceable() = default;
907 virtual void trace(JSTracer
* trc
, const char* name
) = 0;
910 class StackRootedBase
{
912 StackRootedBase
* previous() { return prev
; }
915 StackRootedBase
** stack
;
916 StackRootedBase
* prev
;
918 template <typename T
>
920 return static_cast<JS::Rooted
<T
>*>(this);
924 class PersistentRootedBase
925 : protected mozilla::LinkedListElement
<PersistentRootedBase
> {
927 friend class mozilla::LinkedList
<PersistentRootedBase
>;
928 friend class mozilla::LinkedListElement
<PersistentRootedBase
>;
930 template <typename T
>
932 return static_cast<JS::PersistentRooted
<T
>*>(this);
936 struct StackRootedTraceableBase
: public StackRootedBase
,
937 public VirtualTraceable
{};
939 class PersistentRootedTraceableBase
: public PersistentRootedBase
,
940 public VirtualTraceable
{};
942 template <typename Base
, typename T
>
943 class TypedRootedGCThingBase
: public Base
{
945 void trace(JSTracer
* trc
, const char* name
);
948 template <typename Base
, typename T
>
949 class TypedRootedTraceableBase
: public Base
{
951 void trace(JSTracer
* trc
, const char* name
) override
{
952 auto* self
= this->template derived
<T
>();
953 JS::GCPolicy
<T
>::trace(trc
, self
->address(), name
);
957 template <typename T
>
958 struct RootedTraceableTraits
{
959 using StackBase
= TypedRootedTraceableBase
<StackRootedTraceableBase
, T
>;
960 using PersistentBase
=
961 TypedRootedTraceableBase
<PersistentRootedTraceableBase
, T
>;
964 template <typename T
>
965 struct RootedGCThingTraits
{
966 using StackBase
= TypedRootedGCThingBase
<StackRootedBase
, T
>;
967 using PersistentBase
= TypedRootedGCThingBase
<PersistentRootedBase
, T
>;
974 class JS_PUBLIC_API AutoGCRooter
;
976 enum class AutoGCRooterKind
: uint8_t {
977 WrapperVector
, /* js::AutoWrapperVector */
978 Wrapper
, /* js::AutoWrapperRooter */
979 Custom
, /* js::CustomAutoRooter */
984 using RootedListHeads
=
985 mozilla::EnumeratedArray
<RootKind
, RootKind::Limit
, js::StackRootedBase
*>;
987 using AutoRooterListHeads
=
988 mozilla::EnumeratedArray
<AutoGCRooterKind
, AutoGCRooterKind::Limit
,
991 // Superclass of JSContext which can be used for rooting data in use by the
992 // current thread but that does not provide all the functions of a JSContext.
993 class RootingContext
{
994 // Stack GC roots for Rooted GC heap pointers.
995 RootedListHeads stackRoots_
;
996 template <typename T
>
999 // Stack GC roots for AutoFooRooter classes.
1000 AutoRooterListHeads autoGCRooters_
;
1001 friend class AutoGCRooter
;
1003 // Gecko profiling metadata.
1004 // This isn't really rooting related. It's only here because we want
1005 // GetContextProfilingStackIfEnabled to be inlineable into non-JS code, and
1006 // we didn't want to add another superclass of JSContext just for this.
1007 js::GeckoProfilerThread geckoProfiler_
;
1010 explicit RootingContext(js::Nursery
* nursery
);
1012 void traceStackRoots(JSTracer
* trc
);
1014 /* Implemented in gc/RootMarking.cpp. */
1015 void traceAllGCRooters(JSTracer
* trc
);
1016 void traceWrapperGCRooters(JSTracer
* trc
);
1017 static void traceGCRooterList(JSTracer
* trc
, AutoGCRooter
* head
);
1019 void checkNoGCRooters();
1021 js::GeckoProfilerThread
& geckoProfiler() { return geckoProfiler_
; }
1023 js::Nursery
& nursery() const {
1024 MOZ_ASSERT(nursery_
);
1029 // The remaining members in this class should only be accessed through
1030 // JSContext pointers. They are unrelated to rooting and are in place so
1031 // that inlined API functions can directly access the data.
1033 /* The nursery. Null for non-main-thread contexts. */
1034 js::Nursery
* nursery_
;
1036 /* The current zone. */
1039 /* The current realm. */
1043 /* Limit pointer for checking native stack consumption. */
1044 JS::NativeStackLimit nativeStackLimit
[StackKindCount
];
1047 // For WASI we can't catch call-stack overflows with stack-pointer checks, so
1048 // we count recursion depth with RAII based AutoCheckRecursionLimit.
1049 uint32_t wasiRecursionDepth
= 0u;
1051 static constexpr uint32_t wasiRecursionDepthLimit
= 350u;
1054 static const RootingContext
* get(const JSContext
* cx
) {
1055 return reinterpret_cast<const RootingContext
*>(cx
);
1058 static RootingContext
* get(JSContext
* cx
) {
1059 return reinterpret_cast<RootingContext
*>(cx
);
1062 friend JS::Realm
* js::GetContextRealm(const JSContext
* cx
);
1063 friend JS::Zone
* js::GetContextZone(const JSContext
* cx
);
1066 class JS_PUBLIC_API AutoGCRooter
{
1068 using Kind
= AutoGCRooterKind
;
1070 AutoGCRooter(JSContext
* cx
, Kind kind
)
1071 : AutoGCRooter(JS::RootingContext::get(cx
), kind
) {}
1072 AutoGCRooter(RootingContext
* cx
, Kind kind
)
1073 : down(cx
->autoGCRooters_
[kind
]),
1074 stackTop(&cx
->autoGCRooters_
[kind
]),
1076 MOZ_ASSERT(this != *stackTop
);
1081 MOZ_ASSERT(this == *stackTop
);
1085 void trace(JSTracer
* trc
);
1088 friend class RootingContext
;
1090 AutoGCRooter
* const down
;
1091 AutoGCRooter
** const stackTop
;
1094 * Discriminates actual subclass of this being used. The meaning is
1095 * indicated by the corresponding value in the Kind enum.
1099 /* No copy or assignment semantics. */
1100 AutoGCRooter(AutoGCRooter
& ida
) = delete;
1101 void operator=(AutoGCRooter
& ida
) = delete;
1102 } JS_HAZ_ROOTED_BASE
;
1105 * Custom rooting behavior for internal and external clients.
1107 * Deprecated. Where possible, use Rooted<> instead.
1109 class MOZ_RAII JS_PUBLIC_API CustomAutoRooter
: private AutoGCRooter
{
1111 template <typename CX
>
1112 explicit CustomAutoRooter(const CX
& cx
)
1113 : AutoGCRooter(cx
, AutoGCRooter::Kind::Custom
) {}
1115 friend void AutoGCRooter::trace(JSTracer
* trc
);
1118 virtual ~CustomAutoRooter() = default;
1120 /** Supplied by derived class to trace roots. */
1121 virtual void trace(JSTracer
* trc
) = 0;
1126 template <typename T
>
1127 constexpr bool IsTraceable_v
=
1128 MapTypeToRootKind
<T
>::kind
== JS::RootKind::Traceable
;
1130 template <typename T
>
1131 using RootedTraits
=
1132 std::conditional_t
<IsTraceable_v
<T
>, js::RootedTraceableTraits
<T
>,
1133 js::RootedGCThingTraits
<T
>>;
1135 } /* namespace detail */
1138 * Local variable of type T whose value is always rooted. This is typically
1139 * used for local variables, or for non-rooted values being passed to a
1140 * function that requires a handle, e.g. Foo(Root<T>(cx, x)).
1142 * If you want to add additional methods to Rooted for a specific
1143 * specialization, define a RootedOperations<T> specialization containing them.
1145 template <typename T
>
1146 class MOZ_RAII Rooted
: public detail::RootedTraits
<T
>::StackBase
,
1147 public js::RootedOperations
<T
, Rooted
<T
>> {
1148 inline void registerWithRootLists(RootedListHeads
& roots
) {
1149 this->stack
= &roots
[JS::MapTypeToRootKind
<T
>::kind
];
1150 this->prev
= *this->stack
;
1151 *this->stack
= this;
1154 inline RootedListHeads
& rootLists(RootingContext
* cx
) {
1155 return cx
->stackRoots_
;
1157 inline RootedListHeads
& rootLists(JSContext
* cx
) {
1158 return rootLists(RootingContext::get(cx
));
1162 using ElementType
= T
;
1164 // Construct an empty Rooted holding a safely initialized but empty T.
1165 // Requires T to have a copy constructor in order to copy the safely
1166 // initialized value.
1168 // Note that for SFINAE to reject this method, the 2nd template parameter must
1169 // depend on RootingContext somehow even though we really only care about T.
1170 template <typename RootingContext
,
1171 typename
= std::enable_if_t
<std::is_copy_constructible_v
<T
>,
1173 explicit Rooted(const RootingContext
& cx
)
1174 : ptr(SafelyInitialized
<T
>::create()) {
1175 registerWithRootLists(rootLists(cx
));
1178 // Provide an initial value. Requires T to be constructible from the given
1180 template <typename RootingContext
, typename S
>
1181 Rooted(const RootingContext
& cx
, S
&& initial
)
1182 : ptr(std::forward
<S
>(initial
)) {
1183 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1184 registerWithRootLists(rootLists(cx
));
1187 // (Traceables only) Construct the contained value from the given arguments.
1188 // Constructs in-place, so T does not need to be copyable or movable.
1190 // Note that a copyable Traceable passed only a RootingContext will
1191 // choose the above SafelyInitialized<T> constructor, because otherwise
1192 // identical functions with parameter packs are considered less specialized.
1194 // The SFINAE type must again depend on an inferred template parameter.
1196 typename RootingContext
, typename
... CtorArgs
,
1197 typename
= std::enable_if_t
<detail::IsTraceable_v
<T
>, RootingContext
>>
1198 explicit Rooted(const RootingContext
& cx
, CtorArgs
... args
)
1199 : ptr(std::forward
<CtorArgs
>(args
)...) {
1200 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1201 registerWithRootLists(rootLists(cx
));
1205 MOZ_ASSERT(*this->stack
== this);
1206 *this->stack
= this->prev
;
1210 * This method is public for Rooted so that Codegen.py can use a Rooted
1211 * interchangeably with a MutableHandleValue.
1213 void set(const T
& value
) {
1215 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1217 void set(T
&& value
) {
1218 ptr
= std::move(value
);
1219 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1222 DECLARE_POINTER_CONSTREF_OPS(T
);
1223 DECLARE_POINTER_ASSIGN_OPS(Rooted
, T
);
1225 T
& get() { return ptr
; }
1226 const T
& get() const { return ptr
; }
1228 T
* address() { return &ptr
; }
1229 const T
* address() const { return &ptr
; }
1234 Rooted(const Rooted
&) = delete;
1239 template <typename T
>
1240 struct DefineComparisonOps
<Rooted
<T
>> : std::true_type
{
1241 static const T
& get(const Rooted
<T
>& v
) { return v
.get(); }
1244 } // namespace detail
1246 } /* namespace JS */
1251 * Inlinable accessors for JSContext.
1253 * - These must not be available on the more restricted superclasses of
1254 * JSContext, so we can't simply define them on RootingContext.
1256 * - They're perfectly ordinary JSContext functionality, so ought to be
1257 * usable without resorting to jsfriendapi.h, and when JSContext is an
1260 inline JS::Realm
* GetContextRealm(const JSContext
* cx
) {
1261 return JS::RootingContext::get(cx
)->realm_
;
1264 inline JS::Compartment
* GetContextCompartment(const JSContext
* cx
) {
1265 if (JS::Realm
* realm
= GetContextRealm(cx
)) {
1266 return GetCompartmentForRealm(realm
);
1271 inline JS::Zone
* GetContextZone(const JSContext
* cx
) {
1272 return JS::RootingContext::get(cx
)->zone_
;
1275 inline ProfilingStack
* GetContextProfilingStackIfEnabled(JSContext
* cx
) {
1276 return JS::RootingContext::get(cx
)
1278 .getProfilingStackIfEnabled();
1282 * Augment the generic Rooted<T> interface when T = JSObject* with
1283 * class-querying and downcasting operations.
1285 * Given a Rooted<JSObject*> obj, one can view
1286 * Handle<StringObject*> h = obj.as<StringObject*>();
1287 * as an optimization of
1288 * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
1289 * Handle<StringObject*> h = rooted;
1291 template <typename Container
>
1292 class RootedOperations
<JSObject
*, Container
>
1293 : public MutableWrappedPtrOperations
<JSObject
*, Container
> {
1296 JS::Handle
<U
*> as() const;
1300 * Augment the generic Handle<T> interface when T = JSObject* with
1301 * downcasting operations.
1303 * Given a Handle<JSObject*> obj, one can view
1304 * Handle<StringObject*> h = obj.as<StringObject*>();
1305 * as an optimization of
1306 * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
1307 * Handle<StringObject*> h = rooted;
1309 template <typename Container
>
1310 class HandleOperations
<JSObject
*, Container
>
1311 : public WrappedPtrOperations
<JSObject
*, Container
> {
1314 JS::Handle
<U
*> as() const;
1317 } /* namespace js */
1321 template <typename T
>
1322 template <typename S
>
1323 inline Handle
<T
>::Handle(
1324 const Rooted
<S
>& root
,
1325 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
) {
1326 ptr
= reinterpret_cast<const T
*>(root
.address());
1329 template <typename T
>
1330 template <typename S
>
1331 inline Handle
<T
>::Handle(
1332 const PersistentRooted
<S
>& root
,
1333 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
) {
1334 ptr
= reinterpret_cast<const T
*>(root
.address());
1337 template <typename T
>
1338 template <typename S
>
1339 inline Handle
<T
>::Handle(
1340 MutableHandle
<S
>& root
,
1341 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
) {
1342 ptr
= reinterpret_cast<const T
*>(root
.address());
1345 template <typename T
>
1346 inline MutableHandle
<T
>::MutableHandle(Rooted
<T
>* root
) {
1347 static_assert(sizeof(MutableHandle
<T
>) == sizeof(T
*),
1348 "MutableHandle must be binary compatible with T*.");
1349 ptr
= root
->address();
1352 template <typename T
>
1353 inline MutableHandle
<T
>::MutableHandle(PersistentRooted
<T
>* root
) {
1354 static_assert(sizeof(MutableHandle
<T
>) == sizeof(T
*),
1355 "MutableHandle must be binary compatible with T*.");
1356 ptr
= root
->address();
1359 JS_PUBLIC_API
void AddPersistentRoot(RootingContext
* cx
, RootKind kind
,
1360 js::PersistentRootedBase
* root
);
1362 JS_PUBLIC_API
void AddPersistentRoot(JSRuntime
* rt
, RootKind kind
,
1363 js::PersistentRootedBase
* root
);
1366 * A copyable, assignable global GC root type with arbitrary lifetime, an
1367 * infallible constructor, and automatic unrooting on destruction.
1369 * These roots can be used in heap-allocated data structures, so they are not
1370 * associated with any particular JSContext or stack. They are registered with
1371 * the JSRuntime itself, without locking. Initialization may take place on
1372 * construction, or in two phases if the no-argument constructor is called
1373 * followed by init().
1375 * Note that you must not use an PersistentRooted in an object owned by a JS
1378 * Whenever one object whose lifetime is decided by the GC refers to another
1379 * such object, that edge must be traced only if the owning JS object is traced.
1380 * This applies not only to JS objects (which obviously are managed by the GC)
1381 * but also to C++ objects owned by JS objects.
1383 * If you put a PersistentRooted in such a C++ object, that is almost certainly
1384 * a leak. When a GC begins, the referent of the PersistentRooted is treated as
1385 * live, unconditionally (because a PersistentRooted is a *root*), even if the
1386 * JS object that owns it is unreachable. If there is any path from that
1387 * referent back to the JS object, then the C++ object containing the
1388 * PersistentRooted will not be destructed, and the whole blob of objects will
1389 * not be freed, even if there are no references to them from the outside.
1391 * In the context of Firefox, this is a severe restriction: almost everything in
1392 * Firefox is owned by some JS object or another, so using PersistentRooted in
1393 * such objects would introduce leaks. For these kinds of edges, Heap<T> or
1394 * TenuredHeap<T> would be better types. It's up to the implementor of the type
1395 * containing Heap<T> or TenuredHeap<T> members to make sure their referents get
1396 * marked when the object itself is marked.
1398 template <typename T
>
1399 class PersistentRooted
: public detail::RootedTraits
<T
>::PersistentBase
,
1400 public js::RootedOperations
<T
, PersistentRooted
<T
>> {
1401 void registerWithRootLists(RootingContext
* cx
) {
1402 MOZ_ASSERT(!initialized());
1403 JS::RootKind kind
= JS::MapTypeToRootKind
<T
>::kind
;
1404 AddPersistentRoot(cx
, kind
, this);
1407 void registerWithRootLists(JSRuntime
* rt
) {
1408 MOZ_ASSERT(!initialized());
1409 JS::RootKind kind
= JS::MapTypeToRootKind
<T
>::kind
;
1410 AddPersistentRoot(rt
, kind
, this);
1413 // Used when JSContext type is incomplete and so it is not known to inherit
1414 // from RootingContext.
1415 void registerWithRootLists(JSContext
* cx
) {
1416 registerWithRootLists(RootingContext::get(cx
));
1420 using ElementType
= T
;
1422 PersistentRooted() : ptr(SafelyInitialized
<T
>::create()) {}
1425 typename RootHolder
,
1426 typename
= std::enable_if_t
<std::is_copy_constructible_v
<T
>, RootHolder
>>
1427 explicit PersistentRooted(const RootHolder
& cx
)
1428 : ptr(SafelyInitialized
<T
>::create()) {
1429 registerWithRootLists(cx
);
1433 typename RootHolder
, typename U
,
1434 typename
= std::enable_if_t
<std::is_constructible_v
<T
, U
>, RootHolder
>>
1435 PersistentRooted(const RootHolder
& cx
, U
&& initial
)
1436 : ptr(std::forward
<U
>(initial
)) {
1437 registerWithRootLists(cx
);
1440 template <typename RootHolder
, typename
... CtorArgs
,
1441 typename
= std::enable_if_t
<detail::IsTraceable_v
<T
>, RootHolder
>>
1442 explicit PersistentRooted(const RootHolder
& cx
, CtorArgs
... args
)
1443 : ptr(std::forward
<CtorArgs
>(args
)...) {
1444 registerWithRootLists(cx
);
1447 PersistentRooted(const PersistentRooted
& rhs
) : ptr(rhs
.ptr
) {
1449 * Copy construction takes advantage of the fact that the original
1450 * is already inserted, and simply adds itself to whatever list the
1451 * original was on - no JSRuntime pointer needed.
1453 * This requires mutating rhs's links, but those should be 'mutable'
1454 * anyway. C++ doesn't let us declare mutable base classes.
1456 const_cast<PersistentRooted
&>(rhs
).setNext(this);
1459 bool initialized() const { return this->isInList(); }
1461 void init(RootingContext
* cx
) { init(cx
, SafelyInitialized
<T
>::create()); }
1462 void init(JSContext
* cx
) { init(RootingContext::get(cx
)); }
1464 template <typename U
>
1465 void init(RootingContext
* cx
, U
&& initial
) {
1466 ptr
= std::forward
<U
>(initial
);
1467 registerWithRootLists(cx
);
1469 template <typename U
>
1470 void init(JSContext
* cx
, U
&& initial
) {
1471 ptr
= std::forward
<U
>(initial
);
1472 registerWithRootLists(RootingContext::get(cx
));
1476 if (initialized()) {
1477 set(SafelyInitialized
<T
>::create());
1482 DECLARE_POINTER_CONSTREF_OPS(T
);
1483 DECLARE_POINTER_ASSIGN_OPS(PersistentRooted
, T
);
1485 T
& get() { return ptr
; }
1486 const T
& get() const { return ptr
; }
1489 MOZ_ASSERT(initialized());
1492 const T
* address() const { return &ptr
; }
1494 template <typename U
>
1495 void set(U
&& value
) {
1496 MOZ_ASSERT(initialized());
1497 ptr
= std::forward
<U
>(value
);
1506 template <typename T
>
1507 struct DefineComparisonOps
<PersistentRooted
<T
>> : std::true_type
{
1508 static const T
& get(const PersistentRooted
<T
>& v
) { return v
.get(); }
1511 } // namespace detail
1513 } /* namespace JS */
1517 template <typename T
, typename D
, typename Container
>
1518 class WrappedPtrOperations
<UniquePtr
<T
, D
>, Container
> {
1519 const UniquePtr
<T
, D
>& uniquePtr() const {
1520 return static_cast<const Container
*>(this)->get();
1524 explicit operator bool() const { return !!uniquePtr(); }
1525 T
* get() const { return uniquePtr().get(); }
1526 T
* operator->() const { return get(); }
1527 T
& operator*() const { return *uniquePtr(); }
1530 template <typename T
, typename D
, typename Container
>
1531 class MutableWrappedPtrOperations
<UniquePtr
<T
, D
>, Container
>
1532 : public WrappedPtrOperations
<UniquePtr
<T
, D
>, Container
> {
1533 UniquePtr
<T
, D
>& uniquePtr() { return static_cast<Container
*>(this)->get(); }
1536 [[nodiscard
]] typename UniquePtr
<T
, D
>::Pointer
release() {
1537 return uniquePtr().release();
1539 void reset(T
* ptr
= T()) { uniquePtr().reset(ptr
); }
1542 template <typename T
, typename Container
>
1543 class WrappedPtrOperations
<mozilla::Maybe
<T
>, Container
> {
1544 const mozilla::Maybe
<T
>& maybe() const {
1545 return static_cast<const Container
*>(this)->get();
1549 // This only supports a subset of Maybe's interface.
1550 bool isSome() const { return maybe().isSome(); }
1551 bool isNothing() const { return maybe().isNothing(); }
1552 const T
value() const { return maybe().value(); }
1553 const T
* operator->() const { return maybe().ptr(); }
1554 const T
& operator*() const { return maybe().ref(); }
1557 template <typename T
, typename Container
>
1558 class MutableWrappedPtrOperations
<mozilla::Maybe
<T
>, Container
>
1559 : public WrappedPtrOperations
<mozilla::Maybe
<T
>, Container
> {
1560 mozilla::Maybe
<T
>& maybe() { return static_cast<Container
*>(this)->get(); }
1563 // This only supports a subset of Maybe's interface.
1564 T
* operator->() { return maybe().ptr(); }
1565 T
& operator*() { return maybe().ref(); }
1566 void reset() { return maybe().reset(); }
1571 template <typename T
, typename TraceCallbacks
>
1572 void CallTraceCallbackOnNonHeap(T
* v
, const TraceCallbacks
& aCallbacks
,
1573 const char* aName
, void* aClosure
) {
1574 static_assert(sizeof(T
) == sizeof(JS::Heap
<T
>),
1575 "T and Heap<T> must be compatible.");
1577 mozilla::DebugOnly
<Cell
*> cell
= BarrierMethods
<T
>::asGCThingOrNull(*v
);
1579 MOZ_ASSERT(!IsInsideNursery(cell
));
1580 JS::Heap
<T
>* asHeapT
= reinterpret_cast<JS::Heap
<T
>*>(v
);
1581 aCallbacks
.Trace(asHeapT
, aName
, aClosure
);
1584 } /* namespace gc */
1586 template <typename Wrapper
, typename T1
, typename T2
>
1587 class WrappedPtrOperations
<std::pair
<T1
, T2
>, Wrapper
> {
1588 const std::pair
<T1
, T2
>& pair() const {
1589 return static_cast<const Wrapper
*>(this)->get();
1593 const T1
& first() const { return pair().first
; }
1594 const T2
& second() const { return pair().second
; }
1597 template <typename Wrapper
, typename T1
, typename T2
>
1598 class MutableWrappedPtrOperations
<std::pair
<T1
, T2
>, Wrapper
>
1599 : public WrappedPtrOperations
<std::pair
<T1
, T2
>, Wrapper
> {
1600 std::pair
<T1
, T2
>& pair() { return static_cast<Wrapper
*>(this)->get(); }
1603 T1
& first() { return pair().first
; }
1604 T2
& second() { return pair().second
; }
1607 } /* namespace js */
1609 #endif /* js_RootingAPI_h */