DFG fixup phase should be responsible for inserting ValueToInt32's as needed and it should use Phantom to keep the original values alive in case of OSR exit
https://bugs.webkit.org/show_bug.cgi?id=126600

Reviewed by Michael Saboff.
        
This fixes an embarrassing OSR exit liveness bug. It also simplifies the code. We were
already using FixupPhase as the place where conversion nodes get inserted. ValueToInt32
was the only exception to that rule, and that was one of the reasons why we had this bug.
        
Henceforth ValueToInt32 is only inserted by FixupPhase, and only when it is necessary:
we have a BitOp that will want a ToInt32 conversion and the operand is not predicted to
already be an int32. If FixupPhase inserts any ValueToInt32's then the BitOp will no
longer appear to use the original operand, which will make OSR exit think that the
original operand is dead. We work around this they way we always do: insert a Phantom on
the original operands right after the BitOp. This ensures that any OSR exit in any of the
ValueToInt32's or in the BitOp itself will have values for the original inputs.

* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwo):
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsic):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixIntEdge):
(JSC::DFG::FixupPhase::fixBinaryIntEdges):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* tests/stress/bit-op-value-to-int32-input-liveness.js: Added.
(foo):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@161465 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 08e353e..b39b076 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -94,24 +94,18 @@
             return;
         }
             
-        case BitOr: {
-            fixIntEdge(node->child1());
-            fixIntEdge(node->child2());
-            break;
-        }
         case BitAnd:
+        case BitOr:
         case BitXor:
         case BitRShift:
         case BitLShift:
         case BitURShift: {
-            fixIntEdge(node->child1());
-            fixIntEdge(node->child2());
+            fixBinaryIntEdges();
             break;
         }
-            
+
         case ArithIMul: {
-            fixIntEdge(node->child1());
-            fixIntEdge(node->child2());
+            fixBinaryIntEdges();
             node->setOp(ArithMul);
             node->setArithMode(Arith::Unchecked);
             node->child1().setUseKind(Int32Use);
@@ -120,7 +114,7 @@
         }
             
         case UInt32ToNumber: {
-            fixEdge<KnownInt32Use>(node->child1());
+            fixIntEdge(node->child1());
             if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
                 node->convertToIdentity();
             else if (nodeCanSpeculateInt32(node->arithNodeFlags()))
@@ -130,42 +124,6 @@
             break;
         }
             
-        case DoubleAsInt32: {
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
-            
-        case ValueToInt32: {
-            if (node->child1()->shouldSpeculateInt32()) {
-                fixEdge<Int32Use>(node->child1());
-                node->setOpAndDefaultFlags(Identity);
-                break;
-            }
-            
-            if (node->child1()->shouldSpeculateMachineInt()) {
-                fixEdge<MachineIntUse>(node->child1());
-                break;
-            }
-            
-            if (node->child1()->shouldSpeculateNumber()) {
-                fixEdge<NumberUse>(node->child1());
-                break;
-            }
-            
-            if (node->child1()->shouldSpeculateBoolean()) {
-                fixEdge<BooleanUse>(node->child1());
-                break;
-            }
-            
-            fixEdge<NotCellUse>(node->child1());
-            break;
-        }
-            
-        case Int32ToDouble: {
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
-            
         case ValueAdd: {
             if (attemptToMakeIntegerAdd(node)) {
                 node->setOp(ArithAdd);
@@ -974,6 +932,9 @@
         case CheckArray:
         case CheckInBounds:
         case ConstantStoragePointer:
+        case DoubleAsInt32:
+        case Int32ToDouble:
+        case ValueToInt32:
             // These are just nodes that we don't currently expect to see during fixup.
             // If we ever wanted to insert them prior to fixup, then we just have to create
             // fixup rules for them.
@@ -1624,23 +1585,43 @@
         m_insertionSet.insert(indexInBlock, barrierNode);
     }
 
-    void fixIntEdge(Edge& edge)
+    bool fixIntEdge(Edge& edge)
     {
         Node* node = edge.node();
-        if (node->op() != ValueToInt32) {
-            fixEdge<KnownInt32Use>(edge);
-            return;
+        if (node->shouldSpeculateInt32()) {
+            fixEdge<Int32Use>(edge);
+            return false;
         }
         
-        Edge newEdge = node->child1();
+        UseKind useKind;
+        if (node->shouldSpeculateMachineInt())
+            useKind = MachineIntUse;
+        else if (node->shouldSpeculateNumber())
+            useKind = NumberUse;
+        else if (node->shouldSpeculateBoolean())
+            useKind = BooleanUse;
+        else
+            useKind = NotCellUse;
+        Node* newNode = m_insertionSet.insertNode(
+            m_indexInBlock, SpecInt32, ValueToInt32, m_currentNode->codeOrigin,
+            Edge(node, useKind));
+        observeUseKindOnNode(node, useKind);
         
-        if (newEdge.useKind() != Int32Use) {
-            edge.setUseKind(KnownInt32Use);
+        edge = Edge(newNode, KnownInt32Use);
+        return true;
+    }
+    
+    void fixBinaryIntEdges()
+    {
+        AdjacencyList children = m_currentNode->children;
+        
+        // Call fixIntEdge() on both edges.
+        bool needPhantom =
+            fixIntEdge(m_currentNode->child1()) | fixIntEdge(m_currentNode->child2());
+        
+        if (!needPhantom)
             return;
-        }
-        
-        ASSERT(newEdge->shouldSpeculateInt32());
-        edge = newEdge;
+        m_insertionSet.insertNode(m_indexInBlock + 1, SpecNone, Phantom, m_currentNode->codeOrigin, children);
     }
     
     void injectInt32ToDoubleNode(Edge& edge, UseKind useKind = NumberUse)