<!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>[189712] releases/WebKitGTK/webkit-2.10</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/189712">189712</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2015-09-14 05:27:53 -0700 (Mon, 14 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/189009">r189009</a> - watchdog m_didFire state erroneously retained.
https://bugs.webkit.org/show_bug.cgi?id=131082

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

The watchdog can fire for 2 reasons:
1. an external controlling entity (i.e. another thread) has scheduled termination
   of the script thread via watchdog::terminateSoon().
2. the allowed CPU time has expired.

For case 1, we're doing away with the m_didFire flag.  Watchdog::terminateSoon()
will set the timer deadlines and m_timeLimit to 0, and m_timerDidFire to true.
This will get the script thread to check Watchdog::didFire() and terminate
execution.

Note: the watchdog only guarantees that script execution will terminate as soon
as possible due to a time limit of 0.  Once we've exited the VM, the client of the
VM is responsible from keeping a flag to prevent new script execution.

In a race condition, if terminateSoon() is called just after execution has gotten
past the client's reentry check and the client is in the process of re-entering,
the worst that can happen is that we will schedule the watchdog timer to fire
after a period of 0.  This will terminate script execution quickly, and thereafter
the client's check should be able to prevent further entry into the VM.

The correctness (i.e. has no race condition) of this type of termination relies
on the termination state being sticky.  Once the script thread is terminated this
way, the VM will continue to terminate scripts quickly until the client sets the
time limit to a non-zero value (or clears it which sets the time limit to
noTimeLimit).

For case 2, the watchdog does not alter m_timeLimit.  If the CPU deadline has
been reached, the script thread will terminate execution and exit the VM.

If the client of the VM starts new script execution, the watchdog will allow
execution for the specified m_timeLimit.  In this case, since m_timeLimit is not
0, the script gets a fresh allowance of CPU time to execute.  Hence, terminations
due to watchdog time outs are no longer sticky.

* API/JSContextRef.cpp:
(JSContextGroupSetExecutionTimeLimit):
(JSContextGroupClearExecutionTimeLimit):
* API/tests/ExecutionTimeLimitTest.cpp:
- Add test scenarios to verify that the watchdog is automatically reset by the VM
  upon throwing the TerminatedExecutionException.

(testResetAfterTimeout):
(testExecutionTimeLimit):
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* 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/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::ensureWatchdog):
* runtime/VM.h:
* runtime/VMInlines.h: Added.
(JSC::VM::shouldTriggerTermination):
* runtime/Watchdog.cpp:
(JSC::Watchdog::Watchdog):
(JSC::Watchdog::setTimeLimit):
(JSC::Watchdog::terminateSoon):
(JSC::Watchdog::didFireSlow):
(JSC::Watchdog::hasTimeLimit):
(JSC::Watchdog::enteredVM):
(JSC::Watchdog::exitedVM):
(JSC::Watchdog::startTimer):
(JSC::Watchdog::stopTimer):
(JSC::Watchdog::hasStartedTimer): Deleted.
(JSC::Watchdog::fire): Deleted.
* runtime/Watchdog.h:
(JSC::Watchdog::didFire):
(JSC::Watchdog::timerDidFireAddress):

Source/WebCore:

No new tests.  The new code is covered by the JSC API tests and an existing test:
fast/workers/worker-terminate-forever.html

* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::handleEvent):
* bindings/js/WorkerScriptController.cpp:
(WebCore::WorkerScriptController::WorkerScriptController):
- Always create a watchdog for the Web Worker's VM.  We need this in order to support
  Worker.terminate().
(WebCore::WorkerScriptController::evaluate):
(WebCore::WorkerScriptController::scheduleExecutionTermination):
(WebCore::WorkerScriptController::isTerminatingExecution):
(WebCore::WorkerScriptController::forbidExecution):
(WebCore::WorkerScriptController::isExecutionTerminating): Deleted.
* bindings/js/WorkerScriptController.h:

LayoutTests:

