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.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
36 #include "Arguments.h"
37 #include "CallFrame.h"
38 #include "CodeBlock.h"
41 #include "ExceptionHelpers.h"
42 #include "GetterSetter.h"
45 #include "JSActivation.h"
47 #include "JSByteArray.h"
48 #include "JSFunction.h"
49 #include "JSGlobalObjectFunctions.h"
50 #include "JSNotAnObject.h"
51 #include "JSPropertyNameIterator.h"
52 #include "JSStaticScopeObject.h"
54 #include "ObjectPrototype.h"
55 #include "Operations.h"
58 #include "RegExpObject.h"
59 #include "RegExpPrototype.h"
61 #include "SamplingTool.h"
62 #include <wtf/StdLibExtras.h>
70 #if OS(DARWIN) || (OS(WINDOWS) && CPU(X86))
71 #define SYMBOL_STRING(name) "_" #name
73 #define SYMBOL_STRING(name) #name
77 #define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name)
79 #define THUMB_FUNC_PARAM(name)
82 #if (OS(LINUX) || OS(FREEBSD)) && CPU(X86_64)
83 #define SYMBOL_STRING_RELOCATION(name) #name "@plt"
84 #elif OS(DARWIN) || (CPU(X86_64) && COMPILER(MINGW) && !GCC_VERSION_AT_LEAST(4, 5, 0))
85 #define SYMBOL_STRING_RELOCATION(name) "_" #name
86 #elif CPU(X86) && COMPILER(MINGW)
87 #define SYMBOL_STRING_RELOCATION(name) "@" #name "@4"
89 #define SYMBOL_STRING_RELOCATION(name) #name
94 #define HIDE_SYMBOL(name) ".private_extern _" #name
96 // IBM's own file format
97 #define HIDE_SYMBOL(name) ".lglobl " #name
102 || (OS(HPUX) && CPU(IA64)) \
106 #define HIDE_SYMBOL(name) ".hidden " #name
108 #define HIDE_SYMBOL(name)
111 #if USE(JSVALUE32_64)
113 #if COMPILER(GCC) && CPU(X86)
115 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
116 // need to change the assembly trampolines below to match.
117 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment
);
118 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
119 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
120 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline
);
124 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
125 HIDE_SYMBOL(ctiTrampoline
) "\n"
126 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
128 "movl %esp, %ebp" "\n"
132 "subl $0x3c, %esp" "\n"
133 "movl $512, %esi" "\n"
134 "movl 0x58(%esp), %edi" "\n"
135 "call *0x50(%esp)" "\n"
136 "addl $0x3c, %esp" "\n"
145 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
146 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
147 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
148 "movl %esp, %ecx" "\n"
149 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
154 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
155 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
156 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
157 "addl $0x3c, %esp" "\n"
165 #elif COMPILER(GCC) && CPU(X86_64)
167 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
168 // need to change the assembly trampolines below to match.
169 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment
);
170 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedRBX
) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
171 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
172 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline
);
175 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
176 HIDE_SYMBOL(ctiTrampoline
) "\n"
177 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
179 "movq %rsp, %rbp" "\n"
185 "subq $0x48, %rsp" "\n"
186 "movq $512, %r12" "\n"
187 "movq $0xFFFF000000000000, %r14" "\n"
188 "movq $0xFFFF000000000002, %r15" "\n"
189 "movq 0x90(%rsp), %r13" "\n"
190 "call *0x80(%rsp)" "\n"
191 "addq $0x48, %rsp" "\n"
202 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
203 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
204 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
205 "movq %rsp, %rdi" "\n"
206 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
211 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
212 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
213 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
214 "addq $0x48, %rsp" "\n"
224 #elif (COMPILER(GCC) || COMPILER(RVCT)) && CPU(ARM_THUMB2)
226 #define THUNK_RETURN_ADDRESS_OFFSET 0x38
227 #define PRESERVED_RETURN_ADDRESS_OFFSET 0x3C
228 #define PRESERVED_R4_OFFSET 0x40
229 #define PRESERVED_R5_OFFSET 0x44
230 #define PRESERVED_R6_OFFSET 0x48
231 #define REGISTER_FILE_OFFSET 0x4C
232 #define CALLFRAME_OFFSET 0x50
233 #define EXCEPTION_OFFSET 0x54
234 #define ENABLE_PROFILER_REFERENCE_OFFSET 0x58
236 #elif (COMPILER(GCC) || COMPILER(MSVC) || COMPILER(RVCT)) && CPU(ARM_TRADITIONAL)
238 // Also update the MSVC section (defined at DEFINE_STUB_FUNCTION)
239 // when changing one of the following values.
240 #define THUNK_RETURN_ADDRESS_OFFSET 64
241 #define PRESERVEDR4_OFFSET 68
243 #elif COMPILER(MSVC) && CPU(X86)
245 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
246 // need to change the assembly trampolines below to match.
247 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment
);
248 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
249 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
250 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline
);
254 __declspec(naked
) EncodedJSValue
ctiTrampoline(void* code
, RegisterFile
*, CallFrame
*, void* /*unused1*/, Profiler
**, JSGlobalData
*)
265 mov edi
, [esp
+ 0x58];
276 __declspec(naked
) void ctiVMThrowTrampoline()
290 __declspec(naked
) void ctiOpThrowNotCaught()
305 #define PRESERVED_GP_OFFSET 60
306 #define PRESERVED_S0_OFFSET 64
307 #define PRESERVED_S1_OFFSET 68
308 #define PRESERVED_S2_OFFSET 72
309 #define PRESERVED_RETURN_ADDRESS_OFFSET 76
310 #define THUNK_RETURN_ADDRESS_OFFSET 80
311 #define REGISTER_FILE_OFFSET 84
312 #define CALLFRAME_OFFSET 88
313 #define EXCEPTION_OFFSET 92
314 #define ENABLE_PROFILER_REFERENCE_OFFSET 96
315 #define GLOBAL_DATA_OFFSET 100
316 #define STACK_LENGTH 104
318 #define SYMBOL_STRING(name) #name
319 /* code (r4), RegisterFile* (r5), CallFrame* (r6), JSValue* exception (r7), Profiler**(sp), JSGlobalData (sp)*/
323 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
324 HIDE_SYMBOL(ctiTrampoline
) "\n"
325 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
326 "mov.l r7, @-r15" "\n"
327 "mov.l r6, @-r15" "\n"
328 "mov.l r5, @-r15" "\n"
329 "mov.l r8, @-r15" "\n"
331 "mov.l r14, @-r15" "\n"
332 "sts.l pr, @-r15" "\n"
333 "mov.l r13, @-r15" "\n"
334 "mov.l r11, @-r15" "\n"
335 "mov.l r10, @-r15" "\n"
341 "mov.l @r15+,r10" "\n"
342 "mov.l @r15+,r11" "\n"
343 "mov.l @r15+,r13" "\n"
344 "lds.l @r15+,pr" "\n"
345 "mov.l @r15+,r14" "\n"
346 "mov.l @r15+,r8" "\n"
353 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
354 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
355 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
356 "mov.l .L2"SYMBOL_STRING(cti_vm_throw
)",r0" "\n"
358 "mov.l @(r0,r12),r11" "\n"
362 "mov.l @r15+,r10" "\n"
363 "mov.l @r15+,r11" "\n"
364 "mov.l @r15+,r13" "\n"
365 "lds.l @r15+,pr" "\n"
366 "mov.l @r15+,r14" "\n"
367 "mov.l @r15+,r8" "\n"
372 ".L2"SYMBOL_STRING(cti_vm_throw
)":.long " SYMBOL_STRING(cti_vm_throw
)"@GOT \n"
376 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
377 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
378 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
380 "mov.l @r15+,r10" "\n"
381 "mov.l @r15+,r11" "\n"
382 "mov.l @r15+,r13" "\n"
383 "lds.l @r15+,pr" "\n"
384 "mov.l @r15+,r14" "\n"
385 "mov.l @r15+,r8" "\n"
391 #error "JIT not supported on this platform."
394 #else // USE(JSVALUE32_64)
396 #if COMPILER(GCC) && CPU(X86_64)
398 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
399 // need to change the assembly trampolines below to match.
400 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
401 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline
);
402 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedRBX
) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
406 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
407 HIDE_SYMBOL(ctiTrampoline
) "\n"
408 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
410 "movq %rsp, %rbp" "\n"
416 // Form the JIT stubs area
423 "subq $0x48, %rsp" "\n"
424 "movq $512, %r12" "\n"
425 "movq $0xFFFF000000000000, %r14" "\n"
426 "movq $0xFFFF000000000002, %r15" "\n"
427 "movq %rdx, %r13" "\n"
429 "addq $0x78, %rsp" "\n"
440 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
441 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
442 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
443 "movq %rsp, %rdi" "\n"
444 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
449 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
450 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
451 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
452 "addq $0x78, %rsp" "\n"
463 #error "JIT not supported on this platform."
466 #endif // USE(JSVALUE32_64)
472 ".set noreorder" "\n"
475 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
476 ".ent " SYMBOL_STRING(ctiTrampoline
) "\n"
477 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
478 "addiu $29,$29,-" STRINGIZE_VALUE_OF(STACK_LENGTH
) "\n"
479 "sw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "($29)" "\n"
480 "sw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET
) "($29)" "\n"
481 "sw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET
) "($29)" "\n"
482 "sw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET
) "($29)" "\n"
484 "sw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET
) "($29)" "\n"
486 "move $16,$6 # set callFrameRegister" "\n"
487 "li $17,512 # set timeoutCheckRegister" "\n"
488 "move $25,$4 # move executableAddress to t9" "\n"
489 "sw $5," STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET
) "($29) # store registerFile to current stack" "\n"
490 "sw $6," STRINGIZE_VALUE_OF(CALLFRAME_OFFSET
) "($29) # store callFrame to curent stack" "\n"
491 "sw $7," STRINGIZE_VALUE_OF(EXCEPTION_OFFSET
) "($29) # store exception to current stack" "\n"
492 "lw $8," STRINGIZE_VALUE_OF(STACK_LENGTH
+ 16) "($29) # load enableProfilerReference from previous stack" "\n"
493 "lw $9," STRINGIZE_VALUE_OF(STACK_LENGTH
+ 20) "($29) # load globalData from previous stack" "\n"
494 "sw $8," STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET
) "($29) # store enableProfilerReference to current stack" "\n"
496 "sw $9," STRINGIZE_VALUE_OF(GLOBAL_DATA_OFFSET
) "($29) # store globalData to current stack" "\n"
497 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET
) "($29)" "\n"
498 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET
) "($29)" "\n"
499 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET
) "($29)" "\n"
500 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "($29)" "\n"
502 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH
) "\n"
505 ".end " SYMBOL_STRING(ctiTrampoline
) "\n"
511 ".set noreorder" "\n"
514 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
515 ".ent " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
516 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
518 "lw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET
) "($29)" "\n"
520 "la $25," SYMBOL_STRING(cti_vm_throw
) "\n"
522 "bal " SYMBOL_STRING(cti_vm_throw
) "\n"
525 "jal " SYMBOL_STRING(cti_vm_throw
) "\n"
528 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET
) "($29)" "\n"
529 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET
) "($29)" "\n"
530 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET
) "($29)" "\n"
531 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "($29)" "\n"
533 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH
) "\n"
536 ".end " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
542 ".set noreorder" "\n"
545 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
546 ".ent " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
547 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
548 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET
) "($29)" "\n"
549 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET
) "($29)" "\n"
550 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET
) "($29)" "\n"
551 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "($29)" "\n"
553 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH
) "\n"
556 ".end " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
560 #if COMPILER(GCC) && CPU(ARM_THUMB2)
565 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
566 HIDE_SYMBOL(ctiTrampoline
) "\n"
568 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline
) "\n"
569 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
570 "sub sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET
) "\n"
571 "str lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "]" "\n"
572 "str r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET
) "]" "\n"
573 "str r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET
) "]" "\n"
574 "str r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET
) "]" "\n"
575 "str r1, [sp, #" STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET
) "]" "\n"
576 "str r2, [sp, #" STRINGIZE_VALUE_OF(CALLFRAME_OFFSET
) "]" "\n"
577 "str r3, [sp, #" STRINGIZE_VALUE_OF(EXCEPTION_OFFSET
) "]" "\n"
581 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET
) "]" "\n"
582 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET
) "]" "\n"
583 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET
) "]" "\n"
584 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "]" "\n"
585 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET
) "\n"
592 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
593 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
595 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline
) "\n"
596 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
598 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
599 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET
) "]" "\n"
600 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET
) "]" "\n"
601 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET
) "]" "\n"
602 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "]" "\n"
603 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET
) "\n"
610 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
611 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
613 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught
) "\n"
614 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
615 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET
) "]" "\n"
616 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET
) "]" "\n"
617 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET
) "]" "\n"
618 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "]" "\n"
619 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET
) "\n"
623 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
626 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
627 HIDE_SYMBOL(ctiTrampoline
) "\n"
628 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
629 "stmdb sp!, {r1-r3}" "\n"
630 "stmdb sp!, {r4-r8, lr}" "\n"
631 "sub sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET
) "\n"
634 // r0 contains the code
637 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET
) "\n"
638 "ldmia sp!, {r4-r8, lr}" "\n"
639 "add sp, sp, #12" "\n"
644 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
645 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
646 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
648 "bl " SYMBOL_STRING(cti_vm_throw
) "\n"
650 // Both has the same return sequence
651 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
652 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
653 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
654 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET
) "\n"
655 "ldmia sp!, {r4-r8, lr}" "\n"
656 "add sp, sp, #12" "\n"
660 #elif COMPILER(RVCT) && CPU(ARM_THUMB2)
662 __asm EncodedJSValue
ctiTrampoline(void*, RegisterFile
*, CallFrame
*, JSValue
*, Profiler
**, JSGlobalData
*)
665 sub sp
, sp
, # ENABLE_PROFILER_REFERENCE_OFFSET
666 str lr
, [sp
, # PRESERVED_RETURN_ADDRESS_OFFSET ]
667 str r4
, [sp
, # PRESERVED_R4_OFFSET ]
668 str r5
, [sp
, # PRESERVED_R5_OFFSET ]
669 str r6
, [sp
, # PRESERVED_R6_OFFSET ]
670 str r1
, [sp
, # REGISTER_FILE_OFFSET ]
671 str r2
, [sp
, # CALLFRAME_OFFSET ]
672 str r3
, [sp
, # EXCEPTION_OFFSET ]
676 ldr r6
, [sp
, # PRESERVED_R6_OFFSET ]
677 ldr r5
, [sp
, # PRESERVED_R5_OFFSET ]
678 ldr r4
, [sp
, # PRESERVED_R4_OFFSET ]
679 ldr lr
, [sp
, # PRESERVED_RETURN_ADDRESS_OFFSET ]
680 add sp
, sp
, # ENABLE_PROFILER_REFERENCE_OFFSET
684 __asm
void ctiVMThrowTrampoline()
689 ldr r6
, [sp
, # PRESERVED_R6_OFFSET ]
690 ldr r5
, [sp
, # PRESERVED_R5_OFFSET ]
691 ldr r4
, [sp
, # PRESERVED_R4_OFFSET ]
692 ldr lr
, [sp
, # PRESERVED_RETURN_ADDRESS_OFFSET ]
693 add sp
, sp
, # ENABLE_PROFILER_REFERENCE_OFFSET
697 __asm
void ctiOpThrowNotCaught()
700 ldr r6
, [sp
, # PRESERVED_R6_OFFSET ]
701 ldr r5
, [sp
, # PRESERVED_R5_OFFSET ]
702 ldr r4
, [sp
, # PRESERVED_R4_OFFSET ]
703 ldr lr
, [sp
, # PRESERVED_RETURN_ADDRESS_OFFSET ]
704 add sp
, sp
, # ENABLE_PROFILER_REFERENCE_OFFSET
708 #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
710 __asm EncodedJSValue
ctiTrampoline(void*, RegisterFile
*, CallFrame
*, void* /*unused1*/, Profiler
**, JSGlobalData
*)
714 stmdb sp
!, {r4
-r8
, lr
}
715 sub sp
, sp
, # PRESERVEDR4_OFFSET
720 add sp
, sp
, # PRESERVEDR4_OFFSET
721 ldmia sp
!, {r4
-r8
, lr
}
726 __asm
void ctiVMThrowTrampoline()
732 add sp
, sp
, # PRESERVEDR4_OFFSET
733 ldmia sp
!, {r4
-r8
, lr
}
738 __asm
void ctiOpThrowNotCaught()
741 add sp
, sp
, # PRESERVEDR4_OFFSET
742 ldmia sp
!, {r4
-r8
, lr
}
748 #if ENABLE(OPCODE_SAMPLING)
749 #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler()
751 #define CTI_SAMPLER 0
754 JITThunks::JITThunks(JSGlobalData
* globalData
)
755 : m_hostFunctionStubMap(adoptPtr(new HostFunctionStubMap
))
757 if (!globalData
->executableAllocator
.isValid())
760 JIT::compileCTIMachineTrampolines(globalData
, &m_executablePool
, &m_trampolineStructure
);
761 ASSERT(m_executablePool
);
763 // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
764 // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
766 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedReturnAddress
) == PRESERVED_RETURN_ADDRESS_OFFSET
);
767 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR4
) == PRESERVED_R4_OFFSET
);
768 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR5
) == PRESERVED_R5_OFFSET
);
769 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR6
) == PRESERVED_R6_OFFSET
);
771 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, registerFile
) == REGISTER_FILE_OFFSET
);
772 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, callFrame
) == CALLFRAME_OFFSET
);
773 // The fifth argument is the first item already on the stack.
774 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, enabledProfilerReference
) == ENABLE_PROFILER_REFERENCE_OFFSET
);
776 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, thunkReturnAddress
) == THUNK_RETURN_ADDRESS_OFFSET
);
778 #elif CPU(ARM_TRADITIONAL)
780 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, thunkReturnAddress
) == THUNK_RETURN_ADDRESS_OFFSET
);
781 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR4
) == PRESERVEDR4_OFFSET
);
785 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedGP
) == PRESERVED_GP_OFFSET
);
786 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedS0
) == PRESERVED_S0_OFFSET
);
787 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedS1
) == PRESERVED_S1_OFFSET
);
788 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedS2
) == PRESERVED_S2_OFFSET
);
789 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedReturnAddress
) == PRESERVED_RETURN_ADDRESS_OFFSET
);
790 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, thunkReturnAddress
) == THUNK_RETURN_ADDRESS_OFFSET
);
791 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, registerFile
) == REGISTER_FILE_OFFSET
);
792 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, callFrame
) == CALLFRAME_OFFSET
);
793 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, unused1
) == EXCEPTION_OFFSET
);
794 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, enabledProfilerReference
) == ENABLE_PROFILER_REFERENCE_OFFSET
);
795 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, globalData
) == GLOBAL_DATA_OFFSET
);
800 JITThunks::~JITThunks()
804 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
806 NEVER_INLINE
void JITThunks::tryCachePutByID(CallFrame
* callFrame
, CodeBlock
* codeBlock
, ReturnAddressPtr returnAddress
, JSValue baseValue
, const PutPropertySlot
& slot
, StructureStubInfo
* stubInfo
, bool direct
)
808 // The interpreter checks for recursion here; I do not believe this can occur in CTI.
810 if (!baseValue
.isCell())
813 // Uncacheable: give up.
814 if (!slot
.isCacheable()) {
815 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(direct
? cti_op_put_by_id_direct_generic
: cti_op_put_by_id_generic
));
819 JSCell
* baseCell
= baseValue
.asCell();
820 Structure
* structure
= baseCell
->structure();
822 if (structure
->isUncacheableDictionary() || structure
->typeInfo().prohibitsPropertyCaching()) {
823 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(direct
? cti_op_put_by_id_direct_generic
: cti_op_put_by_id_generic
));
827 // If baseCell != base, then baseCell must be a proxy for another object.
828 if (baseCell
!= slot
.base()) {
829 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(direct
? cti_op_put_by_id_direct_generic
: cti_op_put_by_id_generic
));
833 // Cache hit: Specialize instruction and ref Structures.
835 // Structure transition, cache transition info
836 if (slot
.type() == PutPropertySlot::NewProperty
) {
837 if (structure
->isDictionary()) {
838 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(direct
? cti_op_put_by_id_direct_generic
: cti_op_put_by_id_generic
));
842 // put_by_id_transition checks the prototype chain for setters.
843 normalizePrototypeChain(callFrame
, baseCell
);
845 StructureChain
* prototypeChain
= structure
->prototypeChain(callFrame
);
846 stubInfo
->initPutByIdTransition(callFrame
->globalData(), codeBlock
->ownerExecutable(), structure
->previousID(), structure
, prototypeChain
);
847 JIT::compilePutByIdTransition(callFrame
->scopeChain()->globalData
, codeBlock
, stubInfo
, structure
->previousID(), structure
, slot
.cachedOffset(), prototypeChain
, returnAddress
, direct
);
851 stubInfo
->initPutByIdReplace(callFrame
->globalData(), codeBlock
->ownerExecutable(), structure
);
853 JIT::patchPutByIdReplace(codeBlock
, stubInfo
, structure
, slot
.cachedOffset(), returnAddress
, direct
);
856 NEVER_INLINE
void JITThunks::tryCacheGetByID(CallFrame
* callFrame
, CodeBlock
* codeBlock
, ReturnAddressPtr returnAddress
, JSValue baseValue
, const Identifier
& propertyName
, const PropertySlot
& slot
, StructureStubInfo
* stubInfo
)
858 // FIXME: Write a test that proves we need to check for recursion here just
859 // like the interpreter does, then add a check for recursion.
861 // FIXME: Cache property access for immediates.
862 if (!baseValue
.isCell()) {
863 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
867 JSGlobalData
* globalData
= &callFrame
->globalData();
869 if (isJSArray(globalData
, baseValue
) && propertyName
== callFrame
->propertyNames().length
) {
870 JIT::compilePatchGetArrayLength(callFrame
->scopeChain()->globalData
, codeBlock
, returnAddress
);
874 if (isJSString(globalData
, baseValue
) && propertyName
== callFrame
->propertyNames().length
) {
875 // The tradeoff of compiling an patched inline string length access routine does not seem
876 // to pay off, so we currently only do this for arrays.
877 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, globalData
->jitStubs
->ctiStringLengthTrampoline());
881 // Uncacheable: give up.
882 if (!slot
.isCacheable()) {
883 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
887 JSCell
* baseCell
= baseValue
.asCell();
888 Structure
* structure
= baseCell
->structure();
890 if (structure
->isUncacheableDictionary() || structure
->typeInfo().prohibitsPropertyCaching()) {
891 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
895 // Cache hit: Specialize instruction and ref Structures.
897 if (slot
.slotBase() == baseValue
) {
898 // set this up, so derefStructures can do it's job.
899 stubInfo
->initGetByIdSelf(callFrame
->globalData(), codeBlock
->ownerExecutable(), structure
);
900 if ((slot
.cachedPropertyType() != PropertySlot::Value
) || ((slot
.cachedOffset() * sizeof(JSValue
)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset
))
901 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_self_fail
));
903 JIT::patchGetByIdSelf(codeBlock
, stubInfo
, structure
, slot
.cachedOffset(), returnAddress
);
907 if (structure
->isDictionary()) {
908 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
912 if (slot
.slotBase() == structure
->prototypeForLookup(callFrame
)) {
913 ASSERT(slot
.slotBase().isObject());
915 JSObject
* slotBaseObject
= asObject(slot
.slotBase());
916 size_t offset
= slot
.cachedOffset();
918 // Since we're accessing a prototype in a loop, it's a good bet that it
919 // should not be treated as a dictionary.
920 if (slotBaseObject
->structure()->isDictionary()) {
921 slotBaseObject
->flattenDictionaryObject(callFrame
->globalData());
922 offset
= slotBaseObject
->structure()->get(callFrame
->globalData(), propertyName
);
925 stubInfo
->initGetByIdProto(callFrame
->globalData(), codeBlock
->ownerExecutable(), structure
, slotBaseObject
->structure());
927 ASSERT(!structure
->isDictionary());
928 ASSERT(!slotBaseObject
->structure()->isDictionary());
929 JIT::compileGetByIdProto(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, structure
, slotBaseObject
->structure(), propertyName
, slot
, offset
, returnAddress
);
933 size_t offset
= slot
.cachedOffset();
934 size_t count
= normalizePrototypeChain(callFrame
, baseValue
, slot
.slotBase(), propertyName
, offset
);
936 stubInfo
->accessType
= access_get_by_id_generic
;
940 StructureChain
* prototypeChain
= structure
->prototypeChain(callFrame
);
941 stubInfo
->initGetByIdChain(callFrame
->globalData(), codeBlock
->ownerExecutable(), structure
, prototypeChain
);
942 JIT::compileGetByIdChain(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, structure
, prototypeChain
, count
, propertyName
, slot
, offset
, returnAddress
);
945 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
951 static void jscGeneratedNativeCode()
953 // When executing a JIT stub function (which might do an allocation), we hack the return address
954 // to pretend to be executing this function, to keep stack logging tools from blowing out
961 ALWAYS_INLINE
StackHack(JITStackFrame
& stackFrame
)
962 : stackFrame(stackFrame
)
963 , savedReturnAddress(*stackFrame
.returnAddressSlot())
965 *stackFrame
.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode
));
968 ALWAYS_INLINE
~StackHack()
970 *stackFrame
.returnAddressSlot() = savedReturnAddress
;
973 JITStackFrame
& stackFrame
;
974 ReturnAddressPtr savedReturnAddress
;
977 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
978 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
979 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
983 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS)
984 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
985 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
989 // The reason this is not inlined is to avoid having to do a PIC branch
990 // to get the address of the ctiVMThrowTrampoline function. It's also
991 // good to keep the code size down by leaving as much of the exception
992 // handling code out of line as possible.
993 static NEVER_INLINE
void returnToThrowTrampoline(JSGlobalData
* globalData
, ReturnAddressPtr exceptionLocation
, ReturnAddressPtr
& returnAddressSlot
)
995 ASSERT(globalData
->exception
);
996 globalData
->exceptionLocation
= exceptionLocation
;
997 returnAddressSlot
= ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline
));
1000 static NEVER_INLINE
void throwStackOverflowError(CallFrame
* callFrame
, JSGlobalData
* globalData
, ReturnAddressPtr exceptionLocation
, ReturnAddressPtr
& returnAddressSlot
)
1002 globalData
->exception
= createStackOverflowError(callFrame
);
1003 returnToThrowTrampoline(globalData
, exceptionLocation
, returnAddressSlot
);
1006 #define VM_THROW_EXCEPTION() \
1008 VM_THROW_EXCEPTION_AT_END(); \
1011 #define VM_THROW_EXCEPTION_AT_END() \
1013 returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\
1016 #define CHECK_FOR_EXCEPTION() \
1018 if (UNLIKELY(stackFrame.globalData->exception)) \
1019 VM_THROW_EXCEPTION(); \
1021 #define CHECK_FOR_EXCEPTION_AT_END() \
1023 if (UNLIKELY(stackFrame.globalData->exception)) \
1024 VM_THROW_EXCEPTION_AT_END(); \
1026 #define CHECK_FOR_EXCEPTION_VOID() \
1028 if (UNLIKELY(stackFrame.globalData->exception)) { \
1029 VM_THROW_EXCEPTION_AT_END(); \
1034 struct ExceptionHandler
{
1036 CallFrame
* callFrame
;
1038 static ExceptionHandler
jitThrow(JSGlobalData
* globalData
, CallFrame
* callFrame
, JSValue exceptionValue
, ReturnAddressPtr faultLocation
)
1040 ASSERT(exceptionValue
);
1042 unsigned vPCIndex
= callFrame
->codeBlock()->bytecodeOffset(faultLocation
);
1043 globalData
->exception
= JSValue();
1044 HandlerInfo
* handler
= globalData
->interpreter
->throwException(callFrame
, exceptionValue
, vPCIndex
); // This may update callFrame & exceptionValue!
1045 globalData
->exception
= exceptionValue
;
1047 void* catchRoutine
= handler
? handler
->nativeCode
.executableAddress() : FunctionPtr(ctiOpThrowNotCaught
).value();
1048 ASSERT(catchRoutine
);
1049 ExceptionHandler exceptionHandler
= { catchRoutine
, callFrame
};
1050 return exceptionHandler
;
1053 #if CPU(ARM_THUMB2) && COMPILER(GCC)
1055 #define DEFINE_STUB_FUNCTION(rtype, op) \
1057 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1062 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1063 HIDE_SYMBOL(cti_##op) "\n" \
1065 ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \
1066 SYMBOL_STRING(cti_##op) ":" "\n" \
1067 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1068 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1069 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1072 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
1076 #define DEFINE_STUB_FUNCTION(rtype, op) \
1078 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1083 ".set noreorder" "\n" \
1084 ".set nomacro" "\n" \
1085 ".set nomips16" "\n" \
1086 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1087 ".ent " SYMBOL_STRING(cti_##op) "\n" \
1088 SYMBOL_STRING(cti_##op) ":" "\n" \
1089 "lw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n" \
1090 "sw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1092 "la $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \
1093 ".set nomacro" "\n" \
1094 "bal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1096 "lw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1099 ".set reorder" "\n" \
1101 ".end " SYMBOL_STRING(cti_##op) "\n" \
1103 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1105 #else // WTF_MIPS_PIC
1106 #define DEFINE_STUB_FUNCTION(rtype, op) \
1108 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1113 ".set noreorder" "\n" \
1114 ".set nomacro" "\n" \
1115 ".set nomips16" "\n" \
1116 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1117 ".ent " SYMBOL_STRING(cti_##op) "\n" \
1118 SYMBOL_STRING(cti_##op) ":" "\n" \
1119 "sw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1120 "jal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1122 "lw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1125 ".set reorder" "\n" \
1127 ".end " SYMBOL_STRING(cti_##op) "\n" \
1129 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1133 #elif CPU(ARM_TRADITIONAL) && COMPILER(GCC)
1135 #define DEFINE_STUB_FUNCTION(rtype, op) \
1137 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1140 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1141 SYMBOL_STRING(cti_##op) ":" "\n" \
1142 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1143 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1144 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1147 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1149 #elif (CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)) && COMPILER(RVCT)
1151 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1153 /* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */
1155 /* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */
1156 /* The pattern "#xxx#" will be replaced with "xxx" */
1159 RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
1160 RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
1163 RVCT( IMPORT JITStubThunked_#op#)
1164 RVCT( str lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
1165 RVCT( bl JITStubThunked_#op#)
1166 RVCT( ldr lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
1172 /* Include the generated file */
1173 #include "GeneratedJITStubs_RVCT.h"
1175 #elif CPU(ARM_TRADITIONAL) && COMPILER(MSVC)
1177 #define DEFINE_STUB_FUNCTION(rtype, op) extern "C" rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1179 /* The following is a workaround for MSVC toolchain; inline assembler is not supported */
1181 /* The following section is a template to generate code for GeneratedJITStubs_MSVC.asm */
1182 /* The pattern "#xxx#" will be replaced with "xxx" */
1185 MSVC_BEGIN( AREA Trampoline, CODE)
1187 MSVC_BEGIN( EXPORT ctiTrampoline)
1188 MSVC_BEGIN( EXPORT ctiVMThrowTrampoline)
1189 MSVC_BEGIN( EXPORT ctiOpThrowNotCaught)
1191 MSVC_BEGIN(ctiTrampoline PROC)
1192 MSVC_BEGIN( stmdb sp!, {r1-r3})
1193 MSVC_BEGIN( stmdb sp!, {r4-r8, lr})
1194 MSVC_BEGIN( sub sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1195 MSVC_BEGIN( mov r4, r2)
1196 MSVC_BEGIN( mov r5, #512)
1197 MSVC_BEGIN( ; r0 contains the code)
1198 MSVC_BEGIN( mov lr, pc)
1200 MSVC_BEGIN( add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1201 MSVC_BEGIN( ldmia sp!, {r4-r8, lr})
1202 MSVC_BEGIN( add sp, sp, #12)
1204 MSVC_BEGIN(ctiTrampoline ENDP)
1206 MSVC_BEGIN(ctiVMThrowTrampoline PROC)
1207 MSVC_BEGIN( mov r0, sp)
1208 MSVC_BEGIN( mov lr, pc)
1209 MSVC_BEGIN( bl cti_vm_throw)
1210 MSVC_BEGIN(ctiOpThrowNotCaught)
1211 MSVC_BEGIN( add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1212 MSVC_BEGIN( ldmia sp!, {r4-r8, lr})
1213 MSVC_BEGIN( add sp, sp, #12)
1215 MSVC_BEGIN(ctiVMThrowTrampoline ENDP)
1218 MSVC( EXPORT cti_#op#)
1219 MSVC( IMPORT JITStubThunked_#op#)
1221 MSVC( str lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET)
1222 MSVC( bl JITStubThunked_#op#)
1223 MSVC( ldr lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET)
1232 #define DEFINE_STUB_FUNCTION(rtype, op) \
1234 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1238 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1239 SYMBOL_STRING(cti_##op) ":" "\n" \
1240 "sts pr, r11" "\n" \
1241 "mov.l r11, @(0x38, r15)" "\n" \
1242 "mov.l .L2"SYMBOL_STRING(JITStubThunked_##op)",r0" "\n" \
1243 "mov.l @(r0,r12),r11" "\n" \
1246 "mov.l @(0x38, r15), r11 " "\n" \
1247 "lds r11, pr " "\n" \
1251 ".L2"SYMBOL_STRING(JITStubThunked_##op)":.long " SYMBOL_STRING(JITStubThunked_##op)"@GOT \n" \
1253 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1255 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
1258 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_create_this
)
1260 STUB_INIT_STACK_FRAME(stackFrame
);
1261 CallFrame
* callFrame
= stackFrame
.callFrame
;
1263 JSFunction
* constructor
= asFunction(callFrame
->callee());
1264 #if !ASSERT_DISABLED
1265 ConstructData constructData
;
1266 ASSERT(constructor
->getConstructData(constructData
) == ConstructTypeJS
);
1269 Structure
* structure
;
1270 JSValue proto
= stackFrame
.args
[0].jsValue();
1271 if (proto
.isObject())
1272 structure
= asObject(proto
)->inheritorID(*stackFrame
.globalData
);
1274 structure
= constructor
->scope()->globalObject
->emptyObjectStructure();
1275 JSValue result
= constructEmptyObject(callFrame
, structure
);
1277 return JSValue::encode(result
);
1280 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_convert_this
)
1282 STUB_INIT_STACK_FRAME(stackFrame
);
1284 JSValue v1
= stackFrame
.args
[0].jsValue();
1285 CallFrame
* callFrame
= stackFrame
.callFrame
;
1287 JSObject
* result
= v1
.toThisObject(callFrame
);
1288 CHECK_FOR_EXCEPTION_AT_END();
1289 return JSValue::encode(result
);
1292 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_convert_this_strict
)
1294 STUB_INIT_STACK_FRAME(stackFrame
);
1296 JSValue v1
= stackFrame
.args
[0].jsValue();
1297 CallFrame
* callFrame
= stackFrame
.callFrame
;
1298 ASSERT(v1
.asCell()->structure()->typeInfo().needsThisConversion());
1299 JSValue result
= v1
.toStrictThisObject(callFrame
);
1300 CHECK_FOR_EXCEPTION_AT_END();
1301 return JSValue::encode(result
);
1304 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_add
)
1306 STUB_INIT_STACK_FRAME(stackFrame
);
1308 JSValue v1
= stackFrame
.args
[0].jsValue();
1309 JSValue v2
= stackFrame
.args
[1].jsValue();
1310 CallFrame
* callFrame
= stackFrame
.callFrame
;
1312 if (v1
.isString()) {
1313 JSValue result
= v2
.isString()
1314 ? jsString(callFrame
, asString(v1
), asString(v2
))
1315 : jsString(callFrame
, asString(v1
), v2
.toPrimitiveString(callFrame
));
1316 CHECK_FOR_EXCEPTION_AT_END();
1317 return JSValue::encode(result
);
1320 double left
= 0.0, right
;
1321 if (v1
.getNumber(left
) && v2
.getNumber(right
))
1322 return JSValue::encode(jsNumber(left
+ right
));
1324 // All other cases are pretty uncommon
1325 JSValue result
= jsAddSlowCase(callFrame
, v1
, v2
);
1326 CHECK_FOR_EXCEPTION_AT_END();
1327 return JSValue::encode(result
);
1330 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_pre_inc
)
1332 STUB_INIT_STACK_FRAME(stackFrame
);
1334 JSValue v
= stackFrame
.args
[0].jsValue();
1336 CallFrame
* callFrame
= stackFrame
.callFrame
;
1337 JSValue result
= jsNumber(v
.toNumber(callFrame
) + 1);
1338 CHECK_FOR_EXCEPTION_AT_END();
1339 return JSValue::encode(result
);
1342 DEFINE_STUB_FUNCTION(int, timeout_check
)
1344 STUB_INIT_STACK_FRAME(stackFrame
);
1346 JSGlobalData
* globalData
= stackFrame
.globalData
;
1347 TimeoutChecker
& timeoutChecker
= globalData
->timeoutChecker
;
1349 if (globalData
->terminator
.shouldTerminate()) {
1350 globalData
->exception
= createTerminatedExecutionException(globalData
);
1351 VM_THROW_EXCEPTION_AT_END();
1352 } else if (timeoutChecker
.didTimeOut(stackFrame
.callFrame
)) {
1353 globalData
->exception
= createInterruptedExecutionException(globalData
);
1354 VM_THROW_EXCEPTION_AT_END();
1357 return timeoutChecker
.ticksUntilNextCheck();
1360 DEFINE_STUB_FUNCTION(void*, register_file_check
)
1362 STUB_INIT_STACK_FRAME(stackFrame
);
1363 CallFrame
* callFrame
= stackFrame
.callFrame
;
1365 if (UNLIKELY(!stackFrame
.registerFile
->grow(&callFrame
->registers()[callFrame
->codeBlock()->m_numCalleeRegisters
]))) {
1366 // Rewind to the previous call frame because op_call already optimistically
1367 // moved the call frame forward.
1368 CallFrame
* oldCallFrame
= callFrame
->callerFrame();
1369 ExceptionHandler handler
= jitThrow(stackFrame
.globalData
, oldCallFrame
, createStackOverflowError(oldCallFrame
), ReturnAddressPtr(callFrame
->returnPC()));
1370 STUB_SET_RETURN_ADDRESS(handler
.catchRoutine
);
1371 callFrame
= handler
.callFrame
;
1377 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq
)
1379 STUB_INIT_STACK_FRAME(stackFrame
);
1381 JSValue src1
= stackFrame
.args
[0].jsValue();
1382 JSValue src2
= stackFrame
.args
[1].jsValue();
1383 CallFrame
* callFrame
= stackFrame
.callFrame
;
1385 bool result
= jsLessEq(callFrame
, src1
, src2
);
1386 CHECK_FOR_EXCEPTION_AT_END();
1390 DEFINE_STUB_FUNCTION(JSObject
*, op_new_object
)
1392 STUB_INIT_STACK_FRAME(stackFrame
);
1394 return constructEmptyObject(stackFrame
.callFrame
);
1397 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic
)
1399 STUB_INIT_STACK_FRAME(stackFrame
);
1401 PutPropertySlot
slot(stackFrame
.callFrame
->codeBlock()->isStrictMode());
1402 stackFrame
.args
[0].jsValue().put(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), stackFrame
.args
[2].jsValue(), slot
);
1403 CHECK_FOR_EXCEPTION_AT_END();
1406 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic
)
1408 STUB_INIT_STACK_FRAME(stackFrame
);
1410 PutPropertySlot
slot(stackFrame
.callFrame
->codeBlock()->isStrictMode());
1411 stackFrame
.args
[0].jsValue().putDirect(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), stackFrame
.args
[2].jsValue(), slot
);
1412 CHECK_FOR_EXCEPTION_AT_END();
1415 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_generic
)
1417 STUB_INIT_STACK_FRAME(stackFrame
);
1419 CallFrame
* callFrame
= stackFrame
.callFrame
;
1420 Identifier
& ident
= stackFrame
.args
[1].identifier();
1422 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1423 PropertySlot
slot(baseValue
);
1424 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1426 CHECK_FOR_EXCEPTION_AT_END();
1427 return JSValue::encode(result
);
1430 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1432 DEFINE_STUB_FUNCTION(void, op_put_by_id
)
1434 STUB_INIT_STACK_FRAME(stackFrame
);
1435 CallFrame
* callFrame
= stackFrame
.callFrame
;
1436 Identifier
& ident
= stackFrame
.args
[1].identifier();
1438 PutPropertySlot
slot(callFrame
->codeBlock()->isStrictMode());
1439 stackFrame
.args
[0].jsValue().put(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1441 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1442 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1443 if (!stubInfo
->seenOnce())
1444 stubInfo
->setSeen();
1446 JITThunks::tryCachePutByID(callFrame
, codeBlock
, STUB_RETURN_ADDRESS
, stackFrame
.args
[0].jsValue(), slot
, stubInfo
, false);
1448 CHECK_FOR_EXCEPTION_AT_END();
1451 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct
)
1453 STUB_INIT_STACK_FRAME(stackFrame
);
1454 CallFrame
* callFrame
= stackFrame
.callFrame
;
1455 Identifier
& ident
= stackFrame
.args
[1].identifier();
1457 PutPropertySlot
slot(callFrame
->codeBlock()->isStrictMode());
1458 stackFrame
.args
[0].jsValue().putDirect(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1460 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1461 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1462 if (!stubInfo
->seenOnce())
1463 stubInfo
->setSeen();
1465 JITThunks::tryCachePutByID(callFrame
, codeBlock
, STUB_RETURN_ADDRESS
, stackFrame
.args
[0].jsValue(), slot
, stubInfo
, true);
1467 CHECK_FOR_EXCEPTION_AT_END();
1470 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail
)
1472 STUB_INIT_STACK_FRAME(stackFrame
);
1474 CallFrame
* callFrame
= stackFrame
.callFrame
;
1475 Identifier
& ident
= stackFrame
.args
[1].identifier();
1477 PutPropertySlot
slot(callFrame
->codeBlock()->isStrictMode());
1478 stackFrame
.args
[0].jsValue().put(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1480 CHECK_FOR_EXCEPTION_AT_END();
1483 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail
)
1485 STUB_INIT_STACK_FRAME(stackFrame
);
1487 CallFrame
* callFrame
= stackFrame
.callFrame
;
1488 Identifier
& ident
= stackFrame
.args
[1].identifier();
1490 PutPropertySlot
slot(callFrame
->codeBlock()->isStrictMode());
1491 stackFrame
.args
[0].jsValue().putDirect(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1493 CHECK_FOR_EXCEPTION_AT_END();
1496 DEFINE_STUB_FUNCTION(JSObject
*, op_put_by_id_transition_realloc
)
1498 STUB_INIT_STACK_FRAME(stackFrame
);
1500 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1501 int32_t oldSize
= stackFrame
.args
[3].int32();
1502 int32_t newSize
= stackFrame
.args
[4].int32();
1504 ASSERT(baseValue
.isObject());
1505 JSObject
* base
= asObject(baseValue
);
1506 base
->allocatePropertyStorage(oldSize
, newSize
);
1511 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_method_check
)
1513 STUB_INIT_STACK_FRAME(stackFrame
);
1515 CallFrame
* callFrame
= stackFrame
.callFrame
;
1516 Identifier
& ident
= stackFrame
.args
[1].identifier();
1518 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1519 PropertySlot
slot(baseValue
);
1520 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1521 CHECK_FOR_EXCEPTION();
1523 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1524 MethodCallLinkInfo
& methodCallLinkInfo
= codeBlock
->getMethodCallLinkInfo(STUB_RETURN_ADDRESS
);
1526 if (!methodCallLinkInfo
.seenOnce()) {
1527 methodCallLinkInfo
.setSeen();
1528 return JSValue::encode(result
);
1531 // If we successfully got something, then the base from which it is being accessed must
1532 // be an object. (Assertion to ensure asObject() call below is safe, which comes after
1533 // an isCacheable() chceck.
1534 ASSERT(!slot
.isCacheableValue() || slot
.slotBase().isObject());
1537 // * We're dealing with a JSCell,
1538 // * the property is cachable,
1539 // * it's not a dictionary
1540 // * there is a function cached.
1541 Structure
* structure
;
1543 JSObject
* slotBaseObject
;
1544 if (baseValue
.isCell()
1545 && slot
.isCacheableValue()
1546 && !(structure
= baseValue
.asCell()->structure())->isUncacheableDictionary()
1547 && (slotBaseObject
= asObject(slot
.slotBase()))->getPropertySpecificValue(callFrame
, ident
, specific
)
1551 JSObjectWithGlobalObject
* callee
= (JSObjectWithGlobalObject
*)specific
;
1553 // Since we're accessing a prototype in a loop, it's a good bet that it
1554 // should not be treated as a dictionary.
1555 if (slotBaseObject
->structure()->isDictionary())
1556 slotBaseObject
->flattenDictionaryObject(callFrame
->globalData());
1558 // The result fetched should always be the callee!
1559 ASSERT(result
== JSValue(callee
));
1561 // Check to see if the function is on the object's prototype. Patch up the code to optimize.
1562 if (slot
.slotBase() == structure
->prototypeForLookup(callFrame
)) {
1563 JIT::patchMethodCallProto(callFrame
->globalData(), codeBlock
, methodCallLinkInfo
, callee
, structure
, slotBaseObject
, STUB_RETURN_ADDRESS
);
1564 return JSValue::encode(result
);
1567 // Check to see if the function is on the object itself.
1568 // Since we generate the method-check to check both the structure and a prototype-structure (since this
1569 // is the common case) we have a problem - we need to patch the prototype structure check to do something
1570 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler
1571 // for now. For now it performs a check on a special object on the global object only used for this
1572 // purpose. The object is in no way exposed, and as such the check will always pass.
1573 if (slot
.slotBase() == baseValue
) {
1574 JIT::patchMethodCallProto(callFrame
->globalData(), codeBlock
, methodCallLinkInfo
, callee
, structure
, callFrame
->scopeChain()->globalObject
->methodCallDummy(), STUB_RETURN_ADDRESS
);
1575 return JSValue::encode(result
);
1579 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
1580 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id
));
1581 return JSValue::encode(result
);
1584 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id
)
1586 STUB_INIT_STACK_FRAME(stackFrame
);
1587 CallFrame
* callFrame
= stackFrame
.callFrame
;
1588 Identifier
& ident
= stackFrame
.args
[1].identifier();
1590 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1591 PropertySlot
slot(baseValue
);
1592 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1594 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1595 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1596 if (!stubInfo
->seenOnce())
1597 stubInfo
->setSeen();
1599 JITThunks::tryCacheGetByID(callFrame
, codeBlock
, STUB_RETURN_ADDRESS
, baseValue
, ident
, slot
, stubInfo
);
1601 CHECK_FOR_EXCEPTION_AT_END();
1602 return JSValue::encode(result
);
1605 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_self_fail
)
1607 STUB_INIT_STACK_FRAME(stackFrame
);
1609 CallFrame
* callFrame
= stackFrame
.callFrame
;
1610 Identifier
& ident
= stackFrame
.args
[1].identifier();
1612 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1613 PropertySlot
slot(baseValue
);
1614 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1616 CHECK_FOR_EXCEPTION();
1618 if (baseValue
.isCell()
1619 && slot
.isCacheable()
1620 && !baseValue
.asCell()->structure()->isUncacheableDictionary()
1621 && slot
.slotBase() == baseValue
) {
1623 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1624 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1626 ASSERT(slot
.slotBase().isObject());
1628 PolymorphicAccessStructureList
* polymorphicStructureList
;
1631 if (stubInfo
->accessType
== access_get_by_id_self
) {
1632 ASSERT(!stubInfo
->stubRoutine
);
1633 polymorphicStructureList
= new PolymorphicAccessStructureList(callFrame
->globalData(), codeBlock
->ownerExecutable(), CodeLocationLabel(), stubInfo
->u
.getByIdSelf
.baseObjectStructure
.get());
1634 stubInfo
->initGetByIdSelfList(polymorphicStructureList
, 1);
1636 polymorphicStructureList
= stubInfo
->u
.getByIdSelfList
.structureList
;
1637 listIndex
= stubInfo
->u
.getByIdSelfList
.listSize
;
1639 if (listIndex
< POLYMORPHIC_LIST_CACHE_SIZE
) {
1640 stubInfo
->u
.getByIdSelfList
.listSize
++;
1641 JIT::compileGetByIdSelfList(callFrame
->scopeChain()->globalData
, codeBlock
, stubInfo
, polymorphicStructureList
, listIndex
, baseValue
.asCell()->structure(), ident
, slot
, slot
.cachedOffset());
1643 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1644 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_generic
));
1647 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_generic
));
1648 return JSValue::encode(result
);
1651 static PolymorphicAccessStructureList
* getPolymorphicAccessStructureListSlot(JSGlobalData
& globalData
, ScriptExecutable
* owner
, StructureStubInfo
* stubInfo
, int& listIndex
)
1653 PolymorphicAccessStructureList
* prototypeStructureList
= 0;
1656 switch (stubInfo
->accessType
) {
1657 case access_get_by_id_proto
:
1658 prototypeStructureList
= new PolymorphicAccessStructureList(globalData
, owner
, stubInfo
->stubRoutine
, stubInfo
->u
.getByIdProto
.baseObjectStructure
.get(), stubInfo
->u
.getByIdProto
.prototypeStructure
.get());
1659 stubInfo
->stubRoutine
= CodeLocationLabel();
1660 stubInfo
->initGetByIdProtoList(prototypeStructureList
, 2);
1662 case access_get_by_id_chain
:
1663 prototypeStructureList
= new PolymorphicAccessStructureList(globalData
, owner
, stubInfo
->stubRoutine
, stubInfo
->u
.getByIdChain
.baseObjectStructure
.get(), stubInfo
->u
.getByIdChain
.chain
.get());
1664 stubInfo
->stubRoutine
= CodeLocationLabel();
1665 stubInfo
->initGetByIdProtoList(prototypeStructureList
, 2);
1667 case access_get_by_id_proto_list
:
1668 prototypeStructureList
= stubInfo
->u
.getByIdProtoList
.structureList
;
1669 listIndex
= stubInfo
->u
.getByIdProtoList
.listSize
;
1670 if (listIndex
< POLYMORPHIC_LIST_CACHE_SIZE
)
1671 stubInfo
->u
.getByIdProtoList
.listSize
++;
1674 ASSERT_NOT_REACHED();
1677 ASSERT(listIndex
<= POLYMORPHIC_LIST_CACHE_SIZE
);
1678 return prototypeStructureList
;
1681 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_getter_stub
)
1683 STUB_INIT_STACK_FRAME(stackFrame
);
1684 CallFrame
* callFrame
= stackFrame
.callFrame
;
1685 GetterSetter
* getterSetter
= asGetterSetter(stackFrame
.args
[0].jsObject());
1686 if (!getterSetter
->getter())
1687 return JSValue::encode(jsUndefined());
1688 JSObject
* getter
= asObject(getterSetter
->getter());
1690 CallType callType
= getter
->getCallData(callData
);
1691 JSValue result
= call(callFrame
, getter
, callType
, callData
, stackFrame
.args
[1].jsObject(), ArgList());
1692 if (callFrame
->hadException())
1693 returnToThrowTrampoline(&callFrame
->globalData(), stackFrame
.args
[2].returnAddress(), STUB_RETURN_ADDRESS
);
1695 return JSValue::encode(result
);
1698 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_custom_stub
)
1700 STUB_INIT_STACK_FRAME(stackFrame
);
1701 CallFrame
* callFrame
= stackFrame
.callFrame
;
1702 JSObject
* slotBase
= stackFrame
.args
[0].jsObject();
1703 PropertySlot::GetValueFunc getter
= reinterpret_cast<PropertySlot::GetValueFunc
>(stackFrame
.args
[1].asPointer
);
1704 const Identifier
& ident
= stackFrame
.args
[2].identifier();
1705 JSValue result
= getter(callFrame
, slotBase
, ident
);
1706 if (callFrame
->hadException())
1707 returnToThrowTrampoline(&callFrame
->globalData(), stackFrame
.args
[3].returnAddress(), STUB_RETURN_ADDRESS
);
1709 return JSValue::encode(result
);
1712 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_list
)
1714 STUB_INIT_STACK_FRAME(stackFrame
);
1716 CallFrame
* callFrame
= stackFrame
.callFrame
;
1717 const Identifier
& propertyName
= stackFrame
.args
[1].identifier();
1719 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1720 PropertySlot
slot(baseValue
);
1721 JSValue result
= baseValue
.get(callFrame
, propertyName
, slot
);
1723 CHECK_FOR_EXCEPTION();
1725 if (!baseValue
.isCell() || !slot
.isCacheable() || baseValue
.asCell()->structure()->isDictionary() || baseValue
.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) {
1726 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1727 return JSValue::encode(result
);
1730 Structure
* structure
= baseValue
.asCell()->structure();
1731 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1732 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1734 ASSERT(slot
.slotBase().isObject());
1735 JSObject
* slotBaseObject
= asObject(slot
.slotBase());
1737 size_t offset
= slot
.cachedOffset();
1739 if (slot
.slotBase() == baseValue
)
1740 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1741 else if (slot
.slotBase() == baseValue
.asCell()->structure()->prototypeForLookup(callFrame
)) {
1742 ASSERT(!baseValue
.asCell()->structure()->isDictionary());
1743 // Since we're accessing a prototype in a loop, it's a good bet that it
1744 // should not be treated as a dictionary.
1745 if (slotBaseObject
->structure()->isDictionary()) {
1746 slotBaseObject
->flattenDictionaryObject(callFrame
->globalData());
1747 offset
= slotBaseObject
->structure()->get(callFrame
->globalData(), propertyName
);
1751 PolymorphicAccessStructureList
* prototypeStructureList
= getPolymorphicAccessStructureListSlot(callFrame
->globalData(), codeBlock
->ownerExecutable(), stubInfo
, listIndex
);
1752 if (listIndex
< POLYMORPHIC_LIST_CACHE_SIZE
) {
1753 JIT::compileGetByIdProtoList(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, prototypeStructureList
, listIndex
, structure
, slotBaseObject
->structure(), propertyName
, slot
, offset
);
1755 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1756 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_list_full
));
1758 } else if (size_t count
= normalizePrototypeChain(callFrame
, baseValue
, slot
.slotBase(), propertyName
, offset
)) {
1759 ASSERT(!baseValue
.asCell()->structure()->isDictionary());
1761 PolymorphicAccessStructureList
* prototypeStructureList
= getPolymorphicAccessStructureListSlot(callFrame
->globalData(), codeBlock
->ownerExecutable(), stubInfo
, listIndex
);
1763 if (listIndex
< POLYMORPHIC_LIST_CACHE_SIZE
) {
1764 StructureChain
* protoChain
= structure
->prototypeChain(callFrame
);
1765 JIT::compileGetByIdChainList(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, prototypeStructureList
, listIndex
, structure
, protoChain
, count
, propertyName
, slot
, offset
);
1767 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1768 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_list_full
));
1771 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1773 return JSValue::encode(result
);
1776 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_list_full
)
1778 STUB_INIT_STACK_FRAME(stackFrame
);
1780 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1781 PropertySlot
slot(baseValue
);
1782 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1784 CHECK_FOR_EXCEPTION_AT_END();
1785 return JSValue::encode(result
);
1788 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_fail
)
1790 STUB_INIT_STACK_FRAME(stackFrame
);
1792 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1793 PropertySlot
slot(baseValue
);
1794 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1796 CHECK_FOR_EXCEPTION_AT_END();
1797 return JSValue::encode(result
);
1800 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_array_fail
)
1802 STUB_INIT_STACK_FRAME(stackFrame
);
1804 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1805 PropertySlot
slot(baseValue
);
1806 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1808 CHECK_FOR_EXCEPTION_AT_END();
1809 return JSValue::encode(result
);
1812 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_string_fail
)
1814 STUB_INIT_STACK_FRAME(stackFrame
);
1816 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1817 PropertySlot
slot(baseValue
);
1818 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1820 CHECK_FOR_EXCEPTION_AT_END();
1821 return JSValue::encode(result
);
1824 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1826 DEFINE_STUB_FUNCTION(void, op_check_has_instance
)
1828 STUB_INIT_STACK_FRAME(stackFrame
);
1830 CallFrame
* callFrame
= stackFrame
.callFrame
;
1831 JSValue baseVal
= stackFrame
.args
[0].jsValue();
1833 // ECMA-262 15.3.5.3:
1834 // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
1836 TypeInfo
typeInfo(UnspecifiedType
);
1837 ASSERT(!baseVal
.isObject() || !(typeInfo
= asObject(baseVal
)->structure()->typeInfo()).implementsHasInstance());
1839 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "instanceof", baseVal
);
1840 VM_THROW_EXCEPTION_AT_END();
1843 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_instanceof
)
1845 STUB_INIT_STACK_FRAME(stackFrame
);
1847 CallFrame
* callFrame
= stackFrame
.callFrame
;
1848 JSValue value
= stackFrame
.args
[0].jsValue();
1849 JSValue baseVal
= stackFrame
.args
[1].jsValue();
1850 JSValue proto
= stackFrame
.args
[2].jsValue();
1852 // At least one of these checks must have failed to get to the slow case.
1853 ASSERT(!value
.isCell() || !baseVal
.isCell() || !proto
.isCell()
1854 || !value
.isObject() || !baseVal
.isObject() || !proto
.isObject()
1855 || (asObject(baseVal
)->structure()->typeInfo().flags() & (ImplementsHasInstance
| OverridesHasInstance
)) != ImplementsHasInstance
);
1858 // ECMA-262 15.3.5.3:
1859 // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
1860 TypeInfo
typeInfo(UnspecifiedType
);
1861 if (!baseVal
.isObject() || !(typeInfo
= asObject(baseVal
)->structure()->typeInfo()).implementsHasInstance()) {
1862 stackFrame
.globalData
->exception
= createInvalidParamError(stackFrame
.callFrame
, "instanceof", baseVal
);
1863 VM_THROW_EXCEPTION();
1865 ASSERT(typeInfo
.type() != UnspecifiedType
);
1867 if (!typeInfo
.overridesHasInstance()) {
1868 if (!value
.isObject())
1869 return JSValue::encode(jsBoolean(false));
1871 if (!proto
.isObject()) {
1872 throwError(callFrame
, createTypeError(callFrame
, "instanceof called on an object with an invalid prototype property."));
1873 VM_THROW_EXCEPTION();
1877 JSValue result
= jsBoolean(asObject(baseVal
)->hasInstance(callFrame
, value
, proto
));
1878 CHECK_FOR_EXCEPTION_AT_END();
1880 return JSValue::encode(result
);
1883 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_del_by_id
)
1885 STUB_INIT_STACK_FRAME(stackFrame
);
1887 CallFrame
* callFrame
= stackFrame
.callFrame
;
1889 JSObject
* baseObj
= stackFrame
.args
[0].jsValue().toObject(callFrame
);
1891 bool couldDelete
= baseObj
->deleteProperty(callFrame
, stackFrame
.args
[1].identifier());
1892 JSValue result
= jsBoolean(couldDelete
);
1893 if (!couldDelete
&& callFrame
->codeBlock()->isStrictMode())
1894 stackFrame
.globalData
->exception
= createTypeError(stackFrame
.callFrame
, "Unable to delete property.");
1896 CHECK_FOR_EXCEPTION_AT_END();
1897 return JSValue::encode(result
);
1900 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_mul
)
1902 STUB_INIT_STACK_FRAME(stackFrame
);
1904 JSValue src1
= stackFrame
.args
[0].jsValue();
1905 JSValue src2
= stackFrame
.args
[1].jsValue();
1909 if (src1
.getNumber(left
) && src2
.getNumber(right
))
1910 return JSValue::encode(jsNumber(left
* right
));
1912 CallFrame
* callFrame
= stackFrame
.callFrame
;
1913 JSValue result
= jsNumber(src1
.toNumber(callFrame
) * src2
.toNumber(callFrame
));
1914 CHECK_FOR_EXCEPTION_AT_END();
1915 return JSValue::encode(result
);
1918 DEFINE_STUB_FUNCTION(JSObject
*, op_new_func
)
1920 STUB_INIT_STACK_FRAME(stackFrame
);
1922 ASSERT(stackFrame
.callFrame
->codeBlock()->codeType() != FunctionCode
|| !stackFrame
.callFrame
->codeBlock()->needsFullScopeChain() || stackFrame
.callFrame
->uncheckedR(stackFrame
.callFrame
->codeBlock()->activationRegister()).jsValue());
1923 return stackFrame
.args
[0].function()->make(stackFrame
.callFrame
, stackFrame
.callFrame
->scopeChain());
1926 DEFINE_STUB_FUNCTION(void*, op_call_jitCompile
)
1928 STUB_INIT_STACK_FRAME(stackFrame
);
1930 #if !ASSERT_DISABLED
1932 ASSERT(stackFrame
.callFrame
->callee()->getCallData(callData
) == CallTypeJS
);
1935 JSFunction
* function
= asFunction(stackFrame
.callFrame
->callee());
1936 ASSERT(!function
->isHostFunction());
1937 FunctionExecutable
* executable
= function
->jsExecutable();
1938 ScopeChainNode
* callDataScopeChain
= function
->scope();
1939 JSObject
* error
= executable
->compileForCall(stackFrame
.callFrame
, callDataScopeChain
);
1941 stackFrame
.callFrame
->globalData().exception
= error
;
1947 DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile
)
1949 STUB_INIT_STACK_FRAME(stackFrame
);
1951 #if !ASSERT_DISABLED
1952 ConstructData constructData
;
1953 ASSERT(asFunction(stackFrame
.callFrame
->callee())->getConstructData(constructData
) == ConstructTypeJS
);
1956 JSFunction
* function
= asFunction(stackFrame
.callFrame
->callee());
1957 ASSERT(!function
->isHostFunction());
1958 FunctionExecutable
* executable
= function
->jsExecutable();
1959 ScopeChainNode
* callDataScopeChain
= function
->scope();
1960 JSObject
* error
= executable
->compileForConstruct(stackFrame
.callFrame
, callDataScopeChain
);
1962 stackFrame
.callFrame
->globalData().exception
= error
;
1968 DEFINE_STUB_FUNCTION(void*, op_call_arityCheck
)
1970 STUB_INIT_STACK_FRAME(stackFrame
);
1972 CallFrame
* callFrame
= stackFrame
.callFrame
;
1973 JSFunction
* callee
= asFunction(callFrame
->callee());
1974 ASSERT(!callee
->isHostFunction());
1975 CodeBlock
* newCodeBlock
= &callee
->jsExecutable()->generatedBytecodeForCall();
1976 int argCount
= callFrame
->argumentCountIncludingThis();
1977 ReturnAddressPtr pc
= callFrame
->returnPC();
1979 ASSERT(argCount
!= newCodeBlock
->m_numParameters
);
1981 CallFrame
* oldCallFrame
= callFrame
->callerFrame();
1984 if (argCount
> newCodeBlock
->m_numParameters
) {
1985 size_t numParameters
= newCodeBlock
->m_numParameters
;
1986 r
= callFrame
->registers() + numParameters
;
1987 Register
* newEnd
= r
+ newCodeBlock
->m_numCalleeRegisters
;
1988 if (!stackFrame
.registerFile
->grow(newEnd
)) {
1989 // Rewind to the previous call frame because op_call already optimistically
1990 // moved the call frame forward.
1991 ExceptionHandler handler
= jitThrow(stackFrame
.globalData
, oldCallFrame
, createStackOverflowError(oldCallFrame
), pc
);
1992 STUB_SET_RETURN_ADDRESS(handler
.catchRoutine
);
1993 return handler
.callFrame
;
1996 Register
* argv
= r
- RegisterFile::CallFrameHeaderSize
- numParameters
- argCount
;
1997 for (size_t i
= 0; i
< numParameters
; ++i
)
1998 argv
[i
+ argCount
] = argv
[i
];
2000 size_t omittedArgCount
= newCodeBlock
->m_numParameters
- argCount
;
2001 r
= callFrame
->registers() + omittedArgCount
;
2002 Register
* newEnd
= r
+ newCodeBlock
->m_numCalleeRegisters
;
2003 if (!stackFrame
.registerFile
->grow(newEnd
)) {
2004 // Rewind to the previous call frame because op_call already optimistically
2005 // moved the call frame forward.
2006 ExceptionHandler handler
= jitThrow(stackFrame
.globalData
, oldCallFrame
, createStackOverflowError(oldCallFrame
), pc
);
2007 STUB_SET_RETURN_ADDRESS(handler
.catchRoutine
);
2008 return handler
.callFrame
;
2011 Register
* argv
= r
- RegisterFile::CallFrameHeaderSize
- omittedArgCount
;
2012 for (size_t i
= 0; i
< omittedArgCount
; ++i
)
2013 argv
[i
] = jsUndefined();
2016 callFrame
= CallFrame::create(r
);
2017 callFrame
->setCallerFrame(oldCallFrame
);
2018 callFrame
->setArgumentCountIncludingThis(argCount
);
2019 callFrame
->setCallee(callee
);
2020 callFrame
->setScopeChain(callee
->scope());
2021 callFrame
->setReturnPC(pc
.value());
2023 ASSERT((void*)callFrame
<= stackFrame
.registerFile
->end());
2027 DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck
)
2029 STUB_INIT_STACK_FRAME(stackFrame
);
2031 CallFrame
* callFrame
= stackFrame
.callFrame
;
2032 JSFunction
* callee
= asFunction(callFrame
->callee());
2033 ASSERT(!callee
->isHostFunction());
2034 CodeBlock
* newCodeBlock
= &callee
->jsExecutable()->generatedBytecodeForConstruct();
2035 int argCount
= callFrame
->argumentCountIncludingThis();
2036 ReturnAddressPtr pc
= callFrame
->returnPC();
2038 ASSERT(argCount
!= newCodeBlock
->m_numParameters
);
2040 CallFrame
* oldCallFrame
= callFrame
->callerFrame();
2043 if (argCount
> newCodeBlock
->m_numParameters
) {
2044 size_t numParameters
= newCodeBlock
->m_numParameters
;
2045 r
= callFrame
->registers() + numParameters
;
2046 Register
* newEnd
= r
+ newCodeBlock
->m_numCalleeRegisters
;
2047 if (!stackFrame
.registerFile
->grow(newEnd
)) {
2048 // Rewind to the previous call frame because op_call already optimistically
2049 // moved the call frame forward.
2050 ExceptionHandler handler
= jitThrow(stackFrame
.globalData
, oldCallFrame
, createStackOverflowError(oldCallFrame
), pc
);
2051 STUB_SET_RETURN_ADDRESS(handler
.catchRoutine
);
2052 return handler
.callFrame
;
2055 Register
* argv
= r
- RegisterFile::CallFrameHeaderSize
- numParameters
- argCount
;
2056 for (size_t i
= 0; i
< numParameters
; ++i
)
2057 argv
[i
+ argCount
] = argv
[i
];
2059 size_t omittedArgCount
= newCodeBlock
->m_numParameters
- argCount
;
2060 r
= callFrame
->registers() + omittedArgCount
;
2061 Register
* newEnd
= r
+ newCodeBlock
->m_numCalleeRegisters
;
2062 if (!stackFrame
.registerFile
->grow(newEnd
)) {
2063 // Rewind to the previous call frame because op_call already optimistically
2064 // moved the call frame forward.
2065 ExceptionHandler handler
= jitThrow(stackFrame
.globalData
, oldCallFrame
, createStackOverflowError(oldCallFrame
), pc
);
2066 STUB_SET_RETURN_ADDRESS(handler
.catchRoutine
);
2067 return handler
.callFrame
;
2070 Register
* argv
= r
- RegisterFile::CallFrameHeaderSize
- omittedArgCount
;
2071 for (size_t i
= 0; i
< omittedArgCount
; ++i
)
2072 argv
[i
] = jsUndefined();
2075 ASSERT((void*)callFrame
<= stackFrame
.registerFile
->end());
2076 callFrame
= CallFrame::create(r
);
2077 callFrame
->setCallerFrame(oldCallFrame
);
2078 callFrame
->setArgumentCountIncludingThis(argCount
);
2079 callFrame
->setCallee(callee
);
2080 callFrame
->setScopeChain(callee
->scope());
2081 callFrame
->setReturnPC(pc
.value());
2083 ASSERT((void*)callFrame
<= stackFrame
.registerFile
->end());
2087 #if ENABLE(JIT_OPTIMIZE_CALL)
2088 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall
)
2090 STUB_INIT_STACK_FRAME(stackFrame
);
2091 CallFrame
* callFrame
= stackFrame
.callFrame
;
2092 JSFunction
* callee
= asFunction(callFrame
->callee());
2093 ExecutableBase
* executable
= callee
->executable();
2095 MacroAssemblerCodePtr codePtr
;
2096 CodeBlock
* codeBlock
= 0;
2097 if (executable
->isHostFunction())
2098 codePtr
= executable
->generatedJITCodeForCall().addressForCall();
2100 FunctionExecutable
* functionExecutable
= static_cast<FunctionExecutable
*>(executable
);
2101 JSObject
* error
= functionExecutable
->compileForCall(callFrame
, callee
->scope());
2103 callFrame
->globalData().exception
= createStackOverflowError(callFrame
);
2106 codeBlock
= &functionExecutable
->generatedBytecodeForCall();
2107 if (callFrame
->argumentCountIncludingThis() == static_cast<size_t>(codeBlock
->m_numParameters
))
2108 codePtr
= functionExecutable
->generatedJITCodeForCall().addressForCall();
2110 codePtr
= functionExecutable
->generatedJITCodeForCallWithArityCheck();
2112 CallLinkInfo
* callLinkInfo
= &stackFrame
.callFrame
->callerFrame()->codeBlock()->getCallLinkInfo(callFrame
->returnPC());
2114 if (!callLinkInfo
->seenOnce())
2115 callLinkInfo
->setSeen();
2117 JIT::linkCall(callee
, stackFrame
.callFrame
->callerFrame()->codeBlock(), codeBlock
, codePtr
, callLinkInfo
, callFrame
->argumentCountIncludingThis(), stackFrame
.globalData
);
2119 return codePtr
.executableAddress();
2122 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct
)
2124 STUB_INIT_STACK_FRAME(stackFrame
);
2125 CallFrame
* callFrame
= stackFrame
.callFrame
;
2126 JSFunction
* callee
= asFunction(callFrame
->callee());
2127 ExecutableBase
* executable
= callee
->executable();
2129 MacroAssemblerCodePtr codePtr
;
2130 CodeBlock
* codeBlock
= 0;
2131 if (executable
->isHostFunction())
2132 codePtr
= executable
->generatedJITCodeForConstruct().addressForCall();
2134 FunctionExecutable
* functionExecutable
= static_cast<FunctionExecutable
*>(executable
);
2135 JSObject
* error
= functionExecutable
->compileForConstruct(callFrame
, callee
->scope());
2137 throwStackOverflowError(callFrame
, stackFrame
.globalData
, ReturnAddressPtr(callFrame
->returnPC()), STUB_RETURN_ADDRESS
);
2140 codeBlock
= &functionExecutable
->generatedBytecodeForConstruct();
2141 if (callFrame
->argumentCountIncludingThis() == static_cast<size_t>(codeBlock
->m_numParameters
))
2142 codePtr
= functionExecutable
->generatedJITCodeForConstruct().addressForCall();
2144 codePtr
= functionExecutable
->generatedJITCodeForConstructWithArityCheck();
2146 CallLinkInfo
* callLinkInfo
= &stackFrame
.callFrame
->callerFrame()->codeBlock()->getCallLinkInfo(callFrame
->returnPC());
2148 if (!callLinkInfo
->seenOnce())
2149 callLinkInfo
->setSeen();
2151 JIT::linkConstruct(callee
, stackFrame
.callFrame
->callerFrame()->codeBlock(), codeBlock
, codePtr
, callLinkInfo
, callFrame
->argumentCountIncludingThis(), stackFrame
.globalData
);
2153 return codePtr
.executableAddress();
2155 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
2157 DEFINE_STUB_FUNCTION(JSObject
*, op_push_activation
)
2159 STUB_INIT_STACK_FRAME(stackFrame
);
2161 JSActivation
* activation
= new (stackFrame
.globalData
) JSActivation(stackFrame
.callFrame
, static_cast<FunctionExecutable
*>(stackFrame
.callFrame
->codeBlock()->ownerExecutable()));
2162 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->push(activation
));
2166 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_call_NotJSFunction
)
2168 STUB_INIT_STACK_FRAME(stackFrame
);
2170 JSValue funcVal
= stackFrame
.args
[0].jsValue();
2173 CallType callType
= getCallData(funcVal
, callData
);
2175 ASSERT(callType
!= CallTypeJS
);
2177 if (callType
== CallTypeHost
) {
2178 int registerOffset
= stackFrame
.args
[1].int32();
2179 int argCount
= stackFrame
.args
[2].int32();
2180 CallFrame
* previousCallFrame
= stackFrame
.callFrame
;
2181 CallFrame
* callFrame
= CallFrame::create(previousCallFrame
->registers() + registerOffset
);
2182 if (!stackFrame
.registerFile
->grow(callFrame
->registers())) {
2183 throwStackOverflowError(previousCallFrame
, stackFrame
.globalData
, callFrame
->returnPC(), STUB_RETURN_ADDRESS
);
2184 VM_THROW_EXCEPTION();
2187 callFrame
->init(0, static_cast<Instruction
*>((STUB_RETURN_ADDRESS
).value()), previousCallFrame
->scopeChain(), previousCallFrame
, argCount
, asObject(funcVal
));
2189 EncodedJSValue returnValue
;
2191 SamplingTool::HostCallRecord
callRecord(CTI_SAMPLER
);
2192 returnValue
= callData
.native
.function(callFrame
);
2195 CHECK_FOR_EXCEPTION_AT_END();
2199 ASSERT(callType
== CallTypeNone
);
2201 stackFrame
.globalData
->exception
= createNotAFunctionError(stackFrame
.callFrame
, funcVal
);
2202 VM_THROW_EXCEPTION();
2205 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_create_arguments
)
2207 STUB_INIT_STACK_FRAME(stackFrame
);
2209 Arguments
* arguments
= new (stackFrame
.globalData
) Arguments(stackFrame
.callFrame
);
2210 return JSValue::encode(JSValue(arguments
));
2213 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_create_arguments_no_params
)
2215 STUB_INIT_STACK_FRAME(stackFrame
);
2217 Arguments
* arguments
= new (stackFrame
.globalData
) Arguments(stackFrame
.callFrame
, Arguments::NoParameters
);
2218 return JSValue::encode(JSValue(arguments
));
2221 DEFINE_STUB_FUNCTION(void, op_tear_off_activation
)
2223 STUB_INIT_STACK_FRAME(stackFrame
);
2225 ASSERT(stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
2226 JSValue activationValue
= stackFrame
.args
[0].jsValue();
2227 if (!activationValue
) {
2228 if (JSValue v
= stackFrame
.args
[1].jsValue()) {
2229 if (!stackFrame
.callFrame
->codeBlock()->isStrictMode())
2230 asArguments(v
)->copyRegisters(*stackFrame
.globalData
);
2234 JSActivation
* activation
= asActivation(stackFrame
.args
[0].jsValue());
2235 activation
->copyRegisters(*stackFrame
.globalData
);
2236 if (JSValue v
= stackFrame
.args
[1].jsValue()) {
2237 if (!stackFrame
.callFrame
->codeBlock()->isStrictMode())
2238 asArguments(v
)->setActivation(*stackFrame
.globalData
, activation
);
2242 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments
)
2244 STUB_INIT_STACK_FRAME(stackFrame
);
2246 ASSERT(stackFrame
.callFrame
->codeBlock()->usesArguments() && !stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
2247 asArguments(stackFrame
.args
[0].jsValue())->copyRegisters(*stackFrame
.globalData
);
2250 DEFINE_STUB_FUNCTION(void, op_profile_will_call
)
2252 STUB_INIT_STACK_FRAME(stackFrame
);
2254 ASSERT(*stackFrame
.enabledProfilerReference
);
2255 (*stackFrame
.enabledProfilerReference
)->willExecute(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue());
2258 DEFINE_STUB_FUNCTION(void, op_profile_did_call
)
2260 STUB_INIT_STACK_FRAME(stackFrame
);
2262 ASSERT(*stackFrame
.enabledProfilerReference
);
2263 (*stackFrame
.enabledProfilerReference
)->didExecute(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue());
2266 DEFINE_STUB_FUNCTION(JSObject
*, op_new_array
)
2268 STUB_INIT_STACK_FRAME(stackFrame
);
2270 ArgList
argList(&stackFrame
.callFrame
->registers()[stackFrame
.args
[0].int32()], stackFrame
.args
[1].int32());
2271 return constructArray(stackFrame
.callFrame
, argList
);
2274 DEFINE_STUB_FUNCTION(JSObject
*, op_new_array_buffer
)
2276 STUB_INIT_STACK_FRAME(stackFrame
);
2278 ArgList
argList(stackFrame
.callFrame
->codeBlock()->constantBuffer(stackFrame
.args
[0].int32()), stackFrame
.args
[1].int32());
2279 return constructArray(stackFrame
.callFrame
, argList
);
2282 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve
)
2284 STUB_INIT_STACK_FRAME(stackFrame
);
2286 CallFrame
* callFrame
= stackFrame
.callFrame
;
2287 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
2289 ScopeChainIterator iter
= scopeChain
->begin();
2290 ScopeChainIterator end
= scopeChain
->end();
2291 ASSERT(iter
!= end
);
2293 Identifier
& ident
= stackFrame
.args
[0].identifier();
2295 JSObject
* o
= iter
->get();
2296 PropertySlot
slot(o
);
2297 if (o
->getPropertySlot(callFrame
, ident
, slot
)) {
2298 JSValue result
= slot
.getValue(callFrame
, ident
);
2299 CHECK_FOR_EXCEPTION_AT_END();
2300 return JSValue::encode(result
);
2302 } while (++iter
!= end
);
2304 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
);
2305 VM_THROW_EXCEPTION();
2308 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_construct_NotJSConstruct
)
2310 STUB_INIT_STACK_FRAME(stackFrame
);
2312 JSValue constrVal
= stackFrame
.args
[0].jsValue();
2314 ConstructData constructData
;
2315 ConstructType constructType
= getConstructData(constrVal
, constructData
);
2317 ASSERT(constructType
!= ConstructTypeJS
);
2319 if (constructType
== ConstructTypeHost
) {
2320 int registerOffset
= stackFrame
.args
[1].int32();
2321 int argCount
= stackFrame
.args
[2].int32();
2322 CallFrame
* previousCallFrame
= stackFrame
.callFrame
;
2323 CallFrame
* callFrame
= CallFrame::create(previousCallFrame
->registers() + registerOffset
);
2324 if (!stackFrame
.registerFile
->grow(callFrame
->registers())) {
2325 throwStackOverflowError(previousCallFrame
, stackFrame
.globalData
, callFrame
->returnPC(), STUB_RETURN_ADDRESS
);
2326 VM_THROW_EXCEPTION();
2329 callFrame
->init(0, static_cast<Instruction
*>((STUB_RETURN_ADDRESS
).value()), previousCallFrame
->scopeChain(), previousCallFrame
, argCount
, asObject(constrVal
));
2331 EncodedJSValue returnValue
;
2333 SamplingTool::HostCallRecord
callRecord(CTI_SAMPLER
);
2334 returnValue
= constructData
.native
.function(callFrame
);
2337 CHECK_FOR_EXCEPTION_AT_END();
2341 ASSERT(constructType
== ConstructTypeNone
);
2343 stackFrame
.globalData
->exception
= createNotAConstructorError(stackFrame
.callFrame
, constrVal
);
2344 VM_THROW_EXCEPTION();
2347 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val
)
2349 STUB_INIT_STACK_FRAME(stackFrame
);
2351 CallFrame
* callFrame
= stackFrame
.callFrame
;
2352 JSGlobalData
* globalData
= stackFrame
.globalData
;
2354 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2355 JSValue subscript
= stackFrame
.args
[1].jsValue();
2357 if (LIKELY(baseValue
.isCell() && subscript
.isString())) {
2358 Identifier
propertyName(callFrame
, asString(subscript
)->value(callFrame
));
2359 PropertySlot
slot(baseValue
.asCell());
2360 // JSString::value may have thrown, but we shouldn't find a property with a null identifier,
2361 // so we should miss this case and wind up in the CHECK_FOR_EXCEPTION_AT_END, below.
2362 if (baseValue
.asCell()->fastGetOwnPropertySlot(callFrame
, propertyName
, slot
)) {
2363 JSValue result
= slot
.getValue(callFrame
, propertyName
);
2364 CHECK_FOR_EXCEPTION();
2365 return JSValue::encode(result
);
2369 if (subscript
.isUInt32()) {
2370 uint32_t i
= subscript
.asUInt32();
2371 if (isJSString(globalData
, baseValue
) && asString(baseValue
)->canGetIndex(i
)) {
2372 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val_string
));
2373 JSValue result
= asString(baseValue
)->getIndex(callFrame
, i
);
2374 CHECK_FOR_EXCEPTION();
2375 return JSValue::encode(result
);
2377 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2378 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2379 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val_byte_array
));
2380 return JSValue::encode(asByteArray(baseValue
)->getIndex(callFrame
, i
));
2382 JSValue result
= baseValue
.get(callFrame
, i
);
2383 CHECK_FOR_EXCEPTION();
2384 return JSValue::encode(result
);
2387 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2388 JSValue result
= baseValue
.get(callFrame
, property
);
2389 CHECK_FOR_EXCEPTION_AT_END();
2390 return JSValue::encode(result
);
2393 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val_string
)
2395 STUB_INIT_STACK_FRAME(stackFrame
);
2397 CallFrame
* callFrame
= stackFrame
.callFrame
;
2398 JSGlobalData
* globalData
= stackFrame
.globalData
;
2400 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2401 JSValue subscript
= stackFrame
.args
[1].jsValue();
2405 if (LIKELY(subscript
.isUInt32())) {
2406 uint32_t i
= subscript
.asUInt32();
2407 if (isJSString(globalData
, baseValue
) && asString(baseValue
)->canGetIndex(i
))
2408 result
= asString(baseValue
)->getIndex(callFrame
, i
);
2410 result
= baseValue
.get(callFrame
, i
);
2411 if (!isJSString(globalData
, baseValue
))
2412 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val
));
2415 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2416 result
= baseValue
.get(callFrame
, property
);
2419 CHECK_FOR_EXCEPTION_AT_END();
2420 return JSValue::encode(result
);
2423 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val_byte_array
)
2425 STUB_INIT_STACK_FRAME(stackFrame
);
2427 CallFrame
* callFrame
= stackFrame
.callFrame
;
2428 JSGlobalData
* globalData
= stackFrame
.globalData
;
2430 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2431 JSValue subscript
= stackFrame
.args
[1].jsValue();
2435 if (LIKELY(subscript
.isUInt32())) {
2436 uint32_t i
= subscript
.asUInt32();
2437 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2438 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2439 return JSValue::encode(asByteArray(baseValue
)->getIndex(callFrame
, i
));
2442 result
= baseValue
.get(callFrame
, i
);
2443 if (!isJSByteArray(globalData
, baseValue
))
2444 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val
));
2446 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2447 result
= baseValue
.get(callFrame
, property
);
2450 CHECK_FOR_EXCEPTION_AT_END();
2451 return JSValue::encode(result
);
2454 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_sub
)
2456 STUB_INIT_STACK_FRAME(stackFrame
);
2458 JSValue src1
= stackFrame
.args
[0].jsValue();
2459 JSValue src2
= stackFrame
.args
[1].jsValue();
2463 if (src1
.getNumber(left
) && src2
.getNumber(right
))
2464 return JSValue::encode(jsNumber(left
- right
));
2466 CallFrame
* callFrame
= stackFrame
.callFrame
;
2467 JSValue result
= jsNumber(src1
.toNumber(callFrame
) - src2
.toNumber(callFrame
));
2468 CHECK_FOR_EXCEPTION_AT_END();
2469 return JSValue::encode(result
);
2472 DEFINE_STUB_FUNCTION(void, op_put_by_val
)
2474 STUB_INIT_STACK_FRAME(stackFrame
);
2476 CallFrame
* callFrame
= stackFrame
.callFrame
;
2477 JSGlobalData
* globalData
= stackFrame
.globalData
;
2479 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2480 JSValue subscript
= stackFrame
.args
[1].jsValue();
2481 JSValue value
= stackFrame
.args
[2].jsValue();
2483 if (LIKELY(subscript
.isUInt32())) {
2484 uint32_t i
= subscript
.asUInt32();
2485 if (isJSArray(globalData
, baseValue
)) {
2486 JSArray
* jsArray
= asArray(baseValue
);
2487 if (jsArray
->canSetIndex(i
))
2488 jsArray
->setIndex(*globalData
, i
, value
);
2490 jsArray
->JSArray::put(callFrame
, i
, value
);
2491 } else if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2492 JSByteArray
* jsByteArray
= asByteArray(baseValue
);
2493 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_put_by_val_byte_array
));
2494 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2495 if (value
.isInt32()) {
2496 jsByteArray
->setIndex(i
, value
.asInt32());
2500 if (value
.getNumber(dValue
)) {
2501 jsByteArray
->setIndex(i
, dValue
);
2506 baseValue
.put(callFrame
, i
, value
);
2508 baseValue
.put(callFrame
, i
, value
);
2510 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2511 if (!stackFrame
.globalData
->exception
) { // Don't put to an object if toString threw an exception.
2512 PutPropertySlot
slot(callFrame
->codeBlock()->isStrictMode());
2513 baseValue
.put(callFrame
, property
, value
, slot
);
2517 CHECK_FOR_EXCEPTION_AT_END();
2520 DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array
)
2522 STUB_INIT_STACK_FRAME(stackFrame
);
2524 CallFrame
* callFrame
= stackFrame
.callFrame
;
2525 JSGlobalData
* globalData
= stackFrame
.globalData
;
2527 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2528 JSValue subscript
= stackFrame
.args
[1].jsValue();
2529 JSValue value
= stackFrame
.args
[2].jsValue();
2531 if (LIKELY(subscript
.isUInt32())) {
2532 uint32_t i
= subscript
.asUInt32();
2533 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2534 JSByteArray
* jsByteArray
= asByteArray(baseValue
);
2536 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2537 if (value
.isInt32()) {
2538 jsByteArray
->setIndex(i
, value
.asInt32());
2542 if (value
.getNumber(dValue
)) {
2543 jsByteArray
->setIndex(i
, dValue
);
2549 if (!isJSByteArray(globalData
, baseValue
))
2550 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_put_by_val
));
2551 baseValue
.put(callFrame
, i
, value
);
2553 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2554 if (!stackFrame
.globalData
->exception
) { // Don't put to an object if toString threw an exception.
2555 PutPropertySlot
slot(callFrame
->codeBlock()->isStrictMode());
2556 baseValue
.put(callFrame
, property
, value
, slot
);
2560 CHECK_FOR_EXCEPTION_AT_END();
2563 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_lesseq
)
2565 STUB_INIT_STACK_FRAME(stackFrame
);
2567 CallFrame
* callFrame
= stackFrame
.callFrame
;
2568 JSValue result
= jsBoolean(jsLessEq(callFrame
, stackFrame
.args
[0].jsValue(), stackFrame
.args
[1].jsValue()));
2569 CHECK_FOR_EXCEPTION_AT_END();
2570 return JSValue::encode(result
);
2573 DEFINE_STUB_FUNCTION(int, op_load_varargs
)
2575 STUB_INIT_STACK_FRAME(stackFrame
);
2577 CallFrame
* callFrame
= stackFrame
.callFrame
;
2578 RegisterFile
* registerFile
= stackFrame
.registerFile
;
2579 int argsOffset
= stackFrame
.args
[0].int32();
2580 JSValue arguments
= callFrame
->registers()[argsOffset
].jsValue();
2581 uint32_t argCount
= 0;
2583 int providedParams
= callFrame
->registers()[RegisterFile::ArgumentCount
].i() - 1;
2584 argCount
= providedParams
;
2585 argCount
= min(argCount
, static_cast<uint32_t>(Arguments::MaxArguments
));
2586 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2587 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2588 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2589 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2590 VM_THROW_EXCEPTION();
2592 int32_t expectedParams
= asFunction(callFrame
->callee())->jsExecutable()->parameterCount();
2593 int32_t inplaceArgs
= min(providedParams
, expectedParams
);
2595 Register
* inplaceArgsDst
= callFrame
->registers() + argsOffset
;
2597 Register
* inplaceArgsEnd
= inplaceArgsDst
+ inplaceArgs
;
2598 Register
* inplaceArgsEnd2
= inplaceArgsDst
+ providedParams
;
2600 Register
* inplaceArgsSrc
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- expectedParams
;
2601 Register
* inplaceArgsSrc2
= inplaceArgsSrc
- providedParams
- 1 + inplaceArgs
;
2603 // First step is to copy the "expected" parameters from their normal location relative to the callframe
2604 while (inplaceArgsDst
< inplaceArgsEnd
)
2605 *inplaceArgsDst
++ = *inplaceArgsSrc
++;
2607 // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
2608 while (inplaceArgsDst
< inplaceArgsEnd2
)
2609 *inplaceArgsDst
++ = *inplaceArgsSrc2
++;
2611 } else if (!arguments
.isUndefinedOrNull()) {
2612 if (!arguments
.isObject()) {
2613 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "Function.prototype.apply", arguments
);
2614 VM_THROW_EXCEPTION();
2616 if (asObject(arguments
)->classInfo() == &Arguments::s_info
) {
2617 Arguments
* argsObject
= asArguments(arguments
);
2618 argCount
= argsObject
->numProvidedArguments(callFrame
);
2619 argCount
= min(argCount
, static_cast<uint32_t>(Arguments::MaxArguments
));
2620 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2621 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2622 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2623 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2624 VM_THROW_EXCEPTION();
2626 argsObject
->copyToRegisters(callFrame
, callFrame
->registers() + argsOffset
, argCount
);
2627 } else if (isJSArray(&callFrame
->globalData(), arguments
)) {
2628 JSArray
* array
= asArray(arguments
);
2629 argCount
= array
->length();
2630 argCount
= min(argCount
, static_cast<uint32_t>(Arguments::MaxArguments
));
2631 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2632 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2633 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2634 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2635 VM_THROW_EXCEPTION();
2637 array
->copyToRegisters(callFrame
, callFrame
->registers() + argsOffset
, argCount
);
2638 } else if (asObject(arguments
)->inherits(&JSArray::s_info
)) {
2639 JSObject
* argObject
= asObject(arguments
);
2640 argCount
= argObject
->get(callFrame
, callFrame
->propertyNames().length
).toUInt32(callFrame
);
2641 argCount
= min(argCount
, static_cast<uint32_t>(Arguments::MaxArguments
));
2642 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2643 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2644 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2645 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2646 VM_THROW_EXCEPTION();
2648 Register
* argsBuffer
= callFrame
->registers() + argsOffset
;
2649 for (unsigned i
= 0; i
< argCount
; ++i
) {
2650 argsBuffer
[i
] = asObject(arguments
)->get(callFrame
, i
);
2651 CHECK_FOR_EXCEPTION();
2654 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "Function.prototype.apply", arguments
);
2655 VM_THROW_EXCEPTION();
2659 return argCount
+ 1;
2662 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_negate
)
2664 STUB_INIT_STACK_FRAME(stackFrame
);
2666 JSValue src
= stackFrame
.args
[0].jsValue();
2669 if (src
.getNumber(v
))
2670 return JSValue::encode(jsNumber(-v
));
2672 CallFrame
* callFrame
= stackFrame
.callFrame
;
2673 JSValue result
= jsNumber(-src
.toNumber(callFrame
));
2674 CHECK_FOR_EXCEPTION_AT_END();
2675 return JSValue::encode(result
);
2678 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_base
)
2680 STUB_INIT_STACK_FRAME(stackFrame
);
2682 return JSValue::encode(JSC::resolveBase(stackFrame
.callFrame
, stackFrame
.args
[0].identifier(), stackFrame
.callFrame
->scopeChain(), false));
2685 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_base_strict_put
)
2687 STUB_INIT_STACK_FRAME(stackFrame
);
2688 JSValue base
= JSC::resolveBase(stackFrame
.callFrame
, stackFrame
.args
[0].identifier(), stackFrame
.callFrame
->scopeChain(), true);
2690 stackFrame
.globalData
->exception
= createErrorForInvalidGlobalAssignment(stackFrame
.callFrame
, stackFrame
.args
[0].identifier().ustring());
2691 VM_THROW_EXCEPTION();
2693 return JSValue::encode(base
);
2696 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_ensure_property_exists
)
2698 STUB_INIT_STACK_FRAME(stackFrame
);
2699 JSValue base
= stackFrame
.callFrame
->r(stackFrame
.args
[0].int32()).jsValue();
2700 JSObject
* object
= asObject(base
);
2701 PropertySlot
slot(object
);
2702 ASSERT(stackFrame
.callFrame
->codeBlock()->isStrictMode());
2703 if (!object
->getPropertySlot(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
)) {
2704 stackFrame
.globalData
->exception
= createErrorForInvalidGlobalAssignment(stackFrame
.callFrame
, stackFrame
.args
[1].identifier().ustring());
2705 VM_THROW_EXCEPTION();
2708 return JSValue::encode(base
);
2711 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_skip
)
2713 STUB_INIT_STACK_FRAME(stackFrame
);
2715 CallFrame
* callFrame
= stackFrame
.callFrame
;
2716 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
2718 int skip
= stackFrame
.args
[1].int32();
2720 ScopeChainIterator iter
= scopeChain
->begin();
2721 ScopeChainIterator end
= scopeChain
->end();
2722 ASSERT(iter
!= end
);
2723 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2724 bool checkTopLevel
= codeBlock
->codeType() == FunctionCode
&& codeBlock
->needsFullScopeChain();
2725 ASSERT(skip
|| !checkTopLevel
);
2726 if (checkTopLevel
&& skip
--) {
2727 if (callFrame
->uncheckedR(codeBlock
->activationRegister()).jsValue())
2732 ASSERT(iter
!= end
);
2734 Identifier
& ident
= stackFrame
.args
[0].identifier();
2736 JSObject
* o
= iter
->get();
2737 PropertySlot
slot(o
);
2738 if (o
->getPropertySlot(callFrame
, ident
, slot
)) {
2739 JSValue result
= slot
.getValue(callFrame
, ident
);
2740 CHECK_FOR_EXCEPTION_AT_END();
2741 return JSValue::encode(result
);
2743 } while (++iter
!= end
);
2745 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
);
2746 VM_THROW_EXCEPTION();
2749 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_global
)
2751 STUB_INIT_STACK_FRAME(stackFrame
);
2753 CallFrame
* callFrame
= stackFrame
.callFrame
;
2754 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2755 JSGlobalObject
* globalObject
= codeBlock
->globalObject();
2756 Identifier
& ident
= stackFrame
.args
[0].identifier();
2757 unsigned globalResolveInfoIndex
= stackFrame
.args
[1].int32();
2758 ASSERT(globalObject
->isGlobalObject());
2760 PropertySlot
slot(globalObject
);
2761 if (globalObject
->getPropertySlot(callFrame
, ident
, slot
)) {
2762 JSValue result
= slot
.getValue(callFrame
, ident
);
2763 if (slot
.isCacheableValue() && !globalObject
->structure()->isUncacheableDictionary() && slot
.slotBase() == globalObject
) {
2764 GlobalResolveInfo
& globalResolveInfo
= codeBlock
->globalResolveInfo(globalResolveInfoIndex
);
2765 globalResolveInfo
.structure
.set(callFrame
->globalData(), codeBlock
->ownerExecutable(), globalObject
->structure());
2766 globalResolveInfo
.offset
= slot
.cachedOffset();
2767 return JSValue::encode(result
);
2770 CHECK_FOR_EXCEPTION_AT_END();
2771 return JSValue::encode(result
);
2774 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
);
2775 VM_THROW_EXCEPTION();
2778 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_div
)
2780 STUB_INIT_STACK_FRAME(stackFrame
);
2782 JSValue src1
= stackFrame
.args
[0].jsValue();
2783 JSValue src2
= stackFrame
.args
[1].jsValue();
2787 if (src1
.getNumber(left
) && src2
.getNumber(right
))
2788 return JSValue::encode(jsNumber(left
/ right
));
2790 CallFrame
* callFrame
= stackFrame
.callFrame
;
2791 JSValue result
= jsNumber(src1
.toNumber(callFrame
) / src2
.toNumber(callFrame
));
2792 CHECK_FOR_EXCEPTION_AT_END();
2793 return JSValue::encode(result
);
2796 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_pre_dec
)
2798 STUB_INIT_STACK_FRAME(stackFrame
);
2800 JSValue v
= stackFrame
.args
[0].jsValue();
2802 CallFrame
* callFrame
= stackFrame
.callFrame
;
2803 JSValue result
= jsNumber(v
.toNumber(callFrame
) - 1);
2804 CHECK_FOR_EXCEPTION_AT_END();
2805 return JSValue::encode(result
);
2808 DEFINE_STUB_FUNCTION(int, op_jless
)
2810 STUB_INIT_STACK_FRAME(stackFrame
);
2812 JSValue src1
= stackFrame
.args
[0].jsValue();
2813 JSValue src2
= stackFrame
.args
[1].jsValue();
2814 CallFrame
* callFrame
= stackFrame
.callFrame
;
2816 bool result
= jsLess(callFrame
, src1
, src2
);
2817 CHECK_FOR_EXCEPTION_AT_END();
2821 DEFINE_STUB_FUNCTION(int, op_jlesseq
)
2823 STUB_INIT_STACK_FRAME(stackFrame
);
2825 JSValue src1
= stackFrame
.args
[0].jsValue();
2826 JSValue src2
= stackFrame
.args
[1].jsValue();
2827 CallFrame
* callFrame
= stackFrame
.callFrame
;
2829 bool result
= jsLessEq(callFrame
, src1
, src2
);
2830 CHECK_FOR_EXCEPTION_AT_END();
2834 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_not
)
2836 STUB_INIT_STACK_FRAME(stackFrame
);
2838 JSValue src
= stackFrame
.args
[0].jsValue();
2840 CallFrame
* callFrame
= stackFrame
.callFrame
;
2842 JSValue result
= jsBoolean(!src
.toBoolean(callFrame
));
2843 CHECK_FOR_EXCEPTION_AT_END();
2844 return JSValue::encode(result
);
2847 DEFINE_STUB_FUNCTION(int, op_jtrue
)
2849 STUB_INIT_STACK_FRAME(stackFrame
);
2851 JSValue src1
= stackFrame
.args
[0].jsValue();
2853 CallFrame
* callFrame
= stackFrame
.callFrame
;
2855 bool result
= src1
.toBoolean(callFrame
);
2856 CHECK_FOR_EXCEPTION_AT_END();
2860 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_post_inc
)
2862 STUB_INIT_STACK_FRAME(stackFrame
);
2864 JSValue v
= stackFrame
.args
[0].jsValue();
2866 CallFrame
* callFrame
= stackFrame
.callFrame
;
2868 JSValue number
= v
.toJSNumber(callFrame
);
2869 CHECK_FOR_EXCEPTION_AT_END();
2871 callFrame
->registers()[stackFrame
.args
[1].int32()] = jsNumber(number
.uncheckedGetNumber() + 1);
2872 return JSValue::encode(number
);
2875 DEFINE_STUB_FUNCTION(int, op_eq
)
2877 STUB_INIT_STACK_FRAME(stackFrame
);
2879 JSValue src1
= stackFrame
.args
[0].jsValue();
2880 JSValue src2
= stackFrame
.args
[1].jsValue();
2882 #if USE(JSVALUE32_64)
2884 if (src2
.isUndefined()) {
2885 return src1
.isNull() ||
2886 (src1
.isCell() && src1
.asCell()->structure()->typeInfo().masqueradesAsUndefined())
2887 || src1
.isUndefined();
2890 if (src2
.isNull()) {
2891 return src1
.isUndefined() ||
2892 (src1
.isCell() && src1
.asCell()->structure()->typeInfo().masqueradesAsUndefined())
2896 if (src1
.isInt32()) {
2897 if (src2
.isDouble())
2898 return src1
.asInt32() == src2
.asDouble();
2899 double d
= src2
.toNumber(stackFrame
.callFrame
);
2900 CHECK_FOR_EXCEPTION();
2901 return src1
.asInt32() == d
;
2904 if (src1
.isDouble()) {
2906 return src1
.asDouble() == src2
.asInt32();
2907 double d
= src2
.toNumber(stackFrame
.callFrame
);
2908 CHECK_FOR_EXCEPTION();
2909 return src1
.asDouble() == d
;
2912 if (src1
.isTrue()) {
2915 double d
= src2
.toNumber(stackFrame
.callFrame
);
2916 CHECK_FOR_EXCEPTION();
2920 if (src1
.isFalse()) {
2923 double d
= src2
.toNumber(stackFrame
.callFrame
);
2924 CHECK_FOR_EXCEPTION();
2928 if (src1
.isUndefined())
2929 return src2
.isCell() && src2
.asCell()->structure()->typeInfo().masqueradesAsUndefined();
2932 return src2
.isCell() && src2
.asCell()->structure()->typeInfo().masqueradesAsUndefined();
2934 JSCell
* cell1
= src1
.asCell();
2936 if (cell1
->isString()) {
2938 return jsToNumber(static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
)) == src2
.asInt32();
2940 if (src2
.isDouble())
2941 return jsToNumber(static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
)) == src2
.asDouble();
2944 return jsToNumber(static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
)) == 1.0;
2947 return jsToNumber(static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
)) == 0.0;
2949 JSCell
* cell2
= src2
.asCell();
2950 if (cell2
->isString())
2951 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
) == static_cast<JSString
*>(cell2
)->value(stackFrame
.callFrame
);
2953 src2
= asObject(cell2
)->toPrimitive(stackFrame
.callFrame
);
2954 CHECK_FOR_EXCEPTION();
2958 if (src2
.isObject())
2959 return asObject(cell1
) == asObject(src2
);
2960 src1
= asObject(cell1
)->toPrimitive(stackFrame
.callFrame
);
2961 CHECK_FOR_EXCEPTION();
2964 #else // USE(JSVALUE32_64)
2965 CallFrame
* callFrame
= stackFrame
.callFrame
;
2967 bool result
= JSValue::equalSlowCaseInline(callFrame
, src1
, src2
);
2968 CHECK_FOR_EXCEPTION_AT_END();
2970 #endif // USE(JSVALUE32_64)
2973 DEFINE_STUB_FUNCTION(int, op_eq_strings
)
2975 #if USE(JSVALUE32_64)
2976 STUB_INIT_STACK_FRAME(stackFrame
);
2978 JSString
* string1
= stackFrame
.args
[0].jsString();
2979 JSString
* string2
= stackFrame
.args
[1].jsString();
2981 ASSERT(string1
->isString());
2982 ASSERT(string2
->isString());
2983 return string1
->value(stackFrame
.callFrame
) == string2
->value(stackFrame
.callFrame
);
2986 ASSERT_NOT_REACHED();
2991 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_lshift
)
2993 STUB_INIT_STACK_FRAME(stackFrame
);
2995 JSValue val
= stackFrame
.args
[0].jsValue();
2996 JSValue shift
= stackFrame
.args
[1].jsValue();
2998 CallFrame
* callFrame
= stackFrame
.callFrame
;
2999 JSValue result
= jsNumber((val
.toInt32(callFrame
)) << (shift
.toUInt32(callFrame
) & 0x1f));
3000 CHECK_FOR_EXCEPTION_AT_END();
3001 return JSValue::encode(result
);
3004 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitand
)
3006 STUB_INIT_STACK_FRAME(stackFrame
);
3008 JSValue src1
= stackFrame
.args
[0].jsValue();
3009 JSValue src2
= stackFrame
.args
[1].jsValue();
3011 ASSERT(!src1
.isInt32() || !src2
.isInt32());
3012 CallFrame
* callFrame
= stackFrame
.callFrame
;
3013 JSValue result
= jsNumber(src1
.toInt32(callFrame
) & src2
.toInt32(callFrame
));
3014 CHECK_FOR_EXCEPTION_AT_END();
3015 return JSValue::encode(result
);
3018 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_rshift
)
3020 STUB_INIT_STACK_FRAME(stackFrame
);
3022 JSValue val
= stackFrame
.args
[0].jsValue();
3023 JSValue shift
= stackFrame
.args
[1].jsValue();
3025 CallFrame
* callFrame
= stackFrame
.callFrame
;
3026 JSValue result
= jsNumber((val
.toInt32(callFrame
)) >> (shift
.toUInt32(callFrame
) & 0x1f));
3028 CHECK_FOR_EXCEPTION_AT_END();
3029 return JSValue::encode(result
);
3032 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitnot
)
3034 STUB_INIT_STACK_FRAME(stackFrame
);
3036 JSValue src
= stackFrame
.args
[0].jsValue();
3038 ASSERT(!src
.isInt32());
3039 CallFrame
* callFrame
= stackFrame
.callFrame
;
3040 JSValue result
= jsNumber(~src
.toInt32(callFrame
));
3041 CHECK_FOR_EXCEPTION_AT_END();
3042 return JSValue::encode(result
);
3045 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_with_base
)
3047 STUB_INIT_STACK_FRAME(stackFrame
);
3049 CallFrame
* callFrame
= stackFrame
.callFrame
;
3050 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
3052 ScopeChainIterator iter
= scopeChain
->begin();
3053 ScopeChainIterator end
= scopeChain
->end();
3055 // FIXME: add scopeDepthIsZero optimization
3057 ASSERT(iter
!= end
);
3059 Identifier
& ident
= stackFrame
.args
[0].identifier();
3063 PropertySlot
slot(base
);
3064 if (base
->getPropertySlot(callFrame
, ident
, slot
)) {
3065 JSValue result
= slot
.getValue(callFrame
, ident
);
3066 CHECK_FOR_EXCEPTION_AT_END();
3068 callFrame
->registers()[stackFrame
.args
[1].int32()] = JSValue(base
);
3069 return JSValue::encode(result
);
3072 } while (iter
!= end
);
3074 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
);
3075 VM_THROW_EXCEPTION_AT_END();
3076 return JSValue::encode(JSValue());
3079 DEFINE_STUB_FUNCTION(JSObject
*, op_new_func_exp
)
3081 STUB_INIT_STACK_FRAME(stackFrame
);
3082 CallFrame
* callFrame
= stackFrame
.callFrame
;
3084 FunctionExecutable
* function
= stackFrame
.args
[0].function();
3085 JSFunction
* func
= function
->make(callFrame
, callFrame
->scopeChain());
3086 ASSERT(callFrame
->codeBlock()->codeType() != FunctionCode
|| !callFrame
->codeBlock()->needsFullScopeChain() || callFrame
->uncheckedR(callFrame
->codeBlock()->activationRegister()).jsValue());
3089 The Identifier in a FunctionExpression can be referenced from inside
3090 the FunctionExpression's FunctionBody to allow the function to call
3091 itself recursively. However, unlike in a FunctionDeclaration, the
3092 Identifier in a FunctionExpression cannot be referenced from and
3093 does not affect the scope enclosing the FunctionExpression.
3095 if (!function
->name().isNull()) {
3096 JSStaticScopeObject
* functionScopeObject
= new (callFrame
) JSStaticScopeObject(callFrame
, function
->name(), func
, ReadOnly
| DontDelete
);
3097 func
->setScope(callFrame
->globalData(), func
->scope()->push(functionScopeObject
));
3103 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_mod
)
3105 STUB_INIT_STACK_FRAME(stackFrame
);
3107 JSValue dividendValue
= stackFrame
.args
[0].jsValue();
3108 JSValue divisorValue
= stackFrame
.args
[1].jsValue();
3110 CallFrame
* callFrame
= stackFrame
.callFrame
;
3111 double d
= dividendValue
.toNumber(callFrame
);
3112 JSValue result
= jsNumber(fmod(d
, divisorValue
.toNumber(callFrame
)));
3113 CHECK_FOR_EXCEPTION_AT_END();
3114 return JSValue::encode(result
);
3117 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_less
)
3119 STUB_INIT_STACK_FRAME(stackFrame
);
3121 CallFrame
* callFrame
= stackFrame
.callFrame
;
3122 JSValue result
= jsBoolean(jsLess(callFrame
, stackFrame
.args
[0].jsValue(), stackFrame
.args
[1].jsValue()));
3123 CHECK_FOR_EXCEPTION_AT_END();
3124 return JSValue::encode(result
);
3127 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_post_dec
)
3129 STUB_INIT_STACK_FRAME(stackFrame
);
3131 JSValue v
= stackFrame
.args
[0].jsValue();
3133 CallFrame
* callFrame
= stackFrame
.callFrame
;
3135 JSValue number
= v
.toJSNumber(callFrame
);
3136 CHECK_FOR_EXCEPTION_AT_END();
3138 callFrame
->registers()[stackFrame
.args
[1].int32()] = jsNumber(number
.uncheckedGetNumber() - 1);
3139 return JSValue::encode(number
);
3142 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_urshift
)
3144 STUB_INIT_STACK_FRAME(stackFrame
);
3146 JSValue val
= stackFrame
.args
[0].jsValue();
3147 JSValue shift
= stackFrame
.args
[1].jsValue();
3149 CallFrame
* callFrame
= stackFrame
.callFrame
;
3150 JSValue result
= jsNumber((val
.toUInt32(callFrame
)) >> (shift
.toUInt32(callFrame
) & 0x1f));
3151 CHECK_FOR_EXCEPTION_AT_END();
3152 return JSValue::encode(result
);
3155 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitxor
)
3157 STUB_INIT_STACK_FRAME(stackFrame
);
3159 JSValue src1
= stackFrame
.args
[0].jsValue();
3160 JSValue src2
= stackFrame
.args
[1].jsValue();
3162 CallFrame
* callFrame
= stackFrame
.callFrame
;
3164 JSValue result
= jsNumber(src1
.toInt32(callFrame
) ^ src2
.toInt32(callFrame
));
3165 CHECK_FOR_EXCEPTION_AT_END();
3166 return JSValue::encode(result
);
3169 DEFINE_STUB_FUNCTION(JSObject
*, op_new_regexp
)
3171 STUB_INIT_STACK_FRAME(stackFrame
);
3173 CallFrame
* callFrame
= stackFrame
.callFrame
;
3175 RegExp
* regExp
= stackFrame
.args
[0].regExp();
3176 if (!regExp
->isValid()) {
3177 stackFrame
.globalData
->exception
= createSyntaxError(callFrame
, "Invalid flags supplied to RegExp constructor.");
3178 VM_THROW_EXCEPTION();
3181 return new (stackFrame
.globalData
) RegExpObject(stackFrame
.callFrame
->lexicalGlobalObject(), stackFrame
.callFrame
->lexicalGlobalObject()->regExpStructure(), regExp
);
3184 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitor
)
3186 STUB_INIT_STACK_FRAME(stackFrame
);
3188 JSValue src1
= stackFrame
.args
[0].jsValue();
3189 JSValue src2
= stackFrame
.args
[1].jsValue();
3191 CallFrame
* callFrame
= stackFrame
.callFrame
;
3193 JSValue result
= jsNumber(src1
.toInt32(callFrame
) | src2
.toInt32(callFrame
));
3194 CHECK_FOR_EXCEPTION_AT_END();
3195 return JSValue::encode(result
);
3198 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_call_eval
)
3200 STUB_INIT_STACK_FRAME(stackFrame
);
3201 ASSERT(stackFrame
.callFrame
->codeBlock()->codeType() != FunctionCode
|| !stackFrame
.callFrame
->codeBlock()->needsFullScopeChain() || stackFrame
.callFrame
->uncheckedR(stackFrame
.callFrame
->codeBlock()->activationRegister()).jsValue());
3203 CallFrame
* callFrame
= stackFrame
.callFrame
;
3204 RegisterFile
* registerFile
= stackFrame
.registerFile
;
3206 Interpreter
* interpreter
= stackFrame
.globalData
->interpreter
;
3208 JSValue funcVal
= stackFrame
.args
[0].jsValue();
3209 int registerOffset
= stackFrame
.args
[1].int32();
3210 int argCount
= stackFrame
.args
[2].int32();
3212 Register
* newCallFrame
= callFrame
->registers() + registerOffset
;
3213 Register
* argv
= newCallFrame
- RegisterFile::CallFrameHeaderSize
- argCount
;
3214 JSValue baseValue
= argv
[0].jsValue();
3215 JSGlobalObject
* globalObject
= callFrame
->scopeChain()->globalObject
.get();
3217 if (baseValue
== globalObject
&& funcVal
== globalObject
->evalFunction()) {
3218 JSValue result
= interpreter
->callEval(callFrame
, registerFile
, argv
, argCount
, registerOffset
);
3219 CHECK_FOR_EXCEPTION_AT_END();
3220 return JSValue::encode(result
);
3223 return JSValue::encode(JSValue());
3226 DEFINE_STUB_FUNCTION(void*, op_throw
)
3228 STUB_INIT_STACK_FRAME(stackFrame
);
3229 ExceptionHandler handler
= jitThrow(stackFrame
.globalData
, stackFrame
.callFrame
, stackFrame
.args
[0].jsValue(), STUB_RETURN_ADDRESS
);
3230 STUB_SET_RETURN_ADDRESS(handler
.catchRoutine
);
3231 return handler
.callFrame
;
3234 DEFINE_STUB_FUNCTION(JSPropertyNameIterator
*, op_get_pnames
)
3236 STUB_INIT_STACK_FRAME(stackFrame
);
3238 CallFrame
* callFrame
= stackFrame
.callFrame
;
3239 JSObject
* o
= stackFrame
.args
[0].jsObject();
3240 Structure
* structure
= o
->structure();
3241 JSPropertyNameIterator
* jsPropertyNameIterator
= structure
->enumerationCache();
3242 if (!jsPropertyNameIterator
|| jsPropertyNameIterator
->cachedPrototypeChain() != structure
->prototypeChain(callFrame
))
3243 jsPropertyNameIterator
= JSPropertyNameIterator::create(callFrame
, o
);
3244 return jsPropertyNameIterator
;
3247 DEFINE_STUB_FUNCTION(int, has_property
)
3249 STUB_INIT_STACK_FRAME(stackFrame
);
3251 JSObject
* base
= stackFrame
.args
[0].jsObject();
3252 JSString
* property
= stackFrame
.args
[1].jsString();
3253 int result
= base
->hasProperty(stackFrame
.callFrame
, Identifier(stackFrame
.callFrame
, property
->value(stackFrame
.callFrame
)));
3254 CHECK_FOR_EXCEPTION_AT_END();
3258 DEFINE_STUB_FUNCTION(JSObject
*, op_push_scope
)
3260 STUB_INIT_STACK_FRAME(stackFrame
);
3262 JSObject
* o
= stackFrame
.args
[0].jsValue().toObject(stackFrame
.callFrame
);
3263 CHECK_FOR_EXCEPTION();
3264 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->push(o
));
3268 DEFINE_STUB_FUNCTION(void, op_pop_scope
)
3270 STUB_INIT_STACK_FRAME(stackFrame
);
3272 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->pop());
3275 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_typeof
)
3277 STUB_INIT_STACK_FRAME(stackFrame
);
3279 return JSValue::encode(jsTypeStringForValue(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue()));
3282 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_undefined
)
3284 STUB_INIT_STACK_FRAME(stackFrame
);
3286 JSValue v
= stackFrame
.args
[0].jsValue();
3287 return JSValue::encode(jsBoolean(v
.isCell() ? v
.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v
.isUndefined()));
3290 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_boolean
)
3292 STUB_INIT_STACK_FRAME(stackFrame
);
3294 return JSValue::encode(jsBoolean(stackFrame
.args
[0].jsValue().isBoolean()));
3297 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_number
)
3299 STUB_INIT_STACK_FRAME(stackFrame
);
3301 return JSValue::encode(jsBoolean(stackFrame
.args
[0].jsValue().isNumber()));
3304 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_string
)
3306 STUB_INIT_STACK_FRAME(stackFrame
);
3308 return JSValue::encode(jsBoolean(isJSString(stackFrame
.globalData
, stackFrame
.args
[0].jsValue())));
3311 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_object
)
3313 STUB_INIT_STACK_FRAME(stackFrame
);
3315 return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame
.args
[0].jsValue())));
3318 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_function
)
3320 STUB_INIT_STACK_FRAME(stackFrame
);
3322 return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame
.args
[0].jsValue())));
3325 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_stricteq
)
3327 STUB_INIT_STACK_FRAME(stackFrame
);
3329 JSValue src1
= stackFrame
.args
[0].jsValue();
3330 JSValue src2
= stackFrame
.args
[1].jsValue();
3332 bool result
= JSValue::strictEqual(stackFrame
.callFrame
, src1
, src2
);
3333 CHECK_FOR_EXCEPTION_AT_END();
3334 return JSValue::encode(jsBoolean(result
));
3337 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_to_primitive
)
3339 STUB_INIT_STACK_FRAME(stackFrame
);
3341 return JSValue::encode(stackFrame
.args
[0].jsValue().toPrimitive(stackFrame
.callFrame
));
3344 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_strcat
)
3346 STUB_INIT_STACK_FRAME(stackFrame
);
3348 JSValue result
= jsString(stackFrame
.callFrame
, &stackFrame
.callFrame
->registers()[stackFrame
.args
[0].int32()], stackFrame
.args
[1].int32());
3349 CHECK_FOR_EXCEPTION_AT_END();
3350 return JSValue::encode(result
);
3353 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_nstricteq
)
3355 STUB_INIT_STACK_FRAME(stackFrame
);
3357 JSValue src1
= stackFrame
.args
[0].jsValue();
3358 JSValue src2
= stackFrame
.args
[1].jsValue();
3360 bool result
= !JSValue::strictEqual(stackFrame
.callFrame
, src1
, src2
);
3361 CHECK_FOR_EXCEPTION_AT_END();
3362 return JSValue::encode(jsBoolean(result
));
3365 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_to_jsnumber
)
3367 STUB_INIT_STACK_FRAME(stackFrame
);
3369 JSValue src
= stackFrame
.args
[0].jsValue();
3370 CallFrame
* callFrame
= stackFrame
.callFrame
;
3372 JSValue result
= src
.toJSNumber(callFrame
);
3373 CHECK_FOR_EXCEPTION_AT_END();
3374 return JSValue::encode(result
);
3377 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_in
)
3379 STUB_INIT_STACK_FRAME(stackFrame
);
3381 CallFrame
* callFrame
= stackFrame
.callFrame
;
3382 JSValue baseVal
= stackFrame
.args
[1].jsValue();
3384 if (!baseVal
.isObject()) {
3385 stackFrame
.globalData
->exception
= createInvalidParamError(stackFrame
.callFrame
, "in", baseVal
);
3386 VM_THROW_EXCEPTION();
3389 JSValue propName
= stackFrame
.args
[0].jsValue();
3390 JSObject
* baseObj
= asObject(baseVal
);
3393 if (propName
.getUInt32(i
))
3394 return JSValue::encode(jsBoolean(baseObj
->hasProperty(callFrame
, i
)));
3396 Identifier
property(callFrame
, propName
.toString(callFrame
));
3397 CHECK_FOR_EXCEPTION();
3398 return JSValue::encode(jsBoolean(baseObj
->hasProperty(callFrame
, property
)));
3401 DEFINE_STUB_FUNCTION(JSObject
*, op_push_new_scope
)
3403 STUB_INIT_STACK_FRAME(stackFrame
);
3405 JSObject
* scope
= new (stackFrame
.globalData
) JSStaticScopeObject(stackFrame
.callFrame
, stackFrame
.args
[0].identifier(), stackFrame
.args
[1].jsValue(), DontDelete
);
3407 CallFrame
* callFrame
= stackFrame
.callFrame
;
3408 callFrame
->setScopeChain(callFrame
->scopeChain()->push(scope
));
3412 DEFINE_STUB_FUNCTION(void, op_jmp_scopes
)
3414 STUB_INIT_STACK_FRAME(stackFrame
);
3416 unsigned count
= stackFrame
.args
[0].int32();
3417 CallFrame
* callFrame
= stackFrame
.callFrame
;
3419 ScopeChainNode
* tmp
= callFrame
->scopeChain();
3422 callFrame
->setScopeChain(tmp
);
3425 DEFINE_STUB_FUNCTION(void, op_put_by_index
)
3427 STUB_INIT_STACK_FRAME(stackFrame
);
3429 CallFrame
* callFrame
= stackFrame
.callFrame
;
3430 unsigned property
= stackFrame
.args
[1].int32();
3432 stackFrame
.args
[0].jsValue().put(callFrame
, property
, stackFrame
.args
[2].jsValue());
3435 DEFINE_STUB_FUNCTION(void*, op_switch_imm
)
3437 STUB_INIT_STACK_FRAME(stackFrame
);
3439 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
3440 unsigned tableIndex
= stackFrame
.args
[1].int32();
3441 CallFrame
* callFrame
= stackFrame
.callFrame
;
3442 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3444 if (scrutinee
.isInt32())
3445 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiForValue(scrutinee
.asInt32()).executableAddress();
3449 if (scrutinee
.getNumber(value
) && ((intValue
= static_cast<int32_t>(value
)) == value
))
3450 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiForValue(intValue
).executableAddress();
3452 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
3456 DEFINE_STUB_FUNCTION(void*, op_switch_char
)
3458 STUB_INIT_STACK_FRAME(stackFrame
);
3460 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
3461 unsigned tableIndex
= stackFrame
.args
[1].int32();
3462 CallFrame
* callFrame
= stackFrame
.callFrame
;
3463 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3465 void* result
= codeBlock
->characterSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
3467 if (scrutinee
.isString()) {
3468 StringImpl
* value
= asString(scrutinee
)->value(callFrame
).impl();
3469 if (value
->length() == 1)
3470 result
= codeBlock
->characterSwitchJumpTable(tableIndex
).ctiForValue(value
->characters()[0]).executableAddress();
3473 CHECK_FOR_EXCEPTION_AT_END();
3477 DEFINE_STUB_FUNCTION(void*, op_switch_string
)
3479 STUB_INIT_STACK_FRAME(stackFrame
);
3481 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
3482 unsigned tableIndex
= stackFrame
.args
[1].int32();
3483 CallFrame
* callFrame
= stackFrame
.callFrame
;
3484 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3486 void* result
= codeBlock
->stringSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
3488 if (scrutinee
.isString()) {
3489 StringImpl
* value
= asString(scrutinee
)->value(callFrame
).impl();
3490 result
= codeBlock
->stringSwitchJumpTable(tableIndex
).ctiForValue(value
).executableAddress();
3493 CHECK_FOR_EXCEPTION_AT_END();
3497 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_del_by_val
)
3499 STUB_INIT_STACK_FRAME(stackFrame
);
3501 CallFrame
* callFrame
= stackFrame
.callFrame
;
3503 JSValue baseValue
= stackFrame
.args
[0].jsValue();
3504 JSObject
* baseObj
= baseValue
.toObject(callFrame
); // may throw
3506 JSValue subscript
= stackFrame
.args
[1].jsValue();
3509 if (subscript
.getUInt32(i
))
3510 result
= baseObj
->deleteProperty(callFrame
, i
);
3512 CHECK_FOR_EXCEPTION();
3513 Identifier
property(callFrame
, subscript
.toString(callFrame
));
3514 CHECK_FOR_EXCEPTION();
3515 result
= baseObj
->deleteProperty(callFrame
, property
);
3518 if (!result
&& callFrame
->codeBlock()->isStrictMode())
3519 stackFrame
.globalData
->exception
= createTypeError(stackFrame
.callFrame
, "Unable to delete property.");
3521 CHECK_FOR_EXCEPTION_AT_END();
3522 return JSValue::encode(jsBoolean(result
));
3525 DEFINE_STUB_FUNCTION(void, op_put_getter
)
3527 STUB_INIT_STACK_FRAME(stackFrame
);
3529 CallFrame
* callFrame
= stackFrame
.callFrame
;
3531 ASSERT(stackFrame
.args
[0].jsValue().isObject());
3532 JSObject
* baseObj
= asObject(stackFrame
.args
[0].jsValue());
3533 ASSERT(stackFrame
.args
[2].jsValue().isObject());
3534 baseObj
->defineGetter(callFrame
, stackFrame
.args
[1].identifier(), asObject(stackFrame
.args
[2].jsValue()));
3537 DEFINE_STUB_FUNCTION(void, op_put_setter
)
3539 STUB_INIT_STACK_FRAME(stackFrame
);
3541 CallFrame
* callFrame
= stackFrame
.callFrame
;
3543 ASSERT(stackFrame
.args
[0].jsValue().isObject());
3544 JSObject
* baseObj
= asObject(stackFrame
.args
[0].jsValue());
3545 ASSERT(stackFrame
.args
[2].jsValue().isObject());
3546 baseObj
->defineSetter(callFrame
, stackFrame
.args
[1].identifier(), asObject(stackFrame
.args
[2].jsValue()));
3549 DEFINE_STUB_FUNCTION(void, op_throw_reference_error
)
3551 STUB_INIT_STACK_FRAME(stackFrame
);
3553 CallFrame
* callFrame
= stackFrame
.callFrame
;
3554 UString message
= stackFrame
.args
[0].jsValue().toString(callFrame
);
3555 stackFrame
.globalData
->exception
= createReferenceError(callFrame
, message
);
3556 VM_THROW_EXCEPTION_AT_END();
3559 DEFINE_STUB_FUNCTION(void, op_debug
)
3561 STUB_INIT_STACK_FRAME(stackFrame
);
3563 CallFrame
* callFrame
= stackFrame
.callFrame
;
3565 int debugHookID
= stackFrame
.args
[0].int32();
3566 int firstLine
= stackFrame
.args
[1].int32();
3567 int lastLine
= stackFrame
.args
[2].int32();
3569 stackFrame
.globalData
->interpreter
->debug(callFrame
, static_cast<DebugHookID
>(debugHookID
), firstLine
, lastLine
);
3572 DEFINE_STUB_FUNCTION(void*, vm_throw
)
3574 STUB_INIT_STACK_FRAME(stackFrame
);
3575 JSGlobalData
* globalData
= stackFrame
.globalData
;
3576 ExceptionHandler handler
= jitThrow(globalData
, stackFrame
.callFrame
, globalData
->exception
, globalData
->exceptionLocation
);
3577 STUB_SET_RETURN_ADDRESS(handler
.catchRoutine
);
3578 return handler
.callFrame
;
3581 DEFINE_STUB_FUNCTION(EncodedJSValue
, to_object
)
3583 STUB_INIT_STACK_FRAME(stackFrame
);
3585 CallFrame
* callFrame
= stackFrame
.callFrame
;
3586 return JSValue::encode(stackFrame
.args
[0].jsValue().toObject(callFrame
));
3589 MacroAssemblerCodePtr
JITThunks::ctiStub(JSGlobalData
* globalData
, ThunkGenerator generator
)
3591 std::pair
<CTIStubMap::iterator
, bool> entry
= m_ctiStubMap
.add(generator
, MacroAssemblerCodePtr());
3593 entry
.first
->second
= generator(globalData
, m_executablePool
.get());
3594 return entry
.first
->second
;
3597 NativeExecutable
* JITThunks::hostFunctionStub(JSGlobalData
* globalData
, NativeFunction function
)
3599 std::pair
<HostFunctionStubMap::iterator
, bool> entry
= m_hostFunctionStubMap
->add(function
, Weak
<NativeExecutable
>());
3600 if (!*entry
.first
->second
)
3601 entry
.first
->second
.set(*globalData
, NativeExecutable::create(*globalData
, JIT::compileCTINativeCall(globalData
, m_executablePool
, function
), function
, ctiNativeConstruct(), callHostFunctionAsConstructor
));
3602 return entry
.first
->second
.get();
3605 NativeExecutable
* JITThunks::hostFunctionStub(JSGlobalData
* globalData
, NativeFunction function
, ThunkGenerator generator
)
3607 std::pair
<HostFunctionStubMap::iterator
, bool> entry
= m_hostFunctionStubMap
->add(function
, Weak
<NativeExecutable
>());
3608 if (!*entry
.first
->second
) {
3609 MacroAssemblerCodePtr code
= globalData
->canUseJIT() ? generator(globalData
, m_executablePool
.get()) : MacroAssemblerCodePtr();
3610 entry
.first
->second
.set(*globalData
, NativeExecutable::create(*globalData
, code
, function
, ctiNativeConstruct(), callHostFunctionAsConstructor
));
3612 return entry
.first
->second
.get();
3615 void JITThunks::clearHostFunctionStubs()
3617 m_hostFunctionStubMap
.clear();
3622 #endif // ENABLE(JIT)