1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/public/RootingAPI.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1251 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef js_RootingAPI_h 1.11 +#define js_RootingAPI_h 1.12 + 1.13 +#include "mozilla/Attributes.h" 1.14 +#include "mozilla/GuardObjects.h" 1.15 +#include "mozilla/LinkedList.h" 1.16 +#include "mozilla/NullPtr.h" 1.17 +#include "mozilla/TypeTraits.h" 1.18 + 1.19 +#include "jspubtd.h" 1.20 + 1.21 +#include "js/TypeDecls.h" 1.22 +#include "js/Utility.h" 1.23 + 1.24 +/* 1.25 + * Moving GC Stack Rooting 1.26 + * 1.27 + * A moving GC may change the physical location of GC allocated things, even 1.28 + * when they are rooted, updating all pointers to the thing to refer to its new 1.29 + * location. The GC must therefore know about all live pointers to a thing, 1.30 + * not just one of them, in order to behave correctly. 1.31 + * 1.32 + * The |Rooted| and |Handle| classes below are used to root stack locations 1.33 + * whose value may be held live across a call that can trigger GC. For a 1.34 + * code fragment such as: 1.35 + * 1.36 + * JSObject *obj = NewObject(cx); 1.37 + * DoSomething(cx); 1.38 + * ... = obj->lastProperty(); 1.39 + * 1.40 + * If |DoSomething()| can trigger a GC, the stack location of |obj| must be 1.41 + * rooted to ensure that the GC does not move the JSObject referred to by 1.42 + * |obj| without updating |obj|'s location itself. This rooting must happen 1.43 + * regardless of whether there are other roots which ensure that the object 1.44 + * itself will not be collected. 1.45 + * 1.46 + * If |DoSomething()| cannot trigger a GC, and the same holds for all other 1.47 + * calls made between |obj|'s definitions and its last uses, then no rooting 1.48 + * is required. 1.49 + * 1.50 + * SpiderMonkey can trigger a GC at almost any time and in ways that are not 1.51 + * always clear. For example, the following innocuous-looking actions can 1.52 + * cause a GC: allocation of any new GC thing; JSObject::hasProperty; 1.53 + * JS_ReportError and friends; and ToNumber, among many others. The following 1.54 + * dangerous-looking actions cannot trigger a GC: js_malloc, cx->malloc_, 1.55 + * rt->malloc_, and friends and JS_ReportOutOfMemory. 1.56 + * 1.57 + * The following family of three classes will exactly root a stack location. 1.58 + * Incorrect usage of these classes will result in a compile error in almost 1.59 + * all cases. Therefore, it is very hard to be incorrectly rooted if you use 1.60 + * these classes exclusively. These classes are all templated on the type T of 1.61 + * the value being rooted. 1.62 + * 1.63 + * - Rooted<T> declares a variable of type T, whose value is always rooted. 1.64 + * Rooted<T> may be automatically coerced to a Handle<T>, below. Rooted<T> 1.65 + * should be used whenever a local variable's value may be held live across a 1.66 + * call which can trigger a GC. 1.67 + * 1.68 + * - Handle<T> is a const reference to a Rooted<T>. Functions which take GC 1.69 + * things or values as arguments and need to root those arguments should 1.70 + * generally use handles for those arguments and avoid any explicit rooting. 1.71 + * This has two benefits. First, when several such functions call each other 1.72 + * then redundant rooting of multiple copies of the GC thing can be avoided. 1.73 + * Second, if the caller does not pass a rooted value a compile error will be 1.74 + * generated, which is quicker and easier to fix than when relying on a 1.75 + * separate rooting analysis. 1.76 + * 1.77 + * - MutableHandle<T> is a non-const reference to Rooted<T>. It is used in the 1.78 + * same way as Handle<T> and includes a |set(const T &v)| method to allow 1.79 + * updating the value of the referenced Rooted<T>. A MutableHandle<T> can be 1.80 + * created from a Rooted<T> by using |Rooted<T>::operator&()|. 1.81 + * 1.82 + * In some cases the small performance overhead of exact rooting (measured to 1.83 + * be a few nanoseconds on desktop) is too much. In these cases, try the 1.84 + * following: 1.85 + * 1.86 + * - Move all Rooted<T> above inner loops: this allows you to re-use the root 1.87 + * on each iteration of the loop. 1.88 + * 1.89 + * - Pass Handle<T> through your hot call stack to avoid re-rooting costs at 1.90 + * every invocation. 1.91 + * 1.92 + * The following diagram explains the list of supported, implicit type 1.93 + * conversions between classes of this family: 1.94 + * 1.95 + * Rooted<T> ----> Handle<T> 1.96 + * | ^ 1.97 + * | | 1.98 + * | | 1.99 + * +---> MutableHandle<T> 1.100 + * (via &) 1.101 + * 1.102 + * All of these types have an implicit conversion to raw pointers. 1.103 + */ 1.104 + 1.105 +namespace js { 1.106 + 1.107 +class ScriptSourceObject; 1.108 + 1.109 +template <typename T> 1.110 +struct GCMethods {}; 1.111 + 1.112 +template <typename T> 1.113 +class RootedBase {}; 1.114 + 1.115 +template <typename T> 1.116 +class HandleBase {}; 1.117 + 1.118 +template <typename T> 1.119 +class MutableHandleBase {}; 1.120 + 1.121 +template <typename T> 1.122 +class HeapBase {}; 1.123 + 1.124 +/* 1.125 + * js::NullPtr acts like a nullptr pointer in contexts that require a Handle. 1.126 + * 1.127 + * Handle provides an implicit constructor for js::NullPtr so that, given: 1.128 + * foo(Handle<JSObject*> h); 1.129 + * callers can simply write: 1.130 + * foo(js::NullPtr()); 1.131 + * which avoids creating a Rooted<JSObject*> just to pass nullptr. 1.132 + * 1.133 + * This is the SpiderMonkey internal variant. js::NullPtr should be used in 1.134 + * preference to JS::NullPtr to avoid the GOT access required for JS_PUBLIC_API 1.135 + * symbols. 1.136 + */ 1.137 +struct NullPtr 1.138 +{ 1.139 + static void * const constNullValue; 1.140 +}; 1.141 + 1.142 +namespace gc { 1.143 +struct Cell; 1.144 +template<typename T> 1.145 +struct PersistentRootedMarker; 1.146 +} /* namespace gc */ 1.147 + 1.148 +} /* namespace js */ 1.149 + 1.150 +namespace JS { 1.151 + 1.152 +template <typename T> class Rooted; 1.153 +template <typename T> class PersistentRooted; 1.154 + 1.155 +/* This is exposing internal state of the GC for inlining purposes. */ 1.156 +JS_FRIEND_API(bool) isGCEnabled(); 1.157 + 1.158 +/* 1.159 + * JS::NullPtr acts like a nullptr pointer in contexts that require a Handle. 1.160 + * 1.161 + * Handle provides an implicit constructor for JS::NullPtr so that, given: 1.162 + * foo(Handle<JSObject*> h); 1.163 + * callers can simply write: 1.164 + * foo(JS::NullPtr()); 1.165 + * which avoids creating a Rooted<JSObject*> just to pass nullptr. 1.166 + */ 1.167 +struct JS_PUBLIC_API(NullPtr) 1.168 +{ 1.169 + static void * const constNullValue; 1.170 +}; 1.171 + 1.172 +/* 1.173 + * The Heap<T> class is a heap-stored reference to a JS GC thing. All members of 1.174 + * heap classes that refer to GC things should use Heap<T> (or possibly 1.175 + * TenuredHeap<T>, described below). 1.176 + * 1.177 + * Heap<T> is an abstraction that hides some of the complexity required to 1.178 + * maintain GC invariants for the contained reference. It uses operator 1.179 + * overloading to provide a normal pointer interface, but notifies the GC every 1.180 + * time the value it contains is updated. This is necessary for generational GC, 1.181 + * which keeps track of all pointers into the nursery. 1.182 + * 1.183 + * Heap<T> instances must be traced when their containing object is traced to 1.184 + * keep the pointed-to GC thing alive. 1.185 + * 1.186 + * Heap<T> objects should only be used on the heap. GC references stored on the 1.187 + * C/C++ stack must use Rooted/Handle/MutableHandle instead. 1.188 + * 1.189 + * Type T must be one of: JS::Value, jsid, JSObject*, JSString*, JSScript* 1.190 + */ 1.191 +template <typename T> 1.192 +class Heap : public js::HeapBase<T> 1.193 +{ 1.194 + public: 1.195 + Heap() { 1.196 + static_assert(sizeof(T) == sizeof(Heap<T>), 1.197 + "Heap<T> must be binary compatible with T."); 1.198 + init(js::GCMethods<T>::initial()); 1.199 + } 1.200 + explicit Heap(T p) { init(p); } 1.201 + 1.202 + /* 1.203 + * For Heap, move semantics are equivalent to copy semantics. In C++, a 1.204 + * copy constructor taking const-ref is the way to get a single function 1.205 + * that will be used for both lvalue and rvalue copies, so we can simply 1.206 + * omit the rvalue variant. 1.207 + */ 1.208 + explicit Heap(const Heap<T> &p) { init(p.ptr); } 1.209 + 1.210 + ~Heap() { 1.211 + if (js::GCMethods<T>::needsPostBarrier(ptr)) 1.212 + relocate(); 1.213 + } 1.214 + 1.215 + bool operator==(const Heap<T> &other) { return ptr == other.ptr; } 1.216 + bool operator!=(const Heap<T> &other) { return ptr != other.ptr; } 1.217 + 1.218 + bool operator==(const T &other) const { return ptr == other; } 1.219 + bool operator!=(const T &other) const { return ptr != other; } 1.220 + 1.221 + operator T() const { return ptr; } 1.222 + T operator->() const { return ptr; } 1.223 + const T *address() const { return &ptr; } 1.224 + const T &get() const { return ptr; } 1.225 + 1.226 + T *unsafeGet() { return &ptr; } 1.227 + 1.228 + Heap<T> &operator=(T p) { 1.229 + set(p); 1.230 + return *this; 1.231 + } 1.232 + 1.233 + Heap<T> &operator=(const Heap<T>& other) { 1.234 + set(other.get()); 1.235 + return *this; 1.236 + } 1.237 + 1.238 + void set(T newPtr) { 1.239 + MOZ_ASSERT(!js::GCMethods<T>::poisoned(newPtr)); 1.240 + if (js::GCMethods<T>::needsPostBarrier(newPtr)) { 1.241 + ptr = newPtr; 1.242 + post(); 1.243 + } else if (js::GCMethods<T>::needsPostBarrier(ptr)) { 1.244 + relocate(); /* Called before overwriting ptr. */ 1.245 + ptr = newPtr; 1.246 + } else { 1.247 + ptr = newPtr; 1.248 + } 1.249 + } 1.250 + 1.251 + /* 1.252 + * Set the pointer to a value which will cause a crash if it is 1.253 + * dereferenced. 1.254 + */ 1.255 + void setToCrashOnTouch() { 1.256 + ptr = reinterpret_cast<T>(crashOnTouchPointer); 1.257 + } 1.258 + 1.259 + bool isSetToCrashOnTouch() { 1.260 + return ptr == crashOnTouchPointer; 1.261 + } 1.262 + 1.263 + private: 1.264 + void init(T newPtr) { 1.265 + MOZ_ASSERT(!js::GCMethods<T>::poisoned(newPtr)); 1.266 + ptr = newPtr; 1.267 + if (js::GCMethods<T>::needsPostBarrier(ptr)) 1.268 + post(); 1.269 + } 1.270 + 1.271 + void post() { 1.272 +#ifdef JSGC_GENERATIONAL 1.273 + MOZ_ASSERT(js::GCMethods<T>::needsPostBarrier(ptr)); 1.274 + js::GCMethods<T>::postBarrier(&ptr); 1.275 +#endif 1.276 + } 1.277 + 1.278 + void relocate() { 1.279 +#ifdef JSGC_GENERATIONAL 1.280 + js::GCMethods<T>::relocate(&ptr); 1.281 +#endif 1.282 + } 1.283 + 1.284 + enum { 1.285 + crashOnTouchPointer = 1 1.286 + }; 1.287 + 1.288 + T ptr; 1.289 +}; 1.290 + 1.291 +#ifdef JS_DEBUG 1.292 +/* 1.293 + * For generational GC, assert that an object is in the tenured generation as 1.294 + * opposed to being in the nursery. 1.295 + */ 1.296 +extern JS_FRIEND_API(void) 1.297 +AssertGCThingMustBeTenured(JSObject* obj); 1.298 +#else 1.299 +inline void 1.300 +AssertGCThingMustBeTenured(JSObject *obj) {} 1.301 +#endif 1.302 + 1.303 +/* 1.304 + * The TenuredHeap<T> class is similar to the Heap<T> class above in that it 1.305 + * encapsulates the GC concerns of an on-heap reference to a JS object. However, 1.306 + * it has two important differences: 1.307 + * 1.308 + * 1) Pointers which are statically known to only reference "tenured" objects 1.309 + * can avoid the extra overhead of SpiderMonkey's write barriers. 1.310 + * 1.311 + * 2) Objects in the "tenured" heap have stronger alignment restrictions than 1.312 + * those in the "nursery", so it is possible to store flags in the lower 1.313 + * bits of pointers known to be tenured. TenuredHeap wraps a normal tagged 1.314 + * pointer with a nice API for accessing the flag bits and adds various 1.315 + * assertions to ensure that it is not mis-used. 1.316 + * 1.317 + * GC things are said to be "tenured" when they are located in the long-lived 1.318 + * heap: e.g. they have gained tenure as an object by surviving past at least 1.319 + * one GC. For performance, SpiderMonkey allocates some things which are known 1.320 + * to normally be long lived directly into the tenured generation; for example, 1.321 + * global objects. Additionally, SpiderMonkey does not visit individual objects 1.322 + * when deleting non-tenured objects, so object with finalizers are also always 1.323 + * tenured; for instance, this includes most DOM objects. 1.324 + * 1.325 + * The considerations to keep in mind when using a TenuredHeap<T> vs a normal 1.326 + * Heap<T> are: 1.327 + * 1.328 + * - It is invalid for a TenuredHeap<T> to refer to a non-tenured thing. 1.329 + * - It is however valid for a Heap<T> to refer to a tenured thing. 1.330 + * - It is not possible to store flag bits in a Heap<T>. 1.331 + */ 1.332 +template <typename T> 1.333 +class TenuredHeap : public js::HeapBase<T> 1.334 +{ 1.335 + public: 1.336 + TenuredHeap() : bits(0) { 1.337 + static_assert(sizeof(T) == sizeof(TenuredHeap<T>), 1.338 + "TenuredHeap<T> must be binary compatible with T."); 1.339 + } 1.340 + explicit TenuredHeap(T p) : bits(0) { setPtr(p); } 1.341 + explicit TenuredHeap(const TenuredHeap<T> &p) : bits(0) { setPtr(p.getPtr()); } 1.342 + 1.343 + bool operator==(const TenuredHeap<T> &other) { return bits == other.bits; } 1.344 + bool operator!=(const TenuredHeap<T> &other) { return bits != other.bits; } 1.345 + 1.346 + void setPtr(T newPtr) { 1.347 + MOZ_ASSERT((reinterpret_cast<uintptr_t>(newPtr) & flagsMask) == 0); 1.348 + MOZ_ASSERT(!js::GCMethods<T>::poisoned(newPtr)); 1.349 + if (newPtr) 1.350 + AssertGCThingMustBeTenured(newPtr); 1.351 + bits = (bits & flagsMask) | reinterpret_cast<uintptr_t>(newPtr); 1.352 + } 1.353 + 1.354 + void setFlags(uintptr_t flagsToSet) { 1.355 + MOZ_ASSERT((flagsToSet & ~flagsMask) == 0); 1.356 + bits |= flagsToSet; 1.357 + } 1.358 + 1.359 + void unsetFlags(uintptr_t flagsToUnset) { 1.360 + MOZ_ASSERT((flagsToUnset & ~flagsMask) == 0); 1.361 + bits &= ~flagsToUnset; 1.362 + } 1.363 + 1.364 + bool hasFlag(uintptr_t flag) const { 1.365 + MOZ_ASSERT((flag & ~flagsMask) == 0); 1.366 + return (bits & flag) != 0; 1.367 + } 1.368 + 1.369 + T getPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); } 1.370 + uintptr_t getFlags() const { return bits & flagsMask; } 1.371 + 1.372 + operator T() const { return getPtr(); } 1.373 + T operator->() const { return getPtr(); } 1.374 + 1.375 + TenuredHeap<T> &operator=(T p) { 1.376 + setPtr(p); 1.377 + return *this; 1.378 + } 1.379 + 1.380 + TenuredHeap<T> &operator=(const TenuredHeap<T>& other) { 1.381 + bits = other.bits; 1.382 + return *this; 1.383 + } 1.384 + 1.385 + private: 1.386 + enum { 1.387 + maskBits = 3, 1.388 + flagsMask = (1 << maskBits) - 1, 1.389 + }; 1.390 + 1.391 + uintptr_t bits; 1.392 +}; 1.393 + 1.394 +/* 1.395 + * Reference to a T that has been rooted elsewhere. This is most useful 1.396 + * as a parameter type, which guarantees that the T lvalue is properly 1.397 + * rooted. See "Move GC Stack Rooting" above. 1.398 + * 1.399 + * If you want to add additional methods to Handle for a specific 1.400 + * specialization, define a HandleBase<T> specialization containing them. 1.401 + */ 1.402 +template <typename T> 1.403 +class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T> 1.404 +{ 1.405 + friend class JS::MutableHandle<T>; 1.406 + 1.407 + public: 1.408 + /* Creates a handle from a handle of a type convertible to T. */ 1.409 + template <typename S> 1.410 + Handle(Handle<S> handle, 1.411 + typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0) 1.412 + { 1.413 + static_assert(sizeof(Handle<T>) == sizeof(T *), 1.414 + "Handle must be binary compatible with T*."); 1.415 + ptr = reinterpret_cast<const T *>(handle.address()); 1.416 + } 1.417 + 1.418 + /* Create a handle for a nullptr pointer. */ 1.419 + Handle(js::NullPtr) { 1.420 + static_assert(mozilla::IsPointer<T>::value, 1.421 + "js::NullPtr overload not valid for non-pointer types"); 1.422 + ptr = reinterpret_cast<const T *>(&js::NullPtr::constNullValue); 1.423 + } 1.424 + 1.425 + /* Create a handle for a nullptr pointer. */ 1.426 + Handle(JS::NullPtr) { 1.427 + static_assert(mozilla::IsPointer<T>::value, 1.428 + "JS::NullPtr overload not valid for non-pointer types"); 1.429 + ptr = reinterpret_cast<const T *>(&JS::NullPtr::constNullValue); 1.430 + } 1.431 + 1.432 + Handle(MutableHandle<T> handle) { 1.433 + ptr = handle.address(); 1.434 + } 1.435 + 1.436 + /* 1.437 + * Take care when calling this method! 1.438 + * 1.439 + * This creates a Handle from the raw location of a T. 1.440 + * 1.441 + * It should be called only if the following conditions hold: 1.442 + * 1.443 + * 1) the location of the T is guaranteed to be marked (for some reason 1.444 + * other than being a Rooted), e.g., if it is guaranteed to be reachable 1.445 + * from an implicit root. 1.446 + * 1.447 + * 2) the contents of the location are immutable, or at least cannot change 1.448 + * for the lifetime of the handle, as its users may not expect its value 1.449 + * to change underneath them. 1.450 + */ 1.451 + static MOZ_CONSTEXPR Handle fromMarkedLocation(const T *p) { 1.452 + return Handle(p, DeliberatelyChoosingThisOverload, 1.453 + ImUsingThisOnlyInFromFromMarkedLocation); 1.454 + } 1.455 + 1.456 + /* 1.457 + * Construct a handle from an explicitly rooted location. This is the 1.458 + * normal way to create a handle, and normally happens implicitly. 1.459 + */ 1.460 + template <typename S> 1.461 + inline 1.462 + Handle(const Rooted<S> &root, 1.463 + typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0); 1.464 + 1.465 + template <typename S> 1.466 + inline 1.467 + Handle(const PersistentRooted<S> &root, 1.468 + typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0); 1.469 + 1.470 + /* Construct a read only handle from a mutable handle. */ 1.471 + template <typename S> 1.472 + inline 1.473 + Handle(MutableHandle<S> &root, 1.474 + typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0); 1.475 + 1.476 + const T *address() const { return ptr; } 1.477 + const T& get() const { return *ptr; } 1.478 + 1.479 + /* 1.480 + * Return a reference so passing a Handle<T> to something that 1.481 + * takes a |const T&| is not a GC hazard. 1.482 + */ 1.483 + operator const T&() const { return get(); } 1.484 + T operator->() const { return get(); } 1.485 + 1.486 + bool operator!=(const T &other) const { return *ptr != other; } 1.487 + bool operator==(const T &other) const { return *ptr == other; } 1.488 + 1.489 + /* Change this handle to point to the same rooted location RHS does. */ 1.490 + void repoint(const Handle &rhs) { ptr = rhs.address(); } 1.491 + 1.492 + private: 1.493 + Handle() {} 1.494 + 1.495 + enum Disambiguator { DeliberatelyChoosingThisOverload = 42 }; 1.496 + enum CallerIdentity { ImUsingThisOnlyInFromFromMarkedLocation = 17 }; 1.497 + MOZ_CONSTEXPR Handle(const T *p, Disambiguator, CallerIdentity) : ptr(p) {} 1.498 + 1.499 + const T *ptr; 1.500 + 1.501 + template <typename S> void operator=(S) MOZ_DELETE; 1.502 + void operator=(Handle) MOZ_DELETE; 1.503 +}; 1.504 + 1.505 +/* 1.506 + * Similar to a handle, but the underlying storage can be changed. This is 1.507 + * useful for outparams. 1.508 + * 1.509 + * If you want to add additional methods to MutableHandle for a specific 1.510 + * specialization, define a MutableHandleBase<T> specialization containing 1.511 + * them. 1.512 + */ 1.513 +template <typename T> 1.514 +class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T> 1.515 +{ 1.516 + public: 1.517 + inline MutableHandle(Rooted<T> *root); 1.518 + inline MutableHandle(PersistentRooted<T> *root); 1.519 + 1.520 + private: 1.521 + // Disallow true nullptr and emulated nullptr (gcc 4.4/4.5, __null, appears 1.522 + // as int/long [32/64-bit]) for overloading purposes. 1.523 + template<typename N> 1.524 + MutableHandle(N, 1.525 + typename mozilla::EnableIf<mozilla::IsNullPointer<N>::value || 1.526 + mozilla::IsSame<N, int>::value || 1.527 + mozilla::IsSame<N, long>::value, 1.528 + int>::Type dummy = 0) 1.529 + MOZ_DELETE; 1.530 + 1.531 + public: 1.532 + void set(T v) { 1.533 + MOZ_ASSERT(!js::GCMethods<T>::poisoned(v)); 1.534 + *ptr = v; 1.535 + } 1.536 + 1.537 + /* 1.538 + * This may be called only if the location of the T is guaranteed 1.539 + * to be marked (for some reason other than being a Rooted), 1.540 + * e.g., if it is guaranteed to be reachable from an implicit root. 1.541 + * 1.542 + * Create a MutableHandle from a raw location of a T. 1.543 + */ 1.544 + static MutableHandle fromMarkedLocation(T *p) { 1.545 + MutableHandle h; 1.546 + h.ptr = p; 1.547 + return h; 1.548 + } 1.549 + 1.550 + T *address() const { return ptr; } 1.551 + const T& get() const { return *ptr; } 1.552 + 1.553 + /* 1.554 + * Return a reference so passing a MutableHandle<T> to something that takes 1.555 + * a |const T&| is not a GC hazard. 1.556 + */ 1.557 + operator const T&() const { return get(); } 1.558 + T operator->() const { return get(); } 1.559 + 1.560 + private: 1.561 + MutableHandle() {} 1.562 + 1.563 + T *ptr; 1.564 + 1.565 + template <typename S> void operator=(S v) MOZ_DELETE; 1.566 + void operator=(MutableHandle other) MOZ_DELETE; 1.567 +}; 1.568 + 1.569 +#ifdef JSGC_GENERATIONAL 1.570 +JS_FRIEND_API(void) HeapCellPostBarrier(js::gc::Cell **cellp); 1.571 +JS_FRIEND_API(void) HeapCellRelocate(js::gc::Cell **cellp); 1.572 +#endif 1.573 + 1.574 +} /* namespace JS */ 1.575 + 1.576 +namespace js { 1.577 + 1.578 +/* 1.579 + * InternalHandle is a handle to an internal pointer into a gcthing. Use 1.580 + * InternalHandle when you have a pointer to a direct field of a gcthing, or 1.581 + * when you need a parameter type for something that *may* be a pointer to a 1.582 + * direct field of a gcthing. 1.583 + */ 1.584 +template <typename T> 1.585 +class InternalHandle {}; 1.586 + 1.587 +template <typename T> 1.588 +class InternalHandle<T*> 1.589 +{ 1.590 + void * const *holder; 1.591 + size_t offset; 1.592 + 1.593 + public: 1.594 + /* 1.595 + * Create an InternalHandle using a Handle to the gcthing containing the 1.596 + * field in question, and a pointer to the field. 1.597 + */ 1.598 + template<typename H> 1.599 + InternalHandle(const JS::Handle<H> &handle, T *field) 1.600 + : holder((void**)handle.address()), offset(uintptr_t(field) - uintptr_t(handle.get())) 1.601 + {} 1.602 + 1.603 + /* 1.604 + * Create an InternalHandle to a field within a Rooted<>. 1.605 + */ 1.606 + template<typename R> 1.607 + InternalHandle(const JS::Rooted<R> &root, T *field) 1.608 + : holder((void**)root.address()), offset(uintptr_t(field) - uintptr_t(root.get())) 1.609 + {} 1.610 + 1.611 + InternalHandle(const InternalHandle<T*>& other) 1.612 + : holder(other.holder), offset(other.offset) {} 1.613 + 1.614 + T *get() const { return reinterpret_cast<T*>(uintptr_t(*holder) + offset); } 1.615 + 1.616 + const T &operator*() const { return *get(); } 1.617 + T *operator->() const { return get(); } 1.618 + 1.619 + static InternalHandle<T*> fromMarkedLocation(T *fieldPtr) { 1.620 + return InternalHandle(fieldPtr); 1.621 + } 1.622 + 1.623 + private: 1.624 + /* 1.625 + * Create an InternalHandle to something that is not a pointer to a 1.626 + * gcthing, and so does not need to be rooted in the first place. Use these 1.627 + * InternalHandles to pass pointers into functions that also need to accept 1.628 + * regular InternalHandles to gcthing fields. 1.629 + * 1.630 + * Make this private to prevent accidental misuse; this is only for 1.631 + * fromMarkedLocation(). 1.632 + */ 1.633 + InternalHandle(T *field) 1.634 + : holder(reinterpret_cast<void * const *>(&js::NullPtr::constNullValue)), 1.635 + offset(uintptr_t(field)) 1.636 + {} 1.637 + 1.638 + void operator=(InternalHandle<T*> other) MOZ_DELETE; 1.639 +}; 1.640 + 1.641 +/* 1.642 + * By default, pointers should use the inheritance hierarchy to find their 1.643 + * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that 1.644 + * Rooted<T> may be used without the class definition being available. 1.645 + */ 1.646 +template <typename T> 1.647 +struct RootKind<T *> 1.648 +{ 1.649 + static ThingRootKind rootKind() { return T::rootKind(); } 1.650 +}; 1.651 + 1.652 +template <typename T> 1.653 +struct GCMethods<T *> 1.654 +{ 1.655 + static T *initial() { return nullptr; } 1.656 + static ThingRootKind kind() { return RootKind<T *>::rootKind(); } 1.657 + static bool poisoned(T *v) { return JS::IsPoisonedPtr(v); } 1.658 + static bool needsPostBarrier(T *v) { return false; } 1.659 +#ifdef JSGC_GENERATIONAL 1.660 + static void postBarrier(T **vp) {} 1.661 + static void relocate(T **vp) {} 1.662 +#endif 1.663 +}; 1.664 + 1.665 +template <> 1.666 +struct GCMethods<JSObject *> 1.667 +{ 1.668 + static JSObject *initial() { return nullptr; } 1.669 + static ThingRootKind kind() { return RootKind<JSObject *>::rootKind(); } 1.670 + static bool poisoned(JSObject *v) { return JS::IsPoisonedPtr(v); } 1.671 + static bool needsPostBarrier(JSObject *v) { return v; } 1.672 +#ifdef JSGC_GENERATIONAL 1.673 + static void postBarrier(JSObject **vp) { 1.674 + JS::HeapCellPostBarrier(reinterpret_cast<js::gc::Cell **>(vp)); 1.675 + } 1.676 + static void relocate(JSObject **vp) { 1.677 + JS::HeapCellRelocate(reinterpret_cast<js::gc::Cell **>(vp)); 1.678 + } 1.679 +#endif 1.680 +}; 1.681 + 1.682 +template <> 1.683 +struct GCMethods<JSFunction *> 1.684 +{ 1.685 + static JSFunction *initial() { return nullptr; } 1.686 + static ThingRootKind kind() { return RootKind<JSObject *>::rootKind(); } 1.687 + static bool poisoned(JSFunction *v) { return JS::IsPoisonedPtr(v); } 1.688 + static bool needsPostBarrier(JSFunction *v) { return v; } 1.689 +#ifdef JSGC_GENERATIONAL 1.690 + static void postBarrier(JSFunction **vp) { 1.691 + JS::HeapCellPostBarrier(reinterpret_cast<js::gc::Cell **>(vp)); 1.692 + } 1.693 + static void relocate(JSFunction **vp) { 1.694 + JS::HeapCellRelocate(reinterpret_cast<js::gc::Cell **>(vp)); 1.695 + } 1.696 +#endif 1.697 +}; 1.698 + 1.699 +#ifdef JS_DEBUG 1.700 +/* This helper allows us to assert that Rooted<T> is scoped within a request. */ 1.701 +extern JS_PUBLIC_API(bool) 1.702 +IsInRequest(JSContext *cx); 1.703 +#endif 1.704 + 1.705 +} /* namespace js */ 1.706 + 1.707 +namespace JS { 1.708 + 1.709 +/* 1.710 + * Local variable of type T whose value is always rooted. This is typically 1.711 + * used for local variables, or for non-rooted values being passed to a 1.712 + * function that requires a handle, e.g. Foo(Root<T>(cx, x)). 1.713 + * 1.714 + * If you want to add additional methods to Rooted for a specific 1.715 + * specialization, define a RootedBase<T> specialization containing them. 1.716 + */ 1.717 +template <typename T> 1.718 +class MOZ_STACK_CLASS Rooted : public js::RootedBase<T> 1.719 +{ 1.720 + /* Note: CX is a subclass of either ContextFriendFields or PerThreadDataFriendFields. */ 1.721 + template <typename CX> 1.722 + void init(CX *cx) { 1.723 +#ifdef JSGC_TRACK_EXACT_ROOTS 1.724 + js::ThingRootKind kind = js::GCMethods<T>::kind(); 1.725 + this->stack = &cx->thingGCRooters[kind]; 1.726 + this->prev = *stack; 1.727 + *stack = reinterpret_cast<Rooted<void*>*>(this); 1.728 + 1.729 + MOZ_ASSERT(!js::GCMethods<T>::poisoned(ptr)); 1.730 +#endif 1.731 + } 1.732 + 1.733 + public: 1.734 + Rooted(JSContext *cx 1.735 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.736 + : ptr(js::GCMethods<T>::initial()) 1.737 + { 1.738 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.739 +#ifdef JS_DEBUG 1.740 + MOZ_ASSERT(js::IsInRequest(cx)); 1.741 +#endif 1.742 + init(js::ContextFriendFields::get(cx)); 1.743 + } 1.744 + 1.745 + Rooted(JSContext *cx, T initial 1.746 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.747 + : ptr(initial) 1.748 + { 1.749 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.750 +#ifdef JS_DEBUG 1.751 + MOZ_ASSERT(js::IsInRequest(cx)); 1.752 +#endif 1.753 + init(js::ContextFriendFields::get(cx)); 1.754 + } 1.755 + 1.756 + Rooted(js::ContextFriendFields *cx 1.757 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.758 + : ptr(js::GCMethods<T>::initial()) 1.759 + { 1.760 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.761 + init(cx); 1.762 + } 1.763 + 1.764 + Rooted(js::ContextFriendFields *cx, T initial 1.765 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.766 + : ptr(initial) 1.767 + { 1.768 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.769 + init(cx); 1.770 + } 1.771 + 1.772 + Rooted(js::PerThreadDataFriendFields *pt 1.773 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.774 + : ptr(js::GCMethods<T>::initial()) 1.775 + { 1.776 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.777 + init(pt); 1.778 + } 1.779 + 1.780 + Rooted(js::PerThreadDataFriendFields *pt, T initial 1.781 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.782 + : ptr(initial) 1.783 + { 1.784 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.785 + init(pt); 1.786 + } 1.787 + 1.788 + Rooted(JSRuntime *rt 1.789 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.790 + : ptr(js::GCMethods<T>::initial()) 1.791 + { 1.792 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.793 + init(js::PerThreadDataFriendFields::getMainThread(rt)); 1.794 + } 1.795 + 1.796 + Rooted(JSRuntime *rt, T initial 1.797 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.798 + : ptr(initial) 1.799 + { 1.800 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.801 + init(js::PerThreadDataFriendFields::getMainThread(rt)); 1.802 + } 1.803 + 1.804 + // Note that we need to let the compiler generate the default destructor in 1.805 + // non-exact-rooting builds because of a bug in the instrumented PGO builds 1.806 + // using MSVC, see bug 915735 for more details. 1.807 +#ifdef JSGC_TRACK_EXACT_ROOTS 1.808 + ~Rooted() { 1.809 + MOZ_ASSERT(*stack == reinterpret_cast<Rooted<void*>*>(this)); 1.810 + *stack = prev; 1.811 + } 1.812 +#endif 1.813 + 1.814 +#ifdef JSGC_TRACK_EXACT_ROOTS 1.815 + Rooted<T> *previous() { return prev; } 1.816 +#endif 1.817 + 1.818 + /* 1.819 + * Important: Return a reference here so passing a Rooted<T> to 1.820 + * something that takes a |const T&| is not a GC hazard. 1.821 + */ 1.822 + operator const T&() const { return ptr; } 1.823 + T operator->() const { return ptr; } 1.824 + T *address() { return &ptr; } 1.825 + const T *address() const { return &ptr; } 1.826 + T &get() { return ptr; } 1.827 + const T &get() const { return ptr; } 1.828 + 1.829 + T &operator=(T value) { 1.830 + MOZ_ASSERT(!js::GCMethods<T>::poisoned(value)); 1.831 + ptr = value; 1.832 + return ptr; 1.833 + } 1.834 + 1.835 + T &operator=(const Rooted &value) { 1.836 + ptr = value; 1.837 + return ptr; 1.838 + } 1.839 + 1.840 + void set(T value) { 1.841 + MOZ_ASSERT(!js::GCMethods<T>::poisoned(value)); 1.842 + ptr = value; 1.843 + } 1.844 + 1.845 + bool operator!=(const T &other) const { return ptr != other; } 1.846 + bool operator==(const T &other) const { return ptr == other; } 1.847 + 1.848 + private: 1.849 +#ifdef JSGC_TRACK_EXACT_ROOTS 1.850 + Rooted<void*> **stack, *prev; 1.851 +#endif 1.852 + 1.853 + /* 1.854 + * |ptr| must be the last field in Rooted because the analysis treats all 1.855 + * Rooted as Rooted<void*> during the analysis. See bug 829372. 1.856 + */ 1.857 + T ptr; 1.858 + 1.859 + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER 1.860 + 1.861 + Rooted(const Rooted &) MOZ_DELETE; 1.862 +}; 1.863 + 1.864 +} /* namespace JS */ 1.865 + 1.866 +namespace js { 1.867 + 1.868 +/* 1.869 + * Augment the generic Rooted<T> interface when T = JSObject* with 1.870 + * class-querying and downcasting operations. 1.871 + * 1.872 + * Given a Rooted<JSObject*> obj, one can view 1.873 + * Handle<StringObject*> h = obj.as<StringObject*>(); 1.874 + * as an optimization of 1.875 + * Rooted<StringObject*> rooted(cx, &obj->as<StringObject*>()); 1.876 + * Handle<StringObject*> h = rooted; 1.877 + */ 1.878 +template <> 1.879 +class RootedBase<JSObject*> 1.880 +{ 1.881 + public: 1.882 + template <class U> 1.883 + JS::Handle<U*> as() const; 1.884 +}; 1.885 + 1.886 + 1.887 +/* 1.888 + * RootedGeneric<T> allows a class to instantiate its own Rooted type by 1.889 + * including the following two methods: 1.890 + * 1.891 + * static inline js::ThingRootKind rootKind() { return js::THING_ROOT_CUSTOM; } 1.892 + * void trace(JSTracer *trc); 1.893 + * 1.894 + * The trace() method must trace all of the class's fields. 1.895 + * 1.896 + * Implementation: 1.897 + * 1.898 + * RootedGeneric<T> works by placing a pointer to its 'rooter' field into the 1.899 + * usual list of rooters when it is instantiated. When marking, it backs up 1.900 + * from this pointer to find a vtable containing a type-appropriate trace() 1.901 + * method. 1.902 + */ 1.903 +template <typename GCType> 1.904 +class JS_PUBLIC_API(RootedGeneric) 1.905 +{ 1.906 + public: 1.907 + JS::Rooted<GCType> rooter; 1.908 + 1.909 + RootedGeneric(js::ContextFriendFields *cx) 1.910 + : rooter(cx) 1.911 + { 1.912 + } 1.913 + 1.914 + RootedGeneric(js::ContextFriendFields *cx, const GCType &initial) 1.915 + : rooter(cx, initial) 1.916 + { 1.917 + } 1.918 + 1.919 + virtual inline void trace(JSTracer *trc); 1.920 + 1.921 + operator const GCType&() const { return rooter.get(); } 1.922 + GCType operator->() const { return rooter.get(); } 1.923 +}; 1.924 + 1.925 +template <typename GCType> 1.926 +inline void RootedGeneric<GCType>::trace(JSTracer *trc) 1.927 +{ 1.928 + rooter->trace(trc); 1.929 +} 1.930 + 1.931 +// We will instantiate RootedGeneric<void*> in RootMarking.cpp, and MSVC will 1.932 +// notice that void*s have no trace() method defined on them and complain (even 1.933 +// though it's never called.) MSVC's complaint is not unreasonable, so 1.934 +// specialize for void*. 1.935 +template <> 1.936 +inline void RootedGeneric<void*>::trace(JSTracer *trc) 1.937 +{ 1.938 + MOZ_ASSUME_UNREACHABLE("RootedGeneric<void*>::trace()"); 1.939 +} 1.940 + 1.941 +/* Interface substitute for Rooted<T> which does not root the variable's memory. */ 1.942 +template <typename T> 1.943 +class FakeRooted : public RootedBase<T> 1.944 +{ 1.945 + public: 1.946 + template <typename CX> 1.947 + FakeRooted(CX *cx 1.948 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.949 + : ptr(GCMethods<T>::initial()) 1.950 + { 1.951 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.952 + } 1.953 + 1.954 + template <typename CX> 1.955 + FakeRooted(CX *cx, T initial 1.956 + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) 1.957 + : ptr(initial) 1.958 + { 1.959 + MOZ_GUARD_OBJECT_NOTIFIER_INIT; 1.960 + } 1.961 + 1.962 + operator T() const { return ptr; } 1.963 + T operator->() const { return ptr; } 1.964 + T *address() { return &ptr; } 1.965 + const T *address() const { return &ptr; } 1.966 + T &get() { return ptr; } 1.967 + const T &get() const { return ptr; } 1.968 + 1.969 + FakeRooted<T> &operator=(T value) { 1.970 + MOZ_ASSERT(!GCMethods<T>::poisoned(value)); 1.971 + ptr = value; 1.972 + return *this; 1.973 + } 1.974 + 1.975 + FakeRooted<T> &operator=(const FakeRooted<T> &other) { 1.976 + MOZ_ASSERT(!GCMethods<T>::poisoned(other.ptr)); 1.977 + ptr = other.ptr; 1.978 + return *this; 1.979 + } 1.980 + 1.981 + bool operator!=(const T &other) const { return ptr != other; } 1.982 + bool operator==(const T &other) const { return ptr == other; } 1.983 + 1.984 + private: 1.985 + T ptr; 1.986 + 1.987 + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER 1.988 + 1.989 + FakeRooted(const FakeRooted &) MOZ_DELETE; 1.990 +}; 1.991 + 1.992 +/* Interface substitute for MutableHandle<T> which is not required to point to rooted memory. */ 1.993 +template <typename T> 1.994 +class FakeMutableHandle : public js::MutableHandleBase<T> 1.995 +{ 1.996 + public: 1.997 + FakeMutableHandle(T *t) { 1.998 + ptr = t; 1.999 + } 1.1000 + 1.1001 + FakeMutableHandle(FakeRooted<T> *root) { 1.1002 + ptr = root->address(); 1.1003 + } 1.1004 + 1.1005 + void set(T v) { 1.1006 + MOZ_ASSERT(!js::GCMethods<T>::poisoned(v)); 1.1007 + *ptr = v; 1.1008 + } 1.1009 + 1.1010 + T *address() const { return ptr; } 1.1011 + T get() const { return *ptr; } 1.1012 + 1.1013 + operator T() const { return get(); } 1.1014 + T operator->() const { return get(); } 1.1015 + 1.1016 + private: 1.1017 + FakeMutableHandle() {} 1.1018 + 1.1019 + T *ptr; 1.1020 + 1.1021 + template <typename S> 1.1022 + void operator=(S v) MOZ_DELETE; 1.1023 + 1.1024 + void operator=(const FakeMutableHandle<T>& other) MOZ_DELETE; 1.1025 +}; 1.1026 + 1.1027 +/* 1.1028 + * Types for a variable that either should or shouldn't be rooted, depending on 1.1029 + * the template parameter allowGC. Used for implementing functions that can 1.1030 + * operate on either rooted or unrooted data. 1.1031 + * 1.1032 + * The toHandle() and toMutableHandle() functions are for calling functions 1.1033 + * which require handle types and are only called in the CanGC case. These 1.1034 + * allow the calling code to type check. 1.1035 + */ 1.1036 +enum AllowGC { 1.1037 + NoGC = 0, 1.1038 + CanGC = 1 1.1039 +}; 1.1040 +template <typename T, AllowGC allowGC> 1.1041 +class MaybeRooted 1.1042 +{ 1.1043 +}; 1.1044 + 1.1045 +template <typename T> class MaybeRooted<T, CanGC> 1.1046 +{ 1.1047 + public: 1.1048 + typedef JS::Handle<T> HandleType; 1.1049 + typedef JS::Rooted<T> RootType; 1.1050 + typedef JS::MutableHandle<T> MutableHandleType; 1.1051 + 1.1052 + static inline JS::Handle<T> toHandle(HandleType v) { 1.1053 + return v; 1.1054 + } 1.1055 + 1.1056 + static inline JS::MutableHandle<T> toMutableHandle(MutableHandleType v) { 1.1057 + return v; 1.1058 + } 1.1059 +}; 1.1060 + 1.1061 +template <typename T> class MaybeRooted<T, NoGC> 1.1062 +{ 1.1063 + public: 1.1064 + typedef T HandleType; 1.1065 + typedef FakeRooted<T> RootType; 1.1066 + typedef FakeMutableHandle<T> MutableHandleType; 1.1067 + 1.1068 + static inline JS::Handle<T> toHandle(HandleType v) { 1.1069 + MOZ_ASSUME_UNREACHABLE("Bad conversion"); 1.1070 + } 1.1071 + 1.1072 + static inline JS::MutableHandle<T> toMutableHandle(MutableHandleType v) { 1.1073 + MOZ_ASSUME_UNREACHABLE("Bad conversion"); 1.1074 + } 1.1075 +}; 1.1076 + 1.1077 +} /* namespace js */ 1.1078 + 1.1079 +namespace JS { 1.1080 + 1.1081 +template <typename T> template <typename S> 1.1082 +inline 1.1083 +Handle<T>::Handle(const Rooted<S> &root, 1.1084 + typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy) 1.1085 +{ 1.1086 + ptr = reinterpret_cast<const T *>(root.address()); 1.1087 +} 1.1088 + 1.1089 +template <typename T> template <typename S> 1.1090 +inline 1.1091 +Handle<T>::Handle(const PersistentRooted<S> &root, 1.1092 + typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy) 1.1093 +{ 1.1094 + ptr = reinterpret_cast<const T *>(root.address()); 1.1095 +} 1.1096 + 1.1097 +template <typename T> template <typename S> 1.1098 +inline 1.1099 +Handle<T>::Handle(MutableHandle<S> &root, 1.1100 + typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy) 1.1101 +{ 1.1102 + ptr = reinterpret_cast<const T *>(root.address()); 1.1103 +} 1.1104 + 1.1105 +template <typename T> 1.1106 +inline 1.1107 +MutableHandle<T>::MutableHandle(Rooted<T> *root) 1.1108 +{ 1.1109 + static_assert(sizeof(MutableHandle<T>) == sizeof(T *), 1.1110 + "MutableHandle must be binary compatible with T*."); 1.1111 + ptr = root->address(); 1.1112 +} 1.1113 + 1.1114 +template <typename T> 1.1115 +inline 1.1116 +MutableHandle<T>::MutableHandle(PersistentRooted<T> *root) 1.1117 +{ 1.1118 + static_assert(sizeof(MutableHandle<T>) == sizeof(T *), 1.1119 + "MutableHandle must be binary compatible with T*."); 1.1120 + ptr = root->address(); 1.1121 +} 1.1122 + 1.1123 +/* 1.1124 + * A copyable, assignable global GC root type with arbitrary lifetime, an 1.1125 + * infallible constructor, and automatic unrooting on destruction. 1.1126 + * 1.1127 + * These roots can be used in heap-allocated data structures, so they are not 1.1128 + * associated with any particular JSContext or stack. They are registered with 1.1129 + * the JSRuntime itself, without locking, so they require a full JSContext to be 1.1130 + * constructed, not one of its more restricted superclasses. 1.1131 + * 1.1132 + * Note that you must not use an PersistentRooted in an object owned by a JS 1.1133 + * object: 1.1134 + * 1.1135 + * Whenever one object whose lifetime is decided by the GC refers to another 1.1136 + * such object, that edge must be traced only if the owning JS object is traced. 1.1137 + * This applies not only to JS objects (which obviously are managed by the GC) 1.1138 + * but also to C++ objects owned by JS objects. 1.1139 + * 1.1140 + * If you put a PersistentRooted in such a C++ object, that is almost certainly 1.1141 + * a leak. When a GC begins, the referent of the PersistentRooted is treated as 1.1142 + * live, unconditionally (because a PersistentRooted is a *root*), even if the 1.1143 + * JS object that owns it is unreachable. If there is any path from that 1.1144 + * referent back to the JS object, then the C++ object containing the 1.1145 + * PersistentRooted will not be destructed, and the whole blob of objects will 1.1146 + * not be freed, even if there are no references to them from the outside. 1.1147 + * 1.1148 + * In the context of Firefox, this is a severe restriction: almost everything in 1.1149 + * Firefox is owned by some JS object or another, so using PersistentRooted in 1.1150 + * such objects would introduce leaks. For these kinds of edges, Heap<T> or 1.1151 + * TenuredHeap<T> would be better types. It's up to the implementor of the type 1.1152 + * containing Heap<T> or TenuredHeap<T> members to make sure their referents get 1.1153 + * marked when the object itself is marked. 1.1154 + */ 1.1155 +template<typename T> 1.1156 +class PersistentRooted : private mozilla::LinkedListElement<PersistentRooted<T> > { 1.1157 + friend class mozilla::LinkedList<PersistentRooted>; 1.1158 + friend class mozilla::LinkedListElement<PersistentRooted>; 1.1159 + 1.1160 + friend class js::gc::PersistentRootedMarker<T>; 1.1161 + 1.1162 + void registerWithRuntime(JSRuntime *rt) { 1.1163 + JS::shadow::Runtime *srt = JS::shadow::Runtime::asShadowRuntime(rt); 1.1164 + srt->getPersistentRootedList<T>().insertBack(this); 1.1165 + } 1.1166 + 1.1167 + public: 1.1168 + PersistentRooted(JSContext *cx) : ptr(js::GCMethods<T>::initial()) 1.1169 + { 1.1170 + registerWithRuntime(js::GetRuntime(cx)); 1.1171 + } 1.1172 + 1.1173 + PersistentRooted(JSContext *cx, T initial) : ptr(initial) 1.1174 + { 1.1175 + registerWithRuntime(js::GetRuntime(cx)); 1.1176 + } 1.1177 + 1.1178 + PersistentRooted(JSRuntime *rt) : ptr(js::GCMethods<T>::initial()) 1.1179 + { 1.1180 + registerWithRuntime(rt); 1.1181 + } 1.1182 + 1.1183 + PersistentRooted(JSRuntime *rt, T initial) : ptr(initial) 1.1184 + { 1.1185 + registerWithRuntime(rt); 1.1186 + } 1.1187 + 1.1188 + PersistentRooted(PersistentRooted &rhs) : ptr(rhs.ptr) 1.1189 + { 1.1190 + /* 1.1191 + * Copy construction takes advantage of the fact that the original 1.1192 + * is already inserted, and simply adds itself to whatever list the 1.1193 + * original was on - no JSRuntime pointer needed. 1.1194 + */ 1.1195 + rhs.setNext(this); 1.1196 + } 1.1197 + 1.1198 + /* 1.1199 + * Important: Return a reference here so passing a Rooted<T> to 1.1200 + * something that takes a |const T&| is not a GC hazard. 1.1201 + */ 1.1202 + operator const T&() const { return ptr; } 1.1203 + T operator->() const { return ptr; } 1.1204 + T *address() { return &ptr; } 1.1205 + const T *address() const { return &ptr; } 1.1206 + T &get() { return ptr; } 1.1207 + const T &get() const { return ptr; } 1.1208 + 1.1209 + T &operator=(T value) { 1.1210 + MOZ_ASSERT(!js::GCMethods<T>::poisoned(value)); 1.1211 + ptr = value; 1.1212 + return ptr; 1.1213 + } 1.1214 + 1.1215 + T &operator=(const PersistentRooted &value) { 1.1216 + ptr = value; 1.1217 + return ptr; 1.1218 + } 1.1219 + 1.1220 + void set(T value) { 1.1221 + MOZ_ASSERT(!js::GCMethods<T>::poisoned(value)); 1.1222 + ptr = value; 1.1223 + } 1.1224 + 1.1225 + bool operator!=(const T &other) const { return ptr != other; } 1.1226 + bool operator==(const T &other) const { return ptr == other; } 1.1227 + 1.1228 + private: 1.1229 + T ptr; 1.1230 +}; 1.1231 + 1.1232 +} /* namespace JS */ 1.1233 + 1.1234 +namespace js { 1.1235 + 1.1236 +/* Base class for automatic read-only object rooting during compilation. */ 1.1237 +class CompilerRootNode 1.1238 +{ 1.1239 + protected: 1.1240 + CompilerRootNode(js::gc::Cell *ptr) : next(nullptr), ptr_(ptr) {} 1.1241 + 1.1242 + public: 1.1243 + void **address() { return (void **)&ptr_; } 1.1244 + 1.1245 + public: 1.1246 + CompilerRootNode *next; 1.1247 + 1.1248 + protected: 1.1249 + js::gc::Cell *ptr_; 1.1250 +}; 1.1251 + 1.1252 +} /* namespace js */ 1.1253 + 1.1254 +#endif /* js_RootingAPI_h */