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::Zone
* zoneUnchecked() const { return zone_
; }
1025 js::Nursery
& nursery() const {
1026 MOZ_ASSERT(nursery_
);
1031 // The remaining members in this class should only be accessed through
1032 // JSContext pointers. They are unrelated to rooting and are in place so
1033 // that inlined API functions can directly access the data.
1035 /* The nursery. Null for non-main-thread contexts. */
1036 js::Nursery
* nursery_
;
1038 /* The current zone. */
1041 /* The current realm. */
1045 /* Limit pointer for checking native stack consumption. */
1046 JS::NativeStackLimit nativeStackLimit
[StackKindCount
];
1049 // For WASI we can't catch call-stack overflows with stack-pointer checks, so
1050 // we count recursion depth with RAII based AutoCheckRecursionLimit.
1051 uint32_t wasiRecursionDepth
= 0u;
1053 static constexpr uint32_t wasiRecursionDepthLimit
= 350u;
1056 static const RootingContext
* get(const JSContext
* cx
) {
1057 return reinterpret_cast<const RootingContext
*>(cx
);
1060 static RootingContext
* get(JSContext
* cx
) {
1061 return reinterpret_cast<RootingContext
*>(cx
);
1064 friend JS::Realm
* js::GetContextRealm(const JSContext
* cx
);
1065 friend JS::Zone
* js::GetContextZone(const JSContext
* cx
);
1068 class JS_PUBLIC_API AutoGCRooter
{
1070 using Kind
= AutoGCRooterKind
;
1072 AutoGCRooter(JSContext
* cx
, Kind kind
)
1073 : AutoGCRooter(JS::RootingContext::get(cx
), kind
) {}
1074 AutoGCRooter(RootingContext
* cx
, Kind kind
)
1075 : down(cx
->autoGCRooters_
[kind
]),
1076 stackTop(&cx
->autoGCRooters_
[kind
]),
1078 MOZ_ASSERT(this != *stackTop
);
1083 MOZ_ASSERT(this == *stackTop
);
1087 void trace(JSTracer
* trc
);
1090 friend class RootingContext
;
1092 AutoGCRooter
* const down
;
1093 AutoGCRooter
** const stackTop
;
1096 * Discriminates actual subclass of this being used. The meaning is
1097 * indicated by the corresponding value in the Kind enum.
1101 /* No copy or assignment semantics. */
1102 AutoGCRooter(AutoGCRooter
& ida
) = delete;
1103 void operator=(AutoGCRooter
& ida
) = delete;
1104 } JS_HAZ_ROOTED_BASE
;
1107 * Custom rooting behavior for internal and external clients.
1109 * Deprecated. Where possible, use Rooted<> instead.
1111 class MOZ_RAII JS_PUBLIC_API CustomAutoRooter
: private AutoGCRooter
{
1113 template <typename CX
>
1114 explicit CustomAutoRooter(const CX
& cx
)
1115 : AutoGCRooter(cx
, AutoGCRooter::Kind::Custom
) {}
1117 friend void AutoGCRooter::trace(JSTracer
* trc
);
1120 virtual ~CustomAutoRooter() = default;
1122 /** Supplied by derived class to trace roots. */
1123 virtual void trace(JSTracer
* trc
) = 0;
1128 template <typename T
>
1129 constexpr bool IsTraceable_v
=
1130 MapTypeToRootKind
<T
>::kind
== JS::RootKind::Traceable
;
1132 template <typename T
>
1133 using RootedTraits
=
1134 std::conditional_t
<IsTraceable_v
<T
>, js::RootedTraceableTraits
<T
>,
1135 js::RootedGCThingTraits
<T
>>;
1137 } /* namespace detail */
1140 * Local variable of type T whose value is always rooted. This is typically
1141 * used for local variables, or for non-rooted values being passed to a
1142 * function that requires a handle, e.g. Foo(Root<T>(cx, x)).
1144 * If you want to add additional methods to Rooted for a specific
1145 * specialization, define a RootedOperations<T> specialization containing them.
1147 template <typename T
>
1148 class MOZ_RAII Rooted
: public detail::RootedTraits
<T
>::StackBase
,
1149 public js::RootedOperations
<T
, Rooted
<T
>> {
1150 inline void registerWithRootLists(RootedListHeads
& roots
) {
1151 this->stack
= &roots
[JS::MapTypeToRootKind
<T
>::kind
];
1152 this->prev
= *this->stack
;
1153 *this->stack
= this;
1156 inline RootedListHeads
& rootLists(RootingContext
* cx
) {
1157 return cx
->stackRoots_
;
1159 inline RootedListHeads
& rootLists(JSContext
* cx
) {
1160 return rootLists(RootingContext::get(cx
));
1164 using ElementType
= T
;
1166 // Construct an empty Rooted holding a safely initialized but empty T.
1167 // Requires T to have a copy constructor in order to copy the safely
1168 // initialized value.
1170 // Note that for SFINAE to reject this method, the 2nd template parameter must
1171 // depend on RootingContext somehow even though we really only care about T.
1172 template <typename RootingContext
,
1173 typename
= std::enable_if_t
<std::is_copy_constructible_v
<T
>,
1175 explicit Rooted(const RootingContext
& cx
)
1176 : ptr(SafelyInitialized
<T
>::create()) {
1177 registerWithRootLists(rootLists(cx
));
1180 // Provide an initial value. Requires T to be constructible from the given
1182 template <typename RootingContext
, typename S
>
1183 Rooted(const RootingContext
& cx
, S
&& initial
)
1184 : ptr(std::forward
<S
>(initial
)) {
1185 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1186 registerWithRootLists(rootLists(cx
));
1189 // (Traceables only) Construct the contained value from the given arguments.
1190 // Constructs in-place, so T does not need to be copyable or movable.
1192 // Note that a copyable Traceable passed only a RootingContext will
1193 // choose the above SafelyInitialized<T> constructor, because otherwise
1194 // identical functions with parameter packs are considered less specialized.
1196 // The SFINAE type must again depend on an inferred template parameter.
1198 typename RootingContext
, typename
... CtorArgs
,
1199 typename
= std::enable_if_t
<detail::IsTraceable_v
<T
>, RootingContext
>>
1200 explicit Rooted(const RootingContext
& cx
, CtorArgs
... args
)
1201 : ptr(std::forward
<CtorArgs
>(args
)...) {
1202 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1203 registerWithRootLists(rootLists(cx
));
1207 MOZ_ASSERT(*this->stack
== this);
1208 *this->stack
= this->prev
;
1212 * This method is public for Rooted so that Codegen.py can use a Rooted
1213 * interchangeably with a MutableHandleValue.
1215 void set(const T
& value
) {
1217 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1219 void set(T
&& value
) {
1220 ptr
= std::move(value
);
1221 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1224 DECLARE_POINTER_CONSTREF_OPS(T
);
1225 DECLARE_POINTER_ASSIGN_OPS(Rooted
, T
);
1227 T
& get() { return ptr
; }
1228 const T
& get() const { return ptr
; }
1230 T
* address() { return &ptr
; }
1231 const T
* address() const { return &ptr
; }
1236 Rooted(const Rooted
&) = delete;
1241 template <typename T
>
1242 struct DefineComparisonOps
<Rooted
<T
>> : std::true_type
{
1243 static const T
& get(const Rooted
<T
>& v
) { return v
.get(); }
1246 } // namespace detail
1248 } /* namespace JS */
1253 * Inlinable accessors for JSContext.
1255 * - These must not be available on the more restricted superclasses of
1256 * JSContext, so we can't simply define them on RootingContext.
1258 * - They're perfectly ordinary JSContext functionality, so ought to be
1259 * usable without resorting to jsfriendapi.h, and when JSContext is an
1262 inline JS::Realm
* GetContextRealm(const JSContext
* cx
) {
1263 return JS::RootingContext::get(cx
)->realm_
;
1266 inline JS::Compartment
* GetContextCompartment(const JSContext
* cx
) {
1267 if (JS::Realm
* realm
= GetContextRealm(cx
)) {
1268 return GetCompartmentForRealm(realm
);
1273 inline JS::Zone
* GetContextZone(const JSContext
* cx
) {
1274 return JS::RootingContext::get(cx
)->zone_
;
1277 inline ProfilingStack
* GetContextProfilingStackIfEnabled(JSContext
* cx
) {
1278 return JS::RootingContext::get(cx
)
1280 .getProfilingStackIfEnabled();
1284 * Augment the generic Rooted<T> interface when T = JSObject* with
1285 * class-querying and downcasting operations.
1287 * Given a Rooted<JSObject*> obj, one can view
1288 * Handle<StringObject*> h = obj.as<StringObject*>();
1289 * as an optimization of
1290 * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
1291 * Handle<StringObject*> h = rooted;
1293 template <typename Container
>
1294 class RootedOperations
<JSObject
*, Container
>
1295 : public MutableWrappedPtrOperations
<JSObject
*, Container
> {
1298 JS::Handle
<U
*> as() const;
1302 * Augment the generic Handle<T> interface when T = JSObject* with
1303 * downcasting operations.
1305 * Given a Handle<JSObject*> obj, one can view
1306 * Handle<StringObject*> h = obj.as<StringObject*>();
1307 * as an optimization of
1308 * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
1309 * Handle<StringObject*> h = rooted;
1311 template <typename Container
>
1312 class HandleOperations
<JSObject
*, Container
>
1313 : public WrappedPtrOperations
<JSObject
*, Container
> {
1316 JS::Handle
<U
*> as() const;
1319 } /* namespace js */
1323 template <typename T
>
1324 template <typename S
>
1325 inline Handle
<T
>::Handle(
1326 const Rooted
<S
>& root
,
1327 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
) {
1328 ptr
= reinterpret_cast<const T
*>(root
.address());
1331 template <typename T
>
1332 template <typename S
>
1333 inline Handle
<T
>::Handle(
1334 const PersistentRooted
<S
>& root
,
1335 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
) {
1336 ptr
= reinterpret_cast<const T
*>(root
.address());
1339 template <typename T
>
1340 template <typename S
>
1341 inline Handle
<T
>::Handle(
1342 MutableHandle
<S
>& root
,
1343 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
) {
1344 ptr
= reinterpret_cast<const T
*>(root
.address());
1347 template <typename T
>
1348 inline MutableHandle
<T
>::MutableHandle(Rooted
<T
>* root
) {
1349 static_assert(sizeof(MutableHandle
<T
>) == sizeof(T
*),
1350 "MutableHandle must be binary compatible with T*.");
1351 ptr
= root
->address();
1354 template <typename T
>
1355 inline MutableHandle
<T
>::MutableHandle(PersistentRooted
<T
>* root
) {
1356 static_assert(sizeof(MutableHandle
<T
>) == sizeof(T
*),
1357 "MutableHandle must be binary compatible with T*.");
1358 ptr
= root
->address();
1361 JS_PUBLIC_API
void AddPersistentRoot(RootingContext
* cx
, RootKind kind
,
1362 js::PersistentRootedBase
* root
);
1364 JS_PUBLIC_API
void AddPersistentRoot(JSRuntime
* rt
, RootKind kind
,
1365 js::PersistentRootedBase
* root
);
1368 * A copyable, assignable global GC root type with arbitrary lifetime, an
1369 * infallible constructor, and automatic unrooting on destruction.
1371 * These roots can be used in heap-allocated data structures, so they are not
1372 * associated with any particular JSContext or stack. They are registered with
1373 * the JSRuntime itself, without locking. Initialization may take place on
1374 * construction, or in two phases if the no-argument constructor is called
1375 * followed by init().
1377 * Note that you must not use an PersistentRooted in an object owned by a JS
1380 * Whenever one object whose lifetime is decided by the GC refers to another
1381 * such object, that edge must be traced only if the owning JS object is traced.
1382 * This applies not only to JS objects (which obviously are managed by the GC)
1383 * but also to C++ objects owned by JS objects.
1385 * If you put a PersistentRooted in such a C++ object, that is almost certainly
1386 * a leak. When a GC begins, the referent of the PersistentRooted is treated as
1387 * live, unconditionally (because a PersistentRooted is a *root*), even if the
1388 * JS object that owns it is unreachable. If there is any path from that
1389 * referent back to the JS object, then the C++ object containing the
1390 * PersistentRooted will not be destructed, and the whole blob of objects will
1391 * not be freed, even if there are no references to them from the outside.
1393 * In the context of Firefox, this is a severe restriction: almost everything in
1394 * Firefox is owned by some JS object or another, so using PersistentRooted in
1395 * such objects would introduce leaks. For these kinds of edges, Heap<T> or
1396 * TenuredHeap<T> would be better types. It's up to the implementor of the type
1397 * containing Heap<T> or TenuredHeap<T> members to make sure their referents get
1398 * marked when the object itself is marked.
1400 template <typename T
>
1401 class PersistentRooted
: public detail::RootedTraits
<T
>::PersistentBase
,
1402 public js::RootedOperations
<T
, PersistentRooted
<T
>> {
1403 void registerWithRootLists(RootingContext
* cx
) {
1404 MOZ_ASSERT(!initialized());
1405 JS::RootKind kind
= JS::MapTypeToRootKind
<T
>::kind
;
1406 AddPersistentRoot(cx
, kind
, this);
1409 void registerWithRootLists(JSRuntime
* rt
) {
1410 MOZ_ASSERT(!initialized());
1411 JS::RootKind kind
= JS::MapTypeToRootKind
<T
>::kind
;
1412 AddPersistentRoot(rt
, kind
, this);
1415 // Used when JSContext type is incomplete and so it is not known to inherit
1416 // from RootingContext.
1417 void registerWithRootLists(JSContext
* cx
) {
1418 registerWithRootLists(RootingContext::get(cx
));
1422 using ElementType
= T
;
1424 PersistentRooted() : ptr(SafelyInitialized
<T
>::create()) {}
1427 typename RootHolder
,
1428 typename
= std::enable_if_t
<std::is_copy_constructible_v
<T
>, RootHolder
>>
1429 explicit PersistentRooted(const RootHolder
& cx
)
1430 : ptr(SafelyInitialized
<T
>::create()) {
1431 registerWithRootLists(cx
);
1435 typename RootHolder
, typename U
,
1436 typename
= std::enable_if_t
<std::is_constructible_v
<T
, U
>, RootHolder
>>
1437 PersistentRooted(const RootHolder
& cx
, U
&& initial
)
1438 : ptr(std::forward
<U
>(initial
)) {
1439 registerWithRootLists(cx
);
1442 template <typename RootHolder
, typename
... CtorArgs
,
1443 typename
= std::enable_if_t
<detail::IsTraceable_v
<T
>, RootHolder
>>
1444 explicit PersistentRooted(const RootHolder
& cx
, CtorArgs
... args
)
1445 : ptr(std::forward
<CtorArgs
>(args
)...) {
1446 registerWithRootLists(cx
);
1449 PersistentRooted(const PersistentRooted
& rhs
) : ptr(rhs
.ptr
) {
1451 * Copy construction takes advantage of the fact that the original
1452 * is already inserted, and simply adds itself to whatever list the
1453 * original was on - no JSRuntime pointer needed.
1455 * This requires mutating rhs's links, but those should be 'mutable'
1456 * anyway. C++ doesn't let us declare mutable base classes.
1458 const_cast<PersistentRooted
&>(rhs
).setNext(this);
1461 bool initialized() const { return this->isInList(); }
1463 void init(RootingContext
* cx
) { init(cx
, SafelyInitialized
<T
>::create()); }
1464 void init(JSContext
* cx
) { init(RootingContext::get(cx
)); }
1466 template <typename U
>
1467 void init(RootingContext
* cx
, U
&& initial
) {
1468 ptr
= std::forward
<U
>(initial
);
1469 registerWithRootLists(cx
);
1471 template <typename U
>
1472 void init(JSContext
* cx
, U
&& initial
) {
1473 ptr
= std::forward
<U
>(initial
);
1474 registerWithRootLists(RootingContext::get(cx
));
1478 if (initialized()) {
1479 set(SafelyInitialized
<T
>::create());
1484 DECLARE_POINTER_CONSTREF_OPS(T
);
1485 DECLARE_POINTER_ASSIGN_OPS(PersistentRooted
, T
);
1487 T
& get() { return ptr
; }
1488 const T
& get() const { return ptr
; }
1491 MOZ_ASSERT(initialized());
1494 const T
* address() const { return &ptr
; }
1496 template <typename U
>
1497 void set(U
&& value
) {
1498 MOZ_ASSERT(initialized());
1499 ptr
= std::forward
<U
>(value
);
1508 template <typename T
>
1509 struct DefineComparisonOps
<PersistentRooted
<T
>> : std::true_type
{
1510 static const T
& get(const PersistentRooted
<T
>& v
) { return v
.get(); }
1513 } // namespace detail
1515 } /* namespace JS */
1519 template <typename T
, typename D
, typename Container
>
1520 class WrappedPtrOperations
<UniquePtr
<T
, D
>, Container
> {
1521 const UniquePtr
<T
, D
>& uniquePtr() const {
1522 return static_cast<const Container
*>(this)->get();
1526 explicit operator bool() const { return !!uniquePtr(); }
1527 T
* get() const { return uniquePtr().get(); }
1528 T
* operator->() const { return get(); }
1529 T
& operator*() const { return *uniquePtr(); }
1532 template <typename T
, typename D
, typename Container
>
1533 class MutableWrappedPtrOperations
<UniquePtr
<T
, D
>, Container
>
1534 : public WrappedPtrOperations
<UniquePtr
<T
, D
>, Container
> {
1535 UniquePtr
<T
, D
>& uniquePtr() { return static_cast<Container
*>(this)->get(); }
1538 [[nodiscard
]] typename UniquePtr
<T
, D
>::Pointer
release() {
1539 return uniquePtr().release();
1541 void reset(T
* ptr
= T()) { uniquePtr().reset(ptr
); }
1544 template <typename T
, typename Container
>
1545 class WrappedPtrOperations
<mozilla::Maybe
<T
>, Container
> {
1546 const mozilla::Maybe
<T
>& maybe() const {
1547 return static_cast<const Container
*>(this)->get();
1551 // This only supports a subset of Maybe's interface.
1552 bool isSome() const { return maybe().isSome(); }
1553 bool isNothing() const { return maybe().isNothing(); }
1554 const T
value() const { return maybe().value(); }
1555 const T
* operator->() const { return maybe().ptr(); }
1556 const T
& operator*() const { return maybe().ref(); }
1559 template <typename T
, typename Container
>
1560 class MutableWrappedPtrOperations
<mozilla::Maybe
<T
>, Container
>
1561 : public WrappedPtrOperations
<mozilla::Maybe
<T
>, Container
> {
1562 mozilla::Maybe
<T
>& maybe() { return static_cast<Container
*>(this)->get(); }
1565 // This only supports a subset of Maybe's interface.
1566 T
* operator->() { return maybe().ptr(); }
1567 T
& operator*() { return maybe().ref(); }
1568 void reset() { return maybe().reset(); }
1573 template <typename T
, typename TraceCallbacks
>
1574 void CallTraceCallbackOnNonHeap(T
* v
, const TraceCallbacks
& aCallbacks
,
1575 const char* aName
, void* aClosure
) {
1576 static_assert(sizeof(T
) == sizeof(JS::Heap
<T
>),
1577 "T and Heap<T> must be compatible.");
1579 mozilla::DebugOnly
<Cell
*> cell
= BarrierMethods
<T
>::asGCThingOrNull(*v
);
1581 MOZ_ASSERT(!IsInsideNursery(cell
));
1582 JS::Heap
<T
>* asHeapT
= reinterpret_cast<JS::Heap
<T
>*>(v
);
1583 aCallbacks
.Trace(asHeapT
, aName
, aClosure
);
1586 } /* namespace gc */
1588 template <typename Wrapper
, typename T1
, typename T2
>
1589 class WrappedPtrOperations
<std::pair
<T1
, T2
>, Wrapper
> {
1590 const std::pair
<T1
, T2
>& pair() const {
1591 return static_cast<const Wrapper
*>(this)->get();
1595 const T1
& first() const { return pair().first
; }
1596 const T2
& second() const { return pair().second
; }
1599 template <typename Wrapper
, typename T1
, typename T2
>
1600 class MutableWrappedPtrOperations
<std::pair
<T1
, T2
>, Wrapper
>
1601 : public WrappedPtrOperations
<std::pair
<T1
, T2
>, Wrapper
> {
1602 std::pair
<T1
, T2
>& pair() { return static_cast<Wrapper
*>(this)->get(); }
1605 T1
& first() { return pair().first
; }
1606 T2
& second() { return pair().second
; }
1609 } /* namespace js */
1611 #endif /* js_RootingAPI_h */