<!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>[184260] trunk</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/184260">184260</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-05-12 22:21:16 -0700 (Tue, 12 May 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>js/dom/stack-trace.html fails with eager compilation
https://bugs.webkit.org/show_bug.cgi?id=144853

Reviewed by Benjamin Poulain.
        
Source/JavaScriptCore:

All of our escape analyses were mishandling Check(). They were assuming that this is a
non-escaping operation. But, if we do for example a Check(Int32:@x) and @x is an escape
candidate, then we need to do something: if we eliminate or sink @x, then the check no
longer makes any sense since a phantom allocation has no type. This will make us forget
that this operation would have exited. This was causing us to not call a valueOf method in
js/dom/stack-trace.html with eager compilation enabled, because it was doing something like
+o where o had a valueOf method, and o was otherwise sinkable.
        
This changes our escape analyses to basically pretend that any Check() that isn't obviously
unnecessary is an escape. We don't have to be super careful here. Most checks will be
completely eliminated by constant-folding. If that doesn't run in time, then the most
common check we will see is CellUse. So, we just recognize some very obvious check kinds
that we know would have passed, and for all of the rest we just assume that it's an escape.
        
This was super tricky to test. The obvious way to test it is to use +o like
stack-trace.html, except that doing so relies on the fact that we still haven't implemented
the optimal behavior for op_to_number. So, I take four approaches in testing this patch:
        
1) Use +o. These will test what we want it to test for now, but at some point in the future
   these tests will just be a good sanity-check that our op_to_number implementation is
   right.
        
2) Do fancy control flow tricks to fool the profiling into thinking that some arithmetic
   operation always sees integers even though we eventually feed it an object and that
   object is a sink candidate.
        
3) Introduce a new jsc.cpp intrinsic called isInt32() which returns true if the incoming
   value is an int32. This intrinsic is required to be implemented by DFG by
   unconditionally speculating that the input is int32. This allows us to write much more
   targetted tests of the underlying issue.
        
4) I made a version of stack-trace.html that runs in run-jsc-stress-tests, so that we can
   get regression test coverage of this test in eager mode.

* dfg/DFGArgumentsEliminationPhase.cpp:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsic):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
* dfg/DFGVarargsForwardingPhase.cpp:
* ftl/FTLExitValue.cpp:
(JSC::FTL::ExitValue::dumpInContext):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::buildExitArguments):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileFTLOSRExit):
* jsc.cpp:
(GlobalObject::finishCreation):
(functionIsInt32):
* runtime/Intrinsic.h:
* tests/stress/sink-arguments-past-invalid-check-dfg.js: Added.
* tests/stress/sink-arguments-past-invalid-check-int32-dfg.js: Added.
* tests/stress/sink-arguments-past-invalid-check-int32.js: Added.
* tests/stress/sink-arguments-past-invalid-check-sneakier.js: Added.
* tests/stress/sink-arguments-past-invalid-check.js: Added.
* tests/stress/sink-function-past-invalid-check-sneakier.js: Added.
* tests/stress/sink-function-past-invalid-check-sneaky.js: Added.
* tests/stress/sink-object-past-invalid-check-int32.js: Added.
* tests/stress/sink-object-past-invalid-check-sneakier.js: Added.
* tests/stress/sink-object-past-invalid-check-sneaky.js: Added.
* tests/stress/sink-object-past-invalid-check.js: Added.

LayoutTests:

Make a copy of the stack-trace test that only runs in run-jsc-stress-tests. Sadly, we don't
have a good way of having different expectation files for when a test runs in RJST versus
RWT. So, the approach I take is that I make a copy of the test just for RJST and I exclude
the .html file, which makes RWT overlook it. The test has different expectations in the
two harnesses because it does some small DOM things.

