Bug 811176 - Purge small exec pools on GC (r=njn)
authorBill McCloskey <wmccloskey@mozilla.com>
Tue, 13 Nov 2012 17:13:44 -0800
changeset 113178 6e56236dfd3f200f0fb691036029e279e8d6f5a1
parent 113177 f6511d0a33eb55793e08ca154423c7ec7cbacd3b
child 113179 5a1edbdb251f642466dd427dbd05dec957bfa03c
push id23859
push useremorley@mozilla.com
push dateWed, 14 Nov 2012 14:36:31 +0000
treeherdermozilla-central@87928cd21b40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs811176
milestone19.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 811176 - Purge small exec pools on GC (r=njn)
js/src/assembler/jit/ExecutableAllocator.h
js/src/jscntxt.h
js/src/jsgc.cpp
--- a/js/src/assembler/jit/ExecutableAllocator.h
+++ b/js/src/assembler/jit/ExecutableAllocator.h
@@ -207,16 +207,23 @@ public:
     ~ExecutableAllocator()
     {
         for (size_t i = 0; i < m_smallPools.length(); i++)
             m_smallPools[i]->release(/* willDestroy = */true);
         // XXX: temporarily disabled because it fails;  see bug 654820.
         //JS_ASSERT(m_pools.empty());     // if this asserts we have a pool leak
     }
 
+    void purge() {
+        for (size_t i = 0; i < m_smallPools.length(); i++)
+            m_smallPools[i]->release();
+
+	m_smallPools.clear();
+    }
+
     // alloc() returns a pointer to some memory, and also (by reference) a
     // pointer to reference-counted pool. The caller owns a reference to the
     // pool; i.e. alloc() increments the count before returning the object.
     void* alloc(size_t n, ExecutablePool** poolp, CodeKind type)
     {
         // Round 'n' up to a multiple of word size; if all allocations are of
         // word sized quantities, then all subsequent allocations will be
         // aligned.
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -509,16 +509,19 @@ struct JSRuntime : js::RuntimeFriendFiel
   public:
     JSC::ExecutableAllocator *getExecAlloc(JSContext *cx) {
         return execAlloc_ ? execAlloc_ : createExecutableAllocator(cx);
     }
     JSC::ExecutableAllocator &execAlloc() {
         JS_ASSERT(execAlloc_);
         return *execAlloc_;
     }
+    JSC::ExecutableAllocator *maybeExecAlloc() {
+        return execAlloc_;
+    }
     WTF::BumpPointerAllocator *getBumpPointerAllocator(JSContext *cx) {
         return bumpAlloc_ ? bumpAlloc_ : createBumpPointerAllocator(cx);
     }
 #ifdef JS_METHODJIT
     js::mjit::JaegerRuntime *getJaegerRuntime(JSContext *cx) {
         return jaegerRuntime_ ? jaegerRuntime_ : createJaegerRuntime(cx);
     }
     bool hasJaegerRuntime() const {
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -4005,16 +4005,20 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocat
          * Sweep script filenames after sweeping functions in the generic loop
          * above. In this way when a scripted function's finalizer destroys the
          * script and calls rt->destroyScriptHook, the hook can still access the
          * script's filename. See bug 323267.
          */
         if (rt->gcIsFull)
             SweepScriptFilenames(rt);
 
+        /* Clear out any small pools that we're hanging on to. */
+        if (JSC::ExecutableAllocator *execAlloc = rt->maybeExecAlloc())
+            execAlloc->purge();
+
         /*
          * This removes compartments from rt->compartment, so we do it last to make
          * sure we don't miss sweeping any compartments.
          */
         if (!lastGC)
             SweepCompartments(&fop, lastGC);
 
         if (!rt->gcSweepOnBackgroundThread) {