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 "jspubtd.h"
18 
19 #include "js/GCAPI.h"
20 #include "js/HeapAPI.h"
21 #include "js/TypeDecls.h"
22 #include "js/Utility.h"
23 
24 /*
25  * Moving GC Stack Rooting
26  *
27  * A moving GC may change the physical location of GC allocated things, even
28  * when they are rooted, updating all pointers to the thing to refer to its new
29  * location. The GC must therefore know about all live pointers to a thing,
30  * not just one of them, in order to behave correctly.
31  *
32  * The |Rooted| and |Handle| classes below are used to root stack locations
33  * whose value may be held live across a call that can trigger GC. For a
34  * code fragment such as:
35  *
36  * JSObject* obj = NewObject(cx);
37  * DoSomething(cx);
38  * ... = obj->lastProperty();
39  *
40  * If |DoSomething()| can trigger a GC, the stack location of |obj| must be
41  * rooted to ensure that the GC does not move the JSObject referred to by
42  * |obj| without updating |obj|'s location itself. This rooting must happen
43  * regardless of whether there are other roots which ensure that the object
44  * itself will not be collected.
45  *
46  * If |DoSomething()| cannot trigger a GC, and the same holds for all other
47  * calls made between |obj|'s definitions and its last uses, then no rooting
48  * is required.
49  *
50  * SpiderMonkey can trigger a GC at almost any time and in ways that are not
51  * always clear. For example, the following innocuous-looking actions can
52  * cause a GC: allocation of any new GC thing; JSObject::hasProperty;
53  * JS_ReportError and friends; and ToNumber, among many others. The following
54  * dangerous-looking actions cannot trigger a GC: js_malloc, cx->malloc_,
55  * rt->malloc_, and friends and JS_ReportOutOfMemory.
56  *
57  * The following family of three classes will exactly root a stack location.
58  * Incorrect usage of these classes will result in a compile error in almost
59  * all cases. Therefore, it is very hard to be incorrectly rooted if you use
60  * these classes exclusively. These classes are all templated on the type T of
61  * the value being rooted.
62  *
63  * - Rooted<T> declares a variable of type T, whose value is always rooted.
64  *   Rooted<T> may be automatically coerced to a Handle<T>, below. Rooted<T>
65  *   should be used whenever a local variable's value may be held live across a
66  *   call which can trigger a GC.
67  *
68  * - Handle<T> is a const reference to a Rooted<T>. Functions which take GC
69  *   things or values as arguments and need to root those arguments should
70  *   generally use handles for those arguments and avoid any explicit rooting.
71  *   This has two benefits. First, when several such functions call each other
72  *   then redundant rooting of multiple copies of the GC thing can be avoided.
73  *   Second, if the caller does not pass a rooted value a compile error will be
74  *   generated, which is quicker and easier to fix than when relying on a
75  *   separate rooting analysis.
76  *
77  * - MutableHandle<T> is a non-const reference to Rooted<T>. It is used in the
78  *   same way as Handle<T> and includes a |set(const T& v)| method to allow
79  *   updating the value of the referenced Rooted<T>. A MutableHandle<T> can be
80  *   created with an implicit cast from a Rooted<T>*.
81  *
82  * In some cases the small performance overhead of exact rooting (measured to
83  * be a few nanoseconds on desktop) is too much. In these cases, try the
84  * following:
85  *
86  * - Move all Rooted<T> above inner loops: this allows you to re-use the root
87  *   on each iteration of the loop.
88  *
89  * - Pass Handle<T> through your hot call stack to avoid re-rooting costs at
90  *   every invocation.
91  *
92  * The following diagram explains the list of supported, implicit type
93  * conversions between classes of this family:
94  *
95  *  Rooted<T> ----> Handle<T>
96  *     |               ^
97  *     |               |
98  *     |               |
99  *     +---> MutableHandle<T>
100  *     (via &)
101  *
102  * All of these types have an implicit conversion to raw pointers.
103  */
104 
105 namespace js {
106 
107 template <typename T>
108 struct GCMethods {
initialGCMethods109     static T initial() { return T(); }
110 };
111 
112 template <typename T>
113 class RootedBase {};
114 
115 template <typename T>
116 class HandleBase {};
117 
118 template <typename T>
119 class MutableHandleBase {};
120 
121 template <typename T>
122 class HeapBase {};
123 
124 template <typename T>
125 class PersistentRootedBase {};
126 
127 static void* const ConstNullValue = nullptr;
128 
129 namespace gc {
130 struct Cell;
131 template<typename T>
132 struct PersistentRootedMarker;
133 } /* namespace gc */
134 
135 #define DECLARE_POINTER_COMPARISON_OPS(T)                                                \
136     bool operator==(const T& other) const { return get() == other; }                              \
137     bool operator!=(const T& other) const { return get() != other; }
138 
139 // Important: Return a reference so passing a Rooted<T>, etc. to
140 // something that takes a |const T&| is not a GC hazard.
141 #define DECLARE_POINTER_CONSTREF_OPS(T)                                                  \
142     operator const T&() const { return get(); }                                                  \
143     const T& operator->() const { return get(); }
144 
145 // Assignment operators on a base class are hidden by the implicitly defined
146 // operator= on the derived class. Thus, define the operator= directly on the
147 // class as we would need to manually pass it through anyway.
148 #define DECLARE_POINTER_ASSIGN_OPS(Wrapper, T)                                                    \
149     Wrapper<T>& operator=(const T& p) {                                                           \
150         set(p);                                                                                   \
151         return *this;                                                                             \
152     }                                                                                             \
153     Wrapper<T>& operator=(const Wrapper<T>& other) {                                              \
154         set(other.get());                                                                         \
155         return *this;                                                                             \
156     }                                                                                             \
157 
158 #define DELETE_ASSIGNMENT_OPS(Wrapper, T)                                                 \
159     template <typename S> Wrapper<T>& operator=(S) = delete;                                      \
160     Wrapper<T>& operator=(const Wrapper<T>&) = delete;
161 
162 #define DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr)                                                  \
163     const T* address() const { return &(ptr); }                                                   \
164     const T& get() const { return (ptr); }                                                        \
165 
166 #define DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(ptr)                                          \
167     T* address() { return &(ptr); }                                                               \
168     T& get() { return (ptr); }                                                                    \
169 
170 } /* namespace js */
171 
172 namespace JS {
173 
174 template <typename T> class Rooted;
175 template <typename T> class PersistentRooted;
176 
177 /* This is exposing internal state of the GC for inlining purposes. */
178 JS_FRIEND_API(bool) isGCEnabled();
179 
180 JS_FRIEND_API(void) HeapObjectPostBarrier(JSObject** objp, JSObject* prev, JSObject* next);
181 
182 #ifdef JS_DEBUG
183 /**
184  * For generational GC, assert that an object is in the tenured generation as
185  * opposed to being in the nursery.
186  */
187 extern JS_FRIEND_API(void)
188 AssertGCThingMustBeTenured(JSObject* obj);
189 extern JS_FRIEND_API(void)
190 AssertGCThingIsNotAnObjectSubclass(js::gc::Cell* cell);
191 #else
192 inline void
AssertGCThingMustBeTenured(JSObject * obj)193 AssertGCThingMustBeTenured(JSObject* obj) {}
194 inline void
AssertGCThingIsNotAnObjectSubclass(js::gc::Cell * cell)195 AssertGCThingIsNotAnObjectSubclass(js::gc::Cell* cell) {}
196 #endif
197 
198 /**
199  * The Heap<T> class is a heap-stored reference to a JS GC thing. All members of
200  * heap classes that refer to GC things should use Heap<T> (or possibly
201  * TenuredHeap<T>, described below).
202  *
203  * Heap<T> is an abstraction that hides some of the complexity required to
204  * maintain GC invariants for the contained reference. It uses operator
205  * overloading to provide a normal pointer interface, but notifies the GC every
206  * time the value it contains is updated. This is necessary for generational GC,
207  * which keeps track of all pointers into the nursery.
208  *
209  * Heap<T> instances must be traced when their containing object is traced to
210  * keep the pointed-to GC thing alive.
211  *
212  * Heap<T> objects should only be used on the heap. GC references stored on the
213  * C/C++ stack must use Rooted/Handle/MutableHandle instead.
214  *
215  * Type T must be one of: JS::Value, jsid, JSObject*, JSString*, JSScript*
216  */
217 template <typename T>
218 class Heap : public js::HeapBase<T>
219 {
220   public:
Heap()221     Heap() {
222         static_assert(sizeof(T) == sizeof(Heap<T>),
223                       "Heap<T> must be binary compatible with T.");
224         init(js::GCMethods<T>::initial());
225     }
Heap(T p)226     explicit Heap(T p) { init(p); }
227 
228     /*
229      * For Heap, move semantics are equivalent to copy semantics. In C++, a
230      * copy constructor taking const-ref is the way to get a single function
231      * that will be used for both lvalue and rvalue copies, so we can simply
232      * omit the rvalue variant.
233      */
Heap(const Heap<T> & p)234     explicit Heap(const Heap<T>& p) { init(p.ptr); }
235 
~Heap()236     ~Heap() {
237         post(ptr, js::GCMethods<T>::initial());
238     }
239 
240     DECLARE_POINTER_CONSTREF_OPS(T);
241     DECLARE_POINTER_ASSIGN_OPS(Heap, T);
242     DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr);
243 
unsafeGet()244     T* unsafeGet() { return &ptr; }
245 
246     /*
247      * Set the pointer to a value which will cause a crash if it is
248      * dereferenced.
249      */
setToCrashOnTouch()250     void setToCrashOnTouch() {
251         ptr = reinterpret_cast<T>(crashOnTouchPointer);
252     }
253 
isSetToCrashOnTouch()254     bool isSetToCrashOnTouch() {
255         return ptr == crashOnTouchPointer;
256     }
257 
258   private:
init(T newPtr)259     void init(T newPtr) {
260         ptr = newPtr;
261         post(js::GCMethods<T>::initial(), ptr);
262     }
263 
set(T newPtr)264     void set(T newPtr) {
265         T tmp = ptr;
266         ptr = newPtr;
267         post(tmp, ptr);
268     }
269 
post(const T & prev,const T & next)270     void post(const T& prev, const T& next) {
271         js::GCMethods<T>::postBarrier(&ptr, prev, next);
272     }
273 
274     enum {
275         crashOnTouchPointer = 1
276     };
277 
278     T ptr;
279 };
280 
281 /**
282  * The TenuredHeap<T> class is similar to the Heap<T> class above in that it
283  * encapsulates the GC concerns of an on-heap reference to a JS object. However,
284  * it has two important differences:
285  *
286  *  1) Pointers which are statically known to only reference "tenured" objects
287  *     can avoid the extra overhead of SpiderMonkey's write barriers.
288  *
289  *  2) Objects in the "tenured" heap have stronger alignment restrictions than
290  *     those in the "nursery", so it is possible to store flags in the lower
291  *     bits of pointers known to be tenured. TenuredHeap wraps a normal tagged
292  *     pointer with a nice API for accessing the flag bits and adds various
293  *     assertions to ensure that it is not mis-used.
294  *
295  * GC things are said to be "tenured" when they are located in the long-lived
296  * heap: e.g. they have gained tenure as an object by surviving past at least
297  * one GC. For performance, SpiderMonkey allocates some things which are known
298  * to normally be long lived directly into the tenured generation; for example,
299  * global objects. Additionally, SpiderMonkey does not visit individual objects
300  * when deleting non-tenured objects, so object with finalizers are also always
301  * tenured; for instance, this includes most DOM objects.
302  *
303  * The considerations to keep in mind when using a TenuredHeap<T> vs a normal
304  * Heap<T> are:
305  *
306  *  - It is invalid for a TenuredHeap<T> to refer to a non-tenured thing.
307  *  - It is however valid for a Heap<T> to refer to a tenured thing.
308  *  - It is not possible to store flag bits in a Heap<T>.
309  */
310 template <typename T>
311 class TenuredHeap : public js::HeapBase<T>
312 {
313   public:
TenuredHeap()314     TenuredHeap() : bits(0) {
315         static_assert(sizeof(T) == sizeof(TenuredHeap<T>),
316                       "TenuredHeap<T> must be binary compatible with T.");
317     }
TenuredHeap(T p)318     explicit TenuredHeap(T p) : bits(0) { setPtr(p); }
TenuredHeap(const TenuredHeap<T> & p)319     explicit TenuredHeap(const TenuredHeap<T>& p) : bits(0) { setPtr(p.getPtr()); }
320 
321     bool operator==(const TenuredHeap<T>& other) { return bits == other.bits; }
322     bool operator!=(const TenuredHeap<T>& other) { return bits != other.bits; }
323 
setPtr(T newPtr)324     void setPtr(T newPtr) {
325         MOZ_ASSERT((reinterpret_cast<uintptr_t>(newPtr) & flagsMask) == 0);
326         if (newPtr)
327             AssertGCThingMustBeTenured(newPtr);
328         bits = (bits & flagsMask) | reinterpret_cast<uintptr_t>(newPtr);
329     }
330 
setFlags(uintptr_t flagsToSet)331     void setFlags(uintptr_t flagsToSet) {
332         MOZ_ASSERT((flagsToSet & ~flagsMask) == 0);
333         bits |= flagsToSet;
334     }
335 
unsetFlags(uintptr_t flagsToUnset)336     void unsetFlags(uintptr_t flagsToUnset) {
337         MOZ_ASSERT((flagsToUnset & ~flagsMask) == 0);
338         bits &= ~flagsToUnset;
339     }
340 
hasFlag(uintptr_t flag)341     bool hasFlag(uintptr_t flag) const {
342         MOZ_ASSERT((flag & ~flagsMask) == 0);
343         return (bits & flag) != 0;
344     }
345 
getPtr()346     T getPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); }
getFlags()347     uintptr_t getFlags() const { return bits & flagsMask; }
348 
T()349     operator T() const { return getPtr(); }
350     T operator->() const { return getPtr(); }
351 
352     TenuredHeap<T>& operator=(T p) {
353         setPtr(p);
354         return *this;
355     }
356 
357     TenuredHeap<T>& operator=(const TenuredHeap<T>& other) {
358         bits = other.bits;
359         return *this;
360     }
361 
362   private:
363     enum {
364         maskBits = 3,
365         flagsMask = (1 << maskBits) - 1,
366     };
367 
368     uintptr_t bits;
369 };
370 
371 /**
372  * Reference to a T that has been rooted elsewhere. This is most useful
373  * as a parameter type, which guarantees that the T lvalue is properly
374  * rooted. See "Move GC Stack Rooting" above.
375  *
376  * If you want to add additional methods to Handle for a specific
377  * specialization, define a HandleBase<T> specialization containing them.
378  */
379 template <typename T>
380 class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
381 {
382     friend class JS::MutableHandle<T>;
383 
384   public:
385     /* Creates a handle from a handle of a type convertible to T. */
386     template <typename S>
387     MOZ_IMPLICIT Handle(Handle<S> handle,
388                         typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
389     {
390         static_assert(sizeof(Handle<T>) == sizeof(T*),
391                       "Handle must be binary compatible with T*.");
392         ptr = reinterpret_cast<const T*>(handle.address());
393     }
394 
Handle(decltype (nullptr))395     MOZ_IMPLICIT Handle(decltype(nullptr)) {
396         static_assert(mozilla::IsPointer<T>::value,
397                       "nullptr_t overload not valid for non-pointer types");
398         ptr = reinterpret_cast<const T*>(&js::ConstNullValue);
399     }
400 
Handle(MutableHandle<T> handle)401     MOZ_IMPLICIT Handle(MutableHandle<T> handle) {
402         ptr = handle.address();
403     }
404 
405     /*
406      * Take care when calling this method!
407      *
408      * This creates a Handle from the raw location of a T.
409      *
410      * It should be called only if the following conditions hold:
411      *
412      *  1) the location of the T is guaranteed to be marked (for some reason
413      *     other than being a Rooted), e.g., if it is guaranteed to be reachable
414      *     from an implicit root.
415      *
416      *  2) the contents of the location are immutable, or at least cannot change
417      *     for the lifetime of the handle, as its users may not expect its value
418      *     to change underneath them.
419      */
fromMarkedLocation(const T * p)420     static MOZ_CONSTEXPR Handle fromMarkedLocation(const T* p) {
421         return Handle(p, DeliberatelyChoosingThisOverload,
422                       ImUsingThisOnlyInFromFromMarkedLocation);
423     }
424 
425     /*
426      * Construct a handle from an explicitly rooted location. This is the
427      * normal way to create a handle, and normally happens implicitly.
428      */
429     template <typename S>
430     inline
431     MOZ_IMPLICIT Handle(const Rooted<S>& root,
432                         typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
433 
434     template <typename S>
435     inline
436     MOZ_IMPLICIT Handle(const PersistentRooted<S>& root,
437                         typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
438 
439     /* Construct a read only handle from a mutable handle. */
440     template <typename S>
441     inline
442     MOZ_IMPLICIT Handle(MutableHandle<S>& root,
443                         typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
444 
445     DECLARE_POINTER_COMPARISON_OPS(T);
446     DECLARE_POINTER_CONSTREF_OPS(T);
447     DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr);
448 
449   private:
Handle()450     Handle() {}
451     DELETE_ASSIGNMENT_OPS(Handle, T);
452 
453     enum Disambiguator { DeliberatelyChoosingThisOverload = 42 };
454     enum CallerIdentity { ImUsingThisOnlyInFromFromMarkedLocation = 17 };
Handle(const T * p,Disambiguator,CallerIdentity)455     MOZ_CONSTEXPR Handle(const T* p, Disambiguator, CallerIdentity) : ptr(p) {}
456 
457     const T* ptr;
458 };
459 
460 /**
461  * Similar to a handle, but the underlying storage can be changed. This is
462  * useful for outparams.
463  *
464  * If you want to add additional methods to MutableHandle for a specific
465  * specialization, define a MutableHandleBase<T> specialization containing
466  * them.
467  */
468 template <typename T>
469 class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T>
470 {
471   public:
472     inline MOZ_IMPLICIT MutableHandle(Rooted<T>* root);
473     inline MOZ_IMPLICIT MutableHandle(PersistentRooted<T>* root);
474 
475   private:
476     // Disallow nullptr for overloading purposes.
477     MutableHandle(decltype(nullptr)) = delete;
478 
479   public:
set(T v)480     void set(T v) {
481         *ptr = v;
482     }
483 
484     /*
485      * This may be called only if the location of the T is guaranteed
486      * to be marked (for some reason other than being a Rooted),
487      * e.g., if it is guaranteed to be reachable from an implicit root.
488      *
489      * Create a MutableHandle from a raw location of a T.
490      */
fromMarkedLocation(T * p)491     static MutableHandle fromMarkedLocation(T* p) {
492         MutableHandle h;
493         h.ptr = p;
494         return h;
495     }
496 
497     DECLARE_POINTER_CONSTREF_OPS(T);
498     DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr);
499     DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(*ptr);
500 
501   private:
MutableHandle()502     MutableHandle() {}
503     DELETE_ASSIGNMENT_OPS(MutableHandle, T);
504 
505     T* ptr;
506 };
507 
508 } /* namespace JS */
509 
510 namespace js {
511 
512 /**
513  * By default, things should use the inheritance hierarchy to find their
514  * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
515  * Rooted<T> may be used without the class definition being available.
516  */
517 template <typename T>
518 struct RootKind
519 {
rootKindRootKind520     static ThingRootKind rootKind() { return T::rootKind(); }
521 };
522 
523 template <typename T>
524 struct RootKind<T*>
525 {
526     static ThingRootKind rootKind() { return T::rootKind(); }
527 };
528 
529 template <typename T>
530 struct GCMethods<T*>
531 {
532     static T* initial() { return nullptr; }
533     static void postBarrier(T** vp, T* prev, T* next) {
534         if (next)
535             JS::AssertGCThingIsNotAnObjectSubclass(reinterpret_cast<js::gc::Cell*>(next));
536     }
537     static void relocate(T** vp) {}
538 };
539 
540 template <>
541 struct GCMethods<JSObject*>
542 {
543     static JSObject* initial() { return nullptr; }
544     static gc::Cell* asGCThingOrNull(JSObject* v) {
545         if (!v)
546             return nullptr;
547         MOZ_ASSERT(uintptr_t(v) > 32);
548         return reinterpret_cast<gc::Cell*>(v);
549     }
550     static void postBarrier(JSObject** vp, JSObject* prev, JSObject* next) {
551         JS::HeapObjectPostBarrier(vp, prev, next);
552     }
553 };
554 
555 template <>
556 struct GCMethods<JSFunction*>
557 {
558     static JSFunction* initial() { return nullptr; }
559     static void postBarrier(JSFunction** vp, JSFunction* prev, JSFunction* next) {
560         JS::HeapObjectPostBarrier(reinterpret_cast<JSObject**>(vp),
561                                   reinterpret_cast<JSObject*>(prev),
562                                   reinterpret_cast<JSObject*>(next));
563     }
564 };
565 
566 // Provide hash codes for Cell kinds that may be relocated and, thus, not have
567 // a stable address to use as the base for a hash code. Instead of the address,
568 // this hasher uses Cell::getUniqueId to provide exact matches and as a base
569 // for generating hash codes.
570 //
571 // Note: this hasher, like PointerHasher can "hash" a nullptr. While a nullptr
572 // would not likely be a useful key, there are some cases where being able to
573 // hash a nullptr is useful, either on purpose or because of bugs:
574 // (1) existence checks where the key may happen to be null and (2) some
575 // aggregate Lookup kinds embed a JSObject* that is frequently null and do not
576 // null test before dispatching to the hasher.
577 template <typename T>
578 struct JS_PUBLIC_API(MovableCellHasher)
579 {
580     using Key = T;
581     using Lookup = T;
582 
583     static HashNumber hash(const Lookup& l);
584     static bool match(const Key& k, const Lookup& l);
585     static void rekey(Key& k, const Key& newKey) { k = newKey; }
586 };
587 
588 template <typename T>
589 struct JS_PUBLIC_API(MovableCellHasher<JS::Heap<T>>)
590 {
591     using Key = JS::Heap<T>;
592     using Lookup = T;
593 
594     static HashNumber hash(const Lookup& l) { return MovableCellHasher<T>::hash(l); }
595     static bool match(const Key& k, const Lookup& l) { return MovableCellHasher<T>::match(k, l); }
596     static void rekey(Key& k, const Key& newKey) { k.unsafeSet(newKey); }
597 };
598 
599 } /* namespace js */
600 
601 namespace JS {
602 
603 // Non pointer types -- structs or classes that contain GC pointers, either as
604 // a member or in a more complex container layout -- can also be stored in a
605 // [Persistent]Rooted if it derives from JS::Traceable. A JS::Traceable stored
606 // in a [Persistent]Rooted must implement the method:
607 //     |static void trace(T*, JSTracer*)|
608 class Traceable
609 {
610   public:
611     static js::ThingRootKind rootKind() { return js::THING_ROOT_TRACEABLE; }
612 };
613 
614 } /* namespace JS */
615 
616 namespace js {
617 
618 template <typename T>
619 class DispatchWrapper
620 {
621     static_assert(mozilla::IsBaseOf<JS::Traceable, T>::value,
622                   "DispatchWrapper is intended only for usage with a Traceable");
623 
624     using TraceFn = void (*)(T*, JSTracer*);
625     TraceFn tracer;
626 #if JS_BITS_PER_WORD == 32
627     uint32_t padding; // Ensure the storage fields have CellSize alignment.
628 #endif
629     T storage;
630 
631   public:
632     template <typename U>
633     MOZ_IMPLICIT DispatchWrapper(U&& initial)
634       : tracer(&T::trace),
635         storage(mozilla::Forward<U>(initial))
636     { }
637 
638     // Mimic a pointer type, so that we can drop into Rooted.
639     T* operator &() { return &storage; }
640     const T* operator &() const { return &storage; }
641     operator T&() { return storage; }
642     operator const T&() const { return storage; }
643 
644     // Trace the contained storage (of unknown type) using the trace function
645     // we set aside when we did know the type.
646     static void TraceWrapped(JSTracer* trc, JS::Traceable* thingp, const char* name) {
647         auto wrapper = reinterpret_cast<DispatchWrapper*>(
648                            uintptr_t(thingp) - offsetof(DispatchWrapper, storage));
649         wrapper->tracer(&wrapper->storage, trc);
650     }
651 };
652 
653 inline RootLists&
654 RootListsForRootingContext(JSContext* cx)
655 {
656     return ContextFriendFields::get(cx)->roots;
657 }
658 
659 inline RootLists&
660 RootListsForRootingContext(js::ContextFriendFields* cx)
661 {
662     return cx->roots;
663 }
664 
665 inline RootLists&
666 RootListsForRootingContext(JSRuntime* rt)
667 {
668     return PerThreadDataFriendFields::getMainThread(rt)->roots;
669 }
670 
671 inline RootLists&
672 RootListsForRootingContext(js::PerThreadDataFriendFields* pt)
673 {
674     return pt->roots;
675 }
676 
677 } /* namespace js */
678 
679 namespace JS {
680 
681 /**
682  * Local variable of type T whose value is always rooted. This is typically
683  * used for local variables, or for non-rooted values being passed to a
684  * function that requires a handle, e.g. Foo(Root<T>(cx, x)).
685  *
686  * If you want to add additional methods to Rooted for a specific
687  * specialization, define a RootedBase<T> specialization containing them.
688  */
689 template <typename T>
690 class MOZ_RAII Rooted : public js::RootedBase<T>
691 {
692     static_assert(!mozilla::IsConvertible<T, Traceable*>::value,
693                   "Rooted takes pointer or Traceable types but not Traceable* type");
694 
695     /* Note: CX is a subclass of either ContextFriendFields or PerThreadDataFriendFields. */
696     void registerWithRootLists(js::RootLists& roots) {
697         js::ThingRootKind kind = js::RootKind<T>::rootKind();
698         this->stack = &roots.stackRoots_[kind];
699         this->prev = *stack;
700         *stack = reinterpret_cast<Rooted<void*>*>(this);
701     }
702 
703   public:
704     template <typename RootingContext>
705     explicit Rooted(const RootingContext& cx)
706       : ptr(js::GCMethods<T>::initial())
707     {
708         registerWithRootLists(js::RootListsForRootingContext(cx));
709     }
710 
711     template <typename RootingContext, typename S>
712     Rooted(const RootingContext& cx, S&& initial)
713       : ptr(mozilla::Forward<S>(initial))
714     {
715         registerWithRootLists(js::RootListsForRootingContext(cx));
716     }
717 
718     ~Rooted() {
719         MOZ_ASSERT(*stack == reinterpret_cast<Rooted<void*>*>(this));
720         *stack = prev;
721     }
722 
723     Rooted<T>* previous() { return reinterpret_cast<Rooted<T>*>(prev); }
724 
725     /*
726      * This method is public for Rooted so that Codegen.py can use a Rooted
727      * interchangeably with a MutableHandleValue.
728      */
729     void set(T value) {
730         ptr = value;
731     }
732 
733     DECLARE_POINTER_COMPARISON_OPS(T);
734     DECLARE_POINTER_CONSTREF_OPS(T);
735     DECLARE_POINTER_ASSIGN_OPS(Rooted, T);
736     DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr);
737     DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(ptr);
738 
739   private:
740     /*
741      * These need to be templated on void* to avoid aliasing issues between, for
742      * example, Rooted<JSObject> and Rooted<JSFunction>, which use the same
743      * stack head pointer for different classes.
744      */
745     Rooted<void*>** stack;
746     Rooted<void*>* prev;
747 
748     /*
749      * For pointer types, the TraceKind for tracing is based on the list it is
750      * in (selected via rootKind), so no additional storage is required here.
751      * All Traceable, however, share the same list, so the function to
752      * call for tracing is stored adjacent to the struct. Since C++ cannot
753      * templatize on storage class, this is implemented via the wrapper class
754      * DispatchWrapper.
755      */
756     using MaybeWrapped = typename mozilla::Conditional<
757         mozilla::IsBaseOf<Traceable, T>::value,
758         js::DispatchWrapper<T>,
759         T>::Type;
760     MaybeWrapped ptr;
761 
762     Rooted(const Rooted&) = delete;
763 };
764 
765 } /* namespace JS */
766 
767 namespace js {
768 
769 /**
770  * Augment the generic Rooted<T> interface when T = JSObject* with
771  * class-querying and downcasting operations.
772  *
773  * Given a Rooted<JSObject*> obj, one can view
774  *   Handle<StringObject*> h = obj.as<StringObject*>();
775  * as an optimization of
776  *   Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
777  *   Handle<StringObject*> h = rooted;
778  */
779 template <>
780 class RootedBase<JSObject*>
781 {
782   public:
783     template <class U>
784     JS::Handle<U*> as() const;
785 };
786 
787 /**
788  * Augment the generic Handle<T> interface when T = JSObject* with
789  * downcasting operations.
790  *
791  * Given a Handle<JSObject*> obj, one can view
792  *   Handle<StringObject*> h = obj.as<StringObject*>();
793  * as an optimization of
794  *   Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
795  *   Handle<StringObject*> h = rooted;
796  */
797 template <>
798 class HandleBase<JSObject*>
799 {
800   public:
801     template <class U>
802     JS::Handle<U*> as() const;
803 };
804 
805 /** Interface substitute for Rooted<T> which does not root the variable's memory. */
806 template <typename T>
807 class MOZ_RAII FakeRooted : public RootedBase<T>
808 {
809   public:
810     template <typename CX>
811     explicit FakeRooted(CX* cx) : ptr(GCMethods<T>::initial()) {}
812 
813     template <typename CX>
814     FakeRooted(CX* cx, T initial) : ptr(initial) {}
815 
816     DECLARE_POINTER_COMPARISON_OPS(T);
817     DECLARE_POINTER_CONSTREF_OPS(T);
818     DECLARE_POINTER_ASSIGN_OPS(FakeRooted, T);
819     DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr);
820     DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(ptr);
821 
822   private:
823     T ptr;
824 
825     void set(const T& value) {
826         ptr = value;
827     }
828 
829     FakeRooted(const FakeRooted&) = delete;
830 };
831 
832 /** Interface substitute for MutableHandle<T> which is not required to point to rooted memory. */
833 template <typename T>
834 class FakeMutableHandle : public js::MutableHandleBase<T>
835 {
836   public:
837     MOZ_IMPLICIT FakeMutableHandle(T* t) {
838         ptr = t;
839     }
840 
841     MOZ_IMPLICIT FakeMutableHandle(FakeRooted<T>* root) {
842         ptr = root->address();
843     }
844 
845     void set(T v) {
846         *ptr = v;
847     }
848 
849     DECLARE_POINTER_CONSTREF_OPS(T);
850     DECLARE_NONPOINTER_ACCESSOR_METHODS(*ptr);
851     DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(*ptr);
852 
853   private:
854     FakeMutableHandle() {}
855     DELETE_ASSIGNMENT_OPS(FakeMutableHandle, T);
856 
857     T* ptr;
858 };
859 
860 /**
861  * Types for a variable that either should or shouldn't be rooted, depending on
862  * the template parameter allowGC. Used for implementing functions that can
863  * operate on either rooted or unrooted data.
864  *
865  * The toHandle() and toMutableHandle() functions are for calling functions
866  * which require handle types and are only called in the CanGC case. These
867  * allow the calling code to type check.
868  */
869 enum AllowGC {
870     NoGC = 0,
871     CanGC = 1
872 };
873 template <typename T, AllowGC allowGC>
874 class MaybeRooted
875 {
876 };
877 
878 template <typename T> class MaybeRooted<T, CanGC>
879 {
880   public:
881     typedef JS::Handle<T> HandleType;
882     typedef JS::Rooted<T> RootType;
883     typedef JS::MutableHandle<T> MutableHandleType;
884 
885     static inline JS::Handle<T> toHandle(HandleType v) {
886         return v;
887     }
888 
889     static inline JS::MutableHandle<T> toMutableHandle(MutableHandleType v) {
890         return v;
891     }
892 
893     template <typename T2>
894     static inline JS::Handle<T2*> downcastHandle(HandleType v) {
895         return v.template as<T2>();
896     }
897 };
898 
899 template <typename T> class MaybeRooted<T, NoGC>
900 {
901   public:
902     typedef T HandleType;
903     typedef FakeRooted<T> RootType;
904     typedef FakeMutableHandle<T> MutableHandleType;
905 
906     static JS::Handle<T> toHandle(HandleType v) {
907         MOZ_CRASH("Bad conversion");
908     }
909 
910     static JS::MutableHandle<T> toMutableHandle(MutableHandleType v) {
911         MOZ_CRASH("Bad conversion");
912     }
913 
914     template <typename T2>
915     static inline T2* downcastHandle(HandleType v) {
916         return &v->template as<T2>();
917     }
918 };
919 
920 } /* namespace js */
921 
922 namespace JS {
923 
924 template <typename T> template <typename S>
925 inline
926 Handle<T>::Handle(const Rooted<S>& root,
927                   typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
928 {
929     ptr = reinterpret_cast<const T*>(root.address());
930 }
931 
932 template <typename T> template <typename S>
933 inline
934 Handle<T>::Handle(const PersistentRooted<S>& root,
935                   typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
936 {
937     ptr = reinterpret_cast<const T*>(root.address());
938 }
939 
940 template <typename T> template <typename S>
941 inline
942 Handle<T>::Handle(MutableHandle<S>& root,
943                   typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
944 {
945     ptr = reinterpret_cast<const T*>(root.address());
946 }
947 
948 template <typename T>
949 inline
950 MutableHandle<T>::MutableHandle(Rooted<T>* root)
951 {
952     static_assert(sizeof(MutableHandle<T>) == sizeof(T*),
953                   "MutableHandle must be binary compatible with T*.");
954     ptr = root->address();
955 }
956 
957 template <typename T>
958 inline
959 MutableHandle<T>::MutableHandle(PersistentRooted<T>* root)
960 {
961     static_assert(sizeof(MutableHandle<T>) == sizeof(T*),
962                   "MutableHandle must be binary compatible with T*.");
963     ptr = root->address();
964 }
965 
966 /**
967  * A copyable, assignable global GC root type with arbitrary lifetime, an
968  * infallible constructor, and automatic unrooting on destruction.
969  *
970  * These roots can be used in heap-allocated data structures, so they are not
971  * associated with any particular JSContext or stack. They are registered with
972  * the JSRuntime itself, without locking, so they require a full JSContext to be
973  * initialized, not one of its more restricted superclasses.  Initialization may
974  * take place on construction, or in two phases if the no-argument constructor
975  * is called followed by init().
976  *
977  * Note that you must not use an PersistentRooted in an object owned by a JS
978  * object:
979  *
980  * Whenever one object whose lifetime is decided by the GC refers to another
981  * such object, that edge must be traced only if the owning JS object is traced.
982  * This applies not only to JS objects (which obviously are managed by the GC)
983  * but also to C++ objects owned by JS objects.
984  *
985  * If you put a PersistentRooted in such a C++ object, that is almost certainly
986  * a leak. When a GC begins, the referent of the PersistentRooted is treated as
987  * live, unconditionally (because a PersistentRooted is a *root*), even if the
988  * JS object that owns it is unreachable. If there is any path from that
989  * referent back to the JS object, then the C++ object containing the
990  * PersistentRooted will not be destructed, and the whole blob of objects will
991  * not be freed, even if there are no references to them from the outside.
992  *
993  * In the context of Firefox, this is a severe restriction: almost everything in
994  * Firefox is owned by some JS object or another, so using PersistentRooted in
995  * such objects would introduce leaks. For these kinds of edges, Heap<T> or
996  * TenuredHeap<T> would be better types. It's up to the implementor of the type
997  * containing Heap<T> or TenuredHeap<T> members to make sure their referents get
998  * marked when the object itself is marked.
999  */
1000 template<typename T>
1001 class PersistentRooted : public js::PersistentRootedBase<T>,
1002                          private mozilla::LinkedListElement<PersistentRooted<T>>
1003 {
1004     typedef mozilla::LinkedListElement<PersistentRooted<T>> ListBase;
1005 
1006     friend class mozilla::LinkedList<PersistentRooted>;
1007     friend class mozilla::LinkedListElement<PersistentRooted>;
1008 
1009     friend struct js::gc::PersistentRootedMarker<T>;
1010 
1011     friend void js::gc::FinishPersistentRootedChains(js::RootLists&);
1012 
1013     void registerWithRootLists(js::RootLists& roots) {
1014         MOZ_ASSERT(!initialized());
1015         js::ThingRootKind kind = js::RootKind<T>::rootKind();
1016         roots.heapRoots_[kind].insertBack(reinterpret_cast<JS::PersistentRooted<void*>*>(this));
1017         // Until marking and destruction support the full set, we assert that
1018         // we don't try to add any unsupported types.
1019         MOZ_ASSERT(kind == js::THING_ROOT_OBJECT ||
1020                    kind == js::THING_ROOT_SCRIPT ||
1021                    kind == js::THING_ROOT_STRING ||
1022                    kind == js::THING_ROOT_ID ||
1023                    kind == js::THING_ROOT_VALUE ||
1024                    kind == js::THING_ROOT_TRACEABLE);
1025     }
1026 
1027   public:
1028     PersistentRooted() : ptr(js::GCMethods<T>::initial()) {}
1029 
1030     template <typename RootingContext>
1031     explicit PersistentRooted(const RootingContext& cx)
1032       : ptr(js::GCMethods<T>::initial())
1033     {
1034         registerWithRootLists(js::RootListsForRootingContext(cx));
1035     }
1036 
1037     template <typename RootingContext, typename U>
1038     PersistentRooted(const RootingContext& cx, U&& initial)
1039       : ptr(mozilla::Forward<U>(initial))
1040     {
1041         registerWithRootLists(js::RootListsForRootingContext(cx));
1042     }
1043 
1044     PersistentRooted(const PersistentRooted& rhs)
1045       : mozilla::LinkedListElement<PersistentRooted<T>>(),
1046         ptr(rhs.ptr)
1047     {
1048         /*
1049          * Copy construction takes advantage of the fact that the original
1050          * is already inserted, and simply adds itself to whatever list the
1051          * original was on - no JSRuntime pointer needed.
1052          *
1053          * This requires mutating rhs's links, but those should be 'mutable'
1054          * anyway. C++ doesn't let us declare mutable base classes.
1055          */
1056         const_cast<PersistentRooted&>(rhs).setNext(this);
1057     }
1058 
1059     bool initialized() {
1060         return ListBase::isInList();
1061     }
1062 
1063     template <typename RootingContext>
1064     void init(const RootingContext& cx) {
1065         init(cx, js::GCMethods<T>::initial());
1066     }
1067 
1068     template <typename RootingContext, typename U>
1069     void init(const RootingContext& cx, U&& initial) {
1070         ptr = mozilla::Forward<U>(initial);
1071         registerWithRootLists(js::RootListsForRootingContext(cx));
1072     }
1073 
1074     void reset() {
1075         if (initialized()) {
1076             set(js::GCMethods<T>::initial());
1077             ListBase::remove();
1078         }
1079     }
1080 
1081     DECLARE_POINTER_COMPARISON_OPS(T);
1082     DECLARE_POINTER_CONSTREF_OPS(T);
1083     DECLARE_POINTER_ASSIGN_OPS(PersistentRooted, T);
1084     DECLARE_NONPOINTER_ACCESSOR_METHODS(ptr);
1085 
1086     // These are the same as DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS, except
1087     // they check that |this| is initialized in case the caller later stores
1088     // something in |ptr|.
1089     T* address() {
1090         MOZ_ASSERT(initialized());
1091         return &ptr;
1092     }
1093     T& get() {
1094         MOZ_ASSERT(initialized());
1095         return ptr;
1096     }
1097 
1098   private:
1099     void set(T value) {
1100         MOZ_ASSERT(initialized());
1101         ptr = value;
1102     }
1103 
1104     // See the comment above Rooted::ptr.
1105     using MaybeWrapped = typename mozilla::Conditional<
1106         mozilla::IsBaseOf<Traceable, T>::value,
1107         js::DispatchWrapper<T>,
1108         T>::Type;
1109 
1110     MaybeWrapped ptr;
1111 };
1112 
1113 class JS_PUBLIC_API(ObjectPtr)
1114 {
1115     Heap<JSObject*> value;
1116 
1117   public:
1118     ObjectPtr() : value(nullptr) {}
1119 
1120     explicit ObjectPtr(JSObject* obj) : value(obj) {}
1121 
1122     /* Always call finalize before the destructor. */
1123     ~ObjectPtr() { MOZ_ASSERT(!value); }
1124 
1125     void finalize(JSRuntime* rt) {
1126         if (IsIncrementalBarrierNeeded(rt))
1127             IncrementalObjectBarrier(value);
1128         value = nullptr;
1129     }
1130 
1131     void init(JSObject* obj) { value = obj; }
1132 
1133     JSObject* get() const { return value; }
1134 
1135     void writeBarrierPre(JSRuntime* rt) {
1136         IncrementalObjectBarrier(value);
1137     }
1138 
1139     void updateWeakPointerAfterGC();
1140 
1141     ObjectPtr& operator=(JSObject* obj) {
1142         IncrementalObjectBarrier(value);
1143         value = obj;
1144         return *this;
1145     }
1146 
1147     void trace(JSTracer* trc, const char* name);
1148 
1149     JSObject& operator*() const { return *value; }
1150     JSObject* operator->() const { return value; }
1151     operator JSObject*() const { return value; }
1152 };
1153 
1154 } /* namespace JS */
1155 
1156 namespace js {
1157 namespace gc {
1158 
1159 template <typename T, typename TraceCallbacks>
1160 void
1161 CallTraceCallbackOnNonHeap(T* v, const TraceCallbacks& aCallbacks, const char* aName, void* aClosure)
1162 {
1163     static_assert(sizeof(T) == sizeof(JS::Heap<T>), "T and Heap<T> must be compatible.");
1164     MOZ_ASSERT(v);
1165     mozilla::DebugOnly<Cell*> cell = GCMethods<T>::asGCThingOrNull(*v);
1166     MOZ_ASSERT(cell);
1167     MOZ_ASSERT(!IsInsideNursery(cell));
1168     JS::Heap<T>* asHeapT = reinterpret_cast<JS::Heap<T>*>(v);
1169     aCallbacks.Trace(asHeapT, aName, aClosure);
1170 }
1171 
1172 } /* namespace gc */
1173 } /* namespace js */
1174 
1175 // mozilla::Swap uses a stack temporary, which prevents classes like Heap<T>
1176 // from being declared MOZ_HEAP_CLASS.
1177 namespace mozilla {
1178 
1179 template <typename T>
1180 inline void
1181 Swap(JS::Heap<T>& aX, JS::Heap<T>& aY)
1182 {
1183     T tmp = aX;
1184     aX = aY;
1185     aY = tmp;
1186 }
1187 
1188 template <typename T>
1189 inline void
1190 Swap(JS::TenuredHeap<T>& aX, JS::TenuredHeap<T>& aY)
1191 {
1192     T tmp = aX;
1193     aX = aY;
1194     aY = tmp;
1195 }
1196 
1197 } /* namespace mozilla */
1198 
1199 #undef DELETE_ASSIGNMENT_OPS
1200 
1201 #endif  /* js_RootingAPI_h */
1202