1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
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/. */
6
7 #ifndef js_RootingAPI_h
8 #define js_RootingAPI_h
9
10 #include "mozilla/Attributes.h"
11 #include "mozilla/DebugOnly.h"
12 #include "mozilla/GuardObjects.h"
13 #include "mozilla/LinkedList.h"
14 #include "mozilla/Move.h"
15 #include "mozilla/TypeTraits.h"
16
17 #include <type_traits>
18
19 #include "jspubtd.h"
20
21 #include "js/GCAnnotations.h"
22 #include "js/GCPolicyAPI.h"
23 #include "js/HeapAPI.h"
24 #include "js/ProfilingStack.h"
25 #include "js/TypeDecls.h"
26 #include "js/UniquePtr.h"
27 #include "js/Utility.h"
28
29 /*
30 * Moving GC Stack Rooting
31 *
32 * A moving GC may change the physical location of GC allocated things, even
33 * when they are rooted, updating all pointers to the thing to refer to its new
34 * location. The GC must therefore know about all live pointers to a thing,
35 * not just one of them, in order to behave correctly.
36 *
37 * The |Rooted| and |Handle| classes below are used to root stack locations
38 * whose value may be held live across a call that can trigger GC. For a
39 * code fragment such as:
40 *
41 * JSObject* obj = NewObject(cx);
42 * DoSomething(cx);
43 * ... = obj->lastProperty();
44 *
45 * If |DoSomething()| can trigger a GC, the stack location of |obj| must be
46 * rooted to ensure that the GC does not move the JSObject referred to by
47 * |obj| without updating |obj|'s location itself. This rooting must happen
48 * regardless of whether there are other roots which ensure that the object
49 * itself will not be collected.
50 *
51 * If |DoSomething()| cannot trigger a GC, and the same holds for all other
52 * calls made between |obj|'s definitions and its last uses, then no rooting
53 * is required.
54 *
55 * SpiderMonkey can trigger a GC at almost any time and in ways that are not
56 * always clear. For example, the following innocuous-looking actions can
57 * cause a GC: allocation of any new GC thing; JSObject::hasProperty;
58 * JS_ReportError and friends; and ToNumber, among many others. The following
59 * dangerous-looking actions cannot trigger a GC: js_malloc, cx->malloc_,
60 * rt->malloc_, and friends and JS_ReportOutOfMemory.
61 *
62 * The following family of three classes will exactly root a stack location.
63 * Incorrect usage of these classes will result in a compile error in almost
64 * all cases. Therefore, it is very hard to be incorrectly rooted if you use
65 * these classes exclusively. These classes are all templated on the type T of
66 * the value being rooted.
67 *
68 * - Rooted<T> declares a variable of type T, whose value is always rooted.
69 * Rooted<T> may be automatically coerced to a Handle<T>, below. Rooted<T>
70 * should be used whenever a local variable's value may be held live across a
71 * call which can trigger a GC.
72 *
73 * - Handle<T> is a const reference to a Rooted<T>. Functions which take GC
74 * things or values as arguments and need to root those arguments should
75 * generally use handles for those arguments and avoid any explicit rooting.
76 * This has two benefits. First, when several such functions call each other
77 * then redundant rooting of multiple copies of the GC thing can be avoided.
78 * Second, if the caller does not pass a rooted value a compile error will be
79 * generated, which is quicker and easier to fix than when relying on a
80 * separate rooting analysis.
81 *
82 * - MutableHandle<T> is a non-const reference to Rooted<T>. It is used in the
83 * same way as Handle<T> and includes a |set(const T& v)| method to allow
84 * updating the value of the referenced Rooted<T>. A MutableHandle<T> can be
85 * created with an implicit cast from a Rooted<T>*.
86 *
87 * In some cases the small performance overhead of exact rooting (measured to
88 * be a few nanoseconds on desktop) is too much. In these cases, try the
89 * following:
90 *
91 * - Move all Rooted<T> above inner loops: this allows you to re-use the root
92 * on each iteration of the loop.
93 *
94 * - Pass Handle<T> through your hot call stack to avoid re-rooting costs at
95 * every invocation.
96 *
97 * The following diagram explains the list of supported, implicit type
98 * conversions between classes of this family:
99 *
100 * Rooted<T> ----> Handle<T>
101 * | ^
102 * | |
103 * | |
104 * +---> MutableHandle<T>
105 * (via &)
106 *
107 * All of these types have an implicit conversion to raw pointers.
108 */
109
110 namespace js {
111
112 template <typename T>
113 struct BarrierMethods {};
114
115 template <typename Element, typename Wrapper>
116 class WrappedPtrOperations {};
117
118 template <typename Element, typename Wrapper>
119 class MutableWrappedPtrOperations
120 : public WrappedPtrOperations<Element, Wrapper> {};
121
122 template <typename T, typename Wrapper>
123 class RootedBase : public MutableWrappedPtrOperations<T, Wrapper> {};
124
125 template <typename T, typename Wrapper>
126 class HandleBase : public WrappedPtrOperations<T, Wrapper> {};
127
128 template <typename T, typename Wrapper>
129 class MutableHandleBase : public MutableWrappedPtrOperations<T, Wrapper> {};
130
131 template <typename T, typename Wrapper>
132 class HeapBase : public MutableWrappedPtrOperations<T, Wrapper> {};
133
134 // Cannot use FOR_EACH_HEAP_ABLE_GC_POINTER_TYPE, as this would import too many
135 // macros into scope
136 template <typename T>
137 struct IsHeapConstructibleType {
138 static constexpr bool value = false;
139 };
140 #define DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE(T) \
141 template <> \
142 struct IsHeapConstructibleType<T> { \
143 static constexpr bool value = true; \
144 };
145 FOR_EACH_PUBLIC_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)146 FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE)
147 #undef DECLARE_IS_HEAP_CONSTRUCTIBLE_TYPE
148
149 template <typename T, typename Wrapper>
150 class PersistentRootedBase : public MutableWrappedPtrOperations<T, Wrapper> {};
151
152 template <typename T>
153 class FakeRooted;
154
155 template <typename T>
156 class FakeMutableHandle;
157
158 namespace gc {
159 struct Cell;
160 template <typename T>
161 struct PersistentRootedMarker;
162 } /* namespace gc */
163
164 // Important: Return a reference so passing a Rooted<T>, etc. to
165 // something that takes a |const T&| is not a GC hazard.
166 #define DECLARE_POINTER_CONSTREF_OPS(T) \
167 operator const T&() const { return get(); } \
168 const T& operator->() const { return get(); }
169
170 // Assignment operators on a base class are hidden by the implicitly defined
171 // operator= on the derived class. Thus, define the operator= directly on the
172 // class as we would need to manually pass it through anyway.
173 #define DECLARE_POINTER_ASSIGN_OPS(Wrapper, T) \
174 Wrapper<T>& operator=(const T& p) { \
175 set(p); \
176 return *this; \
177 } \
178 Wrapper<T>& operator=(T&& p) { \
179 set(mozilla::Move(p)); \
180 return *this; \
181 } \
182 Wrapper<T>& operator=(const Wrapper<T>& other) { \
183 set(other.get()); \
184 return *this; \
185 }
186
187 #define DELETE_ASSIGNMENT_OPS(Wrapper, T) \
188 template <typename S> \
189 Wrapper<T>& operator=(S) = delete; \
190 Wrapper<T>& operator=(const Wrapper<T>&) = delete;
191
192 #define DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr) \
193 const T* address() const { return &(ptr); } \
194 const T& get() const { return (ptr); }
195
196 #define DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(ptr) \
197 T* address() { return &(ptr); } \
198 T& get() { return (ptr); }
199
200 } /* namespace js */
201
202 namespace JS {
203
204 template <typename T>
205 class Rooted;
206 template <typename T>
207 class PersistentRooted;
208
209 /* This is exposing internal state of the GC for inlining purposes. */
210 JS_FRIEND_API bool isGCEnabled();
211
212 JS_FRIEND_API void HeapObjectPostBarrier(JSObject** objp, JSObject* prev,
213 JSObject* next);
214 JS_FRIEND_API void HeapStringPostBarrier(JSString** objp, JSString* prev,
215 JSString* next);
216
217 #ifdef JS_DEBUG
218 /**
219 * For generational GC, assert that an object is in the tenured generation as
220 * opposed to being in the nursery.
221 */
222 extern JS_FRIEND_API void AssertGCThingMustBeTenured(JSObject* obj);
223 extern JS_FRIEND_API void AssertGCThingIsNotNurseryAllocable(
224 js::gc::Cell* cell);
225 #else
AssertGCThingMustBeTenured(JSObject * obj)226 inline void AssertGCThingMustBeTenured(JSObject* obj) {}
AssertGCThingIsNotNurseryAllocable(js::gc::Cell * cell)227 inline void AssertGCThingIsNotNurseryAllocable(js::gc::Cell* cell) {}
228 #endif
229
230 /**
231 * The Heap<T> class is a heap-stored reference to a JS GC thing. All members of
232 * heap classes that refer to GC things should use Heap<T> (or possibly
233 * TenuredHeap<T>, described below).
234 *
235 * Heap<T> is an abstraction that hides some of the complexity required to
236 * maintain GC invariants for the contained reference. It uses operator
237 * overloading to provide a normal pointer interface, but notifies the GC every
238 * time the value it contains is updated. This is necessary for generational GC,
239 * which keeps track of all pointers into the nursery.
240 *
241 * Heap<T> instances must be traced when their containing object is traced to
242 * keep the pointed-to GC thing alive.
243 *
244 * Heap<T> objects should only be used on the heap. GC references stored on the
245 * C/C++ stack must use Rooted/Handle/MutableHandle instead.
246 *
247 * Type T must be a public GC pointer type.
248 */
249 template <typename T>
250 class MOZ_NON_MEMMOVABLE Heap : public js::HeapBase<T, Heap<T>> {
251 // Please note: this can actually also be used by nsXBLMaybeCompiled<T>, for
252 // legacy reasons.
253 static_assert(js::IsHeapConstructibleType<T>::value,
254 "Type T must be a public GC pointer type");
255
256 public:
257 using ElementType = T;
258
Heap()259 Heap() {
260 static_assert(sizeof(T) == sizeof(Heap<T>),
261 "Heap<T> must be binary compatible with T.");
262 init(GCPolicy<T>::initial());
263 }
Heap(const T & p)264 explicit Heap(const T& p) { init(p); }
265
266 /*
267 * For Heap, move semantics are equivalent to copy semantics. In C++, a
268 * copy constructor taking const-ref is the way to get a single function
269 * that will be used for both lvalue and rvalue copies, so we can simply
270 * omit the rvalue variant.
271 */
Heap(const Heap<T> & p)272 explicit Heap(const Heap<T>& p) { init(p.ptr); }
273
~Heap()274 ~Heap() { post(ptr, GCPolicy<T>::initial()); }
275
276 DECLARE_POINTER_CONSTREF_OPS(T);
277 DECLARE_POINTER_ASSIGN_OPS(Heap, T);
278
address()279 const T* address() const { return &ptr; }
280
exposeToActiveJS()281 void exposeToActiveJS() const { js::BarrierMethods<T>::exposeToJS(ptr); }
get()282 const T& get() const {
283 exposeToActiveJS();
284 return ptr;
285 }
unbarrieredGet()286 const T& unbarrieredGet() const { return ptr; }
287
unsafeGet()288 T* unsafeGet() { return &ptr; }
289
290 explicit operator bool() const {
291 return bool(js::BarrierMethods<T>::asGCThingOrNull(ptr));
292 }
293 explicit operator bool() {
294 return bool(js::BarrierMethods<T>::asGCThingOrNull(ptr));
295 }
296
297 private:
init(const T & newPtr)298 void init(const T& newPtr) {
299 ptr = newPtr;
300 post(GCPolicy<T>::initial(), ptr);
301 }
302
set(const T & newPtr)303 void set(const T& newPtr) {
304 T tmp = ptr;
305 ptr = newPtr;
306 post(tmp, ptr);
307 }
308
post(const T & prev,const T & next)309 void post(const T& prev, const T& next) {
310 js::BarrierMethods<T>::postBarrier(&ptr, prev, next);
311 }
312
313 T ptr;
314 };
315
ObjectIsTenured(JSObject * obj)316 static MOZ_ALWAYS_INLINE bool ObjectIsTenured(JSObject* obj) {
317 return !js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell*>(obj));
318 }
319
ObjectIsTenured(const Heap<JSObject * > & obj)320 static MOZ_ALWAYS_INLINE bool ObjectIsTenured(const Heap<JSObject*>& obj) {
321 return ObjectIsTenured(obj.unbarrieredGet());
322 }
323
ObjectIsMarkedGray(JSObject * obj)324 static MOZ_ALWAYS_INLINE bool ObjectIsMarkedGray(JSObject* obj) {
325 auto cell = reinterpret_cast<js::gc::Cell*>(obj);
326 return js::gc::detail::CellIsMarkedGrayIfKnown(cell);
327 }
328
ObjectIsMarkedGray(const JS::Heap<JSObject * > & obj)329 static MOZ_ALWAYS_INLINE bool ObjectIsMarkedGray(
330 const JS::Heap<JSObject*>& obj) {
331 return ObjectIsMarkedGray(obj.unbarrieredGet());
332 }
333
334 // The following *IsNotGray functions are for use in assertions and take account
335 // of the eventual gray marking state at the end of any ongoing incremental GC.
336 #ifdef DEBUG
CellIsNotGray(js::gc::Cell * maybeCell)337 inline bool CellIsNotGray(js::gc::Cell* maybeCell) {
338 if (!maybeCell) return true;
339
340 return js::gc::detail::CellIsNotGray(maybeCell);
341 }
342
ObjectIsNotGray(JSObject * maybeObj)343 inline bool ObjectIsNotGray(JSObject* maybeObj) {
344 return CellIsNotGray(reinterpret_cast<js::gc::Cell*>(maybeObj));
345 }
346
ObjectIsNotGray(const JS::Heap<JSObject * > & obj)347 inline bool ObjectIsNotGray(const JS::Heap<JSObject*>& obj) {
348 return ObjectIsNotGray(obj.unbarrieredGet());
349 }
350 #endif
351
352 /**
353 * The TenuredHeap<T> class is similar to the Heap<T> class above in that it
354 * encapsulates the GC concerns of an on-heap reference to a JS object. However,
355 * it has two important differences:
356 *
357 * 1) Pointers which are statically known to only reference "tenured" objects
358 * can avoid the extra overhead of SpiderMonkey's write barriers.
359 *
360 * 2) Objects in the "tenured" heap have stronger alignment restrictions than
361 * those in the "nursery", so it is possible to store flags in the lower
362 * bits of pointers known to be tenured. TenuredHeap wraps a normal tagged
363 * pointer with a nice API for accessing the flag bits and adds various
364 * assertions to ensure that it is not mis-used.
365 *
366 * GC things are said to be "tenured" when they are located in the long-lived
367 * heap: e.g. they have gained tenure as an object by surviving past at least
368 * one GC. For performance, SpiderMonkey allocates some things which are known
369 * to normally be long lived directly into the tenured generation; for example,
370 * global objects. Additionally, SpiderMonkey does not visit individual objects
371 * when deleting non-tenured objects, so object with finalizers are also always
372 * tenured; for instance, this includes most DOM objects.
373 *
374 * The considerations to keep in mind when using a TenuredHeap<T> vs a normal
375 * Heap<T> are:
376 *
377 * - It is invalid for a TenuredHeap<T> to refer to a non-tenured thing.
378 * - It is however valid for a Heap<T> to refer to a tenured thing.
379 * - It is not possible to store flag bits in a Heap<T>.
380 */
381 template <typename T>
382 class TenuredHeap : public js::HeapBase<T, TenuredHeap<T>> {
383 public:
384 using ElementType = T;
385
TenuredHeap()386 TenuredHeap() : bits(0) {
387 static_assert(sizeof(T) == sizeof(TenuredHeap<T>),
388 "TenuredHeap<T> must be binary compatible with T.");
389 }
TenuredHeap(T p)390 explicit TenuredHeap(T p) : bits(0) { setPtr(p); }
TenuredHeap(const TenuredHeap<T> & p)391 explicit TenuredHeap(const TenuredHeap<T>& p) : bits(0) {
392 setPtr(p.getPtr());
393 }
394
setPtr(T newPtr)395 void setPtr(T newPtr) {
396 MOZ_ASSERT((reinterpret_cast<uintptr_t>(newPtr) & flagsMask) == 0);
397 MOZ_ASSERT(js::gc::IsCellPointerValidOrNull(newPtr));
398 if (newPtr) AssertGCThingMustBeTenured(newPtr);
399 bits = (bits & flagsMask) | reinterpret_cast<uintptr_t>(newPtr);
400 }
401
setFlags(uintptr_t flagsToSet)402 void setFlags(uintptr_t flagsToSet) {
403 MOZ_ASSERT((flagsToSet & ~flagsMask) == 0);
404 bits |= flagsToSet;
405 }
406
unsetFlags(uintptr_t flagsToUnset)407 void unsetFlags(uintptr_t flagsToUnset) {
408 MOZ_ASSERT((flagsToUnset & ~flagsMask) == 0);
409 bits &= ~flagsToUnset;
410 }
411
hasFlag(uintptr_t flag)412 bool hasFlag(uintptr_t flag) const {
413 MOZ_ASSERT((flag & ~flagsMask) == 0);
414 return (bits & flag) != 0;
415 }
416
unbarrieredGetPtr()417 T unbarrieredGetPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); }
getFlags()418 uintptr_t getFlags() const { return bits & flagsMask; }
419
exposeToActiveJS()420 void exposeToActiveJS() const {
421 js::BarrierMethods<T>::exposeToJS(unbarrieredGetPtr());
422 }
getPtr()423 T getPtr() const {
424 exposeToActiveJS();
425 return unbarrieredGetPtr();
426 }
427
T()428 operator T() const { return getPtr(); }
429 T operator->() const { return getPtr(); }
430
431 explicit operator bool() const {
432 return bool(js::BarrierMethods<T>::asGCThingOrNull(unbarrieredGetPtr()));
433 }
434 explicit operator bool() {
435 return bool(js::BarrierMethods<T>::asGCThingOrNull(unbarrieredGetPtr()));
436 }
437
438 TenuredHeap<T>& operator=(T p) {
439 setPtr(p);
440 return *this;
441 }
442
443 TenuredHeap<T>& operator=(const TenuredHeap<T>& other) {
444 bits = other.bits;
445 return *this;
446 }
447
448 private:
449 enum {
450 maskBits = 3,
451 flagsMask = (1 << maskBits) - 1,
452 };
453
454 uintptr_t bits;
455 };
456
457 /**
458 * Reference to a T that has been rooted elsewhere. This is most useful
459 * as a parameter type, which guarantees that the T lvalue is properly
460 * rooted. See "Move GC Stack Rooting" above.
461 *
462 * If you want to add additional methods to Handle for a specific
463 * specialization, define a HandleBase<T> specialization containing them.
464 */
465 template <typename T>
466 class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T, Handle<T>> {
467 friend class JS::MutableHandle<T>;
468
469 public:
470 using ElementType = T;
471
472 /* Creates a handle from a handle of a type convertible to T. */
473 template <typename S>
474 MOZ_IMPLICIT Handle(
475 Handle<S> handle,
476 typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type
477 dummy = 0) {
478 static_assert(sizeof(Handle<T>) == sizeof(T*),
479 "Handle must be binary compatible with T*.");
480 ptr = reinterpret_cast<const T*>(handle.address());
481 }
482
Handle(decltype (nullptr))483 MOZ_IMPLICIT Handle(decltype(nullptr)) {
484 static_assert(mozilla::IsPointer<T>::value,
485 "nullptr_t overload not valid for non-pointer types");
486 static void* const ConstNullValue = nullptr;
487 ptr = reinterpret_cast<const T*>(&ConstNullValue);
488 }
489
Handle(MutableHandle<T> handle)490 MOZ_IMPLICIT Handle(MutableHandle<T> handle) { ptr = handle.address(); }
491
492 /*
493 * Take care when calling this method!
494 *
495 * This creates a Handle from the raw location of a T.
496 *
497 * It should be called only if the following conditions hold:
498 *
499 * 1) the location of the T is guaranteed to be marked (for some reason
500 * other than being a Rooted), e.g., if it is guaranteed to be reachable
501 * from an implicit root.
502 *
503 * 2) the contents of the location are immutable, or at least cannot change
504 * for the lifetime of the handle, as its users may not expect its value
505 * to change underneath them.
506 */
fromMarkedLocation(const T * p)507 static constexpr Handle fromMarkedLocation(const T* p) {
508 return Handle(p, DeliberatelyChoosingThisOverload,
509 ImUsingThisOnlyInFromFromMarkedLocation);
510 }
511
512 /*
513 * Construct a handle from an explicitly rooted location. This is the
514 * normal way to create a handle, and normally happens implicitly.
515 */
516 template <typename S>
517 inline MOZ_IMPLICIT Handle(
518 const Rooted<S>& root,
519 typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type
520 dummy = 0);
521
522 template <typename S>
523 inline MOZ_IMPLICIT Handle(
524 const PersistentRooted<S>& root,
525 typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type
526 dummy = 0);
527
528 /* Construct a read only handle from a mutable handle. */
529 template <typename S>
530 inline MOZ_IMPLICIT Handle(
531 MutableHandle<S>& root,
532 typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type
533 dummy = 0);
534
535 DECLARE_POINTER_CONSTREF_OPS(T);
536 DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr);
537
538 private:
Handle()539 Handle() {}
540 DELETE_ASSIGNMENT_OPS(Handle, T);
541
542 enum Disambiguator { DeliberatelyChoosingThisOverload = 42 };
543 enum CallerIdentity { ImUsingThisOnlyInFromFromMarkedLocation = 17 };
Handle(const T * p,Disambiguator,CallerIdentity)544 constexpr Handle(const T* p, Disambiguator, CallerIdentity) : ptr(p) {}
545
546 const T* ptr;
547 };
548
549 /**
550 * Similar to a handle, but the underlying storage can be changed. This is
551 * useful for outparams.
552 *
553 * If you want to add additional methods to MutableHandle for a specific
554 * specialization, define a MutableHandleBase<T> specialization containing
555 * them.
556 */
557 template <typename T>
558 class MOZ_STACK_CLASS MutableHandle
559 : public js::MutableHandleBase<T, MutableHandle<T>> {
560 public:
561 using ElementType = T;
562
563 inline MOZ_IMPLICIT MutableHandle(Rooted<T>* root);
564 inline MOZ_IMPLICIT MutableHandle(PersistentRooted<T>* root);
565
566 private:
567 // Disallow nullptr for overloading purposes.
568 MutableHandle(decltype(nullptr)) = delete;
569
570 public:
set(const T & v)571 void set(const T& v) {
572 *ptr = v;
573 MOZ_ASSERT(GCPolicy<T>::isValid(*ptr));
574 }
set(T && v)575 void set(T&& v) {
576 *ptr = mozilla::Move(v);
577 MOZ_ASSERT(GCPolicy<T>::isValid(*ptr));
578 }
579
580 /*
581 * This may be called only if the location of the T is guaranteed
582 * to be marked (for some reason other than being a Rooted),
583 * e.g., if it is guaranteed to be reachable from an implicit root.
584 *
585 * Create a MutableHandle from a raw location of a T.
586 */
fromMarkedLocation(T * p)587 static MutableHandle fromMarkedLocation(T* p) {
588 MutableHandle h;
589 h.ptr = p;
590 return h;
591 }
592
593 DECLARE_POINTER_CONSTREF_OPS(T);
594 DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr);
595 DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(*ptr);
596
597 private:
MutableHandle()598 MutableHandle() {}
599 DELETE_ASSIGNMENT_OPS(MutableHandle, T);
600
601 T* ptr;
602 };
603
604 } /* namespace JS */
605
606 namespace js {
607
608 template <typename T>
609 struct BarrierMethods<T*> {
610 static T* initial() { return nullptr; }
611 static gc::Cell* asGCThingOrNull(T* v) {
612 if (!v) return nullptr;
613 MOZ_ASSERT(uintptr_t(v) > 32);
614 return reinterpret_cast<gc::Cell*>(v);
615 }
616 static void postBarrier(T** vp, T* prev, T* next) {
617 if (next)
618 JS::AssertGCThingIsNotNurseryAllocable(
619 reinterpret_cast<js::gc::Cell*>(next));
620 }
621 static void exposeToJS(T* t) {
622 if (t) js::gc::ExposeGCThingToActiveJS(JS::GCCellPtr(t));
623 }
624 };
625
626 template <>
627 struct BarrierMethods<JSObject*> {
628 static JSObject* initial() { return nullptr; }
629 static gc::Cell* asGCThingOrNull(JSObject* v) {
630 if (!v) return nullptr;
631 MOZ_ASSERT(uintptr_t(v) > 32);
632 return reinterpret_cast<gc::Cell*>(v);
633 }
634 static void postBarrier(JSObject** vp, JSObject* prev, JSObject* next) {
635 JS::HeapObjectPostBarrier(vp, prev, next);
636 }
637 static void exposeToJS(JSObject* obj) {
638 if (obj) JS::ExposeObjectToActiveJS(obj);
639 }
640 };
641
642 template <>
643 struct BarrierMethods<JSFunction*> {
644 static JSFunction* initial() { return nullptr; }
645 static gc::Cell* asGCThingOrNull(JSFunction* v) {
646 if (!v) return nullptr;
647 MOZ_ASSERT(uintptr_t(v) > 32);
648 return reinterpret_cast<gc::Cell*>(v);
649 }
650 static void postBarrier(JSFunction** vp, JSFunction* prev, JSFunction* next) {
651 JS::HeapObjectPostBarrier(reinterpret_cast<JSObject**>(vp),
652 reinterpret_cast<JSObject*>(prev),
653 reinterpret_cast<JSObject*>(next));
654 }
655 static void exposeToJS(JSFunction* fun) {
656 if (fun) JS::ExposeObjectToActiveJS(reinterpret_cast<JSObject*>(fun));
657 }
658 };
659
660 template <>
661 struct BarrierMethods<JSString*> {
662 static JSString* initial() { return nullptr; }
663 static gc::Cell* asGCThingOrNull(JSString* v) {
664 if (!v) return nullptr;
665 MOZ_ASSERT(uintptr_t(v) > 32);
666 return reinterpret_cast<gc::Cell*>(v);
667 }
668 static void postBarrier(JSString** vp, JSString* prev, JSString* next) {
669 JS::HeapStringPostBarrier(vp, prev, next);
670 }
671 static void exposeToJS(JSString* v) {
672 if (v) js::gc::ExposeGCThingToActiveJS(JS::GCCellPtr(v));
673 }
674 };
675
676 // Provide hash codes for Cell kinds that may be relocated and, thus, not have
677 // a stable address to use as the base for a hash code. Instead of the address,
678 // this hasher uses Cell::getUniqueId to provide exact matches and as a base
679 // for generating hash codes.
680 //
681 // Note: this hasher, like PointerHasher can "hash" a nullptr. While a nullptr
682 // would not likely be a useful key, there are some cases where being able to
683 // hash a nullptr is useful, either on purpose or because of bugs:
684 // (1) existence checks where the key may happen to be null and (2) some
685 // aggregate Lookup kinds embed a JSObject* that is frequently null and do not
686 // null test before dispatching to the hasher.
687 template <typename T>
688 struct JS_PUBLIC_API MovableCellHasher {
689 using Key = T;
690 using Lookup = T;
691
692 static bool hasHash(const Lookup& l);
693 static bool ensureHash(const Lookup& l);
694 static HashNumber hash(const Lookup& l);
695 static bool match(const Key& k, const Lookup& l);
696 static void rekey(Key& k, const Key& newKey) { k = newKey; }
697 };
698
699 template <typename T>
700 struct JS_PUBLIC_API MovableCellHasher<JS::Heap<T>> {
701 using Key = JS::Heap<T>;
702 using Lookup = T;
703
704 static bool hasHash(const Lookup& l) {
705 return MovableCellHasher<T>::hasHash(l);
706 }
707 static bool ensureHash(const Lookup& l) {
708 return MovableCellHasher<T>::ensureHash(l);
709 }
710 static HashNumber hash(const Lookup& l) {
711 return MovableCellHasher<T>::hash(l);
712 }
713 static bool match(const Key& k, const Lookup& l) {
714 return MovableCellHasher<T>::match(k.unbarrieredGet(), l);
715 }
716 static void rekey(Key& k, const Key& newKey) { k.unsafeSet(newKey); }
717 };
718
719 template <typename T>
720 struct FallibleHashMethods<MovableCellHasher<T>> {
721 template <typename Lookup>
722 static bool hasHash(Lookup&& l) {
723 return MovableCellHasher<T>::hasHash(mozilla::Forward<Lookup>(l));
724 }
725 template <typename Lookup>
726 static bool ensureHash(Lookup&& l) {
727 return MovableCellHasher<T>::ensureHash(mozilla::Forward<Lookup>(l));
728 }
729 };
730
731 } /* namespace js */
732
733 namespace js {
734
735 // The alignment must be set because the Rooted and PersistentRooted ptr fields
736 // may be accessed through reinterpret_cast<Rooted<ConcreteTraceable>*>, and
737 // the compiler may choose a different alignment for the ptr field when it
738 // knows the actual type stored in DispatchWrapper<T>.
739 //
740 // It would make more sense to align only those specific fields of type
741 // DispatchWrapper, rather than DispatchWrapper itself, but that causes MSVC to
742 // fail when Rooted is used in an IsConvertible test.
743 template <typename T>
744 class alignas(8) DispatchWrapper {
745 static_assert(JS::MapTypeToRootKind<T>::kind == JS::RootKind::Traceable,
746 "DispatchWrapper is intended only for usage with a Traceable");
747
748 using TraceFn = void (*)(JSTracer*, T*, const char*);
749 TraceFn tracer;
750 alignas(gc::CellAlignBytes) T storage;
751
752 public:
753 template <typename U>
754 MOZ_IMPLICIT DispatchWrapper(U&& initial)
755 : tracer(&JS::GCPolicy<T>::trace),
756 storage(mozilla::Forward<U>(initial)) {}
757
758 // Mimic a pointer type, so that we can drop into Rooted.
759 T* operator&() { return &storage; }
760 const T* operator&() const { return &storage; }
761 operator T&() { return storage; }
762 operator const T&() const { return storage; }
763
764 // Trace the contained storage (of unknown type) using the trace function
765 // we set aside when we did know the type.
766 static void TraceWrapped(JSTracer* trc, T* thingp, const char* name) {
767 auto wrapper = reinterpret_cast<DispatchWrapper*>(
768 uintptr_t(thingp) - offsetof(DispatchWrapper, storage));
769 wrapper->tracer(trc, &wrapper->storage, name);
770 }
771 };
772
773 } /* namespace js */
774
775 namespace JS {
776
777 class JS_PUBLIC_API AutoGCRooter;
778
779 // Our instantiations of Rooted<void*> and PersistentRooted<void*> require an
780 // instantiation of MapTypeToRootKind.
781 template <>
782 struct MapTypeToRootKind<void*> {
783 static const RootKind kind = RootKind::Traceable;
784 };
785
786 using RootedListHeads =
787 mozilla::EnumeratedArray<RootKind, RootKind::Limit, Rooted<void*>*>;
788
789 // Superclass of JSContext which can be used for rooting data in use by the
790 // current thread but that does not provide all the functions of a JSContext.
791 class RootingContext {
792 // Stack GC roots for Rooted GC heap pointers.
793 RootedListHeads stackRoots_;
794 template <typename T>
795 friend class JS::Rooted;
796
797 // Stack GC roots for AutoFooRooter classes.
798 JS::AutoGCRooter* autoGCRooters_;
799 friend class JS::AutoGCRooter;
800
801 // Gecko profiling metadata.
802 // This isn't really rooting related. It's only here because we want
803 // GetContextProfilingStack to be inlineable into non-JS code, and we
804 // didn't want to add another superclass of JSContext just for this.
805 js::GeckoProfilerThread geckoProfiler_;
806
807 public:
808 RootingContext();
809
810 void traceStackRoots(JSTracer* trc);
811 void checkNoGCRooters();
812
813 js::GeckoProfilerThread& geckoProfiler() { return geckoProfiler_; }
814
815 protected:
816 // The remaining members in this class should only be accessed through
817 // JSContext pointers. They are unrelated to rooting and are in place so
818 // that inlined API functions can directly access the data.
819
820 /* The current compartment. */
821 JSCompartment* compartment_;
822
823 /* The current zone. */
824 JS::Zone* zone_;
825
826 public:
827 /* Limit pointer for checking native stack consumption. */
828 uintptr_t nativeStackLimit[StackKindCount];
829
830 static const RootingContext* get(const JSContext* cx) {
831 return reinterpret_cast<const RootingContext*>(cx);
832 }
833
834 static RootingContext* get(JSContext* cx) {
835 return reinterpret_cast<RootingContext*>(cx);
836 }
837
838 friend JSCompartment* js::GetContextCompartment(const JSContext* cx);
839 friend JS::Zone* js::GetContextZone(const JSContext* cx);
840 };
841
842 class JS_PUBLIC_API AutoGCRooter {
843 public:
844 AutoGCRooter(JSContext* cx, ptrdiff_t tag)
845 : AutoGCRooter(JS::RootingContext::get(cx), tag) {}
846 AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag)
847 : down(cx->autoGCRooters_), tag_(tag), stackTop(&cx->autoGCRooters_) {
848 MOZ_ASSERT(this != *stackTop);
849 *stackTop = this;
850 }
851
852 ~AutoGCRooter() {
853 MOZ_ASSERT(this == *stackTop);
854 *stackTop = down;
855 }
856
857 /* Implemented in gc/RootMarking.cpp. */
858 inline void trace(JSTracer* trc);
859 static void traceAll(const js::CooperatingContext& target, JSTracer* trc);
860 static void traceAllWrappers(const js::CooperatingContext& target,
861 JSTracer* trc);
862
863 protected:
864 AutoGCRooter* const down;
865
866 /*
867 * Discriminates actual subclass of this being used. If non-negative, the
868 * subclass roots an array of values of the length stored in this field.
869 * If negative, meaning is indicated by the corresponding value in the enum
870 * below. Any other negative value indicates some deeper problem such as
871 * memory corruption.
872 */
873 ptrdiff_t tag_;
874
875 enum {
876 VALARRAY = -2, /* js::AutoValueArray */
877 PARSER = -3, /* js::frontend::Parser */
878 #if defined(JS_BUILD_BINAST)
879 BINPARSER = -4, /* js::frontend::BinSource */
880 #endif // defined(JS_BUILD_BINAST)
881 IONMASM = -19, /* js::jit::MacroAssembler */
882 WRAPVECTOR = -20, /* js::AutoWrapperVector */
883 WRAPPER = -21, /* js::AutoWrapperRooter */
884 CUSTOM = -26 /* js::CustomAutoRooter */
885 };
886
887 private:
888 AutoGCRooter** const stackTop;
889
890 /* No copy or assignment semantics. */
891 AutoGCRooter(AutoGCRooter& ida) = delete;
892 void operator=(AutoGCRooter& ida) = delete;
893 };
894
895 namespace detail {
896
897 /*
898 * For pointer types, the TraceKind for tracing is based on the list it is
899 * in (selected via MapTypeToRootKind), so no additional storage is
900 * required here. Non-pointer types, however, share the same list, so the
901 * function to call for tracing is stored adjacent to the struct. Since C++
902 * cannot templatize on storage class, this is implemented via the wrapper
903 * class DispatchWrapper.
904 */
905 template <typename T>
906 using MaybeWrapped =
907 typename mozilla::Conditional<MapTypeToRootKind<T>::kind ==
908 JS::RootKind::Traceable,
909 js::DispatchWrapper<T>, T>::Type;
910
911 } /* namespace detail */
912
913 /**
914 * Local variable of type T whose value is always rooted. This is typically
915 * used for local variables, or for non-rooted values being passed to a
916 * function that requires a handle, e.g. Foo(Root<T>(cx, x)).
917 *
918 * If you want to add additional methods to Rooted for a specific
919 * specialization, define a RootedBase<T> specialization containing them.
920 */
921 template <typename T>
922 class MOZ_RAII Rooted : public js::RootedBase<T, Rooted<T>> {
923 inline void registerWithRootLists(RootedListHeads& roots) {
924 this->stack = &roots[JS::MapTypeToRootKind<T>::kind];
925 this->prev = *stack;
926 *stack = reinterpret_cast<Rooted<void*>*>(this);
927 }
928
929 inline RootedListHeads& rootLists(RootingContext* cx) {
930 return cx->stackRoots_;
931 }
932 inline RootedListHeads& rootLists(JSContext* cx) {
933 return rootLists(RootingContext::get(cx));
934 }
935
936 public:
937 using ElementType = T;
938
939 template <typename RootingContext>
940 explicit Rooted(const RootingContext& cx) : ptr(GCPolicy<T>::initial()) {
941 registerWithRootLists(rootLists(cx));
942 }
943
944 template <typename RootingContext, typename S>
945 Rooted(const RootingContext& cx, S&& initial)
946 : ptr(mozilla::Forward<S>(initial)) {
947 MOZ_ASSERT(GCPolicy<T>::isValid(ptr));
948 registerWithRootLists(rootLists(cx));
949 }
950
951 ~Rooted() {
952 MOZ_ASSERT(*stack == reinterpret_cast<Rooted<void*>*>(this));
953 *stack = prev;
954 }
955
956 Rooted<T>* previous() { return reinterpret_cast<Rooted<T>*>(prev); }
957
958 /*
959 * This method is public for Rooted so that Codegen.py can use a Rooted
960 * interchangeably with a MutableHandleValue.
961 */
962 void set(const T& value) {
963 ptr = value;
964 MOZ_ASSERT(GCPolicy<T>::isValid(ptr));
965 }
966 void set(T&& value) {
967 ptr = mozilla::Move(value);
968 MOZ_ASSERT(GCPolicy<T>::isValid(ptr));
969 }
970
971 DECLARE_POINTER_CONSTREF_OPS(T);
972 DECLARE_POINTER_ASSIGN_OPS(Rooted, T);
973 DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr);
974 DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(ptr);
975
976 private:
977 /*
978 * These need to be templated on void* to avoid aliasing issues between, for
979 * example, Rooted<JSObject> and Rooted<JSFunction>, which use the same
980 * stack head pointer for different classes.
981 */
982 Rooted<void*>** stack;
983 Rooted<void*>* prev;
984
985 detail::MaybeWrapped<T> ptr;
986
987 Rooted(const Rooted&) = delete;
988 } JS_HAZ_ROOTED;
989
990 } /* namespace JS */
991
992 namespace js {
993
994 /*
995 * Inlinable accessors for JSContext.
996 *
997 * - These must not be available on the more restricted superclasses of
998 * JSContext, so we can't simply define them on RootingContext.
999 *
1000 * - They're perfectly ordinary JSContext functionality, so ought to be
1001 * usable without resorting to jsfriendapi.h, and when JSContext is an
1002 * incomplete type.
1003 */
1004 inline JSCompartment* GetContextCompartment(const JSContext* cx) {
1005 return JS::RootingContext::get(cx)->compartment_;
1006 }
1007
1008 inline JS::Zone* GetContextZone(const JSContext* cx) {
1009 return JS::RootingContext::get(cx)->zone_;
1010 }
1011
1012 inline PseudoStack* GetContextProfilingStack(JSContext* cx) {
1013 return JS::RootingContext::get(cx)->geckoProfiler().getPseudoStack();
1014 }
1015
1016 /**
1017 * Augment the generic Rooted<T> interface when T = JSObject* with
1018 * class-querying and downcasting operations.
1019 *
1020 * Given a Rooted<JSObject*> obj, one can view
1021 * Handle<StringObject*> h = obj.as<StringObject*>();
1022 * as an optimization of
1023 * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
1024 * Handle<StringObject*> h = rooted;
1025 */
1026 template <typename Container>
1027 class RootedBase<JSObject*, Container>
1028 : public MutableWrappedPtrOperations<JSObject*, Container> {
1029 public:
1030 template <class U>
1031 JS::Handle<U*> as() const;
1032 };
1033
1034 /**
1035 * Augment the generic Handle<T> interface when T = JSObject* with
1036 * downcasting operations.
1037 *
1038 * Given a Handle<JSObject*> obj, one can view
1039 * Handle<StringObject*> h = obj.as<StringObject*>();
1040 * as an optimization of
1041 * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
1042 * Handle<StringObject*> h = rooted;
1043 */
1044 template <typename Container>
1045 class HandleBase<JSObject*, Container>
1046 : public WrappedPtrOperations<JSObject*, Container> {
1047 public:
1048 template <class U>
1049 JS::Handle<U*> as() const;
1050 };
1051
1052 /**
1053 * Types for a variable that either should or shouldn't be rooted, depending on
1054 * the template parameter allowGC. Used for implementing functions that can
1055 * operate on either rooted or unrooted data.
1056 *
1057 * The toHandle() and toMutableHandle() functions are for calling functions
1058 * which require handle types and are only called in the CanGC case. These
1059 * allow the calling code to type check.
1060 */
1061 enum AllowGC { NoGC = 0, CanGC = 1 };
1062 template <typename T, AllowGC allowGC>
1063 class MaybeRooted {};
1064
1065 template <typename T>
1066 class MaybeRooted<T, CanGC> {
1067 public:
1068 typedef JS::Handle<T> HandleType;
1069 typedef JS::Rooted<T> RootType;
1070 typedef JS::MutableHandle<T> MutableHandleType;
1071
1072 static inline JS::Handle<T> toHandle(HandleType v) { return v; }
1073
1074 static inline JS::MutableHandle<T> toMutableHandle(MutableHandleType v) {
1075 return v;
1076 }
1077
1078 template <typename T2>
1079 static inline JS::Handle<T2*> downcastHandle(HandleType v) {
1080 return v.template as<T2>();
1081 }
1082 };
1083
1084 } /* namespace js */
1085
1086 namespace JS {
1087
1088 template <typename T>
1089 template <typename S>
1090 inline Handle<T>::Handle(
1091 const Rooted<S>& root,
1092 typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type
1093 dummy) {
1094 ptr = reinterpret_cast<const T*>(root.address());
1095 }
1096
1097 template <typename T>
1098 template <typename S>
1099 inline Handle<T>::Handle(
1100 const PersistentRooted<S>& root,
1101 typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type
1102 dummy) {
1103 ptr = reinterpret_cast<const T*>(root.address());
1104 }
1105
1106 template <typename T>
1107 template <typename S>
1108 inline Handle<T>::Handle(
1109 MutableHandle<S>& root,
1110 typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type
1111 dummy) {
1112 ptr = reinterpret_cast<const T*>(root.address());
1113 }
1114
1115 template <typename T>
1116 inline MutableHandle<T>::MutableHandle(Rooted<T>* root) {
1117 static_assert(sizeof(MutableHandle<T>) == sizeof(T*),
1118 "MutableHandle must be binary compatible with T*.");
1119 ptr = root->address();
1120 }
1121
1122 template <typename T>
1123 inline MutableHandle<T>::MutableHandle(PersistentRooted<T>* root) {
1124 static_assert(sizeof(MutableHandle<T>) == sizeof(T*),
1125 "MutableHandle must be binary compatible with T*.");
1126 ptr = root->address();
1127 }
1128
1129 JS_PUBLIC_API void AddPersistentRoot(RootingContext* cx, RootKind kind,
1130 PersistentRooted<void*>* root);
1131
1132 JS_PUBLIC_API void AddPersistentRoot(JSRuntime* rt, RootKind kind,
1133 PersistentRooted<void*>* root);
1134
1135 /**
1136 * A copyable, assignable global GC root type with arbitrary lifetime, an
1137 * infallible constructor, and automatic unrooting on destruction.
1138 *
1139 * These roots can be used in heap-allocated data structures, so they are not
1140 * associated with any particular JSContext or stack. They are registered with
1141 * the JSRuntime itself, without locking, so they require a full JSContext to be
1142 * initialized, not one of its more restricted superclasses. Initialization may
1143 * take place on construction, or in two phases if the no-argument constructor
1144 * is called followed by init().
1145 *
1146 * Note that you must not use an PersistentRooted in an object owned by a JS
1147 * object:
1148 *
1149 * Whenever one object whose lifetime is decided by the GC refers to another
1150 * such object, that edge must be traced only if the owning JS object is traced.
1151 * This applies not only to JS objects (which obviously are managed by the GC)
1152 * but also to C++ objects owned by JS objects.
1153 *
1154 * If you put a PersistentRooted in such a C++ object, that is almost certainly
1155 * a leak. When a GC begins, the referent of the PersistentRooted is treated as
1156 * live, unconditionally (because a PersistentRooted is a *root*), even if the
1157 * JS object that owns it is unreachable. If there is any path from that
1158 * referent back to the JS object, then the C++ object containing the
1159 * PersistentRooted will not be destructed, and the whole blob of objects will
1160 * not be freed, even if there are no references to them from the outside.
1161 *
1162 * In the context of Firefox, this is a severe restriction: almost everything in
1163 * Firefox is owned by some JS object or another, so using PersistentRooted in
1164 * such objects would introduce leaks. For these kinds of edges, Heap<T> or
1165 * TenuredHeap<T> would be better types. It's up to the implementor of the type
1166 * containing Heap<T> or TenuredHeap<T> members to make sure their referents get
1167 * marked when the object itself is marked.
1168 */
1169 template <typename T>
1170 class PersistentRooted
1171 : public js::RootedBase<T, PersistentRooted<T>>,
1172 private mozilla::LinkedListElement<PersistentRooted<T>> {
1173 using ListBase = mozilla::LinkedListElement<PersistentRooted<T>>;
1174
1175 friend class mozilla::LinkedList<PersistentRooted>;
1176 friend class mozilla::LinkedListElement<PersistentRooted>;
1177
1178 void registerWithRootLists(RootingContext* cx) {
1179 MOZ_ASSERT(!initialized());
1180 JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
1181 AddPersistentRoot(cx, kind,
1182 reinterpret_cast<JS::PersistentRooted<void*>*>(this));
1183 }
1184
1185 void registerWithRootLists(JSRuntime* rt) {
1186 MOZ_ASSERT(!initialized());
1187 JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
1188 AddPersistentRoot(rt, kind,
1189 reinterpret_cast<JS::PersistentRooted<void*>*>(this));
1190 }
1191
1192 public:
1193 using ElementType = T;
1194
1195 PersistentRooted() : ptr(GCPolicy<T>::initial()) {}
1196
1197 explicit PersistentRooted(RootingContext* cx) : ptr(GCPolicy<T>::initial()) {
1198 registerWithRootLists(cx);
1199 }
1200
1201 explicit PersistentRooted(JSContext* cx) : ptr(GCPolicy<T>::initial()) {
1202 registerWithRootLists(RootingContext::get(cx));
1203 }
1204
1205 template <typename U>
1206 PersistentRooted(RootingContext* cx, U&& initial)
1207 : ptr(mozilla::Forward<U>(initial)) {
1208 registerWithRootLists(cx);
1209 }
1210
1211 template <typename U>
1212 PersistentRooted(JSContext* cx, U&& initial)
1213 : ptr(mozilla::Forward<U>(initial)) {
1214 registerWithRootLists(RootingContext::get(cx));
1215 }
1216
1217 explicit PersistentRooted(JSRuntime* rt) : ptr(GCPolicy<T>::initial()) {
1218 registerWithRootLists(rt);
1219 }
1220
1221 template <typename U>
1222 PersistentRooted(JSRuntime* rt, U&& initial)
1223 : ptr(mozilla::Forward<U>(initial)) {
1224 registerWithRootLists(rt);
1225 }
1226
1227 PersistentRooted(const PersistentRooted& rhs)
1228 : mozilla::LinkedListElement<PersistentRooted<T>>(), ptr(rhs.ptr) {
1229 /*
1230 * Copy construction takes advantage of the fact that the original
1231 * is already inserted, and simply adds itself to whatever list the
1232 * original was on - no JSRuntime pointer needed.
1233 *
1234 * This requires mutating rhs's links, but those should be 'mutable'
1235 * anyway. C++ doesn't let us declare mutable base classes.
1236 */
1237 const_cast<PersistentRooted&>(rhs).setNext(this);
1238 }
1239
1240 bool initialized() { return ListBase::isInList(); }
1241
1242 void init(JSContext* cx) { init(cx, GCPolicy<T>::initial()); }
1243
1244 template <typename U>
1245 void init(JSContext* cx, U&& initial) {
1246 ptr = mozilla::Forward<U>(initial);
1247 registerWithRootLists(RootingContext::get(cx));
1248 }
1249
1250 void reset() {
1251 if (initialized()) {
1252 set(GCPolicy<T>::initial());
1253 ListBase::remove();
1254 }
1255 }
1256
1257 DECLARE_POINTER_CONSTREF_OPS(T);
1258 DECLARE_POINTER_ASSIGN_OPS(PersistentRooted, T);
1259 DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr);
1260
1261 // These are the same as DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS, except
1262 // they check that |this| is initialized in case the caller later stores
1263 // something in |ptr|.
1264 T* address() {
1265 MOZ_ASSERT(initialized());
1266 return &ptr;
1267 }
1268 T& get() {
1269 MOZ_ASSERT(initialized());
1270 return ptr;
1271 }
1272
1273 private:
1274 template <typename U>
1275 void set(U&& value) {
1276 MOZ_ASSERT(initialized());
1277 ptr = mozilla::Forward<U>(value);
1278 }
1279
1280 detail::MaybeWrapped<T> ptr;
1281 } JS_HAZ_ROOTED;
1282
1283 class JS_PUBLIC_API ObjectPtr {
1284 Heap<JSObject*> value;
1285
1286 public:
1287 using ElementType = JSObject*;
1288
1289 ObjectPtr() : value(nullptr) {}
1290
1291 explicit ObjectPtr(JSObject* obj) : value(obj) {}
1292
1293 ObjectPtr(const ObjectPtr& other) : value(other.value) {}
1294
1295 ObjectPtr(ObjectPtr&& other) : value(other.value) { other.value = nullptr; }
1296
1297 /* Always call finalize before the destructor. */
1298 ~ObjectPtr() { MOZ_ASSERT(!value); }
1299
1300 void finalize(JSRuntime* rt);
1301 void finalize(JSContext* cx);
1302
1303 void init(JSObject* obj) { value = obj; }
1304
1305 JSObject* get() const { return value; }
1306 JSObject* unbarrieredGet() const { return value.unbarrieredGet(); }
1307
1308 void writeBarrierPre(JSContext* cx) { IncrementalPreWriteBarrier(value); }
1309
1310 void updateWeakPointerAfterGC();
1311
1312 ObjectPtr& operator=(JSObject* obj) {
1313 IncrementalPreWriteBarrier(value);
1314 value = obj;
1315 return *this;
1316 }
1317
1318 void trace(JSTracer* trc, const char* name);
1319
1320 JSObject& operator*() const { return *value; }
1321 JSObject* operator->() const { return value; }
1322 operator JSObject*() const { return value; }
1323
1324 explicit operator bool() const { return value.unbarrieredGet(); }
1325 explicit operator bool() { return value.unbarrieredGet(); }
1326 };
1327
1328 } /* namespace JS */
1329
1330 namespace js {
1331
1332 template <typename T, typename D, typename Container>
1333 class WrappedPtrOperations<UniquePtr<T, D>, Container> {
1334 const UniquePtr<T, D>& uniquePtr() const {
1335 return static_cast<const Container*>(this)->get();
1336 }
1337
1338 public:
1339 explicit operator bool() const { return !!uniquePtr(); }
1340 T* get() const { return uniquePtr().get(); }
1341 T* operator->() const { return get(); }
1342 T& operator*() const { return *uniquePtr(); }
1343 };
1344
1345 template <typename T, typename D, typename Container>
1346 class MutableWrappedPtrOperations<UniquePtr<T, D>, Container>
1347 : public WrappedPtrOperations<UniquePtr<T, D>, Container> {
1348 UniquePtr<T, D>& uniquePtr() { return static_cast<Container*>(this)->get(); }
1349
1350 public:
1351 MOZ_MUST_USE typename UniquePtr<T, D>::Pointer release() {
1352 return uniquePtr().release();
1353 }
1354 void reset(T* ptr = T()) { uniquePtr().reset(ptr); }
1355 };
1356
1357 namespace gc {
1358
1359 template <typename T, typename TraceCallbacks>
1360 void CallTraceCallbackOnNonHeap(T* v, const TraceCallbacks& aCallbacks,
1361 const char* aName, void* aClosure) {
1362 static_assert(sizeof(T) == sizeof(JS::Heap<T>),
1363 "T and Heap<T> must be compatible.");
1364 MOZ_ASSERT(v);
1365 mozilla::DebugOnly<Cell*> cell = BarrierMethods<T>::asGCThingOrNull(*v);
1366 MOZ_ASSERT(cell);
1367 MOZ_ASSERT(!IsInsideNursery(cell));
1368 JS::Heap<T>* asHeapT = reinterpret_cast<JS::Heap<T>*>(v);
1369 aCallbacks.Trace(asHeapT, aName, aClosure);
1370 }
1371
1372 } /* namespace gc */
1373 } /* namespace js */
1374
1375 // mozilla::Swap uses a stack temporary, which prevents classes like Heap<T>
1376 // from being declared MOZ_HEAP_CLASS.
1377 namespace mozilla {
1378
1379 template <typename T>
1380 inline void Swap(JS::Heap<T>& aX, JS::Heap<T>& aY) {
1381 T tmp = aX;
1382 aX = aY;
1383 aY = tmp;
1384 }
1385
1386 template <typename T>
1387 inline void Swap(JS::TenuredHeap<T>& aX, JS::TenuredHeap<T>& aY) {
1388 T tmp = aX;
1389 aX = aY;
1390 aY = tmp;
1391 }
1392
1393 } /* namespace mozilla */
1394
1395 namespace js {
1396 namespace detail {
1397
1398 // DefineComparisonOps is a trait which selects which wrapper classes to define
1399 // operator== and operator!= for. It supplies a getter function to extract the
1400 // value to compare. This is used to avoid triggering the automatic read
1401 // barriers where appropriate.
1402 //
1403 // If DefineComparisonOps is not specialized for a particular wrapper you may
1404 // get errors such as 'invalid operands to binary expression' or 'no match for
1405 // operator==' when trying to compare against instances of the wrapper.
1406
1407 template <typename T>
1408 struct DefineComparisonOps : mozilla::FalseType {};
1409
1410 template <typename T>
1411 struct DefineComparisonOps<JS::Heap<T>> : mozilla::TrueType {
1412 static const T& get(const JS::Heap<T>& v) { return v.unbarrieredGet(); }
1413 };
1414
1415 template <typename T>
1416 struct DefineComparisonOps<JS::TenuredHeap<T>> : mozilla::TrueType {
1417 static const T get(const JS::TenuredHeap<T>& v) {
1418 return v.unbarrieredGetPtr();
1419 }
1420 };
1421
1422 template <>
1423 struct DefineComparisonOps<JS::ObjectPtr> : mozilla::TrueType {
1424 static const JSObject* get(const JS::ObjectPtr& v) {
1425 return v.unbarrieredGet();
1426 }
1427 };
1428
1429 template <typename T>
1430 struct DefineComparisonOps<JS::Rooted<T>> : mozilla::TrueType {
1431 static const T& get(const JS::Rooted<T>& v) { return v.get(); }
1432 };
1433
1434 template <typename T>
1435 struct DefineComparisonOps<JS::Handle<T>> : mozilla::TrueType {
1436 static const T& get(const JS::Handle<T>& v) { return v.get(); }
1437 };
1438
1439 template <typename T>
1440 struct DefineComparisonOps<JS::MutableHandle<T>> : mozilla::TrueType {
1441 static const T& get(const JS::MutableHandle<T>& v) { return v.get(); }
1442 };
1443
1444 template <typename T>
1445 struct DefineComparisonOps<JS::PersistentRooted<T>> : mozilla::TrueType {
1446 static const T& get(const JS::PersistentRooted<T>& v) { return v.get(); }
1447 };
1448
1449 template <typename T>
1450 struct DefineComparisonOps<js::FakeRooted<T>> : mozilla::TrueType {
1451 static const T& get(const js::FakeRooted<T>& v) { return v.get(); }
1452 };
1453
1454 template <typename T>
1455 struct DefineComparisonOps<js::FakeMutableHandle<T>> : mozilla::TrueType {
1456 static const T& get(const js::FakeMutableHandle<T>& v) { return v.get(); }
1457 };
1458
1459 } /* namespace detail */
1460 } /* namespace js */
1461
1462 // Overload operator== and operator!= for all types with the DefineComparisonOps
1463 // trait using the supplied getter.
1464 //
1465 // There are four cases:
1466
1467 // Case 1: comparison between two wrapper objects.
1468
1469 template <typename T, typename U>
1470 typename mozilla::EnableIf<js::detail::DefineComparisonOps<T>::value &&
1471 js::detail::DefineComparisonOps<U>::value,
1472 bool>::Type
1473 operator==(const T& a, const U& b) {
1474 return js::detail::DefineComparisonOps<T>::get(a) ==
1475 js::detail::DefineComparisonOps<U>::get(b);
1476 }
1477
1478 template <typename T, typename U>
1479 typename mozilla::EnableIf<js::detail::DefineComparisonOps<T>::value &&
1480 js::detail::DefineComparisonOps<U>::value,
1481 bool>::Type
1482 operator!=(const T& a, const U& b) {
1483 return !(a == b);
1484 }
1485
1486 // Case 2: comparison between a wrapper object and its unwrapped element type.
1487
1488 template <typename T>
1489 typename mozilla::EnableIf<js::detail::DefineComparisonOps<T>::value,
1490 bool>::Type
1491 operator==(const T& a, const typename T::ElementType& b) {
1492 return js::detail::DefineComparisonOps<T>::get(a) == b;
1493 }
1494
1495 template <typename T>
1496 typename mozilla::EnableIf<js::detail::DefineComparisonOps<T>::value,
1497 bool>::Type
1498 operator!=(const T& a, const typename T::ElementType& b) {
1499 return !(a == b);
1500 }
1501
1502 template <typename T>
1503 typename mozilla::EnableIf<js::detail::DefineComparisonOps<T>::value,
1504 bool>::Type
1505 operator==(const typename T::ElementType& a, const T& b) {
1506 return a == js::detail::DefineComparisonOps<T>::get(b);
1507 }
1508
1509 template <typename T>
1510 typename mozilla::EnableIf<js::detail::DefineComparisonOps<T>::value,
1511 bool>::Type
1512 operator!=(const typename T::ElementType& a, const T& b) {
1513 return !(a == b);
1514 }
1515
1516 // Case 3: For pointer wrappers, comparison between the wrapper and a const
1517 // element pointer.
1518
1519 template <typename T>
1520 typename mozilla::EnableIf<
1521 js::detail::DefineComparisonOps<T>::value &&
1522 mozilla::IsPointer<typename T::ElementType>::value,
1523 bool>::Type
1524 operator==(
1525 const typename mozilla::RemovePointer<typename T::ElementType>::Type* a,
1526 const T& b) {
1527 return a == js::detail::DefineComparisonOps<T>::get(b);
1528 }
1529
1530 template <typename T>
1531 typename mozilla::EnableIf<
1532 js::detail::DefineComparisonOps<T>::value &&
1533 mozilla::IsPointer<typename T::ElementType>::value,
1534 bool>::Type
1535 operator!=(
1536 const typename mozilla::RemovePointer<typename T::ElementType>::Type* a,
1537 const T& b) {
1538 return !(a == b);
1539 }
1540
1541 template <typename T>
1542 typename mozilla::EnableIf<
1543 js::detail::DefineComparisonOps<T>::value &&
1544 mozilla::IsPointer<typename T::ElementType>::value,
1545 bool>::Type
1546 operator==(
1547 const T& a,
1548 const typename mozilla::RemovePointer<typename T::ElementType>::Type* b) {
1549 return js::detail::DefineComparisonOps<T>::get(a) == b;
1550 }
1551
1552 template <typename T>
1553 typename mozilla::EnableIf<
1554 js::detail::DefineComparisonOps<T>::value &&
1555 mozilla::IsPointer<typename T::ElementType>::value,
1556 bool>::Type
1557 operator!=(
1558 const T& a,
1559 const typename mozilla::RemovePointer<typename T::ElementType>::Type* b) {
1560 return !(a == b);
1561 }
1562
1563 // Case 4: For pointer wrappers, comparison between the wrapper and nullptr.
1564
1565 template <typename T>
1566 typename mozilla::EnableIf<
1567 js::detail::DefineComparisonOps<T>::value &&
1568 mozilla::IsPointer<typename T::ElementType>::value,
1569 bool>::Type
1570 operator==(std::nullptr_t a, const T& b) {
1571 return a == js::detail::DefineComparisonOps<T>::get(b);
1572 }
1573
1574 template <typename T>
1575 typename mozilla::EnableIf<
1576 js::detail::DefineComparisonOps<T>::value &&
1577 mozilla::IsPointer<typename T::ElementType>::value,
1578 bool>::Type
1579 operator!=(std::nullptr_t a, const T& b) {
1580 return !(a == b);
1581 }
1582
1583 template <typename T>
1584 typename mozilla::EnableIf<
1585 js::detail::DefineComparisonOps<T>::value &&
1586 mozilla::IsPointer<typename T::ElementType>::value,
1587 bool>::Type
1588 operator==(const T& a, std::nullptr_t b) {
1589 return js::detail::DefineComparisonOps<T>::get(a) == b;
1590 }
1591
1592 template <typename T>
1593 typename mozilla::EnableIf<
1594 js::detail::DefineComparisonOps<T>::value &&
1595 mozilla::IsPointer<typename T::ElementType>::value,
1596 bool>::Type
1597 operator!=(const T& a, std::nullptr_t b) {
1598 return !(a == b);
1599 }
1600
1601 #endif /* js_RootingAPI_h */
1602