Backed out changeset 67d13c5fcf84 (bug 956899)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 28 May 2016 01:39:00 +0200
changeset 338411 3c86f1e4bbc95042068ec7b1e2246ab54239e1ce
parent 338410 a3a3aa23f4ef145bdc30278e092b77676e00babf
child 338412 764ab2ad75e784d0175f6645c1c2fca4816863af
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs956899
milestone49.0a1
backs out67d13c5fcf841e33734c0568fffa9f7686fd264f
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
Backed out changeset 67d13c5fcf84 (bug 956899)
js/src/shell/js.cpp
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -74,19 +74,16 @@
 #include "js/GCAPI.h"
 #include "js/Initialization.h"
 #include "js/StructuredClone.h"
 #include "js/TrackedOptimizationInfo.h"
 #include "perf/jsperf.h"
 #include "shell/jsoptparse.h"
 #include "shell/jsshell.h"
 #include "shell/OSObject.h"
-#include "threading/ConditionVariable.h"
-#include "threading/LockGuard.h"
-#include "threading/Mutex.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/Compression.h"
 #include "vm/Debugger.h"
 #include "vm/HelperThreads.h"
 #include "vm/Monitor.h"
 #include "vm/Shape.h"
 #include "vm/SharedArrayObject.h"
 #include "vm/StringBuffer.h"
@@ -165,22 +162,22 @@ struct ShellRuntime
 #ifdef SPIDERMONKEY_PROMISE
     JS::PersistentRootedValue promiseRejectionTrackerCallback;
     JS::PersistentRooted<JobQueue> jobQueue;
 #endif // SPIDERMONKEY_PROMISE
 
     /*
      * Watchdog thread state.
      */
-    Mutex watchdogLock;
-    ConditionVariable watchdogWakeup;
+    PRLock* watchdogLock;
+    PRCondVar* watchdogWakeup;
     PRThread* watchdogThread;
     Maybe<TimeStamp> watchdogTimeout;
 
-    ConditionVariable sleepWakeup;
+    PRCondVar* sleepWakeup;
 
     int exitCode;
     bool quitting;
     bool gotError;
 };
 
 // Shell state set once at startup.
 static bool enableCodeCoverage = false;
@@ -214,16 +211,19 @@ static bool OOM_printAllocationCount = f
 
 // Shell state this is only accessed on the main thread.
 bool jsCachingEnabled = false;
 mozilla::Atomic<bool> jsCacheOpened(false);
 
 static bool
 SetTimeoutValue(JSContext* cx, double t);
 
+static bool
+InitWatchdog(JSRuntime* rt);
+
 static void
 KillWatchdog(JSRuntime *rt);
 
 static bool
 ScheduleWatchdog(JSRuntime* rt, double t);
 
 static void
 CancelExecution(JSRuntime* rt);
