Bug 1345307 - Implement runtime-wide WeakCache, r=jonco
authorSteve Fink <sfink@mozilla.com>
Tue, 07 Mar 2017 12:55:37 -0800
changeset 346649 9dd78a5e9eb02fc7b05c353d5821f9c70e910fc0
parent 346648 d2a67bd597870264fd86a52fd2916e8842ccd396
child 346650 1b822c69468163ce8f7dc5c0da8aed529dbf3d3c
push id87864
push usersfink@mozilla.com
push dateThu, 09 Mar 2017 01:24:17 +0000
treeherdermozilla-inbound@9dd78a5e9eb0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1345307
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1345307 - Implement runtime-wide WeakCache, r=jonco MozReview-Commit-ID: DX2nNCZrj6
js/public/SweepingAPI.h
js/src/jsgc.cpp
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
--- a/js/public/SweepingAPI.h
+++ b/js/public/SweepingAPI.h
@@ -10,20 +10,24 @@
 #include "js/HeapAPI.h"
 
 namespace JS {
 template <typename T> class WeakCache;
 
 namespace shadow {
 JS_PUBLIC_API(void)
 RegisterWeakCache(JS::Zone* zone, JS::WeakCache<void*>* cachep);
+JS_PUBLIC_API(void)
+RegisterWeakCache(JSRuntime* rt, JS::WeakCache<void*>* cachep);
 } // namespace shadow
 
 // A WeakCache stores the given Sweepable container and links itself into a
-// list of such caches that are swept during each GC.
+// 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 : public js::MutableWrappedPtrOperations<T, WeakCache<T>>,
                   private mozilla::LinkedListElement<WeakCache<T>>
 {
     friend class mozilla::LinkedListElement<WeakCache<T>>;
     friend class mozilla::LinkedList<WeakCache<T>>;
 
     WeakCache() = delete;
@@ -38,16 +42,23 @@ class WeakCache : public js::MutableWrap
 
     template <typename U>
     WeakCache(Zone* zone, U&& initial)
       : cache(mozilla::Forward<U>(initial))
     {
         sweeper = GCPolicy<T>::sweep;
         shadow::RegisterWeakCache(zone, reinterpret_cast<WeakCache<void*>*>(this));
     }
+    template <typename U>
+    WeakCache(JSRuntime* rt, U&& initial)
+      : cache(mozilla::Forward<U>(initial))
+    {
+        sweeper = GCPolicy<T>::sweep;
+        shadow::RegisterWeakCache(rt, reinterpret_cast<WeakCache<void*>*>(this));
+    }
     WeakCache(WeakCache&& other)
       : sweeper(other.sweeper),
         cache(mozilla::Move(other.cache))
     {
     }
 
     const T& get() const { return cache; }
     T& get() { return cache; }
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2549,16 +2549,18 @@ GCRuntime::updateRuntimePointersToReloca
         if (JSTraceDataOp op = grayRootTracer.op)
             (*op)(&trc, grayRootTracer.data);
     }
 
     // Sweep everything to fix up weak pointers.
     WatchpointMap::sweepAll(rt);
     Debugger::sweepAll(rt->defaultFreeOp());
     jit::JitRuntime::SweepJitcodeGlobalTable(rt);
+    for (JS::WeakCache<void*>* cache : rt->weakCaches())
+        cache->sweep();
 
     // Type inference may put more blocks here to free.
     blocksToFreeAfterSweeping.ref().freeAll();
 
     // Call callbacks to get the rest of the system to fixup other untraced pointers.
     callWeakPointerZoneGroupCallbacks();
 }
 
@@ -5144,16 +5146,20 @@ GCRuntime::beginSweepingZoneGroup(AutoLo
             WatchpointMap::sweepAll(rt);
 
             // Detach unreachable debuggers and global objects from each other.
             Debugger::sweepAll(&fop);
 
             // Sweep entries containing about-to-be-finalized JitCode and
             // update relocated TypeSet::Types inside the JitcodeGlobalTable.
             jit::JitRuntime::SweepJitcodeGlobalTable(rt);
+
+            // Sweep runtime-wide weak caches.
+            for (JS::WeakCache<void*>* cache : rt->weakCaches())
+                cache->sweep();
         }
 
         {
             gcstats::AutoPhase apdc(stats(), gcstats::PHASE_SWEEP_DISCARD_CODE);
             for (GCZoneGroupIter zone(rt); !zone.done(); zone.next())
                 zone->discardJitCode(&fop);
         }
 
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -910,8 +910,14 @@ JSRuntime::ionLazyLinkListRemove(jit::Io
 void
 JSRuntime::ionLazyLinkListAdd(jit::IonBuilder* builder)
 {
     MOZ_ASSERT(CurrentThreadCanAccessRuntime(this),
                "Should only be mutated by the active thread.");
     ionLazyLinkList().insertFront(builder);
     ionLazyLinkListSize_++;
 }
+
+JS_PUBLIC_API(void)
+JS::shadow::RegisterWeakCache(JSRuntime* rt, WeakCache<void*>* cachep)
+{
+    rt->registerWeakCache(cachep);
+}
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -556,16 +556,25 @@ struct JSRuntime : public js::MallocProv
     const js::Class* maybeWindowProxyClass() const {
         return windowProxyClass_;
     }
     void setWindowProxyClass(const js::Class* clasp) {
         windowProxyClass_ = clasp;
     }
 
   private:
+    // List of non-ephemeron weak containers to sweep during beginSweepingZoneGroup.
+    js::ActiveThreadData<mozilla::LinkedList<JS::WeakCache<void*>>> weakCaches_;
+  public:
+    mozilla::LinkedList<JS::WeakCache<void*>>& weakCaches() { return weakCaches_.ref(); }
+    void registerWeakCache(JS::WeakCache<void*>* cachep) {
+        weakCaches().insertBack(cachep);
+    }
+
+  private:
     /*
      * Head of circular list of all enabled Debuggers that have
      * onNewGlobalObject handler methods established.
      */
     js::ActiveThreadData<JSCList> onNewGlobalObjectWatchers_;
   public:
     JSCList& onNewGlobalObjectWatchers() { return onNewGlobalObjectWatchers_.ref(); }