Title: [115093] trunk/Source/_javascript_Core
Revision
115093
Author
[email protected]
Date
2012-04-24 12:19:35 -0700 (Tue, 24 Apr 2012)

Log Message

DFG on ARMv7 should not OSR exit on every integer division
https://bugs.webkit.org/show_bug.cgi?id=84661

Reviewed by Oliver Hunt.
        
On ARMv7, ArithDiv no longer has to know whether or not to speculate integer (since
that was broken with the introduction of Int32ToDouble) nor does it have to know
whether or not to convert its result to integer. This is now taken care of for free
with the addition of the DoubleAsInt32 node, which represents a double-is-really-int
speculation.

* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
(DFG):
* dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::OSRExit):
(JSC::DFG::OSRExit::considerAddingAsFrequentExitSiteSlow):
* dfg/DFGOSRExit.h:
(OSRExit):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
(JSC::DFG::SpeculativeJIT::compileDoubleAsInt32):
(DFG):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
(JSC::DFG::SpeculativeJIT::speculationCheck):
(JSC::DFG::SpeculativeJIT::forwardSpeculationCheck):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (115092 => 115093)


--- trunk/Source/_javascript_Core/ChangeLog	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-04-24 19:19:35 UTC (rev 115093)
@@ -1,3 +1,44 @@
+2012-04-23  Filip Pizlo  <[email protected]>
+
+        DFG on ARMv7 should not OSR exit on every integer division
+        https://bugs.webkit.org/show_bug.cgi?id=84661
+
+        Reviewed by Oliver Hunt.
+        
+        On ARMv7, ArithDiv no longer has to know whether or not to speculate integer (since
+        that was broken with the introduction of Int32ToDouble) nor does it have to know
+        whether or not to convert its result to integer. This is now taken care of for free
+        with the addition of the DoubleAsInt32 node, which represents a double-is-really-int
+        speculation.
+
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::execute):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNodeType.h:
+        (DFG):
+        * dfg/DFGOSRExit.cpp:
+        (JSC::DFG::OSRExit::OSRExit):
+        (JSC::DFG::OSRExit::considerAddingAsFrequentExitSiteSlow):
+        * dfg/DFGOSRExit.h:
+        (OSRExit):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
+        (JSC::DFG::SpeculativeJIT::compileDoubleAsInt32):
+        (DFG):
+        * dfg/DFGSpeculativeJIT.h:
+        (SpeculativeJIT):
+        (JSC::DFG::SpeculativeJIT::speculationCheck):
+        (JSC::DFG::SpeculativeJIT::forwardSpeculationCheck):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2012-04-24  Geoffrey Garen  <[email protected]>
 
         "GlobalHandle" HandleHeap (now WeakSet) allocations grow but do not shrink

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractState.cpp	2012-04-24 19:19:35 UTC (rev 115093)
@@ -290,6 +290,11 @@
             forNode(nodeIndex).set(PredictInt32);
         break;
             
+    case DoubleAsInt32:
+        forNode(node.child1()).filter(PredictNumber);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+            
     case ValueToInt32:
         if (m_graph[node.child1()].shouldSpeculateInteger())
             forNode(node.child1()).filter(PredictInt32);

Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2012-04-24 19:19:35 UTC (rev 115093)
@@ -594,6 +594,7 @@
         case IsString:
         case IsObject:
         case IsFunction:
+        case DoubleAsInt32:
             setReplacement(pureCSE(node));
             break;
             

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2012-04-24 19:19:35 UTC (rev 115093)
@@ -260,10 +260,28 @@
         }
             
         case ArithDiv: {
-            if (isX86()
-                && Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])
-                && node.canSpeculateInteger())
+            if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])
+                && node.canSpeculateInteger()) {
+                if (isX86())
+                    break;
+                fixDoubleEdge(0);
+                fixDoubleEdge(1);
+                
+                Node& oldDivision = m_graph[m_compileIndex];
+                
+                Node newDivision = oldDivision;
+                newDivision.setRefCount(2);
+                newDivision.predict(PredictDouble);
+                NodeIndex newDivisionIndex = m_graph.size();
+                
+                oldDivision.setOp(DoubleAsInt32);
+                oldDivision.children.initialize(Edge(newDivisionIndex, DoubleUse), Edge(), Edge());
+                
+                m_graph.append(newDivision);
+                m_insertionSet.append(m_indexInBlock, newDivisionIndex);
+                
                 break;
+            }
             fixDoubleEdge(0);
             fixDoubleEdge(1);
             break;

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2012-04-24 19:19:35 UTC (rev 115093)
@@ -78,6 +78,8 @@
     /* Used to cast known integers to doubles, so as to separate the double form */\
     /* of the value from the integer form. */\
     macro(Int32ToDouble, NodeResultNumber) \