@@ -310,17 +310,20 @@ ShellRuntime::ShellRuntime(JSRuntime* rt
     serviceInterrupt(false),
     haveInterruptFunc(false),
     interruptFunc(rt, NullValue()),
     lastWarningEnabled(false),
     lastWarning(rt, NullValue()),
 #ifdef SPIDERMONKEY_PROMISE
     promiseRejectionTrackerCallback(rt, NullValue()),
 #endif // SPIDERMONKEY_PROMISE
+    watchdogLock(nullptr),
+    watchdogWakeup(nullptr),
     watchdogThread(nullptr),
+    sleepWakeup(nullptr),
     exitCode(0),
     quitting(false),
     gotError(false)
 {}
 
 static ShellRuntime*
 GetShellRuntime(JSRuntime *rt)
 {
@@ -2928,16 +2931,22 @@ WorkerMain(void* arg)
 
     sr->isWorker = true;
     JS_SetRuntimePrivate(rt, sr.get());
     JS_SetFutexCanWait(rt);
     JS_SetErrorReporter(rt, my_ErrorReporter);
     JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy);
     SetWorkerRuntimeOptions(rt);
 
+    if (!InitWatchdog(rt)) {
+        JS_DestroyRuntime(rt);
+        js_delete(input);
+        return;
+    }
+
     JSContext* cx = NewContext(rt);
     if (!cx) {
         JS_DestroyRuntime(rt);
         js_delete(input);
         return;
     }
 
 #ifdef SPIDERMONKEY_PROMISE
@@ -3087,125 +3096,151 @@ Sleep_fn(JSContext* cx, unsigned argc, V
         duration = TimeDuration::FromSeconds(Max(0.0, t_secs));
 
         /* NB: The next condition also filter out NaNs. */
         if (duration > MAX_TIMEOUT_INTERVAL) {
             JS_ReportError(cx, "Excessive sleep interval");
             return false;
         }
     }
-    {
-        LockGuard<Mutex> guard(sr->watchdogLock);
-        TimeStamp toWakeup = TimeStamp::Now() + duration;
-        for (;;) {
-            sr->sleepWakeup.wait_for(guard, duration);
-            if (sr->serviceInterrupt)
-                break;
-            auto now = TimeStamp::Now();
-            if (now >= toWakeup)
-                break;
-            duration = toWakeup - now;
-        }
-    }
+    PR_Lock(sr->watchdogLock);
+    TimeStamp toWakeup = TimeStamp::Now() + duration;
+    for (;;) {
+        PR_WaitCondVar(sr->sleepWakeup, DurationToPRInterval(duration));
+        if (sr->serviceInterrupt)
+            break;
+        auto now = TimeStamp::Now();
+        if (now >= toWakeup)
+            break;
+        duration = toWakeup - now;
+    }
+    PR_Unlock(sr->watchdogLock);
     args.rval().setUndefined();
     return !sr->serviceInterrupt;
 }
 
