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