* js/script-tests/stack-trace.js: Added.
* js/stack-trace-expected.txt: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArgumentsEliminationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVarargsForwardingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLExitValuecpp">trunk/Source/JavaScriptCore/ftl/FTLExitValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExitCompilercpp">trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntrinsich">trunk/Source/JavaScriptCore/runtime/Intrinsic.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsscripttestsstacktracejs">trunk/LayoutTests/js/script-tests/stack-trace.js</a></li>
<li><a href="#trunkLayoutTestsjsstacktraceexpectedtxt">trunk/LayoutTests/js/stack-trace-expected.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkargumentspastinvalidcheckdfgjs">trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-dfg.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkargumentspastinvalidcheckint32dfgjs">trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-int32-dfg.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkargumentspastinvalidcheckint32js">trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-int32.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkargumentspastinvalidchecksneakierjs">trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-sneakier.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkargumentspastinvalidcheckjs">trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkfunctionpastinvalidchecksneakierjs">trunk/Source/JavaScriptCore/tests/stress/sink-function-past-invalid-check-sneakier.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkfunctionpastinvalidchecksneakyjs">trunk/Source/JavaScriptCore/tests/stress/sink-function-past-invalid-check-sneaky.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkobjectpastinvalidcheckint32js">trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-int32.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkobjectpastinvalidchecksneakierjs">trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-sneakier.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkobjectpastinvalidchecksneakyjs">trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-sneaky.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresssinkobjectpastinvalidcheckjs">trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/LayoutTests/ChangeLog        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2015-05-12  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        js/dom/stack-trace.html fails with eager compilation
+        https://bugs.webkit.org/show_bug.cgi?id=144853
+
+        Reviewed by Benjamin Poulain.
+        
+        Make a copy of the stack-trace test that only runs in run-jsc-stress-tests. Sadly, we don't
+        have a good way of having different expectation files for when a test runs in RJST versus
+        RWT. So, the approach I take is that I make a copy of the test just for RJST and I exclude
+        the .html file, which makes RWT overlook it. The test has different expectations in the
+        two harnesses because it does some small DOM things.
+
+        * js/script-tests/stack-trace.js: Added.
+        * js/stack-trace-expected.txt: Added.
+
</ins><span class="cx"> 2015-05-12  Joanmarie Diggs  &lt;jdiggs@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         AX: [Win] REGRESSION(r184213) breaks aria-menubar-menuitems.html
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsstacktracejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/script-tests/stack-trace.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/stack-trace.js                                (rev 0)
+++ trunk/LayoutTests/js/script-tests/stack-trace.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,371 @@
</span><ins>+if (!this.alert) {
+    debug = print;
+    description = print;
+}
+
+description(
+'This test checks stack trace corectness in special cases.'
+);
+
+function stackTraceLineFor(stackTrace, frameIndex) {
+    var i = frameIndex;
+    var indexOfAt = stackTrace[i].indexOf('@')
+    var indexOfLastSlash = stackTrace[i].lastIndexOf('/');
+    if (indexOfLastSlash == -1)
+        indexOfLastSlash = indexOfAt
+    var functionName = stackTrace[i].substring(0, indexOfAt);
+    var fileName = stackTrace[i].substring(indexOfLastSlash + 1);
+    return functionName + &quot; at &quot; + fileName;
+}
+
+function printStack(stackTrace) {
+    debug(&quot;--&gt; Stack Trace:&quot;)
+    stackTrace = stackTrace.split(&quot;\n&quot;);
+    var length = Math.min(stackTrace.length, 100);
+    for (var i = 0; i &lt; length; i++)
+        debug(&quot;    &quot; + i + &quot;   &quot; + stackTraceLineFor(stackTrace, i));
+    debug('');
+}
+
+function dumpPattern(pattern) {
+    for (var i = 0; i &lt; pattern.length; i++)
+        debug(&quot;    &quot; + i + &quot;   &quot; + pattern[i]);
+}
+
+function matchesPatternAtLine(pattern, patternIndex, traceLine) {
+    var patternLine = pattern[patternIndex];
+    return traceLine.slice(0, patternLine.length) == patternLine;
+}
+
+function matchPattern(pattern, traceLine) {
+    for (var i = 0; i &lt; pattern.length; i++) {
+        if (matchesPatternAtLine(pattern, i, traceLine))
+            return i;
+    }
+    return -1;
+}
+
+function checkStackForPattern(stackTrace, pattern) {
+    stackTrace = stackTrace.split(&quot;\n&quot;);
+    var length = Math.min(stackTrace.length, 100);
+
+    // Get the match in the pattern for the first line:
+    var firstStackTraceLine = stackTraceLineFor(stackTrace, 0);
+    var patternIndex = matchPattern(pattern, firstStackTraceLine);
+    if (patternIndex &lt; 0) {
+        debug(&quot;--&gt; Stack Trace FAILED to match pattern:&quot;)
+        dumpPattern(pattern);
+        debug('');
+        return;
+    }
+
+    for (var i = 1; i &lt; length; i++) {
+        patternIndex = ++patternIndex % pattern.length;
+        var traceLine = stackTraceLineFor(stackTrace, i);
+        if (!matchesPatternAtLine(pattern, patternIndex, traceLine)) {
+            debug(&quot;--&gt; Stack Trace FAILED to match pattern:&quot;)
+            dumpPattern(pattern);
+            debug('');
+            return;
+        }
+    }
+
+    debug(&quot;--&gt; Stack Trace matches pattern:&quot;)
+    dumpPattern(pattern);
+    debug('');
+}
+
+function hostThrower() { Element.prototype.appendChild.call({ }, [{ }]);  }
+function callbacker(f) { [0].map(f); }
+function outer(errorName) { inner(errorName); }
+function inner(errorName) { throw new Error(&quot;Error in &quot; + errorName); }
+function evaler(code) { eval(code); }
+function normalOuter() { normalInner(); }
+function normalInner() { if(thisVarDoesntExist) failIfTrue(&quot;shouldFailBeforeThis&quot;) };
+function scripterInner() { htmlInner(); }
+function scripterOuter() { htmlOuter(); }
+                                                                       // Expected functions in stack trace
+// Normal Case
+try { normalOuter() } catch (e) { printStack(e.stack) }                     // normalOuter -&gt; normalInner
+
+// Eval Case
+try { evaler(&quot;inner('inner eval');&quot;); } catch (e) { printStack(e.stack) }   // evaler -&gt; eval -&gt; inner
+try { evaler(&quot;outer('outer eval');&quot;); } catch (e) { printStack(e.stack) }   // evaler -&gt; eval -&gt; outer -&gt; inner
+
+// Function Callback Case
+try { callbacker(inner('inner map')); } catch (e) { printStack(e.stack); }   // callbacker -&gt; map -&gt; inner
+try { callbacker(outer('outer map')); } catch (e) { printStack(e.stack); }   // callbacker -&gt; map -&gt; outer -&gt; inner
+
+// Host Code Case
+try { hostThrower(); } catch (e) { printStack(e.stack); }                    // hostThrower
+
+try { scripterInner(); } catch (e) { printStack(e.stack) }                   // program -&gt; scripter -&gt; inner
+try { scripterOuter(); } catch (e) { printStack(e.stack) }                   // program -&gt; scripter -&gt; outer -&gt; inner
+
+function selfRecursive1() { selfRecursive1();
+}
+
+
+try { selfRecursive1(); } catch (e) { printStack(e.stack) }                   // selfRecursive1 -&gt; selfRecursive1 -&gt; selfRecursive1 -&gt; selfRecursive1 ...
+
+function selfRecursive2() {
+    // A little work to make the DFG kick in
+    for (var i = 0; i &lt; 10; i++) {
+        if (i == 9)
+            selfRecursive2(); 
+    }
+}
+
+try { selfRecursive2(); } catch (e) { printStack(e.stack) }                   // selfRecursive2 -&gt; selfRecursive2 -&gt; selfRecursive2 -&gt; selfRecursive2 ...
+
+function selfRecursive3() {
+    eval(&quot;selfRecursive3()&quot;);
+}
+
+try {
+    selfRecursive3();
+} catch (e) {
+    var pattern = [
+        &quot; at eval code&quot;,
+        &quot;eval at [native code]&quot;,
+        &quot;selfRecursive3 at stack-trace.js&quot;
+    ];
+    checkStackForPattern(e.stack, pattern);
+}
+
+var callCount = 0;
+
+function throwError() {
+    throw new Error();
+}
+
+var object = {
+    get getter1() {
+        var o = {
+            valueOf: function() {
+                throwError()
+            }
+        };
+        +o;
+    },
+    get getter2() {
+        var o = {
+            valueOf: throwError
+        };
+        +o;
+    },
+    get getter3() {
+        var o1 = {
+            valueOf: throwError
+        };
+        var o2 = {
+            valueOf: function () {
+                throwError();
+            }
+        };
+        if (callCount == 9998)
+            +o1;
+        if (callCount == 9999)
+            +o2;
+    },
+    nonInlineable : function () {
+        if (0) return [arguments, function(){}];
+        ++callCount;
+        if (callCount == 1) {
+            this.getter1;
+        } else if (callCount == 2) {
+            this.getter2;
+        } else {
+            this.getter3;
+        }
+    },
+    inlineable : function () {
+        this.nonInlineable();
+    }
+}
+
+function yetAnotherInlinedCall(o) {
+    o.inlineable();
+}
+
+function makeInlinableCall(o) {
+    for (var i = 0; i &lt; 10000; i++) {
+        new yetAnotherInlinedCall(o);
+    }
+}
+for (var k = 0; k &lt; 4; k++) {
+    try {
+        function g() {
+            var j = 0;
+            for (var i = 0; i &lt; 1000; i++) {
+                j++;
+                makeInlinableCall(object);
+            }
+        }
+        [1].map(g);
+    } catch (e) {
+        printStack(e.stack);
+    }
+}
+
+function h() {
+    if (callCount++ == 1000)
+        throw new Error();
+    if (callCount &gt; 1000) {
+        [].map.apply(undefined, throwError);
+    }
+}
+
+function mapTest(a) {
+    a.map(h);
+}
+
+function mapTestDriver() {
+    var a = [1,2,3];
+    for (var i = 0; i &lt; 2000; i++)
+        mapTest(a);
+}
+
+try {
+    callCount = 0;
+    mapTestDriver()
+} catch(e) {
+    printStack(e.stack);
+}
+
+try {
+    mapTestDriver()
+} catch(e) {
+    printStack(e.stack);
+}
+
+var dfgFunctionShouldThrow = false;
+function dfgFunction() { 
+    if (dfgFunctionShouldThrow) { 
+        dfgFunctionShouldThrow = false; 
+        throwError();
+    }
+}
+
+for (var k = 0; k &lt; 1000; k++)
+    dfgFunction();
+
+try {
+    dfgFunctionShouldThrow = true;
+    [1,2,3,4].map(dfgFunction);
+} catch (e) {
+    printStack(e.stack);
+}
+
+try { 
+    var o = { };
+    o.__defineGetter__(&quot;g&quot;, dfgFunction);
+    function f(o) {
+        o.g;
+    }
+    for (var k = 0; k &lt; 1000; k++)
+        f(o);
+    
+    dfgFunctionShouldThrow = true;
+    f(o);
+
+} catch (e) {
+    printStack(e.stack);
+}
+
+var someValue = null;
+
+function callNonCallable() {
+    someValue();
+}
+
+for (var i = 0; i &lt; 100; i++) {
+    try {
+        callNonCallable();
+    } catch (e) {
+    }
+}
+
+function dfgTest(f) {
+    dfgCount = 0;
+    while (dfgCount++ &lt; 1000) {
+        try {
+            f();
+        } catch (e) {
+            printStack(e.stack)
+            return;
+        }
+    }
+}
+
+function inlineableThrow() {
+    if (dfgCount &gt; 500) throw new Error();
+}
+
+var dfgThing = {
+    get willThrow() {
+        if (dfgCount &gt; 500)
+            throw new Error();
+    },
+    get willThrowEventually() {
+        inlineableThrow();
+    },
+    willThrowFunc: function () { if (dfgCount &gt; 500) throw new Error(); },
+    willThrowEventuallyFunc: function () { inlineableThrow(); }
+}
+dfgThing.__defineGetter__(&quot;hostWillThrow&quot;, hostThrower);
+
+function dfg1() {
+    dfgThing.willThrow
+}
+
+function dfg2() {
+    dfg1();
+}
+
+function dfg3() {
+    dfg2();
+}
+
+function dfg4() {
+    dfgThing.willThrowFunc();
+}
+
+function dfg5() {
+    dfg4();
+}
+
+function dfg6() {
+    dfg5();
+}
+
+function dfg7() {
+    dfgThing.willThrowEventually
+}
+
+function dfg8() {
+    dfg7();
+}
+
+function dfg9() {
+    dfg8();
+}
+
+function dfga() {
+    dfgThing.willThrowEventuallyFunc();
+}
+
+function dfgb() {
+    dfga();
+}
+
+function dfgc() {
+    dfgb();
+}
+
+dfgTest(dfg3)
+dfgTest(dfg6)
+dfgTest(dfg9)
+dfgTest(dfgc)
+
+successfullyParsed = true;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsstacktraceexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/stack-trace-expected.txt (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/stack-trace-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/stack-trace-expected.txt        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,362 @@
</span><ins>+This test checks stack trace corectness in special cases.
+--&gt; Stack Trace:
+    0   normalInner at stack-trace.js:84:47
+    1   normalOuter at stack-trace.js:83:37
+    2   global code at stack-trace.js:89:18
+
+--&gt; Stack Trace:
+    0   inner at stack-trace.js:81:44
+    1    at eval code
+    2   eval at [native code]
+    3   evaler at stack-trace.js:82:29
+    4   global code at stack-trace.js:92:13
+
+--&gt; Stack Trace:
+    0   inner at stack-trace.js:81:44
+    1   outer at stack-trace.js:80:34
+    2    at eval code
+    3   eval at [native code]
+    4   evaler at stack-trace.js:82:29
+    5   global code at stack-trace.js:93:13
+
+--&gt; Stack Trace:
+    0   inner at stack-trace.js:81:44
+    1   global code at stack-trace.js:96:23
+
+--&gt; Stack Trace:
+    0   inner at stack-trace.js:81:44
+    1   outer at stack-trace.js:80:34
+    2   global code at stack-trace.js:97:23
+
+--&gt; Stack Trace:
+    0   hostThrower at stack-trace.js:78:43
+    1   global code at stack-trace.js:100:18
+
+--&gt; Stack Trace:
+    0   scripterInner at stack-trace.js:85:37
+    1   global code at stack-trace.js:102:20
+
+--&gt; Stack Trace:
+    0   scripterOuter at stack-trace.js:86:37
+    1   global code at stack-trace.js:103:20
+
+--&gt; Stack Trace:
+    0   selfRecursive1 at stack-trace.js:105:43
+    1   selfRecursive1 at stack-trace.js:105:43
+    2   selfRecursive1 at stack-trace.js:105:43
+    3   selfRecursive1 at stack-trace.js:105:43
+    4   selfRecursive1 at stack-trace.js:105:43
+    5   selfRecursive1 at stack-trace.js:105:43
+    6   selfRecursive1 at stack-trace.js:105:43
+    7   selfRecursive1 at stack-trace.js:105:43
+    8   selfRecursive1 at stack-trace.js:105:43
+    9   selfRecursive1 at stack-trace.js:105:43
+    10   selfRecursive1 at stack-trace.js:105:43
+    11   selfRecursive1 at stack-trace.js:105:43
+    12   selfRecursive1 at stack-trace.js:105:43
+    13   selfRecursive1 at stack-trace.js:105:43
+    14   selfRecursive1 at stack-trace.js:105:43
+    15   selfRecursive1 at stack-trace.js:105:43
+    16   selfRecursive1 at stack-trace.js:105:43
+    17   selfRecursive1 at stack-trace.js:105:43
+    18   selfRecursive1 at stack-trace.js:105:43
+    19   selfRecursive1 at stack-trace.js:105:43
+    20   selfRecursive1 at stack-trace.js:105:43
+    21   selfRecursive1 at stack-trace.js:105:43
+    22   selfRecursive1 at stack-trace.js:105:43
+    23   selfRecursive1 at stack-trace.js:105:43
+    24   selfRecursive1 at stack-trace.js:105:43
+    25   selfRecursive1 at stack-trace.js:105:43
+    26   selfRecursive1 at stack-trace.js:105:43
+    27   selfRecursive1 at stack-trace.js:105:43
+    28   selfRecursive1 at stack-trace.js:105:43
+    29   selfRecursive1 at stack-trace.js:105:43
+    30   selfRecursive1 at stack-trace.js:105:43
+    31   selfRecursive1 at stack-trace.js:105:43
+    32   selfRecursive1 at stack-trace.js:105:43
+    33   selfRecursive1 at stack-trace.js:105:43
+    34   selfRecursive1 at stack-trace.js:105:43
+    35   selfRecursive1 at stack-trace.js:105:43
+    36   selfRecursive1 at stack-trace.js:105:43
+    37   selfRecursive1 at stack-trace.js:105:43
+    38   selfRecursive1 at stack-trace.js:105:43
+    39   selfRecursive1 at stack-trace.js:105:43
+    40   selfRecursive1 at stack-trace.js:105:43
+    41   selfRecursive1 at stack-trace.js:105:43
+    42   selfRecursive1 at stack-trace.js:105:43
+    43   selfRecursive1 at stack-trace.js:105:43
+    44   selfRecursive1 at stack-trace.js:105:43
+    45   selfRecursive1 at stack-trace.js:105:43
+    46   selfRecursive1 at stack-trace.js:105:43
+    47   selfRecursive1 at stack-trace.js:105:43
+    48   selfRecursive1 at stack-trace.js:105:43
+    49   selfRecursive1 at stack-trace.js:105:43
+    50   selfRecursive1 at stack-trace.js:105:43
+    51   selfRecursive1 at stack-trace.js:105:43
+    52   selfRecursive1 at stack-trace.js:105:43
+    53   selfRecursive1 at stack-trace.js:105:43
+    54   selfRecursive1 at stack-trace.js:105:43
+    55   selfRecursive1 at stack-trace.js:105:43
+    56   selfRecursive1 at stack-trace.js:105:43
+    57   selfRecursive1 at stack-trace.js:105:43
+    58   selfRecursive1 at stack-trace.js:105:43
+    59   selfRecursive1 at stack-trace.js:105:43
+    60   selfRecursive1 at stack-trace.js:105:43
+    61   selfRecursive1 at stack-trace.js:105:43
+    62   selfRecursive1 at stack-trace.js:105:43
+    63   selfRecursive1 at stack-trace.js:105:43
+    64   selfRecursive1 at stack-trace.js:105:43
+    65   selfRecursive1 at stack-trace.js:105:43
+    66   selfRecursive1 at stack-trace.js:105:43
+    67   selfRecursive1 at stack-trace.js:105:43
+    68   selfRecursive1 at stack-trace.js:105:43
+    69   selfRecursive1 at stack-trace.js:105:43
+    70   selfRecursive1 at stack-trace.js:105:43
+    71   selfRecursive1 at stack-trace.js:105:43
+    72   selfRecursive1 at stack-trace.js:105:43
+    73   selfRecursive1 at stack-trace.js:105:43
+    74   selfRecursive1 at stack-trace.js:105:43
+    75   selfRecursive1 at stack-trace.js:105:43
+    76   selfRecursive1 at stack-trace.js:105:43
+    77   selfRecursive1 at stack-trace.js:105:43
+    78   selfRecursive1 at stack-trace.js:105:43
+    79   selfRecursive1 at stack-trace.js:105:43
+    80   selfRecursive1 at stack-trace.js:105:43
+    81   selfRecursive1 at stack-trace.js:105:43
+    82   selfRecursive1 at stack-trace.js:105:43
+    83   selfRecursive1 at stack-trace.js:105:43
+    84   selfRecursive1 at stack-trace.js:105:43
+    85   selfRecursive1 at stack-trace.js:105:43
+    86   selfRecursive1 at stack-trace.js:105:43
+    87   selfRecursive1 at stack-trace.js:105:43
+    88   selfRecursive1 at stack-trace.js:105:43
+    89   selfRecursive1 at stack-trace.js:105:43
+    90   selfRecursive1 at stack-trace.js:105:43
+    91   selfRecursive1 at stack-trace.js:105:43
+    92   selfRecursive1 at stack-trace.js:105:43
+    93   selfRecursive1 at stack-trace.js:105:43
+    94   selfRecursive1 at stack-trace.js:105:43
+    95   selfRecursive1 at stack-trace.js:105:43
+    96   selfRecursive1 at stack-trace.js:105:43
+    97   selfRecursive1 at stack-trace.js:105:43
+    98   selfRecursive1 at stack-trace.js:105:43
+    99   selfRecursive1 at stack-trace.js:105:43
+
+--&gt; Stack Trace:
+    0   selfRecursive2 at stack-trace.js:115:27
+    1   selfRecursive2 at stack-trace.js:115:27
+    2   selfRecursive2 at stack-trace.js:115:27
+    3   selfRecursive2 at stack-trace.js:115:27
+    4   selfRecursive2 at stack-trace.js:115:27
+    5   selfRecursive2 at stack-trace.js:115:27
+    6   selfRecursive2 at stack-trace.js:115:27
+    7   selfRecursive2 at stack-trace.js:115:27
+    8   selfRecursive2 at stack-trace.js:115:27
+    9   selfRecursive2 at stack-trace.js:115:27
+    10   selfRecursive2 at stack-trace.js:115:27
+    11   selfRecursive2 at stack-trace.js:115:27
+    12   selfRecursive2 at stack-trace.js:115:27
+    13   selfRecursive2 at stack-trace.js:115:27
+    14   selfRecursive2 at stack-trace.js:115:27
+    15   selfRecursive2 at stack-trace.js:115:27
+    16   selfRecursive2 at stack-trace.js:115:27
+    17   selfRecursive2 at stack-trace.js:115:27
+    18   selfRecursive2 at stack-trace.js:115:27
+    19   selfRecursive2 at stack-trace.js:115:27
+    20   selfRecursive2 at stack-trace.js:115:27
+    21   selfRecursive2 at stack-trace.js:115:27
+    22   selfRecursive2 at stack-trace.js:115:27
+    23   selfRecursive2 at stack-trace.js:115:27
+    24   selfRecursive2 at stack-trace.js:115:27
+    25   selfRecursive2 at stack-trace.js:115:27
+    26   selfRecursive2 at stack-trace.js:115:27
+    27   selfRecursive2 at stack-trace.js:115:27
+    28   selfRecursive2 at stack-trace.js:115:27
+    29   selfRecursive2 at stack-trace.js:115:27
+    30   selfRecursive2 at stack-trace.js:115:27
+    31   selfRecursive2 at stack-trace.js:115:27
+    32   selfRecursive2 at stack-trace.js:115:27
+    33   selfRecursive2 at stack-trace.js:115:27
+    34   selfRecursive2 at stack-trace.js:115:27
+    35   selfRecursive2 at stack-trace.js:115:27
+    36   selfRecursive2 at stack-trace.js:115:27
+    37   selfRecursive2 at stack-trace.js:115:27
+    38   selfRecursive2 at stack-trace.js:115:27
+    39   selfRecursive2 at stack-trace.js:115:27
+    40   selfRecursive2 at stack-trace.js:115:27
+    41   selfRecursive2 at stack-trace.js:115:27
+    42   selfRecursive2 at stack-trace.js:115:27
+    43   selfRecursive2 at stack-trace.js:115:27
+    44   selfRecursive2 at stack-trace.js:115:27
+    45   selfRecursive2 at stack-trace.js:115:27
+    46   selfRecursive2 at stack-trace.js:115:27
+    47   selfRecursive2 at stack-trace.js:115:27
+    48   selfRecursive2 at stack-trace.js:115:27
+    49   selfRecursive2 at stack-trace.js:115:27
+    50   selfRecursive2 at stack-trace.js:115:27
+    51   selfRecursive2 at stack-trace.js:115:27
+    52   selfRecursive2 at stack-trace.js:115:27
+    53   selfRecursive2 at stack-trace.js:115:27
+    54   selfRecursive2 at stack-trace.js:115:27
+    55   selfRecursive2 at stack-trace.js:115:27
+    56   selfRecursive2 at stack-trace.js:115:27
+    57   selfRecursive2 at stack-trace.js:115:27
+    58   selfRecursive2 at stack-trace.js:115:27
+    59   selfRecursive2 at stack-trace.js:115:27
+    60   selfRecursive2 at stack-trace.js:115:27
+    61   selfRecursive2 at stack-trace.js:115:27
+    62   selfRecursive2 at stack-trace.js:115:27
+    63   selfRecursive2 at stack-trace.js:115:27
+    64   selfRecursive2 at stack-trace.js:115:27
+    65   selfRecursive2 at stack-trace.js:115:27
+    66   selfRecursive2 at stack-trace.js:115:27
+    67   selfRecursive2 at stack-trace.js:115:27
+    68   selfRecursive2 at stack-trace.js:115:27
+    69   selfRecursive2 at stack-trace.js:115:27
+    70   selfRecursive2 at stack-trace.js:115:27
+    71   selfRecursive2 at stack-trace.js:115:27
+    72   selfRecursive2 at stack-trace.js:115:27
+    73   selfRecursive2 at stack-trace.js:115:27
+    74   selfRecursive2 at stack-trace.js:115:27
+    75   selfRecursive2 at stack-trace.js:115:27
+    76   selfRecursive2 at stack-trace.js:115:27
+    77   selfRecursive2 at stack-trace.js:115:27
+    78   selfRecursive2 at stack-trace.js:115:27
+    79   selfRecursive2 at stack-trace.js:115:27
+    80   selfRecursive2 at stack-trace.js:115:27
+    81   selfRecursive2 at stack-trace.js:115:27
+    82   selfRecursive2 at stack-trace.js:115:27
+    83   selfRecursive2 at stack-trace.js:115:27
+    84   selfRecursive2 at stack-trace.js:115:27
+    85   selfRecursive2 at stack-trace.js:115:27
+    86   selfRecursive2 at stack-trace.js:115:27
+    87   selfRecursive2 at stack-trace.js:115:27
+    88   selfRecursive2 at stack-trace.js:115:27
+    89   selfRecursive2 at stack-trace.js:115:27
+    90   selfRecursive2 at stack-trace.js:115:27
+    91   selfRecursive2 at stack-trace.js:115:27
+    92   selfRecursive2 at stack-trace.js:115:27
+    93   selfRecursive2 at stack-trace.js:115:27
+    94   selfRecursive2 at stack-trace.js:115:27
+    95   selfRecursive2 at stack-trace.js:115:27
+    96   selfRecursive2 at stack-trace.js:115:27
+    97   selfRecursive2 at stack-trace.js:115:27
+    98   selfRecursive2 at stack-trace.js:115:27
+    99   selfRecursive2 at stack-trace.js:115:27
+
+--&gt; Stack Trace matches pattern:
+    0    at eval code
+    1   eval at [native code]
+    2   selfRecursive3 at stack-trace.js
+
+--&gt; Stack Trace:
+    0   throwError at stack-trace.js:139:20
+    1   valueOf at stack-trace.js:146:27
+    2   getter1 at stack-trace.js:149:11
+    3   nonInlineable at stack-trace.js:175:17
+    4   inlineable at stack-trace.js:183:27
+    5   yetAnotherInlinedCall at stack-trace.js:188:17
+    6   makeInlinableCall at stack-trace.js:193:34
+    7   g at stack-trace.js:202:34
+    8   map at [native code]
+    9   global code at stack-trace.js:205:16
+
+--&gt; Stack Trace:
+    0   throwError at stack-trace.js:139:20
+    1   getter2 at stack-trace.js:155:11
+    2   nonInlineable at stack-trace.js:177:17
+    3   inlineable at stack-trace.js:183:27
+    4   yetAnotherInlinedCall at stack-trace.js:188:17
+    5   makeInlinableCall at stack-trace.js:193:34
+    6   g at stack-trace.js:202:34
+    7   map at [native code]
+    8   global code at stack-trace.js:205:16
+
+--&gt; Stack Trace:
+    0   throwError at stack-trace.js:139:20
+    1   getter3 at stack-trace.js:167:16
+    2   nonInlineable at stack-trace.js:179:17
+    3   inlineable at stack-trace.js:183:27
+    4   yetAnotherInlinedCall at stack-trace.js:188:17
+    5   makeInlinableCall at stack-trace.js:193:34
+    6   g at stack-trace.js:202:34
+    7   map at [native code]
+    8   global code at stack-trace.js:205:16
+
+--&gt; Stack Trace:
+    0   throwError at stack-trace.js:139:20
+    1   valueOf at stack-trace.js:163:27
+    2   getter3 at stack-trace.js:169:16
+    3   nonInlineable at stack-trace.js:179:17
+    4   inlineable at stack-trace.js:183:27
+    5   yetAnotherInlinedCall at stack-trace.js:188:17
+    6   makeInlinableCall at stack-trace.js:193:34
+    7   g at stack-trace.js:202:34
+    8   map at [native code]
+    9   global code at stack-trace.js:205:16
+
+--&gt; Stack Trace:
+    0   h at stack-trace.js:213:24
+    1   map at [native code]
+    2   mapTest at stack-trace.js:220:10
+    3   mapTestDriver at stack-trace.js:226:16
+    4   global code at stack-trace.js:231:18
+
+--&gt; Stack Trace:
+    0   map at [native code]
+    1   h at stack-trace.js:215:21
+    2   map at [native code]
+    3   mapTest at stack-trace.js:220:10
+    4   mapTestDriver at stack-trace.js:226:16
+    5   global code at stack-trace.js:237:18
+
+--&gt; Stack Trace:
+    0   throwError at stack-trace.js:139:20
+    1   dfgFunction at stack-trace.js:246:19
+    2   map at [native code]
+    3   global code at stack-trace.js:255:18
+
+--&gt; Stack Trace:
+    0   throwError at stack-trace.js:139:20
+    1   dfgFunction at stack-trace.js:246:19
+    2   f at stack-trace.js:264:10
+    3   global code at stack-trace.js:270:6
+
+--&gt; Stack Trace:
+    0   willThrow at stack-trace.js:308:28
+    1   dfg1 at stack-trace.js:319:13
+    2   dfg2 at stack-trace.js:323:9
+    3   dfg3 at stack-trace.js:327:9
+    4   dfgTest at stack-trace.js:293:14
+    5   global code at stack-trace.js:366:8
+
+--&gt; Stack Trace:
+    0   willThrowFunc at stack-trace.js:313:69
+    1   dfg4 at stack-trace.js:331:27
+    2   dfg5 at stack-trace.js:335:9
+    3   dfg6 at stack-trace.js:339:9
+    4   dfgTest at stack-trace.js:293:14
+    5   global code at stack-trace.js:367:8
+
+--&gt; Stack Trace:
+    0   inlineableThrow at stack-trace.js:302:40
+    1   willThrowEventually at stack-trace.js:311:24
+    2   dfg7 at stack-trace.js:343:13
+    3   dfg8 at stack-trace.js:347:9
+    4   dfg9 at stack-trace.js:351:9
+    5   dfgTest at stack-trace.js:293:14
+    6   global code at stack-trace.js:368:8
+
+--&gt; Stack Trace:
+    0   inlineableThrow at stack-trace.js:302:40
+    1   willThrowEventuallyFunc at stack-trace.js:314:59
+    2   dfga at stack-trace.js:355:37
+    3   dfgb at stack-trace.js:359:9
+    4   dfgc at stack-trace.js:363:9
+    5   dfgTest at stack-trace.js:293:14
+    6   global code at stack-trace.js:369:8
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -1,3 +1,72 @@
</span><ins>+2015-05-12  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        js/dom/stack-trace.html fails with eager compilation
+        https://bugs.webkit.org/show_bug.cgi?id=144853
+
+        Reviewed by Benjamin Poulain.
+        
+        All of our escape analyses were mishandling Check(). They were assuming that this is a
+        non-escaping operation. But, if we do for example a Check(Int32:@x) and @x is an escape
+        candidate, then we need to do something: if we eliminate or sink @x, then the check no
+        longer makes any sense since a phantom allocation has no type. This will make us forget
+        that this operation would have exited. This was causing us to not call a valueOf method in
+        js/dom/stack-trace.html with eager compilation enabled, because it was doing something like
+        +o where o had a valueOf method, and o was otherwise sinkable.
+        
+        This changes our escape analyses to basically pretend that any Check() that isn't obviously
+        unnecessary is an escape. We don't have to be super careful here. Most checks will be
+        completely eliminated by constant-folding. If that doesn't run in time, then the most
+        common check we will see is CellUse. So, we just recognize some very obvious check kinds
+        that we know would have passed, and for all of the rest we just assume that it's an escape.
+        
+        This was super tricky to test. The obvious way to test it is to use +o like
+        stack-trace.html, except that doing so relies on the fact that we still haven't implemented
+        the optimal behavior for op_to_number. So, I take four approaches in testing this patch:
+        
+        1) Use +o. These will test what we want it to test for now, but at some point in the future
+           these tests will just be a good sanity-check that our op_to_number implementation is
+           right.
+        
+        2) Do fancy control flow tricks to fool the profiling into thinking that some arithmetic
+           operation always sees integers even though we eventually feed it an object and that
+           object is a sink candidate.
+        
+        3) Introduce a new jsc.cpp intrinsic called isInt32() which returns true if the incoming
+           value is an int32. This intrinsic is required to be implemented by DFG by
+           unconditionally speculating that the input is int32. This allows us to write much more
+           targetted tests of the underlying issue.
+        
+        4) I made a version of stack-trace.html that runs in run-jsc-stress-tests, so that we can
+           get regression test coverage of this test in eager mode.
+
+        * dfg/DFGArgumentsEliminationPhase.cpp:
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsic):
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        (JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
+        * dfg/DFGVarargsForwardingPhase.cpp:
+        * ftl/FTLExitValue.cpp:
+        (JSC::FTL::ExitValue::dumpInContext):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::buildExitArguments):
+        * ftl/FTLOSRExitCompiler.cpp:
+        (JSC::FTL::compileFTLOSRExit):
+        * jsc.cpp:
+        (GlobalObject::finishCreation):
+        (functionIsInt32):
+        * runtime/Intrinsic.h:
+        * tests/stress/sink-arguments-past-invalid-check-dfg.js: Added.
+        * tests/stress/sink-arguments-past-invalid-check-int32-dfg.js: Added.
+        * tests/stress/sink-arguments-past-invalid-check-int32.js: Added.
+        * tests/stress/sink-arguments-past-invalid-check-sneakier.js: Added.
+        * tests/stress/sink-arguments-past-invalid-check.js: Added.
+        * tests/stress/sink-function-past-invalid-check-sneakier.js: Added.
+        * tests/stress/sink-function-past-invalid-check-sneaky.js: Added.
+        * tests/stress/sink-object-past-invalid-check-int32.js: Added.
+        * tests/stress/sink-object-past-invalid-check-sneakier.js: Added.
+        * tests/stress/sink-object-past-invalid-check-sneaky.js: Added.
+        * tests/stress/sink-object-past-invalid-check.js: Added.
+
</ins><span class="cx"> 2015-05-12  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix the iteration count of arith-modulo-node-behaviors.js
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArgumentsEliminationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -42,11 +42,14 @@
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/HashSet.h&gt;
</span><ins>+#include &lt;wtf/ListDump.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><span class="cx"> namespace {
</span><span class="cx"> 
</span><ins>+bool verbose = false;
+
</ins><span class="cx"> class ArgumentsEliminationPhase : public Phase {
</span><span class="cx"> public:
</span><span class="cx">     ArgumentsEliminationPhase(Graph&amp; graph)
</span><span class="lines">@@ -101,6 +104,9 @@
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">         }
</span><ins>+        
+        if (verbose)
+            dataLog(&quot;Candidates: &quot;, listDump(m_candidates), &quot;\n&quot;);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Look for escaping sites, and remove from the candidates set if we see an escape.
</span><span class="lines">@@ -160,6 +166,21 @@
</span><span class="cx">                     break;
</span><span class="cx"> 
</span><span class="cx">                 case Check:
</span><ins>+                    m_graph.doToChildren(
+                        node,
+                        [&amp;] (Edge edge) {
+                            switch (edge.useKind()) {
+                            case CellUse:
+                            case ObjectUse:
+                                break;
+                                
+                            default:
+                                escape(edge);
+                                break;
+                            }
+                        });
+                    break;
+                    
</ins><span class="cx">                 case MovHint:
</span><span class="cx">                 case PutHint:
</span><span class="cx">                     break;
</span><span class="lines">@@ -189,6 +210,9 @@
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">         }
</span><ins>+
+        if (verbose)
+            dataLog(&quot;After escape analysis: &quot;, listDump(m_candidates), &quot;\n&quot;);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Anywhere that a candidate is live (in bytecode or in DFG), check if there is a chance of
</span><span class="lines">@@ -331,6 +355,9 @@
</span><span class="cx">         // availabilities may become whatever. OSR exit should be able to handle this quite naturally,
</span><span class="cx">         // since those availabilities speak of the stack before the optimizing compiler stack frame is
</span><span class="cx">         // torn down.
</span><ins>+
+        if (verbose)
+            dataLog(&quot;After interference analysis: &quot;, listDump(m_candidates), &quot;\n&quot;);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void transform()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -2111,6 +2111,16 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">         
</span><ins>+    case CheckInt32Intrinsic: {
+        insertChecks();
+        for (int i = 1; i &lt; argumentCountIncludingThis; ++i) {
+            Node* node = get(virtualRegisterForArgument(i, registerOffset));
+            addToGraph(Phantom, Edge(node, Int32Use));
+        }
+        set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
+        return true;
+    }
+        
</ins><span class="cx">     case FiatInt52Intrinsic: {
</span><span class="cx">         if (argumentCountIncludingThis != 2)
</span><span class="cx">             return false;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -828,25 +828,45 @@
</span><span class="cx">         case NewFunction:
</span><span class="cx">             if (!node-&gt;castOperand&lt;FunctionExecutable*&gt;()-&gt;singletonFunction()-&gt;isStillValid())
</span><span class="cx">                 sinkCandidate();
</span><del>-            m_graph.doToChildren(
-                node,
-                [&amp;] (Edge edge) {
-                    escape(edge.node());
-                });
</del><ins>+            escape(node-&gt;child1().node());
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case CreateActivation:
</span><span class="cx">             if (!m_graph.symbolTableFor(node-&gt;origin.semantic)-&gt;singletonScope()-&gt;isStillValid())
</span><span class="cx">                 sinkCandidate();
</span><ins>+            escape(node-&gt;child1().node());
+            break;
+
+        case Check:
</ins><span class="cx">             m_graph.doToChildren(
</span><span class="cx">                 node,
</span><span class="cx">                 [&amp;] (Edge edge) {
</span><del>-                    escape(edge.node());
</del><ins>+                    bool ok = true;
+
+                    switch (edge.useKind()) {
+                    case KnownCellUse:
+                    case CellUse:
+                    case ObjectUse:
+                        // All of our allocations will pass this.
+                        break;
+                        
+                    case FunctionUse:
+                        // Function allocations will pass this.
+                        if (edge-&gt;op() != NewFunction)
+                            ok = false;
+                        break;
+                        
+                    default:
+                        ok = false;
+                        break;
+                    }
+                    
+                    if (!ok)
+                        escape(edge.node());
</ins><span class="cx">                 });
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case MovHint:
</span><del>-        case Check:
</del><span class="cx">         case PutHint:
</span><span class="cx">         case StoreBarrier:
</span><span class="cx">         case StoreBarrierWithNullCheck:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVarargsForwardingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -104,7 +104,30 @@
</span><span class="cx">                     relevantLocals.append(node-&gt;unlinkedLocal());
</span><span class="cx">                 break;
</span><span class="cx">                 
</span><del>-            case Check:
</del><ins>+            case Check: {
+                bool sawEscape = false;
+                m_graph.doToChildren(
+                    node,
+                    [&amp;] (Edge edge) {
+                        switch (edge.useKind()) {
+                        case CellUse:
+                        case ObjectUse:
+                            if (edge == candidate)
+                                lastUserIndex = nodeIndex;
+                            break;
+                        default:
+                            sawEscape = true;
+                            break;
+                        }  
+                    });
+                if (sawEscape) {
+                    if (verbose)
+                        dataLog(&quot;    Escape at &quot;, node, &quot;\n&quot;);
+                    return;
+                }
+                break;
+            }
+                
</ins><span class="cx">             case LoadVarargs:
</span><span class="cx">                 if (m_graph.uses(node, candidate))
</span><span class="cx">                     lastUserIndex = nodeIndex;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLExitValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLExitValue.cpp (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLExitValue.cpp        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/Source/JavaScriptCore/ftl/FTLExitValue.cpp        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -114,7 +114,7 @@
</span><span class="cx">         out.print(&quot;Recovery(&quot;, recoveryOpcode(), &quot;, arg&quot;, leftRecoveryArgument(), &quot;, arg&quot;, rightRecoveryArgument(), &quot;, &quot;, recoveryFormat(), &quot;)&quot;);
</span><span class="cx">         return;
</span><span class="cx">     case ExitValueMaterializeNewObject:
</span><del>-        out.print(&quot;Materialize(&quot;, WTF::RawPointer(objectMaterialization()), &quot;:..)&quot;);
</del><ins>+        out.print(&quot;Materialize(&quot;, WTF::RawPointer(objectMaterialization()), &quot;)&quot;);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -8052,7 +8052,7 @@
</span><span class="cx">             if (!exit.m_materializations.isEmpty()) {
</span><span class="cx">                 dataLog(&quot;        Materializations: \n&quot;);
</span><span class="cx">                 for (ExitTimeObjectMaterialization* materialization : exit.m_materializations)
</span><del>-                    dataLog(&quot;            Materialize(&quot;, pointerDump(materialization), &quot;)\n&quot;);
</del><ins>+                    dataLog(&quot;            &quot;, pointerDump(materialization), &quot;\n&quot;);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -477,6 +477,19 @@
</span><span class="cx">     JITCode* jitCode = codeBlock-&gt;jitCode()-&gt;ftl();
</span><span class="cx">     OSRExit&amp; exit = jitCode-&gt;osrExit[exitID];
</span><span class="cx">     
</span><ins>+    if (shouldShowDisassembly() || Options::verboseOSR() || Options::verboseFTLOSRExit()) {
+        dataLog(&quot;    Owning block: &quot;, pointerDump(codeBlock), &quot;\n&quot;);
+        dataLog(&quot;    Origin: &quot;, exit.m_codeOrigin, &quot;\n&quot;);
+        if (exit.m_codeOriginForExitProfile != exit.m_codeOrigin)
+            dataLog(&quot;    Origin for exit profile: &quot;, exit.m_codeOriginForExitProfile, &quot;\n&quot;);
+        dataLog(&quot;    Exit values: &quot;, exit.m_values, &quot;\n&quot;);
+        if (!exit.m_materializations.isEmpty()) {
+            dataLog(&quot;    Materializations:\n&quot;);
+            for (ExitTimeObjectMaterialization* materialization : exit.m_materializations)
+                dataLog(&quot;        &quot;, pointerDump(materialization), &quot;\n&quot;);
+        }
+    }
+
</ins><span class="cx">     prepareCodeOriginForOSRExit(exec, exit.m_codeOrigin);
</span><span class="cx">     
</span><span class="cx">     compileStub(exitID, jitCode, exit, vm, codeBlock);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -470,6 +470,7 @@
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionFalse2(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
</span><ins>+static EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState*);
</ins><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
</span><span class="lines">@@ -620,6 +621,7 @@
</span><span class="cx">         putDirectNativeFunction(vm, this, Identifier::fromString(&amp;vm, &quot;OSRExit&quot;), 0, functionUndefined1, OSRExitIntrinsic, DontEnum | JSC::Function);
</span><span class="cx">         putDirectNativeFunction(vm, this, Identifier::fromString(&amp;vm, &quot;isFinalTier&quot;), 0, functionFalse2, IsFinalTierIntrinsic, DontEnum | JSC::Function);
</span><span class="cx">         putDirectNativeFunction(vm, this, Identifier::fromString(&amp;vm, &quot;predictInt32&quot;), 0, functionUndefined2, SetInt32HeapPredictionIntrinsic, DontEnum | JSC::Function);
</span><ins>+        putDirectNativeFunction(vm, this, Identifier::fromString(&amp;vm, &quot;isInt32&quot;), 0, functionIsInt32, CheckInt32Intrinsic, DontEnum | JSC::Function);
</ins><span class="cx">         putDirectNativeFunction(vm, this, Identifier::fromString(&amp;vm, &quot;fiatInt52&quot;), 0, functionIdentity, FiatInt52Intrinsic, DontEnum | JSC::Function);
</span><span class="cx">         
</span><span class="cx">         addFunction(vm, &quot;effectful42&quot;, functionEffectful42, 0);
</span><span class="lines">@@ -1056,6 +1058,14 @@
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL functionUndefined1(ExecState*) { return JSValue::encode(jsUndefined()); }
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*) { return JSValue::encode(jsUndefined()); }
</span><ins>+EncodedJSValue JSC_HOST_CALL functionIsInt32(ExecState* exec)
+{
+    for (size_t i = 0; i &lt; exec-&gt;argumentCount(); ++i) {
+        if (!exec-&gt;argument(i).isInt32())
+            return JSValue::encode(jsBoolean(false));
+    }
+    return JSValue::encode(jsBoolean(true));
+}
</ins><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState* exec) { return JSValue::encode(exec-&gt;argument(0)); }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntrinsich"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Intrinsic.h (184259 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Intrinsic.h        2015-05-13 05:18:01 UTC (rev 184259)
+++ trunk/Source/JavaScriptCore/runtime/Intrinsic.h        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -60,6 +60,7 @@
</span><span class="cx">     OSRExitIntrinsic,
</span><span class="cx">     IsFinalTierIntrinsic,
</span><span class="cx">     SetInt32HeapPredictionIntrinsic,
</span><ins>+    CheckInt32Intrinsic,
</ins><span class="cx">     FiatInt52Intrinsic,
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkargumentspastinvalidcheckdfgjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-dfg.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-dfg.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-dfg.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+var globalResult;
+Object.prototype.valueOf = function() { globalResult = 1; }
+
+function foo() {
+    globalResult = 0;
+    +arguments;
+    return globalResult;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo();
+    if (result !== 1)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkargumentspastinvalidcheckint32dfgjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-int32-dfg.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-int32-dfg.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-int32-dfg.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+function foo() {
+    return isInt32(arguments);
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo();
+    if (result !== false)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkargumentspastinvalidcheckint32js"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-int32.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-int32.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-int32.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+function foo(p) {
+    var result = 42;
+    var o = arguments;
+    if (p)
+        result = isInt32(o);
+    return result;
+}
+
+noInline(foo);
+
+var result = foo(true);
+if (result !== false)
+    throw &quot;Error: bad result at beginning: &quot; + result;
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(false);
+    if (result !== 42)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var result = foo(true);
+if (result !== false)
+    throw &quot;Error: bad result at end: &quot; + result;
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkargumentspastinvalidchecksneakierjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-sneakier.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-sneakier.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check-sneakier.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+function bar(o, p) {
+    var o2 = {f: 0};
+    if (p)
+        o2.f = o;
+    return +o2.f;
+}
+
+var globalResult;
+Object.prototype.valueOf = function() { globalResult = 1; };
+
+function foo(p, q) {
+    globalResult = 0;
+    var o = arguments;
+    if (p)
+        bar(o, q);
+    return globalResult;
+}
+
+noInline(foo);
+
+foo(true, false);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    bar(1, true);
+    bar({}, false);
+}
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(false, true);
+    if (result !== 0)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var result = foo(true, true);
+if (result !== 1)
+    throw &quot;Error: bad result at end: &quot; + result;
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkargumentspastinvalidcheckjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-arguments-past-invalid-check.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+var globalResult;
+Object.prototype.valueOf = function() { globalResult = 1; }
+
+function foo(p) {
+    globalResult = 0;
+    var o = arguments;
+    if (p)
+        +o;
+    return globalResult;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(false);
+    if (result !== 0)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var result = foo(true);
+if (result !== 1)
+    throw &quot;Error: bad result at end: &quot; + result;
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkfunctionpastinvalidchecksneakierjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-function-past-invalid-check-sneakier.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-function-past-invalid-check-sneakier.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-function-past-invalid-check-sneakier.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+function bar(o, p) {
+    if (p)
+        return +o.f;
+    return 42;
+}
+
+var globalResult;
+Function.prototype.valueOf = function() { globalResult = 1; };
+
+function foo(p, q) {
+    globalResult = 0;
+    var o = function() { };
+    var o2 = {f: o};
+    if (p)
+        bar(o2, q);
+    return globalResult;
+}
+
+noInline(foo);
+
+foo(true, false);
+
+for (var i = 0; i &lt; 10000; ++i)
+    bar({f:42}, true);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(false, true);
+    if (result !== 0)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var result = foo(true, true);
+if (result !== 1)
+    throw &quot;Error: bad result at end: &quot; + result;
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkfunctionpastinvalidchecksneakyjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-function-past-invalid-check-sneaky.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-function-past-invalid-check-sneaky.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-function-past-invalid-check-sneaky.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+function foo(p) {
+    var o = function() { };
+    var q = {f: p ? o : 42};
+    var tmp = q.f + 1;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i)
+    foo(false);
+
+foo(true);
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkobjectpastinvalidcheckint32js"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-int32.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-int32.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-int32.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+function foo(p) {
+    var result = 42;
+    var o = {};
+    if (p)
+        result = isInt32(o);
+    return result;
+}
+
+noInline(foo);
+
+var result = foo(true);
+if (result !== false)
+    throw &quot;Error: bad result at end: &quot; + result;
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(false);
+    if (result !== 42)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var result = foo(true);
+if (result !== false)
+    throw &quot;Error: bad result at end: &quot; + result;
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkobjectpastinvalidchecksneakierjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-sneakier.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-sneakier.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-sneakier.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+function bar(o, p) {
+    if (p)
+        return +o.f;
+    return 42;
+}
+
+function foo(p, q) {
+    var result = 0;
+    var o = {valueOf: function() { result = 1; }};
+    var o2 = {f: o};
+    if (p)
+        bar(o2, q);
+    return result;
+}
+
+noInline(foo);
+
+foo(true, false);
+
+for (var i = 0; i &lt; 10000; ++i)
+    bar({f:42}, true);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(false, true);
+    if (result !== 0)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var result = foo(true, true);
+if (result !== 1)
+    throw &quot;Error: bad result at end: &quot; + result;
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkobjectpastinvalidchecksneakyjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-sneaky.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-sneaky.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check-sneaky.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+// https://bugs.webkit.org/show_bug.cgi?id=144945
+//@ skip
+
+function foo(p) {
+    var result = 0;
+    var o = {valueOf: function() { result = 1; }};
+    var q = {f: p ? o : 42};
+    var tmp = q.f + 1;
+    return result;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(false);
+    if (result !== 0)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var result = foo(true);
+if (result !== 1)
+    throw &quot;Error: bad result at end: &quot; + result;
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssinkobjectpastinvalidcheckjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check.js (0 => 184260)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/sink-object-past-invalid-check.js        2015-05-13 05:21:16 UTC (rev 184260)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+function foo(p) {
+    var result = 0;
+    var o = {valueOf:function() { result = 1; }};
+    if (p)
+        +o;
+    return result;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(false);
+    if (result !== 0)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var result = foo(true);
+if (result !== 1)
+    throw &quot;Error: bad result at end: &quot; + result;
+
</ins></span></pre>
</div>
</div>

</body>
</html>