Changeset 48744 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Sep 24, 2009, 7:40:59 PM (16 years ago)
Author:
[email protected]
Message:

Division is needlessly slow in 64-bit
https://bugs.webkit.org/show_bug.cgi?id=29723

Reviewed by Gavin Barraclough.

Add codegen for op_div on x86-64

Location:
trunk/JavaScriptCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r48738 r48744  
     12009-09-24  Oliver Hunt  <[email protected]>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        Division is needlessly slow in 64-bit
     6        https://bugs.webkit.org/show_bug.cgi?id=29723
     7
     8        Add codegen for op_div on x86-64
     9
     10        * jit/JIT.cpp:
     11        (JSC::JIT::privateCompileMainPass):
     12        (JSC::JIT::privateCompileSlowCases):
     13        * jit/JIT.h:
     14        * jit/JITArithmetic.cpp:
     15        (JSC::JIT::compileBinaryArithOpSlowCase):
     16        (JSC::JIT::emit_op_div):
     17        (JSC::JIT::emitSlow_op_div):
     18        * jit/JITInlineMethods.h:
     19        (JSC::JIT::isOperandConstantImmediateDouble):
     20        (JSC::JIT::addressFor):
     21        (JSC::JIT::emitLoadDouble):
     22        (JSC::JIT::emitLoadInt32ToDouble):
     23        (JSC::JIT::emitJumpSlowCaseIfNotImmediateNumber):
     24
    1252009-09-24  Jeremy Orlow  <[email protected]>
    226
  • trunk/JavaScriptCore/jit/JIT.cpp

    r47597 r48744  
    196196        switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
    197197        DEFINE_BINARY_OP(op_del_by_val)
    198 #if !USE(JSVALUE32_64)
     198#if USE(JSVALUE32)
    199199        DEFINE_BINARY_OP(op_div)
    200200#endif
     
    231231        DEFINE_OP(op_debug)
    232232        DEFINE_OP(op_del_by_id)
    233 #if USE(JSVALUE32_64)
     233#if !USE(JSVALUE32)
    234234        DEFINE_OP(op_div)
    235235#endif
     
    380380        DEFINE_SLOWCASE_OP(op_construct_verify)
    381381        DEFINE_SLOWCASE_OP(op_convert_this)
    382 #if USE(JSVALUE32_64)
     382#if !USE(JSVALUE32)
    383383        DEFINE_SLOWCASE_OP(op_div)
    384384#endif
  • trunk/JavaScriptCore/jit/JIT.h

    r48525 r48744  
    380380        enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
    381381        void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type);
     382        bool isOperandConstantImmediateDouble(unsigned src);
     383       
     384        void emitLoadDouble(unsigned index, FPRegisterID value);
     385        void emitLoadInt32ToDouble(unsigned index, FPRegisterID value);
     386
     387        Address addressFor(unsigned index, RegisterID base = callFrameRegister);
    382388
    383389#if USE(JSVALUE32_64)
    384390        Address tagFor(unsigned index, RegisterID base = callFrameRegister);
    385391        Address payloadFor(unsigned index, RegisterID base = callFrameRegister);
    386         Address addressFor(unsigned index, RegisterID base = callFrameRegister);
    387392
    388393        bool getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant);
    389         bool isOperandConstantImmediateDouble(unsigned src);
    390394
    391395        void emitLoadTag(unsigned index, RegisterID tag);
     
    395399        void emitLoad(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
    396400        void emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1, unsigned index2, RegisterID tag2, RegisterID payload2);
    397         void emitLoadDouble(unsigned index, FPRegisterID value);
    398         void emitLoadInt32ToDouble(unsigned index, FPRegisterID value);
    399401
    400402        void emitStore(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
     
    500502        JIT::Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
    501503        void emitJumpSlowCaseIfNotImmediateInteger(RegisterID);
     504        void emitJumpSlowCaseIfNotImmediateNumber(RegisterID);
    502505        void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
    503506
  • trunk/JavaScriptCore/jit/JITArithmetic.cpp

    r47530 r48744  
    19791979    else if (opcodeID == op_sub)
    19801980        subDouble(fpRegT2, fpRegT1);
     1981    else if (opcodeID == op_mul)
     1982        mulDouble(fpRegT2, fpRegT1);
    19811983    else {
    1982         ASSERT(opcodeID == op_mul);
    1983         mulDouble(fpRegT2, fpRegT1);
     1984        ASSERT(opcodeID == op_div);
     1985        divDouble(fpRegT2, fpRegT1);
    19841986    }
    19851987    moveDoubleToPtr(fpRegT1, regT0);
     
    20812083    } else
    20822084        compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, types);
     2085}
     2086
     2087void JIT::emit_op_div(Instruction* currentInstruction)
     2088{
     2089    unsigned dst = currentInstruction[1].u.operand;
     2090    unsigned op1 = currentInstruction[2].u.operand;
     2091    unsigned op2 = currentInstruction[3].u.operand;
     2092    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
     2093
     2094    if (isOperandConstantImmediateDouble(op1)) {
     2095        emitGetVirtualRegister(op1, regT0);
     2096        addPtr(tagTypeNumberRegister, regT0);
     2097        movePtrToDouble(regT0, fpRegT0);
     2098    } else if (isOperandConstantImmediateInt(op1)) {
     2099        emitLoadInt32ToDouble(op1, fpRegT0);
     2100    } else {
     2101        emitGetVirtualRegister(op1, regT0);
     2102        if (!types.first().definitelyIsNumber())
     2103            emitJumpSlowCaseIfNotImmediateNumber(regT0);
     2104        Jump notInt = emitJumpIfNotImmediateInteger(regT0);
     2105        convertInt32ToDouble(regT0, fpRegT0);
     2106        Jump skipDoubleLoad = jump();
     2107        notInt.link(this);
     2108        addPtr(tagTypeNumberRegister, regT0);
     2109        movePtrToDouble(regT0, fpRegT0);
     2110        skipDoubleLoad.link(this);
     2111    }
     2112   
     2113    if (isOperandConstantImmediateDouble(op2)) {
     2114        emitGetVirtualRegister(op2, regT1);
     2115        addPtr(tagTypeNumberRegister, regT1);
     2116        movePtrToDouble(regT1, fpRegT1);
     2117    } else if (isOperandConstantImmediateInt(op2)) {
     2118        emitLoadInt32ToDouble(op2, fpRegT1);
     2119    } else {
     2120        emitGetVirtualRegister(op2, regT1);
     2121        if (!types.second().definitelyIsNumber())
     2122            emitJumpSlowCaseIfNotImmediateNumber(regT1);
     2123        Jump notInt = emitJumpIfNotImmediateInteger(regT1);
     2124        convertInt32ToDouble(regT1, fpRegT1);
     2125        Jump skipDoubleLoad = jump();
     2126        notInt.link(this);
     2127        addPtr(tagTypeNumberRegister, regT1);
     2128        movePtrToDouble(regT1, fpRegT1);
     2129        skipDoubleLoad.link(this);
     2130    }
     2131    divDouble(fpRegT1, fpRegT0);
     2132
     2133    JumpList doubleResult;
     2134    Jump end;
     2135    bool attemptIntConversion = (!isOperandConstantImmediateInt(op1) || getConstantOperand(op1).asInt32() > 1) && isOperandConstantImmediateInt(op2);
     2136    if (attemptIntConversion) {
     2137        m_assembler.cvttsd2si_rr(fpRegT0, regT0);
     2138        doubleResult.append(branchTest32(Zero, regT0));
     2139        m_assembler.ucomisd_rr(fpRegT1, fpRegT0);
     2140       
     2141        doubleResult.append(m_assembler.jne());
     2142        doubleResult.append(m_assembler.jp());
     2143        emitFastArithIntToImmNoCheck(regT0, regT0);
     2144        end = jump();
     2145    }
     2146
     2147    // Double result.
     2148    doubleResult.link(this);
     2149    moveDoubleToPtr(fpRegT0, regT0);
     2150    subPtr(tagTypeNumberRegister, regT0);
     2151
     2152    if (attemptIntConversion)
     2153        end.link(this);
     2154    emitPutVirtualRegister(dst, regT0);
     2155}
     2156
     2157void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     2158{
     2159    unsigned result = currentInstruction[1].u.operand;
     2160    unsigned op1 = currentInstruction[2].u.operand;
     2161    unsigned op2 = currentInstruction[3].u.operand;
     2162    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
     2163    if (types.first().definitelyIsNumber() && types.second().definitelyIsNumber()) {
     2164#ifndef NDEBUG
     2165        breakpoint();
     2166#endif
     2167        return;
     2168    }
     2169    if (!isOperandConstantImmediateDouble(op1) && !isOperandConstantImmediateInt(op1)) {
     2170        if (!types.first().definitelyIsNumber())
     2171            linkSlowCase(iter);
     2172    }
     2173    if (!isOperandConstantImmediateDouble(op2) && !isOperandConstantImmediateInt(op2)) {
     2174        if (!types.second().definitelyIsNumber())
     2175            linkSlowCase(iter);
     2176    }
     2177    // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
     2178    JITStubCall stubCall(this, cti_op_div);
     2179    stubCall.addArgument(op1, regT2);
     2180    stubCall.addArgument(op2, regT2);
     2181    stubCall.call(result);
    20832182}
    20842183
  • trunk/JavaScriptCore/jit/JITInlineMethods.h

    r48525 r48744  
    6666}
    6767
     68ALWAYS_INLINE bool JIT::isOperandConstantImmediateDouble(unsigned src)
     69{
     70    return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isDouble();
     71}
     72
    6873ALWAYS_INLINE JSValue JIT::getConstantOperand(unsigned src)
    6974{
     
    306311#endif
    307312
     313inline JIT::Address JIT::addressFor(unsigned index, RegisterID base)
     314{
     315    return Address(base, (index * sizeof(Register)));
     316}
     317
    308318#if USE(JSVALUE32_64)
    309319
     
    316326{
    317327    return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
    318 }
    319 
    320 inline JIT::Address JIT::addressFor(unsigned index, RegisterID base)
    321 {
    322     return Address(base, (index * sizeof(Register)));
    323328}
    324329
     
    578583   
    579584    return false;
    580 }
    581 
    582 ALWAYS_INLINE bool JIT::isOperandConstantImmediateDouble(unsigned src)
    583 {
    584     return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isDouble();
    585585}
    586586
     
    733733    return branchTestPtr(Zero, reg, tagTypeNumberRegister);
    734734}
     735
     736inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
     737{
     738    if (m_codeBlock->isConstantRegisterIndex(index)) {
     739        Register& inConstantPool = m_codeBlock->constantRegister(index);
     740        loadDouble(&inConstantPool, value);
     741    } else
     742        loadDouble(addressFor(index), value);
     743}
     744
     745inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
     746{
     747    if (m_codeBlock->isConstantRegisterIndex(index)) {
     748        Register& inConstantPool = m_codeBlock->constantRegister(index);
     749        convertInt32ToDouble(AbsoluteAddress(&inConstantPool), value);
     750    } else
     751        convertInt32ToDouble(addressFor(index), value);
     752}
    735753#endif
    736754
     
    768786{
    769787    addSlowCase(emitJumpIfNotImmediateIntegers(reg1, reg2, scratch));
     788}
     789
     790ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateNumber(RegisterID reg)
     791{
     792    addSlowCase(emitJumpIfNotImmediateNumber(reg));
    770793}
    771794
Note: See TracChangeset for help on using the changeset viewer.