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