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