Strange bug in DFG OSR in JSC
https://bugs.webkit.org/show_bug.cgi?id=109491

Source/JavaScriptCore: 

Reviewed by Mark Hahnenberg.
        
Int32ToDouble was being injected after a side-effecting operation and before a SetLocal. Anytime we
inject something just before a SetLocal we should be aware that the previous operation may have been
a side-effect associated with the current code origin. Hence, we should use a forward exit.
Int32ToDouble does not do forward exits by default.
        
This patch adds a forward-exiting form of Int32ToDouble, for use in SetLocal Int32ToDouble injections.
Changed the CSE and other things to treat these nodes identically, but for the exit strategy to be
distinct (Int32ToDouble -> backward, ForwardInt32ToDouble -> forward). The use of the NodeType for
signaling exit direction is not "great" but it's what we use in other places already (like
ForwardCheckStructure).

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::int32ToDoubleCSE):
(CSEPhase):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGCommon.h:
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixDoubleEdge):
(JSC::DFG::FixupPhase::injectInt32ToDoubleNode):
* dfg/DFGNode.h:
(JSC::DFG::Node::willHaveCodeGenOrOSR):
* dfg/DFGNodeType.h:
(DFG):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::convertLastOSRExitToForward):
(JSC::DFG::SpeculativeJIT::compileInt32ToDouble):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::reconstruct):

LayoutTests: 

Reviewed by Mark Hahnenberg.
        
Added one version of the test (dfg-int32-to-double-on-set-local-and-exit) that is based
exactly on Gabor's original test, and another that ought to fail even if I fix other bugs
in the future (see https://bugs.webkit.org/show_bug.cgi?id=109511).

* fast/js/dfg-int32-to-double-on-set-local-and-exit-expected.txt: Added.
* fast/js/dfg-int32-to-double-on-set-local-and-exit.html: Added.
* fast/js/dfg-int32-to-double-on-set-local-and-sometimes-exit-expected.txt: Added.
* fast/js/dfg-int32-to-double-on-set-local-and-sometimes-exit.html: Added.
* fast/js/script-tests/dfg-int32-to-double-on-set-local-and-exit.js: Added.
(checkpoint):
(func1):
(func2):
(func3):
(test):
* fast/js/script-tests/dfg-int32-to-double-on-set-local-and-sometimes-exit.js: Added.
(checkpoint):
(func1):
(func2):
(func3):
(test):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@142544 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 0217665..1a93765 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -252,7 +252,7 @@
                 break;
             if (!node->variableAccessData()->shouldUseDoubleFormat())
                 break;
-            fixDoubleEdge(0);
+            fixDoubleEdge(0, ForwardSpeculation);
             break;
         }
             
@@ -508,7 +508,7 @@
         edge = newEdge;
     }
     
-    void fixDoubleEdge(unsigned childIndex)
+    void fixDoubleEdge(unsigned childIndex, SpeculationDirection direction = BackwardSpeculation)
     {
         Node* source = m_currentNode;
         Edge& edge = m_graph.child(source, childIndex);
@@ -518,13 +518,14 @@
             return;
         }
         
-        injectInt32ToDoubleNode(childIndex);
+        injectInt32ToDoubleNode(childIndex, direction);
     }
 
-    void injectInt32ToDoubleNode(unsigned childIndex)
+    void injectInt32ToDoubleNode(unsigned childIndex, SpeculationDirection direction = BackwardSpeculation)
     {
         Node* result = m_insertionSet.insertNode(
-            m_indexInBlock, DontRefChildren, RefNode, SpecDouble, Int32ToDouble,
+            m_indexInBlock, DontRefChildren, RefNode, SpecDouble,
+            direction == BackwardSpeculation ? Int32ToDouble : ForwardInt32ToDouble,
             m_currentNode->codeOrigin, m_graph.child(m_currentNode, childIndex).node());
         
 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)