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