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"
17 #include <type_traits>
22 #include "js/ComparisonOperators.h" // JS::detail::DefineComparisonOps
23 #include "js/GCAnnotations.h"
24 #include "js/GCPolicyAPI.h"
25 #include "js/GCTypeMacros.h" // JS_FOR_EACH_PUBLIC_{,TAGGED_}GC_POINTER_TYPE
26 #include "js/HashTable.h"
27 #include "js/HeapAPI.h" // StackKindCount
28 #include "js/ProfilingStack.h"
30 #include "js/Stack.h" // JS::NativeStackLimit
31 #include "js/TypeDecls.h"
32 #include "js/UniquePtr.h"
35 * [SMDOC] Stack Rooting
37 * Moving GC Stack Rooting
39 * A moving GC may change the physical location of GC allocated things, even
40 * when they are rooted, updating all pointers to the thing to refer to its new
41 * location. The GC must therefore know about all live pointers to a thing,
42 * not just one of them, in order to behave correctly.
44 * The |Rooted| and |Handle| classes below are used to root stack locations
45 * whose value may be held live across a call that can trigger GC. For a
46 * code fragment such as:
48 * JSObject* obj = NewObject(cx);
50 * ... = obj->lastProperty();
52 * If |DoSomething()| can trigger a GC, the stack location of |obj| must be
53 * rooted to ensure that the GC does not move the JSObject referred to by
54 * |obj| without updating |obj|'s location itself. This rooting must happen
55 * regardless of whether there are other roots which ensure that the object
56 * itself will not be collected.
58 * If |DoSomething()| cannot trigger a GC, and the same holds for all other
59 * calls made between |obj|'s definitions and its last uses, then no rooting
62 * SpiderMonkey can trigger a GC at almost any time and in ways that are not
63 * always clear. For example, the following innocuous-looking actions can
64 * cause a GC: allocation of any new GC thing; JSObject::hasProperty;
65 * JS_ReportError and friends; and ToNumber, among many others. The following
66 * dangerous-looking actions cannot trigger a GC: js_malloc, cx->malloc_,
67 * rt->malloc_, and friends and JS_ReportOutOfMemory.
69 * The following family of three classes will exactly root a stack location.
70 * Incorrect usage of these classes will result in a compile error in almost
71 * all cases. Therefore, it is very hard to be incorrectly rooted if you use
72 * these classes exclusively. These classes are all templated on the type T of
73 * the value being rooted.
75 * - Rooted<T> declares a variable of type T, whose value is always rooted.
76 * Rooted<T> may be automatically coerced to a Handle<T>, below. Rooted<T>
77 * should be used whenever a local variable's value may be held live across a
78 * call which can trigger a GC.
80 * - Handle<T> is a const reference to a Rooted<T>. Functions which take GC
81 * things or values as arguments and need to root those arguments should
82 * generally use handles for those arguments and avoid any explicit rooting.
83 * This has two benefits. First, when several such functions call each other
84 * then redundant rooting of multiple copies of the GC thing can be avoided.
85 * Second, if the caller does not pass a rooted value a compile error will be
86 * generated, which is quicker and easier to fix than when relying on a
87 * separate rooting analysis.
89 * - MutableHandle<T> is a non-const reference to Rooted<T>. It is used in the
90 * same way as Handle<T> and includes a |set(const T& v)| method to allow
91 * updating the value of the referenced Rooted<T>. A MutableHandle<T> can be
92 * created with an implicit cast from a Rooted<T>*.
94 * In some cases the small performance overhead of exact rooting (measured to
95 * be a few nanoseconds on desktop) is too much. In these cases, try the
98 * - Move all Rooted<T> above inner loops: this allows you to re-use the root
99 * on each iteration of the loop.
101 * - Pass Handle<T> through your hot call stack to avoid re-rooting costs at
104 * The following diagram explains the list of supported, implicit type
105 * conversions between classes of this family:
107 * Rooted<T> ----> Handle<T>
111 * +---> MutableHandle<T>
114 * All of these types have an implicit conversion to raw pointers.
121 // The defaulted Enable parameter for the following two types is for restricting
122 // specializations with std::enable_if.
123 template <typename T
, typename Enable
= void>
124 struct BarrierMethods
{};
126 template <typename Element
, typename Wrapper
, typename Enable
= void>
127 class WrappedPtrOperations
{};
129 template <typename Element
, typename Wrapper
>
130 class MutableWrappedPtrOperations
131 : public WrappedPtrOperations
<Element
, Wrapper
> {};
133 template <typename T
, typename Wrapper
>
134 class RootedOperations
: public MutableWrappedPtrOperations
<T
, Wrapper
> {};
136 template <typename T
, typename Wrapper
>
137 class HandleOperations
: public WrappedPtrOperations
<T
, Wrapper
> {};
139 template <typename T
, typename Wrapper
>
140 class MutableHandleOperations
: public MutableWrappedPtrOperations
<T
, Wrapper
> {
143 template <typename T
, typename Wrapper
>
144 class HeapOperations
: public MutableWrappedPtrOperations
<T
, Wrapper
> {};
146 // Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many
149 // Add a 2nd template parameter to allow conditionally enabling partial
150 // specializations via std::enable_if.
151 template <typename T
, typename Enable
= void>
152 struct IsHeapConstructibleType
: public std::false_type
{};
154 #define JS_DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE(T) \
156 struct IsHeapConstructibleType<T> : public std::true_type {};
157 JS_FOR_EACH_PUBLIC_GC_POINTER_TYPE(JS_DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE
)
158 JS_FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(JS_DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE
)
159 // Note that JS_DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE is left defined, to allow
160 // declaring other types (eg from js/public/experimental/TypedData.h) to
161 // be used with Heap<>.
167 // Important: Return a reference so passing a Rooted<T>, etc. to
168 // something that takes a |const T&| is not a GC hazard.
169 #define DECLARE_POINTER_CONSTREF_OPS(T) \
170 operator const T&() const { return get(); } \
171 const T& operator->() const { return get(); }
173 // Assignment operators on a base class are hidden by the implicitly defined
174 // operator= on the derived class. Thus, define the operator= directly on the
175 // class as we would need to manually pass it through anyway.
176 #define DECLARE_POINTER_ASSIGN_OPS(Wrapper, T) \
177 Wrapper& operator=(const T& p) { \
181 Wrapper& operator=(T&& p) { \
185 Wrapper& operator=(const Wrapper& other) { \
190 #define DELETE_ASSIGNMENT_OPS(Wrapper, T) \
191 template <typename S> \
192 Wrapper<T>& operator=(S) = delete; \
193 Wrapper<T>& operator=(const Wrapper<T>&) = delete;
195 #define DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr) \
196 const T* address() const { return &(ptr); } \
197 const T& get() const { return (ptr); }
199 #define DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(ptr) \
200 T* address() { return &(ptr); } \
201 T& get() { return (ptr); }
207 JS_PUBLIC_API
void HeapObjectPostWriteBarrier(JSObject
** objp
, JSObject
* prev
,
209 JS_PUBLIC_API
void HeapObjectWriteBarriers(JSObject
** objp
, JSObject
* prev
,
211 JS_PUBLIC_API
void HeapStringWriteBarriers(JSString
** objp
, JSString
* prev
,
213 JS_PUBLIC_API
void HeapBigIntWriteBarriers(JS::BigInt
** bip
, JS::BigInt
* prev
,
215 JS_PUBLIC_API
void HeapScriptWriteBarriers(JSScript
** objp
, JSScript
* prev
,
219 * SafelyInitialized<T>::create() creates a safely-initialized |T|, suitable for
220 * use as a default value in situations requiring a safe but arbitrary |T|
221 * value. Implemented as a static method of a struct to allow partial
222 * specialization for subclasses via the Enable template parameter.
224 template <typename T
, typename Enable
= void>
225 struct SafelyInitialized
{
227 // This function wants to presume that |T()| -- which value-initializes a
228 // |T| per C++11 [expr.type.conv]p2 -- will produce a safely-initialized,
229 // safely-usable T that it can return.
231 #if defined(XP_WIN) || defined(XP_DARWIN) || \
232 (defined(XP_UNIX) && !defined(__clang__))
234 // That presumption holds for pointers, where value initialization produces
236 constexpr bool IsPointer
= std::is_pointer_v
<T
>;
238 // For classes and unions we *assume* that if |T|'s default constructor is
239 // non-trivial it'll initialize correctly. (This is unideal, but C++
240 // doesn't offer a type trait indicating whether a class's constructor is
241 // user-defined, which better approximates our desired semantics.)
242 constexpr bool IsNonTriviallyDefaultConstructibleClassOrUnion
=
243 (std::is_class_v
<T
> || std::is_union_v
<T
>) &&
244 !std::is_trivially_default_constructible_v
<T
>;
246 static_assert(IsPointer
|| IsNonTriviallyDefaultConstructibleClassOrUnion
,
247 "T() must evaluate to a safely-initialized T");
257 * For generational GC, assert that an object is in the tenured generation as
258 * opposed to being in the nursery.
260 extern JS_PUBLIC_API
void AssertGCThingMustBeTenured(JSObject
* obj
);
261 extern JS_PUBLIC_API
void AssertGCThingIsNotNurseryAllocable(
264 inline void AssertGCThingMustBeTenured(JSObject
* obj
) {}
265 inline void AssertGCThingIsNotNurseryAllocable(js::gc::Cell
* cell
) {}
269 * The Heap<T> class is a heap-stored reference to a JS GC thing for use outside
270 * the JS engine. All members of heap classes that refer to GC things should use
271 * Heap<T> (or possibly TenuredHeap<T>, described below).
273 * Heap<T> is an abstraction that hides some of the complexity required to
274 * maintain GC invariants for the contained reference. It uses operator
275 * overloading to provide a normal pointer interface, but adds barriers to
276 * notify the GC of changes.
278 * Heap<T> implements the following barriers:
280 * - Pre-write barrier (necessary for incremental GC).
281 * - Post-write barrier (necessary for generational GC).
282 * - Read barrier (necessary for cycle collector integration).
284 * Heap<T> may be moved or destroyed outside of GC finalization and hence may be
285 * used in dynamic storage such as a Vector.
287 * Heap<T> instances must be traced when their containing object is traced to
288 * keep the pointed-to GC thing alive.
290 * Heap<T> objects should only be used on the heap. GC references stored on the
291 * C/C++ stack must use Rooted/Handle/MutableHandle instead.
293 * Type T must be a public GC pointer type.
295 template <typename T
>
296 class MOZ_NON_MEMMOVABLE Heap
: public js::HeapOperations
<T
, Heap
<T
>> {
297 static_assert(js::IsHeapConstructibleType
<T
>::value
,
298 "Type T must be a public GC pointer type");
301 using ElementType
= T
;
303 Heap() : ptr(SafelyInitialized
<T
>::create()) {
304 // No barriers are required for initialization to the default value.
305 static_assert(sizeof(T
) == sizeof(Heap
<T
>),
306 "Heap<T> must be binary compatible with T.");
308 explicit Heap(const T
& p
) : ptr(p
) {
309 writeBarriers(SafelyInitialized
<T
>::create(), ptr
);
313 * For Heap, move semantics are equivalent to copy semantics. However, we want
314 * the copy constructor to be explicit, and an explicit move constructor
315 * breaks common usage of move semantics, so we need to define both, even
316 * though they are equivalent.
318 explicit Heap(const Heap
<T
>& other
) : ptr(other
.unbarrieredGet()) {
319 writeBarriers(SafelyInitialized
<T
>::create(), ptr
);
321 Heap(Heap
<T
>&& other
) : ptr(other
.unbarrieredGet()) {
322 writeBarriers(SafelyInitialized
<T
>::create(), ptr
);
325 Heap
& operator=(Heap
<T
>&& other
) {
326 set(other
.unbarrieredGet());
327 other
.set(SafelyInitialized
<T
>::create());
330 // Copy constructor defined by DECLARE_POINTER_ASSIGN_OPS.
332 ~Heap() { writeBarriers(ptr
, SafelyInitialized
<T
>::create()); }
334 DECLARE_POINTER_CONSTREF_OPS(T
);
335 DECLARE_POINTER_ASSIGN_OPS(Heap
<T
>, T
);
337 void exposeToActiveJS() const { js::BarrierMethods
<T
>::exposeToJS(ptr
); }
339 const T
& get() const {
343 const T
& unbarrieredGet() const { return ptr
; }
345 void set(const T
& newPtr
) {
348 writeBarriers(tmp
, ptr
);
350 void unbarrieredSet(const T
& newPtr
) { ptr
= newPtr
; }
352 T
* unsafeAddress() { return &ptr
; }
353 const T
* unsafeAddress() const { return &ptr
; }
355 explicit operator bool() const {
356 return bool(js::BarrierMethods
<T
>::asGCThingOrNull(ptr
));
360 void writeBarriers(const T
& prev
, const T
& next
) {
361 js::BarrierMethods
<T
>::writeBarriers(&ptr
, prev
, next
);
369 template <typename T
>
370 struct DefineComparisonOps
<Heap
<T
>> : std::true_type
{
371 static const T
& get(const Heap
<T
>& v
) { return v
.unbarrieredGet(); }
374 } // namespace detail
376 static MOZ_ALWAYS_INLINE
bool ObjectIsTenured(JSObject
* obj
) {
377 return !js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell
*>(obj
));
380 static MOZ_ALWAYS_INLINE
bool ObjectIsTenured(const Heap
<JSObject
*>& obj
) {
381 return ObjectIsTenured(obj
.unbarrieredGet());
384 static MOZ_ALWAYS_INLINE
bool ObjectIsMarkedGray(JSObject
* obj
) {
385 auto cell
= reinterpret_cast<js::gc::Cell
*>(obj
);
386 if (js::gc::IsInsideNursery(cell
)) {
390 auto tenuredCell
= reinterpret_cast<js::gc::TenuredCell
*>(cell
);
391 return js::gc::detail::CellIsMarkedGrayIfKnown(tenuredCell
);
394 static MOZ_ALWAYS_INLINE
bool ObjectIsMarkedGray(
395 const JS::Heap
<JSObject
*>& obj
) {
396 return ObjectIsMarkedGray(obj
.unbarrieredGet());
399 // The following *IsNotGray functions take account of the eventual
400 // gray marking state at the end of any ongoing incremental GC by
401 // delaying the checks if necessary.
405 inline void AssertCellIsNotGray(const js::gc::Cell
* maybeCell
) {
407 js::gc::detail::AssertCellIsNotGray(maybeCell
);
411 inline void AssertObjectIsNotGray(JSObject
* maybeObj
) {
412 AssertCellIsNotGray(reinterpret_cast<js::gc::Cell
*>(maybeObj
));
415 inline void AssertObjectIsNotGray(const JS::Heap
<JSObject
*>& obj
) {
416 AssertObjectIsNotGray(obj
.unbarrieredGet());
421 inline void AssertCellIsNotGray(js::gc::Cell
* maybeCell
) {}
422 inline void AssertObjectIsNotGray(JSObject
* maybeObj
) {}
423 inline void AssertObjectIsNotGray(const JS::Heap
<JSObject
*>& obj
) {}
428 * The TenuredHeap<T> class is similar to the Heap<T> class above in that it
429 * encapsulates the GC concerns of an on-heap reference to a JS object. However,
430 * it has two important differences:
432 * 1) Pointers which are statically known to only reference "tenured" objects
433 * can avoid the extra overhead of SpiderMonkey's post write barriers.
435 * 2) Objects in the "tenured" heap have stronger alignment restrictions than
436 * those in the "nursery", so it is possible to store flags in the lower
437 * bits of pointers known to be tenured. TenuredHeap wraps a normal tagged
438 * pointer with a nice API for accessing the flag bits and adds various
439 * assertions to ensure that it is not mis-used.
441 * GC things are said to be "tenured" when they are located in the long-lived
442 * heap: e.g. they have gained tenure as an object by surviving past at least
443 * one GC. For performance, SpiderMonkey allocates some things which are known
444 * to normally be long lived directly into the tenured generation; for example,
445 * global objects. Additionally, SpiderMonkey does not visit individual objects
446 * when deleting non-tenured objects, so object with finalizers are also always
447 * tenured; for instance, this includes most DOM objects.
449 * The considerations to keep in mind when using a TenuredHeap<T> vs a normal
452 * - It is invalid for a TenuredHeap<T> to refer to a non-tenured thing.
453 * - It is however valid for a Heap<T> to refer to a tenured thing.
454 * - It is not possible to store flag bits in a Heap<T>.
456 template <typename T
>
457 class TenuredHeap
: public js::HeapOperations
<T
, TenuredHeap
<T
>> {
458 static_assert(js::IsHeapConstructibleType
<T
>::value
,
459 "Type T must be a public GC pointer type");
462 using ElementType
= T
;
464 TenuredHeap() : bits(0) {
465 static_assert(sizeof(T
) == sizeof(TenuredHeap
<T
>),
466 "TenuredHeap<T> must be binary compatible with T.");
469 explicit TenuredHeap(T p
) : bits(0) { unbarrieredSetPtr(p
); }
470 explicit TenuredHeap(const TenuredHeap
<T
>& p
) : bits(0) {
471 unbarrieredSetPtr(p
.getPtr());
474 TenuredHeap
<T
>& operator=(T p
) {
478 TenuredHeap
<T
>& operator=(const TenuredHeap
<T
>& other
) {
484 ~TenuredHeap() { preWriteBarrier(); }
486 void setPtr(T newPtr
) {
488 unbarrieredSetPtr(newPtr
);
490 void unbarrieredSetPtr(T newPtr
) {
491 MOZ_ASSERT((reinterpret_cast<uintptr_t>(newPtr
) & flagsMask
) == 0);
492 MOZ_ASSERT(js::gc::IsCellPointerValidOrNull(newPtr
));
494 AssertGCThingMustBeTenured(newPtr
);
496 bits
= (bits
& flagsMask
) | reinterpret_cast<uintptr_t>(newPtr
);
499 void setFlags(uintptr_t flagsToSet
) {
500 MOZ_ASSERT((flagsToSet
& ~flagsMask
) == 0);
504 void unsetFlags(uintptr_t flagsToUnset
) {
505 MOZ_ASSERT((flagsToUnset
& ~flagsMask
) == 0);
506 bits
&= ~flagsToUnset
;
509 bool hasFlag(uintptr_t flag
) const {
510 MOZ_ASSERT((flag
& ~flagsMask
) == 0);
511 return (bits
& flag
) != 0;
514 T
unbarrieredGetPtr() const { return reinterpret_cast<T
>(bits
& ~flagsMask
); }
515 uintptr_t getFlags() const { return bits
& flagsMask
; }
517 void exposeToActiveJS() const {
518 js::BarrierMethods
<T
>::exposeToJS(unbarrieredGetPtr());
522 return unbarrieredGetPtr();
525 operator T() const { return getPtr(); }
526 T
operator->() const { return getPtr(); }
528 explicit operator bool() const {
529 return bool(js::BarrierMethods
<T
>::asGCThingOrNull(unbarrieredGetPtr()));
535 flagsMask
= (1 << maskBits
) - 1,
538 void preWriteBarrier() {
539 if (T prev
= unbarrieredGetPtr()) {
540 JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev
));
549 template <typename T
>
550 struct DefineComparisonOps
<TenuredHeap
<T
>> : std::true_type
{
551 static const T
get(const TenuredHeap
<T
>& v
) { return v
.unbarrieredGetPtr(); }
554 } // namespace detail
556 // std::swap uses a stack temporary, which prevents classes like Heap<T>
557 // from being declared MOZ_HEAP_CLASS.
558 template <typename T
>
559 void swap(TenuredHeap
<T
>& aX
, TenuredHeap
<T
>& aY
) {
565 template <typename T
>
566 void swap(Heap
<T
>& aX
, Heap
<T
>& aY
) {
572 static MOZ_ALWAYS_INLINE
bool ObjectIsMarkedGray(
573 const JS::TenuredHeap
<JSObject
*>& obj
) {
574 return ObjectIsMarkedGray(obj
.unbarrieredGetPtr());
577 template <typename T
>
579 template <typename T
>
581 template <typename T
, size_t N
= SIZE_MAX
>
583 template <typename T
>
584 class PersistentRooted
;
587 * Reference to a T that has been rooted elsewhere. This is most useful
588 * as a parameter type, which guarantees that the T lvalue is properly
589 * rooted. See "Move GC Stack Rooting" above.
591 * If you want to add additional methods to Handle for a specific
592 * specialization, define a HandleOperations<T> specialization containing them.
594 template <typename T
>
595 class MOZ_NONHEAP_CLASS Handle
: public js::HandleOperations
<T
, Handle
<T
>> {
596 friend class MutableHandle
<T
>;
599 using ElementType
= T
;
601 Handle(const Handle
<T
>&) = default;
603 /* Creates a handle from a handle of a type convertible to T. */
604 template <typename S
>
607 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
= 0) {
608 static_assert(sizeof(Handle
<T
>) == sizeof(T
*),
609 "Handle must be binary compatible with T*.");
610 ptr
= reinterpret_cast<const T
*>(handle
.address());
613 MOZ_IMPLICIT
Handle(decltype(nullptr)) {
614 static_assert(std::is_pointer_v
<T
>,
615 "nullptr_t overload not valid for non-pointer types");
616 static void* const ConstNullValue
= nullptr;
617 ptr
= reinterpret_cast<const T
*>(&ConstNullValue
);
620 MOZ_IMPLICIT
Handle(MutableHandle
<T
> handle
) { ptr
= handle
.address(); }
623 * Take care when calling this method!
625 * This creates a Handle from the raw location of a T.
627 * It should be called only if the following conditions hold:
629 * 1) the location of the T is guaranteed to be marked (for some reason
630 * other than being a Rooted), e.g., if it is guaranteed to be reachable
631 * from an implicit root.
633 * 2) the contents of the location are immutable, or at least cannot change
634 * for the lifetime of the handle, as its users may not expect its value
635 * to change underneath them.
637 static constexpr Handle
fromMarkedLocation(const T
* p
) {
638 return Handle(p
, DeliberatelyChoosingThisOverload
,
639 ImUsingThisOnlyInFromFromMarkedLocation
);
643 * Construct a handle from an explicitly rooted location. This is the
644 * normal way to create a handle, and normally happens implicitly.
646 template <typename S
>
647 inline MOZ_IMPLICIT
Handle(
648 const Rooted
<S
>& root
,
649 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
= 0);
651 template <typename S
>
652 inline MOZ_IMPLICIT
Handle(
653 const PersistentRooted
<S
>& root
,
654 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
= 0);
656 /* Construct a read only handle from a mutable handle. */
657 template <typename S
>
658 inline MOZ_IMPLICIT
Handle(
659 MutableHandle
<S
>& root
,
660 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
= 0);
662 template <size_t N
, typename S
>
663 inline MOZ_IMPLICIT
Handle(
664 const RootedField
<S
, N
>& rootedField
,
665 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
= 0);
667 DECLARE_POINTER_CONSTREF_OPS(T
);
668 DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr
);
672 DELETE_ASSIGNMENT_OPS(Handle
, T
);
674 enum Disambiguator
{ DeliberatelyChoosingThisOverload
= 42 };
675 enum CallerIdentity
{ ImUsingThisOnlyInFromFromMarkedLocation
= 17 };
676 constexpr Handle(const T
* p
, Disambiguator
, CallerIdentity
) : ptr(p
) {}
683 template <typename T
>
684 struct DefineComparisonOps
<Handle
<T
>> : std::true_type
{
685 static const T
& get(const Handle
<T
>& v
) { return v
.get(); }
688 } // namespace detail
691 * Similar to a handle, but the underlying storage can be changed. This is
692 * useful for outparams.
694 * If you want to add additional methods to MutableHandle for a specific
695 * specialization, define a MutableHandleOperations<T> specialization containing
698 template <typename T
>
699 class MOZ_STACK_CLASS MutableHandle
700 : public js::MutableHandleOperations
<T
, MutableHandle
<T
>> {
702 using ElementType
= T
;
704 inline MOZ_IMPLICIT
MutableHandle(Rooted
<T
>* root
);
706 inline MOZ_IMPLICIT
MutableHandle(RootedField
<T
, N
>* root
);
707 inline MOZ_IMPLICIT
MutableHandle(PersistentRooted
<T
>* root
);
710 // Disallow nullptr for overloading purposes.
711 MutableHandle(decltype(nullptr)) = delete;
714 MutableHandle(const MutableHandle
<T
>&) = default;
715 void set(const T
& v
) {
717 MOZ_ASSERT(GCPolicy
<T
>::isValid(*ptr
));
721 MOZ_ASSERT(GCPolicy
<T
>::isValid(*ptr
));
725 * This may be called only if the location of the T is guaranteed
726 * to be marked (for some reason other than being a Rooted),
727 * e.g., if it is guaranteed to be reachable from an implicit root.
729 * Create a MutableHandle from a raw location of a T.
731 static MutableHandle
fromMarkedLocation(T
* p
) {
737 DECLARE_POINTER_CONSTREF_OPS(T
);
738 DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr
);
739 DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(*ptr
);
742 MutableHandle() = default;
743 DELETE_ASSIGNMENT_OPS(MutableHandle
, T
);
750 template <typename T
>
751 struct DefineComparisonOps
<MutableHandle
<T
>> : std::true_type
{
752 static const T
& get(const MutableHandle
<T
>& v
) { return v
.get(); }
755 } // namespace detail
763 // Default implementations for barrier methods on GC thing pointers.
764 template <typename T
>
765 struct PtrBarrierMethodsBase
{
766 static T
* initial() { return nullptr; }
767 static gc::Cell
* asGCThingOrNull(T
* v
) {
771 MOZ_ASSERT(uintptr_t(v
) > 32);
772 return reinterpret_cast<gc::Cell
*>(v
);
774 static void exposeToJS(T
* t
) {
776 js::gc::ExposeGCThingToActiveJS(JS::GCCellPtr(t
));
779 static void readBarrier(T
* t
) {
781 js::gc::IncrementalReadBarrier(JS::GCCellPtr(t
));
786 } // namespace detail
788 template <typename T
>
789 struct BarrierMethods
<T
*> : public detail::PtrBarrierMethodsBase
<T
> {
790 static void writeBarriers(T
** vp
, T
* prev
, T
* next
) {
792 JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev
));
795 JS::AssertGCThingIsNotNurseryAllocable(
796 reinterpret_cast<js::gc::Cell
*>(next
));
802 struct BarrierMethods
<JSObject
*>
803 : public detail::PtrBarrierMethodsBase
<JSObject
> {
804 static void writeBarriers(JSObject
** vp
, JSObject
* prev
, JSObject
* next
) {
805 JS::HeapObjectWriteBarriers(vp
, prev
, next
);
807 static void postWriteBarrier(JSObject
** vp
, JSObject
* prev
, JSObject
* next
) {
808 JS::HeapObjectPostWriteBarrier(vp
, prev
, next
);
810 static void exposeToJS(JSObject
* obj
) {
812 JS::ExposeObjectToActiveJS(obj
);
818 struct BarrierMethods
<JSFunction
*>
819 : public detail::PtrBarrierMethodsBase
<JSFunction
> {
820 static void writeBarriers(JSFunction
** vp
, JSFunction
* prev
,
822 JS::HeapObjectWriteBarriers(reinterpret_cast<JSObject
**>(vp
),
823 reinterpret_cast<JSObject
*>(prev
),
824 reinterpret_cast<JSObject
*>(next
));
826 static void exposeToJS(JSFunction
* fun
) {
828 JS::ExposeObjectToActiveJS(reinterpret_cast<JSObject
*>(fun
));
834 struct BarrierMethods
<JSString
*>
835 : public detail::PtrBarrierMethodsBase
<JSString
> {
836 static void writeBarriers(JSString
** vp
, JSString
* prev
, JSString
* next
) {
837 JS::HeapStringWriteBarriers(vp
, prev
, next
);
842 struct BarrierMethods
<JSScript
*>
843 : public detail::PtrBarrierMethodsBase
<JSScript
> {
844 static void writeBarriers(JSScript
** vp
, JSScript
* prev
, JSScript
* next
) {
845 JS::HeapScriptWriteBarriers(vp
, prev
, next
);
850 struct BarrierMethods
<JS::BigInt
*>
851 : public detail::PtrBarrierMethodsBase
<JS::BigInt
> {
852 static void writeBarriers(JS::BigInt
** vp
, JS::BigInt
* prev
,
854 JS::HeapBigIntWriteBarriers(vp
, prev
, next
);
858 // Provide hash codes for Cell kinds that may be relocated and, thus, not have
859 // a stable address to use as the base for a hash code. Instead of the address,
860 // this hasher uses Cell::getUniqueId to provide exact matches and as a base
861 // for generating hash codes.
863 // Note: this hasher, like PointerHasher can "hash" a nullptr. While a nullptr
864 // would not likely be a useful key, there are some cases where being able to
865 // hash a nullptr is useful, either on purpose or because of bugs:
866 // (1) existence checks where the key may happen to be null and (2) some
867 // aggregate Lookup kinds embed a JSObject* that is frequently null and do not
868 // null test before dispatching to the hasher.
869 template <typename T
>
870 struct JS_PUBLIC_API StableCellHasher
{
874 static bool maybeGetHash(const Lookup
& l
, mozilla::HashNumber
* hashOut
);
875 static bool ensureHash(const Lookup
& l
, HashNumber
* hashOut
);
876 static HashNumber
hash(const Lookup
& l
);
877 static bool match(const Key
& k
, const Lookup
& l
);
878 // The rekey hash policy method is not provided since you dont't need to
879 // rekey any more when using this policy.
882 template <typename T
>
883 struct JS_PUBLIC_API StableCellHasher
<JS::Heap
<T
>> {
884 using Key
= JS::Heap
<T
>;
887 static bool maybeGetHash(const Lookup
& l
, HashNumber
* hashOut
) {
888 return StableCellHasher
<T
>::maybeGetHash(l
, hashOut
);
890 static bool ensureHash(const Lookup
& l
, HashNumber
* hashOut
) {
891 return StableCellHasher
<T
>::ensureHash(l
, hashOut
);
893 static HashNumber
hash(const Lookup
& l
) {
894 return StableCellHasher
<T
>::hash(l
);
896 static bool match(const Key
& k
, const Lookup
& l
) {
897 return StableCellHasher
<T
>::match(k
.unbarrieredGet(), l
);
905 template <typename T
>
906 struct FallibleHashMethods
<js::StableCellHasher
<T
>> {
907 template <typename Lookup
>
908 static bool maybeGetHash(Lookup
&& l
, HashNumber
* hashOut
) {
909 return js::StableCellHasher
<T
>::maybeGetHash(std::forward
<Lookup
>(l
),
912 template <typename Lookup
>
913 static bool ensureHash(Lookup
&& l
, HashNumber
* hashOut
) {
914 return js::StableCellHasher
<T
>::ensureHash(std::forward
<Lookup
>(l
),
919 } // namespace mozilla
923 struct VirtualTraceable
{
924 virtual ~VirtualTraceable() = default;
925 virtual void trace(JSTracer
* trc
, const char* name
) = 0;
928 class StackRootedBase
{
930 StackRootedBase
* previous() { return prev
; }
933 StackRootedBase
** stack
;
934 StackRootedBase
* prev
;
936 template <typename T
>
938 return static_cast<JS::Rooted
<T
>*>(this);
942 class PersistentRootedBase
943 : protected mozilla::LinkedListElement
<PersistentRootedBase
> {
945 friend class mozilla::LinkedList
<PersistentRootedBase
>;
946 friend class mozilla::LinkedListElement
<PersistentRootedBase
>;
948 template <typename T
>
950 return static_cast<JS::PersistentRooted
<T
>*>(this);
954 struct StackRootedTraceableBase
: public StackRootedBase
,
955 public VirtualTraceable
{};
957 class PersistentRootedTraceableBase
: public PersistentRootedBase
,
958 public VirtualTraceable
{};
960 template <typename Base
, typename T
>
961 class TypedRootedGCThingBase
: public Base
{
963 void trace(JSTracer
* trc
, const char* name
);
966 template <typename Base
, typename T
>
967 class TypedRootedTraceableBase
: public Base
{
969 void trace(JSTracer
* trc
, const char* name
) override
{
970 auto* self
= this->template derived
<T
>();
971 JS::GCPolicy
<T
>::trace(trc
, self
->address(), name
);
975 template <typename T
>
976 struct RootedTraceableTraits
{
977 using StackBase
= TypedRootedTraceableBase
<StackRootedTraceableBase
, T
>;
978 using PersistentBase
=
979 TypedRootedTraceableBase
<PersistentRootedTraceableBase
, T
>;
982 template <typename T
>
983 struct RootedGCThingTraits
{
984 using StackBase
= TypedRootedGCThingBase
<StackRootedBase
, T
>;
985 using PersistentBase
= TypedRootedGCThingBase
<PersistentRootedBase
, T
>;
992 class JS_PUBLIC_API AutoGCRooter
;
994 enum class AutoGCRooterKind
: uint8_t {
995 WrapperVector
, /* js::AutoWrapperVector */
996 Wrapper
, /* js::AutoWrapperRooter */
997 Custom
, /* js::CustomAutoRooter */
1002 using RootedListHeads
= mozilla::EnumeratedArray
<RootKind
, js::StackRootedBase
*,
1003 size_t(RootKind::Limit
)>;
1005 using AutoRooterListHeads
=
1006 mozilla::EnumeratedArray
<AutoGCRooterKind
, AutoGCRooter
*,
1007 size_t(AutoGCRooterKind::Limit
)>;
1009 // Superclass of JSContext which can be used for rooting data in use by the
1010 // current thread but that does not provide all the functions of a JSContext.
1011 class RootingContext
{
1012 // Stack GC roots for Rooted GC heap pointers.
1013 RootedListHeads stackRoots_
;
1014 template <typename T
>
1015 friend class Rooted
;
1017 // Stack GC roots for AutoFooRooter classes.
1018 AutoRooterListHeads autoGCRooters_
;
1019 friend class AutoGCRooter
;
1021 // Gecko profiling metadata.
1022 // This isn't really rooting related. It's only here because we want
1023 // GetContextProfilingStackIfEnabled to be inlineable into non-JS code, and
1024 // we didn't want to add another superclass of JSContext just for this.
1025 js::GeckoProfilerThread geckoProfiler_
;
1028 explicit RootingContext(js::Nursery
* nursery
);
1030 void traceStackRoots(JSTracer
* trc
);
1032 /* Implemented in gc/RootMarking.cpp. */
1033 void traceAllGCRooters(JSTracer
* trc
);
1034 void traceWrapperGCRooters(JSTracer
* trc
);
1035 static void traceGCRooterList(JSTracer
* trc
, AutoGCRooter
* head
);
1037 void checkNoGCRooters();
1039 js::GeckoProfilerThread
& geckoProfiler() { return geckoProfiler_
; }
1041 js::Nursery
& nursery() const {
1042 MOZ_ASSERT(nursery_
);
1047 // The remaining members in this class should only be accessed through
1048 // JSContext pointers. They are unrelated to rooting and are in place so
1049 // that inlined API functions can directly access the data.
1051 /* The nursery. Null for non-main-thread contexts. */
1052 js::Nursery
* nursery_
;
1054 /* The current zone. */
1057 /* The current realm. */
1061 /* Limit pointer for checking native stack consumption. */
1062 JS::NativeStackLimit nativeStackLimit
[StackKindCount
];
1065 // For WASI we can't catch call-stack overflows with stack-pointer checks, so
1066 // we count recursion depth with RAII based AutoCheckRecursionLimit.
1067 uint32_t wasiRecursionDepth
= 0u;
1069 static constexpr uint32_t wasiRecursionDepthLimit
= 350u;
1072 static const RootingContext
* get(const JSContext
* cx
) {
1073 return reinterpret_cast<const RootingContext
*>(cx
);
1076 static RootingContext
* get(JSContext
* cx
) {
1077 return reinterpret_cast<RootingContext
*>(cx
);
1080 friend JS::Realm
* js::GetContextRealm(const JSContext
* cx
);
1081 friend JS::Zone
* js::GetContextZone(const JSContext
* cx
);
1084 class JS_PUBLIC_API AutoGCRooter
{
1086 using Kind
= AutoGCRooterKind
;
1088 AutoGCRooter(JSContext
* cx
, Kind kind
)
1089 : AutoGCRooter(JS::RootingContext::get(cx
), kind
) {}
1090 AutoGCRooter(RootingContext
* cx
, Kind kind
)
1091 : down(cx
->autoGCRooters_
[kind
]),
1092 stackTop(&cx
->autoGCRooters_
[kind
]),
1094 MOZ_ASSERT(this != *stackTop
);
1099 MOZ_ASSERT(this == *stackTop
);
1103 void trace(JSTracer
* trc
);
1106 friend class RootingContext
;
1108 AutoGCRooter
* const down
;
1109 AutoGCRooter
** const stackTop
;
1112 * Discriminates actual subclass of this being used. The meaning is
1113 * indicated by the corresponding value in the Kind enum.
1117 /* No copy or assignment semantics. */
1118 AutoGCRooter(AutoGCRooter
& ida
) = delete;
1119 void operator=(AutoGCRooter
& ida
) = delete;
1120 } JS_HAZ_ROOTED_BASE
;
1123 * Custom rooting behavior for internal and external clients.
1125 * Deprecated. Where possible, use Rooted<> instead.
1127 class MOZ_RAII JS_PUBLIC_API CustomAutoRooter
: private AutoGCRooter
{
1129 template <typename CX
>
1130 explicit CustomAutoRooter(const CX
& cx
)
1131 : AutoGCRooter(cx
, AutoGCRooter::Kind::Custom
) {}
1133 friend void AutoGCRooter::trace(JSTracer
* trc
);
1136 virtual ~CustomAutoRooter() = default;
1138 /** Supplied by derived class to trace roots. */
1139 virtual void trace(JSTracer
* trc
) = 0;
1144 template <typename T
>
1145 constexpr bool IsTraceable_v
=
1146 MapTypeToRootKind
<T
>::kind
== JS::RootKind::Traceable
;
1148 template <typename T
>
1149 using RootedTraits
=
1150 std::conditional_t
<IsTraceable_v
<T
>, js::RootedTraceableTraits
<T
>,
1151 js::RootedGCThingTraits
<T
>>;
1153 } /* namespace detail */
1156 * Local variable of type T whose value is always rooted. This is typically
1157 * used for local variables, or for non-rooted values being passed to a
1158 * function that requires a handle, e.g. Foo(Root<T>(cx, x)).
1160 * If you want to add additional methods to Rooted for a specific
1161 * specialization, define a RootedOperations<T> specialization containing them.
1163 template <typename T
>
1164 class MOZ_RAII Rooted
: public detail::RootedTraits
<T
>::StackBase
,
1165 public js::RootedOperations
<T
, Rooted
<T
>> {
1166 inline void registerWithRootLists(RootedListHeads
& roots
) {
1167 this->stack
= &roots
[JS::MapTypeToRootKind
<T
>::kind
];
1168 this->prev
= *this->stack
;
1169 *this->stack
= this;
1172 inline RootedListHeads
& rootLists(RootingContext
* cx
) {
1173 return cx
->stackRoots_
;
1175 inline RootedListHeads
& rootLists(JSContext
* cx
) {
1176 return rootLists(RootingContext::get(cx
));
1180 using ElementType
= T
;
1182 // Construct an empty Rooted holding a safely initialized but empty T.
1183 // Requires T to have a copy constructor in order to copy the safely
1184 // initialized value.
1186 // Note that for SFINAE to reject this method, the 2nd template parameter must
1187 // depend on RootingContext somehow even though we really only care about T.
1188 template <typename RootingContext
,
1189 typename
= std::enable_if_t
<std::is_copy_constructible_v
<T
>,
1191 explicit Rooted(const RootingContext
& cx
)
1192 : ptr(SafelyInitialized
<T
>::create()) {
1193 registerWithRootLists(rootLists(cx
));
1196 // Provide an initial value. Requires T to be constructible from the given
1198 template <typename RootingContext
, typename S
>
1199 Rooted(const RootingContext
& cx
, S
&& initial
)
1200 : ptr(std::forward
<S
>(initial
)) {
1201 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1202 registerWithRootLists(rootLists(cx
));
1205 // (Traceables only) Construct the contained value from the given arguments.
1206 // Constructs in-place, so T does not need to be copyable or movable.
1208 // Note that a copyable Traceable passed only a RootingContext will
1209 // choose the above SafelyInitialized<T> constructor, because otherwise
1210 // identical functions with parameter packs are considered less specialized.
1212 // The SFINAE type must again depend on an inferred template parameter.
1214 typename RootingContext
, typename
... CtorArgs
,
1215 typename
= std::enable_if_t
<detail::IsTraceable_v
<T
>, RootingContext
>>
1216 explicit Rooted(const RootingContext
& cx
, CtorArgs
... args
)
1217 : ptr(std::forward
<CtorArgs
>(args
)...) {
1218 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1219 registerWithRootLists(rootLists(cx
));
1223 MOZ_ASSERT(*this->stack
== this);
1224 *this->stack
= this->prev
;
1228 * This method is public for Rooted so that Codegen.py can use a Rooted
1229 * interchangeably with a MutableHandleValue.
1231 void set(const T
& value
) {
1233 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1235 void set(T
&& value
) {
1236 ptr
= std::move(value
);
1237 MOZ_ASSERT(GCPolicy
<T
>::isValid(ptr
));
1240 DECLARE_POINTER_CONSTREF_OPS(T
);
1241 DECLARE_POINTER_ASSIGN_OPS(Rooted
<T
>, T
);
1243 T
& get() { return ptr
; }
1244 const T
& get() const { return ptr
; }
1246 T
* address() { return &ptr
; }
1247 const T
* address() const { return &ptr
; }
1252 Rooted(const Rooted
&) = delete;
1257 template <typename T
>
1258 struct DefineComparisonOps
<Rooted
<T
>> : std::true_type
{
1259 static const T
& get(const Rooted
<T
>& v
) { return v
.get(); }
1262 } // namespace detail
1264 template <typename
... Fs
>
1265 using RootedTuple
= Rooted
<std::tuple
<Fs
...>>;
1267 // Reference to a field in a RootedTuple. This is a drop-in replacement for an
1268 // individual Rooted.
1270 // This is very similar to a MutableHandle but with two differences: it has an
1271 // assignment operator so doesn't require set() to be called and its address
1272 // converts to a MutableHandle in the same way as a Rooted.
1274 // The field is specified by the type parameter, optionally disambiguated by
1275 // supplying the field index too.
1279 // RootedTuple<JSObject*, JSString*> roots(cx);
1280 // RootedField<JSObject*> obj(roots);
1281 // RootedField<JSString*> str(roots);
1285 // RootedTuple<JString*, JSObject*, JSObject*> roots(cx);
1286 // RootedField<JString*, 0> str(roots);
1287 // RootedField<JSObject*, 1> obj1(roots);
1288 // RootedField<JSObject*, 2> obj2(roots);
1289 template <typename T
, size_t N
/* = SIZE_MAX */>
1290 class MOZ_RAII RootedField
: public js::RootedOperations
<T
, RootedField
<T
, N
>> {
1292 friend class Handle
<T
>;
1293 friend class MutableHandle
<T
>;
1296 using ElementType
= T
;
1298 template <typename
... Fs
>
1299 explicit RootedField(RootedTuple
<Fs
...>& rootedTuple
) {
1300 using Tuple
= std::tuple
<Fs
...>;
1301 if constexpr (N
== SIZE_MAX
) {
1302 ptr
= &std::get
<T
>(rootedTuple
.get());
1304 static_assert(N
< std::tuple_size_v
<Tuple
>);
1305 static_assert(std::is_same_v
<T
, std::tuple_element_t
<N
, Tuple
>>);
1306 ptr
= &std::get
<N
>(rootedTuple
.get());
1309 template <typename
... Fs
, typename S
>
1310 explicit RootedField(RootedTuple
<Fs
...>& rootedTuple
, S
&& value
)
1311 : RootedField(rootedTuple
) {
1312 *ptr
= std::forward
<S
>(value
);
1315 T
& get() { return *ptr
; }
1316 const T
& get() const { return *ptr
; }
1317 void set(const T
& value
) {
1319 MOZ_ASSERT(GCPolicy
<T
>::isValid(*ptr
));
1321 void set(T
&& value
) {
1322 *ptr
= std::move(value
);
1323 MOZ_ASSERT(GCPolicy
<T
>::isValid(*ptr
));
1326 using WrapperT
= RootedField
<T
, N
>;
1327 DECLARE_POINTER_CONSTREF_OPS(T
);
1328 DECLARE_POINTER_ASSIGN_OPS(WrapperT
, T
);
1329 // DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr);
1330 // DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(*ptr);
1333 RootedField() = delete;
1334 RootedField(const RootedField
& other
) = delete;
1338 template <size_t N
, typename T
>
1339 struct DefineComparisonOps
<JS::RootedField
<T
, N
>> : std::true_type
{
1340 static const T
& get(const JS::RootedField
<T
, N
>& v
) { return v
.get(); }
1342 } // namespace detail
1344 } /* namespace JS */
1349 * Inlinable accessors for JSContext.
1351 * - These must not be available on the more restricted superclasses of
1352 * JSContext, so we can't simply define them on RootingContext.
1354 * - They're perfectly ordinary JSContext functionality, so ought to be
1355 * usable without resorting to jsfriendapi.h, and when JSContext is an
1358 inline JS::Realm
* GetContextRealm(const JSContext
* cx
) {
1359 return JS::RootingContext::get(cx
)->realm_
;
1362 inline JS::Compartment
* GetContextCompartment(const JSContext
* cx
) {
1363 if (JS::Realm
* realm
= GetContextRealm(cx
)) {
1364 return GetCompartmentForRealm(realm
);
1369 inline JS::Zone
* GetContextZone(const JSContext
* cx
) {
1370 return JS::RootingContext::get(cx
)->zone_
;
1373 inline ProfilingStack
* GetContextProfilingStackIfEnabled(JSContext
* cx
) {
1374 return JS::RootingContext::get(cx
)
1376 .getProfilingStackIfEnabled();
1380 * Augment the generic Rooted<T> interface when T = JSObject* with
1381 * class-querying and downcasting operations.
1383 * Given a Rooted<JSObject*> obj, one can view
1384 * Handle<StringObject*> h = obj.as<StringObject*>();
1385 * as an optimization of
1386 * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
1387 * Handle<StringObject*> h = rooted;
1389 template <typename Container
>
1390 class RootedOperations
<JSObject
*, Container
>
1391 : public MutableWrappedPtrOperations
<JSObject
*, Container
> {
1394 JS::Handle
<U
*> as() const;
1398 * Augment the generic Handle<T> interface when T = JSObject* with
1399 * downcasting operations.
1401 * Given a Handle<JSObject*> obj, one can view
1402 * Handle<StringObject*> h = obj.as<StringObject*>();
1403 * as an optimization of
1404 * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
1405 * Handle<StringObject*> h = rooted;
1407 template <typename Container
>
1408 class HandleOperations
<JSObject
*, Container
>
1409 : public WrappedPtrOperations
<JSObject
*, Container
> {
1412 JS::Handle
<U
*> as() const;
1415 } /* namespace js */
1419 template <typename T
>
1420 template <typename S
>
1421 inline Handle
<T
>::Handle(
1422 const Rooted
<S
>& root
,
1423 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
) {
1424 ptr
= reinterpret_cast<const T
*>(root
.address());
1427 template <typename T
>
1428 template <typename S
>
1429 inline Handle
<T
>::Handle(
1430 const PersistentRooted
<S
>& root
,
1431 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
) {
1432 ptr
= reinterpret_cast<const T
*>(root
.address());
1435 template <typename T
>
1436 template <typename S
>
1437 inline Handle
<T
>::Handle(
1438 MutableHandle
<S
>& root
,
1439 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
) {
1440 ptr
= reinterpret_cast<const T
*>(root
.address());
1443 template <typename T
>
1444 template <size_t N
, typename S
>
1445 inline Handle
<T
>::Handle(
1446 const RootedField
<S
, N
>& rootedField
,
1447 std::enable_if_t
<std::is_convertible_v
<S
, T
>, int> dummy
) {
1448 ptr
= reinterpret_cast<const T
*>(rootedField
.ptr
);
1451 template <typename T
>
1452 inline MutableHandle
<T
>::MutableHandle(Rooted
<T
>* root
) {
1453 static_assert(sizeof(MutableHandle
<T
>) == sizeof(T
*),
1454 "MutableHandle must be binary compatible with T*.");
1455 ptr
= root
->address();
1458 template <typename T
>
1460 inline MutableHandle
<T
>::MutableHandle(RootedField
<T
, N
>* rootedField
) {
1461 ptr
= rootedField
->ptr
;
1464 template <typename T
>
1465 inline MutableHandle
<T
>::MutableHandle(PersistentRooted
<T
>* root
) {
1466 static_assert(sizeof(MutableHandle
<T
>) == sizeof(T
*),
1467 "MutableHandle must be binary compatible with T*.");
1468 ptr
= root
->address();
1471 JS_PUBLIC_API
void AddPersistentRoot(RootingContext
* cx
, RootKind kind
,
1472 js::PersistentRootedBase
* root
);
1474 JS_PUBLIC_API
void AddPersistentRoot(JSRuntime
* rt
, RootKind kind
,
1475 js::PersistentRootedBase
* root
);
1478 * A copyable, assignable global GC root type with arbitrary lifetime, an
1479 * infallible constructor, and automatic unrooting on destruction.
1481 * These roots can be used in heap-allocated data structures, so they are not
1482 * associated with any particular JSContext or stack. They are registered with
1483 * the JSRuntime itself, without locking. Initialization may take place on
1484 * construction, or in two phases if the no-argument constructor is called
1485 * followed by init().
1487 * Note that you must not use an PersistentRooted in an object owned by a JS
1490 * Whenever one object whose lifetime is decided by the GC refers to another
1491 * such object, that edge must be traced only if the owning JS object is traced.
1492 * This applies not only to JS objects (which obviously are managed by the GC)
1493 * but also to C++ objects owned by JS objects.
1495 * If you put a PersistentRooted in such a C++ object, that is almost certainly
1496 * a leak. When a GC begins, the referent of the PersistentRooted is treated as
1497 * live, unconditionally (because a PersistentRooted is a *root*), even if the
1498 * JS object that owns it is unreachable. If there is any path from that
1499 * referent back to the JS object, then the C++ object containing the
1500 * PersistentRooted will not be destructed, and the whole blob of objects will
1501 * not be freed, even if there are no references to them from the outside.
1503 * In the context of Firefox, this is a severe restriction: almost everything in
1504 * Firefox is owned by some JS object or another, so using PersistentRooted in
1505 * such objects would introduce leaks. For these kinds of edges, Heap<T> or
1506 * TenuredHeap<T> would be better types. It's up to the implementor of the type
1507 * containing Heap<T> or TenuredHeap<T> members to make sure their referents get
1508 * marked when the object itself is marked.
1510 template <typename T
>
1511 class PersistentRooted
: public detail::RootedTraits
<T
>::PersistentBase
,
1512 public js::RootedOperations
<T
, PersistentRooted
<T
>> {
1513 void registerWithRootLists(RootingContext
* cx
) {
1514 MOZ_ASSERT(!initialized());
1515 JS::RootKind kind
= JS::MapTypeToRootKind
<T
>::kind
;
1516 AddPersistentRoot(cx
, kind
, this);
1519 void registerWithRootLists(JSRuntime
* rt
) {
1520 MOZ_ASSERT(!initialized());
1521 JS::RootKind kind
= JS::MapTypeToRootKind
<T
>::kind
;
1522 AddPersistentRoot(rt
, kind
, this);
1525 // Used when JSContext type is incomplete and so it is not known to inherit
1526 // from RootingContext.
1527 void registerWithRootLists(JSContext
* cx
) {
1528 registerWithRootLists(RootingContext::get(cx
));
1532 using ElementType
= T
;
1534 PersistentRooted() : ptr(SafelyInitialized
<T
>::create()) {}
1537 typename RootHolder
,
1538 typename
= std::enable_if_t
<std::is_copy_constructible_v
<T
>, RootHolder
>>
1539 explicit PersistentRooted(const RootHolder
& cx
)
1540 : ptr(SafelyInitialized
<T
>::create()) {
1541 registerWithRootLists(cx
);
1545 typename RootHolder
, typename U
,
1546 typename
= std::enable_if_t
<std::is_constructible_v
<T
, U
>, RootHolder
>>
1547 PersistentRooted(const RootHolder
& cx
, U
&& initial
)
1548 : ptr(std::forward
<U
>(initial
)) {
1549 registerWithRootLists(cx
);
1552 template <typename RootHolder
, typename
... CtorArgs
,
1553 typename
= std::enable_if_t
<detail::IsTraceable_v
<T
>, RootHolder
>>
1554 explicit PersistentRooted(const RootHolder
& cx
, CtorArgs
... args
)
1555 : ptr(std::forward
<CtorArgs
>(args
)...) {
1556 registerWithRootLists(cx
);
1559 PersistentRooted(const PersistentRooted
& rhs
) : ptr(rhs
.ptr
) {
1561 * Copy construction takes advantage of the fact that the original
1562 * is already inserted, and simply adds itself to whatever list the
1563 * original was on - no JSRuntime pointer needed.
1565 * This requires mutating rhs's links, but those should be 'mutable'
1566 * anyway. C++ doesn't let us declare mutable base classes.
1568 const_cast<PersistentRooted
&>(rhs
).setNext(this);
1571 bool initialized() const { return this->isInList(); }
1573 void init(RootingContext
* cx
) { init(cx
, SafelyInitialized
<T
>::create()); }
1574 void init(JSContext
* cx
) { init(RootingContext::get(cx
)); }
1576 template <typename U
>
1577 void init(RootingContext
* cx
, U
&& initial
) {
1578 ptr
= std::forward
<U
>(initial
);
1579 registerWithRootLists(cx
);
1581 template <typename U
>
1582 void init(JSContext
* cx
, U
&& initial
) {
1583 ptr
= std::forward
<U
>(initial
);
1584 registerWithRootLists(RootingContext::get(cx
));
1588 if (initialized()) {
1589 set(SafelyInitialized
<T
>::create());
1594 DECLARE_POINTER_CONSTREF_OPS(T
);
1595 DECLARE_POINTER_ASSIGN_OPS(PersistentRooted
<T
>, T
);
1597 T
& get() { return ptr
; }
1598 const T
& get() const { return ptr
; }
1601 MOZ_ASSERT(initialized());
1604 const T
* address() const { return &ptr
; }
1606 template <typename U
>
1607 void set(U
&& value
) {
1608 MOZ_ASSERT(initialized());
1609 ptr
= std::forward
<U
>(value
);
1618 template <typename T
>
1619 struct DefineComparisonOps
<PersistentRooted
<T
>> : std::true_type
{
1620 static const T
& get(const PersistentRooted
<T
>& v
) { return v
.get(); }
1623 } // namespace detail
1625 } /* namespace JS */
1629 template <typename T
, typename D
, typename Container
>
1630 class WrappedPtrOperations
<UniquePtr
<T
, D
>, Container
> {
1631 const UniquePtr
<T
, D
>& uniquePtr() const {
1632 return static_cast<const Container
*>(this)->get();
1636 explicit operator bool() const { return !!uniquePtr(); }
1637 T
* get() const { return uniquePtr().get(); }
1638 T
* operator->() const { return get(); }
1639 T
& operator*() const { return *uniquePtr(); }
1642 template <typename T
, typename D
, typename Container
>
1643 class MutableWrappedPtrOperations
<UniquePtr
<T
, D
>, Container
>
1644 : public WrappedPtrOperations
<UniquePtr
<T
, D
>, Container
> {
1645 UniquePtr
<T
, D
>& uniquePtr() { return static_cast<Container
*>(this)->get(); }
1648 [[nodiscard
]] typename UniquePtr
<T
, D
>::Pointer
release() {
1649 return uniquePtr().release();
1651 void reset(T
* ptr
= T()) { uniquePtr().reset(ptr
); }
1654 template <typename T
, typename Container
>
1655 class WrappedPtrOperations
<mozilla::Maybe
<T
>, Container
> {
1656 const mozilla::Maybe
<T
>& maybe() const {
1657 return static_cast<const Container
*>(this)->get();
1661 // This only supports a subset of Maybe's interface.
1662 bool isSome() const { return maybe().isSome(); }
1663 bool isNothing() const { return maybe().isNothing(); }
1664 const T
value() const { return maybe().value(); }
1665 const T
* operator->() const { return maybe().ptr(); }
1666 const T
& operator*() const { return maybe().ref(); }
1669 template <typename T
, typename Container
>
1670 class MutableWrappedPtrOperations
<mozilla::Maybe
<T
>, Container
>
1671 : public WrappedPtrOperations
<mozilla::Maybe
<T
>, Container
> {
1672 mozilla::Maybe
<T
>& maybe() { return static_cast<Container
*>(this)->get(); }
1675 // This only supports a subset of Maybe's interface.
1676 T
* operator->() { return maybe().ptr(); }
1677 T
& operator*() { return maybe().ref(); }
1678 void reset() { return maybe().reset(); }
1683 template <typename T
, typename TraceCallbacks
>
1684 void CallTraceCallbackOnNonHeap(T
* v
, const TraceCallbacks
& aCallbacks
,
1685 const char* aName
, void* aClosure
) {
1686 static_assert(sizeof(T
) == sizeof(JS::Heap
<T
>),
1687 "T and Heap<T> must be compatible.");
1689 mozilla::DebugOnly
<Cell
*> cell
= BarrierMethods
<T
>::asGCThingOrNull(*v
);
1691 MOZ_ASSERT(!IsInsideNursery(cell
));
1692 JS::Heap
<T
>* asHeapT
= reinterpret_cast<JS::Heap
<T
>*>(v
);
1693 aCallbacks
.Trace(asHeapT
, aName
, aClosure
);
1696 } /* namespace gc */
1698 template <typename Wrapper
, typename T1
, typename T2
>
1699 class WrappedPtrOperations
<std::pair
<T1
, T2
>, Wrapper
> {
1700 const std::pair
<T1
, T2
>& pair() const {
1701 return static_cast<const Wrapper
*>(this)->get();
1705 const T1
& first() const { return pair().first
; }
1706 const T2
& second() const { return pair().second
; }
1709 template <typename Wrapper
, typename T1
, typename T2
>
1710 class MutableWrappedPtrOperations
<std::pair
<T1
, T2
>, Wrapper
>
1711 : public WrappedPtrOperations
<std::pair
<T1
, T2
>, Wrapper
> {
1712 std::pair
<T1
, T2
>& pair() { return static_cast<Wrapper
*>(this)->get(); }
1715 T1
& first() { return pair().first
; }
1716 T2
& second() { return pair().second
; }
1719 } /* namespace js */
1721 #endif /* js_RootingAPI_h */