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