+static bool
+InitWatchdog(JSRuntime* rt)
+{
+    ShellRuntime* sr = GetShellRuntime(rt);
+    MOZ_ASSERT(!sr->watchdogThread);
+    sr->watchdogLock = PR_NewLock();
+    if (sr->watchdogLock) {
+        sr->watchdogWakeup = PR_NewCondVar(sr->watchdogLock);
+        if (sr->watchdogWakeup) {
+            sr->sleepWakeup = PR_NewCondVar(sr->watchdogLock);
+            if (sr->sleepWakeup)
+                return true;
+            PR_DestroyCondVar(sr->watchdogWakeup);
+        }
+        PR_DestroyLock(sr->watchdogLock);
+    }
+    return false;
+}
+
 static void
 KillWatchdog(JSRuntime* rt)
 {
     ShellRuntime* sr = GetShellRuntime(rt);
     PRThread* thread;
 
-    {
-        LockGuard<Mutex> guard(sr->watchdogLock);
-        thread = sr->watchdogThread;
-        if (thread) {
-            /*
-             * The watchdog thread is running, tell it to terminate waking it up
-             * if necessary.
-             */
-            sr->watchdogThread = nullptr;
-            sr->watchdogWakeup.notify_one();
-        }
-    }
+    PR_Lock(sr->watchdogLock);
+    thread = sr->watchdogThread;
+    if (thread) {
+        /*
+         * The watchdog thread is running, tell it to terminate waking it up
+         * if necessary.
+         */
+        sr->watchdogThread = nullptr;
+        PR_NotifyCondVar(sr->watchdogWakeup);
+    }
+    PR_Unlock(sr->watchdogLock);
     if (thread)
         PR_JoinThread(thread);
+    PR_DestroyCondVar(sr->sleepWakeup);
+    PR_DestroyCondVar(sr->watchdogWakeup);
+    PR_DestroyLock(sr->watchdogLock);
 }
 
 static void
 WatchdogMain(void* arg)
 {
     PR_SetCurrentThreadName("JS Watchdog");
 
     JSRuntime* rt = (JSRuntime*) arg;
     ShellRuntime* sr = GetShellRuntime(rt);
 
-    LockGuard<Mutex> guard(sr->watchdogLock);
+    PR_Lock(sr->watchdogLock);
     while (sr->watchdogThread) {
         auto now = TimeStamp::Now();
         if (sr->watchdogTimeout.isSome() && now >= sr->watchdogTimeout.value()) {
             /*
              * The timeout has just expired. Request an interrupt callback
              * outside the lock.
              */
             sr->watchdogTimeout = Nothing();
-            {
-                UnlockGuard<Mutex> unlock(guard);
-                CancelExecution(rt);
-            }
+            PR_Unlock(sr->watchdogLock);
+            CancelExecution(rt);
+            PR_Lock(sr->watchdogLock);
 
             /* Wake up any threads doing sleep. */
-            sr->sleepWakeup.notify_all();
+            PR_NotifyAllCondVar(sr->sleepWakeup);
         } else {
             if (sr->watchdogTimeout.isSome()) {
                 /*
                  * Time hasn't expired yet. Simulate an interrupt callback
                  * which doesn't abort execution.
                  */
                 JS_RequestInterruptCallback(rt);
             }
 
             TimeDuration sleepDuration = sr->watchdogTimeout.isSome()
                                          ? TimeDuration::FromSeconds(0.1)
                                          : TimeDuration::Forever();
-            sr->watchdogWakeup.wait_for(guard, sleepDuration);
+            mozilla::DebugOnly<PRStatus> status =
+              PR_WaitCondVar(sr->watchdogWakeup, DurationToPRInterval(sleepDuration));
+            MOZ_ASSERT(status == PR_SUCCESS);
         }
     }
+    PR_Unlock(sr->watchdogLock);
 }
 
 static bool
 ScheduleWatchdog(JSRuntime* rt, double t)
 {
     ShellRuntime* sr = GetShellRuntime(rt);
 
     if (t <= 0) {
-        LockGuard<Mutex> guard(sr->watchdogLock);
+        PR_Lock(sr->watchdogLock);
         sr->watchdogTimeout = Nothing();
+        PR_Unlock(sr->watchdogLock);
         return true;
     }
 
     auto interval = TimeDuration::FromSeconds(t);
     auto timeout = TimeStamp::Now() + interval;
-    LockGuard<Mutex> guard(sr->watchdogLock);
+    PR_Lock(sr->watchdogLock);
     if (!sr->watchdogThread) {
         MOZ_ASSERT(sr->watchdogTimeout.isNothing());
         sr->watchdogThread = PR_CreateThread(PR_USER_THREAD,
                                           WatchdogMain,
                                           rt,
                                           PR_PRIORITY_NORMAL,
                                           PR_GLOBAL_THREAD,
                                           PR_JOINABLE_THREAD,
                                           0);
-        if (!sr->watchdogThread)
+        if (!sr->watchdogThread) {
+            PR_Unlock(sr->watchdogLock);
             return false;
+        }
     } else if (sr->watchdogTimeout.isNothing() || timeout < sr->watchdogTimeout.value()) {
-         sr->watchdogWakeup.notify_one();
+         PR_NotifyCondVar(sr->watchdogWakeup);
     }
     sr->watchdogTimeout = Some(timeout);
+    PR_Unlock(sr->watchdogLock);
     return true;
 }
 
 static void
 KillWorkerThreads()
 {
     MOZ_ASSERT_IF(!CanUseExtraThreads(), workerThreads.empty());
 
@@ -7390,16 +7425,19 @@ main(int argc, char** argv, char** envp)
 
     JS_SetNativeStackQuota(rt, gMaxStackSize);
 
     JS::dbg::SetDebuggerMallocSizeOf(rt, moz_malloc_size_of);
 
     if (!offThreadState.init())
         return 1;
 
+    if (!InitWatchdog(rt))
+        return 1;
+
     cx = NewContext(rt);
     if (!cx)
         return 1;
 
 #ifdef SPIDERMONKEY_PROMISE
     sr->jobQueue.init(cx, JobQueue(SystemAllocPolicy()));
     JS::SetEnqueuePromiseJobCallback(rt, ShellEnqueuePromiseJobCallback);
 #endif // SPIDERMONKEY_PROMISE