<!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>[167612] 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/167612">167612</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-04-21 12:51:54 -0700 (Mon, 21 Apr 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>OSR exit should know about Int52 and Double constants
https://bugs.webkit.org/show_bug.cgi?id=131945

Reviewed by Oliver Hunt.
        
The DFG OSR exit machinery's ignorance would lead to some constants becoming
jsUndefined() after OSR exit.
        
The FTL OSR exit machinery's ignorance just meant that we would sometimes use a
stackmap constant rather than baking the constant into the OSRExit data structure.
So, not a big deal, but worth fixing.
        
Also added some helpful hacks to jsc.cpp for testing such OSR exit pathologies.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsic):
* dfg/DFGMinifiedNode.h:
(JSC::DFG::belongsInMinifiedGraph):
(JSC::DFG::MinifiedNode::hasConstantNumber):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::tryToSetConstantExitArgument):
* jsc.cpp:
(GlobalObject::finishCreation):
(functionOtherFalse):
(functionUndefined):
* runtime/Intrinsic.h:
* tests/stress/fold-to-double-constant-then-exit.js: Added.
(foo):
* tests/stress/fold-to-int52-constant-then-exit.js: Added.
(foo):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMinifiedNodeh">trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.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="#trunkSourceJavaScriptCoretestsstressfoldtodoubleconstantthenexitjs">trunk/Source/JavaScriptCore/tests/stress/fold-to-double-constant-then-exit.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressfoldtoint52constantthenexitjs">trunk/Source/JavaScriptCore/tests/stress/fold-to-int52-constant-then-exit.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (167611 => 167612)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-04-21 19:51:01 UTC (rev 167611)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-04-21 19:51:54 UTC (rev 167612)
</span><span class="lines">@@ -1,5 +1,38 @@
</span><span class="cx"> 2014-04-21  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        OSR exit should know about Int52 and Double constants
+        https://bugs.webkit.org/show_bug.cgi?id=131945
+
+        Reviewed by Oliver Hunt.
+        
+        The DFG OSR exit machinery's ignorance would lead to some constants becoming
+        jsUndefined() after OSR exit.
+        
+        The FTL OSR exit machinery's ignorance just meant that we would sometimes use a
+        stackmap constant rather than baking the constant into the OSRExit data structure.
+        So, not a big deal, but worth fixing.
+        
+        Also added some helpful hacks to jsc.cpp for testing such OSR exit pathologies.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsic):
+        * dfg/DFGMinifiedNode.h:
+        (JSC::DFG::belongsInMinifiedGraph):
+        (JSC::DFG::MinifiedNode::hasConstantNumber):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::tryToSetConstantExitArgument):
+        * jsc.cpp:
+        (GlobalObject::finishCreation):
+        (functionOtherFalse):
+        (functionUndefined):
+        * runtime/Intrinsic.h:
+        * tests/stress/fold-to-double-constant-then-exit.js: Added.
+        (foo):
+        * tests/stress/fold-to-int52-constant-then-exit.js: Added.
+        (foo):
+
+2014-04-21  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         Provide feedback when we encounter an unrecognied node in the FTL backend.
</span><span class="cx"> 
</span><span class="cx">         Rubber stamped by Alexey Proskuryakov.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (167611 => 167612)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-04-21 19:51:01 UTC (rev 167611)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-04-21 19:51:54 UTC (rev 167612)
</span><span class="lines">@@ -1714,11 +1714,23 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case DFGTrue: {
</del><ins>+    case DFGTrueIntrinsic: {
</ins><span class="cx">         set(VirtualRegister(resultOperand), getJSConstantForValue(jsBoolean(true)));
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">         
</span><ins>+    case OSRExitIntrinsic: {
+        addToGraph(ForceOSRExit);
+        set(VirtualRegister(resultOperand), constantUndefined());
+        return true;
+    }
+        
+    case IsFinalTierIntrinsic: {
+        set(VirtualRegister(resultOperand),
+            getJSConstantForValue(jsBoolean(Options::useFTLJIT() ? isFTL(m_graph.m_plan.mode) : true)));
+        return true;
+    }
+        
</ins><span class="cx">     default:
</span><span class="cx">         return false;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMinifiedNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h (167611 => 167612)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h        2014-04-21 19:51:01 UTC (rev 167611)
+++ trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h        2014-04-21 19:51:54 UTC (rev 167612)
</span><span class="lines">@@ -40,6 +40,8 @@
</span><span class="cx"> {
</span><span class="cx">     switch (type) {
</span><span class="cx">     case JSConstant:
</span><ins>+    case Int52Constant:
+    case DoubleConstant:
</ins><span class="cx">     case WeakJSConstant:
</span><span class="cx">     case PhantomArguments:
</span><span class="cx">         return true;
</span><span class="lines">@@ -84,7 +86,7 @@
</span><span class="cx"> private:
</span><span class="cx">     static bool hasConstantNumber(NodeType type)
</span><span class="cx">     {
</span><del>-        return type == JSConstant;
</del><ins>+        return type == JSConstant || type == Int52Constant || type == DoubleConstant;
</ins><span class="cx">     }
</span><span class="cx">     static bool hasWeakConstant(NodeType type)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (167611 => 167612)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-04-21 19:51:01 UTC (rev 167611)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-04-21 19:51:54 UTC (rev 167612)
</span><span class="lines">@@ -5891,6 +5891,8 @@
</span><span class="cx">         
</span><span class="cx">         switch (node-&gt;op()) {
</span><span class="cx">         case JSConstant:
</span><ins>+        case Int52Constant:
+        case DoubleConstant:
</ins><span class="cx">         case WeakJSConstant:
</span><span class="cx">             exit.m_values[index] = ExitValue::constant(m_graph.valueOfJSConstant(node));
</span><span class="cx">             return true;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (167611 => 167612)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2014-04-21 19:51:01 UTC (rev 167611)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2014-04-21 19:51:54 UTC (rev 167612)
</span><span class="lines">@@ -270,6 +270,8 @@
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionTransferArrayBuffer(ExecState*);
</span><span class="cx"> static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*);
</span><ins>+static EncodedJSValue JSC_HOST_CALL functionOtherFalse(ExecState*); // Need a separate function to break hash-consing of native executables.
+static EncodedJSValue JSC_HOST_CALL functionUndefined(ExecState*);
</ins><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
</span><span class="cx"> 
</span><span class="lines">@@ -405,7 +407,9 @@
</span><span class="cx">         addFunction(vm, &quot;getElement&quot;, functionGetElement, 1);
</span><span class="cx">         addFunction(vm, &quot;setElementRoot&quot;, functionSetElementRoot, 2);
</span><span class="cx">         
</span><del>-        putDirectNativeFunction(vm, this, Identifier(&amp;vm, &quot;DFGTrue&quot;), 0, functionFalse, DFGTrue, DontEnum | JSC::Function);
</del><ins>+        putDirectNativeFunction(vm, this, Identifier(&amp;vm, &quot;DFGTrue&quot;), 0, functionFalse, DFGTrueIntrinsic, DontEnum | JSC::Function);
+        putDirectNativeFunction(vm, this, Identifier(&amp;vm, &quot;OSRExit&quot;), 0, functionUndefined, OSRExitIntrinsic, DontEnum | JSC::Function);
+        putDirectNativeFunction(vm, this, Identifier(&amp;vm, &quot;isFinalTier&quot;), 0, functionOtherFalse, IsFinalTierIntrinsic, DontEnum | JSC::Function);
</ins><span class="cx">         
</span><span class="cx">         addFunction(vm, &quot;effectful42&quot;, functionEffectful42, 0);
</span><span class="cx">         addFunction(vm, &quot;makeMasquerader&quot;, functionMakeMasquerader, 0);
</span><span class="lines">@@ -773,6 +777,16 @@
</span><span class="cx">     return JSValue::encode(jsBoolean(false));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JSC_HOST_CALL functionOtherFalse(ExecState*)
+{
+    return JSValue::encode(jsBoolean(false));
+}
+
+EncodedJSValue JSC_HOST_CALL functionUndefined(ExecState*)
+{
+    return JSValue::encode(jsUndefined());
+}
+
</ins><span class="cx"> EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
</span><span class="cx"> {
</span><span class="cx">     return JSValue::encode(jsNumber(42));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntrinsich"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Intrinsic.h (167611 => 167612)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Intrinsic.h        2014-04-21 19:51:01 UTC (rev 167611)
+++ trunk/Source/JavaScriptCore/runtime/Intrinsic.h        2014-04-21 19:51:54 UTC (rev 167612)
</span><span class="lines">@@ -57,7 +57,9 @@
</span><span class="cx">     ArrayIteratorNextGenericIntrinsic,
</span><span class="cx">     
</span><span class="cx">     // Debugging intrinsics
</span><del>-    DFGTrue
</del><ins>+    DFGTrueIntrinsic,
+    OSRExitIntrinsic,
+    IsFinalTierIntrinsic
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressfoldtodoubleconstantthenexitjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/fold-to-double-constant-then-exit.js (0 => 167612)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/fold-to-double-constant-then-exit.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/fold-to-double-constant-then-exit.js        2014-04-21 19:51:54 UTC (rev 167612)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+function foo(a, b) {
+    if (DFGTrue())
+        a = b = 5.4;
+    var c = a + b;
+    if (isFinalTier())
+        OSRExit();
+    return c + 0.5;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo(1.4, 1.3);
+    if (result != 1.4 + 1.3 + 0.5 &amp;&amp; result != 5.4 + 5.4 + 0.5)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressfoldtoint52constantthenexitjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/fold-to-int52-constant-then-exit.js (0 => 167612)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/fold-to-int52-constant-then-exit.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/fold-to-int52-constant-then-exit.js        2014-04-21 19:51:54 UTC (rev 167612)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+function foo(a, b) {
+    if (DFGTrue())
+        a = b = 2000000000;
+    var c = a + b;
+    if (isFinalTier())
+        OSRExit();
+    return c + 42;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo(2000000001, 2000000001);
+    if (result != 2000000001 + 2000000001 + 42 &amp;&amp; result != 2000000000 + 2000000000 + 42)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre>
</div>
</div>

</body>
</html>