Merge autoland to mozilla-central. a=merge
[gecko.git] / js / public / RootingAPI.h
blob42be14e673519370d1f2f475effe4083ef0bb94d
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 <tuple>
17 #include <type_traits>
18 #include <utility>
20 #include "jspubtd.h"
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"
29 #include "js/Realm.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);
49 * DoSomething(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
60 * is required.
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
96 * following:
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
102 * every invocation.
104 * The following diagram explains the list of supported, implicit type
105 * conversions between classes of this family:
107 * Rooted<T> ----> Handle<T>
108 * | ^
109 * | |
110 * | |
111 * +---> MutableHandle<T>
112 * (via &)
114 * All of these types have an implicit conversion to raw pointers.
117 namespace js {
119 class Nursery;
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
147 // macros into scope
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) \
155 template <> \
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<>.
163 namespace gc {
164 struct Cell;
165 } /* namespace gc */
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) { \
178 set(p); \
179 return *this; \
181 Wrapper& operator=(T&& p) { \
182 set(std::move(p)); \
183 return *this; \
185 Wrapper& operator=(const Wrapper& other) { \
186 set(other.get()); \
187 return *this; \
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); }
203 } /* namespace js */
205 namespace JS {
207 JS_PUBLIC_API void HeapObjectPostWriteBarrier(JSObject** objp, JSObject* prev,
208 JSObject* next);
209 JS_PUBLIC_API void HeapObjectWriteBarriers(JSObject** objp, JSObject* prev,
210 JSObject* next);
211 JS_PUBLIC_API void HeapStringWriteBarriers(JSString** objp, JSString* prev,
212 JSString* next);
213 JS_PUBLIC_API void HeapBigIntWriteBarriers(JS::BigInt** bip, JS::BigInt* prev,
214 JS::BigInt* next);
215 JS_PUBLIC_API void HeapScriptWriteBarriers(JSScript** objp, JSScript* prev,
216 JSScript* next);
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 {
226 static T create() {
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
235 // a null pointer.
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");
249 #endif
251 return T();
255 #ifdef JS_DEBUG
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(
262 js::gc::Cell* cell);
263 #else
264 inline void AssertGCThingMustBeTenured(JSObject* obj) {}
265 inline void AssertGCThingIsNotNurseryAllocable(js::gc::Cell* cell) {}
266 #endif
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");
300 public:
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());
328 return *this;
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 {
340 exposeToActiveJS();
341 return ptr;
343 const T& unbarrieredGet() const { return ptr; }
345 void set(const T& newPtr) {
346 T tmp = ptr;
347 ptr = 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));
359 private:
360 void writeBarriers(const T& prev, const T& next) {
361 js::BarrierMethods<T>::writeBarriers(&ptr, prev, next);
364 T ptr;
367 namespace detail {
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)) {
387 return false;
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.
403 #ifdef DEBUG
405 inline void AssertCellIsNotGray(const js::gc::Cell* maybeCell) {
406 if (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());
419 #else
421 inline void AssertCellIsNotGray(js::gc::Cell* maybeCell) {}
422 inline void AssertObjectIsNotGray(JSObject* maybeObj) {}
423 inline void AssertObjectIsNotGray(const JS::Heap<JSObject*>& obj) {}
425 #endif
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
450 * Heap<T> are:
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");
461 public:
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) {
475 setPtr(p);
476 return *this;
478 TenuredHeap<T>& operator=(const TenuredHeap<T>& other) {
479 preWriteBarrier();
480 bits = other.bits;
481 return *this;
484 ~TenuredHeap() { preWriteBarrier(); }
486 void setPtr(T newPtr) {
487 preWriteBarrier();
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));
493 if (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);
501 bits |= flagsToSet;
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());
520 T getPtr() const {
521 exposeToActiveJS();
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()));
532 private:
533 enum {
534 maskBits = 3,
535 flagsMask = (1 << maskBits) - 1,
538 void preWriteBarrier() {
539 if (T prev = unbarrieredGetPtr()) {
540 JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev));
544 uintptr_t bits;
547 namespace detail {
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) {
560 T tmp = aX;
561 aX = aY;
562 aY = tmp;
565 template <typename T>
566 void swap(Heap<T>& aX, Heap<T>& aY) {
567 T tmp = aX;
568 aX = aY;
569 aY = tmp;
572 static MOZ_ALWAYS_INLINE bool ObjectIsMarkedGray(
573 const JS::TenuredHeap<JSObject*>& obj) {
574 return ObjectIsMarkedGray(obj.unbarrieredGetPtr());
577 template <typename T>
578 class MutableHandle;
579 template <typename T>
580 class Rooted;
581 template <typename T, size_t N = SIZE_MAX>
582 class RootedField;
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>;
598 public:
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>
605 MOZ_IMPLICIT Handle(
606 Handle<S> handle,
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);
670 private:
671 Handle() = default;
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) {}
678 const T* ptr;
681 namespace detail {
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
696 * them.
698 template <typename T>
699 class MOZ_STACK_CLASS MutableHandle
700 : public js::MutableHandleOperations<T, MutableHandle<T>> {
701 public:
702 using ElementType = T;
704 inline MOZ_IMPLICIT MutableHandle(Rooted<T>* root);
705 template <size_t N>
706 inline MOZ_IMPLICIT MutableHandle(RootedField<T, N>* root);
707 inline MOZ_IMPLICIT MutableHandle(PersistentRooted<T>* root);
709 private:
710 // Disallow nullptr for overloading purposes.
711 MutableHandle(decltype(nullptr)) = delete;
713 public:
714 MutableHandle(const MutableHandle<T>&) = default;
715 void set(const T& v) {
716 *ptr = v;
717 MOZ_ASSERT(GCPolicy<T>::isValid(*ptr));
719 void set(T&& v) {
720 *ptr = std::move(v);
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) {
732 MutableHandle h;
733 h.ptr = p;
734 return h;
737 DECLARE_POINTER_CONSTREF_OPS(T);
738 DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr);
739 DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(*ptr);
741 private:
742 MutableHandle() = default;
743 DELETE_ASSIGNMENT_OPS(MutableHandle, T);
745 T* ptr;
748 namespace detail {
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
757 } /* namespace JS */
759 namespace js {
761 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) {
768 if (!v) {
769 return nullptr;
771 MOZ_ASSERT(uintptr_t(v) > 32);
772 return reinterpret_cast<gc::Cell*>(v);
774 static void exposeToJS(T* t) {
775 if (t) {
776 js::gc::ExposeGCThingToActiveJS(JS::GCCellPtr(t));
779 static void readBarrier(T* t) {
780 if (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) {
791 if (prev) {
792 JS::IncrementalPreWriteBarrier(JS::GCCellPtr(prev));
794 if (next) {
795 JS::AssertGCThingIsNotNurseryAllocable(
796 reinterpret_cast<js::gc::Cell*>(next));
801 template <>
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) {
811 if (obj) {
812 JS::ExposeObjectToActiveJS(obj);
817 template <>
818 struct BarrierMethods<JSFunction*>
819 : public detail::PtrBarrierMethodsBase<JSFunction> {
820 static void writeBarriers(JSFunction** vp, JSFunction* prev,
821 JSFunction* next) {
822 JS::HeapObjectWriteBarriers(reinterpret_cast<JSObject**>(vp),
823 reinterpret_cast<JSObject*>(prev),
824 reinterpret_cast<JSObject*>(next));
826 static void exposeToJS(JSFunction* fun) {
827 if (fun) {
828 JS::ExposeObjectToActiveJS(reinterpret_cast<JSObject*>(fun));
833 template <>
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);
841 template <>
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);
849 template <>
850 struct BarrierMethods<JS::BigInt*>
851 : public detail::PtrBarrierMethodsBase<JS::BigInt> {
852 static void writeBarriers(JS::BigInt** vp, JS::BigInt* prev,
853 JS::BigInt* next) {
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 {
871 using Key = T;
872 using Lookup = T;
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>;
885 using Lookup = 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);
901 } // namespace js
903 namespace mozilla {
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),
910 hashOut);
912 template <typename Lookup>
913 static bool ensureHash(Lookup&& l, HashNumber* hashOut) {
914 return js::StableCellHasher<T>::ensureHash(std::forward<Lookup>(l),
915 hashOut);
919 } // namespace mozilla
921 namespace js {
923 struct VirtualTraceable {
924 virtual ~VirtualTraceable() = default;
925 virtual void trace(JSTracer* trc, const char* name) = 0;
928 class StackRootedBase {
929 public:
930 StackRootedBase* previous() { return prev; }
932 protected:
933 StackRootedBase** stack;
934 StackRootedBase* prev;
936 template <typename T>
937 auto* derived() {
938 return static_cast<JS::Rooted<T>*>(this);
942 class PersistentRootedBase
943 : protected mozilla::LinkedListElement<PersistentRootedBase> {
944 protected:
945 friend class mozilla::LinkedList<PersistentRootedBase>;
946 friend class mozilla::LinkedListElement<PersistentRootedBase>;
948 template <typename T>
949 auto* derived() {
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 {
962 public:
963 void trace(JSTracer* trc, const char* name);
966 template <typename Base, typename T>
967 class TypedRootedTraceableBase : public Base {
968 public:
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>;
988 } /* namespace js */
990 namespace JS {
992 class JS_PUBLIC_API AutoGCRooter;
994 enum class AutoGCRooterKind : uint8_t {
995 WrapperVector, /* js::AutoWrapperVector */
996 Wrapper, /* js::AutoWrapperRooter */
997 Custom, /* js::CustomAutoRooter */
999 Limit
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_;
1027 public:
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_);
1043 return *nursery_;
1046 protected:
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. */
1055 Zone* zone_;
1057 /* The current realm. */
1058 Realm* realm_;
1060 public:
1061 /* Limit pointer for checking native stack consumption. */
1062 JS::NativeStackLimit nativeStackLimit[StackKindCount];
1064 #ifdef __wasi__
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;
1070 #endif // __wasi__
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 {
1085 public:
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]),
1093 kind_(kind) {
1094 MOZ_ASSERT(this != *stackTop);
1095 *stackTop = this;
1098 ~AutoGCRooter() {
1099 MOZ_ASSERT(this == *stackTop);
1100 *stackTop = down;
1103 void trace(JSTracer* trc);
1105 private:
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.
1115 Kind kind_;
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 {
1128 public:
1129 template <typename CX>
1130 explicit CustomAutoRooter(const CX& cx)
1131 : AutoGCRooter(cx, AutoGCRooter::Kind::Custom) {}
1133 friend void AutoGCRooter::trace(JSTracer* trc);
1135 protected:
1136 virtual ~CustomAutoRooter() = default;
1138 /** Supplied by derived class to trace roots. */
1139 virtual void trace(JSTracer* trc) = 0;
1142 namespace detail {
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));
1179 public:
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>,
1190 RootingContext>>
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
1197 // argument.
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.
1213 template <
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));
1222 ~Rooted() {
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) {
1232 ptr = 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; }
1249 private:
1250 T ptr;
1252 Rooted(const Rooted&) = delete;
1253 } JS_HAZ_ROOTED;
1255 namespace detail {
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.
1277 // Used like this:
1279 // RootedTuple<JSObject*, JSString*> roots(cx);
1280 // RootedField<JSObject*> obj(roots);
1281 // RootedField<JSString*> str(roots);
1283 // or:
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>> {
1291 T* ptr;
1292 friend class Handle<T>;
1293 friend class MutableHandle<T>;
1295 public:
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());
1303 } else {
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) {
1318 *ptr = 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);
1332 private:
1333 RootedField() = delete;
1334 RootedField(const RootedField& other) = delete;
1337 namespace detail {
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 */
1346 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
1356 * incomplete type.
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);
1366 return nullptr;
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)
1375 ->geckoProfiler()
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> {
1392 public:
1393 template <class U>
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> {
1410 public:
1411 template <class U>
1412 JS::Handle<U*> as() const;
1415 } /* namespace js */
1417 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>
1459 template <size_t N>
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
1488 * object:
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));
1531 public:
1532 using ElementType = T;
1534 PersistentRooted() : ptr(SafelyInitialized<T>::create()) {}
1536 template <
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);
1544 template <
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));
1587 void reset() {
1588 if (initialized()) {
1589 set(SafelyInitialized<T>::create());
1590 this->remove();
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; }
1600 T* address() {
1601 MOZ_ASSERT(initialized());
1602 return &ptr;
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);
1612 private:
1613 T ptr;
1614 } JS_HAZ_ROOTED;
1616 namespace detail {
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 */
1627 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();
1635 public:
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(); }
1647 public:
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();
1660 public:
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(); }
1674 public:
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(); }
1681 namespace gc {
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.");
1688 MOZ_ASSERT(v);
1689 mozilla::DebugOnly<Cell*> cell = BarrierMethods<T>::asGCThingOrNull(*v);
1690 MOZ_ASSERT(cell);
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();
1704 public:
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(); }
1714 public:
1715 T1& first() { return pair().first; }
1716 T2& second() { return pair().second; }
1719 } /* namespace js */
1721 #endif /* js_RootingAPI_h */