Title: [91208] trunk/Source/_javascript_Core
Revision
91208
Author
[email protected]
Date
2011-07-18 14:04:51 -0700 (Mon, 18 Jul 2011)

Log Message

DFG JIT does not optimize equal-null comparisons and branches.
https://bugs.webkit.org/show_bug.cgi?id=64659

Patch by Filip Pizlo <[email protected]> on 2011-07-18
Reviewed by Gavin Barraclough.

Added a peephole-aware compare-to-null implementation to JITCodeGenerator,
which is used by both the speculative and non-speculative JIT.  Through
the use of the new isNullConstant helper, the two JITs invoke the
nonSpecualtiveCompareNull() helper instead of their regular comparison
helpers when compiling CompareEq.  Through the use of the new isKnownCell
helper, the compare-null code will skip the is-a-cell check if the
speculative JIT had been speculating cell.

* dfg/DFGJITCodeGenerator.cpp:
(JSC::DFG::JITCodeGenerator::isKnownCell):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeCompareNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranchNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativeCompareNull):
* dfg/DFGJITCodeGenerator.h:
(JSC::DFG::JITCodeGenerator::isNullConstant):
* dfg/DFGNonSpeculativeJIT.cpp:
(JSC::DFG::NonSpeculativeJIT::compile):
* dfg/DFGOperations.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (91207 => 91208)


--- trunk/Source/_javascript_Core/ChangeLog	2011-07-18 20:56:42 UTC (rev 91207)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-07-18 21:04:51 UTC (rev 91208)
@@ -1,3 +1,31 @@
+2011-07-18  Filip Pizlo  <[email protected]>
+
+        DFG JIT does not optimize equal-null comparisons and branches.
+        https://bugs.webkit.org/show_bug.cgi?id=64659
+
+        Reviewed by Gavin Barraclough.
+        
+        Added a peephole-aware compare-to-null implementation to JITCodeGenerator,
+        which is used by both the speculative and non-speculative JIT.  Through
+        the use of the new isNullConstant helper, the two JITs invoke the
+        nonSpecualtiveCompareNull() helper instead of their regular comparison
+        helpers when compiling CompareEq.  Through the use of the new isKnownCell
+        helper, the compare-null code will skip the is-a-cell check if the
+        speculative JIT had been speculating cell.
+
+        * dfg/DFGJITCodeGenerator.cpp:
+        (JSC::DFG::JITCodeGenerator::isKnownCell):
+        (JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeCompareNull):
+        (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranchNull):
+        (JSC::DFG::JITCodeGenerator::nonSpeculativeCompareNull):
+        * dfg/DFGJITCodeGenerator.h:
+        (JSC::DFG::JITCodeGenerator::isNullConstant):
+        * dfg/DFGNonSpeculativeJIT.cpp:
+        (JSC::DFG::NonSpeculativeJIT::compile):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2011-07-18  James Robinson  <[email protected]>
 
         Timer scheduling should be based off the monotonic clock

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp (91207 => 91208)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-07-18 20:56:42 UTC (rev 91207)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-07-18 21:04:51 UTC (rev 91208)
@@ -365,6 +365,21 @@
     return false;
 }
 
+bool JITCodeGenerator::isKnownCell(NodeIndex nodeIndex)
+{
+    GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()];
+    
+    DataFormat registerFormat = info.registerFormat();
+    if (registerFormat != DataFormatNone)
+        return (registerFormat | DataFormatJS) == DataFormatJSCell;
+    
+    DataFormat spillFormat = info.spillFormat();
+    if (spillFormat != DataFormatNone)
+        return (spillFormat | DataFormatJS) == DataFormatJSCell;
+    
+    return false;
+}
+
 bool JITCodeGenerator::isKnownNotInteger(NodeIndex nodeIndex)
 {
     Node& node = m_jit.graph()[nodeIndex];
@@ -519,6 +534,99 @@
     m_jit.addMethodGet(slowCall, structToCompare, protoObj, protoStructToCompare, putFunction);
 }
 
