Title: [91226] trunk/Source/_javascript_Core
Revision
91226
Author
[email protected]
Date
2011-07-18 17:36:37 -0700 (Mon, 18 Jul 2011)

Log Message

DFG JIT does not optimize strict equality as effectively as the old JIT does.
https://bugs.webkit.org/show_bug.cgi?id=64759

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

This adds a more complete set of strict equality optimizations.  If either
operand is known numeric, then the code reverts to the old style of optimizing
(first try integer comparison).  Otherwise it uses the old JIT's trick of
first simultaneously checking if both operands are either numbers or cells;
if not then a fast path is taken.

* dfg/DFGJITCodeGenerator.cpp:
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq):
(JSC::DFG::JITCodeGenerator::nonSpeculativeStrictEq):
* dfg/DFGJITCodeGenerator.h:
* dfg/DFGNonSpeculativeJIT.cpp:
(JSC::DFG::NonSpeculativeJIT::compile):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (91225 => 91226)


--- trunk/Source/_javascript_Core/ChangeLog	2011-07-19 00:26:14 UTC (rev 91225)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-07-19 00:36:37 UTC (rev 91226)
@@ -1,3 +1,28 @@
+2011-07-18  Filip Pizlo  <[email protected]>
+
+        DFG JIT does not optimize strict equality as effectively as the old JIT does.
+        https://bugs.webkit.org/show_bug.cgi?id=64759
+
+        Reviewed by Gavin Barraclough.
+        
+        This adds a more complete set of strict equality optimizations.  If either
+        operand is known numeric, then the code reverts to the old style of optimizing
+        (first try integer comparison).  Otherwise it uses the old JIT's trick of
+        first simultaneously checking if both operands are either numbers or cells;
+        if not then a fast path is taken.
+
+        * dfg/DFGJITCodeGenerator.cpp:
+        (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq):
+        (JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq):
+        (JSC::DFG::JITCodeGenerator::nonSpeculativeStrictEq):
+        * dfg/DFGJITCodeGenerator.h:
+        * dfg/DFGNonSpeculativeJIT.cpp:
+        (JSC::DFG::NonSpeculativeJIT::compile):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2011-07-18  Gavin Barraclough  <[email protected]>
 
         https://bugs.webkit.org/show_bug.cgi?id=64760

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp (91225 => 91226)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-07-19 00:26:14 UTC (rev 91225)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-07-19 00:36:37 UTC (rev 91226)
@@ -764,6 +764,166 @@
     return false;
 }
 
