summaryrefslogtreecommitdiffstats
path: root/js/public/SweepingAPI.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--js/public/SweepingAPI.h121
1 files changed, 121 insertions, 0 deletions
diff --git a/js/public/SweepingAPI.h b/js/public/SweepingAPI.h
new file mode 100644
index 0000000000..7833d65b7a
--- /dev/null
+++ b/js/public/SweepingAPI.h
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef js_SweepingAPI_h
+#define js_SweepingAPI_h
+
+#include "mozilla/LinkedList.h"
+#include "mozilla/Maybe.h"
+
+#include "jstypes.h"
+
+#include "js/GCAnnotations.h"
+#include "js/GCPolicyAPI.h"
+#include "js/RootingAPI.h"
+
+namespace js {
+namespace gc {
+
+class StoreBuffer;
+
+JS_PUBLIC_API void LockStoreBuffer(StoreBuffer* sb);
+JS_PUBLIC_API void UnlockStoreBuffer(StoreBuffer* sb);
+
+class AutoLockStoreBuffer {
+ StoreBuffer* sb;
+
+ public:
+ explicit AutoLockStoreBuffer(StoreBuffer* sb) : sb(sb) {
+ LockStoreBuffer(sb);
+ }
+ ~AutoLockStoreBuffer() { UnlockStoreBuffer(sb); }
+};
+
+} // namespace gc
+} // namespace js
+
+namespace JS {
+namespace detail {
+class WeakCacheBase;
+} // namespace detail
+
+namespace shadow {
+JS_PUBLIC_API void RegisterWeakCache(JS::Zone* zone,
+ JS::detail::WeakCacheBase* cachep);
+JS_PUBLIC_API void RegisterWeakCache(JSRuntime* rt,
+ JS::detail::WeakCacheBase* cachep);
+} // namespace shadow
+
+namespace detail {
+class WeakCacheBase : public mozilla::LinkedListElement<WeakCacheBase> {
+ WeakCacheBase() = delete;
+ explicit WeakCacheBase(const WeakCacheBase&) = delete;
+
+ public:
+ explicit WeakCacheBase(Zone* zone) { shadow::RegisterWeakCache(zone, this); }
+ explicit WeakCacheBase(JSRuntime* rt) { shadow::RegisterWeakCache(rt, this); }
+ WeakCacheBase(WeakCacheBase&& other) = default;
+ virtual ~WeakCacheBase() = default;
+
+ virtual size_t traceWeak(JSTracer* trc, js::gc::StoreBuffer* sbToLock) = 0;
+
+ // Sweeping will be skipped if the cache is empty already.
+ virtual bool empty() = 0;
+
+ // Enable/disable read barrier during incremental sweeping and set the tracer
+ // to use.
+ virtual bool setIncrementalBarrierTracer(JSTracer* trc) {
+ // Derived classes do not support incremental barriers by default.
+ return false;
+ }
+ virtual bool needsIncrementalBarrier() const {
+ // Derived classes do not support incremental barriers by default.
+ return false;
+ }
+};
+} // namespace detail
+
+// A WeakCache stores the given Sweepable container and links itself into a
+// list of such caches that are swept during each GC. A WeakCache can be
+// specific to a zone, or across a whole runtime, depending on which
+// constructor is used.
+template <typename T>
+class WeakCache : protected detail::WeakCacheBase,
+ public js::MutableWrappedPtrOperations<T, WeakCache<T>> {
+ T cache;
+
+ public:
+ using Type = T;
+
+ template <typename... Args>
+ explicit WeakCache(Zone* zone, Args&&... args)
+ : WeakCacheBase(zone), cache(std::forward<Args>(args)...) {}
+ template <typename... Args>
+ explicit WeakCache(JSRuntime* rt, Args&&... args)
+ : WeakCacheBase(rt), cache(std::forward<Args>(args)...) {}
+
+ const T& get() const { return cache; }
+ T& get() { return cache; }
+
+ size_t traceWeak(JSTracer* trc, js::gc::StoreBuffer* sbToLock) override {
+ // Take the store buffer lock in case sweeping triggers any generational
+ // post barriers. This is not always required and WeakCache specializations
+ // may delay or skip taking the lock as appropriate.
+ mozilla::Maybe<js::gc::AutoLockStoreBuffer> lock;
+ if (sbToLock) {
+ lock.emplace(sbToLock);
+ }
+
+ GCPolicy<T>::traceWeak(trc, &cache);
+ return 0;
+ }
+
+ bool empty() override { return cache.empty(); }
+} JS_HAZ_NON_GC_POINTER;
+
+} // namespace JS
+
+#endif // js_SweepingAPI_h