+void JITCodeGenerator::nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert)
+{
+    JSValueOperand arg(this, operand);
+    GPRReg argGPR = arg.gpr();
+    
+    GPRTemporary result(this, arg);
+    GPRReg resultGPR = result.gpr();
+    
+    JITCompiler::Jump notCell;
+    
+    if (!isKnownCell(operand))
+        notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
+    
+    m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
+    m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultGPR);
+    
+    if (!isKnownCell(operand)) {
+        JITCompiler::Jump done = m_jit.jump();
+        
+        notCell.link(&m_jit);
+        
+        m_jit.move(argGPR, resultGPR);
+        m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
+        m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
+        
+        done.link(&m_jit);
+    }
+    
+    m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
+    jsValueResult(resultGPR, m_compileIndex);
+}
+
+void JITCodeGenerator::nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert)
+{
+    Node& branchNode = m_jit.graph()[branchNodeIndex];
+    BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
+    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
+    
+    if (taken == (m_block + 1)) {
+        invert = !invert;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+
+    JSValueOperand arg(this, operand);
+    GPRReg argGPR = arg.gpr();
+    
+    GPRTemporary result(this, arg);
+    GPRReg resultGPR = result.gpr();
+    
+    JITCompiler::Jump notCell;
+    
+    if (!isKnownCell(operand))
+        notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
+    
+    m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
+    addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined)), taken);
+    
+    if (!isKnownCell(operand)) {
+        addBranch(m_jit.jump(), notTaken);
+        
+        notCell.link(&m_jit);
+        
+        m_jit.move(argGPR, resultGPR);
+        m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
+        addBranch(m_jit.branchPtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))), taken);
+    }
+    
+    if (notTaken != (m_block + 1))
+        addBranch(m_jit.jump(), notTaken);
+}
+
+bool JITCodeGenerator::nonSpeculativeCompareNull(Node& node, NodeIndex operand, bool invert)
+{
+    NodeIndex branchNodeIndex = detectPeepHoleBranch();
+    if (branchNodeIndex != NoNode) {
+        ASSERT(node.adjustedRefCount() == 1);
+        
+        nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert);
+    
+        use(node.child1());
+        use(node.child2());
+        m_compileIndex = branchNodeIndex;
+        
+        return true;
+    }
+    
+    nonSpeculativeNonPeepholeCompareNull(operand, invert);
+    
+    return false;
+}
+
 void JITCodeGenerator::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition cond, Z_DFGOperation_EJJ helperFunction)
 {
     Node& branchNode = m_jit.graph()[branchNodeIndex];

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (91207 => 91208)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-07-18 20:56:42 UTC (rev 91207)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-07-18 21:04:51 UTC (rev 91208)
@@ -414,6 +414,7 @@
 
     bool isKnownInteger(NodeIndex);
     bool isKnownNumeric(NodeIndex);
+    bool isKnownCell(NodeIndex);
     
     bool isKnownNotInteger(NodeIndex);
 
@@ -425,6 +426,12 @@
     int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return m_jit.valueOfInt32Constant(nodeIndex); }
     double valueOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.valueOfDoubleConstant(nodeIndex); }
     JSValue valueOfJSConstant(NodeIndex nodeIndex) { return m_jit.valueOfJSConstant(nodeIndex); }
+    bool isNullConstant(NodeIndex nodeIndex)
+    {
+        if (!isConstant(nodeIndex))
+            return false;
+        return valueOfJSConstant(nodeIndex).isNull();
+    }
 
     Identifier* identifier(unsigned index)
     {
@@ -556,6 +563,10 @@
     void cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
     void cachedGetMethod(GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
     
+    void nonSpeculativeNonPeepholeCompareNull(NodeIndex operand, bool invert = false);
+    void nonSpeculativePeepholeBranchNull(NodeIndex operand, NodeIndex branchNodeIndex, bool invert = false);
+    bool nonSpeculativeCompareNull(Node&, NodeIndex operand, bool invert = false);
+    
     void nonSpeculativePeepholeBranch(Node&, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition, Z_DFGOperation_EJJ helperFunction);
     void nonSpeculativeNonPeepholeCompare(Node&, MacroAssembler::RelationalCondition, Z_DFGOperation_EJJ helperFunction);
     bool nonSpeculativeCompare(Node&, MacroAssembler::RelationalCondition, Z_DFGOperation_EJJ helperFunction);

Modified: trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp (91207 => 91208)


--- trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp	2011-07-18 20:56:42 UTC (rev 91207)
+++ trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp	2011-07-18 21:04:51 UTC (rev 91208)
@@ -673,6 +673,16 @@
         break;
         
     case CompareEq:
+        if (isNullConstant(node.child1())) {
+            if (nonSpeculativeCompareNull(node, node.child2()))
+                return;
+            break;
+        }
+        if (isNullConstant(node.child2())) {
+            if (nonSpeculativeCompareNull(node, node.child1()))
+                return;
+            break;
+        }
         if (nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareEq))
             return;
         break;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (91207 => 91208)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-07-18 20:56:42 UTC (rev 91207)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-07-18 21:04:51 UTC (rev 91208)
@@ -767,6 +767,16 @@
         break;
 
     case CompareEq:
+        if (isNullConstant(node.child1())) {
+            if (nonSpeculativeCompareNull(node, node.child2()))
+                return;
+            break;
+        }
+        if (isNullConstant(node.child2())) {
+            if (nonSpeculativeCompareNull(node, node.child1()))
+                return;
+            break;
+        }
         if (compare(node, JITCompiler::Equal, operationCompareEq))
             return;
         break;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to