Bug 587288: 0. Compartmentalize regexp allocator, remove ExecutablePool atomic refcounts. (r=gal)
authorChris Leary <cdleary@mozilla.com>
Wed, 05 Jan 2011 18:44:30 -0800
changeset 60168 b5ccae65b44e9c2f26c9a97eb626b23e7b85013f
parent 60167 a65393138ec4ce375419c40853fb0028025b5841
child 60169 f75602c6e52119670345e5e00161710ca07e1b1c
push id17881
push usercleary@mozilla.com
push dateFri, 07 Jan 2011 19:57:21 +0000
treeherdermozilla-central@54576be62860 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgal
bugs587288
milestone2.0b9pre
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 587288: 0. Compartmentalize regexp allocator, remove ExecutablePool atomic refcounts. (r=gal)
js/src/assembler/jit/ExecutableAllocator.h
js/src/jsapi.cpp
js/src/jscntxt.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsobj.cpp
js/src/jsregexpinlines.h
--- a/js/src/assembler/jit/ExecutableAllocator.h
+++ b/js/src/assembler/jit/ExecutableAllocator.h
@@ -111,30 +111,35 @@ private:
         size_t size;
 #if WTF_PLATFORM_SYMBIAN
         RChunk* chunk;
 #endif
     };
     typedef js::Vector<Allocation, 2 ,js::SystemAllocPolicy > AllocationList;
 
     // Reference count for automatic reclamation.
-    jsrefcount m_refCount;
+    unsigned m_refCount;
 
 public:
-      // It should be impossible for us to roll over, because only small
-      // pools have multiple holders, and they have one holder per chunk
-      // of generated code, and they only hold 16KB or so of code.
-      void addRef() { JS_ATOMIC_INCREMENT(&m_refCount); }
-      void release() { 
-	  JS_ASSERT(m_refCount != 0);
-	  if (JS_ATOMIC_DECREMENT(&m_refCount) == 0) 
-	      delete this; 
-      }
+    // It should be impossible for us to roll over, because only small
+    // pools have multiple holders, and they have one holder per chunk
+    // of generated code, and they only hold 16KB or so of code.
+    void addRef()
+    {
+        JS_ASSERT(m_refCount);
+        ++m_refCount;
+    }
 
-    //static PassRefPtr<ExecutablePool> create(size_t n)
+    void release()
+    { 
+        JS_ASSERT(m_refCount != 0);
+        if (--m_refCount == 0)
+            delete this;
+    }
+
     static ExecutablePool* create(size_t n)
     {
         ExecutablePool *pool = new ExecutablePool(n);
         if (!pool->m_freePtr) {
             delete pool;
             return NULL;
         }
         return pool;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -642,22 +642,16 @@ JSRuntime::init(uint32 maxbytes)
         !defaultCompartment->init() ||
         !compartments.append(defaultCompartment)) {
         return false;
     }
 
     if (!js_InitGC(this, maxbytes) || !js_InitAtomState(this))
         return false;
 
-#if ENABLE_YARR_JIT
-    regExpAllocator = JSC::ExecutableAllocator::create();
-    if (!regExpAllocator)
-        return false;
-#endif
-
     wrapObjectCallback = js::TransparentObjectWrapper;
 
 #ifdef JS_THREADSAFE
     /* this is asymmetric with JS_ShutDown: */
     if (!js_SetupLocks(8, 16))
         return false;
     rtLock = JS_NEW_LOCK();
     if (!rtLock)
@@ -693,19 +687,16 @@ JSRuntime::~JSRuntime()
                 cxcount, (cxcount == 1) ? "" : "s");
     }
 #endif
 
     js_FinishThreads(this);
     js_FreeRuntimeScriptState(this);
     js_FinishAtomState(this);
 
-#if ENABLE_YARR_JIT
-    delete regExpAllocator;
-#endif
     js_FinishGC(this);
 #ifdef JS_THREADSAFE
     if (gcLock)
         JS_DESTROY_LOCK(gcLock);
     if (gcDone)
         JS_DESTROY_CONDVAR(gcDone);
     if (requestDone)
         JS_DESTROY_CONDVAR(requestDone);
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -117,20 +117,16 @@ class Assembler;
 class CodeAlloc;
 class Fragment;
 template<typename K> struct DefaultHash;
 template<typename K, typename V, typename H> class HashMap;
 template<typename T> class Seq;
 
 }  /* namespace nanojit */
 
