Changeset 54534 in webkit


Ignore:
Timestamp:
Feb 9, 2010 12:50:22 AM (14 years ago)
Author:
loki@webkit.org
Message:

Add a soft modulo operation to ARM JIT using a trampoline function.
The performance progression is about ~1.8% on ARMv7
https://bugs.webkit.org/show_bug.cgi?id=34424

Patch by Tamas Szirbucz <szirbucz@inf.u-szeged.hu> on 2010-02-09
Reviewed by Gavin Barraclough.

Developed in cooperation with Gabor Loki.

  • jit/JIT.h:
  • jit/JITArithmetic.cpp:

(JSC::JIT::emit_op_mod):
(JSC::JIT::emitSlow_op_mod):

  • jit/JITOpcodes.cpp:

(JSC::JIT::softModulo):

  • jit/JITStubs.h:

(JSC::JITThunks::ctiSoftModulo):

  • wtf/Platform.h:
Location:
trunk/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r54532 r54534  
     12010-02-09  Tamas Szirbucz  <szirbucz@inf.u-szeged.hu>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        Add a soft modulo operation to ARM JIT using a trampoline function.
     6        The performance progression is about ~1.8% on ARMv7
     7        https://bugs.webkit.org/show_bug.cgi?id=34424
     8
     9        Developed in cooperation with Gabor Loki.
     10
     11        * jit/JIT.h:
     12        * jit/JITArithmetic.cpp:
     13        (JSC::JIT::emit_op_mod):
     14        (JSC::JIT::emitSlow_op_mod):
     15        * jit/JITOpcodes.cpp:
     16        (JSC::JIT::softModulo):
     17        * jit/JITStubs.h:
     18        (JSC::JITThunks::ctiSoftModulo):
     19        * wtf/Platform.h:
     20
    1212010-02-08  Gavin Barraclough  <barraclough@apple.com>
    222
  • trunk/JavaScriptCore/jit/JIT.h

    r54362 r54534  
    801801        void emit_op_to_primitive(Instruction*);
    802802        void emit_op_unexpected_load(Instruction*);
     803#if ENABLE(JIT_OPTIMIZE_MOD)
     804        void softModulo();
     805#endif
    803806
    804807        void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
  • trunk/JavaScriptCore/jit/JITArithmetic.cpp

    r52729 r54534  
    3232#include "JITInlineMethods.h"
    3333#include "JITStubCall.h"
     34#include "JITStubs.h"
    3435#include "JSArray.h"
    3536#include "JSFunction.h"
     
    11871188    unsigned op2 = currentInstruction[3].u.operand;
    11881189
     1190#if ENABLE(JIT_OPTIMIZE_MOD)   
     1191    emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
     1192    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
     1193    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
     1194   
     1195    addSlowCase(branch32(Equal, regT2, Imm32(0)));
     1196   
     1197    emitNakedCall(m_globalData->jitStubs.ctiSoftModulo());
     1198
     1199    emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
     1200#else
    11891201    JITStubCall stubCall(this, cti_op_mod);
    11901202    stubCall.addArgument(op1);
    11911203    stubCall.addArgument(op2);
    11921204    stubCall.call(dst);
    1193 }
    1194 
    1195 void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&)
    1196 {
     1205#endif
     1206}
     1207
     1208void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     1209{
     1210#if ENABLE(JIT_OPTIMIZE_MOD)
     1211    unsigned result = currentInstruction[1].u.operand;
     1212    unsigned op1 = currentInstruction[2].u.operand;
     1213    unsigned op2 = currentInstruction[3].u.operand;
     1214    linkSlowCase(iter);
     1215    linkSlowCase(iter);
     1216    linkSlowCase(iter);
     1217    JITStubCall stubCall(this, cti_op_mod);
     1218    stubCall.addArgument(op1);
     1219    stubCall.addArgument(op2);
     1220    stubCall.call(result);
     1221#else
     1222    ASSERT_NOT_REACHED();
     1223#endif
    11971224}
    11981225
     
    21392166    unsigned op2 = currentInstruction[3].u.operand;
    21402167
     2168#if ENABLE(JIT_OPTIMIZE_MOD)   
     2169    emitGetVirtualRegisters(op1, regT0, op2, regT2);
     2170    emitJumpSlowCaseIfNotImmediateInteger(regT0);
     2171    emitJumpSlowCaseIfNotImmediateInteger(regT2);
     2172   
     2173    addSlowCase(branch32(Equal, regT2, Imm32(1)));
     2174
     2175    emitNakedCall(m_globalData->jitStubs.ctiSoftModulo());
     2176
     2177    emitPutVirtualRegister(result, regT0);
     2178#else
    21412179    JITStubCall stubCall(this, cti_op_mod);
    21422180    stubCall.addArgument(op1, regT2);
    21432181    stubCall.addArgument(op2, regT2);
    21442182    stubCall.call(result);
    2145 }
    2146 
    2147 void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&)
    2148 {
     2183#endif
     2184}
     2185
     2186void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     2187{
     2188#if ENABLE(JIT_OPTIMIZE_MOD)
     2189    unsigned result = currentInstruction[1].u.operand;
     2190    unsigned op1 = currentInstruction[2].u.operand;
     2191    unsigned op2 = currentInstruction[3].u.operand;
     2192    linkSlowCase(iter);
     2193    linkSlowCase(iter);
     2194    linkSlowCase(iter);
     2195    JITStubCall stubCall(this, cti_op_mod);
     2196    stubCall.addArgument(op1, regT2);
     2197    stubCall.addArgument(op2, regT2);
     2198    stubCall.call(result);
     2199#else
    21492200    ASSERT_NOT_REACHED();
     2201#endif
    21502202}
    21512203
  • trunk/JavaScriptCore/jit/JITOpcodes.cpp

    r54362 r54534  
    4343void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, TrampolineStructure *trampolines)
    4444{
     45#if ENABLE(JIT_OPTIMIZE_MOD)
     46    Label softModBegin = align();
     47    softModulo();
     48#endif
    4549#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    4650    // (1) This function provides fast property access for string length
     
    378382    UNUSED_PARAM(ctiVirtualCallLink);
    379383#endif
     384#if ENABLE(JIT_OPTIMIZE_MOD)
     385    trampolines->ctiSoftModulo = trampolineAt(finalCode, softModBegin);
     386#endif
    380387}
    381388
     
    14981505void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, TrampolineStructure *trampolines)
    14991506{
     1507#if ENABLE(JIT_OPTIMIZE_MOD)
     1508    Label softModBegin = align();
     1509    softModulo();
     1510#endif
    15001511#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    15011512    // (2) The second function provides fast property access for string length
     
    18311842    trampolines->ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
    18321843    trampolines->ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk);
     1844#if ENABLE(JIT_OPTIMIZE_MOD)
     1845    trampolines->ctiSoftModulo = trampolineAt(finalCode, softModBegin);
     1846#endif
    18331847#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    18341848    trampolines->ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin);
     
    29792993#endif // USE(JSVALUE32_64)
    29802994
     2995// For both JSValue32_64 and JSValue32
     2996#if ENABLE(JIT_OPTIMIZE_MOD)
     2997#if CPU(ARM_TRADITIONAL)
     2998void JIT::softModulo()
     2999{
     3000    push(regS0);
     3001    push(regS1);
     3002    push(regT1);
     3003    push(regT3);
     3004#if USE(JSVALUE32_64)
     3005    m_assembler.mov_r(regT3, regT2);
     3006    m_assembler.mov_r(regT2, regT0);
     3007#else
     3008    m_assembler.mov_r(regT3, m_assembler.asr(regT2, 1));
     3009    m_assembler.mov_r(regT2, m_assembler.asr(regT0, 1));
     3010#endif
     3011    m_assembler.mov_r(regT1, ARMAssembler::getOp2(0));
     3012   
     3013    m_assembler.teq_r(regT3, ARMAssembler::getOp2(0));
     3014    m_assembler.rsb_r(regT3, regT3, ARMAssembler::getOp2(0), ARMAssembler::MI);
     3015    m_assembler.eor_r(regT1, regT1, ARMAssembler::getOp2(1), ARMAssembler::MI);
     3016   
     3017    m_assembler.teq_r(regT2, ARMAssembler::getOp2(0));
     3018    m_assembler.rsb_r(regT2, regT2, ARMAssembler::getOp2(0), ARMAssembler::MI);
     3019    m_assembler.eor_r(regT1, regT1, ARMAssembler::getOp2(2), ARMAssembler::MI);
     3020   
     3021    Jump exitBranch = branch32(LessThan, regT2, regT3);
     3022
     3023    m_assembler.sub_r(regS1, regT3, ARMAssembler::getOp2(1));
     3024    m_assembler.tst_r(regS1, regT3);
     3025    m_assembler.and_r(regT2, regT2, regS1, ARMAssembler::EQ);
     3026    m_assembler.and_r(regT0, regS1, regT3);
     3027    Jump exitBranch2 = branchTest32(Zero, regT0);
     3028   
     3029    m_assembler.clz_r(regS1, regT2);
     3030    m_assembler.clz_r(regS0, regT3);
     3031    m_assembler.sub_r(regS0, regS0, regS1);
     3032
     3033    m_assembler.rsbs_r(regS0, regS0, ARMAssembler::getOp2(31));
     3034
     3035    m_assembler.mov_r(regS0, m_assembler.lsl(regS0, 1), ARMAssembler::NE);
     3036
     3037    m_assembler.add_r(ARMRegisters::pc, ARMRegisters::pc, m_assembler.lsl(regS0, 2), ARMAssembler::NE);
     3038    m_assembler.mov_r(regT0, regT0);
     3039   
     3040    for (int i = 31; i > 0; --i) {
     3041        m_assembler.cmp_r(regT2, m_assembler.lsl(regT3, i));
     3042        m_assembler.sub_r(regT2, regT2, m_assembler.lsl(regT3, i), ARMAssembler::CS);
     3043    }
     3044
     3045    m_assembler.cmp_r(regT2, regT3);
     3046    m_assembler.sub_r(regT2, regT2, regT3, ARMAssembler::CS);
     3047   
     3048    exitBranch.link(this);
     3049    exitBranch2.link(this);
     3050   
     3051    m_assembler.teq_r(regT1, ARMAssembler::getOp2(0));
     3052    m_assembler.rsb_r(regT2, regT2, ARMAssembler::getOp2(0), ARMAssembler::GT);
     3053   
     3054#if USE(JSVALUE32_64)
     3055    m_assembler.mov_r(regT0, regT2);
     3056#else
     3057    m_assembler.mov_r(regT0, m_assembler.lsl(regT2, 1));
     3058    m_assembler.eor_r(regT0, regT0, ARMAssembler::getOp2(1));
     3059#endif
     3060    pop(regT3);
     3061    pop(regT1);
     3062    pop(regS1);
     3063    pop(regS0);
     3064    ret();
     3065}
     3066#else
     3067#error "JIT_OPTIMIZE_MOD not yet supported on this platform."
     3068#endif // CPU(ARM_TRADITIONAL)
     3069#endif
    29813070} // namespace JSC
    29823071
  • trunk/JavaScriptCore/jit/JITStubs.h

    r54362 r54534  
    8181        MacroAssemblerCodePtr ctiVirtualCall;
    8282        MacroAssemblerCodePtr ctiNativeCallThunk;
     83        MacroAssemblerCodePtr ctiSoftModulo;
    8384    };
    8485
     
    251252        MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; }
    252253        MacroAssemblerCodePtr ctiNativeCallThunk() { return m_trampolineStructure.ctiNativeCallThunk; }
     254        MacroAssemblerCodePtr ctiSoftModulo() { return m_trampolineStructure.ctiSoftModulo; }
    253255
    254256    private:
  • trunk/JavaScriptCore/wtf/Platform.h

    r54528 r54534  
    886886#endif /* !defined(ENABLE_JIT) */
    887887
     888/* CPU architecture specific optimizations */
     889#if CPU(ARM_TRADITIONAL)
     890#if ENABLE(JIT) && !defined(ENABLE_JIT_OPTIMIZE_MOD) && WTF_ARM_ARCH_AT_LEAST(5)
     891#define ENABLE_JIT_OPTIMIZE_MOD 1
     892#endif
     893#endif
     894
    888895#if ENABLE(JIT)
    889896#ifndef ENABLE_JIT_OPTIMIZE_CALL
     
    898905#ifndef ENABLE_JIT_OPTIMIZE_METHOD_CALLS
    899906#define ENABLE_JIT_OPTIMIZE_METHOD_CALLS 1
     907#endif
     908#ifndef ENABLE_JIT_OPTIMIZE_MOD
     909#define ENABLE_JIT_OPTIMIZE_MOD 0
    900910#endif
    901911#endif
Note: See TracChangeset for help on using the changeset viewer.