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

Generated by: LCOV version 1.13-14-ga5dd952