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