Changeset 89961 in webkit


Ignore:
Timestamp:
Jun 28, 2011 2:33:38 PM (13 years ago)
Author:
barraclough@apple.com
Message:

https://bugs.webkit.org/show_bug.cgi?id=63563
DFG JIT - add support for double arith to speculative path

Reviewed by Oliver Hunt.

Add integer support for div & mod, add double support for div, mod,
add, sub & mul, dynamically selecting based on operand types.

  • dfg/DFGJITCodeGenerator.cpp:

(JSC::DFG::FPRTemporary::FPRTemporary):

  • dfg/DFGJITCodeGenerator.h:
  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::assembler):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculateDoubleOperand::SpeculateDoubleOperand):
(JSC::DFG::SpeculateDoubleOperand::~SpeculateDoubleOperand):
(JSC::DFG::SpeculateDoubleOperand::index):
(JSC::DFG::SpeculateDoubleOperand::fpr):

Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r89959 r89961  
     12011-06-28  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=63563
     6        DFG JIT - add support for double arith to speculative path
     7
     8        Add integer support for div & mod, add double support for div, mod,
     9        add, sub & mul, dynamically selecting based on operand types.
     10
     11        * dfg/DFGJITCodeGenerator.cpp:
     12        (JSC::DFG::FPRTemporary::FPRTemporary):
     13        * dfg/DFGJITCodeGenerator.h:
     14        * dfg/DFGJITCompiler.h:
     15        (JSC::DFG::JITCompiler::assembler):
     16        * dfg/DFGSpeculativeJIT.cpp:
     17        (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
     18        (JSC::DFG::SpeculativeJIT::compile):
     19        * dfg/DFGSpeculativeJIT.h:
     20        (JSC::DFG::SpeculateDoubleOperand::SpeculateDoubleOperand):
     21        (JSC::DFG::SpeculateDoubleOperand::~SpeculateDoubleOperand):
     22        (JSC::DFG::SpeculateDoubleOperand::index):
     23        (JSC::DFG::SpeculateDoubleOperand::fpr):
     24
    1252011-06-28  Oliver Hunt  <oliver@apple.com>
    226
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp

    r89956 r89961  
    637637}
    638638
     639FPRTemporary::FPRTemporary(JITCodeGenerator* jit, SpeculateDoubleOperand& op1)
     640    : m_jit(jit)
     641    , m_fpr(InvalidFPRReg)
     642{
     643    if (m_jit->canReuse(op1.index()))
     644        m_fpr = m_jit->reuse(op1.fpr());
     645    else
     646        m_fpr = m_jit->fprAllocate();
     647}
     648
     649FPRTemporary::FPRTemporary(JITCodeGenerator* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& op2)
     650    : m_jit(jit)
     651    , m_fpr(InvalidFPRReg)
     652{
     653    if (m_jit->canReuse(op1.index()))
     654        m_fpr = m_jit->reuse(op1.fpr());
     655    else if (m_jit->canReuse(op2.index()))
     656        m_fpr = m_jit->reuse(op2.fpr());
     657    else
     658        m_fpr = m_jit->fprAllocate();
     659}
     660
    639661} } // namespace JSC::DFG
    640662
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h

    r89956 r89961  
    4040class SpeculateIntegerOperand;
    4141class SpeculateStrictInt32Operand;
     42class SpeculateDoubleOperand;
    4243class SpeculateCellOperand;
    4344
     
    10361037    FPRTemporary(JITCodeGenerator*, DoubleOperand&);
    10371038    FPRTemporary(JITCodeGenerator*, DoubleOperand&, DoubleOperand&);
     1039    FPRTemporary(JITCodeGenerator*, SpeculateDoubleOperand&);
     1040    FPRTemporary(JITCodeGenerator*, SpeculateDoubleOperand&, SpeculateDoubleOperand&);
    10381041
    10391042    ~FPRTemporary()
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r89861 r89961  
    107107    CodeBlock* codeBlock() { return m_codeBlock; }
    108108    JSGlobalData* globalData() { return m_globalData; }
     109    AssemblerType_T& assembler() { return m_assembler; }
    109110
    110111#if CPU(X86_64)
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r89957 r89961  
    175175}
    176176
     177FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
     178{
     179    Node& node = m_jit.graph()[nodeIndex];
     180    VirtualRegister virtualRegister = node.virtualRegister();
     181    GenerationInfo& info = m_generationInfo[virtualRegister];
     182
     183    if (info.registerFormat() == DataFormatNone) {
     184        GPRReg gpr = allocate();
     185
     186        if (node.isConstant()) {
     187            if (isInt32Constant(nodeIndex)) {
     188                FPRReg fpr = fprAllocate();
     189                m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(static_cast<double>(valueOfInt32Constant(nodeIndex))))), gpr);
     190                m_jit.movePtrToDouble(gpr, fpr);
     191                unlock(gpr);
     192
     193                m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
     194                info.fillDouble(fpr);
     195                return fpr;
     196            }
     197            if (isDoubleConstant(nodeIndex)) {
     198                FPRReg fpr = fprAllocate();
     199                m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), gpr);
     200                m_jit.movePtrToDouble(gpr, fpr);
     201                unlock(gpr);
     202
     203                m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
     204                info.fillDouble(fpr);
     205                return fpr;
     206            }
     207            ASSERT(isJSConstant(nodeIndex));
     208            JSValue jsValue = valueOfJSConstant(nodeIndex);
     209            m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
     210            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
     211            info.fillJSValue(gpr, DataFormatJS);
     212            unlock(gpr);
     213        } else {
     214            DataFormat spillFormat = info.spillFormat();
     215            ASSERT(spillFormat & DataFormatJS);
     216            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
     217            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
     218            info.fillJSValue(gpr, spillFormat);
     219            unlock(gpr);
     220        }
     221    }
     222
     223    switch (info.registerFormat()) {
     224    case DataFormatNone:
     225        // Should have filled, above.
     226        ASSERT_NOT_REACHED();
     227       
     228    case DataFormatCell:
     229    case DataFormatJSCell:
     230    case DataFormatJS: {
     231        GPRReg jsValueGpr = info.gpr();
     232        m_gprs.lock(jsValueGpr);
     233        FPRReg fpr = fprAllocate();
     234        GPRReg tempGpr = allocate();
     235
     236        JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
     237
     238        speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
     239
     240        // First, if we get here we have a double encoded as a JSValue
     241        m_jit.move(jsValueGpr, tempGpr);
     242        m_jit.addPtr(GPRInfo::tagTypeNumberRegister, tempGpr);
     243        m_jit.movePtrToDouble(tempGpr, fpr);
     244        JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
     245
     246        // Finally, handle integers.
     247        isInteger.link(&m_jit);
     248        m_jit.convertInt32ToDouble(jsValueGpr, fpr);
     249        hasUnboxedDouble.link(&m_jit);
     250
     251        m_gprs.release(jsValueGpr);
     252        m_gprs.unlock(jsValueGpr);
     253        m_gprs.unlock(tempGpr);
     254        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
     255        info.fillDouble(fpr);
     256        return fpr;
     257    }
     258
     259    case DataFormatJSInteger:
     260    case DataFormatInteger: {
     261        FPRReg fpr = fprAllocate();
     262        GPRReg gpr = info.gpr();
     263        m_gprs.lock(gpr);
     264        m_jit.convertInt32ToDouble(gpr, fpr);
     265        m_gprs.unlock(gpr);
     266        return fpr;
     267    }
     268
     269    // Unbox the double
     270    case DataFormatJSDouble: {
     271        GPRReg gpr = info.gpr();
     272        FPRReg fpr = unboxDouble(gpr);
     273
     274        m_gprs.release(gpr);
     275        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
     276
     277        info.fillDouble(fpr);
     278        return fpr;
     279    }
     280
     281    case DataFormatDouble: {
     282        FPRReg fpr = info.fpr();
     283        m_fprs.lock(fpr);
     284        return fpr;
     285    }
     286    }
     287
     288    ASSERT_NOT_REACHED();
     289    return InvalidFPRReg;
     290}
     291
    177292GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
    178293{
     
    431546
    432547    case ValueToNumber: {
    433         SpeculateIntegerOperand op1(this, node.child1);
    434         GPRTemporary result(this, op1);
    435         m_jit.move(op1.gpr(), result.gpr());
    436         integerResult(result.gpr(), m_compileIndex, op1.format());
     548        if (isInteger(node.child1)) {
     549            SpeculateIntegerOperand op1(this, node.child1);
     550            GPRTemporary result(this, op1);
     551            m_jit.move(op1.gpr(), result.gpr());
     552            integerResult(result.gpr(), m_compileIndex, op1.format());
     553            break;
     554        }
     555        SpeculateDoubleOperand op1(this, node.child1);
     556        FPRTemporary result(this, op1);
     557        m_jit.moveDouble(op1.fpr(), result.fpr());
     558        doubleResult(result.fpr(), m_compileIndex);
    437559        break;
    438560    }
     
    440562    case ValueAdd:
    441563    case ArithAdd: {
    442         if (isInt32Constant(node.child1)) {
    443             int32_t imm1 = valueOfInt32Constant(node.child1);
     564        if (isInteger(node.child1) || isInteger(node.child2)) {
     565            if (isInt32Constant(node.child1)) {
     566                int32_t imm1 = valueOfInt32Constant(node.child1);
     567                SpeculateIntegerOperand op2(this, node.child2);
     568                GPRTemporary result(this);
     569
     570                speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
     571
     572                integerResult(result.gpr(), m_compileIndex);
     573                break;
     574            }
     575               
     576            if (isInt32Constant(node.child2)) {
     577                SpeculateIntegerOperand op1(this, node.child1);
     578                int32_t imm2 = valueOfInt32Constant(node.child2);
     579                GPRTemporary result(this);
     580
     581                speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
     582
     583                integerResult(result.gpr(), m_compileIndex);
     584                break;
     585            }
     586               
     587            SpeculateIntegerOperand op1(this, node.child1);
     588            SpeculateIntegerOperand op2(this, node.child2);
     589            GPRTemporary result(this, op1, op2);
     590
     591            GPRReg gpr1 = op1.gpr();
     592            GPRReg gpr2 = op2.gpr();
     593            GPRReg gprResult = result.gpr();
     594            MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
     595
     596            if (gpr1 == gprResult)
     597                speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
     598            else if (gpr2 == gprResult)
     599                speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
     600            else
     601                speculationCheck(check);
     602
     603            integerResult(gprResult, m_compileIndex);
     604            break;
     605        }
     606
     607        SpeculateDoubleOperand op1(this, node.child1);
     608        SpeculateDoubleOperand op2(this, node.child2);
     609        FPRTemporary result(this, op1, op2);
     610
     611        FPRReg reg1 = op1.fpr();
     612        FPRReg reg2 = op2.fpr();
     613        m_jit.addDouble(reg1, reg2, result.fpr());
     614
     615        doubleResult(result.fpr(), m_compileIndex);
     616        break;
     617    }
     618
     619    case ArithSub: {
     620        if (isInteger(node.child1) || isInteger(node.child2)) {
     621            if (isInt32Constant(node.child2)) {
     622                SpeculateIntegerOperand op1(this, node.child1);
     623                int32_t imm2 = valueOfInt32Constant(node.child2);
     624                GPRTemporary result(this);
     625
     626                speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
     627
     628                integerResult(result.gpr(), m_compileIndex);
     629                break;
     630            }
     631               
     632            SpeculateIntegerOperand op1(this, node.child1);
    444633            SpeculateIntegerOperand op2(this, node.child2);
    445634            GPRTemporary result(this);
    446635
    447             speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
     636            speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
    448637
    449638            integerResult(result.gpr(), m_compileIndex);
    450639            break;
    451640        }
    452            
    453         if (isInt32Constant(node.child2)) {
     641        SpeculateDoubleOperand op1(this, node.child1);
     642        SpeculateDoubleOperand op2(this, node.child2);
     643        FPRTemporary result(this, op1);
     644
     645        FPRReg reg1 = op1.fpr();
     646        FPRReg reg2 = op2.fpr();
     647        m_jit.subDouble(reg1, reg2, result.fpr());
     648
     649        doubleResult(result.fpr(), m_compileIndex);
     650        break;
     651    }
     652
     653    case ArithMul: {
     654        if (isInteger(node.child1) && isInteger(node.child2)) {
    454655            SpeculateIntegerOperand op1(this, node.child1);
    455             int32_t imm2 = valueOfInt32Constant(node.child2);
     656            SpeculateIntegerOperand op2(this, node.child2);
    456657            GPRTemporary result(this);
    457658
    458             speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
     659            GPRReg reg1 = op1.gpr();
     660            GPRReg reg2 = op2.gpr();
     661            speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
     662
     663            MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
     664            speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
     665            speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
     666            resultNonZero.link(&m_jit);
    459667
    460668            integerResult(result.gpr(), m_compileIndex);
    461669            break;
    462670        }
    463            
    464         SpeculateIntegerOperand op1(this, node.child1);
    465         SpeculateIntegerOperand op2(this, node.child2);
    466         GPRTemporary result(this, op1, op2);
    467 
    468         GPRReg gpr1 = op1.gpr();
    469         GPRReg gpr2 = op2.gpr();
    470         GPRReg gprResult = result.gpr();
    471         MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
    472 
    473         if (gpr1 == gprResult)
    474             speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
    475         else if (gpr2 == gprResult)
    476             speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
    477         else
    478             speculationCheck(check);
    479 
    480         integerResult(gprResult, m_compileIndex);
    481         break;
    482     }
    483 
    484     case ArithSub: {
    485         if (isInt32Constant(node.child2)) {
    486             SpeculateIntegerOperand op1(this, node.child1);
    487             int32_t imm2 = valueOfInt32Constant(node.child2);
    488             GPRTemporary result(this);
    489 
    490             speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
    491 
    492             integerResult(result.gpr(), m_compileIndex);
    493             break;
    494         }
    495            
    496         SpeculateIntegerOperand op1(this, node.child1);
    497         SpeculateIntegerOperand op2(this, node.child2);
    498         GPRTemporary result(this);
    499 
    500         speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
    501 
    502         integerResult(result.gpr(), m_compileIndex);
    503         break;
    504     }
    505 
    506     case ArithMul: {
    507         SpeculateIntegerOperand op1(this, node.child1);
    508         SpeculateIntegerOperand op2(this, node.child2);
    509         GPRTemporary result(this);
    510 
    511         GPRReg reg1 = op1.gpr();
    512         GPRReg reg2 = op2.gpr();
    513         speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
    514 
    515         MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
    516         speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
    517         speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
    518         resultNonZero.link(&m_jit);
    519 
    520         integerResult(result.gpr(), m_compileIndex);
     671        SpeculateDoubleOperand op1(this, node.child1);
     672        SpeculateDoubleOperand op2(this, node.child2);
     673        FPRTemporary result(this, op1, op2);
     674
     675        FPRReg reg1 = op1.fpr();
     676        FPRReg reg2 = op2.fpr();
     677       
     678        m_jit.mulDouble(reg1, reg2, result.fpr());
     679       
     680        doubleResult(result.fpr(), m_compileIndex);
    521681        break;
    522682    }
    523683
    524684    case ArithDiv: {
    525         SpeculateIntegerOperand op1(this, node.child1);
    526         SpeculateIntegerOperand op2(this, node.child2);
    527         GPRTemporary result(this, op1, op2);
    528 
    529         op1.gpr();
    530         op2.gpr();
    531         terminateSpeculativeExecution();
    532 
    533         integerResult(result.gpr(), m_compileIndex);
     685        SpeculateDoubleOperand op1(this, node.child1);
     686        SpeculateDoubleOperand op2(this, node.child2);
     687        FPRTemporary result(this, op1);
     688
     689        FPRReg reg1 = op1.fpr();
     690        FPRReg reg2 = op2.fpr();
     691        m_jit.divDouble(reg1, reg2, result.fpr());
     692
     693        doubleResult(result.fpr(), m_compileIndex);
    534694        break;
    535695    }
     
    538698        SpeculateIntegerOperand op1(this, node.child1);
    539699        SpeculateIntegerOperand op2(this, node.child2);
    540         GPRTemporary result(this, op1, op2);
    541 
    542         op1.gpr();
    543         op2.gpr();
    544         terminateSpeculativeExecution();
    545 
    546         integerResult(result.gpr(), m_compileIndex);
     700        GPRTemporary eax(this, X86Registers::eax);
     701        GPRTemporary edx(this, X86Registers::edx);
     702        GPRReg op1Gpr = op1.gpr();
     703        GPRReg op2Gpr = op2.gpr();
     704
     705        speculationCheck(m_jit.branchTestPtr(JITCompiler::Zero, op2Gpr));
     706
     707        GPRReg temp2 = InvalidGPRReg;
     708        if (op2Gpr == X86Registers::eax || op2Gpr == X86Registers::edx) {
     709            temp2 = allocate();
     710            m_jit.move(op2Gpr, temp2);
     711            op2Gpr = temp2;
     712        }
     713
     714        m_jit.move(op1Gpr, eax.gpr());
     715        m_jit.assembler().cdq();
     716        m_jit.assembler().idivl_r(op2Gpr);
     717
     718        if (temp2 != InvalidGPRReg)
     719            unlock(temp2);
     720
     721        integerResult(edx.gpr(), m_compileIndex);
    547722        break;
    548723    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r89957 r89961  
    130130    GPRReg fillSpeculateInt(NodeIndex, DataFormat& returnFormat);
    131131    GPRReg fillSpeculateIntStrict(NodeIndex);
     132    FPRReg fillSpeculateDouble(NodeIndex);
    132133    GPRReg fillSpeculateCell(NodeIndex);
    133134
     
    318319};
    319320
     321class SpeculateDoubleOperand {
     322public:
     323    explicit SpeculateDoubleOperand(SpeculativeJIT* jit, NodeIndex index)
     324        : m_jit(jit)
     325        , m_index(index)
     326        , m_fprOrInvalid(InvalidFPRReg)
     327    {
     328        ASSERT(m_jit);
     329        if (jit->isFilled(index))
     330            fpr();
     331    }
     332
     333    ~SpeculateDoubleOperand()
     334    {
     335        ASSERT(m_fprOrInvalid != InvalidFPRReg);
     336        m_jit->unlock(m_fprOrInvalid);
     337    }
     338
     339    NodeIndex index() const
     340    {
     341        return m_index;
     342    }
     343
     344    FPRReg fpr()
     345    {
     346        if (m_fprOrInvalid == InvalidFPRReg)
     347            m_fprOrInvalid = m_jit->fillSpeculateDouble(index());
     348        return m_fprOrInvalid;
     349    }
     350
     351private:
     352    SpeculativeJIT* m_jit;
     353    NodeIndex m_index;
     354    FPRReg m_fprOrInvalid;
     355};
     356
    320357class SpeculateCellOperand {
    321358public:
Note: See TracChangeset for help on using the changeset viewer.