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