Bug 714050 - Add support for optional JS helper threads (r=luke)
authorBill McCloskey <wmccloskey@mozilla.com>
Tue, 16 Oct 2012 11:57:09 -0700
changeset 110729 3f603fdf63564ea2b9eb1b5ed1ebf98263b990fb
parent 110728 557cfb0bdc396835d11d6d1f62316fbd92df96cf
child 110730 08302471419d5635e79c4d8b0adba82af11d7998
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersluke
bugs714050
milestone19.0a1
Bug 714050 - Add support for optional JS helper threads (r=luke)
dom/indexedDB/IDBObjectStore.cpp
dom/workers/RuntimeService.cpp
gfx/skia/src/xml/SkJS.cpp
js/src/jsapi-tests/testGCOutOfMemory.cpp
js/src/jsapi-tests/testOOM.cpp
js/src/jsapi-tests/tests.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.h
js/src/shell/js.cpp
js/xpconnect/src/XPCJSRuntime.cpp
netwerk/base/src/ProxyAutoConfig.cpp
startupcache/test/TestStartupCache.cpp
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -492,17 +492,17 @@ class ThreadLocalJSRuntime
   ThreadLocalJSRuntime()
   : mRuntime(NULL), mContext(NULL), mGlobal(NULL)
   {
       MOZ_COUNT_CTOR(ThreadLocalJSRuntime);
   }
 
   nsresult Init()
   {
-    mRuntime = JS_NewRuntime(sRuntimeHeapSize);
+    mRuntime = JS_NewRuntime(sRuntimeHeapSize, JS_NO_HELPER_THREADS);
     NS_ENSURE_TRUE(mRuntime, NS_ERROR_OUT_OF_MEMORY);
 
     mContext = JS_NewContext(mRuntime, 0);
     NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);
 
     JSAutoRequest ar(mContext);
 
     mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, NULL);
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -378,17 +378,17 @@ ContentSecurityPolicyAllows(JSContext* a
 JSContext*
 CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate)
 {
   aWorkerPrivate->AssertIsOnWorkerThread();
   NS_ASSERTION(!aWorkerPrivate->GetJSContext(), "Already has a context!");
 
   // The number passed here doesn't matter, we're about to change it in the call
   // to JS_SetGCParameter.
-  JSRuntime* runtime = JS_NewRuntime(WORKER_DEFAULT_RUNTIME_HEAPSIZE);
+  JSRuntime* runtime = JS_NewRuntime(WORKER_DEFAULT_RUNTIME_HEAPSIZE, JS_NO_HELPER_THREADS);
   if (!runtime) {
     NS_WARNING("Could not create new runtime!");
     return nullptr;
   }
 
   // This is the real place where we set the max memory for the runtime.
   JS_SetGCParameter(runtime, JSGC_MAX_BYTES,
                     aWorkerPrivate->GetJSRuntimeHeapSize());
--- a/gfx/skia/src/xml/SkJS.cpp
+++ b/gfx/skia/src/xml/SkJS.cpp
@@ -154,17 +154,17 @@ JSClass global_class = {
     "global", JSCLASS_NEW_RESOLVE,
     JS_PropertyStub,  JS_PropertyStub,
     JS_PropertyStub,  JS_PropertyStub,
     global_enumerate, (JSResolveOp) global_resolve,
     JS_ConvertStub,   JS_FinalizeStub
 };
 
 SkJS::SkJS(void* hwnd) : SkOSWindow(hwnd) {
-    if ((fRuntime = JS_NewRuntime(0x100000)) == NULL) {
+    if ((fRuntime = JS_NewRuntime(0x100000, JS_NO_HELPER_THREADS)) == NULL) {
         SkASSERT(0);
         return;
     }
     if ((fContext = JS_NewContext(fRuntime, 0x1000)) == NULL) {
         SkASSERT(0);
         return;
     }
     ;
--- a/js/src/jsapi-tests/testGCOutOfMemory.cpp
+++ b/js/src/jsapi-tests/testGCOutOfMemory.cpp
@@ -45,16 +45,16 @@ BEGIN_TEST(testGCOutOfMemory)
          "        array.push({});"
          "    }"
          "})();", root.address());
     CHECK_EQUAL(errorCount, 1);
     return true;
 }
 
 virtual JSRuntime * createRuntime() {
-    return JS_NewRuntime(512 * 1024);
+    return JS_NewRuntime(512 * 1024, JS_USE_HELPER_THREADS);
 }
 
 virtual void destroyRuntime() {
     JS_DestroyRuntime(rt);
 }
 
 END_TEST(testGCOutOfMemory)
--- a/js/src/jsapi-tests/testOOM.cpp
+++ b/js/src/jsapi-tests/testOOM.cpp
@@ -13,13 +13,13 @@ BEGIN_TEST(testOOM)
     JS_SetProperty(cx, global, "rootme", &tmp);
     mozilla::DebugOnly<const jschar *> s = JS_GetStringCharsZ(cx, jsstr);
     JS_ASSERT(s[0] == '9' && s[1] == '\0');
     return true;
 }
 
 virtual JSRuntime * createRuntime()
 {
-    JSRuntime *rt = JS_NewRuntime(0);
+    JSRuntime *rt = JS_NewRuntime(0, JS_USE_HELPER_THREADS);
     JS_SetGCParameter(rt, JSGC_MAX_BYTES, (uint32_t)-1);
     return rt;
 }
 END_TEST(testOOM)
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -249,17 +249,17 @@ class JSAPITest
         fflush(stdout);
         JS_SET_RVAL(cx, vp, JSVAL_VOID);
         return JS_TRUE;
     }
 
     bool definePrint();
 
     virtual JSRuntime * createRuntime() {
-        JSRuntime *rt = JS_NewRuntime(8L * 1024 * 1024);
+        JSRuntime *rt = JS_NewRuntime(8L * 1024 * 1024, JS_USE_HELPER_THREADS);
         if (!rt)
             return NULL;
 
         const size_t MAX_STACK_SIZE =
 /* Assume we can't use more than 5e5 bytes of C stack by default. */
 #if (defined(DEBUG) && defined(__SUNPRO_CC))  || defined(JS_CPU_SPARC)
             /*
              * Sun compiler uses a larger stack space for js::Interpret() with
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -711,17 +711,17 @@ JS_FRIEND_API(void) LeaveAssertNoGCScope
 JS_FRIEND_API(bool) InNoGCScope() { return false; }
 JS_FRIEND_API(bool) NeedRelaxedRootChecks() { return false; }
 #endif
 
 } /* namespace JS */
 
 static const JSSecurityCallbacks NullSecurityCallbacks = { };
 
-JSRuntime::JSRuntime()
+JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
   : atomsCompartment(NULL),
 #ifdef JS_THREADSAFE
     ownerThread_(NULL),
 #endif
     tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     freeLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     execAlloc_(NULL),
     bumpAlloc_(NULL),
@@ -858,17 +858,18 @@ JSRuntime::JSRuntime()
 #endif
     inOOMReport(0),
     jitHardening(false),
     ionTop(NULL),
     ionJSContext(NULL),
     ionStackLimit(0),
     ionActivation(NULL),
     ionPcScriptCache(NULL),
-    ionReturnOverride_(MagicValue(JS_ARG_POISON))
+    ionReturnOverride_(MagicValue(JS_ARG_POISON)),
+    useHelperThreads_(useHelperThreads)
 {
     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
     JS_INIT_CLIST(&contextList);
     JS_INIT_CLIST(&debuggerList);
     JS_INIT_CLIST(&onNewGlobalObjectWatchers);
 
     PodZero(&debugHooks);
     PodZero(&atomState);
@@ -1055,17 +1056,17 @@ JS_FRIEND_API(void)
 JSRuntime::assertValidThread() const
 {
     JS_ASSERT(ownerThread_ == PR_GetCurrentThread());
     JS_ASSERT(this == JS::TlsRuntime.get());
 }
 #endif  /* JS_THREADSAFE */
 
 JS_PUBLIC_API(JSRuntime *)
-JS_NewRuntime(uint32_t maxbytes)
+JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads)
 {
     if (!js_NewRuntimeWasCalled) {
 #ifdef DEBUG
         /*
          * This code asserts that the numbers associated with the error names
          * in jsmsg.def are monotonically increasing.  It uses values for the
          * error names enumerated in jscntxt.c.  It's not a compile-time check
          * but it's better than nothing.
@@ -1093,17 +1094,17 @@ JS_NewRuntime(uint32_t maxbytes)
         InitMemorySubsystem();
 
         if (!JS::TlsRuntime.init())
             return NULL;
 
         js_NewRuntimeWasCalled = JS_TRUE;
     }
 
-    JSRuntime *rt = js_new<JSRuntime>();
+    JSRuntime *rt = js_new<JSRuntime>(useHelperThreads);
     if (!rt)
         return NULL;
 
 #if defined(JS_METHODJIT) && defined(JS_ION)
     if (!ion::InitializeIon())
         return NULL;
 #endif
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2921,18 +2921,24 @@ JS_IsBuiltinFunctionConstructor(JSFuncti
  * single-threaded fashion, otherwise the behavior of the library is undefined.
  * See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference
  */
 #define JS_NewRuntime       JS_Init
 #define JS_DestroyRuntime   JS_Finish
 #define JS_LockRuntime      JS_Lock
 #define JS_UnlockRuntime    JS_Unlock
 
+typedef enum JSUseHelperThreads
+{
+    JS_NO_HELPER_THREADS,
+    JS_USE_HELPER_THREADS
+} JSUseHelperThreads;
+
 extern JS_PUBLIC_API(JSRuntime *)
-JS_NewRuntime(uint32_t maxbytes);
+JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads);
 
 /* Deprecated. */
 #define JS_CommenceRuntimeShutDown(rt) ((void) 0)
 
 extern JS_PUBLIC_API(void)
 JS_DestroyRuntime(JSRuntime *rt);
 
 extern JS_PUBLIC_API(void)
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -976,17 +976,17 @@ struct JSRuntime : js::RuntimeFriendFiel
         ionReturnOverride_ = js::MagicValue(JS_ARG_POISON);
         return v;
     }
     void setIonReturnOverride(const js::Value &v) {
         JS_ASSERT(!hasIonReturnOverride());
         ionReturnOverride_ = v;
     }
 
-    JSRuntime();
+    JSRuntime(JSUseHelperThreads useHelperThreads);
     ~JSRuntime();
 
     bool init(uint32_t maxbytes);
 
     JSRuntime *thisFromCtor() { return this; }
 
     /*
      * Call the system malloc while checking for GC memory pressure and
@@ -1093,16 +1093,27 @@ struct JSRuntime : js::RuntimeFriendFiel
 
     void setJitHardening(bool enabled);
     bool getJitHardening() const {
         return jitHardening;
     }
 
     void sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf, JS::RuntimeSizes *runtime);
     size_t sizeOfExplicitNonHeap();
+
+  private:
+    JSUseHelperThreads useHelperThreads_;
+  public:
+    bool useHelperThreads() const {
+#ifdef JS_THREADSAFE
+        return useHelperThreads_ == JS_USE_HELPER_THREADS;
+#else
+        return false;
+#endif
+    }
 };
 
 /* Common macros to access thread-local caches in JSRuntime. */
 #define JS_KEEP_ATOMS(rt)   (rt)->gcKeepAtoms++;
 #define JS_UNKEEP_ATOMS(rt) (rt)->gcKeepAtoms--;
 
 namespace js {
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4939,17 +4939,17 @@ main(int argc, char **argv, char **envp)
 #ifdef XP_WIN
     // Set the timer calibration delay count to 0 so we get high
     // resolution right away, which we need for precise benchmarking.
     extern int CALIBRATION_DELAY_COUNT;
     CALIBRATION_DELAY_COUNT = 0;
 #endif
 
     /* Use the same parameters as the browser in xpcjsruntime.cpp. */
-    rt = JS_NewRuntime(32L * 1024L * 1024L);
+    rt = JS_NewRuntime(32L * 1024L * 1024L, JS_USE_HELPER_THREADS);
     if (!rt)
         return 1;
 
     JS_SetGCParameter(rt, JSGC_MAX_BYTES, 0xffffffff);
 
     JS_SetTrustedPrincipals(rt, &shellTrustedPrincipals);
     JS_SetSecurityCallbacks(rt, &securityCallbacks);
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2279,17 +2279,17 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
     Preferences::AddBoolVarCache(&gExperimentalBindingsEnabled,
                                  "dom.experimental_bindings",
                                  false);
 
 
     // these jsids filled in later when we have a JSContext to work with.
     mStrIDs[0] = JSID_VOID;
 
-    mJSRuntime = JS_NewRuntime(32L * 1024L * 1024L); // pref ?
+    mJSRuntime = JS_NewRuntime(32L * 1024L * 1024L, JS_USE_HELPER_THREADS); // pref ?
     if (!mJSRuntime)
         NS_RUNTIMEABORT("JS_NewRuntime failed.");
 
     // Unconstrain the runtime's threshold on nominal heap size, to avoid
     // triggering GC too often if operating continuously near an arbitrary
     // finite threshold (0xffffffff is infinity for uint32_t parameters).
     // This leaves the maximum-JS_malloc-bytes threshold still in effect
     // to cause period, and we hope hygienic, last-ditch GCs from within
--- a/netwerk/base/src/ProxyAutoConfig.cpp
+++ b/netwerk/base/src/ProxyAutoConfig.cpp
@@ -516,17 +516,17 @@ private:
   JSRuntimeWrapper()
     : mRuntime(nullptr), mContext(nullptr), mGlobal(nullptr), mOK(false)
   {
       MOZ_COUNT_CTOR(JSRuntimeWrapper);
   }
 
   nsresult Init()
   {
-    mRuntime = JS_NewRuntime(sRuntimeHeapSize);
+    mRuntime = JS_NewRuntime(sRuntimeHeapSize, JS_NO_HELPER_THREADS);
     NS_ENSURE_TRUE(mRuntime, NS_ERROR_OUT_OF_MEMORY);
 
     mContext = JS_NewContext(mRuntime, 0);
     NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);
 
     JSAutoRequest ar(mContext);
 
     mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr);
--- a/startupcache/test/TestStartupCache.cpp
+++ b/startupcache/test/TestStartupCache.cpp
@@ -283,17 +283,17 @@ TestEarlyShutdown() {
   }
  
   return NS_OK;
 }
 
 bool
 SetupJS(JSContext **cxp)
 {
-  JSRuntime *rt = JS_NewRuntime(32 * 1024 * 1024);
+  JSRuntime *rt = JS_NewRuntime(32 * 1024 * 1024, JS_NO_HELPER_THREADS);
   if (!rt)
     return false;
   JSContext *cx = JS_NewContext(rt, 8192);
   if (!cx)
     return false;
   *cxp = cx;
   return true;
 }