+    /* Used to speculate that a double value is actually an integer. */\
+    macro(DoubleAsInt32, NodeResultInt32) \
     \
     /* Nodes for arithmetic operations. */\
     macro(ArithAdd, NodeResultNumber | NodeMustGenerate) \

Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp	2012-04-24 19:19:35 UTC (rev 115093)
@@ -49,6 +49,7 @@
     , m_check(check)
     , m_nodeIndex(jit->m_compileIndex)
     , m_codeOrigin(jit->m_codeOriginForOSR)
+    , m_codeOriginForExitProfile(m_codeOrigin)
     , m_recoveryIndex(recoveryIndex)
     , m_kind(kind)
     , m_count(0)
@@ -77,7 +78,7 @@
     if (static_cast<double>(m_count) / dfgCodeBlock->speculativeFailCounter() <= Options::osrExitProminenceForFrequentExitSite)
         return false;
     
-    return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOrigin, profiledCodeBlock)->addFrequentExitSite(FrequentExitSite(m_codeOrigin.bytecodeIndex, m_kind));
+    return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOriginForExitProfile, profiledCodeBlock)->addFrequentExitSite(FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind));
 }
 
 } } // namespace JSC::DFG

Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExit.h (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGOSRExit.h	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExit.h	2012-04-24 19:19:35 UTC (rev 115093)
@@ -93,6 +93,7 @@
     CorrectableJumpPoint m_check;
     NodeIndex m_nodeIndex;
     CodeOrigin m_codeOrigin;
+    CodeOrigin m_codeOriginForExitProfile;
     
     unsigned m_recoveryIndex;
     

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2012-04-24 19:19:35 UTC (rev 115093)
@@ -573,7 +573,8 @@
         case GetFloat32ArrayLength:
         case GetFloat64ArrayLength:
         case GetStringLength:
-        case Int32ToDouble: {
+        case Int32ToDouble:
+        case DoubleAsInt32: {
             // This node should never be visible at this stage of compilation. It is
             // inserted by fixup(), which follows this phase.
             ASSERT_NOT_REACHED();

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2012-04-24 19:19:35 UTC (rev 115093)
@@ -1343,10 +1343,13 @@
             // The reverse of the above: This node could be a UInt32ToNumber, but its
             //    alternative is still alive. This means that the only remaining uses of
             //    the number would be fine with a UInt32 intermediate.
+            //
+            // DoubleAsInt32: Same as UInt32ToNumber.
+            //
         
             bool found = false;
         
-            if (nodePtr->op() == UInt32ToNumber) {
+            if (nodePtr->op() == UInt32ToNumber || nodePtr->op() == DoubleAsInt32) {
                 NodeIndex nodeIndex = nodePtr->child1().index();
                 nodePtr = &at(nodeIndex);
                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
@@ -1358,6 +1361,7 @@
                 NodeIndex int32ToDoubleIndex = NoNode;
                 NodeIndex valueToInt32Index = NoNode;
                 NodeIndex uint32ToNumberIndex = NoNode;
+                NodeIndex doubleAsInt32Index = NoNode;
             
                 for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
                     GenerationInfo& info = m_generationInfo[virtualRegister];
@@ -1378,13 +1382,17 @@
                     case UInt32ToNumber:
                         uint32ToNumberIndex = info.nodeIndex();
                         break;
+                    case DoubleAsInt32:
+                        doubleAsInt32Index = info.nodeIndex();
                     default:
                         break;
                     }
                 }
             
                 NodeIndex nodeIndexToUse;
-                if (int32ToDoubleIndex != NoNode)
+                if (doubleAsInt32Index != NoNode)
+                    nodeIndexToUse = doubleAsInt32Index;
+                else if (int32ToDoubleIndex != NoNode)
                     nodeIndexToUse = int32ToDoubleIndex;
                 else if (valueToInt32Index != NoNode)
                     nodeIndexToUse = valueToInt32Index;
@@ -1729,6 +1737,23 @@
     integerResult(result.gpr(), m_compileIndex, op1.format());
 }
 
+void SpeculativeJIT::compileDoubleAsInt32(Node& node)
+{
+    SpeculateDoubleOperand op1(this, node.child1());
+    FPRTemporary scratch(this);
+    GPRTemporary result(this);
+    
+    FPRReg valueFPR = op1.fpr();
+    FPRReg scratchFPR = scratch.fpr();
+    GPRReg resultGPR = result.gpr();
+
+    JITCompiler::JumpList failureCases;
+    m_jit.branchConvertDoubleToInt32(valueFPR, resultGPR, failureCases, scratchFPR);
+    forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, failureCases, ValueRecovery::inFPR(valueFPR));
+
+    integerResult(resultGPR, m_compileIndex);
+}
+
 void SpeculativeJIT::compileInt32ToDouble(Node& node)
 {
 #if USE(JSVALUE64)

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2012-04-24 19:19:35 UTC (rev 115093)
@@ -1751,6 +1751,7 @@
     void compileGetByValOnString(Node&);
     void compileValueToInt32(Node&);
     void compileUInt32ToNumber(Node&);
+    void compileDoubleAsInt32(Node&);
     void compileInt32ToDouble(Node&);
     void compileGetByValOnByteArray(Node&);
     void compilePutByValForByteArray(GPRReg base, GPRReg property, Node&);
@@ -1848,9 +1849,9 @@
     // Add a set of speculation checks without additional recovery.
     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail)
     {
-        Vector<MacroAssembler::Jump, 16> JumpVector = jumpsToFail.jumps();
-        for (unsigned i = 0; i < JumpVector.size(); ++i)
-            speculationCheck(kind, jsValueSource, nodeIndex, JumpVector[i]);
+        Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps();
+        for (unsigned i = 0; i < jumpVector.size(); ++i)
+            speculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i]);
     }
     void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::JumpList& jumpsToFail)
     {
@@ -1872,18 +1873,33 @@
     {
         speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail);
         
-        Node& setLocal = at(m_jit.graph().m_blocks[m_block]->at(m_indexInBlock + 1));
-        Node& nextNode = at(m_jit.graph().m_blocks[m_block]->at(m_indexInBlock + 2));
-        ASSERT(setLocal.op() == SetLocal);
-        ASSERT(setLocal.codeOrigin == at(m_compileIndex).codeOrigin);
+        unsigned setLocalIndexInBlock = m_indexInBlock + 1;
+        
+        Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock));
+        
+        if (setLocal->op() == Int32ToDouble) {
+            setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));
+            ASSERT(at(setLocal->child1()).child1() == m_compileIndex);
+        } else
+            ASSERT(setLocal->child1() == m_compileIndex);
+        
+        Node& nextNode = at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1));
+        ASSERT(setLocal->op() == SetLocal);
+        ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin);
         ASSERT(nextNode.codeOrigin != at(m_compileIndex).codeOrigin);
         
         OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
         exit.m_codeOrigin = nextNode.codeOrigin;
