<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[188329] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/188329">188329</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2015-08-11 22:56:20 -0700 (Tue, 11 Aug 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implementation JavaScript watchdog using WTF::WorkQueue.
https://bugs.webkit.org/show_bug.cgi?id=147107

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

How the Watchdog works?
======================

1. When do we start the Watchdog?
   =============================
   The watchdog should only be started if both the following conditions are true:
   1. A time limit has been set.
   2. We have entered the VM.
 
2. CPU time vs Wall Clock time
   ===========================
   Why do we need 2 time deadlines: m_cpuDeadline and m_wallClockDeadline?

   The watchdog uses WorkQueue dispatchAfter() to queue a timer to measure the watchdog time
   limit. WorkQueue timers measure time in monotonic wall clock time. m_wallClockDeadline
   indicates the wall clock time point when the WorkQueue timer is expected to fire.

   The time limit for which we allow JS code to run should be measured in CPU time, which can
   differ from wall clock time.  m_cpuDeadline indicates the CPU time point when the watchdog
   should fire.

   Note: the timer firing is not the same thing as the watchdog firing.  When the timer fires,
   we need to check if m_cpuDeadline has been reached.

   If m_cpuDeadline has been reached, the watchdog is considered to have fired.

   If not, then we have a remaining amount of CPU time, Tremainder, that we should allow JS
   code to continue to run for.  Hence, we need to start a new timer to fire again after
   Tremainder microseconds.
    
   See Watchdog::didFireSlow().

3. Spurious wake ups
   =================
   Because the WorkQueue timer cannot be cancelled, the watchdog needs to ignore stale timers.
   It does this by checking the m_wallClockDeadline.  A wakeup that occurs right after
   m_wallClockDeadline expires is considered to be the wakeup for the active timer.  All other
   wake ups are considered to be spurious and will be ignored.
 
   See Watchdog::didFireSlow().
 
4. Minimizing Timer creation cost
   ==============================
   Conceptually, we could start a new timer every time we start the watchdog. But we can do better
   than this.
 
   In practice, the time limit of a watchdog tends to be long, and the amount of time a watchdog
   stays active tends to be short for well-behaved JS code. The user also tends to re-use the same
   time limit. Consider the following example:
 
       |---|-----|---|----------------|---------|
       t0  t1    t2  t3            t0 + L    t2 + L 

       |&lt;--- T1 ---------------------&gt;|
                 |&lt;--- T2 ---------------------&gt;|
       |&lt;-- Td -&gt;|                    |&lt;-- Td -&gt;|

   1. The user initializes the watchdog with time limit L.
   2. At t0, we enter the VM to execute JS code, and starts the watchdog timer, T1.
      The timer is set to expire at t0 + L.
   3. At t1, we exit the VM.
   4. At t2, we enter the VM again, and would like to start a new watchdog timer, T2.
         
      However, we can note that the expiration time for T2 would be after the expiration time
      of T1. Specifically, T2 would have expired at Td after T1 expires.
         
      Hence, we can just wait for T1 to expire, and then start a new timer T2' at time t0 + L
      for a period or Td instead.

   Note that didFireSlow() already compensates for time differences between wall clock and CPU time,
   as well as handle spurious wake ups (see note 2 and 3 above).  As a result, didFireSlow() will
   automatically take care of starting a new timer for the difference Td in the example above.
   Instead of starting the new timer T2 and time t2, we just verify that if the active timer, T1's
   expiration is less than T2s, then we are already covered by T1 and there's no need to start T2.

   The benefit:

   1. we minimize the number of timer instances we have queued in the workqueue at the same time
      (ideally only 1 or 0), and use less peak memory usage.

   2. we minimize the frequency of instantiating timer instances. By waiting for the current
      active timer to expire first, on average, we get to start one timer per time limit
      (which is infrequent because time limits tend to be long) instead of one timer per
      VM entry (which tends to be frequent).

   See Watchdog::startTimer().

* API/JSContextRef.cpp:
(createWatchdogIfNeeded):
(JSContextGroupClearExecutionTimeLimit):
- No need to create the watchdog (if not already created) just to clear it.
  If the watchdog is not created yet, then it is effectively cleared.

* API/tests/ExecutionTimeLimitTest.cpp:
(currentCPUTimeAsJSFunctionCallback):
(testExecutionTimeLimit):
(currentCPUTime): Deleted.
* API/tests/testapi.c:
(main):
* JavaScriptCore.vcxproj/testapi/testapi.vcxproj:
* JavaScriptCore.vcxproj/testapi/testapi.vcxproj.filters:
- Enable watchdog tests for all platforms.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
- Remove now unneeded WatchdogMac.cpp and WatchdogNone.cpp.

* PlatformEfl.cmake:

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGSpeculativeJIT32_64.cpp:
* dfg/DFGSpeculativeJIT64.cpp:
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_loop_hint):
(JSC::JIT::emitSlow_op_loop_hint):
* jit/JITOperations.cpp:
* llint/LLIntOffsetsExtractor.cpp:
* llint/LLIntSlowPaths.cpp:
* runtime/VM.cpp:
- #include Watchdog.h in these files directly instead of doing it via VM.h.
  These saves us from having to recompile the world when we change Watchdog.h.

* runtime/VM.h:
- See comment in Watchdog::startTimer() below for why the Watchdog needs to be
  thread-safe ref counted.

* runtime/VMEntryScope.cpp:
(JSC::VMEntryScope::VMEntryScope):
(JSC::VMEntryScope::~VMEntryScope):
- We have done away with the WatchdogScope and arming/disarming of the watchdog.
  Instead, the VMEntryScope will inform the watchdog of when we have entered and
  exited the VM.

* runtime/Watchdog.cpp:
(JSC::currentWallClockTime):
(JSC::Watchdog::Watchdog):
(JSC::Watchdog::hasStartedTimer):
(JSC::Watchdog::setTimeLimit):
(JSC::Watchdog::didFireSlow):
(JSC::Watchdog::hasTimeLimit):
(JSC::Watchdog::fire):
(JSC::Watchdog::enteredVM):
(JSC::Watchdog::exitedVM):

(JSC::Watchdog::startTimer):
- The Watchdog is now thread-safe ref counted because the WorkQueue may access it
  (from a different thread) even after the VM shuts down.  We need to keep it
  alive until the WorkQueue callback completes.

  In Watchdog::startTimer(), we'll ref the Watchdog to keep it alive for each
  WorkQueue callback we dispatch.  The callback will deref the Watchdog after it
  is done with it.  This ensures that the Watchdog is kept alive until all
  WorkQueue callbacks are done.

(JSC::Watchdog::stopTimer):
(JSC::Watchdog::~Watchdog): Deleted.
(JSC::Watchdog::didFire): Deleted.
(JSC::Watchdog::isEnabled): Deleted.
(JSC::Watchdog::arm): Deleted.
(JSC::Watchdog::disarm): Deleted.
(JSC::Watchdog::startCountdownIfNeeded): Deleted.
(JSC::Watchdog::startCountdown): Deleted.
(JSC::Watchdog::stopCountdown): Deleted.
* runtime/Watchdog.h:
(JSC::Watchdog::didFire):
(JSC::Watchdog::timerDidFireAddress):
(JSC::Watchdog::isArmed): Deleted.
(JSC::Watchdog::Scope::Scope): Deleted.
(JSC::Watchdog::Scope::~Scope): Deleted.
* runtime/WatchdogMac.cpp:
(JSC::Watchdog::initTimer): Deleted.
(JSC::Watchdog::destroyTimer): Deleted.
(JSC::Watchdog::startTimer): Deleted.
(JSC::Watchdog::stopTimer): Deleted.
* runtime/WatchdogNone.cpp:
(JSC::Watchdog::initTimer): Deleted.
(JSC::Watchdog::destroyTimer): Deleted.
(JSC::Watchdog::startTimer): Deleted.
(JSC::Watchdog::stopTimer): Deleted.

Source/WebCore:

No new tests because we're not introducing any behavior change to WebCore here.
We're only #include'ing Watchdog.h directly instead of going through VM.h.

