Policy.h (3715B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 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 /* JS Garbage Collector. */ 8 9 #ifndef gc_Policy_h 10 #define gc_Policy_h 11 12 #include <type_traits> 13 14 #include "gc/Barrier.h" 15 #include "gc/Marking.h" 16 #include "gc/Tracer.h" 17 #include "js/GCPolicyAPI.h" 18 19 namespace js { 20 21 // Define the GCPolicy for all internal pointers. 22 template <typename T> 23 struct InternalGCPointerPolicy : public JS::GCPointerPolicy<T> { 24 using Type = std::remove_pointer_t<T>; 25 26 #define IS_BASE_OF_OR(_1, BaseType, _2, _3) std::is_base_of_v<BaseType, Type> || 27 static_assert( 28 JS_FOR_EACH_TRACEKIND(IS_BASE_OF_OR) false, 29 "InternalGCPointerPolicy must only be used for GC thing pointers"); 30 #undef IS_BASE_OF_OR 31 32 static void trace(JSTracer* trc, T* vp, const char* name) { 33 // It's not safe to trace unbarriered pointers except as part of root 34 // marking. If you get an assertion here you probably need to add a barrier, 35 // e.g. HeapPtr<T>. 36 TraceNullableRoot(trc, vp, name); 37 } 38 }; 39 40 } // namespace js 41 42 namespace JS { 43 44 // Internally, all pointer types are treated as pointers to GC things by 45 // default. 46 template <typename T> 47 struct GCPolicy<T*> : public js::InternalGCPointerPolicy<T*> {}; 48 template <typename T> 49 struct GCPolicy<T* const> : public js::InternalGCPointerPolicy<T* const> {}; 50 51 template <typename T> 52 struct GCPolicy<js::HeapPtr<T>> : public GCPolicyBase<js::HeapPtr<T>> { 53 static void trace(JSTracer* trc, js::HeapPtr<T>* thingp, const char* name) { 54 js::TraceNullableEdge(trc, thingp, name); 55 } 56 static bool traceWeak(JSTracer* trc, js::HeapPtr<T>* thingp) { 57 return js::TraceWeakEdge(trc, thingp, "HeapPtr"); 58 } 59 static bool needsSweep(JSTracer* trc, const js::HeapPtr<T>* thingp) { 60 js::HeapPtr<T> thing(*thingp); 61 auto r = js::TraceWeakEdge(trc, &thing, "HeapPtr"); 62 MOZ_ASSERT(!r.wasMoved()); 63 return r.isDead(); 64 } 65 }; 66 67 template <typename T> 68 struct GCPolicy<js::PreBarriered<T>> 69 : public GCPolicyBase<js::PreBarriered<T>> { 70 static void trace(JSTracer* trc, js::PreBarriered<T>* thingp, 71 const char* name) { 72 js::TraceNullableEdge(trc, thingp, name); 73 } 74 }; 75 76 template <typename T> 77 struct GCPolicy<js::WeakHeapPtr<T>> : public GCPolicyBase<js::WeakHeapPtr<T>> { 78 static void trace(JSTracer* trc, js::WeakHeapPtr<T>* thingp, 79 const char* name) { 80 js::TraceEdge(trc, thingp, name); 81 } 82 static bool traceWeak(JSTracer* trc, js::WeakHeapPtr<T>* thingp) { 83 return js::TraceWeakEdge(trc, thingp, "traceWeak"); 84 } 85 static bool needsSweep(JSTracer* trc, const js::WeakHeapPtr<T>* thingp) { 86 js::WeakHeapPtr<T> thing(*thingp); 87 auto r = js::TraceWeakEdge(trc, &thing, "WeakHeapPtr"); 88 MOZ_ASSERT(!r.wasMoved()); 89 return r.isDead(); 90 } 91 }; 92 93 template <typename T> 94 struct GCPolicy<js::UnsafeBarePtr<T>> 95 : public GCPolicyBase<js::UnsafeBarePtr<T>> { 96 static bool traceWeak(JSTracer* trc, js::UnsafeBarePtr<T>* vp) { 97 if (*vp) { 98 return js::TraceManuallyBarrieredWeakEdge(trc, vp->unbarrieredAddress(), 99 "UnsafeBarePtr"); 100 } 101 return true; 102 } 103 }; 104 105 template <> 106 struct GCPolicy<JS::GCCellPtr> : public GCPolicyBase<JS::GCCellPtr> { 107 static void trace(JSTracer* trc, JS::GCCellPtr* thingp, const char* name) { 108 // It's not safe to trace unbarriered pointers except as part of root 109 // marking. 110 js::TraceGCCellPtrRoot(trc, thingp, name); 111 } 112 }; 113 114 } // namespace JS 115 116 #endif // gc_Policy_h