js/public/RootingAPI.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing 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/. */
     7 #ifndef js_RootingAPI_h
     8 #define js_RootingAPI_h
    10 #include "mozilla/Attributes.h"
    11 #include "mozilla/GuardObjects.h"
    12 #include "mozilla/LinkedList.h"
    13 #include "mozilla/NullPtr.h"
    14 #include "mozilla/TypeTraits.h"
    16 #include "jspubtd.h"
    18 #include "js/TypeDecls.h"
    19 #include "js/Utility.h"
    21 /*
    22  * Moving GC Stack Rooting
    23  *
    24  * A moving GC may change the physical location of GC allocated things, even
    25  * when they are rooted, updating all pointers to the thing to refer to its new
    26  * location. The GC must therefore know about all live pointers to a thing,
    27  * not just one of them, in order to behave correctly.
    28  *
    29  * The |Rooted| and |Handle| classes below are used to root stack locations
    30  * whose value may be held live across a call that can trigger GC. For a
    31  * code fragment such as:
    32  *
    33  * JSObject *obj = NewObject(cx);
    34  * DoSomething(cx);
    35  * ... = obj->lastProperty();
    36  *
    37  * If |DoSomething()| can trigger a GC, the stack location of |obj| must be
    38  * rooted to ensure that the GC does not move the JSObject referred to by
    39  * |obj| without updating |obj|'s location itself. This rooting must happen
    40  * regardless of whether there are other roots which ensure that the object
    41  * itself will not be collected.
    42  *
    43  * If |DoSomething()| cannot trigger a GC, and the same holds for all other
    44  * calls made between |obj|'s definitions and its last uses, then no rooting
    45  * is required.
    46  *
    47  * SpiderMonkey can trigger a GC at almost any time and in ways that are not
    48  * always clear. For example, the following innocuous-looking actions can
    49  * cause a GC: allocation of any new GC thing; JSObject::hasProperty;
    50  * JS_ReportError and friends; and ToNumber, among many others. The following
    51  * dangerous-looking actions cannot trigger a GC: js_malloc, cx->malloc_,
    52  * rt->malloc_, and friends and JS_ReportOutOfMemory.
    53  *
    54  * The following family of three classes will exactly root a stack location.
    55  * Incorrect usage of these classes will result in a compile error in almost
    56  * all cases. Therefore, it is very hard to be incorrectly rooted if you use
    57  * these classes exclusively. These classes are all templated on the type T of
    58  * the value being rooted.
    59  *
    60  * - Rooted<T> declares a variable of type T, whose value is always rooted.
    61  *   Rooted<T> may be automatically coerced to a Handle<T>, below. Rooted<T>
    62  *   should be used whenever a local variable's value may be held live across a
    63  *   call which can trigger a GC.
    64  *
    65  * - Handle<T> is a const reference to a Rooted<T>. Functions which take GC
    66  *   things or values as arguments and need to root those arguments should
    67  *   generally use handles for those arguments and avoid any explicit rooting.
    68  *   This has two benefits. First, when several such functions call each other
    69  *   then redundant rooting of multiple copies of the GC thing can be avoided.
    70  *   Second, if the caller does not pass a rooted value a compile error will be
    71  *   generated, which is quicker and easier to fix than when relying on a
    72  *   separate rooting analysis.
    73  *
    74  * - MutableHandle<T> is a non-const reference to Rooted<T>. It is used in the
    75  *   same way as Handle<T> and includes a |set(const T &v)| method to allow
    76  *   updating the value of the referenced Rooted<T>. A MutableHandle<T> can be
    77  *   created from a Rooted<T> by using |Rooted<T>::operator&()|.
    78  *
    79  * In some cases the small performance overhead of exact rooting (measured to
    80  * be a few nanoseconds on desktop) is too much. In these cases, try the
    81  * following:
    82  *
    83  * - Move all Rooted<T> above inner loops: this allows you to re-use the root
    84  *   on each iteration of the loop.
    85  *
    86  * - Pass Handle<T> through your hot call stack to avoid re-rooting costs at
    87  *   every invocation.
    88  *
    89  * The following diagram explains the list of supported, implicit type
    90  * conversions between classes of this family:
    91  *
    92  *  Rooted<T> ----> Handle<T>
    93  *     |               ^
    94  *     |               |
    95  *     |               |
    96  *     +---> MutableHandle<T>
    97  *     (via &)
    98  *
    99  * All of these types have an implicit conversion to raw pointers.
   100  */
   102 namespace js {
   104 class ScriptSourceObject;
   106 template <typename T>
   107 struct GCMethods {};
   109 template <typename T>
   110 class RootedBase {};
   112 template <typename T>
   113 class HandleBase {};
   115 template <typename T>
   116 class MutableHandleBase {};
   118 template <typename T>
   119 class HeapBase {};
   121 /*
   122  * js::NullPtr acts like a nullptr pointer in contexts that require a Handle.
   123  *
   124  * Handle provides an implicit constructor for js::NullPtr so that, given:
   125  *   foo(Handle<JSObject*> h);
   126  * callers can simply write:
   127  *   foo(js::NullPtr());
   128  * which avoids creating a Rooted<JSObject*> just to pass nullptr.
   129  *
   130  * This is the SpiderMonkey internal variant. js::NullPtr should be used in
   131  * preference to JS::NullPtr to avoid the GOT access required for JS_PUBLIC_API
   132  * symbols.
   133  */
   134 struct NullPtr
   135 {
   136     static void * const constNullValue;
   137 };
   139 namespace gc {
   140 struct Cell;
   141 template<typename T>
   142 struct PersistentRootedMarker;
   143 } /* namespace gc */
   145 } /* namespace js */
   147 namespace JS {
   149 template <typename T> class Rooted;
   150 template <typename T> class PersistentRooted;
   152 /* This is exposing internal state of the GC for inlining purposes. */
   153 JS_FRIEND_API(bool) isGCEnabled();
   155 /*
   156  * JS::NullPtr acts like a nullptr pointer in contexts that require a Handle.
   157  *
   158  * Handle provides an implicit constructor for JS::NullPtr so that, given:
   159  *   foo(Handle<JSObject*> h);
   160  * callers can simply write:
   161  *   foo(JS::NullPtr());
   162  * which avoids creating a Rooted<JSObject*> just to pass nullptr.
   163  */
   164 struct JS_PUBLIC_API(NullPtr)
   165 {
   166     static void * const constNullValue;
   167 };
   169 /*
   170  * The Heap<T> class is a heap-stored reference to a JS GC thing. All members of
   171  * heap classes that refer to GC things should use Heap<T> (or possibly
   172  * TenuredHeap<T>, described below).
   173  *
   174  * Heap<T> is an abstraction that hides some of the complexity required to
   175  * maintain GC invariants for the contained reference. It uses operator
   176  * overloading to provide a normal pointer interface, but notifies the GC every
   177  * time the value it contains is updated. This is necessary for generational GC,
   178  * which keeps track of all pointers into the nursery.
   179  *
   180  * Heap<T> instances must be traced when their containing object is traced to
   181  * keep the pointed-to GC thing alive.
   182  *
   183  * Heap<T> objects should only be used on the heap. GC references stored on the
   184  * C/C++ stack must use Rooted/Handle/MutableHandle instead.
   185  *
   186  * Type T must be one of: JS::Value, jsid, JSObject*, JSString*, JSScript*
   187  */
   188 template <typename T>
   189 class Heap : public js::HeapBase<T>
   190 {
   191   public:
   192     Heap() {
   193         static_assert(sizeof(T) == sizeof(Heap<T>),
   194                       "Heap<T> must be binary compatible with T.");
   195         init(js::GCMethods<T>::initial());
   196     }
   197     explicit Heap(T p) { init(p); }
   199     /*
   200      * For Heap, move semantics are equivalent to copy semantics. In C++, a
   201      * copy constructor taking const-ref is the way to get a single function
   202      * that will be used for both lvalue and rvalue copies, so we can simply
   203      * omit the rvalue variant.
   204      */
   205     explicit Heap(const Heap<T> &p) { init(p.ptr); }
   207     ~Heap() {
   208         if (js::GCMethods<T>::needsPostBarrier(ptr))
   209             relocate();
   210     }
   212     bool operator==(const Heap<T> &other) { return ptr == other.ptr; }
   213     bool operator!=(const Heap<T> &other) { return ptr != other.ptr; }
   215     bool operator==(const T &other) const { return ptr == other; }
   216     bool operator!=(const T &other) const { return ptr != other; }
   218     operator T() const { return ptr; }
   219     T operator->() const { return ptr; }
   220     const T *address() const { return &ptr; }
   221     const T &get() const { return ptr; }
   223     T *unsafeGet() { return &ptr; }
   225     Heap<T> &operator=(T p) {
   226         set(p);
   227         return *this;
   228     }
   230     Heap<T> &operator=(const Heap<T>& other) {
   231         set(other.get());
   232         return *this;
   233     }
   235     void set(T newPtr) {
   236         MOZ_ASSERT(!js::GCMethods<T>::poisoned(newPtr));
   237         if (js::GCMethods<T>::needsPostBarrier(newPtr)) {
   238             ptr = newPtr;
   239             post();
   240         } else if (js::GCMethods<T>::needsPostBarrier(ptr)) {
   241             relocate();  /* Called before overwriting ptr. */
   242             ptr = newPtr;
   243         } else {
   244             ptr = newPtr;
   245         }
   246     }
   248     /*
   249      * Set the pointer to a value which will cause a crash if it is
   250      * dereferenced.
   251      */
   252     void setToCrashOnTouch() {
   253         ptr = reinterpret_cast<T>(crashOnTouchPointer);
   254     }
   256     bool isSetToCrashOnTouch() {
   257         return ptr == crashOnTouchPointer;
   258     }
   260   private:
   261     void init(T newPtr) {
   262         MOZ_ASSERT(!js::GCMethods<T>::poisoned(newPtr));
   263         ptr = newPtr;
   264         if (js::GCMethods<T>::needsPostBarrier(ptr))
   265             post();
   266     }
   268     void post() {
   269 #ifdef JSGC_GENERATIONAL
   270         MOZ_ASSERT(js::GCMethods<T>::needsPostBarrier(ptr));
   271         js::GCMethods<T>::postBarrier(&ptr);
   272 #endif
   273     }
   275     void relocate() {
   276 #ifdef JSGC_GENERATIONAL
   277         js::GCMethods<T>::relocate(&ptr);
   278 #endif
   279     }
   281     enum {
   282         crashOnTouchPointer = 1
   283     };
   285     T ptr;
   286 };
   288 #ifdef JS_DEBUG
   289 /*
   290  * For generational GC, assert that an object is in the tenured generation as
   291  * opposed to being in the nursery.
   292  */
   293 extern JS_FRIEND_API(void)
   294 AssertGCThingMustBeTenured(JSObject* obj);
   295 #else
   296 inline void
   297 AssertGCThingMustBeTenured(JSObject *obj) {}
   298 #endif
   300 /*
   301  * The TenuredHeap<T> class is similar to the Heap<T> class above in that it
   302  * encapsulates the GC concerns of an on-heap reference to a JS object. However,
   303  * it has two important differences:
   304  *
   305  *  1) Pointers which are statically known to only reference "tenured" objects
   306  *     can avoid the extra overhead of SpiderMonkey's write barriers.
   307  *
   308  *  2) Objects in the "tenured" heap have stronger alignment restrictions than
   309  *     those in the "nursery", so it is possible to store flags in the lower
   310  *     bits of pointers known to be tenured. TenuredHeap wraps a normal tagged
   311  *     pointer with a nice API for accessing the flag bits and adds various
   312  *     assertions to ensure that it is not mis-used.
   313  *
   314  * GC things are said to be "tenured" when they are located in the long-lived
   315  * heap: e.g. they have gained tenure as an object by surviving past at least
   316  * one GC. For performance, SpiderMonkey allocates some things which are known
   317  * to normally be long lived directly into the tenured generation; for example,
   318  * global objects. Additionally, SpiderMonkey does not visit individual objects
   319  * when deleting non-tenured objects, so object with finalizers are also always
   320  * tenured; for instance, this includes most DOM objects.
   321  *
   322  * The considerations to keep in mind when using a TenuredHeap<T> vs a normal
   323  * Heap<T> are:
   324  *
   325  *  - It is invalid for a TenuredHeap<T> to refer to a non-tenured thing.
   326  *  - It is however valid for a Heap<T> to refer to a tenured thing.
   327  *  - It is not possible to store flag bits in a Heap<T>.
   328  */
   329 template <typename T>
   330 class TenuredHeap : public js::HeapBase<T>
   331 {
   332   public:
   333     TenuredHeap() : bits(0) {
   334         static_assert(sizeof(T) == sizeof(TenuredHeap<T>),
   335                       "TenuredHeap<T> must be binary compatible with T.");
   336     }
   337     explicit TenuredHeap(T p) : bits(0) { setPtr(p); }
   338     explicit TenuredHeap(const TenuredHeap<T> &p) : bits(0) { setPtr(p.getPtr()); }
   340     bool operator==(const TenuredHeap<T> &other) { return bits == other.bits; }
   341     bool operator!=(const TenuredHeap<T> &other) { return bits != other.bits; }
   343     void setPtr(T newPtr) {
   344         MOZ_ASSERT((reinterpret_cast<uintptr_t>(newPtr) & flagsMask) == 0);
   345         MOZ_ASSERT(!js::GCMethods<T>::poisoned(newPtr));
   346         if (newPtr)
   347             AssertGCThingMustBeTenured(newPtr);
   348         bits = (bits & flagsMask) | reinterpret_cast<uintptr_t>(newPtr);
   349     }
   351     void setFlags(uintptr_t flagsToSet) {
   352         MOZ_ASSERT((flagsToSet & ~flagsMask) == 0);
   353         bits |= flagsToSet;
   354     }
   356     void unsetFlags(uintptr_t flagsToUnset) {
   357         MOZ_ASSERT((flagsToUnset & ~flagsMask) == 0);
   358         bits &= ~flagsToUnset;
   359     }
   361     bool hasFlag(uintptr_t flag) const {
   362         MOZ_ASSERT((flag & ~flagsMask) == 0);
   363         return (bits & flag) != 0;
   364     }
   366     T getPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); }
   367     uintptr_t getFlags() const { return bits & flagsMask; }
   369     operator T() const { return getPtr(); }
   370     T operator->() const { return getPtr(); }
   372     TenuredHeap<T> &operator=(T p) {
   373         setPtr(p);
   374         return *this;
   375     }
   377     TenuredHeap<T> &operator=(const TenuredHeap<T>& other) {
   378         bits = other.bits;
   379         return *this;
   380     }
   382   private:
   383     enum {
   384         maskBits = 3,
   385         flagsMask = (1 << maskBits) - 1,
   386     };
   388     uintptr_t bits;
   389 };
   391 /*
   392  * Reference to a T that has been rooted elsewhere. This is most useful
   393  * as a parameter type, which guarantees that the T lvalue is properly
   394  * rooted. See "Move GC Stack Rooting" above.
   395  *
   396  * If you want to add additional methods to Handle for a specific
   397  * specialization, define a HandleBase<T> specialization containing them.
   398  */
   399 template <typename T>
   400 class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
   401 {
   402     friend class JS::MutableHandle<T>;
   404   public:
   405     /* Creates a handle from a handle of a type convertible to T. */
   406     template <typename S>
   407     Handle(Handle<S> handle,
   408            typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
   409     {
   410         static_assert(sizeof(Handle<T>) == sizeof(T *),
   411                       "Handle must be binary compatible with T*.");
   412         ptr = reinterpret_cast<const T *>(handle.address());
   413     }
   415     /* Create a handle for a nullptr pointer. */
   416     Handle(js::NullPtr) {
   417         static_assert(mozilla::IsPointer<T>::value,
   418                       "js::NullPtr overload not valid for non-pointer types");
   419         ptr = reinterpret_cast<const T *>(&js::NullPtr::constNullValue);
   420     }
   422     /* Create a handle for a nullptr pointer. */
   423     Handle(JS::NullPtr) {
   424         static_assert(mozilla::IsPointer<T>::value,
   425                       "JS::NullPtr overload not valid for non-pointer types");
   426         ptr = reinterpret_cast<const T *>(&JS::NullPtr::constNullValue);
   427     }
   429     Handle(MutableHandle<T> handle) {
   430         ptr = handle.address();
   431     }
   433     /*
   434      * Take care when calling this method!
   435      *
   436      * This creates a Handle from the raw location of a T.
   437      *
   438      * It should be called only if the following conditions hold:
   439      *
   440      *  1) the location of the T is guaranteed to be marked (for some reason
   441      *     other than being a Rooted), e.g., if it is guaranteed to be reachable
   442      *     from an implicit root.
   443      *
   444      *  2) the contents of the location are immutable, or at least cannot change
   445      *     for the lifetime of the handle, as its users may not expect its value
   446      *     to change underneath them.
   447      */
   448     static MOZ_CONSTEXPR Handle fromMarkedLocation(const T *p) {
   449         return Handle(p, DeliberatelyChoosingThisOverload,
   450                       ImUsingThisOnlyInFromFromMarkedLocation);
   451     }
   453     /*
   454      * Construct a handle from an explicitly rooted location. This is the
   455      * normal way to create a handle, and normally happens implicitly.
   456      */
   457     template <typename S>
   458     inline
   459     Handle(const Rooted<S> &root,
   460            typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
   462     template <typename S>
   463     inline
   464     Handle(const PersistentRooted<S> &root,
   465            typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
   467     /* Construct a read only handle from a mutable handle. */
   468     template <typename S>
   469     inline
   470     Handle(MutableHandle<S> &root,
   471            typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
   473     const T *address() const { return ptr; }
   474     const T& get() const { return *ptr; }
   476     /*
   477      * Return a reference so passing a Handle<T> to something that
   478      * takes a |const T&| is not a GC hazard.
   479      */
   480     operator const T&() const { return get(); }
   481     T operator->() const { return get(); }
   483     bool operator!=(const T &other) const { return *ptr != other; }
   484     bool operator==(const T &other) const { return *ptr == other; }
   486     /* Change this handle to point to the same rooted location RHS does. */
   487     void repoint(const Handle &rhs) { ptr = rhs.address(); }
   489   private:
   490     Handle() {}
   492     enum Disambiguator { DeliberatelyChoosingThisOverload = 42 };
   493     enum CallerIdentity { ImUsingThisOnlyInFromFromMarkedLocation = 17 };
   494     MOZ_CONSTEXPR Handle(const T *p, Disambiguator, CallerIdentity) : ptr(p) {}
   496     const T *ptr;
   498     template <typename S> void operator=(S) MOZ_DELETE;
   499     void operator=(Handle) MOZ_DELETE;
   500 };
   502 /*
   503  * Similar to a handle, but the underlying storage can be changed. This is
   504  * useful for outparams.
   505  *
   506  * If you want to add additional methods to MutableHandle for a specific
   507  * specialization, define a MutableHandleBase<T> specialization containing
   508  * them.
   509  */
   510 template <typename T>
   511 class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T>
   512 {
   513   public:
   514     inline MutableHandle(Rooted<T> *root);
   515     inline MutableHandle(PersistentRooted<T> *root);
   517   private:
   518     // Disallow true nullptr and emulated nullptr (gcc 4.4/4.5, __null, appears
   519     // as int/long [32/64-bit]) for overloading purposes.
   520     template<typename N>
   521     MutableHandle(N,
   522                   typename mozilla::EnableIf<mozilla::IsNullPointer<N>::value ||
   523                                              mozilla::IsSame<N, int>::value ||
   524                                              mozilla::IsSame<N, long>::value,
   525                                              int>::Type dummy = 0)
   526     MOZ_DELETE;
   528   public:
   529     void set(T v) {
   530         MOZ_ASSERT(!js::GCMethods<T>::poisoned(v));
   531         *ptr = v;
   532     }
   534     /*
   535      * This may be called only if the location of the T is guaranteed
   536      * to be marked (for some reason other than being a Rooted),
   537      * e.g., if it is guaranteed to be reachable from an implicit root.
   538      *
   539      * Create a MutableHandle from a raw location of a T.
   540      */
   541     static MutableHandle fromMarkedLocation(T *p) {
   542         MutableHandle h;
   543         h.ptr = p;
   544         return h;
   545     }
   547     T *address() const { return ptr; }
   548     const T& get() const { return *ptr; }
   550     /*
   551      * Return a reference so passing a MutableHandle<T> to something that takes
   552      * a |const T&| is not a GC hazard.
   553      */
   554     operator const T&() const { return get(); }
   555     T operator->() const { return get(); }
   557   private:
   558     MutableHandle() {}
   560     T *ptr;
   562     template <typename S> void operator=(S v) MOZ_DELETE;
   563     void operator=(MutableHandle other) MOZ_DELETE;
   564 };
   566 #ifdef JSGC_GENERATIONAL
   567 JS_FRIEND_API(void) HeapCellPostBarrier(js::gc::Cell **cellp);
   568 JS_FRIEND_API(void) HeapCellRelocate(js::gc::Cell **cellp);
   569 #endif
   571 } /* namespace JS */
   573 namespace js {
   575 /*
   576  * InternalHandle is a handle to an internal pointer into a gcthing. Use
   577  * InternalHandle when you have a pointer to a direct field of a gcthing, or
   578  * when you need a parameter type for something that *may* be a pointer to a
   579  * direct field of a gcthing.
   580  */
   581 template <typename T>
   582 class InternalHandle {};
   584 template <typename T>
   585 class InternalHandle<T*>
   586 {
   587     void * const *holder;
   588     size_t offset;
   590   public:
   591     /*
   592      * Create an InternalHandle using a Handle to the gcthing containing the
   593      * field in question, and a pointer to the field.
   594      */
   595     template<typename H>
   596     InternalHandle(const JS::Handle<H> &handle, T *field)
   597       : holder((void**)handle.address()), offset(uintptr_t(field) - uintptr_t(handle.get()))
   598     {}
   600     /*
   601      * Create an InternalHandle to a field within a Rooted<>.
   602      */
   603     template<typename R>
   604     InternalHandle(const JS::Rooted<R> &root, T *field)
   605       : holder((void**)root.address()), offset(uintptr_t(field) - uintptr_t(root.get()))
   606     {}
   608     InternalHandle(const InternalHandle<T*>& other)
   609       : holder(other.holder), offset(other.offset) {}
   611     T *get() const { return reinterpret_cast<T*>(uintptr_t(*holder) + offset); }
   613     const T &operator*() const { return *get(); }
   614     T *operator->() const { return get(); }
   616     static InternalHandle<T*> fromMarkedLocation(T *fieldPtr) {
   617         return InternalHandle(fieldPtr);
   618     }
   620   private:
   621     /*
   622      * Create an InternalHandle to something that is not a pointer to a
   623      * gcthing, and so does not need to be rooted in the first place. Use these
   624      * InternalHandles to pass pointers into functions that also need to accept
   625      * regular InternalHandles to gcthing fields.
   626      *
   627      * Make this private to prevent accidental misuse; this is only for
   628      * fromMarkedLocation().
   629      */
   630     InternalHandle(T *field)
   631       : holder(reinterpret_cast<void * const *>(&js::NullPtr::constNullValue)),
   632         offset(uintptr_t(field))
   633     {}
   635     void operator=(InternalHandle<T*> other) MOZ_DELETE;
   636 };
   638 /*
   639  * By default, pointers should use the inheritance hierarchy to find their
   640  * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
   641  * Rooted<T> may be used without the class definition being available.
   642  */
   643 template <typename T>
   644 struct RootKind<T *>
   645 {
   646     static ThingRootKind rootKind() { return T::rootKind(); }
   647 };
   649 template <typename T>
   650 struct GCMethods<T *>
   651 {
   652     static T *initial() { return nullptr; }
   653     static ThingRootKind kind() { return RootKind<T *>::rootKind(); }
   654     static bool poisoned(T *v) { return JS::IsPoisonedPtr(v); }
   655     static bool needsPostBarrier(T *v) { return false; }
   656 #ifdef JSGC_GENERATIONAL
   657     static void postBarrier(T **vp) {}
   658     static void relocate(T **vp) {}
   659 #endif
   660 };
   662 template <>
   663 struct GCMethods<JSObject *>
   664 {
   665     static JSObject *initial() { return nullptr; }
   666     static ThingRootKind kind() { return RootKind<JSObject *>::rootKind(); }
   667     static bool poisoned(JSObject *v) { return JS::IsPoisonedPtr(v); }
   668     static bool needsPostBarrier(JSObject *v) { return v; }
   669 #ifdef JSGC_GENERATIONAL
   670     static void postBarrier(JSObject **vp) {
   671         JS::HeapCellPostBarrier(reinterpret_cast<js::gc::Cell **>(vp));
   672     }
   673     static void relocate(JSObject **vp) {
   674         JS::HeapCellRelocate(reinterpret_cast<js::gc::Cell **>(vp));
   675     }
   676 #endif
   677 };
   679 template <>
   680 struct GCMethods<JSFunction *>
   681 {
   682     static JSFunction *initial() { return nullptr; }
   683     static ThingRootKind kind() { return RootKind<JSObject *>::rootKind(); }
   684     static bool poisoned(JSFunction *v) { return JS::IsPoisonedPtr(v); }
   685     static bool needsPostBarrier(JSFunction *v) { return v; }
   686 #ifdef JSGC_GENERATIONAL
   687     static void postBarrier(JSFunction **vp) {
   688         JS::HeapCellPostBarrier(reinterpret_cast<js::gc::Cell **>(vp));
   689     }
   690     static void relocate(JSFunction **vp) {
   691         JS::HeapCellRelocate(reinterpret_cast<js::gc::Cell **>(vp));
   692     }
   693 #endif
   694 };
   696 #ifdef JS_DEBUG
   697 /* This helper allows us to assert that Rooted<T> is scoped within a request. */
   698 extern JS_PUBLIC_API(bool)
   699 IsInRequest(JSContext *cx);
   700 #endif
   702 } /* namespace js */
   704 namespace JS {
   706 /*
   707  * Local variable of type T whose value is always rooted. This is typically
   708  * used for local variables, or for non-rooted values being passed to a
   709  * function that requires a handle, e.g. Foo(Root<T>(cx, x)).
   710  *
   711  * If you want to add additional methods to Rooted for a specific
   712  * specialization, define a RootedBase<T> specialization containing them.
   713  */
   714 template <typename T>
   715 class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
   716 {
   717     /* Note: CX is a subclass of either ContextFriendFields or PerThreadDataFriendFields. */
   718     template <typename CX>
   719     void init(CX *cx) {
   720 #ifdef JSGC_TRACK_EXACT_ROOTS
   721         js::ThingRootKind kind = js::GCMethods<T>::kind();
   722         this->stack = &cx->thingGCRooters[kind];
   723         this->prev = *stack;
   724         *stack = reinterpret_cast<Rooted<void*>*>(this);
   726         MOZ_ASSERT(!js::GCMethods<T>::poisoned(ptr));
   727 #endif
   728     }
   730   public:
   731     Rooted(JSContext *cx
   732            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   733       : ptr(js::GCMethods<T>::initial())
   734     {
   735         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   736 #ifdef JS_DEBUG
   737         MOZ_ASSERT(js::IsInRequest(cx));
   738 #endif
   739         init(js::ContextFriendFields::get(cx));
   740     }
   742     Rooted(JSContext *cx, T initial
   743            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   744       : ptr(initial)
   745     {
   746         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   747 #ifdef JS_DEBUG
   748         MOZ_ASSERT(js::IsInRequest(cx));
   749 #endif
   750         init(js::ContextFriendFields::get(cx));
   751     }
   753     Rooted(js::ContextFriendFields *cx
   754            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   755       : ptr(js::GCMethods<T>::initial())
   756     {
   757         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   758         init(cx);
   759     }
   761     Rooted(js::ContextFriendFields *cx, T initial
   762            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   763       : ptr(initial)
   764     {
   765         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   766         init(cx);
   767     }
   769     Rooted(js::PerThreadDataFriendFields *pt
   770            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   771       : ptr(js::GCMethods<T>::initial())
   772     {
   773         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   774         init(pt);
   775     }
   777     Rooted(js::PerThreadDataFriendFields *pt, T initial
   778            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   779       : ptr(initial)
   780     {
   781         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   782         init(pt);
   783     }
   785     Rooted(JSRuntime *rt
   786            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   787       : ptr(js::GCMethods<T>::initial())
   788     {
   789         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   790         init(js::PerThreadDataFriendFields::getMainThread(rt));
   791     }
   793     Rooted(JSRuntime *rt, T initial
   794            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   795       : ptr(initial)
   796     {
   797         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   798         init(js::PerThreadDataFriendFields::getMainThread(rt));
   799     }
   801     // Note that we need to let the compiler generate the default destructor in
   802     // non-exact-rooting builds because of a bug in the instrumented PGO builds
   803     // using MSVC, see bug 915735 for more details.
   804 #ifdef JSGC_TRACK_EXACT_ROOTS
   805     ~Rooted() {
   806         MOZ_ASSERT(*stack == reinterpret_cast<Rooted<void*>*>(this));
   807         *stack = prev;
   808     }
   809 #endif
   811 #ifdef JSGC_TRACK_EXACT_ROOTS
   812     Rooted<T> *previous() { return prev; }
   813 #endif
   815     /*
   816      * Important: Return a reference here so passing a Rooted<T> to
   817      * something that takes a |const T&| is not a GC hazard.
   818      */
   819     operator const T&() const { return ptr; }
   820     T operator->() const { return ptr; }
   821     T *address() { return &ptr; }
   822     const T *address() const { return &ptr; }
   823     T &get() { return ptr; }
   824     const T &get() const { return ptr; }
   826     T &operator=(T value) {
   827         MOZ_ASSERT(!js::GCMethods<T>::poisoned(value));
   828         ptr = value;
   829         return ptr;
   830     }
   832     T &operator=(const Rooted &value) {
   833         ptr = value;
   834         return ptr;
   835     }
   837     void set(T value) {
   838         MOZ_ASSERT(!js::GCMethods<T>::poisoned(value));
   839         ptr = value;
   840     }
   842     bool operator!=(const T &other) const { return ptr != other; }
   843     bool operator==(const T &other) const { return ptr == other; }
   845   private:
   846 #ifdef JSGC_TRACK_EXACT_ROOTS
   847     Rooted<void*> **stack, *prev;
   848 #endif
   850     /*
   851      * |ptr| must be the last field in Rooted because the analysis treats all
   852      * Rooted as Rooted<void*> during the analysis. See bug 829372.
   853      */
   854     T ptr;
   856     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   858     Rooted(const Rooted &) MOZ_DELETE;
   859 };
   861 } /* namespace JS */
   863 namespace js {
   865 /*
   866  * Augment the generic Rooted<T> interface when T = JSObject* with
   867  * class-querying and downcasting operations.
   868  *
   869  * Given a Rooted<JSObject*> obj, one can view
   870  *   Handle<StringObject*> h = obj.as<StringObject*>();
   871  * as an optimization of
   872  *   Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>());
   873  *   Handle<StringObject*> h = rooted;
   874  */
   875 template <>
   876 class RootedBase<JSObject*>
   877 {
   878   public:
   879     template <class U>
   880     JS::Handle<U*> as() const;
   881 };
   884 /*
   885  * RootedGeneric<T> allows a class to instantiate its own Rooted type by
   886  * including the following two methods:
   887  *
   888  *    static inline js::ThingRootKind rootKind() { return js::THING_ROOT_CUSTOM; }
   889  *    void trace(JSTracer *trc);
   890  *
   891  * The trace() method must trace all of the class's fields.
   892  *
   893  * Implementation:
   894  *
   895  * RootedGeneric<T> works by placing a pointer to its 'rooter' field into the
   896  * usual list of rooters when it is instantiated. When marking, it backs up
   897  * from this pointer to find a vtable containing a type-appropriate trace()
   898  * method.
   899  */
   900 template <typename GCType>
   901 class JS_PUBLIC_API(RootedGeneric)
   902 {
   903   public:
   904     JS::Rooted<GCType> rooter;
   906     RootedGeneric(js::ContextFriendFields *cx)
   907         : rooter(cx)
   908     {
   909     }
   911     RootedGeneric(js::ContextFriendFields *cx, const GCType &initial)
   912         : rooter(cx, initial)
   913     {
   914     }
   916     virtual inline void trace(JSTracer *trc);
   918     operator const GCType&() const { return rooter.get(); }
   919     GCType operator->() const { return rooter.get(); }
   920 };
   922 template <typename GCType>
   923 inline void RootedGeneric<GCType>::trace(JSTracer *trc)
   924 {
   925     rooter->trace(trc);
   926 }
   928 // We will instantiate RootedGeneric<void*> in RootMarking.cpp, and MSVC will
   929 // notice that void*s have no trace() method defined on them and complain (even
   930 // though it's never called.) MSVC's complaint is not unreasonable, so
   931 // specialize for void*.
   932 template <>
   933 inline void RootedGeneric<void*>::trace(JSTracer *trc)
   934 {
   935     MOZ_ASSUME_UNREACHABLE("RootedGeneric<void*>::trace()");
   936 }
   938 /* Interface substitute for Rooted<T> which does not root the variable's memory. */
   939 template <typename T>
   940 class FakeRooted : public RootedBase<T>
   941 {
   942   public:
   943     template <typename CX>
   944     FakeRooted(CX *cx
   945                MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   946       : ptr(GCMethods<T>::initial())
   947     {
   948         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   949     }
   951     template <typename CX>
   952     FakeRooted(CX *cx, T initial
   953                MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
   954       : ptr(initial)
   955     {
   956         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   957     }
   959     operator T() const { return ptr; }
   960     T operator->() const { return ptr; }
   961     T *address() { return &ptr; }
   962     const T *address() const { return &ptr; }
   963     T &get() { return ptr; }
   964     const T &get() const { return ptr; }
   966     FakeRooted<T> &operator=(T value) {
   967         MOZ_ASSERT(!GCMethods<T>::poisoned(value));
   968         ptr = value;
   969         return *this;
   970     }
   972     FakeRooted<T> &operator=(const FakeRooted<T> &other) {
   973         MOZ_ASSERT(!GCMethods<T>::poisoned(other.ptr));
   974         ptr = other.ptr;
   975         return *this;
   976     }
   978     bool operator!=(const T &other) const { return ptr != other; }
   979     bool operator==(const T &other) const { return ptr == other; }
   981   private:
   982     T ptr;
   984     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   986     FakeRooted(const FakeRooted &) MOZ_DELETE;
   987 };
   989 /* Interface substitute for MutableHandle<T> which is not required to point to rooted memory. */
   990 template <typename T>
   991 class FakeMutableHandle : public js::MutableHandleBase<T>
   992 {
   993   public:
   994     FakeMutableHandle(T *t) {
   995         ptr = t;
   996     }
   998     FakeMutableHandle(FakeRooted<T> *root) {
   999         ptr = root->address();
  1002     void set(T v) {
  1003         MOZ_ASSERT(!js::GCMethods<T>::poisoned(v));
  1004         *ptr = v;
  1007     T *address() const { return ptr; }
  1008     T get() const { return *ptr; }
  1010     operator T() const { return get(); }
  1011     T operator->() const { return get(); }
  1013   private:
  1014     FakeMutableHandle() {}
  1016     T *ptr;
  1018     template <typename S>
  1019     void operator=(S v) MOZ_DELETE;
  1021     void operator=(const FakeMutableHandle<T>& other) MOZ_DELETE;
  1022 };
  1024 /*
  1025  * Types for a variable that either should or shouldn't be rooted, depending on
  1026  * the template parameter allowGC. Used for implementing functions that can
  1027  * operate on either rooted or unrooted data.
  1029  * The toHandle() and toMutableHandle() functions are for calling functions
  1030  * which require handle types and are only called in the CanGC case. These
  1031  * allow the calling code to type check.
  1032  */
  1033 enum AllowGC {
  1034     NoGC = 0,
  1035     CanGC = 1
  1036 };
  1037 template <typename T, AllowGC allowGC>
  1038 class MaybeRooted
  1040 };
  1042 template <typename T> class MaybeRooted<T, CanGC>
  1044   public:
  1045     typedef JS::Handle<T> HandleType;
  1046     typedef JS::Rooted<T> RootType;
  1047     typedef JS::MutableHandle<T> MutableHandleType;
  1049     static inline JS::Handle<T> toHandle(HandleType v) {
  1050         return v;
  1053     static inline JS::MutableHandle<T> toMutableHandle(MutableHandleType v) {
  1054         return v;
  1056 };
  1058 template <typename T> class MaybeRooted<T, NoGC>
  1060   public:
  1061     typedef T HandleType;
  1062     typedef FakeRooted<T> RootType;
  1063     typedef FakeMutableHandle<T> MutableHandleType;
  1065     static inline JS::Handle<T> toHandle(HandleType v) {
  1066         MOZ_ASSUME_UNREACHABLE("Bad conversion");
  1069     static inline JS::MutableHandle<T> toMutableHandle(MutableHandleType v) {
  1070         MOZ_ASSUME_UNREACHABLE("Bad conversion");
  1072 };
  1074 } /* namespace js */
  1076 namespace JS {
  1078 template <typename T> template <typename S>
  1079 inline
  1080 Handle<T>::Handle(const Rooted<S> &root,
  1081                   typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
  1083     ptr = reinterpret_cast<const T *>(root.address());
  1086 template <typename T> template <typename S>
  1087 inline
  1088 Handle<T>::Handle(const PersistentRooted<S> &root,
  1089                   typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
  1091     ptr = reinterpret_cast<const T *>(root.address());
  1094 template <typename T> template <typename S>
  1095 inline
  1096 Handle<T>::Handle(MutableHandle<S> &root,
  1097                   typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
  1099     ptr = reinterpret_cast<const T *>(root.address());
  1102 template <typename T>
  1103 inline
  1104 MutableHandle<T>::MutableHandle(Rooted<T> *root)
  1106     static_assert(sizeof(MutableHandle<T>) == sizeof(T *),
  1107                   "MutableHandle must be binary compatible with T*.");
  1108     ptr = root->address();
  1111 template <typename T>
  1112 inline
  1113 MutableHandle<T>::MutableHandle(PersistentRooted<T> *root)
  1115     static_assert(sizeof(MutableHandle<T>) == sizeof(T *),
  1116                   "MutableHandle must be binary compatible with T*.");
  1117     ptr = root->address();
  1120 /*
  1121  * A copyable, assignable global GC root type with arbitrary lifetime, an
  1122  * infallible constructor, and automatic unrooting on destruction.
  1124  * These roots can be used in heap-allocated data structures, so they are not
  1125  * associated with any particular JSContext or stack. They are registered with
  1126  * the JSRuntime itself, without locking, so they require a full JSContext to be
  1127  * constructed, not one of its more restricted superclasses.
  1129  * Note that you must not use an PersistentRooted in an object owned by a JS
  1130  * object:
  1132  * Whenever one object whose lifetime is decided by the GC refers to another
  1133  * such object, that edge must be traced only if the owning JS object is traced.
  1134  * This applies not only to JS objects (which obviously are managed by the GC)
  1135  * but also to C++ objects owned by JS objects.
  1137  * If you put a PersistentRooted in such a C++ object, that is almost certainly
  1138  * a leak. When a GC begins, the referent of the PersistentRooted is treated as
  1139  * live, unconditionally (because a PersistentRooted is a *root*), even if the
  1140  * JS object that owns it is unreachable. If there is any path from that
  1141  * referent back to the JS object, then the C++ object containing the
  1142  * PersistentRooted will not be destructed, and the whole blob of objects will
  1143  * not be freed, even if there are no references to them from the outside.
  1145  * In the context of Firefox, this is a severe restriction: almost everything in
  1146  * Firefox is owned by some JS object or another, so using PersistentRooted in
  1147  * such objects would introduce leaks. For these kinds of edges, Heap<T> or
  1148  * TenuredHeap<T> would be better types. It's up to the implementor of the type
  1149  * containing Heap<T> or TenuredHeap<T> members to make sure their referents get
  1150  * marked when the object itself is marked.
  1151  */
  1152 template<typename T>
  1153 class PersistentRooted : private mozilla::LinkedListElement<PersistentRooted<T> > {
  1154     friend class mozilla::LinkedList<PersistentRooted>;
  1155     friend class mozilla::LinkedListElement<PersistentRooted>;
  1157     friend class js::gc::PersistentRootedMarker<T>;
  1159     void registerWithRuntime(JSRuntime *rt) {
  1160         JS::shadow::Runtime *srt = JS::shadow::Runtime::asShadowRuntime(rt);
  1161         srt->getPersistentRootedList<T>().insertBack(this);
  1164   public:
  1165     PersistentRooted(JSContext *cx) : ptr(js::GCMethods<T>::initial())
  1167         registerWithRuntime(js::GetRuntime(cx));
  1170     PersistentRooted(JSContext *cx, T initial) : ptr(initial)
  1172         registerWithRuntime(js::GetRuntime(cx));
  1175     PersistentRooted(JSRuntime *rt) : ptr(js::GCMethods<T>::initial())
  1177         registerWithRuntime(rt);
  1180     PersistentRooted(JSRuntime *rt, T initial) : ptr(initial)
  1182         registerWithRuntime(rt);
  1185     PersistentRooted(PersistentRooted &rhs) : ptr(rhs.ptr)
  1187         /*
  1188          * Copy construction takes advantage of the fact that the original
  1189          * is already inserted, and simply adds itself to whatever list the
  1190          * original was on - no JSRuntime pointer needed.
  1191          */
  1192         rhs.setNext(this);
  1195     /*
  1196      * Important: Return a reference here so passing a Rooted<T> to
  1197      * something that takes a |const T&| is not a GC hazard.
  1198      */
  1199     operator const T&() const { return ptr; }
  1200     T operator->() const { return ptr; }
  1201     T *address() { return &ptr; }
  1202     const T *address() const { return &ptr; }
  1203     T &get() { return ptr; }
  1204     const T &get() const { return ptr; }
  1206     T &operator=(T value) {
  1207         MOZ_ASSERT(!js::GCMethods<T>::poisoned(value));
  1208         ptr = value;
  1209         return ptr;
  1212     T &operator=(const PersistentRooted &value) {
  1213         ptr = value;
  1214         return ptr;
  1217     void set(T value) {
  1218         MOZ_ASSERT(!js::GCMethods<T>::poisoned(value));
  1219         ptr = value;
  1222     bool operator!=(const T &other) const { return ptr != other; }
  1223     bool operator==(const T &other) const { return ptr == other; }
  1225   private:
  1226     T ptr;
  1227 };
  1229 } /* namespace JS */
  1231 namespace js {
  1233 /* Base class for automatic read-only object rooting during compilation. */
  1234 class CompilerRootNode
  1236   protected:
  1237     CompilerRootNode(js::gc::Cell *ptr) : next(nullptr), ptr_(ptr) {}
  1239   public:
  1240     void **address() { return (void **)&ptr_; }
  1242   public:
  1243     CompilerRootNode *next;
  1245   protected:
  1246     js::gc::Cell *ptr_;
  1247 };
  1249 }  /* namespace js */
  1251 #endif  /* js_RootingAPI_h */

mercurial