Home | History | Annotate | Download | only in jit
      1 /*
      2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich (at) uwaterloo.ca>
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * 1.  Redistributions of source code must retain the above copyright
     10  *     notice, this list of conditions and the following disclaimer.
     11  * 2.  Redistributions in binary form must reproduce the above copyright
     12  *     notice, this list of conditions and the following disclaimer in the
     13  *     documentation and/or other materials provided with the distribution.
     14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     15  *     its contributors may be used to endorse or promote products derived
     16  *     from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include "config.h"
     31 #include "JITStubs.h"
     32 
     33 #if ENABLE(JIT)
     34 
     35 #include "Arguments.h"
     36 #include "CallFrame.h"
     37 #include "CodeBlock.h"
     38 #include "Collector.h"
     39 #include "Debugger.h"
     40 #include "ExceptionHelpers.h"
     41 #include "GlobalEvalFunction.h"
     42 #include "JIT.h"
     43 #include "JSActivation.h"
     44 #include "JSArray.h"
     45 #include "JSByteArray.h"
     46 #include "JSFunction.h"
     47 #include "JSNotAnObject.h"
     48 #include "JSPropertyNameIterator.h"
     49 #include "JSStaticScopeObject.h"
     50 #include "JSString.h"
     51 #include "ObjectPrototype.h"
     52 #include "Operations.h"
     53 #include "Parser.h"
     54 #include "Profiler.h"
     55 #include "RegExpObject.h"
     56 #include "RegExpPrototype.h"
     57 #include "Register.h"
     58 #include "SamplingTool.h"
     59 #include <wtf/StdLibExtras.h>
     60 #include <stdarg.h>
     61 #include <stdio.h>
     62 
     63 using namespace std;
     64 
     65 namespace JSC {
     66 
     67 #if OS(DARWIN) || OS(WINDOWS)
     68 #define SYMBOL_STRING(name) "_" #name
     69 #else
     70 #define SYMBOL_STRING(name) #name
     71 #endif
     72 
     73 #if OS(IPHONE_OS)
     74 #define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name)
     75 #else
     76 #define THUMB_FUNC_PARAM(name)
     77 #endif
     78 
     79 #if OS(LINUX) && CPU(X86_64)
     80 #define SYMBOL_STRING_RELOCATION(name) #name "@plt"
     81 #else
     82 #define SYMBOL_STRING_RELOCATION(name) SYMBOL_STRING(name)
     83 #endif
     84 
     85 #if OS(DARWIN)
     86     // Mach-O platform
     87 #define HIDE_SYMBOL(name) ".private_extern _" #name
     88 #elif OS(AIX)
     89     // IBM's own file format
     90 #define HIDE_SYMBOL(name) ".lglobl " #name
     91 #elif   OS(LINUX)               \
     92      || OS(FREEBSD)             \
     93      || OS(OPENBSD)             \
     94      || OS(SOLARIS)             \
     95      || (OS(HPUX) && CPU(IA64)) \
     96      || OS(SYMBIAN)             \
     97      || OS(NETBSD)
     98     // ELF platform
     99 #define HIDE_SYMBOL(name) ".hidden " #name
    100 #else
    101 #define HIDE_SYMBOL(name)
    102 #endif
    103 
    104 #if USE(JSVALUE32_64)
    105 
    106 #if COMPILER(GCC) && CPU(X86)
    107 
    108 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
    109 // need to change the assembly trampolines below to match.
    110 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
    111 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
    112 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
    113 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
    114 
    115 asm volatile (
    116 ".text\n"
    117 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
    118 HIDE_SYMBOL(ctiTrampoline) "\n"
    119 SYMBOL_STRING(ctiTrampoline) ":" "\n"
    120     "pushl %ebp" "\n"
    121     "movl %esp, %ebp" "\n"
    122     "pushl %esi" "\n"
    123     "pushl %edi" "\n"
    124     "pushl %ebx" "\n"
    125     "subl $0x3c, %esp" "\n"
    126     "movl $512, %esi" "\n"
    127     "movl 0x58(%esp), %edi" "\n"
    128     "call *0x50(%esp)" "\n"
    129     "addl $0x3c, %esp" "\n"
    130     "popl %ebx" "\n"
    131     "popl %edi" "\n"
    132     "popl %esi" "\n"
    133     "popl %ebp" "\n"
    134     "ret" "\n"
    135 );
    136 
    137 asm volatile (
    138 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
    139 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
    140 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
    141 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
    142     "movl %esp, %ecx" "\n"
    143 #endif
    144     "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
    145     "addl $0x3c, %esp" "\n"
    146     "popl %ebx" "\n"
    147     "popl %edi" "\n"
    148     "popl %esi" "\n"
    149     "popl %ebp" "\n"
    150     "ret" "\n"
    151 );
    152 
    153 asm volatile (
    154 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
    155 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
    156 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
    157     "addl $0x3c, %esp" "\n"
    158     "popl %ebx" "\n"
    159     "popl %edi" "\n"
    160     "popl %esi" "\n"
    161     "popl %ebp" "\n"
    162     "ret" "\n"
    163 );
    164 
    165 #elif COMPILER(GCC) && CPU(X86_64)
    166 
    167 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
    168 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
    169 #endif
    170 
    171 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
    172 // need to change the assembly trampolines below to match.
    173 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment);
    174 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
    175 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
    176 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline);
    177 
    178 asm volatile (
    179 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
    180 HIDE_SYMBOL(ctiTrampoline) "\n"
    181 SYMBOL_STRING(ctiTrampoline) ":" "\n"
    182     "pushq %rbp" "\n"
    183     "movq %rsp, %rbp" "\n"
    184     "pushq %r12" "\n"
    185     "pushq %r13" "\n"
    186     "pushq %r14" "\n"
    187     "pushq %r15" "\n"
    188     "pushq %rbx" "\n"
    189     "subq $0x48, %rsp" "\n"
    190     "movq $512, %r12" "\n"
    191     "movq $0xFFFF000000000000, %r14" "\n"
    192     "movq $0xFFFF000000000002, %r15" "\n"
    193     "movq 0x90(%rsp), %r13" "\n"
    194     "call *0x80(%rsp)" "\n"
    195     "addq $0x48, %rsp" "\n"
    196     "popq %rbx" "\n"
    197     "popq %r15" "\n"
    198     "popq %r14" "\n"
    199     "popq %r13" "\n"
    200     "popq %r12" "\n"
    201     "popq %rbp" "\n"
    202     "ret" "\n"
    203 );
    204 
    205 asm volatile (
    206 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
    207 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
    208 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
    209     "movq %rsp, %rdi" "\n"
    210     "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
    211     "addq $0x48, %rsp" "\n"
    212     "popq %rbx" "\n"
    213     "popq %r15" "\n"
    214     "popq %r14" "\n"
    215     "popq %r13" "\n"
    216     "popq %r12" "\n"
    217     "popq %rbp" "\n"
    218     "ret" "\n"
    219 );
    220 
    221 asm volatile (
    222 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
    223 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
    224 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
    225     "addq $0x48, %rsp" "\n"
    226     "popq %rbx" "\n"
    227     "popq %r15" "\n"
    228     "popq %r14" "\n"
    229     "popq %r13" "\n"
    230     "popq %r12" "\n"
    231     "popq %rbp" "\n"
    232     "ret" "\n"
    233 );
    234 
    235 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
    236 
    237 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
    238 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
    239 #endif
    240 
    241 asm volatile (
    242 ".text" "\n"
    243 ".align 2" "\n"
    244 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
    245 HIDE_SYMBOL(ctiTrampoline) "\n"
    246 ".thumb" "\n"
    247 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
    248 SYMBOL_STRING(ctiTrampoline) ":" "\n"
    249     "sub sp, sp, #0x3c" "\n"
    250     "str lr, [sp, #0x20]" "\n"
    251     "str r4, [sp, #0x24]" "\n"
    252     "str r5, [sp, #0x28]" "\n"
    253     "str r6, [sp, #0x2c]" "\n"
    254     "str r1, [sp, #0x30]" "\n"
    255     "str r2, [sp, #0x34]" "\n"
    256     "str r3, [sp, #0x38]" "\n"
    257     "cpy r5, r2" "\n"
    258     "mov r6, #512" "\n"
    259     "blx r0" "\n"
    260     "ldr r6, [sp, #0x2c]" "\n"
    261     "ldr r5, [sp, #0x28]" "\n"
    262     "ldr r4, [sp, #0x24]" "\n"
    263     "ldr lr, [sp, #0x20]" "\n"
    264     "add sp, sp, #0x3c" "\n"
    265     "bx lr" "\n"
    266 );
    267 
    268 asm volatile (
    269 ".text" "\n"
    270 ".align 2" "\n"
    271 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
    272 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
    273 ".thumb" "\n"
    274 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
    275 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
    276     "cpy r0, sp" "\n"
    277     "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
    278     "ldr r6, [sp, #0x2c]" "\n"
    279     "ldr r5, [sp, #0x28]" "\n"
    280     "ldr r4, [sp, #0x24]" "\n"
    281     "ldr lr, [sp, #0x20]" "\n"
    282     "add sp, sp, #0x3c" "\n"
    283     "bx lr" "\n"
    284 );
    285 
    286 asm volatile (
    287 ".text" "\n"
    288 ".align 2" "\n"
    289 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
    290 ".thumb" "\n"
    291 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
    292 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
    293     "ldr r6, [sp, #0x2c]" "\n"
    294     "ldr r5, [sp, #0x28]" "\n"
    295     "ldr r4, [sp, #0x24]" "\n"
    296     "ldr lr, [sp, #0x20]" "\n"
    297     "add sp, sp, #0x3c" "\n"
    298     "bx lr" "\n"
    299 );
    300 
    301 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
    302 
    303 asm volatile (
    304 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
    305 SYMBOL_STRING(ctiTrampoline) ":" "\n"
    306     "stmdb sp!, {r1-r3}" "\n"
    307     "stmdb sp!, {r4-r8, lr}" "\n"
    308     "sub sp, sp, #68" "\n"
    309     "mov r4, r2" "\n"
    310     "mov r5, #512" "\n"
    311     // r0 contains the code
    312     "mov lr, pc" "\n"
    313     "mov pc, r0" "\n"
    314     "add sp, sp, #68" "\n"
    315     "ldmia sp!, {r4-r8, lr}" "\n"
    316     "add sp, sp, #12" "\n"
    317     "mov pc, lr" "\n"
    318 );
    319 
    320 asm volatile (
    321 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
    322 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
    323     "mov r0, sp" "\n"
    324     "bl " SYMBOL_STRING(cti_vm_throw) "\n"
    325 
    326 // Both has the same return sequence
    327 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
    328 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
    329     "add sp, sp, #68" "\n"
    330     "ldmia sp!, {r4-r8, lr}" "\n"
    331     "add sp, sp, #12" "\n"
    332     "mov pc, lr" "\n"
    333 );
    334 
    335 #elif COMPILER(MSVC) && CPU(X86)
    336 
    337 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
    338 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
    339 #endif
    340 
    341 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
    342 // need to change the assembly trampolines below to match.
    343 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
    344 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
    345 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
    346 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
    347 
    348 extern "C" {
    349 
    350     __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*)
    351     {
    352         __asm {
    353             push ebp;
    354             mov ebp, esp;
    355             push esi;
    356             push edi;
    357             push ebx;
    358             sub esp, 0x3c;
    359             mov esi, 512;
    360             mov ecx, esp;
    361             mov edi, [esp + 0x58];
    362             call [esp + 0x50];
    363             add esp, 0x3c;
    364             pop ebx;
    365             pop edi;
    366             pop esi;
    367             pop ebp;
    368             ret;
    369         }
    370     }
    371 
    372     __declspec(naked) void ctiVMThrowTrampoline()
    373     {
    374         __asm {
    375             mov ecx, esp;
    376             call cti_vm_throw;
    377             add esp, 0x3c;
    378             pop ebx;
    379             pop edi;
    380             pop esi;
    381             pop ebp;
    382             ret;
    383         }
    384     }
    385 
    386     __declspec(naked) void ctiOpThrowNotCaught()
    387     {
    388         __asm {
    389             add esp, 0x3c;
    390             pop ebx;
    391             pop edi;
    392             pop esi;
    393             pop ebp;
    394             ret;
    395         }
    396     }
    397 }
    398 
    399 #else
    400     #error "JIT not supported on this platform."
    401 #endif
    402 
    403 #else // USE(JSVALUE32_64)
    404 
    405 #if COMPILER(GCC) && CPU(X86)
    406 
    407 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
    408 // need to change the assembly trampolines below to match.
    409 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
    410 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline);
    411 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
    412 
    413 asm volatile (
    414 ".text\n"
    415 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
    416 HIDE_SYMBOL(ctiTrampoline) "\n"
    417 SYMBOL_STRING(ctiTrampoline) ":" "\n"
    418     "pushl %ebp" "\n"
    419     "movl %esp, %ebp" "\n"
    420     "pushl %esi" "\n"
    421     "pushl %edi" "\n"
    422     "pushl %ebx" "\n"
    423     "subl $0x1c, %esp" "\n"
    424     "movl $512, %esi" "\n"
    425     "movl 0x38(%esp), %edi" "\n"
    426     "call *0x30(%esp)" "\n"
    427     "addl $0x1c, %esp" "\n"
    428     "popl %ebx" "\n"
    429     "popl %edi" "\n"
    430     "popl %esi" "\n"
    431     "popl %ebp" "\n"
    432     "ret" "\n"
    433 );
    434 
    435 asm volatile (
    436 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
    437 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
    438 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
    439 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
    440     "movl %esp, %ecx" "\n"
    441 #endif
    442     "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
    443     "addl $0x1c, %esp" "\n"
    444     "popl %ebx" "\n"
    445     "popl %edi" "\n"
    446     "popl %esi" "\n"
    447     "popl %ebp" "\n"
    448     "ret" "\n"
    449 );
    450 
    451 asm volatile (
    452 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
    453 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
    454 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
    455     "addl $0x1c, %esp" "\n"
    456     "popl %ebx" "\n"
    457     "popl %edi" "\n"
    458     "popl %esi" "\n"
    459     "popl %ebp" "\n"
    460     "ret" "\n"
    461 );
    462 
    463 #elif COMPILER(GCC) && CPU(X86_64)
    464 
    465 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
    466 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
    467 #endif
    468 
    469 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
    470 // need to change the assembly trampolines below to match.
    471 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
    472 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline);
    473 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
    474 
    475 asm volatile (
    476 ".text\n"
    477 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
    478 HIDE_SYMBOL(ctiTrampoline) "\n"
    479 SYMBOL_STRING(ctiTrampoline) ":" "\n"
    480     "pushq %rbp" "\n"
    481     "movq %rsp, %rbp" "\n"
    482     "pushq %r12" "\n"
    483     "pushq %r13" "\n"
    484     "pushq %r14" "\n"
    485     "pushq %r15" "\n"
    486     "pushq %rbx" "\n"
    487     // Form the JIT stubs area
    488     "pushq %r9" "\n"
    489     "pushq %r8" "\n"
    490     "pushq %rcx" "\n"
    491     "pushq %rdx" "\n"
    492     "pushq %rsi" "\n"
    493     "pushq %rdi" "\n"
    494     "subq $0x48, %rsp" "\n"
    495     "movq $512, %r12" "\n"
    496     "movq $0xFFFF000000000000, %r14" "\n"
    497     "movq $0xFFFF000000000002, %r15" "\n"
    498     "movq %rdx, %r13" "\n"
    499     "call *%rdi" "\n"
    500     "addq $0x78, %rsp" "\n"
    501     "popq %rbx" "\n"
    502     "popq %r15" "\n"
    503     "popq %r14" "\n"
    504     "popq %r13" "\n"
    505     "popq %r12" "\n"
    506     "popq %rbp" "\n"
    507     "ret" "\n"
    508 );
    509 
    510 asm volatile (
    511 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
    512 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
    513 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
    514     "movq %rsp, %rdi" "\n"
    515     "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
    516     "addq $0x78, %rsp" "\n"
    517     "popq %rbx" "\n"
    518     "popq %r15" "\n"
    519     "popq %r14" "\n"
    520     "popq %r13" "\n"
    521     "popq %r12" "\n"
    522     "popq %rbp" "\n"
    523     "ret" "\n"
    524 );
    525 
    526 asm volatile (
    527 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
    528 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
    529 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
    530     "addq $0x78, %rsp" "\n"
    531     "popq %rbx" "\n"
    532     "popq %r15" "\n"
    533     "popq %r14" "\n"
    534     "popq %r13" "\n"
    535     "popq %r12" "\n"
    536     "popq %rbp" "\n"
    537     "ret" "\n"
    538 );
    539 
    540 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
    541 
    542 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
    543 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
    544 #endif
    545 
    546 asm volatile (
    547 ".text" "\n"
    548 ".align 2" "\n"
    549 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
    550 HIDE_SYMBOL(ctiTrampoline) "\n"
    551 ".thumb" "\n"
    552 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
    553 SYMBOL_STRING(ctiTrampoline) ":" "\n"
    554     "sub sp, sp, #0x40" "\n"
    555     "str lr, [sp, #0x20]" "\n"
    556     "str r4, [sp, #0x24]" "\n"
    557     "str r5, [sp, #0x28]" "\n"
    558     "str r6, [sp, #0x2c]" "\n"
    559     "str r1, [sp, #0x30]" "\n"
    560     "str r2, [sp, #0x34]" "\n"
    561     "str r3, [sp, #0x38]" "\n"
    562     "cpy r5, r2" "\n"
    563     "mov r6, #512" "\n"
    564     "blx r0" "\n"
    565     "ldr r6, [sp, #0x2c]" "\n"
    566     "ldr r5, [sp, #0x28]" "\n"
    567     "ldr r4, [sp, #0x24]" "\n"
    568     "ldr lr, [sp, #0x20]" "\n"
    569     "add sp, sp, #0x40" "\n"
    570     "bx lr" "\n"
    571 );
    572 
    573 asm volatile (
    574 ".text" "\n"
    575 ".align 2" "\n"
    576 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
    577 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
    578 ".thumb" "\n"
    579 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
    580 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
    581     "cpy r0, sp" "\n"
    582     "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
    583     "ldr r6, [sp, #0x2c]" "\n"
    584     "ldr r5, [sp, #0x28]" "\n"
    585     "ldr r4, [sp, #0x24]" "\n"
    586     "ldr lr, [sp, #0x20]" "\n"
    587     "add sp, sp, #0x40" "\n"
    588     "bx lr" "\n"
    589 );
    590 
    591 asm volatile (
    592 ".text" "\n"
    593 ".align 2" "\n"
    594 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
    595 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
    596 ".thumb" "\n"
    597 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
    598 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
    599     "ldr r6, [sp, #0x2c]" "\n"
    600     "ldr r5, [sp, #0x28]" "\n"
    601     "ldr r4, [sp, #0x24]" "\n"
    602     "ldr lr, [sp, #0x20]" "\n"
    603     "add sp, sp, #0x3c" "\n"
    604     "bx lr" "\n"
    605 );
    606 
    607 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
    608 
    609 asm volatile (
    610 ".text\n"
    611 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
    612 HIDE_SYMBOL(ctiTrampoline) "\n"
    613 SYMBOL_STRING(ctiTrampoline) ":" "\n"
    614     "stmdb sp!, {r1-r3}" "\n"
    615     "stmdb sp!, {r4-r8, lr}" "\n"
    616     "sub sp, sp, #36" "\n"
    617     "mov r4, r2" "\n"
    618     "mov r5, #512" "\n"
    619     "mov lr, pc" "\n"
    620     "mov pc, r0" "\n"
    621     "add sp, sp, #36" "\n"
    622     "ldmia sp!, {r4-r8, lr}" "\n"
    623     "add sp, sp, #12" "\n"
    624     "mov pc, lr" "\n"
    625 );
    626 
    627 asm volatile (
    628 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
    629 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
    630 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
    631     "mov r0, sp" "\n"
    632     "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
    633 
    634 // Both has the same return sequence
    635 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
    636 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
    637 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
    638     "add sp, sp, #36" "\n"
    639     "ldmia sp!, {r4-r8, lr}" "\n"
    640     "add sp, sp, #12" "\n"
    641     "mov pc, lr" "\n"
    642 );
    643 
    644 #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
    645 
    646 __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*)
    647 {
    648     ARM
    649     stmdb sp!, {r1-r3}
    650     stmdb sp!, {r4-r8, lr}
    651     sub sp, sp, #36
    652     mov r4, r2
    653     mov r5, #512
    654     mov lr, pc
    655     bx r0
    656     add sp, sp, #36
    657     ldmia sp!, {r4-r8, lr}
    658     add sp, sp, #12
    659     bx lr
    660 }
    661 
    662 __asm void ctiVMThrowTrampoline()
    663 {
    664     ARM
    665     PRESERVE8
    666     mov r0, sp
    667     bl cti_vm_throw
    668     add sp, sp, #36
    669     ldmia sp!, {r4-r8, lr}
    670     add sp, sp, #12
    671     bx lr
    672 }
    673 
    674 __asm void ctiOpThrowNotCaught()
    675 {
    676     ARM
    677     add sp, sp, #36
    678     ldmia sp!, {r4-r8, lr}
    679     add sp, sp, #12
    680     bx lr
    681 }
    682 
    683 #elif COMPILER(MSVC) && CPU(X86)
    684 
    685 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
    686 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
    687 #endif
    688 
    689 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
    690 // need to change the assembly trampolines below to match.
    691 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
    692 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline);
    693 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
    694 
    695 extern "C" {
    696 
    697     __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*)
    698     {
    699         __asm {
    700             push ebp;
    701             mov ebp, esp;
    702             push esi;
    703             push edi;
    704             push ebx;
    705             sub esp, 0x1c;
    706             mov esi, 512;
    707             mov ecx, esp;
    708             mov edi, [esp + 0x38];
    709             call [esp + 0x30];
    710             add esp, 0x1c;
    711             pop ebx;
    712             pop edi;
    713             pop esi;
    714             pop ebp;
    715             ret;
    716         }
    717     }
    718 
    719     __declspec(naked) void ctiVMThrowTrampoline()
    720     {
    721         __asm {
    722             mov ecx, esp;
    723             call cti_vm_throw;
    724             add esp, 0x1c;
    725             pop ebx;
    726             pop edi;
    727             pop esi;
    728             pop ebp;
    729             ret;
    730         }
    731     }
    732 
    733      __declspec(naked) void ctiOpThrowNotCaught()
    734      {
    735          __asm {
    736              add esp, 0x1c;
    737              pop ebx;
    738              pop edi;
    739              pop esi;
    740              pop ebp;
    741              ret;
    742          }
    743      }
    744 }
    745 
    746 #else
    747     #error "JIT not supported on this platform."
    748 #endif
    749 
    750 #endif // USE(JSVALUE32_64)
    751 
    752 #if ENABLE(OPCODE_SAMPLING)
    753     #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler()
    754 #else
    755     #define CTI_SAMPLER 0
    756 #endif
    757 
    758 JITThunks::JITThunks(JSGlobalData* globalData)
    759 {
    760     JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_trampolineStructure);
    761 
    762 #if CPU(ARM_THUMB2)
    763     // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
    764     // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
    765     // macros.
    766     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == 0x20);
    767     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == 0x24);
    768     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == 0x28);
    769     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == 0x2c);
    770 
    771     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == 0x30);
    772     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == 0x34);
    773     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == 0x38);
    774     // The fifth argument is the first item already on the stack.
    775     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == 0x40);
    776 
    777     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == 0x1C);
    778 #endif
    779 }
    780 
    781 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    782 
    783 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo)
    784 {
    785     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
    786 
    787     if (!baseValue.isCell())
    788         return;
    789 
    790     // Uncacheable: give up.
    791     if (!slot.isCacheable()) {
    792         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
    793         return;
    794     }
    795 
    796     JSCell* baseCell = asCell(baseValue);
    797     Structure* structure = baseCell->structure();
    798 
    799     if (structure->isUncacheableDictionary()) {
    800         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
    801         return;
    802     }
    803 
    804     // If baseCell != base, then baseCell must be a proxy for another object.
    805     if (baseCell != slot.base()) {
    806         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
    807         return;
    808     }
    809 
    810     // Cache hit: Specialize instruction and ref Structures.
    811 
    812     // Structure transition, cache transition info
    813     if (slot.type() == PutPropertySlot::NewProperty) {
    814         if (structure->isDictionary()) {
    815             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
    816             return;
    817         }
    818 
    819         // put_by_id_transition checks the prototype chain for setters.
    820         normalizePrototypeChain(callFrame, baseCell);
    821 
    822         StructureChain* prototypeChain = structure->prototypeChain(callFrame);
    823         stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
    824         JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress);
    825         return;
    826     }
    827 
    828     stubInfo->initPutByIdReplace(structure);
    829 
    830     JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
    831 }
    832 
    833 NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
    834 {
    835     // FIXME: Write a test that proves we need to check for recursion here just
    836     // like the interpreter does, then add a check for recursion.
    837 
    838     // FIXME: Cache property access for immediates.
    839     if (!baseValue.isCell()) {
    840         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
    841         return;
    842     }
    843 
    844     JSGlobalData* globalData = &callFrame->globalData();
    845 
    846     if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
    847         JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
    848         return;
    849     }
    850 
    851     if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
    852         // The tradeoff of compiling an patched inline string length access routine does not seem
    853         // to pay off, so we currently only do this for arrays.
    854         ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs.ctiStringLengthTrampoline());
    855         return;
    856     }
    857 
    858     // Uncacheable: give up.
    859     if (!slot.isCacheable()) {
    860         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
    861         return;
    862     }
    863 
    864     JSCell* baseCell = asCell(baseValue);
    865     Structure* structure = baseCell->structure();
    866 
    867     if (structure->isUncacheableDictionary()) {
    868         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
    869         return;
    870     }
    871 
    872     // Cache hit: Specialize instruction and ref Structures.
    873 
    874     if (slot.slotBase() == baseValue) {
    875         // set this up, so derefStructures can do it's job.
    876         stubInfo->initGetByIdSelf(structure);
    877 
    878         JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
    879         return;
    880     }
    881 
    882     if (structure->isDictionary()) {
    883         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
    884         return;
    885     }
    886 
    887     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
    888         ASSERT(slot.slotBase().isObject());
    889 
    890         JSObject* slotBaseObject = asObject(slot.slotBase());
    891         size_t offset = slot.cachedOffset();
    892 
    893         // Since we're accessing a prototype in a loop, it's a good bet that it
    894         // should not be treated as a dictionary.
    895         if (slotBaseObject->structure()->isDictionary()) {
    896             slotBaseObject->flattenDictionaryObject();
    897             offset = slotBaseObject->structure()->get(propertyName);
    898         }
    899 
    900         stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
    901 
    902         ASSERT(!structure->isDictionary());
    903         ASSERT(!slotBaseObject->structure()->isDictionary());
    904         JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), offset, returnAddress);
    905         return;
    906     }
    907 
    908     size_t offset = slot.cachedOffset();
    909     size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
    910     if (!count) {
    911         stubInfo->accessType = access_get_by_id_generic;
    912         return;
    913     }
    914 
    915     StructureChain* prototypeChain = structure->prototypeChain(callFrame);
    916     stubInfo->initGetByIdChain(structure, prototypeChain);
    917     JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, offset, returnAddress);
    918 }
    919 
    920 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    921 
    922 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
    923 #define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args)
    924 #else
    925 #define SETUP_VA_LISTL_ARGS
    926 #endif
    927 
    928 #ifndef NDEBUG
    929 
    930 extern "C" {
    931 
    932 static void jscGeneratedNativeCode()
    933 {
    934     // When executing a JIT stub function (which might do an allocation), we hack the return address
    935     // to pretend to be executing this function, to keep stack logging tools from blowing out
    936     // memory.
    937 }
    938 
    939 }
    940 
    941 struct StackHack {
    942     ALWAYS_INLINE StackHack(JITStackFrame& stackFrame)
    943         : stackFrame(stackFrame)
    944         , savedReturnAddress(*stackFrame.returnAddressSlot())
    945     {
    946         *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
    947     }
    948 
    949     ALWAYS_INLINE ~StackHack()
    950     {
    951         *stackFrame.returnAddressSlot() = savedReturnAddress;
    952     }
    953 
    954     JITStackFrame& stackFrame;
    955     ReturnAddressPtr savedReturnAddress;
    956 };
    957 
    958 #define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
    959 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
    960 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
    961 
    962 #else
    963 
    964 #define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS)
    965 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
    966 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
    967 
    968 #endif
    969 
    970 // The reason this is not inlined is to avoid having to do a PIC branch
    971 // to get the address of the ctiVMThrowTrampoline function. It's also
    972 // good to keep the code size down by leaving as much of the exception
    973 // handling code out of line as possible.
    974 static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
    975 {
    976     ASSERT(globalData->exception);
    977     globalData->exceptionLocation = exceptionLocation;
    978     returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline));
    979 }
    980 
    981 static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
    982 {
    983     globalData->exception = createStackOverflowError(callFrame);
    984     returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot);
    985 }
    986 
    987 #define VM_THROW_EXCEPTION() \
    988     do { \
    989         VM_THROW_EXCEPTION_AT_END(); \
    990         return 0; \
    991     } while (0)
    992 #define VM_THROW_EXCEPTION_AT_END() \
    993     returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS)
    994 
    995 #define CHECK_FOR_EXCEPTION() \
    996     do { \
    997         if (UNLIKELY(stackFrame.globalData->exception)) \
    998             VM_THROW_EXCEPTION(); \
    999     } while (0)
   1000 #define CHECK_FOR_EXCEPTION_AT_END() \
   1001     do { \
   1002         if (UNLIKELY(stackFrame.globalData->exception)) \
   1003             VM_THROW_EXCEPTION_AT_END(); \
   1004     } while (0)
   1005 #define CHECK_FOR_EXCEPTION_VOID() \
   1006     do { \
   1007         if (UNLIKELY(stackFrame.globalData->exception)) { \
   1008             VM_THROW_EXCEPTION_AT_END(); \
   1009             return; \
   1010         } \
   1011     } while (0)
   1012 
   1013 #if CPU(ARM_THUMB2)
   1014 
   1015 #define DEFINE_STUB_FUNCTION(rtype, op) \
   1016     extern "C" { \
   1017         rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
   1018     }; \
   1019     asm volatile ( \
   1020         ".text" "\n" \
   1021         ".align 2" "\n" \
   1022         ".globl " SYMBOL_STRING(cti_##op) "\n" \
   1023         HIDE_SYMBOL(cti_##op) "\n"             \
   1024         ".thumb" "\n" \
   1025         ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \
   1026         SYMBOL_STRING(cti_##op) ":" "\n" \
   1027         "str lr, [sp, #0x1c]" "\n" \
   1028         "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
   1029         "ldr lr, [sp, #0x1c]" "\n" \
   1030         "bx lr" "\n" \
   1031         ); \
   1032     rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
   1033 
   1034 #elif CPU(ARM_TRADITIONAL) && COMPILER(GCC)
   1035 
   1036 #if USE(JSVALUE32_64)
   1037 #define THUNK_RETURN_ADDRESS_OFFSET 64
   1038 #else
   1039 #define THUNK_RETURN_ADDRESS_OFFSET 32
   1040 #endif
   1041 
   1042 COMPILE_ASSERT(offsetof(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET, JITStackFrame_thunkReturnAddress_offset_mismatch);
   1043 
   1044 #define DEFINE_STUB_FUNCTION(rtype, op) \
   1045     extern "C" { \
   1046         rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
   1047     }; \
   1048     asm volatile ( \
   1049         ".globl " SYMBOL_STRING(cti_##op) "\n" \
   1050         SYMBOL_STRING(cti_##op) ":" "\n" \
   1051         "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
   1052         "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
   1053         "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
   1054         "mov pc, lr" "\n" \
   1055         ); \
   1056     rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
   1057 
   1058 #elif CPU(ARM_TRADITIONAL) && COMPILER(RVCT)
   1059 
   1060 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
   1061 
   1062 /* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */
   1063 
   1064 /* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */
   1065 /* The pattern "#xxx#" will be replaced with "xxx" */
   1066 
   1067 /*
   1068 RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
   1069 RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
   1070 RVCT({)
   1071 RVCT(    ARM)
   1072 RVCT(    IMPORT JITStubThunked_#op#)
   1073 RVCT(    str lr, [sp, #32])
   1074 RVCT(    bl JITStubThunked_#op#)
   1075 RVCT(    ldr lr, [sp, #32])
   1076 RVCT(    bx lr)
   1077 RVCT(})
   1078 RVCT()
   1079 */
   1080 
   1081 /* Include the generated file */
   1082 #include "GeneratedJITStubs_RVCT.h"
   1083 
   1084 #else
   1085 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
   1086 #endif
   1087 
   1088 DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this)
   1089 {
   1090     STUB_INIT_STACK_FRAME(stackFrame);
   1091 
   1092     JSValue v1 = stackFrame.args[0].jsValue();
   1093     CallFrame* callFrame = stackFrame.callFrame;
   1094 
   1095     JSObject* result = v1.toThisObject(callFrame);
   1096     CHECK_FOR_EXCEPTION_AT_END();
   1097     return JSValue::encode(result);
   1098 }
   1099 
   1100 DEFINE_STUB_FUNCTION(void, op_end)
   1101 {
   1102     STUB_INIT_STACK_FRAME(stackFrame);
   1103 
   1104     ScopeChainNode* scopeChain = stackFrame.callFrame->scopeChain();
   1105     ASSERT(scopeChain->refCount > 1);
   1106     scopeChain->deref();
   1107 }
   1108 
   1109 DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
   1110 {
   1111     STUB_INIT_STACK_FRAME(stackFrame);
   1112 
   1113     JSValue v1 = stackFrame.args[0].jsValue();
   1114     JSValue v2 = stackFrame.args[1].jsValue();
   1115     CallFrame* callFrame = stackFrame.callFrame;
   1116 
   1117     if (v1.isString()) {
   1118         JSValue result = v2.isString()
   1119             ? jsString(callFrame, asString(v1), asString(v2))
   1120             : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
   1121         CHECK_FOR_EXCEPTION_AT_END();
   1122         return JSValue::encode(result);
   1123     }
   1124 
   1125     double left = 0.0, right;
   1126     if (v1.getNumber(left) && v2.getNumber(right))
   1127         return JSValue::encode(jsNumber(stackFrame.globalData, left + right));
   1128 
   1129     // All other cases are pretty uncommon
   1130     JSValue result = jsAddSlowCase(callFrame, v1, v2);
   1131     CHECK_FOR_EXCEPTION_AT_END();
   1132     return JSValue::encode(result);
   1133 }
   1134 
   1135 DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_inc)
   1136 {
   1137     STUB_INIT_STACK_FRAME(stackFrame);
   1138 
   1139     JSValue v = stackFrame.args[0].jsValue();
   1140 
   1141     CallFrame* callFrame = stackFrame.callFrame;
   1142     JSValue result = jsNumber(stackFrame.globalData, v.toNumber(callFrame) + 1);
   1143     CHECK_FOR_EXCEPTION_AT_END();
   1144     return JSValue::encode(result);
   1145 }
   1146 
   1147 DEFINE_STUB_FUNCTION(int, timeout_check)
   1148 {
   1149     STUB_INIT_STACK_FRAME(stackFrame);
   1150 
   1151     JSGlobalData* globalData = stackFrame.globalData;
   1152     TimeoutChecker& timeoutChecker = globalData->timeoutChecker;
   1153 
   1154     if (timeoutChecker.didTimeOut(stackFrame.callFrame)) {
   1155         globalData->exception = createInterruptedExecutionException(globalData);
   1156         VM_THROW_EXCEPTION_AT_END();
   1157     }
   1158 
   1159     return timeoutChecker.ticksUntilNextCheck();
   1160 }
   1161 
   1162 DEFINE_STUB_FUNCTION(void, register_file_check)
   1163 {
   1164     STUB_INIT_STACK_FRAME(stackFrame);
   1165 
   1166     if (LIKELY(stackFrame.registerFile->grow(&stackFrame.callFrame->registers()[stackFrame.callFrame->codeBlock()->m_numCalleeRegisters])))
   1167         return;
   1168 
   1169     // Rewind to the previous call frame because op_call already optimistically
   1170     // moved the call frame forward.
   1171     CallFrame* oldCallFrame = stackFrame.callFrame->callerFrame();
   1172     stackFrame.callFrame = oldCallFrame;
   1173     throwStackOverflowError(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS);
   1174 }
   1175 
   1176 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
   1177 {
   1178     STUB_INIT_STACK_FRAME(stackFrame);
   1179 
   1180     JSValue src1 = stackFrame.args[0].jsValue();
   1181     JSValue src2 = stackFrame.args[1].jsValue();
   1182     CallFrame* callFrame = stackFrame.callFrame;
   1183 
   1184     bool result = jsLessEq(callFrame, src1, src2);
   1185     CHECK_FOR_EXCEPTION_AT_END();
   1186     return result;
   1187 }
   1188 
   1189 DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
   1190 {
   1191     STUB_INIT_STACK_FRAME(stackFrame);
   1192 
   1193     return constructEmptyObject(stackFrame.callFrame);
   1194 }
   1195 
   1196 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
   1197 {
   1198     STUB_INIT_STACK_FRAME(stackFrame);
   1199 
   1200     PutPropertySlot slot;
   1201     stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
   1202     CHECK_FOR_EXCEPTION_AT_END();
   1203 }
   1204 
   1205 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
   1206 {
   1207     STUB_INIT_STACK_FRAME(stackFrame);
   1208 
   1209     CallFrame* callFrame = stackFrame.callFrame;
   1210     Identifier& ident = stackFrame.args[1].identifier();
   1211 
   1212     JSValue baseValue = stackFrame.args[0].jsValue();
   1213     PropertySlot slot(baseValue);
   1214     JSValue result = baseValue.get(callFrame, ident, slot);
   1215 
   1216     CHECK_FOR_EXCEPTION_AT_END();
   1217     return JSValue::encode(result);
   1218 }
   1219 
   1220 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
   1221 
   1222 DEFINE_STUB_FUNCTION(void, op_put_by_id)
   1223 {
   1224     STUB_INIT_STACK_FRAME(stackFrame);
   1225     CallFrame* callFrame = stackFrame.callFrame;
   1226     Identifier& ident = stackFrame.args[1].identifier();
   1227 
   1228     PutPropertySlot slot;
   1229     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
   1230 
   1231     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
   1232     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
   1233     if (!stubInfo->seenOnce())
   1234         stubInfo->setSeen();
   1235     else
   1236         JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo);
   1237 
   1238     CHECK_FOR_EXCEPTION_AT_END();
   1239 }
   1240 
   1241 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
   1242 {
   1243     STUB_INIT_STACK_FRAME(stackFrame);
   1244 
   1245     CallFrame* callFrame = stackFrame.callFrame;
   1246     Identifier& ident = stackFrame.args[1].identifier();
   1247 
   1248     PutPropertySlot slot;
   1249     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
   1250 
   1251     CHECK_FOR_EXCEPTION_AT_END();
   1252 }
   1253 
   1254 DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
   1255 {
   1256     STUB_INIT_STACK_FRAME(stackFrame);
   1257 
   1258     JSValue baseValue = stackFrame.args[0].jsValue();
   1259     int32_t oldSize = stackFrame.args[3].int32();
   1260     int32_t newSize = stackFrame.args[4].int32();
   1261 
   1262     ASSERT(baseValue.isObject());
   1263     JSObject* base = asObject(baseValue);
   1264     base->allocatePropertyStorage(oldSize, newSize);
   1265 
   1266     return base;
   1267 }
   1268 
   1269 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
   1270 {
   1271     STUB_INIT_STACK_FRAME(stackFrame);
   1272 
   1273     CallFrame* callFrame = stackFrame.callFrame;
   1274     Identifier& ident = stackFrame.args[1].identifier();
   1275 
   1276     JSValue baseValue = stackFrame.args[0].jsValue();
   1277     PropertySlot slot(baseValue);
   1278     JSValue result = baseValue.get(callFrame, ident, slot);
   1279     CHECK_FOR_EXCEPTION();
   1280 
   1281     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
   1282     MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
   1283 
   1284     if (!methodCallLinkInfo.seenOnce()) {
   1285         methodCallLinkInfo.setSeen();
   1286         return JSValue::encode(result);
   1287     }
   1288 
   1289     // If we successfully got something, then the base from which it is being accessed must
   1290     // be an object.  (Assertion to ensure asObject() call below is safe, which comes after
   1291     // an isCacheable() chceck.
   1292     ASSERT(!slot.isCacheable() || slot.slotBase().isObject());
   1293 
   1294     // Check that:
   1295     //   * We're dealing with a JSCell,
   1296     //   * the property is cachable,
   1297     //   * it's not a dictionary
   1298     //   * there is a function cached.
   1299     Structure* structure;
   1300     JSCell* specific;
   1301     JSObject* slotBaseObject;
   1302     if (baseValue.isCell()
   1303         && slot.isCacheable()
   1304         && !(structure = asCell(baseValue)->structure())->isUncacheableDictionary()
   1305         && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
   1306         && specific
   1307         ) {
   1308 
   1309         JSFunction* callee = (JSFunction*)specific;
   1310 
   1311         // Since we're accessing a prototype in a loop, it's a good bet that it
   1312         // should not be treated as a dictionary.
   1313         if (slotBaseObject->structure()->isDictionary())
   1314             slotBaseObject->flattenDictionaryObject();
   1315 
   1316         // The result fetched should always be the callee!
   1317         ASSERT(result == JSValue(callee));
   1318 
   1319         // Check to see if the function is on the object's prototype.  Patch up the code to optimize.
   1320         if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
   1321             JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
   1322             return JSValue::encode(result);
   1323         }
   1324 
   1325         // Check to see if the function is on the object itself.
   1326         // Since we generate the method-check to check both the structure and a prototype-structure (since this
   1327         // is the common case) we have a problem - we need to patch the prototype structure check to do something
   1328         // useful.  We could try to nop it out altogether, but that's a little messy, so lets do something simpler
   1329         // for now.  For now it performs a check on a special object on the global object only used for this
   1330         // purpose.  The object is in no way exposed, and as such the check will always pass.
   1331         if (slot.slotBase() == baseValue) {
   1332             JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
   1333             return JSValue::encode(result);
   1334         }
   1335     }
   1336 
   1337     // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
   1338     ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
   1339     return JSValue::encode(result);
   1340 }
   1341 
   1342 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
   1343 {
   1344     STUB_INIT_STACK_FRAME(stackFrame);
   1345     CallFrame* callFrame = stackFrame.callFrame;
   1346     Identifier& ident = stackFrame.args[1].identifier();
   1347 
   1348     JSValue baseValue = stackFrame.args[0].jsValue();
   1349     PropertySlot slot(baseValue);
   1350     JSValue result = baseValue.get(callFrame, ident, slot);
   1351 
   1352     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
   1353     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
   1354     if (!stubInfo->seenOnce())
   1355         stubInfo->setSeen();
   1356     else
   1357         JITThunks::tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo);
   1358 
   1359     CHECK_FOR_EXCEPTION_AT_END();
   1360     return JSValue::encode(result);
   1361 }
   1362 
   1363 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
   1364 {
   1365     STUB_INIT_STACK_FRAME(stackFrame);
   1366 
   1367     CallFrame* callFrame = stackFrame.callFrame;
   1368     Identifier& ident = stackFrame.args[1].identifier();
   1369 
   1370     JSValue baseValue = stackFrame.args[0].jsValue();
   1371     PropertySlot slot(baseValue);
   1372     JSValue result = baseValue.get(callFrame, ident, slot);
   1373 
   1374     CHECK_FOR_EXCEPTION();
   1375 
   1376     if (baseValue.isCell()
   1377         && slot.isCacheable()
   1378         && !asCell(baseValue)->structure()->isUncacheableDictionary()
   1379         && slot.slotBase() == baseValue) {
   1380 
   1381         CodeBlock* codeBlock = callFrame->codeBlock();
   1382         StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
   1383 
   1384         ASSERT(slot.slotBase().isObject());
   1385 
   1386         PolymorphicAccessStructureList* polymorphicStructureList;
   1387         int listIndex = 1;
   1388 
   1389         if (stubInfo->accessType == access_get_by_id_self) {
   1390             ASSERT(!stubInfo->stubRoutine);
   1391             polymorphicStructureList = new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure);
   1392             stubInfo->initGetByIdSelfList(polymorphicStructureList, 2);
   1393         } else {
   1394             polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
   1395             listIndex = stubInfo->u.getByIdSelfList.listSize;
   1396             stubInfo->u.getByIdSelfList.listSize++;
   1397         }
   1398 
   1399         JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset());
   1400 
   1401         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
   1402             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
   1403     } else
   1404         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
   1405     return JSValue::encode(result);
   1406 }
   1407 
   1408 static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex)
   1409 {
   1410     PolymorphicAccessStructureList* prototypeStructureList = 0;
   1411     listIndex = 1;
   1412 
   1413     switch (stubInfo->accessType) {
   1414     case access_get_by_id_proto:
   1415         prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
   1416         stubInfo->stubRoutine = CodeLocationLabel();
   1417         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
   1418         break;
   1419     case access_get_by_id_chain:
   1420         prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
   1421         stubInfo->stubRoutine = CodeLocationLabel();
   1422         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
   1423         break;
   1424     case access_get_by_id_proto_list:
   1425         prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
   1426         listIndex = stubInfo->u.getByIdProtoList.listSize;
   1427         stubInfo->u.getByIdProtoList.listSize++;
   1428         break;
   1429     default:
   1430         ASSERT_NOT_REACHED();
   1431     }
   1432 
   1433     ASSERT(listIndex < POLYMORPHIC_LIST_CACHE_SIZE);
   1434     return prototypeStructureList;
   1435 }
   1436 
   1437 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
   1438 {
   1439     STUB_INIT_STACK_FRAME(stackFrame);
   1440 
   1441     CallFrame* callFrame = stackFrame.callFrame;
   1442     const Identifier& propertyName = stackFrame.args[1].identifier();
   1443 
   1444     JSValue baseValue = stackFrame.args[0].jsValue();
   1445     PropertySlot slot(baseValue);
   1446     JSValue result = baseValue.get(callFrame, propertyName, slot);
   1447 
   1448     CHECK_FOR_EXCEPTION();
   1449 
   1450     if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
   1451         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
   1452         return JSValue::encode(result);
   1453     }
   1454 
   1455     Structure* structure = asCell(baseValue)->structure();
   1456     CodeBlock* codeBlock = callFrame->codeBlock();
   1457     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
   1458 
   1459     ASSERT(slot.slotBase().isObject());
   1460     JSObject* slotBaseObject = asObject(slot.slotBase());
   1461 
   1462     size_t offset = slot.cachedOffset();
   1463 
   1464     if (slot.slotBase() == baseValue)
   1465         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
   1466     else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) {
   1467         ASSERT(!asCell(baseValue)->structure()->isDictionary());
   1468         // Since we're accessing a prototype in a loop, it's a good bet that it
   1469         // should not be treated as a dictionary.
   1470         if (slotBaseObject->structure()->isDictionary()) {
   1471             slotBaseObject->flattenDictionaryObject();
   1472             offset = slotBaseObject->structure()->get(propertyName);
   1473         }
   1474 
   1475         int listIndex;
   1476         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
   1477 
   1478         JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), offset);
   1479 
   1480         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
   1481             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
   1482     } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
   1483         ASSERT(!asCell(baseValue)->structure()->isDictionary());
   1484         int listIndex;
   1485         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
   1486 
   1487         StructureChain* protoChain = structure->prototypeChain(callFrame);
   1488         JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, offset);
   1489 
   1490         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
   1491             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
   1492     } else
   1493         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
   1494 
   1495     return JSValue::encode(result);
   1496 }
   1497 
   1498 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full)
   1499 {
   1500     STUB_INIT_STACK_FRAME(stackFrame);
   1501 
   1502     JSValue baseValue = stackFrame.args[0].jsValue();
   1503     PropertySlot slot(baseValue);
   1504     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
   1505 
   1506     CHECK_FOR_EXCEPTION_AT_END();
   1507     return JSValue::encode(result);
   1508 }
   1509 
   1510 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_fail)
   1511 {
   1512     STUB_INIT_STACK_FRAME(stackFrame);
   1513 
   1514     JSValue baseValue = stackFrame.args[0].jsValue();
   1515     PropertySlot slot(baseValue);
   1516     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
   1517 
   1518     CHECK_FOR_EXCEPTION_AT_END();
   1519     return JSValue::encode(result);
   1520 }
   1521 
   1522 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_array_fail)
   1523 {
   1524     STUB_INIT_STACK_FRAME(stackFrame);
   1525 
   1526     JSValue baseValue = stackFrame.args[0].jsValue();
   1527     PropertySlot slot(baseValue);
   1528     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
   1529 
   1530     CHECK_FOR_EXCEPTION_AT_END();
   1531     return JSValue::encode(result);
   1532 }
   1533 
   1534 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
   1535 {
   1536     STUB_INIT_STACK_FRAME(stackFrame);
   1537 
   1538     JSValue baseValue = stackFrame.args[0].jsValue();
   1539     PropertySlot slot(baseValue);
   1540     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
   1541 
   1542     CHECK_FOR_EXCEPTION_AT_END();
   1543     return JSValue::encode(result);
   1544 }
   1545 
   1546 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
   1547 
   1548 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
   1549 {
   1550     STUB_INIT_STACK_FRAME(stackFrame);
   1551 
   1552     CallFrame* callFrame = stackFrame.callFrame;
   1553     JSValue value = stackFrame.args[0].jsValue();
   1554     JSValue baseVal = stackFrame.args[1].jsValue();
   1555     JSValue proto = stackFrame.args[2].jsValue();
   1556 
   1557     // At least one of these checks must have failed to get to the slow case.
   1558     ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
   1559            || !value.isObject() || !baseVal.isObject() || !proto.isObject()
   1560            || (asObject(baseVal)->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance);
   1561 
   1562 
   1563     // ECMA-262 15.3.5.3:
   1564     // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
   1565     TypeInfo typeInfo(UnspecifiedType);
   1566     if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) {
   1567         CallFrame* callFrame = stackFrame.callFrame;
   1568         CodeBlock* codeBlock = callFrame->codeBlock();
   1569         unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   1570         stackFrame.globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, vPCIndex, codeBlock);
   1571         VM_THROW_EXCEPTION();
   1572     }
   1573     ASSERT(typeInfo.type() != UnspecifiedType);
   1574 
   1575     if (!typeInfo.overridesHasInstance()) {
   1576         if (!value.isObject())
   1577             return JSValue::encode(jsBoolean(false));
   1578 
   1579         if (!proto.isObject()) {
   1580             throwError(callFrame, TypeError, "instanceof called on an object with an invalid prototype property.");
   1581             VM_THROW_EXCEPTION();
   1582         }
   1583     }
   1584 
   1585     JSValue result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
   1586     CHECK_FOR_EXCEPTION_AT_END();
   1587 
   1588     return JSValue::encode(result);
   1589 }
   1590 
   1591 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
   1592 {
   1593     STUB_INIT_STACK_FRAME(stackFrame);
   1594 
   1595     CallFrame* callFrame = stackFrame.callFrame;
   1596 
   1597     JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
   1598 
   1599     JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier()));
   1600     CHECK_FOR_EXCEPTION_AT_END();
   1601     return JSValue::encode(result);
   1602 }
   1603 
   1604 DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul)
   1605 {
   1606     STUB_INIT_STACK_FRAME(stackFrame);
   1607 
   1608     JSValue src1 = stackFrame.args[0].jsValue();
   1609     JSValue src2 = stackFrame.args[1].jsValue();
   1610 
   1611     double left;
   1612     double right;
   1613     if (src1.getNumber(left) && src2.getNumber(right))
   1614         return JSValue::encode(jsNumber(stackFrame.globalData, left * right));
   1615 
   1616     CallFrame* callFrame = stackFrame.callFrame;
   1617     JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) * src2.toNumber(callFrame));
   1618     CHECK_FOR_EXCEPTION_AT_END();
   1619     return JSValue::encode(result);
   1620 }
   1621 
   1622 DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
   1623 {
   1624     STUB_INIT_STACK_FRAME(stackFrame);
   1625 
   1626     return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
   1627 }
   1628 
   1629 DEFINE_STUB_FUNCTION(void*, op_call_JSFunction)
   1630 {
   1631     STUB_INIT_STACK_FRAME(stackFrame);
   1632 
   1633 #if !ASSERT_DISABLED
   1634     CallData callData;
   1635     ASSERT(stackFrame.args[0].jsValue().getCallData(callData) == CallTypeJS);
   1636 #endif
   1637 
   1638     JSFunction* function = asFunction(stackFrame.args[0].jsValue());
   1639     ASSERT(!function->isHostFunction());
   1640     FunctionExecutable* executable = function->jsExecutable();
   1641     ScopeChainNode* callDataScopeChain = function->scope().node();
   1642     executable->jitCode(stackFrame.callFrame, callDataScopeChain);
   1643 
   1644     return function;
   1645 }
   1646 
   1647 DEFINE_STUB_FUNCTION(VoidPtrPair, op_call_arityCheck)
   1648 {
   1649     STUB_INIT_STACK_FRAME(stackFrame);
   1650 
   1651     CallFrame* callFrame = stackFrame.callFrame;
   1652     JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
   1653     ASSERT(!callee->isHostFunction());
   1654     CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecode();
   1655     int argCount = stackFrame.args[2].int32();
   1656 
   1657     ASSERT(argCount != newCodeBlock->m_numParameters);
   1658 
   1659     CallFrame* oldCallFrame = callFrame->callerFrame();
   1660 
   1661     if (argCount > newCodeBlock->m_numParameters) {
   1662         size_t numParameters = newCodeBlock->m_numParameters;
   1663         Register* r = callFrame->registers() + numParameters;
   1664 
   1665         Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
   1666         for (size_t i = 0; i < numParameters; ++i)
   1667             argv[i + argCount] = argv[i];
   1668 
   1669         callFrame = CallFrame::create(r);
   1670         callFrame->setCallerFrame(oldCallFrame);
   1671     } else {
   1672         size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
   1673         Register* r = callFrame->registers() + omittedArgCount;
   1674         Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
   1675         if (!stackFrame.registerFile->grow(newEnd)) {
   1676             // Rewind to the previous call frame because op_call already optimistically
   1677             // moved the call frame forward.
   1678             stackFrame.callFrame = oldCallFrame;
   1679             throwStackOverflowError(oldCallFrame, stackFrame.globalData, stackFrame.args[1].returnAddress(), STUB_RETURN_ADDRESS);
   1680             RETURN_POINTER_PAIR(0, 0);
   1681         }
   1682 
   1683         Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
   1684         for (size_t i = 0; i < omittedArgCount; ++i)
   1685             argv[i] = jsUndefined();
   1686 
   1687         callFrame = CallFrame::create(r);
   1688         callFrame->setCallerFrame(oldCallFrame);
   1689     }
   1690 
   1691     RETURN_POINTER_PAIR(callee, callFrame);
   1692 }
   1693 
   1694 #if ENABLE(JIT_OPTIMIZE_CALL)
   1695 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
   1696 {
   1697     STUB_INIT_STACK_FRAME(stackFrame);
   1698     JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
   1699     ExecutableBase* executable = callee->executable();
   1700     JITCode& jitCode = executable->generatedJITCode();
   1701 
   1702     CodeBlock* codeBlock = 0;
   1703     if (!executable->isHostFunction())
   1704         codeBlock = &static_cast<FunctionExecutable*>(executable)->bytecode(stackFrame.callFrame, callee->scope().node());
   1705     CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress());
   1706 
   1707     if (!callLinkInfo->seenOnce())
   1708         callLinkInfo->setSeen();
   1709     else
   1710         JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData);
   1711 
   1712     return jitCode.addressForCall().executableAddress();
   1713 }
   1714 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
   1715 
   1716 DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
   1717 {
   1718     STUB_INIT_STACK_FRAME(stackFrame);
   1719 
   1720     JSActivation* activation = new (stackFrame.globalData) JSActivation(stackFrame.callFrame, static_cast<FunctionExecutable*>(stackFrame.callFrame->codeBlock()->ownerExecutable()));
   1721     stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->copy()->push(activation));
   1722     return activation;
   1723 }
   1724 
   1725 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
   1726 {
   1727     STUB_INIT_STACK_FRAME(stackFrame);
   1728 
   1729     JSValue funcVal = stackFrame.args[0].jsValue();
   1730 
   1731     CallData callData;
   1732     CallType callType = funcVal.getCallData(callData);
   1733 
   1734     ASSERT(callType != CallTypeJS);
   1735 
   1736     if (callType == CallTypeHost) {
   1737         int registerOffset = stackFrame.args[1].int32();
   1738         int argCount = stackFrame.args[2].int32();
   1739         CallFrame* previousCallFrame = stackFrame.callFrame;
   1740         CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
   1741 
   1742         callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0);
   1743         stackFrame.callFrame = callFrame;
   1744 
   1745         Register* argv = stackFrame.callFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
   1746         ArgList argList(argv + 1, argCount - 1);
   1747 
   1748         JSValue returnValue;
   1749         {
   1750             SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
   1751 
   1752             // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
   1753             JSValue thisValue = argv[0].jsValue();
   1754             if (thisValue == jsNull())
   1755                 thisValue = callFrame->globalThisValue();
   1756 
   1757             returnValue = callData.native.function(callFrame, asObject(funcVal), thisValue, argList);
   1758         }
   1759         stackFrame.callFrame = previousCallFrame;
   1760         CHECK_FOR_EXCEPTION();
   1761 
   1762         return JSValue::encode(returnValue);
   1763     }
   1764 
   1765     ASSERT(callType == CallTypeNone);
   1766 
   1767     CallFrame* callFrame = stackFrame.callFrame;
   1768     CodeBlock* codeBlock = callFrame->codeBlock();
   1769     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   1770     stackFrame.globalData->exception = createNotAFunctionError(stackFrame.callFrame, funcVal, vPCIndex, codeBlock);
   1771     VM_THROW_EXCEPTION();
   1772 }
   1773 
   1774 DEFINE_STUB_FUNCTION(void, op_create_arguments)
   1775 {
   1776     STUB_INIT_STACK_FRAME(stackFrame);
   1777 
   1778     Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame);
   1779     stackFrame.callFrame->setCalleeArguments(arguments);
   1780     stackFrame.callFrame[RegisterFile::ArgumentsRegister] = JSValue(arguments);
   1781 }
   1782 
   1783 DEFINE_STUB_FUNCTION(void, op_create_arguments_no_params)
   1784 {
   1785     STUB_INIT_STACK_FRAME(stackFrame);
   1786 
   1787     Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame, Arguments::NoParameters);
   1788     stackFrame.callFrame->setCalleeArguments(arguments);
   1789     stackFrame.callFrame[RegisterFile::ArgumentsRegister] = JSValue(arguments);
   1790 }
   1791 
   1792 DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
   1793 {
   1794     STUB_INIT_STACK_FRAME(stackFrame);
   1795 
   1796     ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
   1797     asActivation(stackFrame.args[0].jsValue())->copyRegisters(stackFrame.callFrame->optionalCalleeArguments());
   1798 }
   1799 
   1800 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
   1801 {
   1802     STUB_INIT_STACK_FRAME(stackFrame);
   1803 
   1804     ASSERT(stackFrame.callFrame->codeBlock()->usesArguments() && !stackFrame.callFrame->codeBlock()->needsFullScopeChain());
   1805     if (stackFrame.callFrame->optionalCalleeArguments())
   1806         stackFrame.callFrame->optionalCalleeArguments()->copyRegisters();
   1807 }
   1808 
   1809 DEFINE_STUB_FUNCTION(void, op_profile_will_call)
   1810 {
   1811     STUB_INIT_STACK_FRAME(stackFrame);
   1812 
   1813     ASSERT(*stackFrame.enabledProfilerReference);
   1814     (*stackFrame.enabledProfilerReference)->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
   1815 }
   1816 
   1817 DEFINE_STUB_FUNCTION(void, op_profile_did_call)
   1818 {
   1819     STUB_INIT_STACK_FRAME(stackFrame);
   1820 
   1821     ASSERT(*stackFrame.enabledProfilerReference);
   1822     (*stackFrame.enabledProfilerReference)->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
   1823 }
   1824 
   1825 DEFINE_STUB_FUNCTION(void, op_ret_scopeChain)
   1826 {
   1827     STUB_INIT_STACK_FRAME(stackFrame);
   1828 
   1829     ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
   1830     stackFrame.callFrame->scopeChain()->deref();
   1831 }
   1832 
   1833 DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
   1834 {
   1835     STUB_INIT_STACK_FRAME(stackFrame);
   1836 
   1837     ArgList argList(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
   1838     return constructArray(stackFrame.callFrame, argList);
   1839 }
   1840 
   1841 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
   1842 {
   1843     STUB_INIT_STACK_FRAME(stackFrame);
   1844 
   1845     CallFrame* callFrame = stackFrame.callFrame;
   1846     ScopeChainNode* scopeChain = callFrame->scopeChain();
   1847 
   1848     ScopeChainIterator iter = scopeChain->begin();
   1849     ScopeChainIterator end = scopeChain->end();
   1850     ASSERT(iter != end);
   1851 
   1852     Identifier& ident = stackFrame.args[0].identifier();
   1853     do {
   1854         JSObject* o = *iter;
   1855         PropertySlot slot(o);
   1856         if (o->getPropertySlot(callFrame, ident, slot)) {
   1857             JSValue result = slot.getValue(callFrame, ident);
   1858             CHECK_FOR_EXCEPTION_AT_END();
   1859             return JSValue::encode(result);
   1860         }
   1861     } while (++iter != end);
   1862 
   1863     CodeBlock* codeBlock = callFrame->codeBlock();
   1864     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   1865     stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
   1866     VM_THROW_EXCEPTION();
   1867 }
   1868 
   1869 DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct)
   1870 {
   1871     STUB_INIT_STACK_FRAME(stackFrame);
   1872 
   1873     JSFunction* constructor = asFunction(stackFrame.args[0].jsValue());
   1874     if (constructor->isHostFunction()) {
   1875         CallFrame* callFrame = stackFrame.callFrame;
   1876         CodeBlock* codeBlock = callFrame->codeBlock();
   1877         unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   1878         stackFrame.globalData->exception = createNotAConstructorError(callFrame, constructor, vPCIndex, codeBlock);
   1879         VM_THROW_EXCEPTION();
   1880     }
   1881 
   1882 #if !ASSERT_DISABLED
   1883     ConstructData constructData;
   1884     ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
   1885 #endif
   1886 
   1887     Structure* structure;
   1888     if (stackFrame.args[3].jsValue().isObject())
   1889         structure = asObject(stackFrame.args[3].jsValue())->inheritorID();
   1890     else
   1891         structure = constructor->scope().node()->globalObject->emptyObjectStructure();
   1892     return new (stackFrame.globalData) JSObject(structure);
   1893 }
   1894 
   1895 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
   1896 {
   1897     STUB_INIT_STACK_FRAME(stackFrame);
   1898 
   1899     CallFrame* callFrame = stackFrame.callFrame;
   1900 
   1901     JSValue constrVal = stackFrame.args[0].jsValue();
   1902     int argCount = stackFrame.args[2].int32();
   1903     int thisRegister = stackFrame.args[4].int32();
   1904 
   1905     ConstructData constructData;
   1906     ConstructType constructType = constrVal.getConstructData(constructData);
   1907 
   1908     if (constructType == ConstructTypeHost) {
   1909         ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1);
   1910 
   1911         JSValue returnValue;
   1912         {
   1913             SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
   1914             returnValue = constructData.native.function(callFrame, asObject(constrVal), argList);
   1915         }
   1916         CHECK_FOR_EXCEPTION();
   1917 
   1918         return JSValue::encode(returnValue);
   1919     }
   1920 
   1921     ASSERT(constructType == ConstructTypeNone);
   1922 
   1923     CodeBlock* codeBlock = callFrame->codeBlock();
   1924     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   1925     stackFrame.globalData->exception = createNotAConstructorError(callFrame, constrVal, vPCIndex, codeBlock);
   1926     VM_THROW_EXCEPTION();
   1927 }
   1928 
   1929 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
   1930 {
   1931     STUB_INIT_STACK_FRAME(stackFrame);
   1932 
   1933     CallFrame* callFrame = stackFrame.callFrame;
   1934     JSGlobalData* globalData = stackFrame.globalData;
   1935 
   1936     JSValue baseValue = stackFrame.args[0].jsValue();
   1937     JSValue subscript = stackFrame.args[1].jsValue();
   1938 
   1939     JSValue result;
   1940 
   1941     if (LIKELY(subscript.isUInt32())) {
   1942         uint32_t i = subscript.asUInt32();
   1943         if (isJSArray(globalData, baseValue)) {
   1944             JSArray* jsArray = asArray(baseValue);
   1945             if (jsArray->canGetIndex(i))
   1946                 result = jsArray->getIndex(i);
   1947             else
   1948                 result = jsArray->JSArray::get(callFrame, i);
   1949         } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
   1950             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
   1951             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
   1952             result = asString(baseValue)->getIndex(callFrame, i);
   1953         } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
   1954             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
   1955             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
   1956             return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
   1957         } else
   1958             result = baseValue.get(callFrame, i);
   1959     } else {
   1960         Identifier property(callFrame, subscript.toString(callFrame));
   1961         result = baseValue.get(callFrame, property);
   1962     }
   1963 
   1964     CHECK_FOR_EXCEPTION_AT_END();
   1965     return JSValue::encode(result);
   1966 }
   1967 
   1968 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
   1969 {
   1970     STUB_INIT_STACK_FRAME(stackFrame);
   1971 
   1972     CallFrame* callFrame = stackFrame.callFrame;
   1973     JSGlobalData* globalData = stackFrame.globalData;
   1974 
   1975     JSValue baseValue = stackFrame.args[0].jsValue();
   1976     JSValue subscript = stackFrame.args[1].jsValue();
   1977 
   1978     JSValue result;
   1979 
   1980     if (LIKELY(subscript.isUInt32())) {
   1981         uint32_t i = subscript.asUInt32();
   1982         if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
   1983             result = asString(baseValue)->getIndex(callFrame, i);
   1984         else {
   1985             result = baseValue.get(callFrame, i);
   1986             if (!isJSString(globalData, baseValue))
   1987                 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
   1988         }
   1989     } else {
   1990         Identifier property(callFrame, subscript.toString(callFrame));
   1991         result = baseValue.get(callFrame, property);
   1992     }
   1993 
   1994     CHECK_FOR_EXCEPTION_AT_END();
   1995     return JSValue::encode(result);
   1996 }
   1997 
   1998 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_byte_array)
   1999 {
   2000     STUB_INIT_STACK_FRAME(stackFrame);
   2001 
   2002     CallFrame* callFrame = stackFrame.callFrame;
   2003     JSGlobalData* globalData = stackFrame.globalData;
   2004 
   2005     JSValue baseValue = stackFrame.args[0].jsValue();
   2006     JSValue subscript = stackFrame.args[1].jsValue();
   2007 
   2008     JSValue result;
   2009 
   2010     if (LIKELY(subscript.isUInt32())) {
   2011         uint32_t i = subscript.asUInt32();
   2012         if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
   2013             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
   2014             return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
   2015         }
   2016 
   2017         result = baseValue.get(callFrame, i);
   2018         if (!isJSByteArray(globalData, baseValue))
   2019             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
   2020     } else {
   2021         Identifier property(callFrame, subscript.toString(callFrame));
   2022         result = baseValue.get(callFrame, property);
   2023     }
   2024 
   2025     CHECK_FOR_EXCEPTION_AT_END();
   2026     return JSValue::encode(result);
   2027 }
   2028 
   2029 DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub)
   2030 {
   2031     STUB_INIT_STACK_FRAME(stackFrame);
   2032 
   2033     JSValue src1 = stackFrame.args[0].jsValue();
   2034     JSValue src2 = stackFrame.args[1].jsValue();
   2035 
   2036     double left;
   2037     double right;
   2038     if (src1.getNumber(left) && src2.getNumber(right))
   2039         return JSValue::encode(jsNumber(stackFrame.globalData, left - right));
   2040 
   2041     CallFrame* callFrame = stackFrame.callFrame;
   2042     JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) - src2.toNumber(callFrame));
   2043     CHECK_FOR_EXCEPTION_AT_END();
   2044     return JSValue::encode(result);
   2045 }
   2046 
   2047 DEFINE_STUB_FUNCTION(void, op_put_by_val)
   2048 {
   2049     STUB_INIT_STACK_FRAME(stackFrame);
   2050 
   2051     CallFrame* callFrame = stackFrame.callFrame;
   2052     JSGlobalData* globalData = stackFrame.globalData;
   2053 
   2054     JSValue baseValue = stackFrame.args[0].jsValue();
   2055     JSValue subscript = stackFrame.args[1].jsValue();
   2056     JSValue value = stackFrame.args[2].jsValue();
   2057 
   2058     if (LIKELY(subscript.isUInt32())) {
   2059         uint32_t i = subscript.asUInt32();
   2060         if (isJSArray(globalData, baseValue)) {
   2061             JSArray* jsArray = asArray(baseValue);
   2062             if (jsArray->canSetIndex(i))
   2063                 jsArray->setIndex(i, value);
   2064             else
   2065                 jsArray->JSArray::put(callFrame, i, value);
   2066         } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
   2067             JSByteArray* jsByteArray = asByteArray(baseValue);
   2068             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_byte_array));
   2069             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
   2070             if (value.isInt32()) {
   2071                 jsByteArray->setIndex(i, value.asInt32());
   2072                 return;
   2073             } else {
   2074                 double dValue = 0;
   2075                 if (value.getNumber(dValue)) {
   2076                     jsByteArray->setIndex(i, dValue);
   2077                     return;
   2078                 }
   2079             }
   2080 
   2081             baseValue.put(callFrame, i, value);
   2082         } else
   2083             baseValue.put(callFrame, i, value);
   2084     } else {
   2085         Identifier property(callFrame, subscript.toString(callFrame));
   2086         if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
   2087             PutPropertySlot slot;
   2088             baseValue.put(callFrame, property, value, slot);
   2089         }
   2090     }
   2091 
   2092     CHECK_FOR_EXCEPTION_AT_END();
   2093 }
   2094 
   2095 DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array)
   2096 {
   2097     STUB_INIT_STACK_FRAME(stackFrame);
   2098 
   2099     CallFrame* callFrame = stackFrame.callFrame;
   2100     JSGlobalData* globalData = stackFrame.globalData;
   2101 
   2102     JSValue baseValue = stackFrame.args[0].jsValue();
   2103     JSValue subscript = stackFrame.args[1].jsValue();
   2104     JSValue value = stackFrame.args[2].jsValue();
   2105 
   2106     if (LIKELY(subscript.isUInt32())) {
   2107         uint32_t i = subscript.asUInt32();
   2108         if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
   2109             JSByteArray* jsByteArray = asByteArray(baseValue);
   2110 
   2111             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
   2112             if (value.isInt32()) {
   2113                 jsByteArray->setIndex(i, value.asInt32());
   2114                 return;
   2115             } else {
   2116                 double dValue = 0;
   2117                 if (value.getNumber(dValue)) {
   2118                     jsByteArray->setIndex(i, dValue);
   2119                     return;
   2120                 }
   2121             }
   2122         }
   2123 
   2124         if (!isJSByteArray(globalData, baseValue))
   2125             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
   2126         baseValue.put(callFrame, i, value);
   2127     } else {
   2128         Identifier property(callFrame, subscript.toString(callFrame));
   2129         if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
   2130             PutPropertySlot slot;
   2131             baseValue.put(callFrame, property, value, slot);
   2132         }
   2133     }
   2134 
   2135     CHECK_FOR_EXCEPTION_AT_END();
   2136 }
   2137 
   2138 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
   2139 {
   2140     STUB_INIT_STACK_FRAME(stackFrame);
   2141 
   2142     CallFrame* callFrame = stackFrame.callFrame;
   2143     JSValue result = jsBoolean(jsLessEq(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
   2144     CHECK_FOR_EXCEPTION_AT_END();
   2145     return JSValue::encode(result);
   2146 }
   2147 
   2148 DEFINE_STUB_FUNCTION(int, op_load_varargs)
   2149 {
   2150     STUB_INIT_STACK_FRAME(stackFrame);
   2151 
   2152     CallFrame* callFrame = stackFrame.callFrame;
   2153     RegisterFile* registerFile = stackFrame.registerFile;
   2154     int argsOffset = stackFrame.args[0].int32();
   2155     JSValue arguments = callFrame->registers()[argsOffset].jsValue();
   2156     uint32_t argCount = 0;
   2157     if (!arguments) {
   2158         int providedParams = callFrame->registers()[RegisterFile::ArgumentCount].i() - 1;
   2159         argCount = providedParams;
   2160         int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   2161         Register* newEnd = callFrame->registers() + sizeDelta;
   2162         if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   2163             stackFrame.globalData->exception = createStackOverflowError(callFrame);
   2164             VM_THROW_EXCEPTION();
   2165         }
   2166         int32_t expectedParams = callFrame->callee()->jsExecutable()->parameterCount();
   2167         int32_t inplaceArgs = min(providedParams, expectedParams);
   2168 
   2169         Register* inplaceArgsDst = callFrame->registers() + argsOffset;
   2170 
   2171         Register* inplaceArgsEnd = inplaceArgsDst + inplaceArgs;
   2172         Register* inplaceArgsEnd2 = inplaceArgsDst + providedParams;
   2173 
   2174         Register* inplaceArgsSrc = callFrame->registers() - RegisterFile::CallFrameHeaderSize - expectedParams;
   2175         Register* inplaceArgsSrc2 = inplaceArgsSrc - providedParams - 1 + inplaceArgs;
   2176 
   2177         // First step is to copy the "expected" parameters from their normal location relative to the callframe
   2178         while (inplaceArgsDst < inplaceArgsEnd)
   2179             *inplaceArgsDst++ = *inplaceArgsSrc++;
   2180 
   2181         // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
   2182         while (inplaceArgsDst < inplaceArgsEnd2)
   2183             *inplaceArgsDst++ = *inplaceArgsSrc2++;
   2184 
   2185     } else if (!arguments.isUndefinedOrNull()) {
   2186         if (!arguments.isObject()) {
   2187             CodeBlock* codeBlock = callFrame->codeBlock();
   2188             unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   2189             stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
   2190             VM_THROW_EXCEPTION();
   2191         }
   2192         if (asObject(arguments)->classInfo() == &Arguments::info) {
   2193             Arguments* argsObject = asArguments(arguments);
   2194             argCount = argsObject->numProvidedArguments(callFrame);
   2195             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   2196             Register* newEnd = callFrame->registers() + sizeDelta;
   2197             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   2198                 stackFrame.globalData->exception = createStackOverflowError(callFrame);
   2199                 VM_THROW_EXCEPTION();
   2200             }
   2201             argsObject->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
   2202         } else if (isJSArray(&callFrame->globalData(), arguments)) {
   2203             JSArray* array = asArray(arguments);
   2204             argCount = array->length();
   2205             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   2206             Register* newEnd = callFrame->registers() + sizeDelta;
   2207             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   2208                 stackFrame.globalData->exception = createStackOverflowError(callFrame);
   2209                 VM_THROW_EXCEPTION();
   2210             }
   2211             array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
   2212         } else if (asObject(arguments)->inherits(&JSArray::info)) {
   2213             JSObject* argObject = asObject(arguments);
   2214             argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
   2215             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   2216             Register* newEnd = callFrame->registers() + sizeDelta;
   2217             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   2218                 stackFrame.globalData->exception = createStackOverflowError(callFrame);
   2219                 VM_THROW_EXCEPTION();
   2220             }
   2221             Register* argsBuffer = callFrame->registers() + argsOffset;
   2222             for (unsigned i = 0; i < argCount; ++i) {
   2223                 argsBuffer[i] = asObject(arguments)->get(callFrame, i);
   2224                 CHECK_FOR_EXCEPTION();
   2225             }
   2226         } else {
   2227             CodeBlock* codeBlock = callFrame->codeBlock();
   2228             unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   2229             stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
   2230             VM_THROW_EXCEPTION();
   2231         }
   2232     }
   2233 
   2234     return argCount + 1;
   2235 }
   2236 
   2237 DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate)
   2238 {
   2239     STUB_INIT_STACK_FRAME(stackFrame);
   2240 
   2241     JSValue src = stackFrame.args[0].jsValue();
   2242 
   2243     double v;
   2244     if (src.getNumber(v))
   2245         return JSValue::encode(jsNumber(stackFrame.globalData, -v));
   2246 
   2247     CallFrame* callFrame = stackFrame.callFrame;
   2248     JSValue result = jsNumber(stackFrame.globalData, -src.toNumber(callFrame));
   2249     CHECK_FOR_EXCEPTION_AT_END();
   2250     return JSValue::encode(result);
   2251 }
   2252 
   2253 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base)
   2254 {
   2255     STUB_INIT_STACK_FRAME(stackFrame);
   2256 
   2257     return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain()));
   2258 }
   2259 
   2260 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
   2261 {
   2262     STUB_INIT_STACK_FRAME(stackFrame);
   2263 
   2264     CallFrame* callFrame = stackFrame.callFrame;
   2265     ScopeChainNode* scopeChain = callFrame->scopeChain();
   2266 
   2267     int skip = stackFrame.args[1].int32();
   2268 
   2269     ScopeChainIterator iter = scopeChain->begin();
   2270     ScopeChainIterator end = scopeChain->end();
   2271     ASSERT(iter != end);
   2272     while (skip--) {
   2273         ++iter;
   2274         ASSERT(iter != end);
   2275     }
   2276     Identifier& ident = stackFrame.args[0].identifier();
   2277     do {
   2278         JSObject* o = *iter;
   2279         PropertySlot slot(o);
   2280         if (o->getPropertySlot(callFrame, ident, slot)) {
   2281             JSValue result = slot.getValue(callFrame, ident);
   2282             CHECK_FOR_EXCEPTION_AT_END();
   2283             return JSValue::encode(result);
   2284         }
   2285     } while (++iter != end);
   2286 
   2287     CodeBlock* codeBlock = callFrame->codeBlock();
   2288     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   2289     stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
   2290     VM_THROW_EXCEPTION();
   2291 }
   2292 
   2293 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
   2294 {
   2295     STUB_INIT_STACK_FRAME(stackFrame);
   2296 
   2297     CallFrame* callFrame = stackFrame.callFrame;
   2298     JSGlobalObject* globalObject = stackFrame.args[0].globalObject();
   2299     Identifier& ident = stackFrame.args[1].identifier();
   2300     unsigned globalResolveInfoIndex = stackFrame.args[2].int32();
   2301     ASSERT(globalObject->isGlobalObject());
   2302 
   2303     PropertySlot slot(globalObject);
   2304     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
   2305         JSValue result = slot.getValue(callFrame, ident);
   2306         if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
   2307             GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex);
   2308             if (globalResolveInfo.structure)
   2309                 globalResolveInfo.structure->deref();
   2310             globalObject->structure()->ref();
   2311             globalResolveInfo.structure = globalObject->structure();
   2312             globalResolveInfo.offset = slot.cachedOffset();
   2313             return JSValue::encode(result);
   2314         }
   2315 
   2316         CHECK_FOR_EXCEPTION_AT_END();
   2317         return JSValue::encode(result);
   2318     }
   2319 
   2320     unsigned vPCIndex = callFrame->codeBlock()->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   2321     stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, callFrame->codeBlock());
   2322     VM_THROW_EXCEPTION();
   2323 }
   2324 
   2325 DEFINE_STUB_FUNCTION(EncodedJSValue, op_div)
   2326 {
   2327     STUB_INIT_STACK_FRAME(stackFrame);
   2328 
   2329     JSValue src1 = stackFrame.args[0].jsValue();
   2330     JSValue src2 = stackFrame.args[1].jsValue();
   2331 
   2332     double left;
   2333     double right;
   2334     if (src1.getNumber(left) && src2.getNumber(right))
   2335         return JSValue::encode(jsNumber(stackFrame.globalData, left / right));
   2336 
   2337     CallFrame* callFrame = stackFrame.callFrame;
   2338     JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) / src2.toNumber(callFrame));
   2339     CHECK_FOR_EXCEPTION_AT_END();
   2340     return JSValue::encode(result);
   2341 }
   2342 
   2343 DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_dec)
   2344 {
   2345     STUB_INIT_STACK_FRAME(stackFrame);
   2346 
   2347     JSValue v = stackFrame.args[0].jsValue();
   2348 
   2349     CallFrame* callFrame = stackFrame.callFrame;
   2350     JSValue result = jsNumber(stackFrame.globalData, v.toNumber(callFrame) - 1);
   2351     CHECK_FOR_EXCEPTION_AT_END();
   2352     return JSValue::encode(result);
   2353 }
   2354 
   2355 DEFINE_STUB_FUNCTION(int, op_jless)
   2356 {
   2357     STUB_INIT_STACK_FRAME(stackFrame);
   2358 
   2359     JSValue src1 = stackFrame.args[0].jsValue();
   2360     JSValue src2 = stackFrame.args[1].jsValue();
   2361     CallFrame* callFrame = stackFrame.callFrame;
   2362 
   2363     bool result = jsLess(callFrame, src1, src2);
   2364     CHECK_FOR_EXCEPTION_AT_END();
   2365     return result;
   2366 }
   2367 
   2368 DEFINE_STUB_FUNCTION(int, op_jlesseq)
   2369 {
   2370     STUB_INIT_STACK_FRAME(stackFrame);
   2371 
   2372     JSValue src1 = stackFrame.args[0].jsValue();
   2373     JSValue src2 = stackFrame.args[1].jsValue();
   2374     CallFrame* callFrame = stackFrame.callFrame;
   2375 
   2376     bool result = jsLessEq(callFrame, src1, src2);
   2377     CHECK_FOR_EXCEPTION_AT_END();
   2378     return result;
   2379 }
   2380 
   2381 DEFINE_STUB_FUNCTION(EncodedJSValue, op_not)
   2382 {
   2383     STUB_INIT_STACK_FRAME(stackFrame);
   2384 
   2385     JSValue src = stackFrame.args[0].jsValue();
   2386 
   2387     CallFrame* callFrame = stackFrame.callFrame;
   2388 
   2389     JSValue result = jsBoolean(!src.toBoolean(callFrame));
   2390     CHECK_FOR_EXCEPTION_AT_END();
   2391     return JSValue::encode(result);
   2392 }
   2393 
   2394 DEFINE_STUB_FUNCTION(int, op_jtrue)
   2395 {
   2396     STUB_INIT_STACK_FRAME(stackFrame);
   2397 
   2398     JSValue src1 = stackFrame.args[0].jsValue();
   2399 
   2400     CallFrame* callFrame = stackFrame.callFrame;
   2401 
   2402     bool result = src1.toBoolean(callFrame);
   2403     CHECK_FOR_EXCEPTION_AT_END();
   2404     return result;
   2405 }
   2406 
   2407 DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_inc)
   2408 {
   2409     STUB_INIT_STACK_FRAME(stackFrame);
   2410 
   2411     JSValue v = stackFrame.args[0].jsValue();
   2412 
   2413     CallFrame* callFrame = stackFrame.callFrame;
   2414 
   2415     JSValue number = v.toJSNumber(callFrame);
   2416     CHECK_FOR_EXCEPTION_AT_END();
   2417 
   2418     callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(stackFrame.globalData, number.uncheckedGetNumber() + 1);
   2419     return JSValue::encode(number);
   2420 }
   2421 
   2422 DEFINE_STUB_FUNCTION(int, op_eq)
   2423 {
   2424     STUB_INIT_STACK_FRAME(stackFrame);
   2425 
   2426     JSValue src1 = stackFrame.args[0].jsValue();
   2427     JSValue src2 = stackFrame.args[1].jsValue();
   2428 
   2429 #if USE(JSVALUE32_64)
   2430     start:
   2431     if (src2.isUndefined()) {
   2432         return src1.isNull() ||
   2433                (src1.isCell() && asCell(src1)->structure()->typeInfo().masqueradesAsUndefined()) ||
   2434                src1.isUndefined();
   2435     }
   2436 
   2437     if (src2.isNull()) {
   2438         return src1.isUndefined() ||
   2439                (src1.isCell() && asCell(src1)->structure()->typeInfo().masqueradesAsUndefined()) ||
   2440                src1.isNull();
   2441     }
   2442 
   2443     if (src1.isInt32()) {
   2444         if (src2.isDouble())
   2445             return src1.asInt32() == src2.asDouble();
   2446         double d = src2.toNumber(stackFrame.callFrame);
   2447         CHECK_FOR_EXCEPTION();
   2448         return src1.asInt32() == d;
   2449     }
   2450 
   2451     if (src1.isDouble()) {
   2452         if (src2.isInt32())
   2453             return src1.asDouble() == src2.asInt32();
   2454         double d = src2.toNumber(stackFrame.callFrame);
   2455         CHECK_FOR_EXCEPTION();
   2456         return src1.asDouble() == d;
   2457     }
   2458 
   2459     if (src1.isTrue()) {
   2460         if (src2.isFalse())
   2461             return false;
   2462         double d = src2.toNumber(stackFrame.callFrame);
   2463         CHECK_FOR_EXCEPTION();
   2464         return d == 1.0;
   2465     }
   2466 
   2467     if (src1.isFalse()) {
   2468         if (src2.isTrue())
   2469             return false;
   2470         double d = src2.toNumber(stackFrame.callFrame);
   2471         CHECK_FOR_EXCEPTION();
   2472         return d == 0.0;
   2473     }
   2474 
   2475     if (src1.isUndefined())
   2476         return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined();
   2477 
   2478     if (src1.isNull())
   2479         return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined();
   2480 
   2481     JSCell* cell1 = asCell(src1);
   2482 
   2483     if (cell1->isString()) {
   2484         if (src2.isInt32())
   2485             return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asInt32();
   2486 
   2487         if (src2.isDouble())
   2488             return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asDouble();
   2489 
   2490         if (src2.isTrue())
   2491             return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 1.0;
   2492 
   2493         if (src2.isFalse())
   2494             return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 0.0;
   2495 
   2496         JSCell* cell2 = asCell(src2);
   2497         if (cell2->isString())
   2498             return static_cast<JSString*>(cell1)->value(stackFrame.callFrame) == static_cast<JSString*>(cell2)->value(stackFrame.callFrame);
   2499 
   2500         src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
   2501         CHECK_FOR_EXCEPTION();
   2502         goto start;
   2503     }
   2504 
   2505     if (src2.isObject())
   2506         return asObject(cell1) == asObject(src2);
   2507     src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame);
   2508     CHECK_FOR_EXCEPTION();
   2509     goto start;
   2510 
   2511 #else // USE(JSVALUE32_64)
   2512     CallFrame* callFrame = stackFrame.callFrame;
   2513 
   2514     bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2);
   2515     CHECK_FOR_EXCEPTION_AT_END();
   2516     return result;
   2517 #endif // USE(JSVALUE32_64)
   2518 }
   2519 
   2520 #if USE(JSVALUE32_64)
   2521 
   2522 DEFINE_STUB_FUNCTION(int, op_eq_strings)
   2523 {
   2524     STUB_INIT_STACK_FRAME(stackFrame);
   2525 
   2526     JSString* string1 = stackFrame.args[0].jsString();
   2527     JSString* string2 = stackFrame.args[1].jsString();
   2528 
   2529     ASSERT(string1->isString());
   2530     ASSERT(string2->isString());
   2531     return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame);
   2532 }
   2533 
   2534 #endif
   2535 
   2536 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift)
   2537 {
   2538     STUB_INIT_STACK_FRAME(stackFrame);
   2539 
   2540     JSValue val = stackFrame.args[0].jsValue();
   2541     JSValue shift = stackFrame.args[1].jsValue();
   2542 
   2543     CallFrame* callFrame = stackFrame.callFrame;
   2544     JSValue result = jsNumber(stackFrame.globalData, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
   2545     CHECK_FOR_EXCEPTION_AT_END();
   2546     return JSValue::encode(result);
   2547 }
   2548 
   2549 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitand)
   2550 {
   2551     STUB_INIT_STACK_FRAME(stackFrame);
   2552 
   2553     JSValue src1 = stackFrame.args[0].jsValue();
   2554     JSValue src2 = stackFrame.args[1].jsValue();
   2555 
   2556     ASSERT(!src1.isInt32() || !src2.isInt32());
   2557     CallFrame* callFrame = stackFrame.callFrame;
   2558     JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) & src2.toInt32(callFrame));
   2559     CHECK_FOR_EXCEPTION_AT_END();
   2560     return JSValue::encode(result);
   2561 }
   2562 
   2563 DEFINE_STUB_FUNCTION(EncodedJSValue, op_rshift)
   2564 {
   2565     STUB_INIT_STACK_FRAME(stackFrame);
   2566 
   2567     JSValue val = stackFrame.args[0].jsValue();
   2568     JSValue shift = stackFrame.args[1].jsValue();
   2569 
   2570     CallFrame* callFrame = stackFrame.callFrame;
   2571     JSValue result = jsNumber(stackFrame.globalData, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
   2572 
   2573     CHECK_FOR_EXCEPTION_AT_END();
   2574     return JSValue::encode(result);
   2575 }
   2576 
   2577 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitnot)
   2578 {
   2579     STUB_INIT_STACK_FRAME(stackFrame);
   2580 
   2581     JSValue src = stackFrame.args[0].jsValue();
   2582 
   2583     ASSERT(!src.isInt32());
   2584     CallFrame* callFrame = stackFrame.callFrame;
   2585     JSValue result = jsNumber(stackFrame.globalData, ~src.toInt32(callFrame));
   2586     CHECK_FOR_EXCEPTION_AT_END();
   2587     return JSValue::encode(result);
   2588 }
   2589 
   2590 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base)
   2591 {
   2592     STUB_INIT_STACK_FRAME(stackFrame);
   2593 
   2594     CallFrame* callFrame = stackFrame.callFrame;
   2595     ScopeChainNode* scopeChain = callFrame->scopeChain();
   2596 
   2597     ScopeChainIterator iter = scopeChain->begin();
   2598     ScopeChainIterator end = scopeChain->end();
   2599 
   2600     // FIXME: add scopeDepthIsZero optimization
   2601 
   2602     ASSERT(iter != end);
   2603 
   2604     Identifier& ident = stackFrame.args[0].identifier();
   2605     JSObject* base;
   2606     do {
   2607         base = *iter;
   2608         PropertySlot slot(base);
   2609         if (base->getPropertySlot(callFrame, ident, slot)) {
   2610             JSValue result = slot.getValue(callFrame, ident);
   2611             CHECK_FOR_EXCEPTION_AT_END();
   2612 
   2613             callFrame->registers()[stackFrame.args[1].int32()] = JSValue(base);
   2614             return JSValue::encode(result);
   2615         }
   2616         ++iter;
   2617     } while (iter != end);
   2618 
   2619     CodeBlock* codeBlock = callFrame->codeBlock();
   2620     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   2621     stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
   2622     VM_THROW_EXCEPTION_AT_END();
   2623     return JSValue::encode(JSValue());
   2624 }
   2625 
   2626 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
   2627 {
   2628     STUB_INIT_STACK_FRAME(stackFrame);
   2629     CallFrame* callFrame = stackFrame.callFrame;
   2630 
   2631     FunctionExecutable* function = stackFrame.args[0].function();
   2632     JSFunction* func = function->make(callFrame, callFrame->scopeChain());
   2633 
   2634     /*
   2635         The Identifier in a FunctionExpression can be referenced from inside
   2636         the FunctionExpression's FunctionBody to allow the function to call
   2637         itself recursively. However, unlike in a FunctionDeclaration, the
   2638         Identifier in a FunctionExpression cannot be referenced from and
   2639         does not affect the scope enclosing the FunctionExpression.
   2640      */
   2641     if (!function->name().isNull()) {
   2642         JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
   2643         func->scope().push(functionScopeObject);
   2644     }
   2645 
   2646     return func;
   2647 }
   2648 
   2649 DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod)
   2650 {
   2651     STUB_INIT_STACK_FRAME(stackFrame);
   2652 
   2653     JSValue dividendValue = stackFrame.args[0].jsValue();
   2654     JSValue divisorValue = stackFrame.args[1].jsValue();
   2655 
   2656     CallFrame* callFrame = stackFrame.callFrame;
   2657     double d = dividendValue.toNumber(callFrame);
   2658     JSValue result = jsNumber(stackFrame.globalData, fmod(d, divisorValue.toNumber(callFrame)));
   2659     CHECK_FOR_EXCEPTION_AT_END();
   2660     return JSValue::encode(result);
   2661 }
   2662 
   2663 DEFINE_STUB_FUNCTION(EncodedJSValue, op_less)
   2664 {
   2665     STUB_INIT_STACK_FRAME(stackFrame);
   2666 
   2667     CallFrame* callFrame = stackFrame.callFrame;
   2668     JSValue result = jsBoolean(jsLess(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
   2669     CHECK_FOR_EXCEPTION_AT_END();
   2670     return JSValue::encode(result);
   2671 }
   2672 
   2673 DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_dec)
   2674 {
   2675     STUB_INIT_STACK_FRAME(stackFrame);
   2676 
   2677     JSValue v = stackFrame.args[0].jsValue();
   2678 
   2679     CallFrame* callFrame = stackFrame.callFrame;
   2680 
   2681     JSValue number = v.toJSNumber(callFrame);
   2682     CHECK_FOR_EXCEPTION_AT_END();
   2683 
   2684     callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(stackFrame.globalData, number.uncheckedGetNumber() - 1);
   2685     return JSValue::encode(number);
   2686 }
   2687 
   2688 DEFINE_STUB_FUNCTION(EncodedJSValue, op_urshift)
   2689 {
   2690     STUB_INIT_STACK_FRAME(stackFrame);
   2691 
   2692     JSValue val = stackFrame.args[0].jsValue();
   2693     JSValue shift = stackFrame.args[1].jsValue();
   2694 
   2695     CallFrame* callFrame = stackFrame.callFrame;
   2696     JSValue result = jsNumber(stackFrame.globalData, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
   2697     CHECK_FOR_EXCEPTION_AT_END();
   2698     return JSValue::encode(result);
   2699 }
   2700 
   2701 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitxor)
   2702 {
   2703     STUB_INIT_STACK_FRAME(stackFrame);
   2704 
   2705     JSValue src1 = stackFrame.args[0].jsValue();
   2706     JSValue src2 = stackFrame.args[1].jsValue();
   2707 
   2708     CallFrame* callFrame = stackFrame.callFrame;
   2709 
   2710     JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
   2711     CHECK_FOR_EXCEPTION_AT_END();
   2712     return JSValue::encode(result);
   2713 }
   2714 
   2715 DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp)
   2716 {
   2717     STUB_INIT_STACK_FRAME(stackFrame);
   2718 
   2719     return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), stackFrame.args[0].regExp());
   2720 }
   2721 
   2722 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
   2723 {
   2724     STUB_INIT_STACK_FRAME(stackFrame);
   2725 
   2726     JSValue src1 = stackFrame.args[0].jsValue();
   2727     JSValue src2 = stackFrame.args[1].jsValue();
   2728 
   2729     CallFrame* callFrame = stackFrame.callFrame;
   2730 
   2731     JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) | src2.toInt32(callFrame));
   2732     CHECK_FOR_EXCEPTION_AT_END();
   2733     return JSValue::encode(result);
   2734 }
   2735 
   2736 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
   2737 {
   2738     STUB_INIT_STACK_FRAME(stackFrame);
   2739 
   2740     CallFrame* callFrame = stackFrame.callFrame;
   2741     RegisterFile* registerFile = stackFrame.registerFile;
   2742 
   2743     Interpreter* interpreter = stackFrame.globalData->interpreter;
   2744 
   2745     JSValue funcVal = stackFrame.args[0].jsValue();
   2746     int registerOffset = stackFrame.args[1].int32();
   2747     int argCount = stackFrame.args[2].int32();
   2748 
   2749     Register* newCallFrame = callFrame->registers() + registerOffset;
   2750     Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
   2751     JSValue thisValue = argv[0].jsValue();
   2752     JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
   2753 
   2754     if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
   2755         JSValue exceptionValue;
   2756         JSValue result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
   2757         if (UNLIKELY(exceptionValue)) {
   2758             stackFrame.globalData->exception = exceptionValue;
   2759             VM_THROW_EXCEPTION_AT_END();
   2760         }
   2761         return JSValue::encode(result);
   2762     }
   2763 
   2764     return JSValue::encode(JSValue());
   2765 }
   2766 
   2767 DEFINE_STUB_FUNCTION(EncodedJSValue, op_throw)
   2768 {
   2769     STUB_INIT_STACK_FRAME(stackFrame);
   2770 
   2771     CallFrame* callFrame = stackFrame.callFrame;
   2772     CodeBlock* codeBlock = callFrame->codeBlock();
   2773 
   2774     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   2775 
   2776     JSValue exceptionValue = stackFrame.args[0].jsValue();
   2777     ASSERT(exceptionValue);
   2778 
   2779     HandlerInfo* handler = stackFrame.globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, true);
   2780 
   2781     if (!handler) {
   2782         *stackFrame.exception = exceptionValue;
   2783         STUB_SET_RETURN_ADDRESS(FunctionPtr(ctiOpThrowNotCaught).value());
   2784         return JSValue::encode(jsNull());
   2785     }
   2786 
   2787     stackFrame.callFrame = callFrame;
   2788     void* catchRoutine = handler->nativeCode.executableAddress();
   2789     ASSERT(catchRoutine);
   2790     STUB_SET_RETURN_ADDRESS(catchRoutine);
   2791     return JSValue::encode(exceptionValue);
   2792 }
   2793 
   2794 DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
   2795 {
   2796     STUB_INIT_STACK_FRAME(stackFrame);
   2797 
   2798     CallFrame* callFrame = stackFrame.callFrame;
   2799     JSObject* o = stackFrame.args[0].jsObject();
   2800     Structure* structure = o->structure();
   2801     JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
   2802     if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
   2803         jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
   2804     return jsPropertyNameIterator;
   2805 }
   2806 
   2807 DEFINE_STUB_FUNCTION(int, has_property)
   2808 {
   2809     STUB_INIT_STACK_FRAME(stackFrame);
   2810 
   2811     JSObject* base = stackFrame.args[0].jsObject();
   2812     JSString* property = stackFrame.args[1].jsString();
   2813     return base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame)));
   2814 }
   2815 
   2816 DEFINE_STUB_FUNCTION(JSObject*, op_push_scope)
   2817 {
   2818     STUB_INIT_STACK_FRAME(stackFrame);
   2819 
   2820     JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame);
   2821     CHECK_FOR_EXCEPTION();
   2822     stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(o));
   2823     return o;
   2824 }
   2825 
   2826 DEFINE_STUB_FUNCTION(void, op_pop_scope)
   2827 {
   2828     STUB_INIT_STACK_FRAME(stackFrame);
   2829 
   2830     stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->pop());
   2831 }
   2832 
   2833 DEFINE_STUB_FUNCTION(EncodedJSValue, op_typeof)
   2834 {
   2835     STUB_INIT_STACK_FRAME(stackFrame);
   2836 
   2837     return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue()));
   2838 }
   2839 
   2840 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_undefined)
   2841 {
   2842     STUB_INIT_STACK_FRAME(stackFrame);
   2843 
   2844     JSValue v = stackFrame.args[0].jsValue();
   2845     return JSValue::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
   2846 }
   2847 
   2848 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_boolean)
   2849 {
   2850     STUB_INIT_STACK_FRAME(stackFrame);
   2851 
   2852     return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isBoolean()));
   2853 }
   2854 
   2855 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_number)
   2856 {
   2857     STUB_INIT_STACK_FRAME(stackFrame);
   2858 
   2859     return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isNumber()));
   2860 }
   2861 
   2862 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_string)
   2863 {
   2864     STUB_INIT_STACK_FRAME(stackFrame);
   2865 
   2866     return JSValue::encode(jsBoolean(isJSString(stackFrame.globalData, stackFrame.args[0].jsValue())));
   2867 }
   2868 
   2869 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object)
   2870 {
   2871     STUB_INIT_STACK_FRAME(stackFrame);
   2872 
   2873     return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame.args[0].jsValue())));
   2874 }
   2875 
   2876 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_function)
   2877 {
   2878     STUB_INIT_STACK_FRAME(stackFrame);
   2879 
   2880     return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame.args[0].jsValue())));
   2881 }
   2882 
   2883 DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq)
   2884 {
   2885     STUB_INIT_STACK_FRAME(stackFrame);
   2886 
   2887     JSValue src1 = stackFrame.args[0].jsValue();
   2888     JSValue src2 = stackFrame.args[1].jsValue();
   2889 
   2890     return JSValue::encode(jsBoolean(JSValue::strictEqual(stackFrame.callFrame, src1, src2)));
   2891 }
   2892 
   2893 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive)
   2894 {
   2895     STUB_INIT_STACK_FRAME(stackFrame);
   2896 
   2897     return JSValue::encode(stackFrame.args[0].jsValue().toPrimitive(stackFrame.callFrame));
   2898 }
   2899 
   2900 DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat)
   2901 {
   2902     STUB_INIT_STACK_FRAME(stackFrame);
   2903 
   2904     JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
   2905     CHECK_FOR_EXCEPTION_AT_END();
   2906     return JSValue::encode(result);
   2907 }
   2908 
   2909 DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq)
   2910 {
   2911     STUB_INIT_STACK_FRAME(stackFrame);
   2912 
   2913     JSValue src1 = stackFrame.args[0].jsValue();
   2914     JSValue src2 = stackFrame.args[1].jsValue();
   2915 
   2916     return JSValue::encode(jsBoolean(!JSValue::strictEqual(stackFrame.callFrame, src1, src2)));
   2917 }
   2918 
   2919 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber)
   2920 {
   2921     STUB_INIT_STACK_FRAME(stackFrame);
   2922 
   2923     JSValue src = stackFrame.args[0].jsValue();
   2924     CallFrame* callFrame = stackFrame.callFrame;
   2925 
   2926     JSValue result = src.toJSNumber(callFrame);
   2927     CHECK_FOR_EXCEPTION_AT_END();
   2928     return JSValue::encode(result);
   2929 }
   2930 
   2931 DEFINE_STUB_FUNCTION(EncodedJSValue, op_in)
   2932 {
   2933     STUB_INIT_STACK_FRAME(stackFrame);
   2934 
   2935     CallFrame* callFrame = stackFrame.callFrame;
   2936     JSValue baseVal = stackFrame.args[1].jsValue();
   2937 
   2938     if (!baseVal.isObject()) {
   2939         CallFrame* callFrame = stackFrame.callFrame;
   2940         CodeBlock* codeBlock = callFrame->codeBlock();
   2941         unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
   2942         stackFrame.globalData->exception = createInvalidParamError(callFrame, "in", baseVal, vPCIndex, codeBlock);
   2943         VM_THROW_EXCEPTION();
   2944     }
   2945 
   2946     JSValue propName = stackFrame.args[0].jsValue();
   2947     JSObject* baseObj = asObject(baseVal);
   2948 
   2949     uint32_t i;
   2950     if (propName.getUInt32(i))
   2951         return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
   2952 
   2953     Identifier property(callFrame, propName.toString(callFrame));
   2954     CHECK_FOR_EXCEPTION();
   2955     return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
   2956 }
   2957 
   2958 DEFINE_STUB_FUNCTION(JSObject*, op_push_new_scope)
   2959 {
   2960     STUB_INIT_STACK_FRAME(stackFrame);
   2961 
   2962     JSObject* scope = new (stackFrame.globalData) JSStaticScopeObject(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), DontDelete);
   2963 
   2964     CallFrame* callFrame = stackFrame.callFrame;
   2965     callFrame->setScopeChain(callFrame->scopeChain()->push(scope));
   2966     return scope;
   2967 }
   2968 
   2969 DEFINE_STUB_FUNCTION(void, op_jmp_scopes)
   2970 {
   2971     STUB_INIT_STACK_FRAME(stackFrame);
   2972 
   2973     unsigned count = stackFrame.args[0].int32();
   2974     CallFrame* callFrame = stackFrame.callFrame;
   2975 
   2976     ScopeChainNode* tmp = callFrame->scopeChain();
   2977     while (count--)
   2978         tmp = tmp->pop();
   2979     callFrame->setScopeChain(tmp);
   2980 }
   2981 
   2982 DEFINE_STUB_FUNCTION(void, op_put_by_index)
   2983 {
   2984     STUB_INIT_STACK_FRAME(stackFrame);
   2985 
   2986     CallFrame* callFrame = stackFrame.callFrame;
   2987     unsigned property = stackFrame.args[1].int32();
   2988 
   2989     stackFrame.args[0].jsValue().put(callFrame, property, stackFrame.args[2].jsValue());
   2990 }
   2991 
   2992 DEFINE_STUB_FUNCTION(void*, op_switch_imm)
   2993 {
   2994     STUB_INIT_STACK_FRAME(stackFrame);
   2995 
   2996     JSValue scrutinee = stackFrame.args[0].jsValue();
   2997     unsigned tableIndex = stackFrame.args[1].int32();
   2998     CallFrame* callFrame = stackFrame.callFrame;
   2999     CodeBlock* codeBlock = callFrame->codeBlock();
   3000 
   3001     if (scrutinee.isInt32())
   3002         return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
   3003     else {
   3004         double value;
   3005         int32_t intValue;
   3006         if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
   3007             return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(intValue).executableAddress();
   3008         else
   3009             return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
   3010     }
   3011 }
   3012 
   3013 DEFINE_STUB_FUNCTION(void*, op_switch_char)
   3014 {
   3015     STUB_INIT_STACK_FRAME(stackFrame);
   3016 
   3017     JSValue scrutinee = stackFrame.args[0].jsValue();
   3018     unsigned tableIndex = stackFrame.args[1].int32();
   3019     CallFrame* callFrame = stackFrame.callFrame;
   3020     CodeBlock* codeBlock = callFrame->codeBlock();
   3021 
   3022     void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
   3023 
   3024     if (scrutinee.isString()) {
   3025         UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
   3026         if (value->size() == 1)
   3027             result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]).executableAddress();
   3028     }
   3029 
   3030     return result;
   3031 }
   3032 
   3033 DEFINE_STUB_FUNCTION(void*, op_switch_string)
   3034 {
   3035     STUB_INIT_STACK_FRAME(stackFrame);
   3036 
   3037     JSValue scrutinee = stackFrame.args[0].jsValue();
   3038     unsigned tableIndex = stackFrame.args[1].int32();
   3039     CallFrame* callFrame = stackFrame.callFrame;
   3040     CodeBlock* codeBlock = callFrame->codeBlock();
   3041 
   3042     void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
   3043 
   3044     if (scrutinee.isString()) {
   3045         UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
   3046         result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
   3047     }
   3048 
   3049     return result;
   3050 }
   3051 
   3052 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val)
   3053 {
   3054     STUB_INIT_STACK_FRAME(stackFrame);
   3055 
   3056     CallFrame* callFrame = stackFrame.callFrame;
   3057 
   3058     JSValue baseValue = stackFrame.args[0].jsValue();
   3059     JSObject* baseObj = baseValue.toObject(callFrame); // may throw
   3060 
   3061     JSValue subscript = stackFrame.args[1].jsValue();
   3062     JSValue result;
   3063     uint32_t i;
   3064     if (subscript.getUInt32(i))
   3065         result = jsBoolean(baseObj->deleteProperty(callFrame, i));
   3066     else {
   3067         CHECK_FOR_EXCEPTION();
   3068         Identifier property(callFrame, subscript.toString(callFrame));
   3069         CHECK_FOR_EXCEPTION();
   3070         result = jsBoolean(baseObj->deleteProperty(callFrame, property));
   3071     }
   3072 
   3073     CHECK_FOR_EXCEPTION_AT_END();
   3074     return JSValue::encode(result);
   3075 }
   3076 
   3077 DEFINE_STUB_FUNCTION(void, op_put_getter)
   3078 {
   3079     STUB_INIT_STACK_FRAME(stackFrame);
   3080 
   3081     CallFrame* callFrame = stackFrame.callFrame;
   3082 
   3083     ASSERT(stackFrame.args[0].jsValue().isObject());
   3084     JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
   3085     ASSERT(stackFrame.args[2].jsValue().isObject());
   3086     baseObj->defineGetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
   3087 }
   3088 
   3089 DEFINE_STUB_FUNCTION(void, op_put_setter)
   3090 {
   3091     STUB_INIT_STACK_FRAME(stackFrame);
   3092 
   3093     CallFrame* callFrame = stackFrame.callFrame;
   3094 
   3095     ASSERT(stackFrame.args[0].jsValue().isObject());
   3096     JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
   3097     ASSERT(stackFrame.args[2].jsValue().isObject());
   3098     baseObj->defineSetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
   3099 }
   3100 
   3101 DEFINE_STUB_FUNCTION(JSObject*, op_new_error)
   3102 {
   3103     STUB_INIT_STACK_FRAME(stackFrame);
   3104 
   3105     CallFrame* callFrame = stackFrame.callFrame;
   3106     CodeBlock* codeBlock = callFrame->codeBlock();
   3107     unsigned type = stackFrame.args[0].int32();
   3108     JSValue message = stackFrame.args[1].jsValue();
   3109     unsigned bytecodeOffset = stackFrame.args[2].int32();
   3110 
   3111     unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
   3112     return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
   3113 }
   3114 
   3115 DEFINE_STUB_FUNCTION(void, op_debug)
   3116 {
   3117     STUB_INIT_STACK_FRAME(stackFrame);
   3118 
   3119     CallFrame* callFrame = stackFrame.callFrame;
   3120 
   3121     int debugHookID = stackFrame.args[0].int32();
   3122     int firstLine = stackFrame.args[1].int32();
   3123     int lastLine = stackFrame.args[2].int32();
   3124 
   3125     stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
   3126 }
   3127 
   3128 DEFINE_STUB_FUNCTION(EncodedJSValue, vm_throw)
   3129 {
   3130     STUB_INIT_STACK_FRAME(stackFrame);
   3131 
   3132     CallFrame* callFrame = stackFrame.callFrame;
   3133     CodeBlock* codeBlock = callFrame->codeBlock();
   3134     JSGlobalData* globalData = stackFrame.globalData;
   3135 
   3136     unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, globalData->exceptionLocation);
   3137 
   3138     JSValue exceptionValue = globalData->exception;
   3139     ASSERT(exceptionValue);
   3140     globalData->exception = JSValue();
   3141 
   3142     HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false);
   3143 
   3144     if (!handler) {
   3145         *stackFrame.exception = exceptionValue;
   3146         return JSValue::encode(jsNull());
   3147     }
   3148 
   3149     stackFrame.callFrame = callFrame;
   3150     void* catchRoutine = handler->nativeCode.executableAddress();
   3151     ASSERT(catchRoutine);
   3152     STUB_SET_RETURN_ADDRESS(catchRoutine);
   3153     return JSValue::encode(exceptionValue);
   3154 }
   3155 
   3156 DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
   3157 {
   3158     STUB_INIT_STACK_FRAME(stackFrame);
   3159 
   3160     CallFrame* callFrame = stackFrame.callFrame;
   3161     return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
   3162 }
   3163 
   3164 } // namespace JSC
   3165 
   3166 #endif // ENABLE(JIT)
   3167