Bug 1275306 - Part 2: Use a TimeStamp to implement watchdogTimeout; r=jandem
authorTerrence Cole <terrence@mozilla.com>
Sat, 28 May 2016 16:10:15 +0200
changeset 338434 10a2a0ed4d329e7509883acb17d8817319e28017
parent 338433 d58e8b384d3ed41a9008ae4991a3218ebc43950b
child 338435 cbce330b4dd328a0d7ccc87a1f0d9a1f8ee07a01
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)
reviewersjandem
bugs1275306
milestone49.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 1275306 - Part 2: Use a TimeStamp to implement watchdogTimeout; r=jandem
js/src/shell/js.cpp
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -100,16 +100,17 @@
 
 using namespace js;
 using namespace js::cli;
 using namespace js::shell;
 
 using mozilla::ArrayLength;
 using mozilla::Atomic;
 using mozilla::Maybe;
+using mozilla::Nothing;
 using mozilla::NumberEqualsInt32;
 using mozilla::PodCopy;
 using mozilla::PodEqual;
 using mozilla::TimeDuration;
 using mozilla::TimeStamp;
 
 enum JSShellExitCode {
     EXITCODE_RUNTIME_ERROR      = 3,
@@ -164,18 +165,17 @@ struct ShellRuntime
 #endif // SPIDERMONKEY_PROMISE
 
     /*
      * Watchdog thread state.
      */
     PRLock* watchdogLock;
     PRCondVar* watchdogWakeup;
     PRThread* watchdogThread;
-    bool watchdogHasTimeout;
-    int64_t watchdogTimeout;
+    Maybe<TimeStamp> watchdogTimeout;
 
     PRCondVar* sleepWakeup;
 
     int exitCode;
     bool quitting;
 };
 
 struct MOZ_STACK_CLASS EnvironmentPreparer : public js::ScriptEnvironmentPreparer {
@@ -322,18 +322,16 @@ ShellRuntime::ShellRuntime(JSRuntime* rt
     lastWarningEnabled(false),
     lastWarning(rt, NullValue()),
 #ifdef SPIDERMONKEY_PROMISE
     promiseRejectionTrackerCallback(rt, NullValue()),
 #endif // SPIDERMONKEY_PROMISE
     watchdogLock(nullptr),
     watchdogWakeup(nullptr),
     watchdogThread(nullptr),
-    watchdogHasTimeout(false),
-    watchdogTimeout(0),
     sleepWakeup(nullptr),
     exitCode(0),
     quitting(false)
 {}
 
 static ShellRuntime*
 GetShellRuntime(JSRuntime *rt)
 {
@@ -3099,27 +3097,16 @@ ShapeOf(JSContext* cx, unsigned argc, JS
         JS_ReportError(cx, "shapeOf: object expected");
         return false;
     }
     JSObject* obj = &args[0].toObject();
     args.rval().set(JS_NumberValue(double(uintptr_t(obj->maybeShape()) >> 3)));
     return true;
 }
 
-/*
- * Check that t1 comes strictly before t2. The function correctly deals with
- * wrap-around between t2 and t1 assuming that t2 and t1 stays within INT32_MAX
- * from each other. We use MAX_TIMEOUT_INTERVAL to enforce this restriction.
- */
-static bool
-IsBefore(int64_t t1, int64_t t2)
-{
-    return int32_t(t1 - t2) < 0;
-}
-
 static bool
 Sleep_fn(JSContext* cx, unsigned argc, Value* vp)
 {
     ShellRuntime* sr = GetShellRuntime(cx);
     CallArgs args = CallArgsFromVp(argc, vp);
 
     TimeDuration duration = TimeDuration::FromSeconds(0.0);
     if (args.length() > 0) {
@@ -3198,39 +3185,39 @@ WatchdogMain(void* arg)
 {
     PR_SetCurrentThreadName("JS Watchdog");
 
     JSRuntime* rt = (JSRuntime*) arg;
     ShellRuntime* sr = GetShellRuntime(rt);
 
     PR_Lock(sr->watchdogLock);
     while (sr->watchdogThread) {
-        int64_t now = PRMJ_Now();
-        if (sr->watchdogHasTimeout && !IsBefore(now, sr->watchdogTimeout)) {
+        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->watchdogHasTimeout = false;
+            sr->watchdogTimeout = Nothing();
             PR_Unlock(sr->watchdogLock);
             CancelExecution(rt);
             PR_Lock(sr->watchdogLock);
 
             /* Wake up any threads doing sleep. */
             PR_NotifyAllCondVar(sr->sleepWakeup);
         } else {
-            if (sr->watchdogHasTimeout) {
+            if (sr->watchdogTimeout.isSome()) {
                 /*
                  * Time hasn't expired yet. Simulate an interrupt callback
                  * which doesn't abort execution.
                  */
                 JS_RequestInterruptCallback(rt);
             }
 
-            TimeDuration sleepDuration = sr->watchdogHasTimeout
+            TimeDuration sleepDuration = sr->watchdogTimeout.isSome()
                                          ? TimeDuration::FromSeconds(0.1)
                                          : TimeDuration::Forever();
             mozilla::DebugOnly<PRStatus> status =
               PR_WaitCondVar(sr->watchdogWakeup, DurationToPRInterval(sleepDuration));
             MOZ_ASSERT(status == PR_SUCCESS);
         }
     }
     PR_Unlock(sr->watchdogLock);
@@ -3238,42 +3225,41 @@ WatchdogMain(void* arg)
 
 static bool
 ScheduleWatchdog(JSRuntime* rt, double t)
 {
     ShellRuntime* sr = GetShellRuntime(rt);
 
     if (t <= 0) {
         PR_Lock(sr->watchdogLock);
-        sr->watchdogHasTimeout = false;
+        sr->watchdogTimeout = Nothing();
         PR_Unlock(sr->watchdogLock);
         return true;
     }
 
-    int64_t interval = int64_t(ceil(t * PRMJ_USEC_PER_SEC));
-    int64_t timeout = PRMJ_Now() + interval;
+    auto interval = TimeDuration::FromSeconds(t);
+    auto timeout = TimeStamp::Now() + interval;
     PR_Lock(sr->watchdogLock);
     if (!sr->watchdogThread) {
-        MOZ_ASSERT(!sr->watchdogHasTimeout);
+        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) {
             PR_Unlock(sr->watchdogLock);
             return false;
         }
-    } else if (!sr->watchdogHasTimeout || IsBefore(timeout, sr->watchdogTimeout)) {
+    } else if (sr->watchdogTimeout.isNothing() || timeout < sr->watchdogTimeout.value()) {
          PR_NotifyCondVar(sr->watchdogWakeup);
     }
-    sr->watchdogHasTimeout = true;
-    sr->watchdogTimeout = timeout;
+    sr->watchdogTimeout = Some(timeout);
     PR_Unlock(sr->watchdogLock);
     return true;
 }
 
 static void
 KillWorkerThreads()
 {
     MOZ_ASSERT_IF(!CanUseExtraThreads(), workerThreads.empty());