<!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>[202286] trunk/Source/JavaScriptCore</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/202286">202286</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-06-21 12:03:22 -0700 (Tue, 21 Jun 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>LLInt doesn't throw stack exception overflow from parent frame
https://bugs.webkit.org/show_bug.cgi?id=158962
<rdar://problem/26902188>
Reviewed by Filip Pizlo.
All JIT tiers will throw stack overflow exceptions from the parent frame.
The LLInt, on the other hand, did not use to. I've changed the LLInt to be
consistent with the JITs. The reason I found this bug is because we had a
test that would give different results depending on if the function was compiled
in the baseline or the LLInt. Since Filip recently landed the concurrent baseline
JIT patch, this otherwise deterministic test became dependent on it being compiled
in the LLInt or one of the JIT tiers. I've added a new test that is deterministic
because it runs the test with --useJIT=false.
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* tests/stress/llint-stack-overflow-location.js: Added.
(stackTraceDescription):
(foo):
(catch):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressllintstackoverflowlocationjs">trunk/Source/JavaScriptCore/tests/stress/llint-stack-overflow-location.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (202285 => 202286)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-06-21 18:54:29 UTC (rev 202285)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-06-21 19:03:22 UTC (rev 202286)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2016-06-21 Saam Barati <sbarati@apple.com>
+
+ LLInt doesn't throw stack exception overflow from parent frame
+ https://bugs.webkit.org/show_bug.cgi?id=158962
+ <rdar://problem/26902188>
+
+ Reviewed by Filip Pizlo.
+
+ All JIT tiers will throw stack overflow exceptions from the parent frame.
+ The LLInt, on the other hand, did not use to. I've changed the LLInt to be
+ consistent with the JITs. The reason I found this bug is because we had a
+ test that would give different results depending on if the function was compiled
+ in the baseline or the LLInt. Since Filip recently landed the concurrent baseline
+ JIT patch, this otherwise deterministic test became dependent on it being compiled
+ in the LLInt or one of the JIT tiers. I've added a new test that is deterministic
+ because it runs the test with --useJIT=false.
+
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * tests/stress/llint-stack-overflow-location.js: Added.
+ (stackTraceDescription):
+ (foo):
+ (catch):
+
</ins><span class="cx"> 2016-06-21 David Kilzer <ddkilzer@apple.com>
</span><span class="cx">
</span><span class="cx"> CODE_SIGN_ENTITLEMENTS should be applied to iOS Simulator builds
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (202285 => 202286)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-06-21 18:54:29 UTC (rev 202285)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-06-21 19:03:22 UTC (rev 202286)
</span><span class="lines">@@ -93,8 +93,10 @@
</span><span class="cx">
</span><span class="cx"> VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
</span><span class="cx"> CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
</span><del>- if (!callerFrame)
</del><ins>+ if (!callerFrame) {
</ins><span class="cx"> callerFrame = exec;
</span><ins>+ vmEntryFrame = vm->topVMEntryFrame;
+ }
</ins><span class="cx">
</span><span class="cx"> NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
</span><span class="cx"> throwStackOverflowError(callerFrame);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (202285 => 202286)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-06-21 18:54:29 UTC (rev 202285)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-06-21 19:03:22 UTC (rev 202286)
</span><span class="lines">@@ -466,7 +466,17 @@
</span><span class="cx">
</span><span class="cx"> LLINT_SLOW_PATH_DECL(stack_check)
</span><span class="cx"> {
</span><del>- LLINT_BEGIN();
</del><ins>+ VM& vm = exec->vm();
+ VMEntryFrame* vmEntryFrame = vm.topVMEntryFrame;
+ CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
+ if (!callerFrame) {
+ callerFrame = exec;
+ vmEntryFrame = vm.topVMEntryFrame;
+ }
+ NativeCallFrameTracerWithRestore tracer(&vm, vmEntryFrame, callerFrame);
+
+ LLINT_SET_PC_FOR_STUBS();
+
</ins><span class="cx"> #if LLINT_SLOW_PATH_TRACING
</span><span class="cx"> dataLogF("Checking stack height with exec = %p.\n", exec);
</span><span class="cx"> dataLogF("CodeBlock = %p.\n", exec->codeBlock());
</span><span class="lines">@@ -493,10 +503,9 @@
</span><span class="cx"> LLINT_RETURN_TWO(pc, 0);
</span><span class="cx"> #endif
</span><span class="cx">
</span><del>- vm.topCallFrame = exec;
</del><span class="cx"> ErrorHandlingScope errorScope(vm);
</span><del>- vm.throwException(exec, createStackOverflowError(exec));
- pc = returnToThrow(exec);
</del><ins>+ throwStackOverflowError(callerFrame);
+ pc = returnToThrow(callerFrame);
</ins><span class="cx"> LLINT_RETURN_TWO(pc, exec);
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressllintstackoverflowlocationjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/llint-stack-overflow-location.js (0 => 202286)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/llint-stack-overflow-location.js         (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/llint-stack-overflow-location.js        2016-06-21 19:03:22 UTC (rev 202286)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+//@ runNoJIT
+
+function stackTraceDescription(stackFrame) {
+ let indexOfAt = stackFrame.indexOf('@')
+ let indexOfLastSlash = stackFrame.lastIndexOf('/');
+ if (indexOfLastSlash == -1)
+ indexOfLastSlash = indexOfAt
+ let functionName = stackFrame.substring(0, indexOfAt);
+ let fileName = stackFrame.substring(indexOfLastSlash + 1);
+ return functionName + " at " + fileName;
+}
+
+function foo(j) {
+ for (let i = 0; i < 20; i++) {
+ i--;
+ i++;
+ }
+ foo(j + 1);
+}
+
+let error = null;
+try {
+ foo(10);
+} catch(e) {
+ error = e;
+}
+
+if (!error)
+ throw new Error("No exception!");
+
+let frame = error.stack.split("\n")[0];
+let description = stackTraceDescription(frame);
+if (description.indexOf(".js:18") < 0)
+ throw new Error("Bad location: '" + description + "'");
+
</ins></span></pre>
</div>
</div>
</body>
</html>