+void JITCodeGenerator::nonSpeculativePeepholeStrictEq(Node& node, 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());
+
+    // The branch instruction will branch to the taken block.
+    // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
+    if (taken == (m_block + 1)) {
+        invert = !invert;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+    
+    JSValueOperand arg1(this, node.child1());
+    JSValueOperand arg2(this, node.child2());
+    GPRReg arg1GPR = arg1.gpr();
+    GPRReg arg2GPR = arg2.gpr();
+    
+    GPRTemporary result(this);
+    GPRReg resultGPR = result.gpr();
+    
+    if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
+        // see if we get lucky: if the arguments are cells and they reference the same
+        // cell, then they must be strictly equal.
+        addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
+        
+        silentSpillAllRegisters(resultGPR);
+        setupStubArguments(arg1GPR, arg2GPR);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        appendCallWithExceptionCheck(operationCompareStrictEqCell);
+        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
+        silentFillAllRegisters(resultGPR);
+        
+        addBranch(m_jit.branchTest8(invert ? JITCompiler::NonZero : JITCompiler::Zero, resultGPR), taken);
+    } else {
+        m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
+        
+        JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
+        
+        JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
+        
+        addBranch(m_jit.branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR), taken);
+        addBranch(m_jit.jump(), notTaken);
+        
+        twoCellsCase.link(&m_jit);
+        addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
+        
+        numberCase.link(&m_jit);
+        
+        silentSpillAllRegisters(resultGPR);
+        setupStubArguments(arg1GPR, arg2GPR);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        appendCallWithExceptionCheck(operationCompareStrictEq);
+        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
+        silentFillAllRegisters(resultGPR);
+        
+        addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR), taken);
+    }
+    
+    if (notTaken != (m_block + 1))
+        addBranch(m_jit.jump(), notTaken);
+}
+
+void JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
+{
+    JSValueOperand arg1(this, node.child1());
+    JSValueOperand arg2(this, node.child2());
+    GPRReg arg1GPR = arg1.gpr();
+    GPRReg arg2GPR = arg2.gpr();
+    
+    GPRTemporary result(this);
+    GPRReg resultGPR = result.gpr();
+    
+    if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
+        // see if we get lucky: if the arguments are cells and they reference the same
+        // cell, then they must be strictly equal.
+        JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
+        
+        m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
+        
+        JITCompiler::Jump done = m_jit.jump();
+
+        notEqualCase.link(&m_jit);
+        
+        silentSpillAllRegisters(resultGPR);
+        setupStubArguments(arg1GPR, arg2GPR);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        appendCallWithExceptionCheck(operationCompareStrictEqCell);
+        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
+        silentFillAllRegisters(resultGPR);
+        
+        m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
+        m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
+        
+        done.link(&m_jit);
+    } else {
+        m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
+        
+        JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
+        
+        JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
+        
+        m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
+        
+        JITCompiler::Jump done1 = m_jit.jump();
+        
+        twoCellsCase.link(&m_jit);
+        JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
+        
+        m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
+        
+        JITCompiler::Jump done2 = m_jit.jump();
+        
+        numberCase.link(&m_jit);
+        notEqualCase.link(&m_jit);
+        
+        silentSpillAllRegisters(resultGPR);
+        setupStubArguments(arg1GPR, arg2GPR);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        appendCallWithExceptionCheck(operationCompareStrictEq);
+        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
+        silentFillAllRegisters(resultGPR);
+        
+        m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
+
+        done1.link(&m_jit);
+
+        m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
+        
+        done2.link(&m_jit);
+    }
+    
+    jsValueResult(resultGPR, m_compileIndex);
+}
+
+bool JITCodeGenerator::nonSpeculativeStrictEq(Node& node, bool invert)
+{
+    if (!invert && (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2())))
+        return nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq);
+    
+    NodeIndex branchNodeIndex = detectPeepHoleBranch();
+    if (branchNodeIndex != NoNode) {
+        ASSERT(node.adjustedRefCount() == 1);
+        
+        nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert);
+    
+        use(node.child1());
+        use(node.child2());
+        m_compileIndex = branchNodeIndex;
+        
+        return true;
+    }
+    
+    nonSpeculativeNonPeepholeStrictEq(node, invert);
+    
+    return false;
+}
+
 void JITCodeGenerator::emitBranch(Node& node)
 {
     JSValueOperand value(this, node.child1());

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (91225 => 91226)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-07-19 00:26:14 UTC (rev 91225)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-07-19 00:36:37 UTC (rev 91226)
@@ -571,6 +571,10 @@
     void nonSpeculativeNonPeepholeCompare(Node&, MacroAssembler::RelationalCondition, Z_DFGOperation_EJJ helperFunction);
     bool nonSpeculativeCompare(Node&, MacroAssembler::RelationalCondition, Z_DFGOperation_EJJ helperFunction);
     
+    void nonSpeculativePeepholeStrictEq(Node&, NodeIndex branchNodeIndex, bool invert = false);
+    void nonSpeculativeNonPeepholeStrictEq(Node&, bool invert = false);
+    bool nonSpeculativeStrictEq(Node&, bool invert = false);
+    
     void emitBranch(Node&);
     
     MacroAssembler::Address addressOfCallData(int idx)

Modified: trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp (91225 => 91226)


--- trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp	2011-07-19 00:26:14 UTC (rev 91225)
+++ trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp	2011-07-19 00:36:37 UTC (rev 91226)
@@ -688,7 +688,7 @@
         break;
 
     case CompareStrictEq:
-        if (nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq))
+        if (nonSpeculativeStrictEq(node))
             return;
         break;
 

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (91225 => 91226)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-07-19 00:26:14 UTC (rev 91225)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-07-19 00:36:37 UTC (rev 91226)
@@ -424,6 +424,17 @@
     return JSValue::equalSlowCaseInline(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
 }
 
+bool operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
+    
+    ASSERT(op1.isCell());
+    ASSERT(op2.isCell());
+    
+    return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
+}
+
 bool operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
     return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (91225 => 91226)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2011-07-19 00:26:14 UTC (rev 91225)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2011-07-19 00:36:37 UTC (rev 91226)
@@ -82,6 +82,7 @@
 bool operationCompareGreater(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
 bool operationCompareGreaterEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
 bool operationCompareEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+bool operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
 bool operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
 void* operationVirtualCall(ExecState*);
 void* operationLinkCall(ExecState*);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (91225 => 91226)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-07-19 00:26:14 UTC (rev 91225)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-07-19 00:36:37 UTC (rev 91226)
@@ -782,7 +782,7 @@
         break;
 
     case CompareStrictEq:
-        if (compare(node, JITCompiler::Equal, operationCompareStrictEq))
+        if (nonSpeculativeStrictEq(node))
             return;
         break;
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to