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