RootingAPI.h 43 KB

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