<!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>[166095] 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/166095">166095</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-03-21 13:23:55 -0700 (Fri, 21 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Constants folded by DFG::ByteCodeParser should not be dead.
https://bugs.webkit.org/show_bug.cgi?id=130576

Reviewed by Mark Hahnenberg.
        
This fixes bugs in the ByteCodeParser's constant folder by removing that constant folder. This
reduces the number of folders in JSC from fourish to just threeish (parser, DFG AI, and one
or more folders in LLVM). Doing so has no performance impact since the other constant folders
already subsume this one.
        
Also added a test case for the specific bug that instigated this.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::getJSConstantForValue):
(JSC::DFG::ByteCodeParser::getJSConstant):
(JSC::DFG::ByteCodeParser::inferredConstant):
(JSC::DFG::ByteCodeParser::handleIntrinsic):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGNode.h:
* dfg/DFGNodeFlags.h:
* tests/stress/constand-folding-osr-exit.js: Added.
(foo):
(test):
(.var):</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="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeFlagsh">trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressconstandfoldingosrexitjs">trunk/Source/JavaScriptCore/tests/stress/constand-folding-osr-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 (166094 => 166095)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-03-21 19:56:27 UTC (rev 166094)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-03-21 20:23:55 UTC (rev 166095)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2014-03-21  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Constants folded by DFG::ByteCodeParser should not be dead.
+        https://bugs.webkit.org/show_bug.cgi?id=130576
+
+        Reviewed by Mark Hahnenberg.
+        
+        This fixes bugs in the ByteCodeParser's constant folder by removing that constant folder. This
+        reduces the number of folders in JSC from fourish to just threeish (parser, DFG AI, and one
+        or more folders in LLVM). Doing so has no performance impact since the other constant folders
+        already subsume this one.
+        
+        Also added a test case for the specific bug that instigated this.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::getJSConstantForValue):
+        (JSC::DFG::ByteCodeParser::getJSConstant):
+        (JSC::DFG::ByteCodeParser::inferredConstant):
+        (JSC::DFG::ByteCodeParser::handleIntrinsic):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGNode.h:
+        * dfg/DFGNodeFlags.h:
+        * tests/stress/constand-folding-osr-exit.js: Added.
+        (foo):
+        (test):
+        (.var):
+
</ins><span class="cx"> 2014-03-21  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         StackLayoutPhase should find the union'ed calleeVariable before accessing its machineLocal.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (166094 => 166095)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-03-21 19:56:27 UTC (rev 166094)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-03-21 20:23:55 UTC (rev 166095)
</span><span class="lines">@@ -530,7 +530,7 @@
</span><span class="cx">     // constant folding. I.e. creating constants using this if we had constant
</span><span class="cx">     // field inference would be a bad idea, since the bytecode parser's folding
</span><span class="cx">     // doesn't handle liveness preservation.
</span><del>-    Node* getJSConstantForValue(JSValue constantValue, NodeFlags flags = NodeIsStaticConstant)
</del><ins>+    Node* getJSConstantForValue(JSValue constantValue)
</ins><span class="cx">     {
</span><span class="cx">         unsigned constantIndex;
</span><span class="cx">         if (!m_codeBlock-&gt;findConstant(constantValue, constantIndex)) {
</span><span class="lines">@@ -540,17 +540,16 @@
</span><span class="cx">         
</span><span class="cx">         ASSERT(m_constants.size() == m_codeBlock-&gt;numberOfConstantRegisters());
</span><span class="cx">         
</span><del>-        return getJSConstant(constantIndex, flags);
</del><ins>+        return getJSConstant(constantIndex);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Node* getJSConstant(unsigned constant, NodeFlags flags = NodeIsStaticConstant)
</del><ins>+    Node* getJSConstant(unsigned constant)
</ins><span class="cx">     {
</span><span class="cx">         Node* node = m_constants[constant].asJSValue;
</span><span class="cx">         if (node)
</span><span class="cx">             return node;
</span><span class="cx"> 
</span><span class="cx">         Node* result = addToGraph(JSConstant, OpInfo(constant));
</span><del>-        result-&gt;mergeFlags(flags);
</del><span class="cx">         m_constants[constant].asJSValue = result;
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="lines">@@ -704,7 +703,7 @@
</span><span class="cx">     {
</span><span class="cx">         if (value.isCell())
</span><span class="cx">             return cellConstant(value.asCell());
</span><del>-        return getJSConstantForValue(value, 0);
</del><ins>+        return getJSConstantForValue(value);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     InlineCallFrame* inlineCallFrame()
</span><span class="lines">@@ -717,20 +716,6 @@
</span><span class="cx">         return CodeOrigin(m_currentIndex, inlineCallFrame());
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool canFold(Node* node)
-    {
-        if (Options::validateFTLOSRExitLiveness()) {
-            // The static folding that the bytecode parser does results in the DFG
-            // being able to do some DCE that the bytecode liveness analysis would
-            // miss. Hence, we disable the static folding if we're validating FTL OSR
-            // exit liveness. This may be brutish, but this validator is powerful
-            // enough that it's worth it.
-            return false;
-        }
-        
-        return node-&gt;isStronglyProvedConstantIn(inlineCallFrame());
-    }
-
</del><span class="cx">     BranchData* branchData(unsigned taken, unsigned notTaken)
</span><span class="cx">     {
</span><span class="cx">         // We assume that branches originating from bytecode always have a fall-through. We
</span><span class="lines">@@ -1697,7 +1682,7 @@
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     case DFGTrue: {
</span><del>-        set(VirtualRegister(resultOperand), getJSConstantForValue(jsBoolean(true), 0));
</del><ins>+        set(VirtualRegister(resultOperand), getJSConstantForValue(jsBoolean(true)));
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -2523,15 +2508,6 @@
</span><span class="cx">         case op_less: {
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue a = valueOfJSConstant(op1);
-                JSValue b = valueOfJSConstant(op2);
-                if (a.isNumber() &amp;&amp; b.isNumber()) {
-                    set(VirtualRegister(currentInstruction[1].u.operand),
-                        getJSConstantForValue(jsBoolean(a.asNumber() &lt; b.asNumber())));
-                    NEXT_OPCODE(op_less);
-                }
-            }
</del><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareLess, op1, op2));
</span><span class="cx">             NEXT_OPCODE(op_less);
</span><span class="cx">         }
</span><span class="lines">@@ -2539,15 +2515,6 @@
</span><span class="cx">         case op_lesseq: {
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue a = valueOfJSConstant(op1);
-                JSValue b = valueOfJSConstant(op2);
-                if (a.isNumber() &amp;&amp; b.isNumber()) {
-                    set(VirtualRegister(currentInstruction[1].u.operand),
-                        getJSConstantForValue(jsBoolean(a.asNumber() &lt;= b.asNumber())));
-                    NEXT_OPCODE(op_lesseq);
-                }
-            }
</del><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareLessEq, op1, op2));
</span><span class="cx">             NEXT_OPCODE(op_lesseq);
</span><span class="cx">         }
</span><span class="lines">@@ -2555,15 +2522,6 @@
</span><span class="cx">         case op_greater: {
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue a = valueOfJSConstant(op1);
-                JSValue b = valueOfJSConstant(op2);
-                if (a.isNumber() &amp;&amp; b.isNumber()) {
-                    set(VirtualRegister(currentInstruction[1].u.operand),
-                        getJSConstantForValue(jsBoolean(a.asNumber() &gt; b.asNumber())));
-                    NEXT_OPCODE(op_greater);
-                }
-            }
</del><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareGreater, op1, op2));
</span><span class="cx">             NEXT_OPCODE(op_greater);
</span><span class="cx">         }
</span><span class="lines">@@ -2571,15 +2529,6 @@
</span><span class="cx">         case op_greatereq: {
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue a = valueOfJSConstant(op1);
-                JSValue b = valueOfJSConstant(op2);
-                if (a.isNumber() &amp;&amp; b.isNumber()) {
-                    set(VirtualRegister(currentInstruction[1].u.operand),
-                        getJSConstantForValue(jsBoolean(a.asNumber() &gt;= b.asNumber())));
-                    NEXT_OPCODE(op_greatereq);
-                }
-            }
</del><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareGreaterEq, op1, op2));
</span><span class="cx">             NEXT_OPCODE(op_greatereq);
</span><span class="cx">         }
</span><span class="lines">@@ -2587,13 +2536,6 @@
</span><span class="cx">         case op_eq: {
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue a = valueOfJSConstant(op1);
-                JSValue b = valueOfJSConstant(op2);
-                set(VirtualRegister(currentInstruction[1].u.operand),
-                    getJSConstantForValue(jsBoolean(JSValue::equal(m_codeBlock-&gt;globalObject()-&gt;globalExec(), a, b))));
-                NEXT_OPCODE(op_eq);
-            }
</del><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareEq, op1, op2));
</span><span class="cx">             NEXT_OPCODE(op_eq);
</span><span class="cx">         }
</span><span class="lines">@@ -2607,13 +2549,6 @@
</span><span class="cx">         case op_stricteq: {
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue a = valueOfJSConstant(op1);
-                JSValue b = valueOfJSConstant(op2);
-                set(VirtualRegister(currentInstruction[1].u.operand),
-                    getJSConstantForValue(jsBoolean(JSValue::strictEqual(m_codeBlock-&gt;globalObject()-&gt;globalExec(), a, b))));
-                NEXT_OPCODE(op_stricteq);
-            }
</del><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareStrictEq, op1, op2));
</span><span class="cx">             NEXT_OPCODE(op_stricteq);
</span><span class="cx">         }
</span><span class="lines">@@ -2621,13 +2556,6 @@
</span><span class="cx">         case op_neq: {
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue a = valueOfJSConstant(op1);
-                JSValue b = valueOfJSConstant(op2);
-                set(VirtualRegister(currentInstruction[1].u.operand),
-                    getJSConstantForValue(jsBoolean(!JSValue::equal(m_codeBlock-&gt;globalObject()-&gt;globalExec(), a, b))));
-                NEXT_OPCODE(op_neq);
-            }
</del><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, addToGraph(CompareEq, op1, op2)));
</span><span class="cx">             NEXT_OPCODE(op_neq);
</span><span class="cx">         }
</span><span class="lines">@@ -2641,13 +2569,6 @@
</span><span class="cx">         case op_nstricteq: {
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue a = valueOfJSConstant(op1);
-                JSValue b = valueOfJSConstant(op2);
-                set(VirtualRegister(currentInstruction[1].u.operand),
-                    getJSConstantForValue(jsBoolean(!JSValue::strictEqual(m_codeBlock-&gt;globalObject()-&gt;globalExec(), a, b))));
-                NEXT_OPCODE(op_nstricteq);
-            }
</del><span class="cx">             Node* invertedResult;
</span><span class="cx">             invertedResult = addToGraph(CompareStrictEq, op1, op2);
</span><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, invertedResult));
</span><span class="lines">@@ -2752,18 +2673,6 @@
</span><span class="cx">         case op_jtrue: {
</span><span class="cx">             unsigned relativeOffset = currentInstruction[2].u.operand;
</span><span class="cx">             Node* condition = get(VirtualRegister(currentInstruction[1].u.operand));
</span><del>-            if (canFold(condition)) {
-                TriState state = valueOfJSConstant(condition).pureToBoolean();
-                if (state == TrueTriState) {
-                    addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
-                    LAST_OPCODE(op_jtrue);
-                } else if (state == FalseTriState) {
-                    // Emit a placeholder for this bytecode operation but otherwise
-                    // just fall through.
-                    addToGraph(Phantom);
-                    NEXT_OPCODE(op_jtrue);
-                }
-            }
</del><span class="cx">             addToGraph(Branch, OpInfo(branchData(m_currentIndex + relativeOffset, m_currentIndex + OPCODE_LENGTH(op_jtrue))), condition);
</span><span class="cx">             LAST_OPCODE(op_jtrue);
</span><span class="cx">         }
</span><span class="lines">@@ -2771,18 +2680,6 @@
</span><span class="cx">         case op_jfalse: {
</span><span class="cx">             unsigned relativeOffset = currentInstruction[2].u.operand;
</span><span class="cx">             Node* condition = get(VirtualRegister(currentInstruction[1].u.operand));
</span><del>-            if (canFold(condition)) {
-                TriState state = valueOfJSConstant(condition).pureToBoolean();
-                if (state == FalseTriState) {
-                    addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
-                    LAST_OPCODE(op_jfalse);
-                } else if (state == TrueTriState) {
-                    // Emit a placeholder for this bytecode operation but otherwise
-                    // just fall through.
-                    addToGraph(Phantom);
-                    NEXT_OPCODE(op_jfalse);
-                }
-            }
</del><span class="cx">             addToGraph(Branch, OpInfo(branchData(m_currentIndex + OPCODE_LENGTH(op_jfalse), m_currentIndex + relativeOffset)), condition);
</span><span class="cx">             LAST_OPCODE(op_jfalse);
</span><span class="cx">         }
</span><span class="lines">@@ -2807,23 +2704,6 @@
</span><span class="cx">             unsigned relativeOffset = currentInstruction[3].u.operand;
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue aValue = valueOfJSConstant(op1);
-                JSValue bValue = valueOfJSConstant(op2);
-                if (aValue.isNumber() &amp;&amp; bValue.isNumber()) {
-                    double a = aValue.asNumber();
-                    double b = bValue.asNumber();
-                    if (a &lt; b) {
-                        addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
-                        LAST_OPCODE(op_jless);
-                    } else {
-                        // Emit a placeholder for this bytecode operation but otherwise
-                        // just fall through.
-                        addToGraph(Phantom);
-                        NEXT_OPCODE(op_jless);
-                    }
-                }
-            }
</del><span class="cx">             Node* condition = addToGraph(CompareLess, op1, op2);
</span><span class="cx">             addToGraph(Branch, OpInfo(branchData(m_currentIndex + relativeOffset, m_currentIndex + OPCODE_LENGTH(op_jless))), condition);
</span><span class="cx">             LAST_OPCODE(op_jless);
</span><span class="lines">@@ -2833,23 +2713,6 @@
</span><span class="cx">             unsigned relativeOffset = currentInstruction[3].u.operand;
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue aValue = valueOfJSConstant(op1);
-                JSValue bValue = valueOfJSConstant(op2);
-                if (aValue.isNumber() &amp;&amp; bValue.isNumber()) {
-                    double a = aValue.asNumber();
-                    double b = bValue.asNumber();
-                    if (a &lt;= b) {
-                        addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
-                        LAST_OPCODE(op_jlesseq);
-                    } else {
-                        // Emit a placeholder for this bytecode operation but otherwise
-                        // just fall through.
-                        addToGraph(Phantom);
-                        NEXT_OPCODE(op_jlesseq);
-                    }
-                }
-            }
</del><span class="cx">             Node* condition = addToGraph(CompareLessEq, op1, op2);
</span><span class="cx">             addToGraph(Branch, OpInfo(branchData(m_currentIndex + relativeOffset, m_currentIndex + OPCODE_LENGTH(op_jlesseq))), condition);
</span><span class="cx">             LAST_OPCODE(op_jlesseq);
</span><span class="lines">@@ -2859,23 +2722,6 @@
</span><span class="cx">             unsigned relativeOffset = currentInstruction[3].u.operand;
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue aValue = valueOfJSConstant(op1);
-                JSValue bValue = valueOfJSConstant(op2);
-                if (aValue.isNumber() &amp;&amp; bValue.isNumber()) {
-                    double a = aValue.asNumber();
-                    double b = bValue.asNumber();
-                    if (a &gt; b) {
-                        addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
-                        LAST_OPCODE(op_jgreater);
-                    } else {
-                        // Emit a placeholder for this bytecode operation but otherwise
-                        // just fall through.
-                        addToGraph(Phantom);
-                        NEXT_OPCODE(op_jgreater);
-                    }
-                }
-            }
</del><span class="cx">             Node* condition = addToGraph(CompareGreater, op1, op2);
</span><span class="cx">             addToGraph(Branch, OpInfo(branchData(m_currentIndex + relativeOffset, m_currentIndex + OPCODE_LENGTH(op_jgreater))), condition);
</span><span class="cx">             LAST_OPCODE(op_jgreater);
</span><span class="lines">@@ -2885,23 +2731,6 @@
</span><span class="cx">             unsigned relativeOffset = currentInstruction[3].u.operand;
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue aValue = valueOfJSConstant(op1);
-                JSValue bValue = valueOfJSConstant(op2);
-                if (aValue.isNumber() &amp;&amp; bValue.isNumber()) {
-                    double a = aValue.asNumber();
-                    double b = bValue.asNumber();
-                    if (a &gt;= b) {
-                        addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
-                        LAST_OPCODE(op_jgreatereq);
-                    } else {
-                        // Emit a placeholder for this bytecode operation but otherwise
-                        // just fall through.
-                        addToGraph(Phantom);
-                        NEXT_OPCODE(op_jgreatereq);
-                    }
-                }
-            }
</del><span class="cx">             Node* condition = addToGraph(CompareGreaterEq, op1, op2);
</span><span class="cx">             addToGraph(Branch, OpInfo(branchData(m_currentIndex + relativeOffset, m_currentIndex + OPCODE_LENGTH(op_jgreatereq))), condition);
</span><span class="cx">             LAST_OPCODE(op_jgreatereq);
</span><span class="lines">@@ -2911,23 +2740,6 @@
</span><span class="cx">             unsigned relativeOffset = currentInstruction[3].u.operand;
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue aValue = valueOfJSConstant(op1);
-                JSValue bValue = valueOfJSConstant(op2);
-                if (aValue.isNumber() &amp;&amp; bValue.isNumber()) {
-                    double a = aValue.asNumber();
-                    double b = bValue.asNumber();
-                    if (a &lt; b) {
-                        // Emit a placeholder for this bytecode operation but otherwise
-                        // just fall through.
-                        addToGraph(Phantom);
-                        NEXT_OPCODE(op_jnless);
-                    } else {
-                        addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
-                        LAST_OPCODE(op_jnless);
-                    }
-                }
-            }
</del><span class="cx">             Node* condition = addToGraph(CompareLess, op1, op2);
</span><span class="cx">             addToGraph(Branch, OpInfo(branchData(m_currentIndex + OPCODE_LENGTH(op_jnless), m_currentIndex + relativeOffset)), condition);
</span><span class="cx">             LAST_OPCODE(op_jnless);
</span><span class="lines">@@ -2937,23 +2749,6 @@
</span><span class="cx">             unsigned relativeOffset = currentInstruction[3].u.operand;
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue aValue = valueOfJSConstant(op1);
-                JSValue bValue = valueOfJSConstant(op2);
-                if (aValue.isNumber() &amp;&amp; bValue.isNumber()) {
-                    double a = aValue.asNumber();
-                    double b = bValue.asNumber();
-                    if (a &lt;= b) {
-                        // Emit a placeholder for this bytecode operation but otherwise
-                        // just fall through.
-                        addToGraph(Phantom);
-                        NEXT_OPCODE(op_jnlesseq);
-                    } else {
-                        addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
-                        LAST_OPCODE(op_jnlesseq);
-                    }
-                }
-            }
</del><span class="cx">             Node* condition = addToGraph(CompareLessEq, op1, op2);
</span><span class="cx">             addToGraph(Branch, OpInfo(branchData(m_currentIndex + OPCODE_LENGTH(op_jnlesseq), m_currentIndex + relativeOffset)), condition);
</span><span class="cx">             LAST_OPCODE(op_jnlesseq);
</span><span class="lines">@@ -2963,23 +2758,6 @@
</span><span class="cx">             unsigned relativeOffset = currentInstruction[3].u.operand;
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue aValue = valueOfJSConstant(op1);
-                JSValue bValue = valueOfJSConstant(op2);
-                if (aValue.isNumber() &amp;&amp; bValue.isNumber()) {
-                    double a = aValue.asNumber();
-                    double b = bValue.asNumber();
-                    if (a &gt; b) {
-                        // Emit a placeholder for this bytecode operation but otherwise
-                        // just fall through.
-                        addToGraph(Phantom);
-                        NEXT_OPCODE(op_jngreater);
-                    } else {
-                        addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
-                        LAST_OPCODE(op_jngreater);
-                    }
-                }
-            }
</del><span class="cx">             Node* condition = addToGraph(CompareGreater, op1, op2);
</span><span class="cx">             addToGraph(Branch, OpInfo(branchData(m_currentIndex + OPCODE_LENGTH(op_jngreater), m_currentIndex + relativeOffset)), condition);
</span><span class="cx">             LAST_OPCODE(op_jngreater);
</span><span class="lines">@@ -2989,23 +2767,6 @@
</span><span class="cx">             unsigned relativeOffset = currentInstruction[3].u.operand;
</span><span class="cx">             Node* op1 = get(VirtualRegister(currentInstruction[1].u.operand));
</span><span class="cx">             Node* op2 = get(VirtualRegister(currentInstruction[2].u.operand));
</span><del>-            if (canFold(op1) &amp;&amp; canFold(op2)) {
-                JSValue aValue = valueOfJSConstant(op1);
-                JSValue bValue = valueOfJSConstant(op2);
-                if (aValue.isNumber() &amp;&amp; bValue.isNumber()) {
-                    double a = aValue.asNumber();
-                    double b = bValue.asNumber();
-                    if (a &gt;= b) {
-                        // Emit a placeholder for this bytecode operation but otherwise
-                        // just fall through.
-                        addToGraph(Phantom);
-                        NEXT_OPCODE(op_jngreatereq);
-                    } else {
-                        addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
-                        LAST_OPCODE(op_jngreatereq);
-                    }
-                }
-            }
</del><span class="cx">             Node* condition = addToGraph(CompareGreaterEq, op1, op2);
</span><span class="cx">             addToGraph(Branch, OpInfo(branchData(m_currentIndex + OPCODE_LENGTH(op_jngreatereq), m_currentIndex + relativeOffset)), condition);
</span><span class="cx">             LAST_OPCODE(op_jngreatereq);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (166094 => 166095)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-03-21 19:56:27 UTC (rev 166094)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-03-21 20:23:55 UTC (rev 166095)
</span><span class="lines">@@ -376,17 +376,6 @@
</span><span class="cx">         return op() == WeakJSConstant;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool isStronglyProvedConstantIn(InlineCallFrame* inlineCallFrame)
-    {
-        return !!(flags() &amp; NodeIsStaticConstant)
-            &amp;&amp; origin.semantic.inlineCallFrame == inlineCallFrame;
-    }
-    
-    bool isStronglyProvedConstantIn(const CodeOrigin&amp; codeOrigin)
-    {
-        return isStronglyProvedConstantIn(codeOrigin.inlineCallFrame);
-    }
-    
</del><span class="cx">     bool isPhantomArguments()
</span><span class="cx">     {
</span><span class="cx">         return op() == PhantomArguments;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeFlagsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h (166094 => 166095)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h        2014-03-21 19:56:27 UTC (rev 166094)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h        2014-03-21 20:23:55 UTC (rev 166095)
</span><span class="lines">@@ -66,8 +66,7 @@
</span><span class="cx"> 
</span><span class="cx"> #define NodeRelevantToOSR                0x4000
</span><span class="cx"> 
</span><del>-#define NodeIsStaticConstant             0x8000 // Used only by the parser, to determine if a constant arose statically and hence could be folded at parse-time.
-#define NodeIsFlushed                   0x10000 // Used by Graph::computeIsFlushed(), will tell you which local nodes are backwards-reachable from a Flush.
</del><ins>+#define NodeIsFlushed                    0x8000 // Used by Graph::computeIsFlushed(), will tell you which local nodes are backwards-reachable from a Flush.
</ins><span class="cx"> 
</span><span class="cx"> typedef uint32_t NodeFlags;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressconstandfoldingosrexitjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/constand-folding-osr-exit.js (0 => 166095)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/constand-folding-osr-exit.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/constand-folding-osr-exit.js        2014-03-21 20:23:55 UTC (rev 166095)
</span><span class="lines">@@ -0,0 +1,132 @@
</span><ins>+var foo = [
+    function(o) {
+        var x = true;
+        o.f.f;
+        if (x)
+            return;
+        throw new Error();
+    },
+    function(o) {
+        var x = true;
+        o.f.f;
+        if (!x)
+            throw new Error();
+        return;
+    },
+    function(o) {
+        var x = 0;
+        var y = 1;
+        o.f.f;
+        if (x &lt; y)
+            return;
+        throw new Error();
+    },
+    function(o) {
+        var x = 1;
+        var y = 0;
+        o.f.f;
+        if (x &gt; y)
+            return;
+        throw new Error();
+    },
+    function(o) {
+        var x = 0;
+        var y = 1;
+        o.f.f;
+        if (x &lt;= y)
+            return;
+        throw new Error();
+    },
+    function(o) {
+        var x = 1;
+        var y = 0;
+        o.f.f;
+        if (x &gt;= y)
+            return;
+        throw new Error();
+    },
+    function(o) {
+        var x = 0;
+        var y = 1;
+        o.f.f;
+        if (x &gt;= y)
+            throw new Error();
+        return;
+    },
+    function(o) {
+        var x = 1;
+        var y = 0;
+        o.f.f;
+        if (x &lt;= y)
+            throw new Error();
+        return;
+    },
+    function(o) {
+        var x = 0;
+        var y = 1;
+        o.f.f;
+        if (x &gt; y)
+            throw new Error();
+        return;
+    },
+    function(o) {
+        var x = 1;
+        var y = 0;
+        o.f.f;
+        if (x &lt; y)
+            throw new Error();
+        return;
+    },
+    function(o) {
+        var x = 42;
+        o.f.f;
+        if (x == 42)
+            return;
+        throw new Error();
+    },
+    function(o) {
+        var x = 42;
+        o.f.f;
+        if (x != 42)
+            throw new Error();
+        return;
+    },
+    function(o) {
+        var x = 42;
+        o.f.f;
+        if (x === 42)
+            return;
+        throw new Error();
+    },
+    function(o) {
+        var x = 42;
+        o.f.f;
+        if (x !== 42)
+            throw new Error();
+        return;
+    },
+];
+for (var i = 0; i &lt; foo.length; ++i)
+    noInline(foo[i]);
+
+function test(o) {
+    var failed = [];
+    for (var i = 0; i &lt; foo.length; ++i) {
+        try {
+            foo[i](o);
+        } catch (e) {
+            failed.push(&quot;Failed &quot; + foo[i] + &quot; with &quot; + e);
+        }
+    }
+    if (failed.length)
+        throw failed;
+}
+
+var object = {f:{f:42}};
+
+for (var i = 0; i &lt; 10000; ++i) {
+    test(object);
+}
+
+test({f:{g:43}});
+
</ins></span></pre>
</div>
</div>

</body>
</html>