Changeset 144043 in webkit


Ignore:
Timestamp:
Feb 26, 2013 5:04:28 AM (11 years ago)
Author:
jocelyn.turcotte@digia.com
Message:

Implement JIT on Windows 64 bits
https://bugs.webkit.org/show_bug.cgi?id=107965

Reviewed by Simon Hausmann.

Source/JavaScriptCore:

  1. MSVC doesn't support inline assembly for 64 bits, implements the trampoline in a separate ASM file.
  1. Windows 64 bits has a different calling convention than other OSes following the AMD64 ABI.

Differences that we have to handle here:

  • Registers passed parameters are RCX, RDX, R8 and R9 instead of RDI, RSI, RDX, RCX, R8 and R9
  • RDI and RSI must be preserved by callee
  • Only return values <= 8 bytes can be returned by register (RDX can't be used to return a second word)
  • There is no red-zone after RIP on the stack, but instead 4 reserved words before it
  • Target.pri:
  • jit/JITStubs.cpp:
  • jit/JITStubs.h:

(JSC):
(JITStackFrame):
(JSC::JITStackFrame::returnAddressSlot):

  • jit/JITStubsMSVC64.asm: Added.
  • jit/JSInterfaceJIT.h:

(JSInterfaceJIT):

  • jit/ThunkGenerators.cpp:

(JSC::nativeForGenerator):

  • yarr/YarrJIT.cpp:

(YarrGenerator):
(JSC::Yarr::YarrGenerator::generateEnter):
(JSC::Yarr::YarrGenerator::generateReturn):

Source/WTF:

  • wtf/Platform.h:
Location:
trunk/Source
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r144026 r144043  
     12013-02-26  Jocelyn Turcotte  <jocelyn.turcotte@digia.com>
     2
     3        Implement JIT on Windows 64 bits
     4        https://bugs.webkit.org/show_bug.cgi?id=107965
     5
     6        Reviewed by Simon Hausmann.
     7
     8        1. MSVC doesn't support inline assembly for 64 bits, implements the trampoline in a separate ASM file.
     9
     10        2. Windows 64 bits has a different calling convention than other OSes following the AMD64 ABI.
     11        Differences that we have to handle here:
     12        - Registers passed parameters are RCX, RDX, R8 and R9 instead of RDI, RSI, RDX, RCX, R8 and R9
     13        - RDI and RSI must be preserved by callee
     14        - Only return values <= 8 bytes can be returned by register (RDX can't be used to return a second word)
     15        - There is no red-zone after RIP on the stack, but instead 4 reserved words before it
     16
     17        * Target.pri:
     18        * jit/JITStubs.cpp:
     19        * jit/JITStubs.h:
     20        (JSC):
     21        (JITStackFrame):
     22        (JSC::JITStackFrame::returnAddressSlot):
     23        * jit/JITStubsMSVC64.asm: Added.
     24        * jit/JSInterfaceJIT.h:
     25        (JSInterfaceJIT):
     26        * jit/ThunkGenerators.cpp:
     27        (JSC::nativeForGenerator):
     28        * yarr/YarrJIT.cpp:
     29        (YarrGenerator):
     30        (JSC::Yarr::YarrGenerator::generateEnter):
     31        (JSC::Yarr::YarrGenerator::generateReturn):
     32
    1332013-02-26  Oliver Hunt  <oliver@apple.com>
    234
  • trunk/Source/JavaScriptCore/Target.pri

    r143654 r144043  
    336336}
    337337
     338win32:!win32-g++*:isEqual(QT_ARCH, "x86_64"):{
     339    asm_compiler.commands = ml64 /c
     340    asm_compiler.commands +=  /Fo ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
     341    asm_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
     342    asm_compiler.input = ASM_SOURCES
     343    asm_compiler.variable_out = OBJECTS
     344    asm_compiler.name = compiling[asm] ${QMAKE_FILE_IN}
     345    silent:asm_compiler.commands = @echo compiling[asm] ${QMAKE_FILE_IN} && $$asm_compiler.commands
     346    QMAKE_EXTRA_COMPILERS += asm_compiler
     347
     348    ASM_SOURCES += jit/JITStubsMSVC64.asm
     349}
     350
    338351HEADERS += $$files(*.h, true)
    339352
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r141651 r144043  
    437437    "ret" "\n"
    438438);
     439
     440#elif COMPILER(MSVC) && CPU(X86_64)
     441
     442// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
     443// need to change the assembly trampolines in JITStubsMSVC64.asm to match.
     444COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
     445COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x58, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
    439446
    440447#else
  • trunk/Source/JavaScriptCore/jit/JITStubs.h

    r139541 r144043  
    8888};
    8989   
    90 #if CPU(X86_64)
     90#if !OS(WINDOWS) && CPU(X86_64)
    9191struct JITStackFrame {
    9292    void* reserved; // Unused
     
    108108    void* savedRBP;
    109109    void* savedRIP;
     110
     111    // When JIT code makes a call, it pushes its return address just below the rest of the stack.
     112    ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast<ReturnAddressPtr*>(this) - 1; }
     113};
     114#elif OS(WINDOWS) && CPU(X86_64)
     115struct JITStackFrame {
     116    void* shadow[4]; // Shadow space reserved for a callee's parameters home addresses
     117    void* reserved; // Unused, also maintains the 16-bytes stack alignment
     118    JITStubArg args[6];
     119
     120    void* savedRBX;
     121    void* savedR15;
     122    void* savedR14;
     123    void* savedR13;
     124    void* savedR12;
     125    void* savedRBP;
     126    void* savedRIP;
     127
     128    // Home addresses for our register passed parameters
     129    // http://msdn.microsoft.com/en-us/library/ew5tede7.aspx
     130    void* code;
     131    JSStack* stack;
     132    CallFrame* callFrame;
     133    void* unused1;
     134
     135    // Passed on the stack
     136    void* unused2;
     137    JSGlobalData* globalData;
    110138
    111139    // When JIT code makes a call, it pushes its return address just below the rest of the stack.
  • trunk/Source/JavaScriptCore/jit/JSInterfaceJIT.h

    r143247 r144043  
    5858        static const RegisterID returnValueRegister = X86Registers::eax;
    5959        static const RegisterID cachedResultRegister = X86Registers::eax;
     60#if !OS(WINDOWS)
    6061        static const RegisterID firstArgumentRegister = X86Registers::edi;
    61        
     62#else
     63        static const RegisterID firstArgumentRegister = X86Registers::ecx;
     64#endif
     65
    6266#if ENABLE(VALUE_PROFILER)
    6367        static const RegisterID bucketCounterRegister = X86Registers::r10;
    6468#endif
    65        
     69
    6670        static const RegisterID timeoutCheckRegister = X86Registers::r12;
    6771        static const RegisterID callFrameRegister = X86Registers::r13;
    6872        static const RegisterID tagTypeNumberRegister = X86Registers::r14;
    6973        static const RegisterID tagMaskRegister = X86Registers::r15;
    70        
     74
    7175        static const RegisterID regT0 = X86Registers::eax;
    7276        static const RegisterID regT1 = X86Registers::edx;
    7377        static const RegisterID regT2 = X86Registers::ecx;
    7478        static const RegisterID regT3 = X86Registers::ebx;
    75        
     79
    7680        static const FPRegisterID fpRegT0 = X86Registers::xmm0;
    7781        static const FPRegisterID fpRegT1 = X86Registers::xmm1;
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r138609 r144043  
    265265    jit.emitPutToCallFrameHeader(JSInterfaceJIT::regT1, JSStack::ReturnPC);
    266266
     267#if !OS(WINDOWS)
    267268    // Calling convention:      f(edi, esi, edx, ecx, ...);
    268269    // Host function signature: f(ExecState*);
     
    277278
    278279    jit.addPtr(JSInterfaceJIT::TrustedImm32(16 - sizeof(int64_t)), JSInterfaceJIT::stackPointerRegister);
     280#else
     281    // Calling convention:      f(ecx, edx, r8, r9, ...);
     282    // Host function signature: f(ExecState*);
     283    jit.move(JSInterfaceJIT::callFrameRegister, X86Registers::ecx);
     284
     285    // Leave space for the callee parameter home addresses and align the stack.
     286    jit.subPtr(JSInterfaceJIT::TrustedImm32(4 * sizeof(int64_t) + 16 - sizeof(int64_t)), JSInterfaceJIT::stackPointerRegister);
     287
     288    jit.emitGetFromCallFrameHeaderPtr(JSStack::Callee, X86Registers::edx);
     289    jit.loadPtr(JSInterfaceJIT::Address(X86Registers::edx, JSFunction::offsetOfExecutable()), X86Registers::r9);
     290    jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
     291    jit.call(JSInterfaceJIT::Address(X86Registers::r9, executableOffsetToFunction));
     292
     293    jit.addPtr(JSInterfaceJIT::TrustedImm32(4 * sizeof(int64_t) + 16 - sizeof(int64_t)), JSInterfaceJIT::stackPointerRegister);
     294#endif
    279295
    280296#elif CPU(ARM)
  • trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp

    r143018 r144043  
    8888    static const RegisterID returnRegister2 = X86Registers::edx;
    8989#elif CPU(X86_64)
     90#if !OS(WINDOWS)
    9091    static const RegisterID input = X86Registers::edi;
    9192    static const RegisterID index = X86Registers::esi;
    9293    static const RegisterID length = X86Registers::edx;
    9394    static const RegisterID output = X86Registers::ecx;
     95#else
     96    // If the return value doesn't fit in 64bits, its destination is pointed by rcx and the parameters are shifted.
     97    // http://msdn.microsoft.com/en-us/library/7572ztz4.aspx
     98    COMPILE_ASSERT(sizeof(MatchResult) > sizeof(void*), MatchResult_does_not_fit_in_64bits);
     99    static const RegisterID input = X86Registers::edx;
     100    static const RegisterID index = X86Registers::r8;
     101    static const RegisterID length = X86Registers::r9;
     102    static const RegisterID output = X86Registers::r10;
     103#endif
    94104
    95105    static const RegisterID regT0 = X86Registers::eax;
     
    25152525        move(stackPointerRegister, X86Registers::ebp);
    25162526        push(X86Registers::ebx);
     2527#if OS(WINDOWS)
     2528        if (compileMode == IncludeSubpatterns)
     2529            loadPtr(Address(X86Registers::ebp, 6 * sizeof(void*)), output);
     2530#endif
    25172531#elif CPU(X86)
    25182532        push(X86Registers::ebp);
     
    25532567    {
    25542568#if CPU(X86_64)
     2569#if OS(WINDOWS)
     2570        // Store the return value in the allocated space pointed by rcx.
     2571        store64(returnRegister, Address(X86Registers::ecx));
     2572        store64(returnRegister2, Address(X86Registers::ecx, sizeof(void*)));
     2573        move(X86Registers::ecx, returnRegister);
     2574#endif
    25552575        pop(X86Registers::ebx);
    25562576        pop(X86Registers::ebp);
  • trunk/Source/WTF/ChangeLog

    r144020 r144043  
     12013-02-26  Jocelyn Turcotte  <jocelyn.turcotte@digia.com>
     2
     3        Implement JIT on Windows 64 bits
     4        https://bugs.webkit.org/show_bug.cgi?id=107965
     5
     6        Reviewed by Simon Hausmann.
     7
     8        * wtf/Platform.h:
     9
    1102013-02-26  Oliver Hunt  <oliver@apple.com>
    211
  • trunk/Source/WTF/wtf/Platform.h

    r143247 r144043  
    757757#endif
    758758
    759 /* JIT is not implemented for Windows 64-bit */
    760 #if !defined(ENABLE_JIT) && OS(WINDOWS) && CPU(X86_64)
    761 #define ENABLE_JIT 0
    762 #define ENABLE_YARR_JIT 0
    763 #endif
    764 
    765759#if !defined(ENABLE_JIT) && CPU(SH4) && PLATFORM(QT)
    766760#define ENABLE_JIT 1
     
    907901   On x86-64 we use a single fixed mmap, on other platforms we mmap on demand. */
    908902#if ENABLE(ASSEMBLER)
    909 #if CPU(X86_64) || PLATFORM(IOS)
     903#if CPU(X86_64) && !OS(WINDOWS) || PLATFORM(IOS)
    910904#define ENABLE_EXECUTABLE_ALLOCATOR_FIXED 1
    911905#else
Note: See TracChangeset for help on using the changeset viewer.