Changeset 91226 in webkit


Ignore:
Timestamp:
Jul 18, 2011 5:36:37 PM (13 years ago)
Author:
commit-queue@webkit.org
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 <fpizlo@apple.com> 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):

Location:
trunk/Source/JavaScriptCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r91225 r91226  
     12011-07-18  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG JIT does not optimize strict equality as effectively as the old JIT does.
     4        https://bugs.webkit.org/show_bug.cgi?id=64759
     5
     6        Reviewed by Gavin Barraclough.
     7       
     8        This adds a more complete set of strict equality optimizations.  If either
     9        operand is known numeric, then the code reverts to the old style of optimizing
     10        (first try integer comparison).  Otherwise it uses the old JIT's trick of
     11        first simultaneously checking if both operands are either numbers or cells;
     12        if not then a fast path is taken.
     13
     14        * dfg/DFGJITCodeGenerator.cpp:
     15        (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq):
     16        (JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq):
     17        (JSC::DFG::JITCodeGenerator::nonSpeculativeStrictEq):
     18        * dfg/DFGJITCodeGenerator.h:
     19        * dfg/DFGNonSpeculativeJIT.cpp:
     20        (JSC::DFG::NonSpeculativeJIT::compile):
     21        * dfg/DFGOperations.cpp:
     22        * dfg/DFGOperations.h:
     23        * dfg/DFGSpeculativeJIT.cpp:
     24        (JSC::DFG::SpeculativeJIT::compile):
     25
    1262011-07-18  Gavin Barraclough  <barraclough@apple.com>
    227
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp

    r91208 r91226  
    765765}
    766766
     767void JITCodeGenerator::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert)
     768{
     769    Node& branchNode = m_jit.graph()[branchNodeIndex];
     770    BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
     771    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     772
     773    // The branch instruction will branch to the taken block.
     774    // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
     775    if (taken == (m_block + 1)) {
     776        invert = !invert;
     777        BlockIndex tmp = taken;
     778        taken = notTaken;
     779        notTaken = tmp;
     780    }
     781   
     782    JSValueOperand arg1(this, node.child1());
     783    JSValueOperand arg2(this, node.child2());
     784    GPRReg arg1GPR = arg1.gpr();
     785    GPRReg arg2GPR = arg2.gpr();
     786   
     787    GPRTemporary result(this);
     788    GPRReg resultGPR = result.gpr();
     789   
     790    if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
     791        // see if we get lucky: if the arguments are cells and they reference the same
     792        // cell, then they must be strictly equal.
     793        addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
     794       
     795        silentSpillAllRegisters(resultGPR);
     796        setupStubArguments(arg1GPR, arg2GPR);
     797        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     798        appendCallWithExceptionCheck(operationCompareStrictEqCell);
     799        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
     800        silentFillAllRegisters(resultGPR);
     801       
     802        addBranch(m_jit.branchTest8(invert ? JITCompiler::NonZero : JITCompiler::Zero, resultGPR), taken);
     803    } else {
     804        m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
     805       
     806        JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
     807       
     808        JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
     809       
     810        addBranch(m_jit.branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR), taken);
     811        addBranch(m_jit.jump(), notTaken);
     812       
     813        twoCellsCase.link(&m_jit);
     814        addBranch(m_jit.branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR), invert ? notTaken : taken);
     815       
     816        numberCase.link(&m_jit);
     817       
     818        silentSpillAllRegisters(resultGPR);
     819        setupStubArguments(arg1GPR, arg2GPR);
     820        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     821        appendCallWithExceptionCheck(operationCompareStrictEq);
     822        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
     823        silentFillAllRegisters(resultGPR);
     824       
     825        addBranch(m_jit.branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR), taken);
     826    }
     827   
     828    if (notTaken != (m_block + 1))
     829        addBranch(m_jit.jump(), notTaken);
     830}
     831
     832void JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
     833{
     834    JSValueOperand arg1(this, node.child1());
     835    JSValueOperand arg2(this, node.child2());
     836    GPRReg arg1GPR = arg1.gpr();
     837    GPRReg arg2GPR = arg2.gpr();
     838   
     839    GPRTemporary result(this);
     840    GPRReg resultGPR = result.gpr();
     841   
     842    if (isKnownCell(node.child1()) && isKnownCell(node.child2())) {
     843        // see if we get lucky: if the arguments are cells and they reference the same
     844        // cell, then they must be strictly equal.
     845        JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
     846       
     847        m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
     848       
     849        JITCompiler::Jump done = m_jit.jump();
     850
     851        notEqualCase.link(&m_jit);
     852       
     853        silentSpillAllRegisters(resultGPR);
     854        setupStubArguments(arg1GPR, arg2GPR);
     855        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     856        appendCallWithExceptionCheck(operationCompareStrictEqCell);
     857        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
     858        silentFillAllRegisters(resultGPR);
     859       
     860        m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
     861        m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
     862       
     863        done.link(&m_jit);
     864    } else {
     865        m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
     866       
     867        JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
     868       
     869        JITCompiler::Jump numberCase = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR, GPRInfo::tagTypeNumberRegister);
     870       
     871        m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
     872       
     873        JITCompiler::Jump done1 = m_jit.jump();
     874       
     875        twoCellsCase.link(&m_jit);
     876        JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
     877       
     878        m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
     879       
     880        JITCompiler::Jump done2 = m_jit.jump();
     881       
     882        numberCase.link(&m_jit);
     883        notEqualCase.link(&m_jit);
     884       
     885        silentSpillAllRegisters(resultGPR);
     886        setupStubArguments(arg1GPR, arg2GPR);
     887        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     888        appendCallWithExceptionCheck(operationCompareStrictEq);
     889        m_jit.move(GPRInfo::returnValueGPR, resultGPR);
     890        silentFillAllRegisters(resultGPR);
     891       
     892        m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
     893
     894        done1.link(&m_jit);
     895
     896        m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
     897       
     898        done2.link(&m_jit);
     899    }
     900   
     901    jsValueResult(resultGPR, m_compileIndex);
     902}
     903
     904bool JITCodeGenerator::nonSpeculativeStrictEq(Node& node, bool invert)
     905{
     906    if (!invert && (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2())))
     907        return nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq);
     908   
     909    NodeIndex branchNodeIndex = detectPeepHoleBranch();
     910    if (branchNodeIndex != NoNode) {
     911        ASSERT(node.adjustedRefCount() == 1);
     912       
     913        nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert);
     914   
     915        use(node.child1());
     916        use(node.child2());
     917        m_compileIndex = branchNodeIndex;
     918       
     919        return true;
     920    }
     921   
     922    nonSpeculativeNonPeepholeStrictEq(node, invert);
     923   
     924    return false;
     925}
     926
    767927void JITCodeGenerator::emitBranch(Node& node)
    768928{
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h

    r91208 r91226  
    572572    bool nonSpeculativeCompare(Node&, MacroAssembler::RelationalCondition, Z_DFGOperation_EJJ helperFunction);
    573573   
     574    void nonSpeculativePeepholeStrictEq(Node&, NodeIndex branchNodeIndex, bool invert = false);
     575    void nonSpeculativeNonPeepholeStrictEq(Node&, bool invert = false);
     576    bool nonSpeculativeStrictEq(Node&, bool invert = false);
     577   
    574578    void emitBranch(Node&);
    575579   
  • trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp

    r91208 r91226  
    689689
    690690    case CompareStrictEq:
    691         if (nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq))
     691        if (nonSpeculativeStrictEq(node))
    692692            return;
    693693        break;
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r91168 r91226  
    425425}
    426426
     427bool operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
     428{
     429    JSValue op1 = JSValue::decode(encodedOp1);
     430    JSValue op2 = JSValue::decode(encodedOp2);
     431   
     432    ASSERT(op1.isCell());
     433    ASSERT(op2.isCell());
     434   
     435    return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
     436}
     437
    427438bool operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
    428439{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r90950 r91226  
    8383bool operationCompareGreaterEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
    8484bool operationCompareEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
     85bool operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
    8586bool operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
    8687void* operationVirtualCall(ExecState*);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r91208 r91226  
    783783
    784784    case CompareStrictEq:
    785         if (compare(node, JITCompiler::Equal, operationCompareStrictEq))
     785        if (nonSpeculativeStrictEq(node))
    786786            return;
    787787        break;
Note: See TracChangeset for help on using the changeset viewer.