SweepingAPI.h (3806B)
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 #ifndef js_SweepingAPI_h 8 #define js_SweepingAPI_h 9 10 #include "mozilla/LinkedList.h" 11 #include "mozilla/Maybe.h" 12 13 #include "jstypes.h" 14 15 #include "js/GCAnnotations.h" 16 #include "js/GCPolicyAPI.h" 17 #include "js/RootingAPI.h" 18 19 namespace js { 20 namespace gc { 21 22 JS_PUBLIC_API void LockStoreBuffer(JSRuntime* runtime); 23 JS_PUBLIC_API void UnlockStoreBuffer(JSRuntime* runtim); 24 25 class AutoLockStoreBuffer { 26 JSRuntime* runtime; 27 28 public: 29 explicit AutoLockStoreBuffer(JSRuntime* runtime) : runtime(runtime) { 30 LockStoreBuffer(runtime); 31 } 32 ~AutoLockStoreBuffer() { UnlockStoreBuffer(runtime); } 33 }; 34 35 } // namespace gc 36 } // namespace js 37 38 namespace JS { 39 namespace detail { 40 class WeakCacheBase; 41 } // namespace detail 42 43 namespace shadow { 44 JS_PUBLIC_API void RegisterWeakCache(JS::Zone* zone, 45 JS::detail::WeakCacheBase* cachep); 46 JS_PUBLIC_API void RegisterWeakCache(JSRuntime* rt, 47 JS::detail::WeakCacheBase* cachep); 48 } // namespace shadow 49 50 namespace detail { 51 52 class WeakCacheBase : public mozilla::LinkedListElement<WeakCacheBase> { 53 WeakCacheBase() = delete; 54 explicit WeakCacheBase(const WeakCacheBase&) = delete; 55 56 public: 57 enum NeedsLock : bool { LockStoreBuffer = true, DontLockStoreBuffer = false }; 58 59 explicit WeakCacheBase(JS::Zone* zone) { 60 shadow::RegisterWeakCache(zone, this); 61 } 62 explicit WeakCacheBase(JSRuntime* rt) { shadow::RegisterWeakCache(rt, this); } 63 WeakCacheBase(WeakCacheBase&& other) = default; 64 virtual ~WeakCacheBase() = default; 65 66 virtual size_t traceWeak(JSTracer* trc, NeedsLock needLock) = 0; 67 68 // Sweeping will be skipped if the cache is empty already. 69 virtual bool empty() = 0; 70 71 // Enable/disable read barrier during incremental sweeping and set the tracer 72 // to use. 73 virtual bool setIncrementalBarrierTracer(JSTracer* trc) { 74 // Derived classes do not support incremental barriers by default. 75 return false; 76 } 77 virtual bool needsIncrementalBarrier() const { 78 // Derived classes do not support incremental barriers by default. 79 return false; 80 } 81 }; 82 83 } // namespace detail 84 85 // A WeakCache stores the given Sweepable container and links itself into a 86 // list of such caches that are swept during each GC. A WeakCache can be 87 // specific to a zone, or across a whole runtime, depending on which 88 // constructor is used. 89 template <typename T> 90 class WeakCache : protected detail::WeakCacheBase, 91 public js::MutableWrappedPtrOperations<T, WeakCache<T>> { 92 T cache; 93 94 public: 95 using Type = T; 96 97 template <typename... Args> 98 explicit WeakCache(Zone* zone, Args&&... args) 99 : WeakCacheBase(zone), cache(std::forward<Args>(args)...) {} 100 template <typename... Args> 101 explicit WeakCache(JSRuntime* rt, Args&&... args) 102 : WeakCacheBase(rt), cache(std::forward<Args>(args)...) {} 103 104 const T& get() const { return cache; } 105 T& get() { return cache; } 106 107 size_t traceWeak(JSTracer* trc, NeedsLock needsLock) override { 108 // Take the store buffer lock in case sweeping triggers any generational 109 // post barriers. This is not always required and WeakCache specializations 110 // may delay or skip taking the lock as appropriate. 111 mozilla::Maybe<js::gc::AutoLockStoreBuffer> lock; 112 if (needsLock) { 113 lock.emplace(trc->runtime()); 114 } 115 116 GCPolicy<T>::traceWeak(trc, &cache); 117 return 0; 118 } 119 120 bool empty() override { return cache.empty(); } 121 } JS_HAZ_NON_GC_POINTER; 122 123 } // namespace JS 124 125 #endif // js_SweepingAPI_h