js/src/assembler/TestMain.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 // A short test program with which to experiment with the assembler.
     8 //satisfies  CPU(X86_64)
     9 //#define WTF_CPU_X86_64
    11 // satisfies  ENABLE(ASSEMBLER)
    12 #define ENABLE_ASSEMBLER 1
    14 // satisfies  ENABLE(JIT)
    15 #define ENABLE_JIT 1
    17 #define USE_SYSTEM_MALLOC 1
    18 // leads to FORCE_SYSTEM_MALLOC in wtf/FastMalloc.cpp
    20 #include "assembler/jit/ExecutableAllocator.h"
    21 #include "assembler/assembler/LinkBuffer.h"
    22 #include "assembler/assembler/CodeLocation.h"
    23 #include "assembler/assembler/RepatchBuffer.h"
    25 #include "assembler/assembler/MacroAssembler.h"
    27 #include <stdio.h>
    29 /////////////////////////////////////////////////////////////////
    30 // Temporary scaffolding for selecting the arch
    31 #undef ARCH_x86
    32 #undef ARCH_amd64
    33 #undef ARCH_arm
    35 #if defined(__APPLE__) && defined(__i386__)
    36 #  define ARCH_x86 1
    37 #elif defined(__APPLE__) && defined(__x86_64__)
    38 #  define ARCH_amd64 1
    39 #elif defined(__linux__) && defined(__i386__)
    40 #  define ARCH_x86 1
    41 #elif defined(__linux__) && defined(__x86_64__)
    42 #  define ARCH_amd64 1
    43 #elif defined(__linux__) && defined(__arm__)
    44 #  define ARCH_arm 1
    45 #elif defined(_MSC_VER) && defined(_M_IX86)
    46 #  define ARCH_x86 1
    47 #endif
    48 /////////////////////////////////////////////////////////////////
    50 // just somewhere convenient to put a breakpoint, before
    51 // running gdb
    52 #if WTF_COMPILER_GCC
    53 __attribute__((noinline))
    54 #endif
    55 void pre_run ( void ) { }
    57 /////////////////////////////////////////////////////////////////
    58 //// test1 (simple straight line code)
    59 #if WTF_COMPILER_GCC
    61 void test1 ( void )
    62 {
    63   printf("\n------------ Test 1 (straight line code) ------------\n\n" );
    65   // Create new assembler
    66   JSC::MacroAssembler* am = new JSC::MacroAssembler();
    68 #if defined(ARCH_amd64)
    69   JSC::X86Registers::RegisterID areg = JSC::X86Registers::r15;
    70   // dump some instructions into it
    71   //    xor    %r15,%r15
    72   //    add    $0x7b,%r15
    73   //    add    $0x141,%r15
    74   //    retq
    75   am->xorPtr(areg,areg);
    76   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
    77   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
    78   am->ret();
    79 #endif
    81 #if defined(ARCH_x86)
    82   JSC::X86Registers::RegisterID areg = JSC::X86Registers::edi;
    83   // dump some instructions into it
    84   //    xor    %edi,%edi
    85   //    add    $0x7b,%edi
    86   //    add    $0x141,%edi
    87   //    ret
    88   am->xorPtr(areg,areg);
    89   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
    90   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
    91   am->ret();
    92 #endif
    94 #if defined(ARCH_arm)
    95   JSC::ARMRegisters::RegisterID areg = JSC::ARMRegisters::r8;
    96   //    eors    r8, r8, r8
    97   //    adds    r8, r8, #123    ; 0x7b
    98   //    mov     r3, #256        ; 0x100
    99   //    orr     r3, r3, #65     ; 0x41
   100   //    adds    r8, r8, r3
   101   //    mov     pc, lr
   102   am->xorPtr(areg,areg);
   103   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
   104   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
   105   am->ret();
   106 #endif
   108   // prepare a link buffer, into which we can copy the completed insns
   109   JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
   111   // intermediate step .. get the pool suited for the size of code in 'am'
   112   //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
   113   JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
   115   // constructor for LinkBuffer asks ep to allocate r-x memory,
   116   // then copies it there.
   117   JSC::LinkBuffer patchBuffer(am, ep, JSC::METHOD_CODE);
   119   // finalize
   120   JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
   122   // cr now holds a pointer to the final runnable code.
   123   void* entry = cr.m_code.executableAddress();
   125   printf("disas %p %p\n",
   126          entry, (char*)entry + cr.m_size);
   127   pre_run();
   129   unsigned long result = 0x55555555;
   131 #if defined(ARCH_amd64)
   132   // call the generated piece of code.  It puts its result in r15.
   133   __asm__ __volatile__(
   134      "callq *%1"           "\n\t"
   135      "movq  %%r15, %0"     "\n"
   136      :/*out*/   "=r"(result)
   137      :/*in*/    "r"(entry)
   138      :/*trash*/ "r15","cc"
   139   );
   140 #endif
   141 #if defined(ARCH_x86)
   142   // call the generated piece of code.  It puts its result in edi.
   143   __asm__ __volatile__(
   144      "calll *%1"           "\n\t"
   145      "movl  %%edi, %0"     "\n"
   146      :/*out*/   "=r"(result)
   147      :/*in*/    "r"(entry)
   148      :/*trash*/ "edi","cc"
   149   );
   150 #endif
   151 #if defined(ARCH_arm)
   152   // call the generated piece of code.  It puts its result in r8.
   153   __asm__ __volatile__(
   154      "blx   %1"            "\n\t"
   155      "mov   %0, %%r8"      "\n"
   156      :/*out*/   "=r"(result)
   157      :/*in*/    "r"(entry)
   158      :/*trash*/ "r8","cc"
   159   );
   160 #endif
   162   printf("\n");
   163   printf("value computed is %lu (expected 444)\n", result);
   164   printf("\n");
   166   delete eal;
   167   delete am;
   168 }
   170 #endif /* WTF_COMPILER_GCC */
   172 /////////////////////////////////////////////////////////////////
   173 //// test2 (a simple counting-down loop)
   174 #if WTF_COMPILER_GCC
   176 void test2 ( void )
   177 {
   178   printf("\n------------ Test 2 (mini loop) ------------\n\n" );
   180   // Create new assembler
   181   JSC::MacroAssembler* am = new JSC::MacroAssembler();
   183 #if defined(ARCH_amd64)
   184   JSC::X86Registers::RegisterID areg = JSC::X86Registers::r15;
   185   //    xor    %r15,%r15
   186   //    add    $0x7b,%r15
   187   //    add    $0x141,%r15
   188   //    sub    $0x1,%r15
   189   //    mov    $0x0,%r11
   190   //    cmp    %r11,%r15
   191   //    jne    0x7ff6d3e6a00e
   192   //    retq
   193   // so r15 always winds up being zero
   194   am->xorPtr(areg,areg);
   195   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
   196   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
   198   JSC::MacroAssembler::Label loopHeadLabel(am);
   199   am->subPtr(JSC::MacroAssembler::Imm32(1), areg);
   201   JSC::MacroAssembler::Jump j
   202      = am->branchPtr(JSC::MacroAssembler::NotEqual,
   203                      areg, JSC::MacroAssembler::ImmPtr(0));
   204   j.linkTo(loopHeadLabel, am);
   206   am->ret();
   207 #endif
   209 #if defined(ARCH_x86)
   210   JSC::X86Registers::RegisterID areg = JSC::X86Registers::edi;
   211   //    xor    %edi,%edi
   212   //    add    $0x7b,%edi
   213   //    add    $0x141,%edi
   214   //    sub    $0x1,%edi
   215   //    test   %edi,%edi
   216   //    jne    0xf7f9700b
   217   //    ret
   218   // so edi always winds up being zero
   219   am->xorPtr(areg,areg);
   220   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
   221   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
   223   JSC::MacroAssembler::Label loopHeadLabel(am);
   224   am->subPtr(JSC::MacroAssembler::Imm32(1), areg);
   226   JSC::MacroAssembler::Jump j
   227      = am->branchPtr(JSC::MacroAssembler::NotEqual,
   228                      areg, JSC::MacroAssembler::ImmPtr(0));
   229   j.linkTo(loopHeadLabel, am);
   231   am->ret();
   232 #endif
   234 #if defined(ARCH_arm)
   235   JSC::ARMRegisters::RegisterID areg = JSC::ARMRegisters::r8;
   236   //    eors    r8, r8, r8
   237   //    adds    r8, r8, #123    ; 0x7b
   238   //    mov     r3, #256        ; 0x100
   239   //    orr     r3, r3, #65     ; 0x41
   240   //    adds    r8, r8, r3
   241   //    subs    r8, r8, #1      ; 0x1
   242   //    ldr     r3, [pc, #8]    ; 0x40026028
   243   //    cmp     r8, r3
   244   //    bne     0x40026014
   245   //    mov     pc, lr
   246   //    andeq   r0, r0, r0         // DATA (0)
   247   //    andeq   r0, r0, r4, lsl r0 // DATA (?? what's this for?)
   248   // so r8 always winds up being zero
   249   am->xorPtr(areg,areg);
   250   am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
   251   am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
   253   JSC::MacroAssembler::Label loopHeadLabel(am);
   254   am->subPtr(JSC::MacroAssembler::Imm32(1), areg);
   256   JSC::MacroAssembler::Jump j
   257      = am->branchPtr(JSC::MacroAssembler::NotEqual,
   258                      areg, JSC::MacroAssembler::ImmPtr(0));
   259   j.linkTo(loopHeadLabel, am);
   261   am->ret();
   262 #endif
   264   // prepare a link buffer, into which we can copy the completed insns
   265   JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
   267   // intermediate step .. get the pool suited for the size of code in 'am'
   268   //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
   269   JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
   271   // constructor for LinkBuffer asks ep to allocate r-x memory,
   272   // then copies it there.
   273   JSC::LinkBuffer patchBuffer(am, ep, JSC::METHOD_CODE);
   275   // finalize
   276   JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
   278   // cr now holds a pointer to the final runnable code.
   279   void* entry = cr.m_code.executableAddress();
   281   printf("disas %p %p\n",
   282          entry, (char*)entry + cr.m_size);
   283   pre_run();
   285   unsigned long result = 0x55555555;
   287 #if defined(ARCH_amd64)
   288   // call the generated piece of code.  It puts its result in r15.
   289   __asm__ __volatile__(
   290      "callq *%1"           "\n\t"
   291      "movq  %%r15, %0"     "\n"
   292      :/*out*/   "=r"(result)
   293      :/*in*/    "r"(entry)
   294      :/*trash*/ "r15","cc"
   295   );
   296 #endif
   297 #if defined(ARCH_x86)
   298   // call the generated piece of code.  It puts its result in edi.
   299   __asm__ __volatile__(
   300      "calll *%1"           "\n\t"
   301      "movl  %%edi, %0"     "\n"
   302      :/*out*/   "=r"(result)
   303      :/*in*/    "r"(entry)
   304      :/*trash*/ "edi","cc"
   305   );
   306 #endif
   307 #if defined(ARCH_arm)
   308   // call the generated piece of code.  It puts its result in r8.
   309   __asm__ __volatile__(
   310      "blx   %1"            "\n\t"
   311      "mov   %0, %%r8"      "\n"
   312      :/*out*/   "=r"(result)
   313      :/*in*/    "r"(entry)
   314      :/*trash*/ "r8","cc"
   315   );
   316 #endif
   318   printf("\n");
   319   printf("value computed is %lu (expected 0)\n", result);
   320   printf("\n");
   322   delete eal;
   323   delete am;
   324 }
   326 #endif /* WTF_COMPILER_GCC */
   328 /////////////////////////////////////////////////////////////////
   329 //// test3 (if-then-else)
   330 #if WTF_COMPILER_GCC
   332 void test3 ( void )
   333 {
   334   printf("\n------------ Test 3 (if-then-else) ------------\n\n" );
   336   // Create new assembler
   337   JSC::MacroAssembler* am = new JSC::MacroAssembler();
   339 #if defined(ARCH_amd64)
   340   JSC::X86Registers::RegisterID areg = JSC::X86Registers::r15;
   341   //    mov    $0x64,%r15d
   342   //    mov    $0x0,%r11
   343   //    cmp    %r11,%r15
   344   //    jne    0x7ff6d3e6a024
   345   //    mov    $0x40,%r15d
   346   //    jmpq   0x7ff6d3e6a02a
   347   //    mov    $0x4,%r15d
   348   //    retq
   349   // so r15 ends up being 4
   351   // put a value in reg
   352   am->move(JSC::MacroAssembler::Imm32(100), areg);
   354   // test, and conditionally jump to 'else' branch
   355   JSC::MacroAssembler::Jump jToElse
   356     = am->branchPtr(JSC::MacroAssembler::NotEqual,
   357                     areg, JSC::MacroAssembler::ImmPtr(0));
   359   // 'then' branch
   360   am->move(JSC::MacroAssembler::Imm32(64), areg);
   361   JSC::MacroAssembler::Jump jToAfter
   362     = am->jump();
   364   // 'else' branch
   365   JSC::MacroAssembler::Label elseLbl(am);
   366   am->move(JSC::MacroAssembler::Imm32(4), areg);
   368   // after
   369   JSC::MacroAssembler::Label afterLbl(am);
   371   am->ret();
   372 #endif
   374 #if defined(ARCH_x86)
   375   JSC::X86Registers::RegisterID areg = JSC::X86Registers::edi;
   376   //    mov    $0x64,%edi
   377   //    test   %edi,%edi
   378   //    jne    0xf7f22017
   379   //    mov    $0x40,%edi
   380   //    jmp    0xf7f2201c
   381   //    mov    $0x4,%edi
   382   //    ret
   383   // so edi ends up being 4
   385   // put a value in reg
   386   am->move(JSC::MacroAssembler::Imm32(100), areg);
   388   // test, and conditionally jump to 'else' branch
   389   JSC::MacroAssembler::Jump jToElse
   390     = am->branchPtr(JSC::MacroAssembler::NotEqual,
   391                     areg, JSC::MacroAssembler::ImmPtr(0));
   393   // 'then' branch
   394   am->move(JSC::MacroAssembler::Imm32(64), areg);
   395   JSC::MacroAssembler::Jump jToAfter
   396     = am->jump();
   398   // 'else' branch
   399   JSC::MacroAssembler::Label elseLbl(am);
   400   am->move(JSC::MacroAssembler::Imm32(4), areg);
   402   // after
   403   JSC::MacroAssembler::Label afterLbl(am);
   405   am->ret();
   406 #endif
   408 #if defined(ARCH_arm)
   409   JSC::ARMRegisters::RegisterID areg = JSC::ARMRegisters::r8;
   410   //    mov     r8, #100        ; 0x64
   411   //    ldr     r3, [pc, #20]   ; 0x40026020
   412   //    cmp     r8, r3
   413   //    bne     0x40026018
   414   //    mov     r8, #64 ; 0x40
   415   //    b       0x4002601c
   416   //    mov     r8, #4  ; 0x4
   417   //    mov     pc, lr
   418   //    andeq   r0, r0, r0           // DATA
   419   //    andeq   r0, r0, r8, lsl r0   // DATA
   420   //    andeq   r0, r0, r12, lsl r0  // DATA
   421   //    ldr     r3, [r3, -r3]        // DATA
   422   // so r8 ends up being 4
   424   // put a value in reg
   425   am->move(JSC::MacroAssembler::Imm32(100), areg);
   427   // test, and conditionally jump to 'else' branch
   428   JSC::MacroAssembler::Jump jToElse
   429     = am->branchPtr(JSC::MacroAssembler::NotEqual,
   430                     areg, JSC::MacroAssembler::ImmPtr(0));
   432   // 'then' branch
   433   am->move(JSC::MacroAssembler::Imm32(64), areg);
   434   JSC::MacroAssembler::Jump jToAfter
   435     = am->jump();
   437   // 'else' branch
   438   JSC::MacroAssembler::Label elseLbl(am);
   439   am->move(JSC::MacroAssembler::Imm32(4), areg);
   441   // after
   442   JSC::MacroAssembler::Label afterLbl(am);
   444   am->ret();
   445 #endif
   447   // set branch targets appropriately
   448   jToElse.linkTo(elseLbl, am);
   449   jToAfter.linkTo(afterLbl, am);
   451   // prepare a link buffer, into which we can copy the completed insns
   452   JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
   454   // intermediate step .. get the pool suited for the size of code in 'am'
   455   //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
   456   JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
   458   // constructor for LinkBuffer asks ep to allocate r-x memory,
   459   // then copies it there.
   460   JSC::LinkBuffer patchBuffer(am, ep, JSC::METHOD_CODE);
   462   // finalize
   463   JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
   465   // cr now holds a pointer to the final runnable code.
   466   void* entry = cr.m_code.executableAddress();
   468   printf("disas %p %p\n",
   469          entry, (char*)entry + cr.m_size);
   470   pre_run();
   472   unsigned long result = 0x55555555;
   474 #if defined(ARCH_amd64)
   475   // call the generated piece of code.  It puts its result in r15.
   476   __asm__ __volatile__(
   477      "callq *%1"           "\n\t"
   478      "movq  %%r15, %0"     "\n"
   479      :/*out*/   "=r"(result)
   480      :/*in*/    "r"(entry)
   481      :/*trash*/ "r15","cc"
   482   );
   483 #endif
   484 #if defined(ARCH_x86)
   485   // call the generated piece of code.  It puts its result in edi.
   486   __asm__ __volatile__(
   487      "calll *%1"           "\n\t"
   488      "movl  %%edi, %0"     "\n"
   489      :/*out*/   "=r"(result)
   490      :/*in*/    "r"(entry)
   491      :/*trash*/ "edi","cc"
   492   );
   493 #endif
   494 #if defined(ARCH_arm)
   495   // call the generated piece of code.  It puts its result in r8.
   496   __asm__ __volatile__(
   497      "blx   %1"            "\n\t"
   498      "mov   %0, %%r8"      "\n"
   499      :/*out*/   "=r"(result)
   500      :/*in*/    "r"(entry)
   501      :/*trash*/ "r8","cc"
   502   );
   503 #endif
   505   printf("\n");
   506   printf("value computed is %lu (expected 4)\n", result);
   507   printf("\n");
   509   delete eal;
   510   delete am;
   511 }
   513 #endif /* WTF_COMPILER_GCC */
   515 /////////////////////////////////////////////////////////////////
   516 //// test4 (callable function)
   518 void test4 ( void )
   519 {
   520   printf("\n------------ Test 4 (callable fn) ------------\n\n" );
   522   // Create new assembler
   523   JSC::MacroAssembler* am = new JSC::MacroAssembler();
   525 #if defined(ARCH_amd64)
   526   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
   527   //    push   %rbp
   528   //    mov    %rsp,%rbp
   529   //    push   %rbx
   530   //    push   %r12
   531   //    push   %r13
   532   //    push   %r14
   533   //    push   %r15
   534   //    xor    %rax,%rax
   535   //    add    $0x7b,%rax
   536   //    add    $0x141,%rax
   537   //    pop    %r15
   538   //    pop    %r14
   539   //    pop    %r13
   540   //    pop    %r12
   541   //    pop    %rbx
   542   //    mov    %rbp,%rsp
   543   //    pop    %rbp
   544   //    retq
   545   // callable as a normal function, returns 444
   547   JSC::X86Registers::RegisterID rreg = JSC::X86Registers::eax;
   548   am->push(JSC::X86Registers::ebp);
   549   am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
   550   am->push(JSC::X86Registers::ebx);
   551   am->push(JSC::X86Registers::r12);
   552   am->push(JSC::X86Registers::r13);
   553   am->push(JSC::X86Registers::r14);
   554   am->push(JSC::X86Registers::r15);
   556   am->xorPtr(rreg,rreg);
   557   am->addPtr(JSC::MacroAssembler::Imm32(123), rreg);
   558   am->addPtr(JSC::MacroAssembler::Imm32(321), rreg);
   560   am->pop(JSC::X86Registers::r15);
   561   am->pop(JSC::X86Registers::r14);
   562   am->pop(JSC::X86Registers::r13);
   563   am->pop(JSC::X86Registers::r12);
   564   am->pop(JSC::X86Registers::ebx);
   565   am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
   566   am->pop(JSC::X86Registers::ebp);
   567   am->ret();
   568 #endif
   570 #if defined(ARCH_x86)
   571   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
   572   //    push   %ebp
   573   //    mov    %esp,%ebp
   574   //    push   %ebx
   575   //    push   %esi
   576   //    push   %edi
   577   //    xor    %eax,%eax
   578   //    add    $0x7b,%eax
   579   //    add    $0x141,%eax
   580   //    pop    %edi
   581   //    pop    %esi
   582   //    pop    %ebx
   583   //    mov    %ebp,%esp
   584   //    pop    %ebp
   585   //    ret
   586   // callable as a normal function, returns 444
   588   JSC::X86Registers::RegisterID rreg = JSC::X86Registers::eax;
   590   am->push(JSC::X86Registers::ebp);
   591   am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
   592   am->push(JSC::X86Registers::ebx);
   593   am->push(JSC::X86Registers::esi);
   594   am->push(JSC::X86Registers::edi);
   596   am->xorPtr(rreg,rreg);
   597   am->addPtr(JSC::MacroAssembler::Imm32(123), rreg);
   598   am->addPtr(JSC::MacroAssembler::Imm32(321), rreg);
   600   am->pop(JSC::X86Registers::edi);
   601   am->pop(JSC::X86Registers::esi);
   602   am->pop(JSC::X86Registers::ebx);
   603   am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
   604   am->pop(JSC::X86Registers::ebp);
   605   am->ret();
   606 #endif
   608 #if defined(ARCH_arm)
   609   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
   610   //    push    {r4}            ; (str r4, [sp, #-4]!)
   611   //    push    {r5}            ; (str r5, [sp, #-4]!)
   612   //    push    {r6}            ; (str r6, [sp, #-4]!)
   613   //    push    {r7}            ; (str r7, [sp, #-4]!)
   614   //    push    {r8}            ; (str r8, [sp, #-4]!)
   615   //    push    {r9}            ; (str r9, [sp, #-4]!)
   616   //    push    {r10}           ; (str r10, [sp, #-4]!)
   617   //    push    {r11}           ; (str r11, [sp, #-4]!)
   618   //    eors    r0, r0, r0
   619   //    adds    r0, r0, #123    ; 0x7b
   620   //    mov     r3, #256        ; 0x100
   621   //    orr     r3, r3, #65     ; 0x41
   622   //    adds    r0, r0, r3
   623   //    pop     {r11}           ; (ldr r11, [sp], #4)
   624   //    pop     {r10}           ; (ldr r10, [sp], #4)
   625   //    pop     {r9}            ; (ldr r9, [sp], #4)
   626   //    pop     {r8}            ; (ldr r8, [sp], #4)
   627   //    pop     {r7}            ; (ldr r7, [sp], #4)
   628   //    pop     {r6}            ; (ldr r6, [sp], #4)
   629   //    pop     {r5}            ; (ldr r5, [sp], #4)
   630   //    pop     {r4}            ; (ldr r4, [sp], #4)
   631   //    mov     pc, lr
   632   // callable as a normal function, returns 444
   634   JSC::ARMRegisters::RegisterID rreg = JSC::ARMRegisters::r0;
   636   am->push(JSC::ARMRegisters::r4);
   637   am->push(JSC::ARMRegisters::r5);
   638   am->push(JSC::ARMRegisters::r6);
   639   am->push(JSC::ARMRegisters::r7);
   640   am->push(JSC::ARMRegisters::r8);
   641   am->push(JSC::ARMRegisters::r9);
   642   am->push(JSC::ARMRegisters::r10);
   643   am->push(JSC::ARMRegisters::r11);
   645   am->xorPtr(rreg,rreg);
   646   am->addPtr(JSC::MacroAssembler::Imm32(123), rreg);
   647   am->addPtr(JSC::MacroAssembler::Imm32(321), rreg);
   649   am->pop(JSC::ARMRegisters::r11);
   650   am->pop(JSC::ARMRegisters::r10);
   651   am->pop(JSC::ARMRegisters::r9);
   652   am->pop(JSC::ARMRegisters::r8);
   653   am->pop(JSC::ARMRegisters::r7);
   654   am->pop(JSC::ARMRegisters::r6);
   655   am->pop(JSC::ARMRegisters::r5);
   656   am->pop(JSC::ARMRegisters::r4);
   658   am->ret();
   659 #endif
   661   // prepare a link buffer, into which we can copy the completed insns
   662   JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
   664   // intermediate step .. get the pool suited for the size of code in 'am'
   665   //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
   666   JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
   668   // constructor for LinkBuffer asks ep to allocate r-x memory,
   669   // then copies it there.
   670   JSC::LinkBuffer patchBuffer(am, ep, JSC::METHOD_CODE);
   672   // now fix up any branches/calls
   673   //JSC::FunctionPtr target = JSC::FunctionPtr::FunctionPtr( &cube );
   675   // finalize
   676   JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
   678   // cr now holds a pointer to the final runnable code.
   679   void* entry = cr.m_code.executableAddress();
   681   printf("disas %p %p\n",
   682          entry, (char*)entry + cr.m_size);
   683   pre_run();
   685   // call the function
   686   unsigned long (*fn)(void) = (unsigned long (*)())entry;
   687   unsigned long result = fn();
   689   printf("\n");
   690   printf("value computed is %lu (expected 444)\n", result);
   691   printf("\n");
   693   delete eal;
   694   delete am;
   695 }
   698 /////////////////////////////////////////////////////////////////
   699 //// test5 (call in, out, repatch)
   701 // a function which we will call from the JIT generated code
   702 unsigned long cube   ( unsigned long x ) { return x * x * x; }
   703 unsigned long square ( unsigned long x ) { return x * x; }
   705 void test5 ( void )
   706 {
   707   printf("\n--------- Test 5 (call in, out, repatch) ---------\n\n" );
   709   // Create new assembler
   710   JSC::MacroAssembler* am = new JSC::MacroAssembler();
   711   JSC::MacroAssembler::Call cl;
   712   ptrdiff_t offset_of_call_insn;
   714 #if defined(ARCH_amd64)
   715   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
   716   // and then call a non-JIT-generated helper from within
   717   // this code
   718   //    push   %rbp
   719   //    mov    %rsp,%rbp
   720   //    push   %rbx
   721   //    push   %r12
   722   //    push   %r13
   723   //    push   %r14
   724   //    push   %r15
   725   //    mov    $0x9,%edi
   726   //    mov    $0x40187e,%r11
   727   //    callq  *%r11
   728   //    pop    %r15
   729   //    pop    %r14
   730   //    pop    %r13
   731   //    pop    %r12
   732   //    pop    %rbx
   733   //    mov    %rbp,%rsp
   734   //    pop    %rbp
   735   //    retq
   736   JSC::MacroAssembler::Label startOfFnLbl(am);
   737   am->push(JSC::X86Registers::ebp);
   738   am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
   739   am->push(JSC::X86Registers::ebx);
   740   am->push(JSC::X86Registers::r12);
   741   am->push(JSC::X86Registers::r13);
   742   am->push(JSC::X86Registers::r14);
   743   am->push(JSC::X86Registers::r15);
   745   // let's compute cube(9).  Move $9 to the first arg reg.
   746   am->move(JSC::MacroAssembler::Imm32(9), JSC::X86Registers::edi);
   747   cl = am->JSC::MacroAssembler::call();
   749   // result is now in %rax.  Leave it ther and just return.
   751   am->pop(JSC::X86Registers::r15);
   752   am->pop(JSC::X86Registers::r14);
   753   am->pop(JSC::X86Registers::r13);
   754   am->pop(JSC::X86Registers::r12);
   755   am->pop(JSC::X86Registers::ebx);
   756   am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
   757   am->pop(JSC::X86Registers::ebp);
   758   am->ret();
   760   offset_of_call_insn
   761      = am->JSC::MacroAssembler::differenceBetween(startOfFnLbl, cl);
   762   if (0) printf("XXXXXXXX offset = %lu\n", offset_of_call_insn);
   763 #endif
   765 #if defined(ARCH_x86)
   766   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
   767   // and then call a non-JIT-generated helper from within
   768   // this code
   769   //    push   %ebp
   770   //    mov    %esp,%ebp
   771   //    push   %ebx
   772   //    push   %esi
   773   //    push   %edi
   774   //    push   $0x9
   775   //    call   0x80490e9 <_Z4cubem>
   776   //    add    $0x4,%esp
   777   //    pop    %edi
   778   //    pop    %esi
   779   //    pop    %ebx
   780   //    mov    %ebp,%esp
   781   //    pop    %ebp
   782   //    ret
   783   JSC::MacroAssembler::Label startOfFnLbl(am);
   784   am->push(JSC::X86Registers::ebp);
   785   am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
   786   am->push(JSC::X86Registers::ebx);
   787   am->push(JSC::X86Registers::esi);
   788   am->push(JSC::X86Registers::edi);
   790   // let's compute cube(9).  Push $9 on the stack.
   791   am->push(JSC::MacroAssembler::Imm32(9));
   792   cl = am->JSC::MacroAssembler::call();
   793   am->addPtr(JSC::MacroAssembler::Imm32(4), JSC::X86Registers::esp);
   794   // result is now in %eax.  Leave it there and just return.
   796   am->pop(JSC::X86Registers::edi);
   797   am->pop(JSC::X86Registers::esi);
   798   am->pop(JSC::X86Registers::ebx);
   799   am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
   800   am->pop(JSC::X86Registers::ebp);
   801   am->ret();
   803   offset_of_call_insn
   804      = am->JSC::MacroAssembler::differenceBetween(startOfFnLbl, cl);
   805   if (0) printf("XXXXXXXX offset = %lu\n",
   806                 (unsigned long)offset_of_call_insn);
   807 #endif
   809 #if defined(ARCH_arm)
   810   // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
   811   //    push    {r4}            ; (str r4, [sp, #-4]!)
   812   //    push    {r5}            ; (str r5, [sp, #-4]!)
   813   //    push    {r6}            ; (str r6, [sp, #-4]!)
   814   //    push    {r7}            ; (str r7, [sp, #-4]!)
   815   //    push    {r8}            ; (str r8, [sp, #-4]!)
   816   //    push    {r9}            ; (str r9, [sp, #-4]!)
   817   //    push    {r10}           ; (str r10, [sp, #-4]!)
   818   //    push    {r11}           ; (str r11, [sp, #-4]!)
   819   //    eors    r0, r0, r0
   820   //    adds    r0, r0, #123    ; 0x7b
   821   //    mov     r3, #256        ; 0x100
   822   //    orr     r3, r3, #65     ; 0x41
   823   //    adds    r0, r0, r3
   824   //    pop     {r11}           ; (ldr r11, [sp], #4)
   825   //    pop     {r10}           ; (ldr r10, [sp], #4)
   826   //    pop     {r9}            ; (ldr r9, [sp], #4)
   827   //    pop     {r8}            ; (ldr r8, [sp], #4)
   828   //    pop     {r7}            ; (ldr r7, [sp], #4)
   829   //    pop     {r6}            ; (ldr r6, [sp], #4)
   830   //    pop     {r5}            ; (ldr r5, [sp], #4)
   831   //    pop     {r4}            ; (ldr r4, [sp], #4)
   832   //    mov     pc, lr
   833   // callable as a normal function, returns 444
   834   JSC::MacroAssembler::Label startOfFnLbl(am);
   835   am->push(JSC::ARMRegisters::r4);
   836   am->push(JSC::ARMRegisters::r5);
   837   am->push(JSC::ARMRegisters::r6);
   838   am->push(JSC::ARMRegisters::r7);
   839   am->push(JSC::ARMRegisters::r8);
   840   am->push(JSC::ARMRegisters::r9);
   841   am->push(JSC::ARMRegisters::r10);
   842   am->push(JSC::ARMRegisters::r11);
   843   am->push(JSC::ARMRegisters::lr);
   845   // let's compute cube(9).  Get $9 into r0.
   846   am->move(JSC::MacroAssembler::Imm32(9), JSC::ARMRegisters::r0);
   847   cl = am->JSC::MacroAssembler::call();
   848   // result is now in r0.  Leave it there and just return.
   850   am->pop(JSC::ARMRegisters::lr);
   851   am->pop(JSC::ARMRegisters::r11);
   852   am->pop(JSC::ARMRegisters::r10);
   853   am->pop(JSC::ARMRegisters::r9);
   854   am->pop(JSC::ARMRegisters::r8);
   855   am->pop(JSC::ARMRegisters::r7);
   856   am->pop(JSC::ARMRegisters::r6);
   857   am->pop(JSC::ARMRegisters::r5);
   858   am->pop(JSC::ARMRegisters::r4);
   859   am->ret();
   861   offset_of_call_insn
   862      = am->JSC::MacroAssembler::differenceBetween(startOfFnLbl, cl);
   863   if (0) printf("XXXXXXXX offset = %lu\n",
   864                 (unsigned long)offset_of_call_insn);
   865 #endif
   867   // prepare a link buffer, into which we can copy the completed insns
   868   JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
   870   // intermediate step .. get the pool suited for the size of code in 'am'
   871   //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
   872   JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
   874   // constructor for LinkBuffer asks ep to allocate r-x memory,
   875   // then copies it there.
   876   JSC::LinkBuffer patchBuffer(am, ep, JSC::METHOD_CODE);
   878   // now fix up any branches/calls
   879   JSC::FunctionPtr target = JSC::FunctionPtr::FunctionPtr( &cube );
   880   patchBuffer.link(cl, target);
   882   JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
   884   // cr now holds a pointer to the final runnable code.
   885   void* entry = cr.m_code.executableAddress();
   887   printf("disas %p %p\n",
   888          entry, (char*)entry + cr.m_size);
   891   pre_run();
   893   printf("\n");
   895   unsigned long (*fn)() = (unsigned long(*)())entry;
   896   unsigned long result = fn();
   898   printf("value computed is %lu (expected 729)\n", result);
   899   printf("\n");
   901   // now repatch the call in the JITted code to go elsewhere
   902   JSC::JITCode jc = JSC::JITCode::JITCode(entry, cr.m_size);
   903   JSC::CodeBlock cb = JSC::CodeBlock::CodeBlock(jc);
   905   // the address of the call insn, that we want to prod
   906   JSC::MacroAssemblerCodePtr cp
   907      = JSC::MacroAssemblerCodePtr( ((char*)entry) + offset_of_call_insn );
   909   JSC::RepatchBuffer repatchBuffer(&cb);
   910   repatchBuffer.relink( JSC::CodeLocationCall(cp),
   911                         JSC::FunctionPtr::FunctionPtr( &square ));
   913   result = fn();
   914   printf("value computed is %lu (expected 81)\n", result);
   915   printf("\n\n");
   917   delete eal;
   918   delete am;
   919 }
   921 /////////////////////////////////////////////////////////////////
   923 int main ( void )
   924 {
   925 #if WTF_COMPILER_GCC
   926   test1();
   927   test2();
   928   test3();
   929 #endif
   930   test4();
   931   test5();
   932   return 0;
   933 }

mercurial