-        exit.m_lastSetOperand = setLocal.local();
+        exit.m_lastSetOperand = setLocal->local();
         
-        exit.valueRecoveryForOperand(setLocal.local()) = valueRecovery;
+        exit.valueRecoveryForOperand(setLocal->local()) = valueRecovery;
     }
+    void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery)
+    {
+        Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps();
+        for (unsigned i = 0; i < jumpVector.size(); ++i)
+            forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i], valueRecovery);
+    }
 
     // Called when we statically determine that a speculation will fail.
     void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex)

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2012-04-24 19:19:35 UTC (rev 115093)
@@ -2038,6 +2038,11 @@
         compileUInt32ToNumber(node);
         break;
     }
+        
+    case DoubleAsInt32: {
+        compileDoubleAsInt32(node);
+        break;
+    }
 
     case ValueToInt32: {
         compileValueToInt32(node);
@@ -2071,25 +2076,7 @@
 #if CPU(X86)
             compileIntegerArithDivForX86(node);
 #else // CPU(X86) -> so non-X86 code follows
-            SpeculateDoubleOperand op1(this, node.child1());
-            SpeculateDoubleOperand op2(this, node.child2());
-            FPRTemporary result(this);
-            FPRTemporary scratch(this);
-            GPRTemporary intResult(this);
-            
-            FPRReg op1FPR = op1.fpr();
-            FPRReg op2FPR = op2.fpr();
-            FPRReg resultFPR = result.fpr();
-            FPRReg scratchFPR = scratch.fpr();
-            GPRReg resultGPR = intResult.gpr();
-            
-            m_jit.divDouble(op1FPR, op2FPR, resultFPR);
-            
-            JITCompiler::JumpList failureCases;
-            m_jit.branchConvertDoubleToInt32(resultFPR, resultGPR, failureCases, scratchFPR);
-            speculationCheck(Overflow, JSValueRegs(), NoNode, failureCases);
-
-            integerResult(resultGPR, m_compileIndex);
+            ASSERT_NOT_REACHED(); // should have been coverted into a double divide.
 #endif // CPU(X86)
             break;
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (115092 => 115093)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2012-04-24 19:11:12 UTC (rev 115092)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2012-04-24 19:19:35 UTC (rev 115093)
@@ -2114,6 +2114,11 @@
         break;
     }
 
+    case DoubleAsInt32: {
+        compileDoubleAsInt32(node);
+        break;
+    }
+
     case ValueToInt32: {
         compileValueToInt32(node);
         break;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to