Changeset 95172 in webkit


Ignore:
Timestamp:
Sep 14, 2011 10:49:19 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG does not speculate aggressively enough on comparisons
https://bugs.webkit.org/show_bug.cgi?id=68138

Reviewed by Oliver Hunt.

This is a 75% speed-up on Kraken/ai-astar. It's a 1% win on
V8 and an 8.5% win on Kraken. Neutral on SunSpider.

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compilePeepHoleDoubleBranch):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compare):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::shouldSpeculateFinalObject):
(JSC::DFG::SpeculativeJIT::shouldSpeculateArray):
(JSC::DFG::SpeculativeJIT::shouldSpeculateObject):
(JSC::DFG::SpeculativeJIT::shouldSpeculateCell):

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r95170 r95172  
     12011-09-14  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG does not speculate aggressively enough on comparisons
     4        https://bugs.webkit.org/show_bug.cgi?id=68138
     5
     6        Reviewed by Oliver Hunt.
     7       
     8        This is a 75% speed-up on Kraken/ai-astar.  It's a 1% win on
     9        V8 and an 8.5% win on Kraken.  Neutral on SunSpider.
     10
     11        * dfg/DFGSpeculativeJIT.cpp:
     12        (JSC::DFG::SpeculativeJIT::compilePeepHoleDoubleBranch):
     13        (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
     14        (JSC::DFG::SpeculativeJIT::compileObjectEquality):
     15        (JSC::DFG::SpeculativeJIT::compare):
     16        * dfg/DFGSpeculativeJIT.h:
     17        (JSC::DFG::SpeculativeJIT::shouldSpeculateFinalObject):
     18        (JSC::DFG::SpeculativeJIT::shouldSpeculateArray):
     19        (JSC::DFG::SpeculativeJIT::shouldSpeculateObject):
     20        (JSC::DFG::SpeculativeJIT::shouldSpeculateCell):
     21
    1222011-09-14  Filip Pizlo  <fpizlo@apple.com>
    223
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r95170 r95172  
    3434GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat& returnFormat)
    3535{
     36#if ENABLE(DFG_DEBUG_VERBOSE)
     37    fprintf(stderr, "SpecInt@%d   ", nodeIndex);
     38#endif
    3639    Node& node = m_jit.graph()[nodeIndex];
    3740    VirtualRegister virtualRegister = node.virtualRegister();
     
    255258FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
    256259{
     260#if ENABLE(DFG_DEBUG_VERBOSE)
     261    fprintf(stderr, "SpecDouble@%d   ", nodeIndex);
     262#endif
    257263    Node& node = m_jit.graph()[nodeIndex];
    258264    VirtualRegister virtualRegister = node.virtualRegister();
     
    375381GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
    376382{
     383#if ENABLE(DFG_DEBUG_VERBOSE)
     384    fprintf(stderr, "SpecCell@%d   ", nodeIndex);
     385#endif
    377386    Node& node = m_jit.graph()[nodeIndex];
    378387    VirtualRegister virtualRegister = node.virtualRegister();
     
    437446GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
    438447{
     448#if ENABLE(DFG_DEBUG_VERBOSE)
     449    fprintf(stderr, "SpecBool@%d   ", nodeIndex);
     450#endif
    439451    Node& node = m_jit.graph()[nodeIndex];
    440452    VirtualRegister virtualRegister = node.virtualRegister();
     
    556568}
    557569
    558 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition, Z_DFGOperation_EJJ operation)
     570void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
    559571{
    560572    Node& branchNode = m_jit.graph()[branchNodeIndex];
     
    562574    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
    563575   
    564     bool op1Numeric = isKnownNumeric(node.child1());
    565     bool op2Numeric = isKnownNumeric(node.child2());
    566    
    567     if (op1Numeric && op2Numeric) {
    568         SpeculateDoubleOperand op1(this, node.child1());
    569         SpeculateDoubleOperand op2(this, node.child2());
    570        
    571         addBranch(m_jit.branchDouble(condition, op1.fpr(), op2.fpr()), taken);
    572     } else if (op1Numeric) {
    573         SpeculateDoubleOperand op1(this, node.child1());
    574         JSValueOperand op2(this, node.child2());
    575        
    576         FPRTemporary fprTmp(this);
    577         GPRTemporary gprTmp(this);
    578        
    579         FPRReg op1FPR = op1.fpr();
    580         GPRReg op2GPR = op2.gpr();
    581         FPRReg op2FPR = fprTmp.fpr();
    582         GPRReg gpr = gprTmp.gpr();
    583        
    584         JITCompiler::Jump slowPath = convertToDouble(op2GPR, op2FPR, gpr);
    585        
    586         addBranch(m_jit.branchDouble(condition, op1FPR, op2FPR), taken);
    587         addBranch(m_jit.jump(), notTaken);
    588        
    589         slowPath.link(&m_jit);
    590        
    591         boxDouble(op1FPR, gpr);
    592        
    593         silentSpillAllRegisters(gpr);
    594         setupStubArguments(gpr, op2GPR);
    595         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    596         appendCallWithExceptionCheck(operation);
    597         m_jit.move(GPRInfo::returnValueGPR, gpr);
    598         silentFillAllRegisters(gpr);
    599        
    600         addBranch(m_jit.branchTest8(JITCompiler::NonZero, gpr), taken);
    601     } else {
    602         JSValueOperand op1(this, node.child1());
    603         SpeculateDoubleOperand op2(this, node.child2());
    604        
    605         FPRTemporary fprTmp(this);
    606         GPRTemporary gprTmp(this);
    607        
    608         FPRReg op2FPR = op2.fpr();
    609         GPRReg op1GPR = op1.gpr();
    610         FPRReg op1FPR = fprTmp.fpr();
    611         GPRReg gpr = gprTmp.gpr();
    612        
    613         JITCompiler::Jump slowPath = convertToDouble(op1GPR, op1FPR, gpr);
    614        
    615         addBranch(m_jit.branchDouble(condition, op1FPR, op2FPR), taken);
    616         addBranch(m_jit.jump(), notTaken);
    617        
    618         slowPath.link(&m_jit);
    619        
    620         boxDouble(op2FPR, gpr);
    621        
    622         silentSpillAllRegisters(gpr);
    623         setupStubArguments(op1GPR, gpr);
    624         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    625         appendCallWithExceptionCheck(operation);
    626         m_jit.move(GPRInfo::returnValueGPR, gpr);
    627         silentFillAllRegisters(gpr);
    628        
    629         addBranch(m_jit.branchTest8(JITCompiler::NonZero, gpr), taken);
    630     }
     576    SpeculateDoubleOperand op1(this, node.child1());
     577    SpeculateDoubleOperand op2(this, node.child2());
     578   
     579    addBranch(m_jit.branchDouble(condition, op1.fpr(), op2.fpr()), taken);
    631580   
    632581    if (notTaken != (m_block + 1))
    633582        addBranch(m_jit.jump(), notTaken);
     583}
     584
     585void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr)
     586{
     587    Node& branchNode = m_jit.graph()[branchNodeIndex];
     588    BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
     589    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     590
     591    MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
     592   
     593    if (taken == (m_block + 1)) {
     594        condition = MacroAssembler::NotEqual;
     595        BlockIndex tmp = taken;
     596        taken = notTaken;
     597        notTaken = tmp;
     598    }
     599
     600    SpeculateCellOperand op1(this, node.child1());
     601    SpeculateCellOperand op2(this, node.child2());
     602   
     603    GPRReg op1GPR = op1.gpr();
     604    GPRReg op2GPR = op2.gpr();
     605   
     606    speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
     607    speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
     608   
     609    addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken);
     610    if (notTaken != (m_block + 1))
     611        addBranch(m_jit.jump(), notTaken);
     612}
     613
     614void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr)
     615{
     616    SpeculateCellOperand op1(this, node.child1());
     617    SpeculateCellOperand op2(this, node.child2());
     618    GPRTemporary result(this, op1);
     619   
     620    GPRReg op1GPR = op1.gpr();
     621    GPRReg op2GPR = op2.gpr();
     622    GPRReg resultGPR = result.gpr();
     623   
     624    speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
     625    speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
     626   
     627    MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
     628    m_jit.move(Imm32(ValueTrue), resultGPR);
     629    MacroAssembler::Jump done = m_jit.jump();
     630    falseCase.link(&m_jit);
     631    m_jit.move(Imm32(ValueFalse), resultGPR);
     632    done.link(&m_jit);
     633
     634    jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
    634635}
    635636
     
    648649            use(node.child1());
    649650            use(node.child2());
    650         } else if (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2())) {
    651             compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition, operation);
     651        } else if (shouldSpeculateNumber(node.child1(), node.child2())) {
     652            compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
     653            use(node.child1());
     654            use(node.child2());
     655        } else if (node.op == CompareEq && shouldSpeculateFinalObject(node.child1(), node.child2())) {
     656            compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr);
     657            use(node.child1());
     658            use(node.child2());
     659        } else if (node.op == CompareEq && shouldSpeculateArray(node.child1(), node.child2())) {
     660            compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr);
    652661            use(node.child1());
    653662            use(node.child2());
     
    658667        return true;
    659668    }
    660 
    661     if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2()))
     669   
     670    if (shouldSpeculateFinalObject(node.child1(), node.child2()))
     671        compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr);
     672    else if (shouldSpeculateArray(node.child1(), node.child2()))
     673        compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr);
     674    else if (!shouldSpeculateNumber(node.child1()) && !shouldSpeculateNumber(node.child2()))
    662675        nonSpeculativeNonPeepholeCompare(node, condition, operation);
    663     else {
     676    else if ((shouldSpeculateNumber(node.child1()) || shouldSpeculateNumber(node.child2())) && !shouldSpeculateInteger(node.child1(), node.child2())) {
     677        // Normal case, not fused to branch.
     678        SpeculateDoubleOperand op1(this, node.child1());
     679        SpeculateDoubleOperand op2(this, node.child2());
     680        GPRTemporary result(this);
     681       
     682        m_jit.move(TrustedImm32(ValueTrue), result.gpr());
     683        MacroAssembler::Jump trueCase = m_jit.branchDouble(doubleCondition, op1.fpr(), op2.fpr());
     684        m_jit.xorPtr(Imm32(true), result.gpr());
     685        trueCase.link(&m_jit);
     686
     687        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
     688    } else {
    664689        // Normal case, not fused to branch.
    665690        SpeculateIntegerOperand op1(this, node.child1());
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r95147 r95172  
    428428    }
    429429   
     430    bool shouldSpeculateFinalObject(NodeIndex nodeIndex)
     431    {
     432        PredictedType prediction;
     433        if (isJSConstant(nodeIndex))
     434            prediction = predictionFromValue(valueOfJSConstant(nodeIndex));
     435        else
     436            prediction = m_jit.graph().getPrediction(m_jit.graph()[nodeIndex]);
     437        return isFinalObjectPrediction(prediction);
     438    }
     439   
     440    bool shouldSpeculateArray(NodeIndex nodeIndex)
     441    {
     442        PredictedType prediction;
     443        if (isJSConstant(nodeIndex))
     444            prediction = predictionFromValue(valueOfJSConstant(nodeIndex));
     445        else
     446            prediction = m_jit.graph().getPrediction(m_jit.graph()[nodeIndex]);
     447        return isArrayPrediction(prediction);
     448    }
     449   
     450    bool shouldSpeculateObject(NodeIndex nodeIndex)
     451    {
     452        Node& node = m_jit.graph()[nodeIndex];
     453        if (node.op == ConvertThis)
     454            return true;
     455        PredictedType prediction;
     456        if (isJSConstant(nodeIndex))
     457            prediction = predictionFromValue(valueOfJSConstant(nodeIndex));
     458        else
     459            prediction = m_jit.graph().getPrediction(m_jit.graph()[nodeIndex]);
     460        return isObjectPrediction(prediction);
     461    }
     462   
     463    bool shouldSpeculateCell(NodeIndex nodeIndex)
     464    {
     465        if (isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isCell())
     466            return true;
     467       
     468        Node& node = m_jit.graph()[nodeIndex];
     469
     470        if (isCellPrediction(m_jit.graph().getPrediction(node)))
     471            return true;
     472
     473        VirtualRegister virtualRegister = node.virtualRegister();
     474        GenerationInfo& info = m_generationInfo[virtualRegister];
     475       
     476        if (info.isJSCell())
     477            return true;
     478       
     479        return false;
     480    }
     481   
    430482    bool shouldSpeculateInteger(NodeIndex op1, NodeIndex op2)
    431483    {
     
    437489        return shouldSpeculateNumber(op1) && shouldSpeculateNumber(op2);
    438490    }
    439 
     491   
     492    bool shouldSpeculateFinalObject(NodeIndex op1, NodeIndex op2)
     493    {
     494        return shouldSpeculateFinalObject(op1) && shouldSpeculateObject(op2)
     495            || shouldSpeculateObject(op1) && shouldSpeculateFinalObject(op2);
     496    }
     497
     498    bool shouldSpeculateArray(NodeIndex op1, NodeIndex op2)
     499    {
     500        return shouldSpeculateArray(op1) && shouldSpeculateObject(op2)
     501            || shouldSpeculateObject(op1) && shouldSpeculateArray(op2);
     502    }
     503   
    440504    bool compare(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, Z_DFGOperation_EJJ);
    441505    void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition);
    442     void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition, Z_DFGOperation_EJJ);
     506    void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition);
     507    void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, void* vptr);
     508    void compileObjectEquality(Node&, void* vptr);
    443509   
    444510    JITCompiler::Jump convertToDouble(GPRReg value, FPRReg result, GPRReg tmp);
Note: See TracChangeset for help on using the changeset viewer.