Changeset 58469 in webkit


Ignore:
Timestamp:
Apr 28, 2010 8:57:16 PM (14 years ago)
Author:
oliver@apple.com
Message:

2010-04-28 Oliver Hunt <oliver@apple.com>

Reviewed by Gavin Barraclough.

Add fast paths for Math.pow and Math.sqrt
https://bugs.webkit.org/show_bug.cgi?id=38294

Add specialized thunks for Math.pow and Math.sqrt.
This requires adding a sqrtDouble function to the MacroAssembler
and sqrtsd to the x86 assembler.

Math.pow is slightly more complicated, in that we have
to implement exponentiation ourselves rather than relying
on hardware support. The inline exponentiation is restricted
to positive integer exponents on a numeric base. Exponentiation
is finally performed through the "Exponentiation by Squaring"
algorithm.

  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::ImmPtr::ImmPtr):
  • assembler/MacroAssemblerARM.h: (JSC::MacroAssemblerARM::supportsFloatingPointSqrt): (JSC::MacroAssemblerARM::loadDouble): (JSC::MacroAssemblerARM::sqrtDouble):
  • assembler/MacroAssemblerARMv7.h: (JSC::MacroAssemblerARMv7::supportsFloatingPointSqrt): (JSC::MacroAssemblerARMv7::sqrtDouble):
  • assembler/MacroAssemblerX86.h: (JSC::MacroAssemblerX86::loadDouble): (JSC::MacroAssemblerX86::supportsFloatingPointSqrt):
  • assembler/MacroAssemblerX86Common.h: (JSC::MacroAssemblerX86Common::sqrtDouble):
  • assembler/MacroAssemblerX86_64.h: (JSC::MacroAssemblerX86_64::loadDouble): (JSC::MacroAssemblerX86_64::supportsFloatingPointSqrt):
  • assembler/X86Assembler.h: (JSC::X86Assembler::): (JSC::X86Assembler::movsd_mr): (JSC::X86Assembler::sqrtsd_rr): (JSC::X86Assembler::X86InstructionFormatter::twoByteOp): (JSC::X86Assembler::X86InstructionFormatter::memoryModRM):
  • create_hash_table:
  • jit/JIT.h:
  • jit/JITInlineMethods.h:
  • jit/JITOpcodes.cpp:
  • jit/JITStubs.h: (JSC::JITThunks::ctiNativeCallThunk):
  • jit/JSInterfaceJIT.h: (JSC::JSInterfaceJIT::emitLoadDouble): (JSC::JSInterfaceJIT::emitJumpIfImmediateNumber): (JSC::JSInterfaceJIT::emitJumpIfNotImmediateNumber): (JSC::JSInterfaceJIT::emitLoadInt32):
  • jit/SpecializedThunkJIT.h: (JSC::SpecializedThunkJIT::loadDoubleArgument): (JSC::SpecializedThunkJIT::loadInt32Argument): (JSC::SpecializedThunkJIT::returnJSValue): (JSC::SpecializedThunkJIT::returnDouble): (JSC::SpecializedThunkJIT::finalize):
  • jit/ThunkGenerators.cpp: (JSC::sqrtThunkGenerator): (JSC::powThunkGenerator):
  • jit/ThunkGenerators.h:
  • runtime/Executable.h: (JSC::NativeExecutable::NativeExecutable):
  • runtime/JSFunction.cpp: (JSC::JSFunction::JSFunction):