* ForwardingHeaders/runtime/Watchdog.h: Added.
* PlatformEfl.cmake:
* WebCore.vcxproj/WebCore.vcxproj:
* WebCore.vcxproj/WebCore.vcxproj.filters:
* bindings/js/JSEventListener.cpp:
* bindings/js/WorkerScriptController.cpp:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreAPIJSContextRefcpp">trunk/Source/JavaScriptCore/API/JSContextRef.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreAPItestsExecutionTimeLimitTestcpp">trunk/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreAPIteststestapic">trunk/Source/JavaScriptCore/API/tests/testapi.c</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojtestapitestapivcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/testapi/testapi.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojtestapitestapivcxprojfilters">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/testapi/testapi.vcxproj.filters</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorePlatformEflcmake">trunk/Source/JavaScriptCore/PlatformEfl.cmake</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntOffsetsExtractorcpp">trunk/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMEntryScopecpp">trunk/Source/JavaScriptCore/runtime/VMEntryScope.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeWatchdogcpp">trunk/Source/JavaScriptCore/runtime/Watchdog.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeWatchdogh">trunk/Source/JavaScriptCore/runtime/Watchdog.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeWatchdogMaccpp">trunk/Source/JavaScriptCore/runtime/WatchdogMac.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeWatchdogNonecpp">trunk/Source/JavaScriptCore/runtime/WatchdogNone.cpp</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorePlatformEflcmake">trunk/Source/WebCore/PlatformEfl.cmake</a></li>
<li><a href="#trunkSourceWebCoreWebCorevcxprojWebCorevcxproj">trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj</a></li>
<li><a href="#trunkSourceWebCoreWebCorevcxprojWebCorevcxprojfilters">trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSEventListenercpp">trunk/Source/WebCore/bindings/js/JSEventListener.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsWorkerScriptControllercpp">trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreForwardingHeadersruntimeWatchdogh">trunk/Source/WebCore/ForwardingHeaders/runtime/Watchdog.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreAPIJSContextRefcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/JSContextRef.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/JSContextRef.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/API/JSContextRef.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;SourceProvider.h&quot;
</span><span class="cx"> #include &quot;StackVisitor.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span><span class="cx"> #include &lt;wtf/text/StringHash.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -94,7 +95,7 @@
</span><span class="cx"> static void createWatchdogIfNeeded(VM&amp; vm)
</span><span class="cx"> {
</span><span class="cx">     if (!vm.watchdog) {
</span><del>-        vm.watchdog = std::make_unique&lt;Watchdog&gt;();
</del><ins>+        vm.watchdog = adoptRef(new Watchdog());
</ins><span class="cx"> 
</span><span class="cx">         // The LLINT peeks into the Watchdog object directly. In order to do that,
</span><span class="cx">         // the LLINT assumes that the internal shape of a std::unique_ptr is the
</span><span class="lines">@@ -120,9 +121,8 @@
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = *toJS(group);
</span><span class="cx">     JSLockHolder locker(&amp;vm);
</span><del>-    createWatchdogIfNeeded(vm);
-    Watchdog&amp; watchdog = *vm.watchdog;
-    watchdog.setTimeLimit(vm, std::chrono::microseconds::max());
</del><ins>+    if (vm.watchdog)
+        vm.watchdog-&gt;setTimeLimit(vm, Watchdog::noTimeLimit);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // From the API's perspective, a global context remains alive iff it has been JSGlobalContextRetained.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreAPItestsExecutionTimeLimitTestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -26,34 +26,15 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;ExecutionTimeLimitTest.h&quot;
</span><span class="cx"> 
</span><del>-#if OS(DARWIN)
-
</del><span class="cx"> #include &quot;JSContextRefPrivate.h&quot;
</span><span class="cx"> #include &quot;JavaScriptCore.h&quot;
</span><ins>+#include &lt;chrono&gt;
+#include &lt;wtf/CurrentTime.h&gt;
</ins><span class="cx"> 
</span><del>-#include &lt;mach/mach.h&gt;
-#include &lt;mach/mach_time.h&gt;
-#include &lt;stdio.h&gt;
-#include &lt;sys/time.h&gt;
</del><ins>+using namespace std::chrono;
</ins><span class="cx"> 
</span><span class="cx"> static JSGlobalContextRef context = nullptr;
</span><span class="cx"> 
</span><del>-static double currentCPUTime()
-{
-    mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
-    thread_basic_info_data_t info;
-    
-    /* Get thread information */
-    mach_port_t threadPort = mach_thread_self();
-    thread_info(threadPort, THREAD_BASIC_INFO, (thread_info_t)(&amp;info), &amp;infoCount);
-    mach_port_deallocate(mach_task_self(), threadPort);
-    
-    double time = info.user_time.seconds + info.user_time.microseconds / 1000000.;
-    time += info.system_time.seconds + info.system_time.microseconds / 1000000.;
-    
-    return time;
-}
-
</del><span class="cx"> static JSValueRef currentCPUTimeAsJSFunctionCallback(JSContextRef ctx, JSObjectRef functionObject, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(functionObject);
</span><span class="lines">@@ -63,7 +44,7 @@
</span><span class="cx">     UNUSED_PARAM(exception);
</span><span class="cx">     
</span><span class="cx">     ASSERT(JSContextGetGlobalContext(ctx) == context);
</span><del>-    return JSValueMakeNumber(ctx, currentCPUTime());
</del><ins>+    return JSValueMakeNumber(ctx, currentCPUTime().count() / 1000000.);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool shouldTerminateCallbackWasCalled = false;
</span><span class="lines">@@ -120,18 +101,16 @@
</span><span class="cx">     {
</span><span class="cx">         const char* loopForeverScript = &quot;var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime &gt; .150) break; } &quot;;
</span><span class="cx">         JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
</span><del>-        double startTime;
-        double endTime;
</del><span class="cx">         exception = nullptr;
</span><span class="cx">         shouldTerminateCallbackWasCalled = false;
</span><del>-        startTime = currentCPUTime();
</del><ins>+        auto startTime = currentCPUTime();
</ins><span class="cx">         v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &amp;exception);
</span><del>-        endTime = currentCPUTime();
</del><ins>+        auto endTime = currentCPUTime();
</ins><span class="cx">         
</span><del>-        if (((endTime - startTime) &lt; .150f) &amp;&amp; shouldTerminateCallbackWasCalled)
</del><ins>+        if (((endTime - startTime) &lt; milliseconds(150)) &amp;&amp; shouldTerminateCallbackWasCalled)
</ins><span class="cx">             printf(&quot;PASS: script timed out as expected.\n&quot;);
</span><span class="cx">         else {
</span><del>-            if (!((endTime - startTime) &lt; .150f))
</del><ins>+            if (!((endTime - startTime) &lt; milliseconds(150)))
</ins><span class="cx">                 printf(&quot;FAIL: script did not time out as expected.\n&quot;);
</span><span class="cx">             if (!shouldTerminateCallbackWasCalled)
</span><span class="cx">                 printf(&quot;FAIL: script timeout callback was not called.\n&quot;);
</span><span class="lines">@@ -149,16 +128,14 @@
</span><span class="cx">     {
</span><span class="cx">         const char* loopForeverScript = &quot;var startTime = currentCPUTime(); try { while (true) { if (currentCPUTime() - startTime &gt; .150) break; } } catch(e) { }&quot;;
</span><span class="cx">         JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
</span><del>-        double startTime;
-        double endTime;
</del><span class="cx">         exception = nullptr;
</span><span class="cx">         shouldTerminateCallbackWasCalled = false;
</span><del>-        startTime = currentCPUTime();
</del><ins>+        auto startTime = currentCPUTime();
</ins><span class="cx">         v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &amp;exception);
</span><del>-        endTime = currentCPUTime();
</del><ins>+        auto endTime = currentCPUTime();
</ins><span class="cx">         
</span><del>-        if (((endTime - startTime) &gt;= .150f) || !shouldTerminateCallbackWasCalled) {
-            if (!((endTime - startTime) &lt; .150f))
</del><ins>+        if (((endTime - startTime) &gt;= milliseconds(150)) || !shouldTerminateCallbackWasCalled) {
+            if (!((endTime - startTime) &lt; milliseconds(150)))
</ins><span class="cx">                 printf(&quot;FAIL: script did not time out as expected.\n&quot;);
</span><span class="cx">             if (!shouldTerminateCallbackWasCalled)
</span><span class="cx">                 printf(&quot;FAIL: script timeout callback was not called.\n&quot;);
</span><span class="lines">@@ -178,17 +155,15 @@
</span><span class="cx">     {
</span><span class="cx">         const char* loopForeverScript = &quot;var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime &gt; .150) break; } &quot;;
</span><span class="cx">         JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
</span><del>-        double startTime;
-        double endTime;
</del><span class="cx">         exception = nullptr;
</span><del>-        startTime = currentCPUTime();
</del><ins>+        auto startTime = currentCPUTime();
</ins><span class="cx">         v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &amp;exception);
</span><del>-        endTime = currentCPUTime();
</del><ins>+        auto endTime = currentCPUTime();
</ins><span class="cx">         
</span><del>-        if (((endTime - startTime) &lt; .150f) &amp;&amp; shouldTerminateCallbackWasCalled)
</del><ins>+        if (((endTime - startTime) &lt; milliseconds(150)) &amp;&amp; shouldTerminateCallbackWasCalled)
</ins><span class="cx">             printf(&quot;PASS: script timed out as expected when no callback is specified.\n&quot;);
</span><span class="cx">         else {
</span><del>-            if (!((endTime - startTime) &lt; .150f))
</del><ins>+            if (!((endTime - startTime) &lt; milliseconds(150)))
</ins><span class="cx">                 printf(&quot;FAIL: script did not time out as expected when no callback is specified.\n&quot;);
</span><span class="cx">             failed = true;
</span><span class="cx">         }
</span><span class="lines">@@ -204,17 +179,15 @@
</span><span class="cx">     {
</span><span class="cx">         const char* loopForeverScript = &quot;var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime &gt; .150) break; } &quot;;
</span><span class="cx">         JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
</span><del>-        double startTime;
-        double endTime;
</del><span class="cx">         exception = nullptr;
</span><del>-        startTime = currentCPUTime();
</del><ins>+        auto startTime = currentCPUTime();
</ins><span class="cx">         v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &amp;exception);
</span><del>-        endTime = currentCPUTime();
</del><ins>+        auto endTime = currentCPUTime();
</ins><span class="cx">         
</span><del>-        if (((endTime - startTime) &gt;= .150f) &amp;&amp; cancelTerminateCallbackWasCalled &amp;&amp; !exception)
</del><ins>+        if (((endTime - startTime) &gt;= milliseconds(150)) &amp;&amp; cancelTerminateCallbackWasCalled &amp;&amp; !exception)
</ins><span class="cx">             printf(&quot;PASS: script timeout was cancelled as expected.\n&quot;);
</span><span class="cx">         else {
</span><del>-            if (((endTime - startTime) &lt; .150) || exception)
</del><ins>+            if (((endTime - startTime) &lt; milliseconds(150)) || exception)
</ins><span class="cx">                 printf(&quot;FAIL: script timeout was not cancelled.\n&quot;);
</span><span class="cx">             if (!cancelTerminateCallbackWasCalled)
</span><span class="cx">                 printf(&quot;FAIL: script timeout callback was not called.\n&quot;);
</span><span class="lines">@@ -232,21 +205,18 @@
</span><span class="cx">     {
</span><span class="cx">         const char* loopForeverScript = &quot;var startTime = currentCPUTime(); while (true) { if (currentCPUTime() - startTime &gt; .500) break; } &quot;;
</span><span class="cx">         JSStringRef script = JSStringCreateWithUTF8CString(loopForeverScript);
</span><del>-        double startTime;
-        double endTime;
-        double deltaTime;
</del><span class="cx">         exception = nullptr;
</span><del>-        startTime = currentCPUTime();
</del><ins>+        auto startTime = currentCPUTime();
</ins><span class="cx">         v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &amp;exception);
</span><del>-        endTime = currentCPUTime();
-        deltaTime = endTime - startTime;
</del><ins>+        auto endTime = currentCPUTime();
+        auto deltaTime = endTime - startTime;
</ins><span class="cx">         
</span><del>-        if ((deltaTime &gt;= .300f) &amp;&amp; (deltaTime &lt; .500f) &amp;&amp; (extendTerminateCallbackCalled == 2) &amp;&amp; exception)
</del><ins>+        if ((deltaTime &gt;= milliseconds(300)) &amp;&amp; (deltaTime &lt; milliseconds(500)) &amp;&amp; (extendTerminateCallbackCalled == 2) &amp;&amp; exception)
</ins><span class="cx">             printf(&quot;PASS: script timeout was extended as expected.\n&quot;);
</span><span class="cx">         else {
</span><del>-            if (deltaTime &lt; .200f)
</del><ins>+            if (deltaTime &lt; milliseconds(200))
</ins><span class="cx">                 printf(&quot;FAIL: script timeout was not extended as expected.\n&quot;);
</span><del>-            else if (deltaTime &gt;= .500f)
</del><ins>+            else if (deltaTime &gt;= milliseconds(500))
</ins><span class="cx">                 printf(&quot;FAIL: script did not timeout.\n&quot;);
</span><span class="cx">             
</span><span class="cx">             if (extendTerminateCallbackCalled &lt; 1)
</span><span class="lines">@@ -264,5 +234,3 @@
</span><span class="cx">     JSGlobalContextRelease(context);
</span><span class="cx">     return failed;
</span><span class="cx"> }
</span><del>-
-#endif // OS(DARWIN)
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreAPIteststestapic"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/tests/testapi.c (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/tests/testapi.c        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/API/tests/testapi.c        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -43,9 +43,7 @@
</span><span class="cx"> #include &quot;CustomGlobalObjectClassTest.h&quot;
</span><span class="cx"> #include &quot;GlobalContextWithFinalizerTest.h&quot;
</span><span class="cx"> 
</span><del>-#if OS(DARWIN)
</del><span class="cx"> #include &quot;ExecutionTimeLimitTest.h&quot;
</span><del>-#endif
</del><span class="cx"> 
</span><span class="cx"> #if JSC_OBJC_API_ENABLED
</span><span class="cx"> void testObjectiveCAPI(void);
</span><span class="lines">@@ -1893,9 +1891,7 @@
</span><span class="cx">         JSGlobalContextRelease(context);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-#if OS(DARWIN)
</del><span class="cx">     failed = testExecutionTimeLimit() || failed;
</span><del>-#endif /* OS(DARWIN) */
</del><span class="cx">     failed = testGlobalContextWithFinalizer() || failed;
</span><span class="cx"> 
</span><span class="cx">     // Clear out local variables pointing at JSObjectRefs to allow their values to be collected
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -617,7 +617,6 @@
</span><span class="cx">     runtime/VMEntryScope.cpp
</span><span class="cx">     runtime/VarOffset.cpp
</span><span class="cx">     runtime/Watchdog.cpp
</span><del>-    runtime/WatchdogNone.cpp
</del><span class="cx">     runtime/WeakMapConstructor.cpp
</span><span class="cx">     runtime/WeakMapData.cpp
</span><span class="cx">     runtime/WeakMapPrototype.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -1,3 +1,197 @@
</span><ins>+2015-08-11  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        Implementation JavaScript watchdog using WTF::WorkQueue.
+        https://bugs.webkit.org/show_bug.cgi?id=147107
+
+        Reviewed by Geoffrey Garen.
+
+        How the Watchdog works?
+        ======================
+
+        1. When do we start the Watchdog?
+           =============================
+           The watchdog should only be started if both the following conditions are true:
+           1. A time limit has been set.
+           2. We have entered the VM.

+        2. CPU time vs Wall Clock time
+           ===========================
+           Why do we need 2 time deadlines: m_cpuDeadline and m_wallClockDeadline?
+
+           The watchdog uses WorkQueue dispatchAfter() to queue a timer to measure the watchdog time
+           limit. WorkQueue timers measure time in monotonic wall clock time. m_wallClockDeadline
+           indicates the wall clock time point when the WorkQueue timer is expected to fire.
+
+           The time limit for which we allow JS code to run should be measured in CPU time, which can
+           differ from wall clock time.  m_cpuDeadline indicates the CPU time point when the watchdog
+           should fire.
+
+           Note: the timer firing is not the same thing as the watchdog firing.  When the timer fires,
+           we need to check if m_cpuDeadline has been reached.
+
+           If m_cpuDeadline has been reached, the watchdog is considered to have fired.
+
+           If not, then we have a remaining amount of CPU time, Tremainder, that we should allow JS
+           code to continue to run for.  Hence, we need to start a new timer to fire again after
+           Tremainder microseconds.
+    
+           See Watchdog::didFireSlow().
+
+        3. Spurious wake ups
+           =================
+           Because the WorkQueue timer cannot be cancelled, the watchdog needs to ignore stale timers.
+           It does this by checking the m_wallClockDeadline.  A wakeup that occurs right after
+           m_wallClockDeadline expires is considered to be the wakeup for the active timer.  All other
+           wake ups are considered to be spurious and will be ignored.

+           See Watchdog::didFireSlow().

+        4. Minimizing Timer creation cost
+           ==============================
+           Conceptually, we could start a new timer every time we start the watchdog. But we can do better
+           than this.

+           In practice, the time limit of a watchdog tends to be long, and the amount of time a watchdog
+           stays active tends to be short for well-behaved JS code. The user also tends to re-use the same
+           time limit. Consider the following example:

+               |---|-----|---|----------------|---------|
+               t0  t1    t2  t3            t0 + L    t2 + L 
+
+               |&lt;--- T1 ---------------------&gt;|
+                         |&lt;--- T2 ---------------------&gt;|
+               |&lt;-- Td -&gt;|                    |&lt;-- Td -&gt;|
+
+           1. The user initializes the watchdog with time limit L.
+           2. At t0, we enter the VM to execute JS code, and starts the watchdog timer, T1.
+              The timer is set to expire at t0 + L.
+           3. At t1, we exit the VM.
+           4. At t2, we enter the VM again, and would like to start a new watchdog timer, T2.
+         
+              However, we can note that the expiration time for T2 would be after the expiration time
+              of T1. Specifically, T2 would have expired at Td after T1 expires.
+         
+              Hence, we can just wait for T1 to expire, and then start a new timer T2' at time t0 + L
+              for a period or Td instead.
+
+           Note that didFireSlow() already compensates for time differences between wall clock and CPU time,
+           as well as handle spurious wake ups (see note 2 and 3 above).  As a result, didFireSlow() will
+           automatically take care of starting a new timer for the difference Td in the example above.
+           Instead of starting the new timer T2 and time t2, we just verify that if the active timer, T1's
+           expiration is less than T2s, then we are already covered by T1 and there's no need to start T2.
+
+           The benefit:
+
+           1. we minimize the number of timer instances we have queued in the workqueue at the same time
+              (ideally only 1 or 0), and use less peak memory usage.
+
+           2. we minimize the frequency of instantiating timer instances. By waiting for the current
+              active timer to expire first, on average, we get to start one timer per time limit
+              (which is infrequent because time limits tend to be long) instead of one timer per
+              VM entry (which tends to be frequent).
+
+           See Watchdog::startTimer().
+
+        * API/JSContextRef.cpp:
+        (createWatchdogIfNeeded):
+        (JSContextGroupClearExecutionTimeLimit):
+        - No need to create the watchdog (if not already created) just to clear it.
+          If the watchdog is not created yet, then it is effectively cleared.
+
+        * API/tests/ExecutionTimeLimitTest.cpp:
+        (currentCPUTimeAsJSFunctionCallback):
+        (testExecutionTimeLimit):
+        (currentCPUTime): Deleted.
+        * API/tests/testapi.c:
+        (main):
+        * JavaScriptCore.vcxproj/testapi/testapi.vcxproj:
+        * JavaScriptCore.vcxproj/testapi/testapi.vcxproj.filters:
+        - Enable watchdog tests for all platforms.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        - Remove now unneeded WatchdogMac.cpp and WatchdogNone.cpp.
+
+        * PlatformEfl.cmake:
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        * dfg/DFGSpeculativeJIT64.cpp:
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_loop_hint):
+        (JSC::JIT::emitSlow_op_loop_hint):
+        * jit/JITOperations.cpp:
+        * llint/LLIntOffsetsExtractor.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        * runtime/VM.cpp:
+        - #include Watchdog.h in these files directly instead of doing it via VM.h.
+          These saves us from having to recompile the world when we change Watchdog.h.
+
+        * runtime/VM.h:
+        - See comment in Watchdog::startTimer() below for why the Watchdog needs to be
+          thread-safe ref counted.
+
+        * runtime/VMEntryScope.cpp:
+        (JSC::VMEntryScope::VMEntryScope):
+        (JSC::VMEntryScope::~VMEntryScope):
+        - We have done away with the WatchdogScope and arming/disarming of the watchdog.
+          Instead, the VMEntryScope will inform the watchdog of when we have entered and
+          exited the VM.
+
+        * runtime/Watchdog.cpp:
+        (JSC::currentWallClockTime):
+        (JSC::Watchdog::Watchdog):
+        (JSC::Watchdog::hasStartedTimer):
+        (JSC::Watchdog::setTimeLimit):
+        (JSC::Watchdog::didFireSlow):
+        (JSC::Watchdog::hasTimeLimit):
+        (JSC::Watchdog::fire):
+        (JSC::Watchdog::enteredVM):
+        (JSC::Watchdog::exitedVM):
+
+        (JSC::Watchdog::startTimer):
+        - The Watchdog is now thread-safe ref counted because the WorkQueue may access it
+          (from a different thread) even after the VM shuts down.  We need to keep it
+          alive until the WorkQueue callback completes.
+
+          In Watchdog::startTimer(), we'll ref the Watchdog to keep it alive for each
+          WorkQueue callback we dispatch.  The callback will deref the Watchdog after it
+          is done with it.  This ensures that the Watchdog is kept alive until all
+          WorkQueue callbacks are done.
+
+        (JSC::Watchdog::stopTimer):
+        (JSC::Watchdog::~Watchdog): Deleted.
+        (JSC::Watchdog::didFire): Deleted.
+        (JSC::Watchdog::isEnabled): Deleted.
+        (JSC::Watchdog::arm): Deleted.
+        (JSC::Watchdog::disarm): Deleted.
+        (JSC::Watchdog::startCountdownIfNeeded): Deleted.
+        (JSC::Watchdog::startCountdown): Deleted.
+        (JSC::Watchdog::stopCountdown): Deleted.
+        * runtime/Watchdog.h:
+        (JSC::Watchdog::didFire):
+        (JSC::Watchdog::timerDidFireAddress):
+        (JSC::Watchdog::isArmed): Deleted.
+        (JSC::Watchdog::Scope::Scope): Deleted.
+        (JSC::Watchdog::Scope::~Scope): Deleted.
+        * runtime/WatchdogMac.cpp:
+        (JSC::Watchdog::initTimer): Deleted.
+        (JSC::Watchdog::destroyTimer): Deleted.
+        (JSC::Watchdog::startTimer): Deleted.
+        (JSC::Watchdog::stopTimer): Deleted.
+        * runtime/WatchdogNone.cpp:
+        (JSC::Watchdog::initTimer): Deleted.
+        (JSC::Watchdog::destroyTimer): Deleted.
+        (JSC::Watchdog::startTimer): Deleted.
+        (JSC::Watchdog::stopTimer): Deleted.
+
</ins><span class="cx"> 2015-08-11  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Always use a byte-sized lock implementation
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -870,7 +870,6 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\VMEntryScope.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\VarOffset.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\Watchdog.cpp&quot; /&gt;
</span><del>-    &lt;ClCompile Include=&quot;..\runtime\WatchdogNone.cpp&quot; /&gt;
</del><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\WeakMapConstructor.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\WeakMapData.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\WeakMapPrototype.cpp&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -936,9 +936,6 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\Watchdog.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;runtime&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><del>-    &lt;ClCompile Include=&quot;..\runtime\WatchdogNone.cpp&quot;&gt;
-      &lt;Filter&gt;runtime&lt;/Filter&gt;
-    &lt;/ClCompile&gt;
</del><span class="cx">     &lt;ClCompile Include=&quot;..\tools\CodeProfile.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;tools&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojtestapitestapivcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/testapi/testapi.vcxproj (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/testapi/testapi.vcxproj        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/testapi/testapi.vcxproj        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -297,6 +297,8 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\..\API\tests\CompareAndSwapTest.h&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\..\API\tests\CustomGlobalObjectClassTest.c&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\..\API\tests\CustomGlobalObjectClassTest.h&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\..\API\tests\ExecutionTimeLimitTest.cpp&quot; /&gt;
+    &lt;ClInclude Include=&quot;..\..\API\tests\ExecutionTimeLimitTest.h&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\..\API\tests\GlobalContextWithFinalizerTest.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\..\API\tests\GlobalContextWithFinalizerTest.h&quot; /&gt;
</span><span class="cx">   &lt;/ItemGroup&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojtestapitestapivcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/testapi/testapi.vcxproj.filters (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/testapi/testapi.vcxproj.filters        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/testapi/testapi.vcxproj.filters        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -12,6 +12,8 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\..\API\tests\CompareAndSwapTest.h&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\..\API\tests\CustomGlobalObjectClassTest.c&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\..\API\tests\CustomGlobalObjectClassTest.h&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\..\API\tests\ExecutionTimeLimitTest.cpp&quot; /&gt;
+    &lt;ClInclude Include=&quot;..\..\API\tests\ExecutionTimeLimitTest.h&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\..\API\tests\GlobalContextWithFinalizerTest.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\..\API\tests\GlobalContextWithFinalizerTest.h&quot; /&gt;
</span><span class="cx">   &lt;/ItemGroup&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -1728,7 +1728,6 @@
</span><span class="cx">                 FED287B215EC9A5700DA8161 /* LLIntOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = FED287B115EC9A5700DA8161 /* LLIntOpcode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 FED94F2E171E3E2300BE77A4 /* Watchdog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */; };
</span><span class="cx">                 FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                FED94F30171E3E2300BE77A4 /* WatchdogMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED94F2D171E3E2300BE77A4 /* WatchdogMac.cpp */; };
</del><span class="cx">                 FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
</span><span class="cx">                 FEF6835E174343CC00A32E25 /* JITStubsARM.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF6835A174343CC00A32E25 /* JITStubsARM.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 FEF6835F174343CC00A32E25 /* JITStubsARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF6835B174343CC00A32E25 /* JITStubsARMv7.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -3587,7 +3586,6 @@
</span><span class="cx">                 FED287B115EC9A5700DA8161 /* LLIntOpcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntOpcode.h; path = llint/LLIntOpcode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Watchdog.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FED94F2C171E3E2300BE77A4 /* Watchdog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Watchdog.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                FED94F2D171E3E2300BE77A4 /* WatchdogMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WatchdogMac.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FEF6835A174343CC00A32E25 /* JITStubsARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITStubsARM.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4920,7 +4918,6 @@
</span><span class="cx">                                 FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
</span><span class="cx">                                 FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
</span><span class="cx">                                 FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
</span><del>-                                FED94F2D171E3E2300BE77A4 /* WatchdogMac.cpp */,
</del><span class="cx">                                 14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
</span><span class="cx">                                 AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */,
</span><span class="cx">                                 A7CA3ADD17DA41AE006538AF /* WeakMapConstructor.cpp */,
</span><span class="lines">@@ -7833,7 +7830,6 @@
</span><span class="cx">                                 E18E3A590DF9278C00D90B34 /* VM.cpp in Sources */,
</span><span class="cx">                                 FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */,
</span><span class="cx">                                 FED94F2E171E3E2300BE77A4 /* Watchdog.cpp in Sources */,
</span><del>-                                FED94F30171E3E2300BE77A4 /* WatchdogMac.cpp in Sources */,
</del><span class="cx">                                 7B98D1361B60CD5F0023B1A4 /* JSWASMModule.cpp in Sources */,
</span><span class="cx">                                 0F919D2515853CE0004A4E7D /* Watchpoint.cpp in Sources */,
</span><span class="cx">                                 1ACF7377171CA6FB00C9BB1E /* Weak.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorePlatformEflcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/PlatformEfl.cmake (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/PlatformEfl.cmake        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/PlatformEfl.cmake        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -2,6 +2,7 @@
</span><span class="cx">     ${ECORE_INCLUDE_DIRS}
</span><span class="cx">     ${EINA_INCLUDE_DIRS}
</span><span class="cx">     ${EO_INCLUDE_DIRS}
</span><ins>+    &quot;${WTF_DIR}/wtf/efl&quot;
</ins><span class="cx"> )
</span><span class="cx"> add_definitions(-DSTATICALLY_LINKED_WITH_WTF)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> #include &quot;PutByIdStatus.h&quot;
</span><span class="cx"> #include &quot;StackAlignment.h&quot;
</span><span class="cx"> #include &quot;StringConstructor.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> #include &lt;wtf/CommaPrinter.h&gt;
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/MathExtras.h&gt;
</span><span class="lines">@@ -4030,7 +4031,7 @@
</span><span class="cx"> 
</span><span class="cx">             addToGraph(LoopHint);
</span><span class="cx">             
</span><del>-            if (m_vm-&gt;watchdog &amp;&amp; m_vm-&gt;watchdog-&gt;isEnabled())
</del><ins>+            if (m_vm-&gt;watchdog &amp;&amp; m_vm-&gt;watchdog-&gt;hasTimeLimit())
</ins><span class="cx">                 addToGraph(CheckWatchdogTimer);
</span><span class="cx">             
</span><span class="cx">             NEXT_OPCODE(op_loop_hint);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;SetupVarargsFrame.h&quot;
</span><span class="cx"> #include &quot;TypeProfilerLog.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> #include &quot;SetupVarargsFrame.h&quot;
</span><span class="cx"> #include &quot;SpillRegistersMode.h&quot;
</span><span class="cx"> #include &quot;TypeProfilerLog.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -71,6 +71,7 @@
</span><span class="cx"> #include &quot;Symbol.h&quot;
</span><span class="cx"> #include &quot;VMEntryScope.h&quot;
</span><span class="cx"> #include &quot;VirtualRegister.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> #include &lt;limits.h&gt;
</span><span class="cx"> #include &lt;stdio.h&gt;
</span><span class="lines">@@ -880,8 +881,6 @@
</span><span class="cx">     JSValue result;
</span><span class="cx">     {
</span><span class="cx">         SamplingTool::CallRecord callRecord(m_sampler.get());
</span><del>-        Watchdog::Scope watchdogScope(vm.watchdog.get());
-
</del><span class="cx">         result = program-&gt;generatedJITCode()-&gt;execute(&amp;vm, &amp;protoCallFrame);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -942,7 +941,6 @@
</span><span class="cx">     JSValue result;
</span><span class="cx">     {
</span><span class="cx">         SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSCall);
</span><del>-        Watchdog::Scope watchdogScope(vm.watchdog.get());
</del><span class="cx"> 
</span><span class="cx">         // Execute the code:
</span><span class="cx">         if (isJSCall)
</span><span class="lines">@@ -1013,7 +1011,6 @@
</span><span class="cx">     JSValue result;
</span><span class="cx">     {
</span><span class="cx">         SamplingTool::CallRecord callRecord(m_sampler.get(), !isJSConstruct);
</span><del>-        Watchdog::Scope watchdogScope(vm.watchdog.get());
</del><span class="cx"> 
</span><span class="cx">         // Execute the code.
</span><span class="cx">         if (isJSConstruct)
</span><span class="lines">@@ -1082,8 +1079,6 @@
</span><span class="cx">     JSValue result;
</span><span class="cx">     {
</span><span class="cx">         SamplingTool::CallRecord callRecord(m_sampler.get());
</span><del>-        Watchdog::Scope watchdogScope(vm.watchdog.get());
-
</del><span class="cx">         result = closure.functionExecutable-&gt;generatedJITCodeForCall()-&gt;execute(&amp;vm, closure.protoCallFrame);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1173,8 +1168,6 @@
</span><span class="cx">     JSValue result;
</span><span class="cx">     {
</span><span class="cx">         SamplingTool::CallRecord callRecord(m_sampler.get());
</span><del>-        Watchdog::Scope watchdogScope(vm.watchdog.get());
-
</del><span class="cx">         result = eval-&gt;generatedJITCode()-&gt;execute(&amp;vm, &amp;protoCallFrame);
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> #include &quot;TypeLocation.h&quot;
</span><span class="cx"> #include &quot;TypeProfilerLog.h&quot;
</span><span class="cx"> #include &quot;VirtualRegister.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -905,7 +906,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Emit the watchdog timer check:
</span><del>-    if (m_vm-&gt;watchdog &amp;&amp; m_vm-&gt;watchdog-&gt;isEnabled())
</del><ins>+    if (m_vm-&gt;watchdog &amp;&amp; m_vm-&gt;watchdog-&gt;hasTimeLimit())
</ins><span class="cx">         addSlowCase(branchTest8(NonZero, AbsoluteAddress(m_vm-&gt;watchdog-&gt;timerDidFireAddress())));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -931,7 +932,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     // Emit the slow path of the watchdog timer check:
</span><del>-    if (m_vm-&gt;watchdog &amp;&amp; m_vm-&gt;watchdog-&gt;isEnabled()) {
</del><ins>+    if (m_vm-&gt;watchdog &amp;&amp; m_vm-&gt;watchdog-&gt;hasTimeLimit()) {
</ins><span class="cx">         linkSlowCase(iter);
</span><span class="cx">         callOperation(operationHandleWatchdogTimer);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx"> #include &quot;ScopedArguments.h&quot;
</span><span class="cx"> #include &quot;TestRunnerUtils.h&quot;
</span><span class="cx"> #include &quot;TypeProfilerLog.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> #include &lt;wtf/InlineASM.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntOffsetsExtractorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -55,6 +55,7 @@
</span><span class="cx"> #include &quot;TypeProfilerLog.h&quot;
</span><span class="cx"> #include &quot;VMEntryRecord.h&quot;
</span><span class="cx"> #include &quot;ValueProfile.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> #include &lt;wtf/text/StringImpl.h&gt;
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx"> #include &quot;ObjectConstructor.h&quot;
</span><span class="cx"> #include &quot;ProtoCallFrame.h&quot;
</span><span class="cx"> #include &quot;StructureRareDataInlines.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> #include &lt;wtf/StringPrintStream.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace LLInt {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -85,6 +85,7 @@
</span><span class="cx"> #include &quot;TypeProfiler.h&quot;
</span><span class="cx"> #include &quot;TypeProfilerLog.h&quot;
</span><span class="cx"> #include &quot;UnlinkedCodeBlock.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> #include &quot;WeakGCMapInlines.h&quot;
</span><span class="cx"> #include &quot;WeakMapData.h&quot;
</span><span class="cx"> #include &lt;wtf/CurrentTime.h&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -50,7 +50,6 @@
</span><span class="cx"> #include &quot;ThunkGenerators.h&quot;
</span><span class="cx"> #include &quot;TypedArrayController.h&quot;
</span><span class="cx"> #include &quot;VMEntryRecord.h&quot;
</span><del>-#include &quot;Watchdog.h&quot;
</del><span class="cx"> #include &quot;Watchpoint.h&quot;
</span><span class="cx"> #include &quot;WeakRandom.h&quot;
</span><span class="cx"> #include &lt;wtf/Bag.h&gt;
</span><span class="lines">@@ -107,6 +106,7 @@
</span><span class="cx"> class UnlinkedProgramCodeBlock;
</span><span class="cx"> class VirtualRegister;
</span><span class="cx"> class VMEntryScope;
</span><ins>+class Watchdog;
</ins><span class="cx"> class Watchpoint;
</span><span class="cx"> class WatchpointSet;
</span><span class="cx"> 
</span><span class="lines">@@ -259,7 +259,7 @@
</span><span class="cx">     ClientData* clientData;
</span><span class="cx">     VMEntryFrame* topVMEntryFrame;
</span><span class="cx">     ExecState* topCallFrame;
</span><del>-    std::unique_ptr&lt;Watchdog&gt; watchdog;
</del><ins>+    RefPtr&lt;Watchdog&gt; watchdog;
</ins><span class="cx"> 
</span><span class="cx">     Strong&lt;Structure&gt; structureStructure;
</span><span class="cx">     Strong&lt;Structure&gt; structureRareDataStructure;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMEntryScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VMEntryScope.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VMEntryScope.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/runtime/VMEntryScope.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include &quot;Debugger.h&quot;
</span><span class="cx"> #include &quot;Options.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span><ins>+#include &quot;Watchdog.h&quot;
</ins><span class="cx"> #include &lt;wtf/StackBounds.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -48,6 +49,9 @@
</span><span class="cx">         // Reset the date cache between JS invocations to force the VM to
</span><span class="cx">         // observe time xone changes.
</span><span class="cx">         vm.resetDateCache();
</span><ins>+
+        if (vm.watchdog)
+            vm.watchdog-&gt;enteredVM();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     vm.clearLastException();
</span><span class="lines">@@ -63,6 +67,9 @@
</span><span class="cx">     if (m_vm.entryScope != this)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    if (m_vm.watchdog)
+        m_vm.watchdog-&gt;exitedVM();
+
</ins><span class="cx">     m_vm.entryScope = nullptr;
</span><span class="cx"> 
</span><span class="cx">     for (auto&amp; listener : m_allEntryScopeDidPopListeners.values())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeWatchdogcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Watchdog.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Watchdog.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/runtime/Watchdog.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -32,75 +32,136 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-#define NO_LIMIT std::chrono::microseconds::max()
</del><ins>+const std::chrono::microseconds Watchdog::noTimeLimit = std::chrono::microseconds::max();
</ins><span class="cx"> 
</span><ins>+static std::chrono::microseconds currentWallClockTime()
+{
+    auto steadyTimeSinceEpoch = std::chrono::steady_clock::now().time_since_epoch();
+    return std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(steadyTimeSinceEpoch);
+}
+
</ins><span class="cx"> Watchdog::Watchdog()
</span><span class="cx">     : m_timerDidFire(false)
</span><span class="cx">     , m_didFire(false)
</span><del>-    , m_timeoutPeriod(NO_LIMIT)
-    , m_startCPUTime(0)
-    , m_elapsedCPUTime(0)
-    , m_reentryCount(0)
-    , m_isStopped(true)
</del><ins>+    , m_timeLimit(noTimeLimit)
+    , m_cpuDeadline(noTimeLimit)
+    , m_wallClockDeadline(noTimeLimit)
</ins><span class="cx">     , m_callback(0)
</span><span class="cx">     , m_callbackData1(0)
</span><span class="cx">     , m_callbackData2(0)
</span><ins>+    , m_timerQueue(WorkQueue::create(&quot;jsc.watchdog.queue&quot;, WorkQueue::Type::Serial, WorkQueue::QOS::Utility))
</ins><span class="cx"> {
</span><del>-    initTimer();
</del><ins>+    m_timerHandler = [this] {
+        this-&gt;m_timerDidFire = true;
+        this-&gt;deref();
+    };
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-Watchdog::~Watchdog()
</del><ins>+inline bool Watchdog::hasStartedTimer()
</ins><span class="cx"> {
</span><del>-    ASSERT(!isArmed());
-    stopCountdown();
-    destroyTimer();
</del><ins>+    return m_cpuDeadline != noTimeLimit;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Watchdog::setTimeLimit(VM&amp; vm, std::chrono::microseconds limit,
</span><span class="cx">     ShouldTerminateCallback callback, void* data1, void* data2)
</span><span class="cx"> {
</span><del>-    bool wasEnabled = isEnabled();
</del><ins>+    bool hadTimeLimit = hasTimeLimit();
</ins><span class="cx"> 
</span><del>-    if (!m_isStopped)
-        stopCountdown();
-
</del><span class="cx">     m_didFire = false; // Reset the watchdog.
</span><span class="cx"> 
</span><del>-    m_timeoutPeriod = limit;
</del><ins>+    m_timeLimit = limit;
</ins><span class="cx">     m_callback = callback;
</span><span class="cx">     m_callbackData1 = data1;
</span><span class="cx">     m_callbackData2 = data2;
</span><span class="cx"> 
</span><del>-    // If this is the first time that timeout is being enabled, then any
</del><ins>+    // If this is the first time that time limit is being enabled, then any
</ins><span class="cx">     // previously JIT compiled code will not have the needed polling checks.
</span><span class="cx">     // Hence, we need to flush all the pre-existing compiled code.
</span><span class="cx">     //
</span><del>-    // However, if the timeout is already enabled, and we're just changing the
-    // timeout value, then any existing JITted code will have the appropriate
</del><ins>+    // However, if the time limit is already enabled, and we're just changing the
+    // time limit value, then any existing JITted code will have the appropriate
</ins><span class="cx">     // polling checks. Hence, there is no need to re-do this flushing.
</span><del>-    if (!wasEnabled) {
</del><ins>+    if (!hadTimeLimit) {
</ins><span class="cx">         // And if we've previously compiled any functions, we need to revert
</span><span class="cx">         // them because they don't have the needed polling checks yet.
</span><span class="cx">         vm.releaseExecutableMemory();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    startCountdownIfNeeded();
</del><ins>+    if (m_hasEnteredVM &amp;&amp; hasTimeLimit())
+        startTimer(m_timeLimit);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Watchdog::didFire(ExecState* exec)
</del><ins>+bool Watchdog::didFireSlow(ExecState* exec)
</ins><span class="cx"> {
</span><del>-    if (m_didFire)
-        return true;
-
-    if (!m_timerDidFire)
-        return false;
</del><ins>+    ASSERT(m_timerDidFire);
</ins><span class="cx">     m_timerDidFire = false;
</span><del>-    stopCountdown();
</del><span class="cx"> 
</span><del>-    auto currentTime = currentCPUTime();
-    auto deltaCPUTime = currentTime - m_startCPUTime;
-    auto totalElapsedCPUTime = m_elapsedCPUTime + deltaCPUTime;
-    if (totalElapsedCPUTime &gt; m_timeoutPeriod) {
</del><ins>+    // A legitimate timer is the timer which woke up watchdog and can caused didFireSlow() to be
+    // called after m_wallClockDeadline has expired. All other timers are considered to be stale,
+    // and their wake ups are considered to be spurious and should be ignored.
+    //
+    // didFireSlow() will race against m_timerHandler to clear and set m_timerDidFire respectively.
+    // We need to deal with a variety of scenarios where we can have stale timers and legitimate
+    // timers firing in close proximity to each other.
+    //
+    // Consider the following scenarios:
+    //
+    // 1. A stale timer fires long before m_wallClockDeadline expires.
+    //
+    //    In this case, the m_wallClockDeadline check below will fail and the stale timer will be
+    //    ignored as spurious. We just need to make sure that we clear m_timerDidFire before we
+    //    check m_wallClockDeadline and return below.
+    //
+    // 2. A stale timer fires just before m_wallClockDeadline expires.
+    //    Before the watchdog can gets to the clearing m_timerDidFire above, the legit timer also fires.
+    //
+    //    In this case, m_timerDidFire was set twice by the 2 timers, but we only clear need to clear
+    //    it once. The m_wallClockDeadline below will pass and this invocation of didFireSlow() will
+    //    be treated as the response to the legit timer. The spurious timer is effectively ignored.
+    //
+    // 3. A state timer fires just before m_wallClockDeadline expires.
+    //    Right after the watchdog clears m_timerDidFire above, the legit timer also fires.
+    //
+    //    The fact that the legit timer fails means that the m_wallClockDeadline check will pass.
+    //    As long as we clear m_timerDidFire before we do the check, we are safe. This is the same
+    //    scenario as 2 above.
+    //
+    // 4. A stale timer fires just before m_wallClockDeadline expires.
+    //    Right after we do the m_wallClockDeadline check below, the legit timer fires.
+    //
+    //    The fact that the legit timer fires after the m_wallClockDeadline check means that
+    //    the m_wallClockDeadline check will have failed. This is the same scenario as 1 above.
+    //
+    // 5. A legit timer fires.
+    //    A stale timer also fires before we clear m_timerDidFire above.
+    //
+    //    This is the same scenario as 2 above.
+    //
+    // 6. A legit timer fires.
+    //    A stale timer fires right after we clear m_timerDidFire above.
+    //
+    //    In this case, the m_wallClockDeadline check will pass, and we fire the watchdog
+    //    though m_timerDidFire remains set. This just means that didFireSlow() will be called again due
+    //    to m_timerDidFire being set. The subsequent invocation of didFireSlow() will end up handling
+    //    the stale timer and ignoring it. This is the same scenario as 1 above.
+    //
+    // 7. A legit timer fires.
+    //    A stale timer fires right after we do the m_wallClockDeadline check.
+    //
+    //    This is the same as 6, which means it's the same as 1 above.
+    //
+    // In all these cases, we just need to ensure that we clear m_timerDidFire before we do the
+    // m_wallClockDeadline check below. Hence, a storeLoad fence is needed to ensure that these 2
+    // operations do not get re-ordered.
+
+    WTF::storeLoadFence();
+
+    if (currentWallClockTime() &lt; m_wallClockDeadline)
+        return false; // Just a stale timer firing. Nothing to do.
+
+    m_wallClockDeadline = noTimeLimit;
+
+    if (currentCPUTime() &gt;= m_cpuDeadline) {
</ins><span class="cx">         // Case 1: the allowed CPU time has elapsed.
</span><span class="cx"> 
</span><span class="cx">         // If m_callback is not set, then we terminate by default.
</span><span class="lines">@@ -112,27 +173,32 @@
</span><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        // The m_callback may have set a new limit. So, we may need to restart
-        // the countdown.
-        startCountdownIfNeeded();
</del><ins>+        // If we get here, then the callback above did not want to terminate execution. As a
+        // result, the callback may have done one of the following:
+        //   1. cleared the time limit (i.e. watchdog is disabled),
+        //   2. set a new time limit via Watchdog::setTimeLimit(), or
+        //   3. did nothing (i.e. allow another cycle of the current time limit).
+        //
+        // In the case of 1, we don't have to do anything.
+        // In the case of 2, Watchdog::setTimeLimit() would already have started the timer.
+        // In the case of 3, we need to re-start the timer here.
</ins><span class="cx"> 
</span><ins>+        ASSERT(m_hasEnteredVM);
+        if (hasTimeLimit() &amp;&amp; !hasStartedTimer())
+            startTimer(m_timeLimit);
+
</ins><span class="cx">     } else {
</span><span class="cx">         // Case 2: the allowed CPU time has NOT elapsed.
</span><del>-
-        // Tell the timer to alarm us again when it thinks we've reached the
-        // end of the allowed time.
-        auto remainingCPUTime = m_timeoutPeriod - totalElapsedCPUTime;
-        m_elapsedCPUTime = totalElapsedCPUTime;
-        m_startCPUTime = currentTime;
-        startCountdown(remainingCPUTime);
</del><ins>+        auto remainingCPUTime = m_cpuDeadline - currentCPUTime();
+        startTimer(remainingCPUTime);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Watchdog::isEnabled()
</del><ins>+bool Watchdog::hasTimeLimit()
</ins><span class="cx"> {
</span><del>-    return (m_timeoutPeriod != NO_LIMIT);
</del><ins>+    return (m_timeLimit != noTimeLimit);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Watchdog::fire()
</span><span class="lines">@@ -140,49 +206,51 @@
</span><span class="cx">     m_didFire = true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Watchdog::arm()
</del><ins>+void Watchdog::enteredVM()
</ins><span class="cx"> {
</span><del>-    m_reentryCount++;
-    if (m_reentryCount == 1)
-        startCountdownIfNeeded();
</del><ins>+    m_hasEnteredVM = true;
+    if (hasTimeLimit())
+        startTimer(m_timeLimit);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Watchdog::disarm()
</del><ins>+void Watchdog::exitedVM()
</ins><span class="cx"> {
</span><del>-    ASSERT(m_reentryCount &gt; 0);
-    if (m_reentryCount == 1)
-        stopCountdown();
-    m_reentryCount--;
</del><ins>+    ASSERT(m_hasEnteredVM);
+    stopTimer();
+    m_hasEnteredVM = false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Watchdog::startCountdownIfNeeded()
</del><ins>+void Watchdog::startTimer(std::chrono::microseconds timeLimit)
</ins><span class="cx"> {
</span><del>-    if (!m_isStopped)
-        return; // Already started.
</del><ins>+    ASSERT(m_hasEnteredVM);
+    ASSERT(hasTimeLimit());
</ins><span class="cx"> 
</span><del>-    if (!isArmed())
-        return; // Not executing JS script. No need to start.
</del><ins>+    m_cpuDeadline = currentCPUTime() + timeLimit;
+    auto wallClockTime = currentWallClockTime();
+    auto wallClockDeadline = wallClockTime + timeLimit;
</ins><span class="cx"> 
</span><del>-    if (isEnabled()) {
-        m_elapsedCPUTime = std::chrono::microseconds::zero();
-        m_startCPUTime = currentCPUTime();
-        startCountdown(m_timeoutPeriod);
</del><ins>+    if ((wallClockTime &lt; m_wallClockDeadline)
+        &amp;&amp; (m_wallClockDeadline &lt;= wallClockDeadline)) {
+        return; // Wait for the current active timer to expire before starting a new one.
</ins><span class="cx">     }
</span><del>-}
</del><span class="cx"> 
</span><del>-void Watchdog::startCountdown(std::chrono::microseconds limit)
-{
-    ASSERT(m_isStopped);
-    m_isStopped = false;
-    startTimer(limit);
</del><ins>+    // Else, the current active timer won't fire soon enough. So, start a new timer.
+    this-&gt;ref(); // m_timerHandler will deref to match later.
+    m_wallClockDeadline = wallClockDeadline;
+    m_timerDidFire = false;
+
+    // We clear m_timerDidFire because we're starting a new timer. However, we need to make sure
+    // that the clearing occurs before the timer thread is started. Thereafter, only didFireSlow()
+    // should clear m_timerDidFire (unless we start yet another timer). Hence, we need a storeStore
+    // fence here to ensure these operations do not get re-ordered.
+    WTF::storeStoreFence();
+
+    m_timerQueue-&gt;dispatchAfter(std::chrono::nanoseconds(timeLimit), m_timerHandler);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Watchdog::stopCountdown()
</del><ins>+void Watchdog::stopTimer()
</ins><span class="cx"> {
</span><del>-    if (m_isStopped)
-        return;
-    stopTimer();
-    m_isStopped = true;
</del><ins>+    m_cpuDeadline = noTimeLimit;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeWatchdogh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Watchdog.h (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Watchdog.h        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/runtime/Watchdog.h        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -26,31 +26,40 @@
</span><span class="cx"> #ifndef Watchdog_h
</span><span class="cx"> #define Watchdog_h
</span><span class="cx"> 
</span><del>-#if OS(DARWIN)
-#include &lt;dispatch/dispatch.h&gt;    
-#endif
</del><ins>+#include &lt;mutex&gt;
+#include &lt;wtf/Ref.h&gt;
+#include &lt;wtf/ThreadSafeRefCounted.h&gt;
+#include &lt;wtf/WorkQueue.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class ExecState;
</span><span class="cx"> class VM;
</span><span class="cx"> 
</span><del>-class Watchdog {
</del><ins>+class Watchdog : public WTF::ThreadSafeRefCounted&lt;Watchdog&gt; {
</ins><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="cx">     class Scope;
</span><span class="cx"> 
</span><span class="cx">     Watchdog();
</span><del>-    ~Watchdog();
</del><span class="cx"> 
</span><span class="cx">     typedef bool (*ShouldTerminateCallback)(ExecState*, void* data1, void* data2);
</span><span class="cx">     void setTimeLimit(VM&amp;, std::chrono::microseconds limit, ShouldTerminateCallback = 0, void* data1 = 0, void* data2 = 0);
</span><span class="cx"> 
</span><span class="cx">     // This version of didFire() will check the elapsed CPU time and call the
</span><span class="cx">     // callback (if needed) to determine if the watchdog should fire.
</span><del>-    bool didFire(ExecState*);
</del><ins>+    bool didFire(ExecState* exec)
+    {
+        if (m_didFire)
+            return true;
+        if (!m_timerDidFire)
+            return false;
+        return didFireSlow(exec);
+    }
</ins><span class="cx"> 
</span><del>-    bool isEnabled();
</del><ins>+    bool hasTimeLimit();
+    void enteredVM();
+    void exitedVM();
</ins><span class="cx"> 
</span><span class="cx">     // This version of didFire() is a more efficient version for when we want
</span><span class="cx">     // to know if the watchdog has fired in the past, and not whether it should
</span><span class="lines">@@ -60,21 +69,17 @@
</span><span class="cx"> 
</span><span class="cx">     void* timerDidFireAddress() { return &amp;m_timerDidFire; }
</span><span class="cx"> 
</span><del>-private:
-    void arm();
-    void disarm();
-    void startCountdownIfNeeded();
-    void startCountdown(std::chrono::microseconds limit);
-    void stopCountdown();
-    bool isArmed() { return !!m_reentryCount; }
</del><ins>+    static const std::chrono::microseconds noTimeLimit;
</ins><span class="cx"> 
</span><del>-    // Platform specific timer implementation:
-    void initTimer();
-    void destroyTimer();
-    void startTimer(std::chrono::microseconds limit);
</del><ins>+private:
+    void startTimer(std::chrono::microseconds timeLimit);
</ins><span class="cx">     void stopTimer();
</span><span class="cx"> 
</span><del>-    // m_timerDidFire (above) indicates whether the timer fired. The Watchdog
</del><ins>+    inline bool hasStartedTimer();
+
+    bool didFireSlow(ExecState*);
+
+    // m_timerDidFire indicates whether the timer fired. The Watchdog
</ins><span class="cx">     // still needs to check if the allowed CPU time has elapsed. If so, then
</span><span class="cx">     // the Watchdog fires and m_didFire will be set.
</span><span class="cx">     // NOTE: m_timerDidFire is only set by the platform specific timer
</span><span class="lines">@@ -82,47 +87,23 @@
</span><span class="cx">     bool m_timerDidFire;
</span><span class="cx">     bool m_didFire;
</span><span class="cx"> 
</span><del>-    std::chrono::microseconds m_timeoutPeriod;
-    std::chrono::microseconds m_startCPUTime;
-    std::chrono::microseconds m_elapsedCPUTime;
</del><ins>+    std::chrono::microseconds m_timeLimit;
</ins><span class="cx"> 
</span><del>-    int m_reentryCount;
-    bool m_isStopped;
</del><ins>+    std::chrono::microseconds m_cpuDeadline;
+    std::chrono::microseconds m_wallClockDeadline;
</ins><span class="cx"> 
</span><ins>+    bool m_hasEnteredVM { false };
+
</ins><span class="cx">     ShouldTerminateCallback m_callback;
</span><span class="cx">     void* m_callbackData1;
</span><span class="cx">     void* m_callbackData2;
</span><span class="cx"> 
</span><del>-#if OS(DARWIN) &amp;&amp; !PLATFORM(EFL) &amp;&amp; !PLATFORM(GTK)
-    dispatch_queue_t m_queue;
-    dispatch_source_t m_timer;
-#endif
</del><ins>+    Ref&lt;WorkQueue&gt; m_timerQueue;
+    std::function&lt;void ()&gt; m_timerHandler;
</ins><span class="cx"> 
</span><del>-    friend class Watchdog::Scope;
</del><span class="cx">     friend class LLIntOffsetsExtractor;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-class Watchdog::Scope {
-public:
-    Scope(Watchdog* watchdog)
-        : m_watchdog(watchdog)
-    {
-        if (!watchdog)
-            return;
-        m_watchdog-&gt;arm();
-    }
-    
-    ~Scope()
-    {
-        if (!m_watchdog)
-            return;
-        m_watchdog-&gt;disarm();
-    }
-
-private:
-    Watchdog* m_watchdog;
-};
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // Watchdog_h
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeWatchdogMaccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/WatchdogMac.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/WatchdogMac.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/runtime/WatchdogMac.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -1,72 +0,0 @@
</span><del>-/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include &quot;config.h&quot;
-#include &quot;Watchdog.h&quot;
-
-namespace JSC {
-
-void Watchdog::initTimer()
-{
-    m_queue = 0;
-    m_timer = 0;
-}
-
-void Watchdog::destroyTimer()
-{
-    ASSERT(!m_timer);
-    if (m_queue)
-        dispatch_release(m_queue);
-}
-
-void Watchdog::startTimer(std::chrono::microseconds limit)
-{
-    ASSERT(!m_timer);
-    if (!m_queue)
-        m_queue = dispatch_queue_create(&quot;jsc.watchdog.queue&quot;, 0);
-    m_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, m_queue);
-
-    dispatch_source_set_timer(m_timer,
-        dispatch_time(DISPATCH_TIME_NOW, std::chrono::nanoseconds(limit).count()),
-        DISPATCH_TIME_FOREVER, 0);
-
-    dispatch_source_set_event_handler(m_timer, ^{
-        m_timerDidFire = true;
-    });
-
-    dispatch_resume(m_timer);
-}
-
-void Watchdog::stopTimer()
-{
-    ASSERT(m_queue);
-    dispatch_sync(m_queue, ^{
-        dispatch_source_cancel(m_timer);
-    });
-    dispatch_release(m_timer);
-    m_timer = 0;
-}
-
-} // namespace JSC
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeWatchdogNonecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/WatchdogNone.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/WatchdogNone.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/JavaScriptCore/runtime/WatchdogNone.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -1,50 +0,0 @@
</span><del>-/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include &quot;config.h&quot;
-#include &quot;Watchdog.h&quot;
-
-namespace JSC {
-
-// This is a stub for platforms that have not implemented this functionality.
-// In this case, the platform timer here never fires.
-
-void Watchdog::initTimer()
-{
-}
-
-void Watchdog::destroyTimer()
-{
-}
-
-void Watchdog::startTimer(std::chrono::microseconds)
-{
-}
-
-void Watchdog::stopTimer()
-{
-}
-
-} // namespace JSC
</del></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/WebCore/ChangeLog        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2015-08-11  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        Implementation JavaScript watchdog using WTF::WorkQueue.
+        https://bugs.webkit.org/show_bug.cgi?id=147107
+
+        Reviewed by Geoffrey Garen.
+
+        No new tests because we're not introducing any behavior change to WebCore here.
+        We're only #include'ing Watchdog.h directly instead of going through VM.h.
+
+        * ForwardingHeaders/runtime/Watchdog.h: Added.
+        * PlatformEfl.cmake:
+        * WebCore.vcxproj/WebCore.vcxproj:
+        * WebCore.vcxproj/WebCore.vcxproj.filters:
+        * bindings/js/JSEventListener.cpp:
+        * bindings/js/WorkerScriptController.cpp:
+
</ins><span class="cx"> 2015-08-11  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [iOS WK2] ASSERT(!m_properties.backingStore || owner()) sometimes on zooming
</span></span></pre></div>
<a id="trunkSourceWebCoreForwardingHeadersruntimeWatchdogh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/ForwardingHeaders/runtime/Watchdog.h (0 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ForwardingHeaders/runtime/Watchdog.h                                (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/runtime/Watchdog.h        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+#ifndef WebCore_FWD_Watchdog_h
+#define WebCore_FWD_Watchdog_h
+#include &lt;JavaScriptCore/Watchdog.h&gt;
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebCorePlatformEflcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/PlatformEfl.cmake (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/PlatformEfl.cmake        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/WebCore/PlatformEfl.cmake        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -24,6 +24,7 @@
</span><span class="cx">     &quot;${WEBCORE_DIR}/platform/network/soup&quot;
</span><span class="cx">     &quot;${WEBCORE_DIR}/platform/text/efl&quot;
</span><span class="cx">     &quot;${WEBCORE_DIR}/plugins/efl&quot;
</span><ins>+    &quot;${WTF_DIR}/wtf/efl&quot;
</ins><span class="cx"> )
</span><span class="cx"> 
</span><span class="cx"> list(APPEND WebCore_SOURCES
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorevcxprojWebCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -20436,6 +20436,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\ForwardingHeaders\runtime\Structure.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\ForwardingHeaders\runtime\StructureChain.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\ForwardingHeaders\runtime\SymbolTable.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\ForwardingHeaders\runtime\Watchdog.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\ForwardingHeaders\runtime\WeakGCMap.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\ForwardingHeaders\runtime\WriteBarrier.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\ForwardingHeaders\yarr\YarrJIT.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorevcxprojWebCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -12198,6 +12198,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\ForwardingHeaders\runtime\SymbolTable.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;ForwardingHeaders\runtime&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\ForwardingHeaders\runtime\Watchdog.h&quot;&gt;
+      &lt;Filter&gt;ForwardingHeaders\runtime&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\ForwardingHeaders\runtime\WeakGCMap.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;ForwardingHeaders\runtime&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSEventListenercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSEventListener.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSEventListener.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/WebCore/bindings/js/JSEventListener.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &lt;runtime/ExceptionHelpers.h&gt;
</span><span class="cx"> #include &lt;runtime/JSLock.h&gt;
</span><span class="cx"> #include &lt;runtime/VMEntryScope.h&gt;
</span><ins>+#include &lt;runtime/Watchdog.h&gt;
</ins><span class="cx"> #include &lt;wtf/Ref.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCountedLeakCounter.h&gt;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsWorkerScriptControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp (188328 => 188329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp        2015-08-12 05:54:14 UTC (rev 188328)
+++ trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp        2015-08-12 05:56:20 UTC (rev 188329)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> #include &lt;runtime/ExceptionHelpers.h&gt;
</span><span class="cx"> #include &lt;runtime/Error.h&gt;
</span><span class="cx"> #include &lt;runtime/JSLock.h&gt;
</span><ins>+#include &lt;runtime/Watchdog.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> using namespace JSC;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>