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