Location:
trunk/JavaScriptCore
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r58461 r58469  
     12010-04-28  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        Add fast paths for Math.pow and Math.sqrt
     6        https://bugs.webkit.org/show_bug.cgi?id=38294
     7
     8        Add specialized thunks for Math.pow and Math.sqrt.
     9        This requires adding a sqrtDouble function to the MacroAssembler
     10        and sqrtsd to the x86 assembler.
     11
     12        Math.pow is slightly more complicated, in that we have
     13        to implement exponentiation ourselves rather than relying
     14        on hardware support.  The inline exponentiation is restricted
     15        to positive integer exponents on a numeric base.  Exponentiation
     16        is finally performed through the "Exponentiation by Squaring"
     17        algorithm.
     18
     19        * assembler/AbstractMacroAssembler.h:
     20        (JSC::AbstractMacroAssembler::ImmPtr::ImmPtr):
     21        * assembler/MacroAssemblerARM.h:
     22        (JSC::MacroAssemblerARM::supportsFloatingPointSqrt):
     23        (JSC::MacroAssemblerARM::loadDouble):
     24        (JSC::MacroAssemblerARM::sqrtDouble):
     25        * assembler/MacroAssemblerARMv7.h:
     26        (JSC::MacroAssemblerARMv7::supportsFloatingPointSqrt):
     27        (JSC::MacroAssemblerARMv7::sqrtDouble):
     28        * assembler/MacroAssemblerX86.h:
     29        (JSC::MacroAssemblerX86::loadDouble):
     30        (JSC::MacroAssemblerX86::supportsFloatingPointSqrt):
     31        * assembler/MacroAssemblerX86Common.h:
     32        (JSC::MacroAssemblerX86Common::sqrtDouble):
     33        * assembler/MacroAssemblerX86_64.h:
     34        (JSC::MacroAssemblerX86_64::loadDouble):
     35        (JSC::MacroAssemblerX86_64::supportsFloatingPointSqrt):
     36        * assembler/X86Assembler.h:
     37        (JSC::X86Assembler::):
     38        (JSC::X86Assembler::movsd_mr):
     39        (JSC::X86Assembler::sqrtsd_rr):
     40        (JSC::X86Assembler::X86InstructionFormatter::twoByteOp):
     41        (JSC::X86Assembler::X86InstructionFormatter::memoryModRM):
     42        * create_hash_table:
     43        * jit/JIT.h:
     44        * jit/JITInlineMethods.h:
     45        * jit/JITOpcodes.cpp:
     46        * jit/JITStubs.h:
     47        (JSC::JITThunks::ctiNativeCallThunk):
     48        * jit/JSInterfaceJIT.h:
     49        (JSC::JSInterfaceJIT::emitLoadDouble):
     50        (JSC::JSInterfaceJIT::emitJumpIfImmediateNumber):
     51        (JSC::JSInterfaceJIT::emitJumpIfNotImmediateNumber):
     52        (JSC::JSInterfaceJIT::emitLoadInt32):
     53        * jit/SpecializedThunkJIT.h:
     54        (JSC::SpecializedThunkJIT::loadDoubleArgument):
     55        (JSC::SpecializedThunkJIT::loadInt32Argument):
     56        (JSC::SpecializedThunkJIT::returnJSValue):
     57        (JSC::SpecializedThunkJIT::returnDouble):
     58        (JSC::SpecializedThunkJIT::finalize):
     59        * jit/ThunkGenerators.cpp:
     60        (JSC::sqrtThunkGenerator):
     61        (JSC::powThunkGenerator):
     62        * jit/ThunkGenerators.h:
     63        * runtime/Executable.h:
     64        (JSC::NativeExecutable::NativeExecutable):
     65        * runtime/JSFunction.cpp:
     66        (JSC::JSFunction::JSFunction):
     67
    1682010-04-28  Mike Thole  <mthole@apple.com>
    269
  • trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r57925 r58469  
    161161    // from pointers used as absolute addresses to memory operations
    162162    struct ImmPtr {
    163         explicit ImmPtr(void* value)
     163        explicit ImmPtr(const void* value)
    164164            : m_value(value)
    165165        {
     
    171171        }
    172172
    173         void* m_value;
     173        const void* m_value;
    174174    };
    175175
  • trunk/JavaScriptCore/assembler/MacroAssemblerARM.h

    r58091 r58469  
    752752    }
    753753
     754    bool supportsFloatingPointSqrt() const
     755    {
     756        return false;
     757    }
     758
    754759    void loadDouble(ImplicitAddress address, FPRegisterID dest)
    755760    {
     
    757762    }
    758763
    759     void loadDouble(void* address, FPRegisterID dest)
     764    void loadDouble(const void* address, FPRegisterID dest)
    760765    {
    761766        m_assembler.ldr_un_imm(ARMRegisters::S0, (ARMWord)address);
     
    811816        loadDouble(src, ARMRegisters::SD0);
    812817        mulDouble(ARMRegisters::SD0, dest);
     818    }
     819
     820    void sqrtDouble(FPRegisterID, FPRegisterID)
     821    {
     822        ASSERT_NOT_REACHED();
    813823    }
    814824
  • trunk/JavaScriptCore/assembler/MacroAssemblerARMv7.h

    r55834 r58469  
    495495    bool supportsFloatingPointTruncate() const { return false; }
    496496
     497    bool supportsFloatingPointSqrt() const
     498    {
     499        return false;
     500    }
     501
    497502    void loadDouble(ImplicitAddress address, FPRegisterID dest)
    498503    {
     
    556561        loadDouble(src, fpTempRegister);
    557562        mulDouble(fpTempRegister, dest);
     563    }
     564
     565    void sqrtDouble(FPRegisterID, FPRegisterID)
     566    {
     567        ASSERT_NOT_REACHED();
    558568    }
    559569
  • trunk/JavaScriptCore/assembler/MacroAssemblerX86.h

    r55633 r58469  
    8888    }
    8989
    90     void loadDouble(void* address, FPRegisterID dest)
     90    void loadDouble(const void* address, FPRegisterID dest)
    9191    {
    9292        ASSERT(isSSE2Present());
     
    173173    // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
    174174    bool supportsFloatingPointTruncate() const { return m_isSSE2Present; }
     175    bool supportsFloatingPointSqrt() const { return m_isSSE2Present; }
    175176
    176177private:
  • trunk/JavaScriptCore/assembler/MacroAssemblerX86Common.h

    r57925 r58469  
    302302    }
    303303   
     304    void sqrtDouble(FPRegisterID src, FPRegisterID dst)
     305    {
     306        m_assembler.sqrtsd_rr(src, dst);
     307    }
    304308
    305309    // Memory access operations:
  • trunk/JavaScriptCore/assembler/MacroAssemblerX86_64.h

    r57925 r58469  
    8787    }
    8888
    89     void loadDouble(void* address, FPRegisterID dest)
     89    void loadDouble(const void* address, FPRegisterID dest)
    9090    {
    9191        move(ImmPtr(address), scratchRegister);
     
    428428    // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
    429429    bool supportsFloatingPointTruncate() const { return true; }
     430    bool supportsFloatingPointSqrt() const { return true; }
    430431
    431432private:
  • trunk/JavaScriptCore/assembler/X86Assembler.h

    r57925 r58469  
    168168        OP2_SUBSD_VsdWsd    = 0x5C,
    169169        OP2_DIVSD_VsdWsd    = 0x5E,
     170        OP2_SQRTSD_VsdWsd   = 0x51,
    170171        OP2_XORPD_VpdWpd    = 0x57,
    171172        OP2_MOVD_VdEd       = 0x6E,
     
    13941395
    13951396#if !CPU(X86_64)
    1396     void movsd_mr(void* address, XMMRegisterID dst)
     1397    void movsd_mr(const void* address, XMMRegisterID dst)
    13971398    {
    13981399        m_formatter.prefix(PRE_SSE_F2);
     
    14601461        m_formatter.prefix(PRE_SSE_66);
    14611462        m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
     1463    }
     1464
     1465    void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst)
     1466    {
     1467        m_formatter.prefix(PRE_SSE_F2);
     1468        m_formatter.twoByteOp(OP2_SQRTSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
    14621469    }
    14631470
     
    17471754
    17481755#if !CPU(X86_64)
    1749         void twoByteOp(TwoByteOpcodeID opcode, int reg, void* address)
     1756        void twoByteOp(TwoByteOpcodeID opcode, int reg, const void* address)
    17501757        {
    17511758            m_buffer.ensureSpace(maxInstructionSize);
     
    20582065
    20592066#if !CPU(X86_64)
    2060         void memoryModRM(int reg, void* address)
     2067        void memoryModRM(int reg, const void* address)
    20612068        {
    20622069            // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
  • trunk/JavaScriptCore/create_hash_table

    r58317 r58469  
    279279            $thunkGenerator = "charAtThunkGenerator";
    280280        }
     281        if ($key eq "sqrt") {
     282            $thunkGenerator = "sqrtThunkGenerator";
     283        }
     284        if ($key eq "pow") {
     285            $thunkGenerator = "powThunkGenerator";
     286        }
    281287        print "   { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue THUNK_GENERATOR($thunkGenerator) },\n";
    282288        $i++;
  • trunk/JavaScriptCore/jit/JIT.h

    r58283 r58469  
    425425        void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg);
    426426#if USE(JSVALUE64)
    427         JIT::Jump emitJumpIfImmediateNumber(RegisterID);
    428         JIT::Jump emitJumpIfNotImmediateNumber(RegisterID);
    429427#else
    430428        JIT::Jump emitJumpIfImmediateNumber(RegisterID reg)
  • trunk/JavaScriptCore/jit/JITInlineMethods.h

    r58283 r58469  
    723723
    724724#if USE(JSVALUE64)
    725 ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateNumber(RegisterID reg)
    726 {
    727     return branchTestPtr(NonZero, reg, tagTypeNumberRegister);
    728 }
    729 ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateNumber(RegisterID reg)
    730 {
    731     return branchTestPtr(Zero, reg, tagTypeNumberRegister);
    732 }
    733725
    734726inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
  • trunk/JavaScriptCore/jit/JITOpcodes.cpp

    r57955 r58469  
    401401
    402402    trampolines->ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
    403     trampolines->ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk);
     403    trampolines->ctiNativeCallThunk = adoptRef(new NativeExecutable(JITCode(JITCode::HostFunction(trampolineAt(finalCode, nativeCallThunk)))));
    404404#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    405405    trampolines->ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin);
     
    19381938    trampolines->ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
    19391939    trampolines->ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
    1940     trampolines->ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk);
     1940    trampolines->ctiNativeCallThunk = adoptRef(new NativeExecutable(JITCode(JITCode::HostFunction(trampolineAt(finalCode, nativeCallThunk)))));
    19411941#if ENABLE(JIT_OPTIMIZE_MOD)
    19421942    trampolines->ctiSoftModulo = trampolineAt(finalCode, softModBegin);
  • trunk/JavaScriptCore/jit/JITStubs.h

    r58286 r58469  
    8080        MacroAssemblerCodePtr ctiVirtualCallLink;
    8181        MacroAssemblerCodePtr ctiVirtualCall;
    82         MacroAssemblerCodePtr ctiNativeCallThunk;
     82        RefPtr<NativeExecutable> ctiNativeCallThunk;
    8383        MacroAssemblerCodePtr ctiSoftModulo;
    8484    };
     
    276276        MacroAssemblerCodePtr ctiVirtualCallLink() { return m_trampolineStructure.ctiVirtualCallLink; }
    277277        MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; }
    278         MacroAssemblerCodePtr ctiNativeCallThunk() { return m_trampolineStructure.ctiNativeCallThunk; }
     278        NativeExecutable* ctiNativeCallThunk() { return m_trampolineStructure.ctiNativeCallThunk.get(); }
    279279        MacroAssemblerCodePtr ctiSoftModulo() { return m_trampolineStructure.ctiSoftModulo; }
    280280
  • trunk/JavaScriptCore/jit/JSInterfaceJIT.h

    r58283 r58469  
    6969        static const FPRegisterID fpRegT1 = X86Registers::xmm1;
    7070        static const FPRegisterID fpRegT2 = X86Registers::xmm2;
     71        static const FPRegisterID fpRegT3 = X86Registers::xmm3;
    7172#elif CPU(X86)
    7273        static const RegisterID returnValueRegister = X86Registers::eax;
     
    8788        static const FPRegisterID fpRegT1 = X86Registers::xmm1;
    8889        static const FPRegisterID fpRegT2 = X86Registers::xmm2;
     90        static const FPRegisterID fpRegT3 = X86Registers::xmm3;
    8991#elif CPU(ARM_THUMB2)
    9092        static const RegisterID returnValueRegister = ARMRegisters::r0;
     
    103105        static const FPRegisterID fpRegT1 = ARMRegisters::d1;
    104106        static const FPRegisterID fpRegT2 = ARMRegisters::d2;
     107        static const FPRegisterID fpRegT3 = ARMRegisters::d3;
    105108#elif CPU(ARM_TRADITIONAL)
    106109        static const RegisterID returnValueRegister = ARMRegisters::r0;
     
    127130        static const FPRegisterID fpRegT1 = ARMRegisters::d1;
    128131        static const FPRegisterID fpRegT2 = ARMRegisters::d2;
     132        static const FPRegisterID fpRegT3 = ARMRegisters::d3;
    129133#elif CPU(MIPS)
    130134        static const RegisterID returnValueRegister = MIPSRegisters::v0;
     
    149153        static const FPRegisterID fpRegT1 = MIPSRegisters::f6;
    150154        static const FPRegisterID fpRegT2 = MIPSRegisters::f8;
     155        static const FPRegisterID fpRegT2 = MIPSRegisters::f10;
    151156#else
    152157#error "JIT not supported on this platform."
     
    155160        inline Jump emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload);
    156161        inline Jump emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst);
     162        inline Jump emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch);
    157163
    158164#if USE(JSVALUE32_64)
     
    160166        inline Address tagFor(unsigned index, RegisterID base = callFrameRegister);
    161167#endif
     168
     169#if USE(JSVALUE32) || USE(JSVALUE64)
     170        Jump emitJumpIfImmediateNumber(RegisterID reg);
     171        Jump emitJumpIfNotImmediateNumber(RegisterID reg);
     172#endif
     173
    162174        inline Address payloadFor(unsigned index, RegisterID base = callFrameRegister);
    163175        inline Address addressFor(unsigned index, RegisterID base = callFrameRegister);
    164176    };
    165    
     177
    166178#if USE(JSVALUE32_64)
    167179    inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload)
     
    191203        return Address(base, (index * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
    192204    }
     205
     206    inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
     207    {
     208        loadPtr(tagFor(virtualRegisterIndex), scratch);
     209        Jump isDouble = branch32(Below, scratch, Imm32(JSValue::LowestTag));
     210        Jump notInt = branch32(NotEqual, scratch, Imm32(JSValue::Int32Tag));
     211        loadPtr(payloadFor(virtualRegisterIndex), scratch);
     212        convertInt32ToDouble(scratch, dst);
     213        Jump done = jump();
     214        isDouble.link(this);
     215        loadDouble(addressFor(virtualRegisterIndex), dst);
     216        done.link(this);
     217        return notInt;
     218    }   
    193219#endif
    194220
    195221#if USE(JSVALUE64)
     222    ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfImmediateNumber(RegisterID reg)
     223    {
     224        return branchTestPtr(NonZero, reg, tagTypeNumberRegister);
     225    }
     226    ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotImmediateNumber(RegisterID reg)
     227    {
     228        return branchTestPtr(Zero, reg, tagTypeNumberRegister);
     229    }
    196230    inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID dst)
    197231    {
     
    207241        return result;
    208242    }
     243
     244    inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
     245    {
     246        loadPtr(addressFor(virtualRegisterIndex), scratch);
     247        Jump notNumber = emitJumpIfNotImmediateNumber(scratch);
     248        Jump notInt = branchPtr(Below, scratch, tagTypeNumberRegister);
     249        convertInt32ToDouble(scratch, dst);
     250        Jump done = jump();
     251        notInt.link(this);
     252        addPtr(tagTypeNumberRegister, scratch);
     253        movePtrToDouble(scratch, dst);
     254        done.link(this);
     255        return notNumber;
     256    }
     257
    209258#endif
    210259
     
    222271        rshift32(Imm32(JSImmediate::IntegerPayloadShift), dst);
    223272        return result;
    224     }   
     273    }
     274
     275    inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned, FPRegisterID, RegisterID)
     276    {
     277        ASSERT_NOT_REACHED();
     278        return jump();
     279    }
    225280#endif
    226281
  • trunk/JavaScriptCore/jit/SpecializedThunkJIT.h

    r58317 r58469  
    4747        }
    4848       
     49        void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch)
     50        {
     51            unsigned src = argumentToVirtualRegister(argument);
     52            m_failures.append(emitLoadDouble(src, dst, scratch));
     53        }
     54       
    4955        void loadCellArgument(int argument, RegisterID dst)
    5056        {
     
    6066        }
    6167       
     68        void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget)
     69        {
     70            unsigned src = argumentToVirtualRegister(argument);
     71            failTarget = emitLoadInt32(src, dst);
     72        }
     73       
    6274        void loadInt32Argument(int argument, RegisterID dst)
    6375        {
    64             unsigned src = argumentToVirtualRegister(argument);
    65             m_failures.append(emitLoadInt32(src, dst));
     76            Jump conversionFailed;
     77            loadInt32Argument(argument, dst, conversionFailed);
     78            m_failures.append(conversionFailed);
    6679        }
    6780       
     
    7083            m_failures.append(failure);
    7184        }
     85
     86        void returnJSValue(RegisterID src)
     87        {
     88            if (src != regT0)
     89                move(src, regT0);
     90            loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister);
     91            ret();
     92        }
    7293       
     94        void returnDouble(FPRegisterID src)
     95        {
     96#if USE(JSVALUE64)
     97            moveDoubleToPtr(src, regT0);
     98            subPtr(tagTypeNumberRegister, regT0);
     99#elif USE(JSVALUE32_64)
     100            storeDouble(src, Address(stackPointerRegister, -(int)sizeof(double)));
     101            loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - sizeof(double)), regT1);
     102            loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - sizeof(double)), regT0);
     103#else
     104            UNUSED_PARAM(src);
     105            ASSERT_NOT_REACHED();
     106            m_failures.append(jump());
     107#endif
     108            loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister);
     109            ret();
     110        }
     111
    73112        void returnInt32(RegisterID src)
    74113        {
     
    92131        {
    93132            LinkBuffer patchBuffer(this, m_pool.get());
    94             patchBuffer.link(m_failures, CodeLocationLabel(m_globalData->jitStubs.ctiNativeCallThunk()));
     133            patchBuffer.link(m_failures, CodeLocationLabel(m_globalData->jitStubs.ctiNativeCallThunk()->generatedJITCode().addressForCall()));
    95134            return adoptRef(new NativeExecutable(patchBuffer.finalizeCode()));
    96135        }
     
    115154#endif
    116155        }
    117        
     156
    118157        void tagReturnAsJSCell()
    119158        {
  • trunk/JavaScriptCore/jit/ThunkGenerators.cpp

    r58317 r58469  
    9595}
    9696
     97PassRefPtr<NativeExecutable> sqrtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
     98{
     99#if USE(JSVALUE64) || USE(JSVALUE32_64)
     100    SpecializedThunkJIT jit(1, globalData, pool);
     101    if (!jit.supportsFloatingPointSqrt())
     102        return globalData->jitStubs.ctiNativeCallThunk();
     103
     104    jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
     105    jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
     106    jit.returnDouble(SpecializedThunkJIT::fpRegT0);
     107    return jit.finalize();
     108#else
     109    UNUSED_PARAM(pool);
     110    return globalData->jitStubs.ctiNativeCallThunk();
     111#endif
     112}
     113
     114static const double oneConstant = 1.0;
     115static const double negativeHalfConstant = -0.5;
     116
     117PassRefPtr<NativeExecutable> powThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
     118{
     119#if USE(JSVALUE64) || USE(JSVALUE32_64)
     120    SpecializedThunkJIT jit(2, globalData, pool);
     121    if (!jit.supportsFloatingPoint())
     122        return globalData->jitStubs.ctiNativeCallThunk();
     123
     124    jit.loadDouble(&oneConstant, SpecializedThunkJIT::fpRegT1);
     125    jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
     126    MacroAssembler::Jump nonIntExponent;
     127    jit.loadInt32Argument(1, SpecializedThunkJIT::regT0, nonIntExponent);
     128    jit.appendFailure(jit.branch32(MacroAssembler::LessThan, SpecializedThunkJIT::regT0, MacroAssembler::Imm32(0)));
     129   
     130    MacroAssembler::Jump exponentIsZero = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0);
     131    MacroAssembler::Label startLoop(jit.label());
     132
     133    MacroAssembler::Jump exponentIsEven = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0, MacroAssembler::Imm32(1));
     134    jit.mulDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
     135    exponentIsEven.link(&jit);
     136    jit.mulDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
     137    jit.rshift32(MacroAssembler::Imm32(1), SpecializedThunkJIT::regT0);
     138    jit.branchTest32(MacroAssembler::NonZero, SpecializedThunkJIT::regT0).linkTo(startLoop, &jit);
     139
     140    exponentIsZero.link(&jit);
     141    jit.returnDouble(SpecializedThunkJIT::fpRegT1);
     142
     143    if (jit.supportsFloatingPointSqrt()) {
     144        nonIntExponent.link(&jit);
     145        jit.loadDouble(&negativeHalfConstant, SpecializedThunkJIT::fpRegT3);
     146        jit.loadDoubleArgument(1, SpecializedThunkJIT::fpRegT2, SpecializedThunkJIT::regT0);
     147        jit.appendFailure(jit.branchDouble(MacroAssembler::DoubleLessThanOrEqual, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1));
     148        jit.appendFailure(jit.branchDouble(MacroAssembler::DoubleNotEqual, SpecializedThunkJIT::fpRegT2, SpecializedThunkJIT::fpRegT3));
     149        jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
     150        jit.divDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
     151        jit.returnDouble(SpecializedThunkJIT::fpRegT1);
     152    } else
     153        jit.appendFailure(nonIntExponent);
     154
     155    return jit.finalize();
     156#else
     157    UNUSED_PARAM(pool);
     158    return globalData->jitStubs.ctiNativeCallThunk();
     159#endif
     160}
     161
    97162}
    98163
  • trunk/JavaScriptCore/jit/ThunkGenerators.h

    r58317 r58469  
    3939    PassRefPtr<NativeExecutable> charAtThunkGenerator(JSGlobalData*, ExecutablePool*);
    4040    PassRefPtr<NativeExecutable> fromCharCodeThunkGenerator(JSGlobalData*, ExecutablePool*);
     41    PassRefPtr<NativeExecutable> sqrtThunkGenerator(JSGlobalData*, ExecutablePool*);
     42    PassRefPtr<NativeExecutable> powThunkGenerator(JSGlobalData*, ExecutablePool*);
    4143}
    4244#endif
  • trunk/JavaScriptCore/runtime/Executable.h

    r58286 r58469  
    8686            : ExecutableBase(NUM_PARAMETERS_IS_HOST)
    8787        {
    88             m_jitCode = JITCode(JITCode::HostFunction(exec->globalData().jitStubs.ctiNativeCallThunk()));
     88            m_jitCode = exec->globalData().jitStubs.ctiNativeCallThunk()->m_jitCode;
    8989        }
    9090        NativeExecutable(JITCode thunk)
  • trunk/JavaScriptCore/runtime/JSFunction.cpp

    r58286 r58469  
    7777    : Base(&exec->globalData(), structure, name)
    7878#if ENABLE(JIT)
    79     , m_executable(adoptRef(new NativeExecutable(exec)))
     79    , m_executable(exec->globalData().jitStubs.ctiNativeCallThunk())
    8080#endif
    8181{
Note: See TracChangeset for help on using the changeset viewer.