* fast/workers/worker-terminate-forever-expected.txt:
* fast/workers/worker-terminate-forever.html:
- Updated to check if the worker actually did terminate.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit210LayoutTestsChangeLog">releases/WebKitGTK/webkit-2.10/LayoutTests/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit210LayoutTestsfastworkersworkerterminateforeverexpectedtxt">releases/WebKitGTK/webkit-2.10/LayoutTests/fast/workers/worker-terminate-forever-expected.txt</a></li>
<li><a href="#releasesWebKitGTKwebkit210LayoutTestsfastworkersworkerterminateforeverhtml">releases/WebKitGTK/webkit-2.10/LayoutTests/fast/workers/worker-terminate-forever.html</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreAPIJSContextRefcpp">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/API/JSContextRef.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreAPItestsExecutionTimeLimitTestcpp">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreChangeLog">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoredfgDFGByteCodeParsercpp">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreinterpreterInterpretercpp">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCorejitJITOpcodescpp">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCorejitJITOperationscpp">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCorellintLLIntSlowPathscpp">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreruntimeVMcpp">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreruntimeVMh">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreruntimeWatchdogcpp">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/Watchdog.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreruntimeWatchdogh">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/Watchdog.h</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWebCoreChangeLog">releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWebCorebindingsjsJSEventListenercpp">releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/JSEventListener.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWebCorebindingsjsWorkerScriptControllercpp">releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/WorkerScriptController.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWebCorebindingsjsWorkerScriptControllerh">releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/WorkerScriptController.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit210SourceJavaScriptCoreruntimeVMInlinesh">releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VMInlines.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit210LayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/LayoutTests/ChangeLog (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/LayoutTests/ChangeLog        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/LayoutTests/ChangeLog        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-08-26  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        watchdog m_didFire state erroneously retained.
+        https://bugs.webkit.org/show_bug.cgi?id=131082
+
+        Reviewed by Geoffrey Garen.
+
+        * fast/workers/worker-terminate-forever-expected.txt:
+        * fast/workers/worker-terminate-forever.html:
+        - Updated to check if the worker actually did terminate. 
+
</ins><span class="cx"> 2015-08-27  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION (r188987): imported/mozilla/svg/filters/feConvolveMatrix-1.svg fails
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210LayoutTestsfastworkersworkerterminateforeverexpectedtxt"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/LayoutTests/fast/workers/worker-terminate-forever-expected.txt (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/LayoutTests/fast/workers/worker-terminate-forever-expected.txt        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/LayoutTests/fast/workers/worker-terminate-forever-expected.txt        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -1 +1,3 @@
</span><ins>+CONSOLE MESSAGE: line 15: Worker was started
+CONSOLE MESSAGE: line 34: Worker was terminated
</ins><span class="cx"> Test Worker.terminate() for a worker that tries to run forever.
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210LayoutTestsfastworkersworkerterminateforeverhtml"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/LayoutTests/fast/workers/worker-terminate-forever.html (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/LayoutTests/fast/workers/worker-terminate-forever.html        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/LayoutTests/fast/workers/worker-terminate-forever.html        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -1,11 +1,52 @@
</span><span class="cx"> &lt;body&gt;
</span><span class="cx"> &lt;p&gt;Test Worker.terminate() for a worker that tries to run forever.&lt;/p&gt;
</span><span class="cx"> &lt;script&gt;
</span><del>-if (window.testRunner)
</del><ins>+if (window.testRunner) {
</ins><span class="cx">     testRunner.dumpAsText();
</span><ins>+    testRunner.waitUntilDone();
+}
</ins><span class="cx"> 
</span><span class="cx"> var worker = new Worker('resources/worker-run-forever.js');
</span><del>-worker.terminate();
</del><ins>+
+function waitForWorkerToStart() {
+    var startTime = Date.now();
+    function checkIfWorkerStarted() {
+        if (internals.workerThreadCount == 1) {
+            console.log(&quot;Worker was started&quot;);
+            worker.terminate();
+            setTimeout(waitForWorkerToStop, 0);
+
+        } else if (Date.now() - startTime &lt; 5000) {
+            setTimeout(checkIfWorkerStarted, 0);
+
+        } else {
+            console.log(&quot;Worker did not show up&quot;);
+            testRunner.notifyDone();
+        }            
+    }
+    setTimeout(checkIfWorkerStarted, 0);
+}
+
+function waitForWorkerToStop() {
+    var startTime = Date.now();
+    function checkIfWorkerStopped() {
+        if (internals.workerThreadCount == 0) {
+            console.log(&quot;Worker was terminated&quot;);
+            testRunner.notifyDone();
+
+        } else if (Date.now() - startTime &lt; 5000) {
+            setTimeout(checkIfWorkerStopped, 0);
+
+        } else {
+            console.log(&quot;Did not see worker terminate&quot;);
+            testRunner.notifyDone();
+        }            
+    }
+    setTimeout(checkIfWorkerStopped, 0);
+}
+
+window.setTimeout(waitForWorkerToStart, 0);
+
</ins><span class="cx"> &lt;/script&gt;
</span><span class="cx"> &lt;/body&gt;
</span><span class="cx"> &lt;/html&gt;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoreAPIJSContextRefcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/API/JSContextRef.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/API/JSContextRef.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/API/JSContextRef.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -99,9 +99,9 @@
</span><span class="cx">     Watchdog&amp; watchdog = vm.ensureWatchdog();
</span><span class="cx">     if (callback) {
</span><span class="cx">         void* callbackPtr = reinterpret_cast&lt;void*&gt;(callback);
</span><del>-        watchdog.setTimeLimit(vm, std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(std::chrono::duration&lt;double&gt;(limit)), internalScriptTimeoutCallback, callbackPtr, callbackData);
</del><ins>+        watchdog.setTimeLimit(std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(std::chrono::duration&lt;double&gt;(limit)), internalScriptTimeoutCallback, callbackPtr, callbackData);
</ins><span class="cx">     } else
</span><del>-        watchdog.setTimeLimit(vm, std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(std::chrono::duration&lt;double&gt;(limit)));
</del><ins>+        watchdog.setTimeLimit(std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(std::chrono::duration&lt;double&gt;(limit)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSContextGroupClearExecutionTimeLimit(JSContextGroupRef group)
</span><span class="lines">@@ -109,7 +109,7 @@
</span><span class="cx">     VM&amp; vm = *toJS(group);
</span><span class="cx">     JSLockHolder locker(&amp;vm);
</span><span class="cx">     if (vm.watchdog)
</span><del>-        vm.watchdog-&gt;setTimeLimit(vm, Watchdog::noTimeLimit);
</del><ins>+        vm.watchdog-&gt;setTimeLimit(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="releasesWebKitGTKwebkit210SourceJavaScriptCoreAPItestsExecutionTimeLimitTestcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/API/tests/ExecutionTimeLimitTest.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -83,6 +83,22 @@
</span><span class="cx">     const char* optionsStr;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+static void testResetAfterTimeout(bool&amp; failed)
+{
+    JSValueRef v = nullptr;
+    JSValueRef exception = nullptr;
+    const char* reentryScript = &quot;100&quot;;
+    JSStringRef script = JSStringCreateWithUTF8CString(reentryScript);
+    v = JSEvaluateScript(context, script, nullptr, nullptr, 1, &amp;exception);
+    if (exception) {
+        printf(&quot;FAIL: Watchdog timeout was not reset.\n&quot;);
+        failed = true;
+    } else if (!JSValueIsNumber(context, v) || JSValueToNumber(context, v, nullptr) != 100) {
+        printf(&quot;FAIL: Script result is not as expected.\n&quot;);
+        failed = true;
+    }
+}
+
</ins><span class="cx"> int testExecutionTimeLimit()
</span><span class="cx"> {
</span><span class="cx">     static const TierOptions tierOptionsList[] = {
</span><span class="lines">@@ -152,6 +168,8 @@
</span><span class="cx">                 printf(&quot;FAIL: %s TerminatedExecutionException was not thrown.\n&quot;, tierOptions.tier);
</span><span class="cx">                 failed = true;
</span><span class="cx">             }
</span><ins>+
+            testResetAfterTimeout(failed);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         /* Test the script timeout's TerminatedExecutionException should NOT be catchable: */
</span><span class="lines">@@ -187,6 +205,8 @@
</span><span class="cx">                 printf(&quot;FAIL: %s TerminatedExecutionException was caught.\n&quot;, tierOptions.tier);
</span><span class="cx">                 failed = true;
</span><span class="cx">             }
</span><ins>+
+            testResetAfterTimeout(failed);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         /* Test script timeout with no callback: */
</span><span class="lines">@@ -222,6 +242,8 @@
</span><span class="cx">                 printf(&quot;FAIL: %s TerminatedExecutionException was not thrown.\n&quot;, tierOptions.tier);
</span><span class="cx">                 failed = true;
</span><span class="cx">             }
</span><ins>+
+            testResetAfterTimeout(failed);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         /* Test script timeout cancellation: */
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/ChangeLog (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/ChangeLog        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/ChangeLog        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -1,3 +1,90 @@
</span><ins>+2015-08-26  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        watchdog m_didFire state erroneously retained.
+        https://bugs.webkit.org/show_bug.cgi?id=131082
+
+        Reviewed by Geoffrey Garen.
+
+        The watchdog can fire for 2 reasons:
+        1. an external controlling entity (i.e. another thread) has scheduled termination
+           of the script thread via watchdog::terminateSoon().
+        2. the allowed CPU time has expired.
+
+        For case 1, we're doing away with the m_didFire flag.  Watchdog::terminateSoon() 
+        will set the timer deadlines and m_timeLimit to 0, and m_timerDidFire to true.
+        This will get the script thread to check Watchdog::didFire() and terminate
+        execution.
+
+        Note: the watchdog only guarantees that script execution will terminate as soon
+        as possible due to a time limit of 0.  Once we've exited the VM, the client of the
+        VM is responsible from keeping a flag to prevent new script execution.
+
+        In a race condition, if terminateSoon() is called just after execution has gotten
+        past the client's reentry check and the client is in the process of re-entering,
+        the worst that can happen is that we will schedule the watchdog timer to fire
+        after a period of 0.  This will terminate script execution quickly, and thereafter
+        the client's check should be able to prevent further entry into the VM.
+
+        The correctness (i.e. has no race condition) of this type of termination relies
+        on the termination state being sticky.  Once the script thread is terminated this
+        way, the VM will continue to terminate scripts quickly until the client sets the
+        time limit to a non-zero value (or clears it which sets the time limit to
+        noTimeLimit).
+
+        For case 2, the watchdog does not alter m_timeLimit.  If the CPU deadline has
+        been reached, the script thread will terminate execution and exit the VM.
+
+        If the client of the VM starts new script execution, the watchdog will allow
+        execution for the specified m_timeLimit.  In this case, since m_timeLimit is not
+        0, the script gets a fresh allowance of CPU time to execute.  Hence, terminations
+        due to watchdog time outs are no longer sticky.
+
+        * API/JSContextRef.cpp:
+        (JSContextGroupSetExecutionTimeLimit):
+        (JSContextGroupClearExecutionTimeLimit):
+        * API/tests/ExecutionTimeLimitTest.cpp:
+        - Add test scenarios to verify that the watchdog is automatically reset by the VM
+          upon throwing the TerminatedExecutionException.
+
+        (testResetAfterTimeout):
+        (testExecutionTimeLimit):
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * 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/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::VM::ensureWatchdog):
+        * runtime/VM.h:
+        * runtime/VMInlines.h: Added.
+        (JSC::VM::shouldTriggerTermination):
+        * runtime/Watchdog.cpp:
+        (JSC::Watchdog::Watchdog):
+        (JSC::Watchdog::setTimeLimit):
+        (JSC::Watchdog::terminateSoon):
+        (JSC::Watchdog::didFireSlow):
+        (JSC::Watchdog::hasTimeLimit):
+        (JSC::Watchdog::enteredVM):
+        (JSC::Watchdog::exitedVM):
+        (JSC::Watchdog::startTimer):
+        (JSC::Watchdog::stopTimer):
+        (JSC::Watchdog::hasStartedTimer): Deleted.
+        (JSC::Watchdog::fire): Deleted.
+        * runtime/Watchdog.h:
+        (JSC::Watchdog::didFire):
+        (JSC::Watchdog::timerDidFireAddress):
+
</ins><span class="cx"> 2015-08-20  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         A watchdog tests is failing on Windows.
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -1747,6 +1747,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\Uint32Array.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\Uint8Array.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\VM.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\runtime\VMInlines.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\VMEntryScope.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\VarOffset.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\Watchdog.h&quot; /&gt;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -3234,6 +3234,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\VM.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;runtime&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\runtime\VMInlines.h&quot;&gt;
+      &lt;Filter&gt;runtime&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\VMEntryScope.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;runtime&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -3587,6 +3587,7 @@
</span><span class="cx">                 FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMEntryScope.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapVerifier.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapVerifier.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 FEA0861E182B7A0400F6D851 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpoint.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerPrimitives.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FEB51F6A1A97B688001F921C /* Regress141809.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Regress141809.h; path = API/tests/Regress141809.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4929,6 +4930,7 @@
</span><span class="cx">                                 0FE050241AA9095600D33B33 /* VarOffset.h */,
</span><span class="cx">                                 E18E3A570DF9278C00D90B34 /* VM.cpp */,
</span><span class="cx">                                 E18E3A560DF9278C00D90B34 /* VM.h */,
</span><ins>+                                FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
</ins><span class="cx">                                 FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
</span><span class="cx">                                 FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
</span><span class="cx">                                 FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -4039,7 +4039,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;hasTimeLimit())
</del><ins>+            if (m_vm-&gt;watchdog)
</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="releasesWebKitGTKwebkit210SourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/interpreter/Interpreter.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -70,8 +70,8 @@
</span><span class="cx"> #include &quot;StrongInlines.h&quot;
</span><span class="cx"> #include &quot;Symbol.h&quot;
</span><span class="cx"> #include &quot;VMEntryScope.h&quot;
</span><ins>+#include &quot;VMInlines.h&quot;
</ins><span class="cx"> #include &quot;VirtualRegister.h&quot;
</span><del>-#include &quot;Watchdog.h&quot;
</del><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">@@ -866,7 +866,7 @@
</span><span class="cx"> 
</span><span class="cx">     ProgramCodeBlock* codeBlock = program-&gt;codeBlock();
</span><span class="cx"> 
</span><del>-    if (UNLIKELY(vm.watchdog &amp;&amp; vm.watchdog-&gt;didFire(callFrame)))
</del><ins>+    if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
</ins><span class="cx">         return throwTerminatedExecutionException(callFrame);
</span><span class="cx"> 
</span><span class="cx">     ASSERT(codeBlock-&gt;numParameters() == 1); // 1 parameter for 'this'.
</span><span class="lines">@@ -929,7 +929,7 @@
</span><span class="cx">     } else
</span><span class="cx">         newCodeBlock = 0;
</span><span class="cx"> 
</span><del>-    if (UNLIKELY(vm.watchdog &amp;&amp; vm.watchdog-&gt;didFire(callFrame)))
</del><ins>+    if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
</ins><span class="cx">         return throwTerminatedExecutionException(callFrame);
</span><span class="cx"> 
</span><span class="cx">     ProtoCallFrame protoCallFrame;
</span><span class="lines">@@ -999,7 +999,7 @@
</span><span class="cx">     } else
</span><span class="cx">         newCodeBlock = 0;
</span><span class="cx"> 
</span><del>-    if (UNLIKELY(vm.watchdog &amp;&amp; vm.watchdog-&gt;didFire(callFrame)))
</del><ins>+    if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
</ins><span class="cx">         return throwTerminatedExecutionException(callFrame);
</span><span class="cx"> 
</span><span class="cx">     ProtoCallFrame protoCallFrame;
</span><span class="lines">@@ -1072,7 +1072,7 @@
</span><span class="cx">     if (LegacyProfiler* profiler = vm.enabledProfiler())
</span><span class="cx">         profiler-&gt;willExecute(closure.oldCallFrame, closure.function);
</span><span class="cx"> 
</span><del>-    if (UNLIKELY(vm.watchdog &amp;&amp; vm.watchdog-&gt;didFire(closure.oldCallFrame)))
</del><ins>+    if (UNLIKELY(vm.shouldTriggerTermination(closure.oldCallFrame)))
</ins><span class="cx">         return throwTerminatedExecutionException(closure.oldCallFrame);
</span><span class="cx"> 
</span><span class="cx">     // Execute the code:
</span><span class="lines">@@ -1153,7 +1153,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (UNLIKELY(vm.watchdog &amp;&amp; vm.watchdog-&gt;didFire(callFrame)))
</del><ins>+    if (UNLIKELY(vm.shouldTriggerTermination(callFrame)))
</ins><span class="cx">         return throwTerminatedExecutionException(callFrame);
</span><span class="cx"> 
</span><span class="cx">     ASSERT(codeBlock-&gt;numParameters() == 1); // 1 parameter for 'this'.
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/jit/JITOpcodes.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -906,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;hasTimeLimit())
</del><ins>+    if (m_vm-&gt;watchdog)
</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">@@ -932,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;hasTimeLimit()) {
</del><ins>+    if (m_vm-&gt;watchdog) {
</ins><span class="cx">         linkSlowCase(iter);
</span><span class="cx">         callOperation(operationHandleWatchdogTimer);
</span><span class="cx"> 
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/jit/JITOperations.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/jit/JITOperations.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/jit/JITOperations.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -57,7 +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><del>-#include &quot;Watchdog.h&quot;
</del><ins>+#include &quot;VMInlines.h&quot;
</ins><span class="cx"> #include &lt;wtf/InlineASM.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -968,7 +968,7 @@
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(&amp;vm, exec);
</span><span class="cx"> 
</span><del>-    if (UNLIKELY(vm.watchdog &amp;&amp; vm.watchdog-&gt;didFire(exec)))
</del><ins>+    if (UNLIKELY(vm.shouldTriggerTermination(exec)))
</ins><span class="cx">         vm.throwException(exec, createTerminatedExecutionException(&amp;vm));
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -53,7 +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><del>-#include &quot;Watchdog.h&quot;
</del><ins>+#include &quot;VMInlines.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 class="lines">@@ -1286,7 +1286,7 @@
</span><span class="cx"> {
</span><span class="cx">     LLINT_BEGIN_NO_SET_PC();
</span><span class="cx">     ASSERT(vm.watchdog);
</span><del>-    if (UNLIKELY(vm.watchdog-&gt;didFire(exec)))
</del><ins>+    if (UNLIKELY(vm.shouldTriggerTermination(exec)))
</ins><span class="cx">         LLINT_THROW(createTerminatedExecutionException(&amp;vm));
</span><span class="cx">     LLINT_RETURN_TWO(0, exec);
</span><span class="cx"> }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VM.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VM.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VM.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -289,7 +289,7 @@
</span><span class="cx">     if (Options::watchdog()) {
</span><span class="cx">         std::chrono::milliseconds timeoutMillis(Options::watchdog());
</span><span class="cx">         Watchdog&amp; watchdog = ensureWatchdog();
</span><del>-        watchdog.setTimeLimit(*this, timeoutMillis);
</del><ins>+        watchdog.setTimeLimit(timeoutMillis);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -385,6 +385,11 @@
</span><span class="cx">         // the LLINT assumes that the internal shape of a std::unique_ptr is the
</span><span class="cx">         // same as a plain C++ pointer, and loads the address of Watchdog from it.
</span><span class="cx">         RELEASE_ASSERT(*reinterpret_cast&lt;Watchdog**&gt;(&amp;watchdog) == watchdog.get());
</span><ins>+
+        // And if we've previously compiled any functions, we need to revert
+        // them because they don't have the needed polling checks for the watchdog
+        // yet.
+        deleteAllCode();
</ins><span class="cx">     }
</span><span class="cx">     return *watchdog;
</span><span class="cx"> }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VM.h (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VM.h        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VM.h        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -236,7 +236,7 @@
</span><span class="cx">     static Ref&lt;VM&gt; createContextGroup(HeapType = SmallHeap);
</span><span class="cx">     JS_EXPORT_PRIVATE ~VM();
</span><span class="cx"> 
</span><del>-    Watchdog&amp; ensureWatchdog();
</del><ins>+    JS_EXPORT_PRIVATE Watchdog&amp; ensureWatchdog();
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     RefPtr&lt;JSLock&gt; m_apiLock;
</span><span class="lines">@@ -556,6 +556,8 @@
</span><span class="cx">     JS_EXPORT_PRIVATE void queueMicrotask(JSGlobalObject*, PassRefPtr&lt;Microtask&gt;);
</span><span class="cx">     JS_EXPORT_PRIVATE void drainMicrotasks();
</span><span class="cx"> 
</span><ins>+    inline bool shouldTriggerTermination(ExecState*);
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span><span class="cx">     friend class ClearExceptionScope;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoreruntimeVMInlinesh"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VMInlines.h (0 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VMInlines.h                                (rev 0)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/VMInlines.h        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef VMInlines_h
+#define VMInlines_h
+
+#include &quot;VM.h&quot;
+#include &quot;Watchdog.h&quot;
+
+namespace JSC {
+    
+bool VM::shouldTriggerTermination(ExecState* exec)
+{
+    if (!watchdog)
+        return false;
+    return watchdog-&gt;didFire(exec);
+}
+
+} // namespace JSC
+
+#endif // LLIntData_h
+
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoreruntimeWatchdogcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/Watchdog.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/Watchdog.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/Watchdog.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -42,7 +42,6 @@
</span><span class="cx"> 
</span><span class="cx"> Watchdog::Watchdog()
</span><span class="cx">     : m_timerDidFire(false)
</span><del>-    , m_didFire(false)
</del><span class="cx">     , m_timeLimit(noTimeLimit)
</span><span class="cx">     , m_cpuDeadline(noTimeLimit)
</span><span class="cx">     , m_wallClockDeadline(noTimeLimit)
</span><span class="lines">@@ -52,127 +51,72 @@
</span><span class="cx">     , m_timerQueue(WorkQueue::create(&quot;jsc.watchdog.queue&quot;, WorkQueue::Type::Serial, WorkQueue::QOS::Utility))
</span><span class="cx"> {
</span><span class="cx">     m_timerHandler = [this] {
</span><ins>+        LockHolder locker(m_lock);
</ins><span class="cx">         this-&gt;m_timerDidFire = true;
</span><span class="cx">         this-&gt;deref();
</span><span class="cx">     };
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool Watchdog::hasStartedTimer()
-{
-    return m_cpuDeadline != noTimeLimit;
-}
-
-void Watchdog::setTimeLimit(VM&amp; vm, std::chrono::microseconds limit,
</del><ins>+void Watchdog::setTimeLimit(std::chrono::microseconds limit,
</ins><span class="cx">     ShouldTerminateCallback callback, void* data1, void* data2)
</span><span class="cx"> {
</span><del>-    bool hadTimeLimit = hasTimeLimit();
</del><ins>+    LockHolder locker(m_lock);
</ins><span class="cx"> 
</span><del>-    m_didFire = false; // Reset the watchdog.
-
</del><span class="cx">     m_timeLimit = limit;
</span><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 time limit is being enabled, then any
-    // previously JIT compiled code will not have the needed polling checks.
-    // Hence, we need to flush all the pre-existing compiled code.
-    //
-    // 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
-    // polling checks. Hence, there is no need to re-do this flushing.
-    if (!hadTimeLimit) {
-        // And if we've previously compiled any functions, we need to revert
-        // them because they don't have the needed polling checks yet.
-        vm.deleteAllCode();
-    }
-
</del><span class="cx">     if (m_hasEnteredVM &amp;&amp; hasTimeLimit())
</span><del>-        startTimer(m_timeLimit);
</del><ins>+        startTimer(locker, m_timeLimit);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Watchdog::didFireSlow(ExecState* exec)
</del><ins>+JS_EXPORT_PRIVATE void Watchdog::terminateSoon()
</ins><span class="cx"> {
</span><del>-    ASSERT(m_timerDidFire);
-    m_timerDidFire = false;
</del><ins>+    LockHolder locker(m_lock);
</ins><span class="cx"> 
</span><del>-    // 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.
</del><ins>+    m_timeLimit = std::chrono::microseconds(0);
+    m_cpuDeadline = std::chrono::microseconds(0);
+    m_wallClockDeadline = std::chrono::microseconds(0);
+    m_timerDidFire = true;
+}
</ins><span class="cx"> 
</span><del>-    WTF::storeLoadFence();
</del><ins>+bool Watchdog::didFireSlow(ExecState* exec)
+{
+    {
+        LockHolder locker(m_lock);
</ins><span class="cx"> 
</span><del>-    if (currentWallClockTime() &lt; m_wallClockDeadline)
-        return false; // Just a stale timer firing. Nothing to do.
</del><ins>+        ASSERT(m_timerDidFire);
+        m_timerDidFire = false;
</ins><span class="cx"> 
</span><del>-    m_wallClockDeadline = noTimeLimit;
</del><ins>+        if (currentWallClockTime() &lt; m_wallClockDeadline)
+            return false; // Just a stale timer firing. Nothing to do.
</ins><span class="cx"> 
</span><del>-    if (currentCPUTime() &gt;= m_cpuDeadline) {
-        // Case 1: the allowed CPU time has elapsed.
</del><ins>+        // Set m_wallClockDeadline to noTimeLimit here so that we can reject all future
+        // spurious wakes.
+        m_wallClockDeadline = noTimeLimit;
</ins><span class="cx"> 
</span><del>-        // If m_callback is not set, then we terminate by default.
-        // Else, we let m_callback decide if we should terminate or not.
-        bool needsTermination = !m_callback
-            || m_callback(exec, m_callbackData1, m_callbackData2);
-        if (needsTermination) {
-            m_didFire = true;
-            return true;
</del><ins>+        auto cpuTime = currentCPUTime();
+        if (cpuTime &lt; m_cpuDeadline) {
+            auto remainingCPUTime = m_cpuDeadline - cpuTime;
+            startTimer(locker, remainingCPUTime);
+            return false;
</ins><span class="cx">         }
</span><ins>+    }
</ins><span class="cx"> 
</span><ins>+    // Note: we should not be holding the lock while calling the callbacks. The callbacks may
+    // call setTimeLimit() which will try to lock as well.
+
+    // If m_callback is not set, then we terminate by default.
+    // Else, we let m_callback decide if we should terminate or not.
+    bool needsTermination = !m_callback
+        || m_callback(exec, m_callbackData1, m_callbackData2);
+    if (needsTermination)
+        return true;
+
+    {
+        LockHolder locker(m_lock);
+
</ins><span class="cx">         // If we get here, then the callback above did not want to terminate execution. As a
</span><span class="cx">         // result, the callback may have done one of the following:
</span><span class="cx">         //   1. cleared the time limit (i.e. watchdog is disabled),
</span><span class="lines">@@ -184,15 +128,10 @@
</span><span class="cx">         // In the case of 3, we need to re-start the timer here.
</span><span class="cx"> 
</span><span class="cx">         ASSERT(m_hasEnteredVM);
</span><del>-        if (hasTimeLimit() &amp;&amp; !hasStartedTimer())
-            startTimer(m_timeLimit);
-
-    } else {
-        // Case 2: the allowed CPU time has NOT elapsed.
-        auto remainingCPUTime = m_cpuDeadline - currentCPUTime();
-        startTimer(remainingCPUTime);
</del><ins>+        bool callbackAlreadyStartedTimer = (m_cpuDeadline != noTimeLimit);
+        if (hasTimeLimit() &amp;&amp; !callbackAlreadyStartedTimer)
+            startTimer(locker, m_timeLimit);
</ins><span class="cx">     }
</span><del>-
</del><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -201,54 +140,45 @@
</span><span class="cx">     return (m_timeLimit != noTimeLimit);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Watchdog::fire()
-{
-    m_didFire = true;
-}
-
</del><span class="cx"> void Watchdog::enteredVM()
</span><span class="cx"> {
</span><span class="cx">     m_hasEnteredVM = true;
</span><del>-    if (hasTimeLimit())
-        startTimer(m_timeLimit);
</del><ins>+    if (hasTimeLimit()) {
+        LockHolder locker(m_lock);
+        startTimer(locker, m_timeLimit);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Watchdog::exitedVM()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_hasEnteredVM);
</span><del>-    stopTimer();
</del><ins>+    LockHolder locker(m_lock);
+    stopTimer(locker);
</ins><span class="cx">     m_hasEnteredVM = false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Watchdog::startTimer(std::chrono::microseconds timeLimit)
</del><ins>+void Watchdog::startTimer(LockHolder&amp;, std::chrono::microseconds timeLimit)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_hasEnteredVM);
</span><span class="cx">     ASSERT(hasTimeLimit());
</span><ins>+    ASSERT(timeLimit &lt;= m_timeLimit);
</ins><span class="cx"> 
</span><span class="cx">     m_cpuDeadline = currentCPUTime() + timeLimit;
</span><span class="cx">     auto wallClockTime = currentWallClockTime();
</span><span class="cx">     auto wallClockDeadline = wallClockTime + timeLimit;
</span><span class="cx"> 
</span><span class="cx">     if ((wallClockTime &lt; m_wallClockDeadline)
</span><del>-        &amp;&amp; (m_wallClockDeadline &lt;= wallClockDeadline)) {
</del><ins>+        &amp;&amp; (m_wallClockDeadline &lt;= wallClockDeadline))
</ins><span class="cx">         return; // Wait for the current active timer to expire before starting a new one.
</span><del>-    }
</del><span class="cx"> 
</span><span class="cx">     // Else, the current active timer won't fire soon enough. So, start a new timer.
</span><span class="cx">     this-&gt;ref(); // m_timerHandler will deref to match later.
</span><span class="cx">     m_wallClockDeadline = wallClockDeadline;
</span><del>-    m_timerDidFire = false;
</del><span class="cx"> 
</span><del>-    // 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();
-
</del><span class="cx">     m_timerQueue-&gt;dispatchAfter(std::chrono::nanoseconds(timeLimit), m_timerHandler);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Watchdog::stopTimer()
</del><ins>+void Watchdog::stopTimer(LockHolder&amp;)
</ins><span class="cx"> {
</span><span class="cx">     m_cpuDeadline = noTimeLimit;
</span><span class="cx"> }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceJavaScriptCoreruntimeWatchdogh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/Watchdog.h (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/Watchdog.h        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/JavaScriptCore/runtime/Watchdog.h        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -26,7 +26,7 @@
</span><span class="cx"> #ifndef Watchdog_h
</span><span class="cx"> #define Watchdog_h
</span><span class="cx"> 
</span><del>-#include &lt;mutex&gt;
</del><ins>+#include &lt;wtf/Lock.h&gt;
</ins><span class="cx"> #include &lt;wtf/Ref.h&gt;
</span><span class="cx"> #include &lt;wtf/ThreadSafeRefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/WorkQueue.h&gt;
</span><span class="lines">@@ -44,14 +44,11 @@
</span><span class="cx">     Watchdog();
</span><span class="cx"> 
</span><span class="cx">     typedef bool (*ShouldTerminateCallback)(ExecState*, void* data1, void* data2);
</span><del>-    void setTimeLimit(VM&amp;, std::chrono::microseconds limit, ShouldTerminateCallback = 0, void* data1 = 0, void* data2 = 0);
</del><ins>+    void setTimeLimit(std::chrono::microseconds limit, ShouldTerminateCallback = 0, void* data1 = 0, void* data2 = 0);
+    JS_EXPORT_PRIVATE void terminateSoon();
</ins><span class="cx"> 
</span><del>-    // This version of didFire() will check the elapsed CPU time and call the
-    // callback (if needed) to determine if the watchdog should fire.
</del><span class="cx">     bool didFire(ExecState* exec)
</span><span class="cx">     {
</span><del>-        if (m_didFire)
-            return true;
</del><span class="cx">         if (!m_timerDidFire)
</span><span class="cx">             return false;
</span><span class="cx">         return didFireSlow(exec);
</span><span class="lines">@@ -61,22 +58,14 @@
</span><span class="cx">     void enteredVM();
</span><span class="cx">     void exitedVM();
</span><span class="cx"> 
</span><del>-    // This version of didFire() is a more efficient version for when we want
-    // to know if the watchdog has fired in the past, and not whether it should
-    // fire right now.
-    bool didFire() { return m_didFire; }
-    JS_EXPORT_PRIVATE void fire();
-
</del><span class="cx">     void* timerDidFireAddress() { return &amp;m_timerDidFire; }
</span><span class="cx"> 
</span><span class="cx">     static const std::chrono::microseconds noTimeLimit;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    void startTimer(std::chrono::microseconds timeLimit);
-    void stopTimer();
</del><ins>+    void startTimer(LockHolder&amp;, std::chrono::microseconds timeLimit);
+    void stopTimer(LockHolder&amp;);
</ins><span class="cx"> 
</span><del>-    inline bool hasStartedTimer();
-
</del><span class="cx">     bool didFireSlow(ExecState*);
</span><span class="cx"> 
</span><span class="cx">     // m_timerDidFire indicates whether the timer fired. The Watchdog
</span><span class="lines">@@ -85,13 +74,16 @@
</span><span class="cx">     // NOTE: m_timerDidFire is only set by the platform specific timer
</span><span class="cx">     // (probably from another thread) but is only cleared in the script thread.
</span><span class="cx">     bool m_timerDidFire;
</span><del>-    bool m_didFire;
</del><span class="cx"> 
</span><span class="cx">     std::chrono::microseconds m_timeLimit;
</span><span class="cx"> 
</span><span class="cx">     std::chrono::microseconds m_cpuDeadline;
</span><span class="cx">     std::chrono::microseconds m_wallClockDeadline;
</span><span class="cx"> 
</span><ins>+    // Writes to m_timerDidFire and m_timeLimit, and Reads+Writes to m_cpuDeadline and m_wallClockDeadline
+    // must be guarded by this lock.
+    Lock m_lock;
+
</ins><span class="cx">     bool m_hasEnteredVM { false };
</span><span class="cx"> 
</span><span class="cx">     ShouldTerminateCallback m_callback;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+2015-08-26  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        watchdog m_didFire state erroneously retained.
+        https://bugs.webkit.org/show_bug.cgi?id=131082
+
+        Reviewed by Geoffrey Garen.
+
+        No new tests.  The new code is covered by the JSC API tests and an existing test:
+        fast/workers/worker-terminate-forever.html
+
+        * bindings/js/JSEventListener.cpp:
+        (WebCore::JSEventListener::handleEvent):
+        * bindings/js/WorkerScriptController.cpp:
+        (WebCore::WorkerScriptController::WorkerScriptController):
+        - Always create a watchdog for the Web Worker's VM.  We need this in order to support
+          Worker.terminate().
+        (WebCore::WorkerScriptController::evaluate):
+        (WebCore::WorkerScriptController::scheduleExecutionTermination):
+        (WebCore::WorkerScriptController::isTerminatingExecution):
+        (WebCore::WorkerScriptController::forbidExecution):
+        (WebCore::WorkerScriptController::isExecutionTerminating): Deleted.
+        * bindings/js/WorkerScriptController.h:
+
</ins><span class="cx"> 2015-08-27  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION (r188987): imported/mozilla/svg/filters/feConvolveMatrix-1.svg fails
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWebCorebindingsjsJSEventListenercpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/JSEventListener.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/JSEventListener.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/JSEventListener.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -135,9 +135,10 @@
</span><span class="cx">         globalObject-&gt;setCurrentEvent(savedEvent);
</span><span class="cx"> 
</span><span class="cx">         if (is&lt;WorkerGlobalScope&gt;(*scriptExecutionContext)) {
</span><ins>+            auto scriptController = downcast&lt;WorkerGlobalScope&gt;(*scriptExecutionContext).script();
</ins><span class="cx">             bool terminatorCausedException = (exec-&gt;hadException() &amp;&amp; isTerminatedExecutionException(exec-&gt;exception()));
</span><del>-            if (terminatorCausedException || (vm.watchdog &amp;&amp; vm.watchdog-&gt;didFire()))
-                downcast&lt;WorkerGlobalScope&gt;(*scriptExecutionContext).script()-&gt;forbidExecution();
</del><ins>+            if (terminatorCausedException || scriptController-&gt;isTerminatingExecution())
+                scriptController-&gt;forbidExecution();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (exception) {
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWebCorebindingsjsWorkerScriptControllercpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/WorkerScriptController.cpp (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/WorkerScriptController.cpp        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/WorkerScriptController.cpp        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -56,6 +56,7 @@
</span><span class="cx">     , m_workerGlobalScopeWrapper(*m_vm)
</span><span class="cx">     , m_executionForbidden(false)
</span><span class="cx"> {
</span><ins>+    m_vm-&gt;ensureWatchdog();
</ins><span class="cx">     initNormalWorldClientData(m_vm.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -121,8 +122,7 @@
</span><span class="cx">     JSC::evaluate(exec, sourceCode.jsSourceCode(), m_workerGlobalScopeWrapper-&gt;globalThis(), returnedException);
</span><span class="cx"> 
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><del>-    if ((returnedException &amp;&amp; isTerminatedExecutionException(returnedException))
-        || (vm.watchdog &amp;&amp; vm.watchdog-&gt;didFire())) {
</del><ins>+    if ((returnedException &amp;&amp; isTerminatedExecutionException(returnedException)) || isTerminatingExecution()) {
</ins><span class="cx">         forbidExecution();
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -149,20 +149,20 @@
</span><span class="cx"> void WorkerScriptController::scheduleExecutionTermination()
</span><span class="cx"> {
</span><span class="cx">     // The mutex provides a memory barrier to ensure that once
</span><del>-    // termination is scheduled, isExecutionTerminating will
</del><ins>+    // termination is scheduled, isTerminatingExecution() will
</ins><span class="cx">     // accurately reflect that state when called from another thread.
</span><span class="cx">     LockHolder locker(m_scheduledTerminationMutex);
</span><del>-    if (m_vm-&gt;watchdog)
-        m_vm-&gt;watchdog-&gt;fire();
</del><ins>+    m_isTerminatingExecution = true;
+
+    ASSERT(m_vm-&gt;watchdog);
+    m_vm-&gt;watchdog-&gt;terminateSoon();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool WorkerScriptController::isExecutionTerminating() const
</del><ins>+bool WorkerScriptController::isTerminatingExecution() const
</ins><span class="cx"> {
</span><span class="cx">     // See comments in scheduleExecutionTermination regarding mutex usage.
</span><span class="cx">     LockHolder locker(m_scheduledTerminationMutex);
</span><del>-    if (m_vm-&gt;watchdog)
-        return m_vm-&gt;watchdog-&gt;didFire();
-    return false;
</del><ins>+    return m_isTerminatingExecution;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WorkerScriptController::forbidExecution()
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWebCorebindingsjsWorkerScriptControllerh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/WorkerScriptController.h (189711 => 189712)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/WorkerScriptController.h        2015-09-14 12:00:47 UTC (rev 189711)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/bindings/js/WorkerScriptController.h        2015-09-14 12:27:53 UTC (rev 189712)
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx">         // forbidExecution()/isExecutionForbidden() to guard against reentry into JS.
</span><span class="cx">         // Can be called from any thread.
</span><span class="cx">         void scheduleExecutionTermination();
</span><del>-        bool isExecutionTerminating() const;
</del><ins>+        bool isTerminatingExecution() const;
</ins><span class="cx"> 
</span><span class="cx">         // Called on Worker thread when JS exits with termination exception caused by forbidExecution() request,
</span><span class="cx">         // or by Worker thread termination code to prevent future entry into JS.
</span><span class="lines">@@ -97,6 +97,7 @@
</span><span class="cx">         WorkerGlobalScope* m_workerGlobalScope;
</span><span class="cx">         JSC::Strong&lt;JSWorkerGlobalScope&gt; m_workerGlobalScopeWrapper;
</span><span class="cx">         bool m_executionForbidden;
</span><ins>+        bool m_isTerminatingExecution { false };
</ins><span class="cx">         mutable Lock m_scheduledTerminationMutex;
</span><span class="cx">     };
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>