-namespace JSC {
-    class ExecutableAllocator;
-}
-
 namespace js {
 
 /* Tracer constants. */
 static const size_t MONITOR_N_GLOBAL_STATES = 4;
 static const size_t FRAGMENT_TABLE_SIZE = 512;
 static const size_t MAX_NATIVE_STACK_SLOTS = 4096;
 static const size_t MAX_CALL_STACK_ENTRIES = 500;
 static const size_t MAX_GLOBAL_SLOTS = 4096;
@@ -1434,18 +1430,16 @@ struct JSRuntime {
 
     FunctionCountMap    methodReadBarrierCountMap;
     FunctionCountMap    unjoinedFunctionCountMap;
 #endif
 
     JSWrapObjectCallback wrapObjectCallback;
     JSPreWrapCallback    preWrapObjectCallback;
 
-    JSC::ExecutableAllocator *regExpAllocator;
-
     JSRuntime();
     ~JSRuntime();
 
     bool init(uint32 maxbytes);
 
     void setGCTriggerFactor(uint32 factor);
     void setGCLastBytes(size_t lastBytes);
 
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -67,16 +67,20 @@ JSCompartment::JSCompartment(JSRuntime *
 {
     JS_INIT_CLIST(&scripts);
 
     PodArrayZero(scriptsToGC);
 }
 
 JSCompartment::~JSCompartment()
 {
+#if ENABLE_YARR_JIT
+    delete regExpAllocator;
+#endif
+
 #if defined JS_TRACER
     FinishJIT(&traceMonitor);
 #endif
 #ifdef JS_METHODJIT
     delete jaegerCompartment;
 #endif
 
     delete mathCache;
@@ -102,16 +106,22 @@ JSCompartment::init()
         return false;
 
 #ifdef JS_TRACER
     if (!InitJIT(&traceMonitor)) {
         return false;
     }
 #endif
 
+#if ENABLE_YARR_JIT
+    regExpAllocator = JSC::ExecutableAllocator::create();
+    if (!regExpAllocator)
+        return false;
+#endif
+
 #ifdef JS_METHODJIT
     if (!(jaegerCompartment = new mjit::JaegerCompartment)) {
 #ifdef JS_TRACER
         FinishJIT(&traceMonitor);
 #endif
         return false;
     }
     return jaegerCompartment->Initialize();
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -49,16 +49,22 @@
 #include "jsclist.h"
 #include "jsxml.h"
 
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4251) /* Silence warning about JS_FRIEND_API and data members. */
 #endif
 
+namespace JSC {
+
+class ExecutableAllocator;
+
+}
+
 namespace js {
 
 /* Holds the number of recording attemps for an address. */
 typedef HashMap<jsbytecode*,
                 size_t,
                 DefaultHasher<jsbytecode*>,
                 SystemAllocPolicy> RecordAttemptMap;
 
@@ -300,16 +306,18 @@ struct JS_FRIEND_API(JSCompartment) {
      *
      * NB: Singleton objects must be carefully disconnected from the rest of
      * the object graph usually associated with a JSContext's global object,
      * including the set of standard class objects.  See jsxml.c for details.
      */
     JSObject                     *anynameObject;
     JSObject                     *functionNamespaceObject;
 
+    JSC::ExecutableAllocator     *regExpAllocator;
+
     js::NativeIterCache          nativeIterCache;
 
     JSCompartment(JSRuntime *cx);
     ~JSCompartment();
 
     bool init();
 
     bool wrap(JSContext *cx, js::Value *vp);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3462,16 +3462,23 @@ JSObject::clone(JSContext *cx, JSObject 
 }
 
 static void
 TradeGuts(JSObject *a, JSObject *b)
 {
     JS_ASSERT(a->compartment() == b->compartment());
     JS_ASSERT(a->isFunction() == b->isFunction());
 
+    /*
+     * Regexp guts are more complicated -- we would need to migrate the
+     * refcounted JIT code blob for them across compartments instead of just
+     * swapping guts.
+     */
+    JS_ASSERT(!a->isRegExp() && !b->isRegExp());
+
     bool aInline = !a->hasSlotsArray();
     bool bInline = !b->hasSlotsArray();
 
     /* Trade the guts of the objects. */
     const size_t size = GetObjectSize(a);
     if (size == GetObjectSize(b)) {
         /*
          * If the objects are the same size, then we make no assumptions about
--- a/js/src/jsregexpinlines.h
+++ b/js/src/jsregexpinlines.h
@@ -429,17 +429,17 @@ YarrJITIsBroken(JSContext *cx)
 #endif  /* ANDROID */
 
 inline bool
 RegExp::compileHelper(JSContext *cx, JSLinearString &pattern)
 {
 #if ENABLE_YARR_JIT
     bool fellBack = false;
     int error = 0;
-    jitCompileRegex(*cx->runtime->regExpAllocator, compiled, pattern, parenCount, error, fellBack, ignoreCase(), multiline()
+    jitCompileRegex(*cx->compartment->regExpAllocator, compiled, pattern, parenCount, error, fellBack, ignoreCase(), multiline()
 #ifdef ANDROID
                     /* Temporary gross hack to work around buggy kernels. */
                     , YarrJITIsBroken(cx)
 #endif
 );
     if (!error)
         return true;
     if (fellBack)