LCOV - code coverage report
Current view: top level - js/public - RootingAPI.h (source / functions) Hit Total Coverage
Test: output.info Lines: 325 367 88.6 %
Date: 2017-07-14 16:53:18 Functions: 2691 4881 55.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13