1/*
2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@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
66using namespace std;
67
68namespace 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.
117COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
118COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
119COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
120COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
121
122asm (
123".text\n"
124".globl " SYMBOL_STRING(ctiTrampoline) "\n"
125HIDE_SYMBOL(ctiTrampoline) "\n"
126SYMBOL_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
144asm (
145".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
146HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
147SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
148    "movl %esp, %ecx" "\n"
149    "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
150    "int3" "\n"
151);
152
153asm (
154".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
155HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
156SYMBOL_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.
169COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment);
170COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
171COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
172COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline);
173
174asm (
175".globl " SYMBOL_STRING(ctiTrampoline) "\n"
176HIDE_SYMBOL(ctiTrampoline) "\n"
177SYMBOL_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
201asm (
202".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
203HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
204SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
205    "movq %rsp, %rdi" "\n"
206    "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
207    "int3" "\n"
208);
209
210asm (
211".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
212HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
213SYMBOL_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.
247COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
248COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
249COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
250COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
251
252extern "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
321asm volatile (
322".text\n"
323".globl " SYMBOL_STRING(ctiTrampoline) "\n"
324HIDE_SYMBOL(ctiTrampoline) "\n"
325SYMBOL_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
352asm volatile (
353".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
354HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
355SYMBOL_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
375asm volatile (
376".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
377HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
378SYMBOL_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.
400COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
401COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline);
402COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
403
404asm (
405".text\n"
406".globl " SYMBOL_STRING(ctiTrampoline) "\n"
407HIDE_SYMBOL(ctiTrampoline) "\n"
408SYMBOL_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
439asm (
440".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
441HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
442SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
443    "movq %rsp, %rdi" "\n"
444    "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
445    "int3" "\n"
446);
447
448asm (
449".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
450HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
451SYMBOL_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)
469asm (
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"
477SYMBOL_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
508asm (
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"
516SYMBOL_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
539asm (
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"
547SYMBOL_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
562asm (
563".text" "\n"
564".align 2" "\n"
565".globl " SYMBOL_STRING(ctiTrampoline) "\n"
566HIDE_SYMBOL(ctiTrampoline) "\n"
567".thumb" "\n"
568".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
569SYMBOL_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
589asm (
590".text" "\n"
591".align 2" "\n"
592".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
593HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
594".thumb" "\n"
595".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
596SYMBOL_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
607asm (
608".text" "\n"
609".align 2" "\n"
610".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
611HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
612".thumb" "\n"
613".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
614SYMBOL_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
625asm (
626".globl " SYMBOL_STRING(ctiTrampoline) "\n"
627HIDE_SYMBOL(ctiTrampoline) "\n"
628SYMBOL_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
643asm (
644".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
645HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
646SYMBOL_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"
652HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
653SYMBOL_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
754JITThunks::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
800JITThunks::~JITThunks()
801{
802}
803
804#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
805
806NEVER_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
856NEVER_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
949extern "C" {
950
951static 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
960struct 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.
993static 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
1000static 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
1034struct ExceptionHandler {
1035    void* catchRoutine;
1036    CallFrame* callFrame;
1037};
1038static 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/*
1159RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
1160RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
1161RVCT({)
1162RVCT(    PRESERVE8)
1163RVCT(    IMPORT JITStubThunked_#op#)
1164RVCT(    str lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
1165RVCT(    bl JITStubThunked_#op#)
1166RVCT(    ldr lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
1167RVCT(    bx lr)
1168RVCT(})
1169RVCT()
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/*
1185MSVC_BEGIN(    AREA Trampoline, CODE)
1186MSVC_BEGIN()
1187MSVC_BEGIN(    EXPORT ctiTrampoline)
1188MSVC_BEGIN(    EXPORT ctiVMThrowTrampoline)
1189MSVC_BEGIN(    EXPORT ctiOpThrowNotCaught)
1190MSVC_BEGIN()
1191MSVC_BEGIN(ctiTrampoline PROC)
1192MSVC_BEGIN(    stmdb sp!, {r1-r3})
1193MSVC_BEGIN(    stmdb sp!, {r4-r8, lr})
1194MSVC_BEGIN(    sub sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1195MSVC_BEGIN(    mov r4, r2)
1196MSVC_BEGIN(    mov r5, #512)
1197MSVC_BEGIN(    ; r0 contains the code)
1198MSVC_BEGIN(    mov lr, pc)
1199MSVC_BEGIN(    bx r0)
1200MSVC_BEGIN(    add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1201MSVC_BEGIN(    ldmia sp!, {r4-r8, lr})
1202MSVC_BEGIN(    add sp, sp, #12)
1203MSVC_BEGIN(    bx lr)
1204MSVC_BEGIN(ctiTrampoline ENDP)
1205MSVC_BEGIN()
1206MSVC_BEGIN(ctiVMThrowTrampoline PROC)
1207MSVC_BEGIN(    mov r0, sp)
1208MSVC_BEGIN(    mov lr, pc)
1209MSVC_BEGIN(    bl cti_vm_throw)
1210MSVC_BEGIN(ctiOpThrowNotCaught)
1211MSVC_BEGIN(    add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1212MSVC_BEGIN(    ldmia sp!, {r4-r8, lr})
1213MSVC_BEGIN(    add sp, sp, #12)
1214MSVC_BEGIN(    bx lr)
1215MSVC_BEGIN(ctiVMThrowTrampoline ENDP)
1216MSVC_BEGIN()
1217
1218MSVC(    EXPORT cti_#op#)
1219MSVC(    IMPORT JITStubThunked_#op#)
1220MSVC(cti_#op# PROC)
1221MSVC(    str lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET)
1222MSVC(    bl JITStubThunked_#op#)
1223MSVC(    ldr lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET)
1224MSVC(    bx lr)
1225MSVC(cti_#op# ENDP)
1226MSVC()
1227
1228MSVC_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
1258DEFINE_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
1280DEFINE_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
1292DEFINE_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
1304DEFINE_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
1330DEFINE_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
1342DEFINE_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
1360DEFINE_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
1377DEFINE_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
1390DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
1391{
1392    STUB_INIT_STACK_FRAME(stackFrame);
1393
1394    return constructEmptyObject(stackFrame.callFrame);
1395}
1396
1397DEFINE_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
1406DEFINE_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
1415DEFINE_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
1432DEFINE_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
1451DEFINE_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
1470DEFINE_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
1483DEFINE_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
1496DEFINE_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
1511DEFINE_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
1584DEFINE_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
1605DEFINE_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
1651static 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
1681DEFINE_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
1698DEFINE_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
1712DEFINE_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
1776DEFINE_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
1788DEFINE_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
1800DEFINE_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
1812DEFINE_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
1826DEFINE_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
1843DEFINE_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
1883DEFINE_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
1900DEFINE_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
1918DEFINE_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
1926DEFINE_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
1947DEFINE_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
1968DEFINE_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
2027DEFINE_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)
2087DEFINE_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
2121DEFINE_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
2156DEFINE_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
2165DEFINE_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
2204DEFINE_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
2212DEFINE_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
2220DEFINE_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
2241DEFINE_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
2249DEFINE_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
2257DEFINE_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
2265DEFINE_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
2273DEFINE_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
2299DEFINE_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
2338DEFINE_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
2384DEFINE_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
2414DEFINE_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
2445DEFINE_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
2463DEFINE_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
2511DEFINE_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
2554DEFINE_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
2564DEFINE_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
2653DEFINE_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
2669DEFINE_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
2676DEFINE_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
2687DEFINE_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
2702DEFINE_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
2740DEFINE_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
2769DEFINE_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
2787DEFINE_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
2799DEFINE_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
2812DEFINE_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
2825DEFINE_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
2838DEFINE_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
2851DEFINE_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
2866DEFINE_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
2964DEFINE_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
2982DEFINE_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
2995DEFINE_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
3009DEFINE_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
3023DEFINE_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
3036DEFINE_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
3070DEFINE_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
3094DEFINE_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
3108DEFINE_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
3118DEFINE_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
3133DEFINE_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
3146DEFINE_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
3160DEFINE_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
3175DEFINE_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
3189DEFINE_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
3217DEFINE_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
3225DEFINE_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
3238DEFINE_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
3249DEFINE_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
3259DEFINE_STUB_FUNCTION(void, op_pop_scope)
3260{
3261    STUB_INIT_STACK_FRAME(stackFrame);
3262
3263    stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->pop());
3264}
3265
3266DEFINE_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
3273DEFINE_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
3281DEFINE_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
3288DEFINE_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
3295DEFINE_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
3302DEFINE_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
3309DEFINE_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
3316DEFINE_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
3328DEFINE_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
3335DEFINE_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
3344DEFINE_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
3356DEFINE_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
3368DEFINE_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
3392DEFINE_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
3403DEFINE_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
3416DEFINE_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
3426DEFINE_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
3447DEFINE_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
3468DEFINE_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
3488DEFINE_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
3516DEFINE_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
3528DEFINE_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
3540DEFINE_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
3550DEFINE_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
3563DEFINE_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
3572DEFINE_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
3580MacroAssemblerCodePtr 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
3588NativeExecutable* 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
3596NativeExecutable* 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
3606void JITThunks::clearHostFunctionStubs()
3607{
3608    m_hostFunctionStubMap.clear();
3609}
3610
3611} // namespace JSC
3612
3613#endif // ENABLE(JIT)
3614