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. 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"
39 #include "Collector.h"
41 #include "ExceptionHelpers.h"
42 #include "GetterSetter.h"
43 #include "GlobalEvalFunction.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)
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) && CPU(X86_64)
83 #define SYMBOL_STRING_RELOCATION(name) #name "@plt"
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) && 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(RVCT)) && CPU(ARM_TRADITIONAL)
238 #define THUNK_RETURN_ADDRESS_OFFSET 64
239 #define PRESERVEDR4_OFFSET 68
241 #elif COMPILER(MSVC) && CPU(X86)
243 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
244 // need to change the assembly trampolines below to match.
245 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
246 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
247 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
248 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
252 __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
263 mov edi, [esp + 0x58];
274 __declspec(naked) void ctiVMThrowTrampoline()
288 __declspec(naked) void ctiOpThrowNotCaught()
301 #elif COMPILER(MSVC) && CPU(ARM_TRADITIONAL)
303 #define THUNK_RETURN_ADDRESS_OFFSET 64
304 #define PRESERVEDR4_OFFSET 68
305 // See DEFINE_STUB_FUNCTION for more information.
309 #define PRESERVED_GP_OFFSET 60
310 #define PRESERVED_S0_OFFSET 64
311 #define PRESERVED_S1_OFFSET 68
312 #define PRESERVED_S2_OFFSET 72
313 #define PRESERVED_RETURN_ADDRESS_OFFSET 76
314 #define THUNK_RETURN_ADDRESS_OFFSET 80
315 #define REGISTER_FILE_OFFSET 84
316 #define CALLFRAME_OFFSET 88
317 #define EXCEPTION_OFFSET 92
318 #define ENABLE_PROFILER_REFERENCE_OFFSET 96
319 #define GLOBAL_DATA_OFFSET 100
320 #define STACK_LENGTH 104
323 #error "JIT not supported on this platform."
326 #else // USE(JSVALUE32_64)
328 #if COMPILER(GCC) && CPU(X86)
330 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
331 // need to change the assembly trampolines below to match.
332 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
333 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline);
334 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
338 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
339 HIDE_SYMBOL(ctiTrampoline) "\n"
340 SYMBOL_STRING(ctiTrampoline) ":" "\n"
342 "movl %esp, %ebp" "\n"
346 "subl $0x1c, %esp" "\n"
347 "movl $512, %esi" "\n"
348 "movl 0x38(%esp), %edi" "\n"
349 "call *0x30(%esp)" "\n"
350 "addl $0x1c, %esp" "\n"
359 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
360 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
361 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
362 "movl %esp, %ecx" "\n"
363 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
368 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
369 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
370 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
371 "addl $0x1c, %esp" "\n"
379 #elif COMPILER(GCC) && CPU(X86_64)
381 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
382 // need to change the assembly trampolines below to match.
383 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
384 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline);
385 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
389 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
390 HIDE_SYMBOL(ctiTrampoline) "\n"
391 SYMBOL_STRING(ctiTrampoline) ":" "\n"
393 "movq %rsp, %rbp" "\n"
399 // Form the JIT stubs area
406 "subq $0x48, %rsp" "\n"
407 "movq $512, %r12" "\n"
408 "movq $0xFFFF000000000000, %r14" "\n"
409 "movq $0xFFFF000000000002, %r15" "\n"
410 "movq %rdx, %r13" "\n"
412 "addq $0x78, %rsp" "\n"
423 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
424 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
425 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
426 "movq %rsp, %rdi" "\n"
427 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
432 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
433 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
434 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
435 "addq $0x78, %rsp" "\n"
445 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
447 #define THUNK_RETURN_ADDRESS_OFFSET 0x20
448 #define PRESERVED_RETURN_ADDRESS_OFFSET 0x24
449 #define PRESERVED_R4_OFFSET 0x28
450 #define PRESERVED_R5_OFFSET 0x2C
451 #define PRESERVED_R6_OFFSET 0x30
452 #define REGISTER_FILE_OFFSET 0x34
453 #define CALLFRAME_OFFSET 0x38
454 #define EXCEPTION_OFFSET 0x3C
455 #define ENABLE_PROFILER_REFERENCE_OFFSET 0x40
457 #elif (COMPILER(GCC) || COMPILER(RVCT)) && CPU(ARM_TRADITIONAL)
459 #define THUNK_RETURN_ADDRESS_OFFSET 32
460 #define PRESERVEDR4_OFFSET 36
464 #define PRESERVED_GP_OFFSET 28
465 #define PRESERVED_S0_OFFSET 32
466 #define PRESERVED_S1_OFFSET 36
467 #define PRESERVED_S2_OFFSET 40
468 #define PRESERVED_RETURN_ADDRESS_OFFSET 44
469 #define THUNK_RETURN_ADDRESS_OFFSET 48
470 #define REGISTER_FILE_OFFSET 52
471 #define CALLFRAME_OFFSET 56
472 #define EXCEPTION_OFFSET 60
473 #define ENABLE_PROFILER_REFERENCE_OFFSET 64
474 #define GLOBAL_DATA_OFFSET 68
475 #define STACK_LENGTH 72
477 #elif COMPILER(MSVC) && CPU(X86)
479 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
480 // need to change the assembly trampolines below to match.
481 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
482 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline);
483 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
487 __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
498 mov edi, [esp + 0x38];
509 __declspec(naked) void ctiVMThrowTrampoline()
523 __declspec(naked) void ctiOpThrowNotCaught()
536 #elif COMPILER(MSVC) && CPU(ARM_TRADITIONAL)
538 #define THUNK_RETURN_ADDRESS_OFFSET 32
539 #define PRESERVEDR4_OFFSET 36
540 // See DEFINE_STUB_FUNCTION for more information.
543 #error "JIT not supported on this platform."
546 #endif // USE(JSVALUE32_64)
552 ".set noreorder" "\n"
555 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
556 ".ent " SYMBOL_STRING(ctiTrampoline) "\n"
557 SYMBOL_STRING(ctiTrampoline) ":" "\n"
558 "addiu $29,$29,-" STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
559 "sw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
560 "sw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
561 "sw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
562 "sw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
564 "sw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n"
566 "move $16,$6 # set callFrameRegister" "\n"
567 "li $17,512 # set timeoutCheckRegister" "\n"
568 "move $25,$4 # move executableAddress to t9" "\n"
569 "sw $5," STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "($29) # store registerFile to current stack" "\n"
570 "sw $6," STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "($29) # store callFrame to curent stack" "\n"
571 "sw $7," STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "($29) # store exception to current stack" "\n"
572 "lw $8," STRINGIZE_VALUE_OF(STACK_LENGTH + 16) "($29) # load enableProfilerReference from previous stack" "\n"
573 "lw $9," STRINGIZE_VALUE_OF(STACK_LENGTH + 20) "($29) # load globalData from previous stack" "\n"
574 "sw $8," STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "($29) # store enableProfilerReference to current stack" "\n"
576 "sw $9," STRINGIZE_VALUE_OF(GLOBAL_DATA_OFFSET) "($29) # store globalData to current stack" "\n"
577 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
578 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
579 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
580 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
582 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
585 ".end " SYMBOL_STRING(ctiTrampoline) "\n"
591 ".set noreorder" "\n"
594 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
595 ".ent " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
596 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
598 "lw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n"
600 "la $25," SYMBOL_STRING(cti_vm_throw) "\n"
602 "bal " SYMBOL_STRING(cti_vm_throw) "\n"
605 "jal " SYMBOL_STRING(cti_vm_throw) "\n"
608 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
609 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
610 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
611 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
613 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
616 ".end " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
622 ".set noreorder" "\n"
625 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
626 ".ent " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
627 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
628 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
629 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
630 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
631 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
633 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
636 ".end " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
640 #if COMPILER(GCC) && CPU(ARM_THUMB2)
645 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
646 HIDE_SYMBOL(ctiTrampoline) "\n"
648 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
649 SYMBOL_STRING(ctiTrampoline) ":" "\n"
650 "sub sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
651 "str lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
652 "str r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
653 "str r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
654 "str r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
655 "str r1, [sp, #" STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "]" "\n"
656 "str r2, [sp, #" STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "]" "\n"
657 "str r3, [sp, #" STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "]" "\n"
661 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
662 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
663 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
664 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
665 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
672 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
673 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
675 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
676 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
678 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
679 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
680 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
681 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
682 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
683 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
690 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
691 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
693 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
694 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
695 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
696 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
697 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
698 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
699 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
703 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
706 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
707 HIDE_SYMBOL(ctiTrampoline) "\n"
708 SYMBOL_STRING(ctiTrampoline) ":" "\n"
709 "stmdb sp!, {r1-r3}" "\n"
710 "stmdb sp!, {r4-r8, lr}" "\n"
711 "sub sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n"
714 // r0 contains the code
717 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n"
718 "ldmia sp!, {r4-r8, lr}" "\n"
719 "add sp, sp, #12" "\n"
724 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
725 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
726 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
728 "bl " SYMBOL_STRING(cti_vm_throw) "\n"
730 // Both has the same return sequence
731 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
732 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
733 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
734 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n"
735 "ldmia sp!, {r4-r8, lr}" "\n"
736 "add sp, sp, #12" "\n"
740 #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
742 __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
746 stmdb sp!, {r4-r8, lr}
747 sub sp, sp, # PRESERVEDR4_OFFSET
752 add sp, sp, # PRESERVEDR4_OFFSET
753 ldmia sp!, {r4-r8, lr}
758 __asm void ctiVMThrowTrampoline()
764 add sp, sp, # PRESERVEDR4_OFFSET
765 ldmia sp!, {r4-r8, lr}
770 __asm void ctiOpThrowNotCaught()
773 add sp, sp, # PRESERVEDR4_OFFSET
774 ldmia sp!, {r4-r8, lr}
780 #if ENABLE(OPCODE_SAMPLING)
781 #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler()
783 #define CTI_SAMPLER 0
786 JITThunks::JITThunks(JSGlobalData* globalData)
788 if (!globalData->executableAllocator.isValid())
791 JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_trampolineStructure);
792 ASSERT(m_executablePool);
794 // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
795 // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
797 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET);
798 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVED_R4_OFFSET);
799 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == PRESERVED_R5_OFFSET);
800 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == PRESERVED_R6_OFFSET);
802 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET);
803 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET);
804 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == EXCEPTION_OFFSET);
805 // The fifth argument is the first item already on the stack.
806 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET);
808 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
810 #elif CPU(ARM_TRADITIONAL)
812 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
813 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVEDR4_OFFSET);
817 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedGP) == PRESERVED_GP_OFFSET);
818 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS0) == PRESERVED_S0_OFFSET);
819 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS1) == PRESERVED_S1_OFFSET);
820 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS2) == PRESERVED_S2_OFFSET);
821 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET);
822 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
823 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET);
824 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET);
825 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == EXCEPTION_OFFSET);
826 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET);
827 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, globalData) == GLOBAL_DATA_OFFSET);
832 JITThunks::~JITThunks()
836 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
838 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct)
840 // The interpreter checks for recursion here; I do not believe this can occur in CTI.
842 if (!baseValue.isCell())
845 // Uncacheable: give up.
846 if (!slot.isCacheable()) {
847 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
851 JSCell* baseCell = baseValue.asCell();
852 Structure* structure = baseCell->structure();
854 if (structure->isUncacheableDictionary()) {
855 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
859 // If baseCell != base, then baseCell must be a proxy for another object.
860 if (baseCell != slot.base()) {
861 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
865 // Cache hit: Specialize instruction and ref Structures.
867 // Structure transition, cache transition info
868 if (slot.type() == PutPropertySlot::NewProperty) {
869 if (structure->isDictionary()) {
870 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
874 // put_by_id_transition checks the prototype chain for setters.
875 normalizePrototypeChain(callFrame, baseCell);
877 StructureChain* prototypeChain = structure->prototypeChain(callFrame);
878 stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
879 JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct);
883 stubInfo->initPutByIdReplace(structure);
885 JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct);
888 NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
890 // FIXME: Write a test that proves we need to check for recursion here just
891 // like the interpreter does, then add a check for recursion.
893 // FIXME: Cache property access for immediates.
894 if (!baseValue.isCell()) {
895 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
899 JSGlobalData* globalData = &callFrame->globalData();
901 if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
902 JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
906 if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
907 // The tradeoff of compiling an patched inline string length access routine does not seem
908 // to pay off, so we currently only do this for arrays.
909 ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs->ctiStringLengthTrampoline());
913 // Uncacheable: give up.
914 if (!slot.isCacheable()) {
915 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
919 JSCell* baseCell = baseValue.asCell();
920 Structure* structure = baseCell->structure();
922 if (structure->isUncacheableDictionary()) {
923 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
927 // Cache hit: Specialize instruction and ref Structures.
929 if (slot.slotBase() == baseValue) {
930 // set this up, so derefStructures can do it's job.
931 stubInfo->initGetByIdSelf(structure);
932 if (slot.cachedPropertyType() != PropertySlot::Value)
933 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
935 JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
939 if (structure->isDictionary()) {
940 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
944 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
945 ASSERT(slot.slotBase().isObject());
947 JSObject* slotBaseObject = asObject(slot.slotBase());
948 size_t offset = slot.cachedOffset();
950 // Since we're accessing a prototype in a loop, it's a good bet that it
951 // should not be treated as a dictionary.
952 if (slotBaseObject->structure()->isDictionary()) {
953 slotBaseObject->flattenDictionaryObject();
954 offset = slotBaseObject->structure()->get(propertyName);
957 stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
959 ASSERT(!structure->isDictionary());
960 ASSERT(!slotBaseObject->structure()->isDictionary());
961 JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), propertyName, slot, offset, returnAddress);
965 size_t offset = slot.cachedOffset();
966 size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
968 stubInfo->accessType = access_get_by_id_generic;
972 StructureChain* prototypeChain = structure->prototypeChain(callFrame);
973 stubInfo->initGetByIdChain(structure, prototypeChain);
974 JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
977 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
983 static void jscGeneratedNativeCode()
985 // When executing a JIT stub function (which might do an allocation), we hack the return address
986 // to pretend to be executing this function, to keep stack logging tools from blowing out
993 ALWAYS_INLINE StackHack(JITStackFrame& stackFrame)
994 : stackFrame(stackFrame)
995 , savedReturnAddress(*stackFrame.returnAddressSlot())
997 *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
1000 ALWAYS_INLINE ~StackHack()
1002 *stackFrame.returnAddressSlot() = savedReturnAddress;
1005 JITStackFrame& stackFrame;
1006 ReturnAddressPtr savedReturnAddress;
1009 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
1010 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
1011 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
1015 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS)
1016 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
1017 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
1021 // The reason this is not inlined is to avoid having to do a PIC branch
1022 // to get the address of the ctiVMThrowTrampoline function. It's also
1023 // good to keep the code size down by leaving as much of the exception
1024 // handling code out of line as possible.
1025 static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
1027 ASSERT(globalData->exception);
1028 globalData->exceptionLocation = exceptionLocation;
1029 returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline));
1032 static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
1034 globalData->exception = createStackOverflowError(callFrame);
1035 returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot);
1038 #define VM_THROW_EXCEPTION() \
1040 VM_THROW_EXCEPTION_AT_END(); \
1043 #define VM_THROW_EXCEPTION_AT_END() \
1045 returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\
1048 #define CHECK_FOR_EXCEPTION() \
1050 if (UNLIKELY(stackFrame.globalData->exception)) \
1051 VM_THROW_EXCEPTION(); \
1053 #define CHECK_FOR_EXCEPTION_AT_END() \
1055 if (UNLIKELY(stackFrame.globalData->exception)) \
1056 VM_THROW_EXCEPTION_AT_END(); \
1058 #define CHECK_FOR_EXCEPTION_VOID() \
1060 if (UNLIKELY(stackFrame.globalData->exception)) { \
1061 VM_THROW_EXCEPTION_AT_END(); \
1066 struct ExceptionHandler {
1068 CallFrame* callFrame;
1070 static ExceptionHandler jitThrow(JSGlobalData* globalData, CallFrame* callFrame, JSValue exceptionValue, ReturnAddressPtr faultLocation, bool explicitThrow)
1072 ASSERT(exceptionValue);
1074 unsigned vPCIndex = callFrame->codeBlock()->bytecodeOffset(callFrame, faultLocation);
1075 globalData->exception = JSValue();
1076 HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, explicitThrow); // This may update callFrame & exceptionValue!
1077 globalData->exception = exceptionValue;
1079 void* catchRoutine = handler ? handler->nativeCode.executableAddress() : FunctionPtr(ctiOpThrowNotCaught).value();
1080 ASSERT(catchRoutine);
1081 ExceptionHandler exceptionHandler = { catchRoutine, callFrame };
1082 return exceptionHandler;
1087 #define DEFINE_STUB_FUNCTION(rtype, op) \
1089 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1094 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1095 HIDE_SYMBOL(cti_##op) "\n" \
1097 ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \
1098 SYMBOL_STRING(cti_##op) ":" "\n" \
1099 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1100 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1101 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1104 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
1108 #define DEFINE_STUB_FUNCTION(rtype, op) \
1110 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1115 ".set noreorder" "\n" \
1116 ".set nomacro" "\n" \
1117 ".set nomips16" "\n" \
1118 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1119 ".ent " SYMBOL_STRING(cti_##op) "\n" \
1120 SYMBOL_STRING(cti_##op) ":" "\n" \
1121 "lw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n" \
1122 "sw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1124 "la $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \
1125 ".set nomacro" "\n" \
1126 "bal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1128 "lw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1131 ".set reorder" "\n" \
1133 ".end " SYMBOL_STRING(cti_##op) "\n" \
1135 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1137 #else // WTF_MIPS_PIC
1138 #define DEFINE_STUB_FUNCTION(rtype, op) \
1140 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1145 ".set noreorder" "\n" \
1146 ".set nomacro" "\n" \
1147 ".set nomips16" "\n" \
1148 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1149 ".ent " SYMBOL_STRING(cti_##op) "\n" \
1150 SYMBOL_STRING(cti_##op) ":" "\n" \
1151 "sw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1152 "jal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1154 "lw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1157 ".set reorder" "\n" \
1159 ".end " SYMBOL_STRING(cti_##op) "\n" \
1161 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1165 #elif CPU(ARM_TRADITIONAL) && COMPILER(GCC)
1167 #define DEFINE_STUB_FUNCTION(rtype, op) \
1169 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1172 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1173 SYMBOL_STRING(cti_##op) ":" "\n" \
1174 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1175 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1176 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1179 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1181 #elif CPU(ARM_TRADITIONAL) && COMPILER(RVCT)
1183 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1185 /* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */
1187 /* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */
1188 /* The pattern "#xxx#" will be replaced with "xxx" */
1191 RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
1192 RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
1195 RVCT( IMPORT JITStubThunked_#op#)
1196 RVCT( str lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
1197 RVCT( bl JITStubThunked_#op#)
1198 RVCT( ldr lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
1204 /* Include the generated file */
1205 #include "GeneratedJITStubs_RVCT.h"
1207 #elif CPU(ARM_TRADITIONAL) && COMPILER(MSVC)
1209 #define DEFINE_STUB_FUNCTION(rtype, op) extern "C" rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1211 /* The following is a workaround for MSVC toolchain; inline assembler is not supported */
1213 /* The following section is a template to generate code for GeneratedJITStubs_MSVC.asm */
1214 /* The pattern "#xxx#" will be replaced with "xxx" */
1217 MSVC_BEGIN( AREA Trampoline, CODE)
1219 MSVC_BEGIN( EXPORT ctiTrampoline)
1220 MSVC_BEGIN( EXPORT ctiVMThrowTrampoline)
1221 MSVC_BEGIN( EXPORT ctiOpThrowNotCaught)
1223 MSVC_BEGIN(ctiTrampoline PROC)
1224 MSVC_BEGIN( stmdb sp!, {r1-r3})
1225 MSVC_BEGIN( stmdb sp!, {r4-r8, lr})
1226 MSVC_BEGIN( sub sp, sp, # THUNK_RETURN_ADDRESS_OFFSET + 4)
1227 MSVC_BEGIN( mov r4, r2)
1228 MSVC_BEGIN( mov r5, #512)
1229 MSVC_BEGIN( ; r0 contains the code)
1230 MSVC_BEGIN( mov lr, pc)
1232 MSVC_BEGIN( add sp, sp, # THUNK_RETURN_ADDRESS_OFFSET + 4)
1233 MSVC_BEGIN( ldmia sp!, {r4-r8, lr})
1234 MSVC_BEGIN( add sp, sp, #12)
1236 MSVC_BEGIN(ctiTrampoline ENDP)
1238 MSVC_BEGIN(ctiVMThrowTrampoline PROC)
1239 MSVC_BEGIN( mov r0, sp)
1240 MSVC_BEGIN( mov lr, pc)
1241 MSVC_BEGIN( bl cti_vm_throw)
1242 MSVC_BEGIN(ctiOpThrowNotCaught)
1243 MSVC_BEGIN( add sp, sp, # THUNK_RETURN_ADDRESS_OFFSET + 4)
1244 MSVC_BEGIN( ldmia sp!, {r4-r8, lr})
1245 MSVC_BEGIN( add sp, sp, #12)
1247 MSVC_BEGIN(ctiVMThrowTrampoline ENDP)
1250 MSVC( EXPORT cti_#op#)
1251 MSVC( IMPORT JITStubThunked_#op#)
1253 MSVC( str lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
1254 MSVC( bl JITStubThunked_#op#)
1255 MSVC( ldr lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
1264 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
1267 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_this)
1269 STUB_INIT_STACK_FRAME(stackFrame);
1270 CallFrame* callFrame = stackFrame.callFrame;
1272 JSFunction* constructor = asFunction(callFrame->callee());
1273 #if !ASSERT_DISABLED
1274 ConstructData constructData;
1275 ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
1278 Structure* structure;
1279 JSValue proto = stackFrame.args[0].jsValue();
1280 if (proto.isObject())
1281 structure = asObject(proto)->inheritorID();
1283 structure = constructor->scope().node()->globalObject->emptyObjectStructure();
1284 JSValue result = new (&callFrame->globalData()) JSObject(structure);
1286 return JSValue::encode(result);
1289 DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this)
1291 STUB_INIT_STACK_FRAME(stackFrame);
1293 JSValue v1 = stackFrame.args[0].jsValue();
1294 CallFrame* callFrame = stackFrame.callFrame;
1296 JSObject* result = v1.toThisObject(callFrame);
1297 CHECK_FOR_EXCEPTION_AT_END();
1298 return JSValue::encode(result);
1301 DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this_strict)
1303 STUB_INIT_STACK_FRAME(stackFrame);
1305 JSValue v1 = stackFrame.args[0].jsValue();
1306 CallFrame* callFrame = stackFrame.callFrame;
1307 ASSERT(v1.asCell()->structure()->typeInfo().needsThisConversion());
1308 JSValue result = v1.toStrictThisObject(callFrame);
1309 CHECK_FOR_EXCEPTION_AT_END();
1310 return JSValue::encode(result);
1313 DEFINE_STUB_FUNCTION(void, op_end)
1315 STUB_INIT_STACK_FRAME(stackFrame);
1317 ScopeChainNode* scopeChain = stackFrame.callFrame->scopeChain();
1318 ASSERT(scopeChain->refCount > 1);
1319 scopeChain->deref();
1322 DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
1324 STUB_INIT_STACK_FRAME(stackFrame);
1326 JSValue v1 = stackFrame.args[0].jsValue();
1327 JSValue v2 = stackFrame.args[1].jsValue();
1328 CallFrame* callFrame = stackFrame.callFrame;
1330 if (v1.isString()) {
1331 JSValue result = v2.isString()
1332 ? jsString(callFrame, asString(v1), asString(v2))
1333 : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
1334 CHECK_FOR_EXCEPTION_AT_END();
1335 return JSValue::encode(result);
1338 double left = 0.0, right;
1339 if (v1.getNumber(left) && v2.getNumber(right))
1340 return JSValue::encode(jsNumber(left + right));
1342 // All other cases are pretty uncommon
1343 JSValue result = jsAddSlowCase(callFrame, v1, v2);
1344 CHECK_FOR_EXCEPTION_AT_END();
1345 return JSValue::encode(result);
1348 DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_inc)
1350 STUB_INIT_STACK_FRAME(stackFrame);
1352 JSValue v = stackFrame.args[0].jsValue();
1354 CallFrame* callFrame = stackFrame.callFrame;
1355 JSValue result = jsNumber(v.toNumber(callFrame) + 1);
1356 CHECK_FOR_EXCEPTION_AT_END();
1357 return JSValue::encode(result);
1360 DEFINE_STUB_FUNCTION(int, timeout_check)
1362 STUB_INIT_STACK_FRAME(stackFrame);
1364 JSGlobalData* globalData = stackFrame.globalData;
1365 TimeoutChecker& timeoutChecker = globalData->timeoutChecker;
1367 if (globalData->terminator.shouldTerminate()) {
1368 globalData->exception = createTerminatedExecutionException(globalData);
1369 VM_THROW_EXCEPTION_AT_END();
1370 } else if (timeoutChecker.didTimeOut(stackFrame.callFrame)) {
1371 globalData->exception = createInterruptedExecutionException(globalData);
1372 VM_THROW_EXCEPTION_AT_END();
1375 return timeoutChecker.ticksUntilNextCheck();
1378 DEFINE_STUB_FUNCTION(void*, register_file_check)
1380 STUB_INIT_STACK_FRAME(stackFrame);
1381 CallFrame* callFrame = stackFrame.callFrame;
1383 if (UNLIKELY(!stackFrame.registerFile->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters]))) {
1384 // Rewind to the previous call frame because op_call already optimistically
1385 // moved the call frame forward.
1386 CallFrame* oldCallFrame = callFrame->callerFrame();
1387 ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), ReturnAddressPtr(oldCallFrame->returnPC()), false);
1388 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1389 callFrame = handler.callFrame;
1395 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
1397 STUB_INIT_STACK_FRAME(stackFrame);
1399 JSValue src1 = stackFrame.args[0].jsValue();
1400 JSValue src2 = stackFrame.args[1].jsValue();
1401 CallFrame* callFrame = stackFrame.callFrame;
1403 bool result = jsLessEq(callFrame, src1, src2);
1404 CHECK_FOR_EXCEPTION_AT_END();
1408 DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
1410 STUB_INIT_STACK_FRAME(stackFrame);
1412 return constructEmptyObject(stackFrame.callFrame);
1415 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
1417 STUB_INIT_STACK_FRAME(stackFrame);
1419 PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
1420 stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
1421 CHECK_FOR_EXCEPTION_AT_END();
1424 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
1426 STUB_INIT_STACK_FRAME(stackFrame);
1428 PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
1429 stackFrame.args[0].jsValue().putDirect(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
1430 CHECK_FOR_EXCEPTION_AT_END();
1433 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
1435 STUB_INIT_STACK_FRAME(stackFrame);
1437 CallFrame* callFrame = stackFrame.callFrame;
1438 Identifier& ident = stackFrame.args[1].identifier();
1440 JSValue baseValue = stackFrame.args[0].jsValue();
1441 PropertySlot slot(baseValue);
1442 JSValue result = baseValue.get(callFrame, ident, slot);
1444 CHECK_FOR_EXCEPTION_AT_END();
1445 return JSValue::encode(result);
1448 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1450 DEFINE_STUB_FUNCTION(void, op_put_by_id)
1452 STUB_INIT_STACK_FRAME(stackFrame);
1453 CallFrame* callFrame = stackFrame.callFrame;
1454 Identifier& ident = stackFrame.args[1].identifier();
1456 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1457 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
1459 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1460 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1461 if (!stubInfo->seenOnce())
1462 stubInfo->setSeen();
1464 JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false);
1466 CHECK_FOR_EXCEPTION_AT_END();
1469 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
1471 STUB_INIT_STACK_FRAME(stackFrame);
1472 CallFrame* callFrame = stackFrame.callFrame;
1473 Identifier& ident = stackFrame.args[1].identifier();
1475 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1476 stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
1478 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1479 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1480 if (!stubInfo->seenOnce())
1481 stubInfo->setSeen();
1483 JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true);
1485 CHECK_FOR_EXCEPTION_AT_END();
1488 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
1490 STUB_INIT_STACK_FRAME(stackFrame);
1492 CallFrame* callFrame = stackFrame.callFrame;
1493 Identifier& ident = stackFrame.args[1].identifier();
1495 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1496 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
1498 CHECK_FOR_EXCEPTION_AT_END();
1501 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
1503 STUB_INIT_STACK_FRAME(stackFrame);
1505 CallFrame* callFrame = stackFrame.callFrame;
1506 Identifier& ident = stackFrame.args[1].identifier();
1508 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1509 stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
1511 CHECK_FOR_EXCEPTION_AT_END();
1514 DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
1516 STUB_INIT_STACK_FRAME(stackFrame);
1518 JSValue baseValue = stackFrame.args[0].jsValue();
1519 int32_t oldSize = stackFrame.args[3].int32();
1520 int32_t newSize = stackFrame.args[4].int32();
1522 ASSERT(baseValue.isObject());
1523 JSObject* base = asObject(baseValue);
1524 base->allocatePropertyStorage(oldSize, newSize);
1529 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
1531 STUB_INIT_STACK_FRAME(stackFrame);
1533 CallFrame* callFrame = stackFrame.callFrame;
1534 Identifier& ident = stackFrame.args[1].identifier();
1536 JSValue baseValue = stackFrame.args[0].jsValue();
1537 PropertySlot slot(baseValue);
1538 JSValue result = baseValue.get(callFrame, ident, slot);
1539 CHECK_FOR_EXCEPTION();
1541 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1542 MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
1544 if (!methodCallLinkInfo.seenOnce()) {
1545 methodCallLinkInfo.setSeen();
1546 return JSValue::encode(result);
1549 // If we successfully got something, then the base from which it is being accessed must
1550 // be an object. (Assertion to ensure asObject() call below is safe, which comes after
1551 // an isCacheable() chceck.
1552 ASSERT(!slot.isCacheableValue() || slot.slotBase().isObject());
1555 // * We're dealing with a JSCell,
1556 // * the property is cachable,
1557 // * it's not a dictionary
1558 // * there is a function cached.
1559 Structure* structure;
1561 JSObject* slotBaseObject;
1562 if (baseValue.isCell()
1563 && slot.isCacheableValue()
1564 && !(structure = baseValue.asCell()->structure())->isUncacheableDictionary()
1565 && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
1569 JSFunction* callee = (JSFunction*)specific;
1571 // Since we're accessing a prototype in a loop, it's a good bet that it
1572 // should not be treated as a dictionary.
1573 if (slotBaseObject->structure()->isDictionary())
1574 slotBaseObject->flattenDictionaryObject();
1576 // The result fetched should always be the callee!
1577 ASSERT(result == JSValue(callee));
1579 // Check to see if the function is on the object's prototype. Patch up the code to optimize.
1580 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
1581 JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
1582 return JSValue::encode(result);
1585 // Check to see if the function is on the object itself.
1586 // Since we generate the method-check to check both the structure and a prototype-structure (since this
1587 // is the common case) we have a problem - we need to patch the prototype structure check to do something
1588 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler
1589 // for now. For now it performs a check on a special object on the global object only used for this
1590 // purpose. The object is in no way exposed, and as such the check will always pass.
1591 if (slot.slotBase() == baseValue) {
1592 JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
1593 return JSValue::encode(result);
1597 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
1598 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
1599 return JSValue::encode(result);
1602 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
1604 STUB_INIT_STACK_FRAME(stackFrame);
1605 CallFrame* callFrame = stackFrame.callFrame;
1606 Identifier& ident = stackFrame.args[1].identifier();
1608 JSValue baseValue = stackFrame.args[0].jsValue();
1609 PropertySlot slot(baseValue);
1610 JSValue result = baseValue.get(callFrame, ident, slot);
1612 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1613 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1614 if (!stubInfo->seenOnce())
1615 stubInfo->setSeen();
1617 JITThunks::tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo);
1619 CHECK_FOR_EXCEPTION_AT_END();
1620 return JSValue::encode(result);
1623 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
1625 STUB_INIT_STACK_FRAME(stackFrame);
1627 CallFrame* callFrame = stackFrame.callFrame;
1628 Identifier& ident = stackFrame.args[1].identifier();
1630 JSValue baseValue = stackFrame.args[0].jsValue();
1631 PropertySlot slot(baseValue);
1632 JSValue result = baseValue.get(callFrame, ident, slot);
1634 CHECK_FOR_EXCEPTION();
1636 if (baseValue.isCell()
1637 && slot.isCacheable()
1638 && !baseValue.asCell()->structure()->isUncacheableDictionary()
1639 && slot.slotBase() == baseValue) {
1641 CodeBlock* codeBlock = callFrame->codeBlock();
1642 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1644 ASSERT(slot.slotBase().isObject());
1646 PolymorphicAccessStructureList* polymorphicStructureList;
1649 if (stubInfo->accessType == access_get_by_id_self) {
1650 ASSERT(!stubInfo->stubRoutine);
1651 polymorphicStructureList = new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure);
1652 stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
1654 polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
1655 listIndex = stubInfo->u.getByIdSelfList.listSize;
1657 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
1658 stubInfo->u.getByIdSelfList.listSize++;
1659 JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, baseValue.asCell()->structure(), ident, slot, slot.cachedOffset());
1661 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1662 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
1665 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
1666 return JSValue::encode(result);
1669 static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex)
1671 PolymorphicAccessStructureList* prototypeStructureList = 0;
1674 switch (stubInfo->accessType) {
1675 case access_get_by_id_proto:
1676 prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
1677 stubInfo->stubRoutine = CodeLocationLabel();
1678 stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
1680 case access_get_by_id_chain:
1681 prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
1682 stubInfo->stubRoutine = CodeLocationLabel();
1683 stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
1685 case access_get_by_id_proto_list:
1686 prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
1687 listIndex = stubInfo->u.getByIdProtoList.listSize;
1688 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE)
1689 stubInfo->u.getByIdProtoList.listSize++;
1692 ASSERT_NOT_REACHED();
1695 ASSERT(listIndex <= POLYMORPHIC_LIST_CACHE_SIZE);
1696 return prototypeStructureList;
1699 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_getter_stub)
1701 STUB_INIT_STACK_FRAME(stackFrame);
1702 CallFrame* callFrame = stackFrame.callFrame;
1703 GetterSetter* getterSetter = asGetterSetter(stackFrame.args[0].jsObject());
1704 if (!getterSetter->getter())
1705 return JSValue::encode(jsUndefined());
1706 JSObject* getter = asObject(getterSetter->getter());
1708 CallType callType = getter->getCallData(callData);
1709 JSValue result = call(callFrame, getter, callType, callData, stackFrame.args[1].jsObject(), ArgList());
1710 if (callFrame->hadException())
1711 returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS);
1713 return JSValue::encode(result);
1716 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_custom_stub)
1718 STUB_INIT_STACK_FRAME(stackFrame);
1719 CallFrame* callFrame = stackFrame.callFrame;
1720 JSObject* slotBase = stackFrame.args[0].jsObject();
1721 PropertySlot::GetValueFunc getter = reinterpret_cast<PropertySlot::GetValueFunc>(stackFrame.args[1].asPointer);
1722 const Identifier& ident = stackFrame.args[2].identifier();
1723 JSValue result = getter(callFrame, slotBase, ident);
1724 if (callFrame->hadException())
1725 returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[3].returnAddress(), STUB_RETURN_ADDRESS);
1727 return JSValue::encode(result);
1730 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
1732 STUB_INIT_STACK_FRAME(stackFrame);
1734 CallFrame* callFrame = stackFrame.callFrame;
1735 const Identifier& propertyName = stackFrame.args[1].identifier();
1737 JSValue baseValue = stackFrame.args[0].jsValue();
1738 PropertySlot slot(baseValue);
1739 JSValue result = baseValue.get(callFrame, propertyName, slot);
1741 CHECK_FOR_EXCEPTION();
1743 if (!baseValue.isCell() || !slot.isCacheable() || baseValue.asCell()->structure()->isDictionary()) {
1744 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1745 return JSValue::encode(result);
1748 Structure* structure = baseValue.asCell()->structure();
1749 CodeBlock* codeBlock = callFrame->codeBlock();
1750 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1752 ASSERT(slot.slotBase().isObject());
1753 JSObject* slotBaseObject = asObject(slot.slotBase());
1755 size_t offset = slot.cachedOffset();
1757 if (slot.slotBase() == baseValue)
1758 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1759 else if (slot.slotBase() == baseValue.asCell()->structure()->prototypeForLookup(callFrame)) {
1760 ASSERT(!baseValue.asCell()->structure()->isDictionary());
1761 // Since we're accessing a prototype in a loop, it's a good bet that it
1762 // should not be treated as a dictionary.
1763 if (slotBaseObject->structure()->isDictionary()) {
1764 slotBaseObject->flattenDictionaryObject();
1765 offset = slotBaseObject->structure()->get(propertyName);
1769 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
1770 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
1771 JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset);
1773 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1774 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
1776 } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
1777 ASSERT(!baseValue.asCell()->structure()->isDictionary());
1779 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
1781 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
1782 StructureChain* protoChain = structure->prototypeChain(callFrame);
1783 JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, propertyName, slot, offset);
1785 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1786 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
1789 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1791 return JSValue::encode(result);
1794 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full)
1796 STUB_INIT_STACK_FRAME(stackFrame);
1798 JSValue baseValue = stackFrame.args[0].jsValue();
1799 PropertySlot slot(baseValue);
1800 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1802 CHECK_FOR_EXCEPTION_AT_END();
1803 return JSValue::encode(result);
1806 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_fail)
1808 STUB_INIT_STACK_FRAME(stackFrame);
1810 JSValue baseValue = stackFrame.args[0].jsValue();
1811 PropertySlot slot(baseValue);
1812 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1814 CHECK_FOR_EXCEPTION_AT_END();
1815 return JSValue::encode(result);
1818 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_array_fail)
1820 STUB_INIT_STACK_FRAME(stackFrame);
1822 JSValue baseValue = stackFrame.args[0].jsValue();
1823 PropertySlot slot(baseValue);
1824 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1826 CHECK_FOR_EXCEPTION_AT_END();
1827 return JSValue::encode(result);
1830 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
1832 STUB_INIT_STACK_FRAME(stackFrame);
1834 JSValue baseValue = stackFrame.args[0].jsValue();
1835 PropertySlot slot(baseValue);
1836 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1838 CHECK_FOR_EXCEPTION_AT_END();
1839 return JSValue::encode(result);
1842 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1844 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
1846 STUB_INIT_STACK_FRAME(stackFrame);
1848 CallFrame* callFrame = stackFrame.callFrame;
1849 JSValue value = stackFrame.args[0].jsValue();
1850 JSValue baseVal = stackFrame.args[1].jsValue();
1851 JSValue proto = stackFrame.args[2].jsValue();
1853 // At least one of these checks must have failed to get to the slow case.
1854 ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
1855 || !value.isObject() || !baseVal.isObject() || !proto.isObject()
1856 || (asObject(baseVal)->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance);
1859 // ECMA-262 15.3.5.3:
1860 // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
1861 TypeInfo typeInfo(UnspecifiedType);
1862 if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) {
1863 CallFrame* callFrame = stackFrame.callFrame;
1864 CodeBlock* codeBlock = callFrame->codeBlock();
1865 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
1866 stackFrame.globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, vPCIndex, codeBlock);
1867 VM_THROW_EXCEPTION();
1869 ASSERT(typeInfo.type() != UnspecifiedType);
1871 if (!typeInfo.overridesHasInstance()) {
1872 if (!value.isObject())
1873 return JSValue::encode(jsBoolean(false));
1875 if (!proto.isObject()) {
1876 throwError(callFrame, createTypeError(callFrame, "instanceof called on an object with an invalid prototype property."));
1877 VM_THROW_EXCEPTION();
1881 JSValue result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
1882 CHECK_FOR_EXCEPTION_AT_END();
1884 return JSValue::encode(result);
1887 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
1889 STUB_INIT_STACK_FRAME(stackFrame);
1891 CallFrame* callFrame = stackFrame.callFrame;
1893 JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
1895 bool couldDelete = baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier());
1896 JSValue result = jsBoolean(couldDelete);
1897 if (!couldDelete && callFrame->codeBlock()->isStrictMode())
1898 stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
1900 CHECK_FOR_EXCEPTION_AT_END();
1901 return JSValue::encode(result);
1904 DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul)
1906 STUB_INIT_STACK_FRAME(stackFrame);
1908 JSValue src1 = stackFrame.args[0].jsValue();
1909 JSValue src2 = stackFrame.args[1].jsValue();
1913 if (src1.getNumber(left) && src2.getNumber(right))
1914 return JSValue::encode(jsNumber(left * right));
1916 CallFrame* callFrame = stackFrame.callFrame;
1917 JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
1918 CHECK_FOR_EXCEPTION_AT_END();
1919 return JSValue::encode(result);
1922 DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
1924 STUB_INIT_STACK_FRAME(stackFrame);
1926 ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->r(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
1927 return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
1930 DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
1932 STUB_INIT_STACK_FRAME(stackFrame);
1934 #if !ASSERT_DISABLED
1936 ASSERT(stackFrame.callFrame->callee()->getCallData(callData) == CallTypeJS);
1939 JSFunction* function = asFunction(stackFrame.callFrame->callee());
1940 ASSERT(!function->isHostFunction());
1941 FunctionExecutable* executable = function->jsExecutable();
1942 ScopeChainNode* callDataScopeChain = function->scope().node();
1943 JSObject* error = executable->compileForCall(stackFrame.callFrame, callDataScopeChain);
1945 stackFrame.callFrame->globalData().exception = error;
1951 DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
1953 STUB_INIT_STACK_FRAME(stackFrame);
1955 #if !ASSERT_DISABLED
1956 ConstructData constructData;
1957 ASSERT(asFunction(stackFrame.callFrame->callee())->getConstructData(constructData) == ConstructTypeJS);
1960 JSFunction* function = asFunction(stackFrame.callFrame->callee());
1961 ASSERT(!function->isHostFunction());
1962 FunctionExecutable* executable = function->jsExecutable();
1963 ScopeChainNode* callDataScopeChain = function->scope().node();
1964 JSObject* error = executable->compileForConstruct(stackFrame.callFrame, callDataScopeChain);
1966 stackFrame.callFrame->globalData().exception = error;
1972 DEFINE_STUB_FUNCTION(void*, op_call_arityCheck)
1974 STUB_INIT_STACK_FRAME(stackFrame);
1976 CallFrame* callFrame = stackFrame.callFrame;
1977 JSFunction* callee = asFunction(callFrame->callee());
1978 ASSERT(!callee->isHostFunction());
1979 CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeForCall();
1980 int argCount = callFrame->argumentCountIncludingThis();
1981 ReturnAddressPtr pc = callFrame->returnPC();
1983 ASSERT(argCount != newCodeBlock->m_numParameters);
1985 CallFrame* oldCallFrame = callFrame->callerFrame();
1988 if (argCount > newCodeBlock->m_numParameters) {
1989 size_t numParameters = newCodeBlock->m_numParameters;
1990 r = callFrame->registers() + numParameters;
1991 Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
1992 if (!stackFrame.registerFile->grow(newEnd)) {
1993 // Rewind to the previous call frame because op_call already optimistically
1994 // moved the call frame forward.
1995 ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc, false);
1996 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1997 return handler.callFrame;
2000 Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
2001 for (size_t i = 0; i < numParameters; ++i)
2002 argv[i + argCount] = argv[i];
2004 size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
2005 r = callFrame->registers() + omittedArgCount;
2006 Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
2007 if (!stackFrame.registerFile->grow(newEnd)) {
2008 // Rewind to the previous call frame because op_call already optimistically
2009 // moved the call frame forward.
2010 ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc, false);
2011 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
2012 return handler.callFrame;
2015 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
2016 for (size_t i = 0; i < omittedArgCount; ++i)
2017 argv[i] = jsUndefined();
2020 callFrame = CallFrame::create(r);
2021 callFrame->setCallerFrame(oldCallFrame);
2022 callFrame->setArgumentCountIncludingThis(argCount);
2023 callFrame->setCallee(callee);
2024 callFrame->setScopeChain(callee->scope().node());
2025 callFrame->setReturnPC(pc.value());
2027 ASSERT((void*)callFrame <= stackFrame.registerFile->end());
2031 DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck)
2033 STUB_INIT_STACK_FRAME(stackFrame);
2035 CallFrame* callFrame = stackFrame.callFrame;
2036 JSFunction* callee = asFunction(callFrame->callee());
2037 ASSERT(!callee->isHostFunction());
2038 CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeForConstruct();
2039 int argCount = callFrame->argumentCountIncludingThis();
2040 ReturnAddressPtr pc = callFrame->returnPC();
2042 ASSERT(argCount != newCodeBlock->m_numParameters);
2044 CallFrame* oldCallFrame = callFrame->callerFrame();
2047 if (argCount > newCodeBlock->m_numParameters) {
2048 size_t numParameters = newCodeBlock->m_numParameters;
2049 r = callFrame->registers() + numParameters;
2050 Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
2051 if (!stackFrame.registerFile->grow(newEnd)) {
2052 // Rewind to the previous call frame because op_call already optimistically
2053 // moved the call frame forward.
2054 ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc, false);
2055 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
2056 return handler.callFrame;
2059 Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
2060 for (size_t i = 0; i < numParameters; ++i)
2061 argv[i + argCount] = argv[i];
2063 size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
2064 r = callFrame->registers() + omittedArgCount;
2065 Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
2066 if (!stackFrame.registerFile->grow(newEnd)) {
2067 // Rewind to the previous call frame because op_call already optimistically
2068 // moved the call frame forward.
2069 ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc, false);
2070 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
2071 return handler.callFrame;
2074 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
2075 for (size_t i = 0; i < omittedArgCount; ++i)
2076 argv[i] = jsUndefined();
2079 callFrame = CallFrame::create(r);
2080 callFrame->setCallerFrame(oldCallFrame);
2081 callFrame->setArgumentCountIncludingThis(argCount);
2082 callFrame->setCallee(callee);
2083 callFrame->setScopeChain(callee->scope().node());
2084 callFrame->setReturnPC(pc.value());
2086 ASSERT((void*)callFrame <= stackFrame.registerFile->end());
2090 #if ENABLE(JIT_OPTIMIZE_CALL)
2091 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
2093 STUB_INIT_STACK_FRAME(stackFrame);
2094 CallFrame* callFrame = stackFrame.callFrame;
2095 JSFunction* callee = asFunction(callFrame->callee());
2096 ExecutableBase* executable = callee->executable();
2098 MacroAssemblerCodePtr codePtr;
2099 CodeBlock* codeBlock = 0;
2100 if (executable->isHostFunction())
2101 codePtr = executable->generatedJITCodeForCall().addressForCall();
2103 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
2104 JSObject* error = functionExecutable->compileForCall(callFrame, callee->scope().node());
2106 callFrame->globalData().exception = createStackOverflowError(callFrame);
2109 codeBlock = &functionExecutable->generatedBytecodeForCall();
2110 if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
2111 codePtr = functionExecutable->generatedJITCodeForCall().addressForCall();
2113 codePtr = functionExecutable->generatedJITCodeForCallWithArityCheck();
2115 CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
2117 if (!callLinkInfo->seenOnce())
2118 callLinkInfo->setSeen();
2120 JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, callFrame->argumentCountIncludingThis(), stackFrame.globalData);
2122 return codePtr.executableAddress();
2125 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
2127 STUB_INIT_STACK_FRAME(stackFrame);
2128 CallFrame* callFrame = stackFrame.callFrame;
2129 JSFunction* callee = asFunction(callFrame->callee());
2130 ExecutableBase* executable = callee->executable();
2132 MacroAssemblerCodePtr codePtr;
2133 CodeBlock* codeBlock = 0;
2134 if (executable->isHostFunction())
2135 codePtr = executable->generatedJITCodeForConstruct().addressForCall();
2137 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
2138 JSObject* error = functionExecutable->compileForConstruct(callFrame, callee->scope().node());
2140 throwStackOverflowError(callFrame, stackFrame.globalData, ReturnAddressPtr(callFrame->returnPC()), STUB_RETURN_ADDRESS);
2143 codeBlock = &functionExecutable->generatedBytecodeForConstruct();
2144 if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
2145 codePtr = functionExecutable->generatedJITCodeForConstruct().addressForCall();
2147 codePtr = functionExecutable->generatedJITCodeForConstructWithArityCheck();
2149 CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
2151 if (!callLinkInfo->seenOnce())
2152 callLinkInfo->setSeen();
2154 JIT::linkConstruct(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, callFrame->argumentCountIncludingThis(), stackFrame.globalData);
2156 return codePtr.executableAddress();
2158 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
2160 DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
2162 STUB_INIT_STACK_FRAME(stackFrame);
2164 JSActivation* activation = new (stackFrame.globalData) JSActivation(stackFrame.callFrame, static_cast<FunctionExecutable*>(stackFrame.callFrame->codeBlock()->ownerExecutable()));
2165 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->copy()->push(activation));
2169 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
2171 STUB_INIT_STACK_FRAME(stackFrame);
2173 JSValue funcVal = stackFrame.args[0].jsValue();
2176 CallType callType = getCallData(funcVal, callData);
2178 ASSERT(callType != CallTypeJS);
2180 if (callType == CallTypeHost) {
2181 int registerOffset = stackFrame.args[1].int32();
2182 int argCount = stackFrame.args[2].int32();
2183 CallFrame* previousCallFrame = stackFrame.callFrame;
2184 CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
2185 if (!stackFrame.registerFile->grow(callFrame->registers())) {
2186 throwStackOverflowError(previousCallFrame, stackFrame.globalData, callFrame->returnPC(), STUB_RETURN_ADDRESS);
2187 VM_THROW_EXCEPTION();
2190 callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(funcVal));
2192 EncodedJSValue returnValue;
2194 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
2195 returnValue = callData.native.function(callFrame);
2198 CHECK_FOR_EXCEPTION_AT_END();
2202 ASSERT(callType == CallTypeNone);
2204 CallFrame* callFrame = stackFrame.callFrame;
2205 CodeBlock* codeBlock = callFrame->codeBlock();
2206 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
2207 stackFrame.globalData->exception = createNotAFunctionError(stackFrame.callFrame, funcVal, vPCIndex, codeBlock);
2208 VM_THROW_EXCEPTION();
2211 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
2213 STUB_INIT_STACK_FRAME(stackFrame);
2215 Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame);
2216 return JSValue::encode(JSValue(arguments));
2219 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments_no_params)
2221 STUB_INIT_STACK_FRAME(stackFrame);
2223 Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame, Arguments::NoParameters);
2224 return JSValue::encode(JSValue(arguments));
2227 DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
2229 STUB_INIT_STACK_FRAME(stackFrame);
2231 ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
2232 JSValue activationValue = stackFrame.args[0].jsValue();
2233 if (!activationValue) {
2234 if (JSValue v = stackFrame.args[1].jsValue()) {
2235 if (!stackFrame.callFrame->codeBlock()->isStrictMode())
2236 asArguments(v)->copyRegisters();
2240 JSActivation* activation = asActivation(stackFrame.args[0].jsValue());
2241 activation->copyRegisters();
2242 if (JSValue v = stackFrame.args[1].jsValue()) {
2243 if (!stackFrame.callFrame->codeBlock()->isStrictMode())
2244 asArguments(v)->setActivation(activation);
2248 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
2250 STUB_INIT_STACK_FRAME(stackFrame);
2252 ASSERT(stackFrame.callFrame->codeBlock()->usesArguments() && !stackFrame.callFrame->codeBlock()->needsFullScopeChain());
2253 asArguments(stackFrame.args[0].jsValue())->copyRegisters();
2256 DEFINE_STUB_FUNCTION(void, op_profile_will_call)
2258 STUB_INIT_STACK_FRAME(stackFrame);
2260 ASSERT(*stackFrame.enabledProfilerReference);
2261 (*stackFrame.enabledProfilerReference)->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
2264 DEFINE_STUB_FUNCTION(void, op_profile_did_call)
2266 STUB_INIT_STACK_FRAME(stackFrame);
2268 ASSERT(*stackFrame.enabledProfilerReference);
2269 (*stackFrame.enabledProfilerReference)->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
2272 DEFINE_STUB_FUNCTION(void, op_ret_scopeChain)
2274 STUB_INIT_STACK_FRAME(stackFrame);
2276 ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
2277 stackFrame.callFrame->scopeChain()->deref();
2280 DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
2282 STUB_INIT_STACK_FRAME(stackFrame);
2284 ArgList argList(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
2285 return constructArray(stackFrame.callFrame, argList);
2288 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
2290 STUB_INIT_STACK_FRAME(stackFrame);
2292 CallFrame* callFrame = stackFrame.callFrame;
2293 ScopeChainNode* scopeChain = callFrame->scopeChain();
2295 ScopeChainIterator iter = scopeChain->begin();
2296 ScopeChainIterator end = scopeChain->end();
2297 ASSERT(iter != end);
2299 Identifier& ident = stackFrame.args[0].identifier();
2301 JSObject* o = *iter;
2302 PropertySlot slot(o);
2303 if (o->getPropertySlot(callFrame, ident, slot)) {
2304 JSValue result = slot.getValue(callFrame, ident);
2305 CHECK_FOR_EXCEPTION_AT_END();
2306 return JSValue::encode(result);
2308 } while (++iter != end);
2310 CodeBlock* codeBlock = callFrame->codeBlock();
2311 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
2312 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
2313 VM_THROW_EXCEPTION();
2316 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
2318 STUB_INIT_STACK_FRAME(stackFrame);
2320 JSValue constrVal = stackFrame.args[0].jsValue();
2322 ConstructData constructData;
2323 ConstructType constructType = getConstructData(constrVal, constructData);
2325 ASSERT(constructType != ConstructTypeJS);
2327 if (constructType == ConstructTypeHost) {
2328 int registerOffset = stackFrame.args[1].int32();
2329 int argCount = stackFrame.args[2].int32();
2330 CallFrame* previousCallFrame = stackFrame.callFrame;
2331 CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
2332 if (!stackFrame.registerFile->grow(callFrame->registers())) {
2333 throwStackOverflowError(previousCallFrame, stackFrame.globalData, callFrame->returnPC(), STUB_RETURN_ADDRESS);
2334 VM_THROW_EXCEPTION();
2337 callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(constrVal));
2339 EncodedJSValue returnValue;
2341 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
2342 returnValue = constructData.native.function(callFrame);
2345 CHECK_FOR_EXCEPTION_AT_END();
2349 ASSERT(constructType == ConstructTypeNone);
2351 CallFrame* callFrame = stackFrame.callFrame;
2352 CodeBlock* codeBlock = callFrame->codeBlock();
2353 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
2354 stackFrame.globalData->exception = createNotAConstructorError(callFrame, constrVal, vPCIndex, codeBlock);
2355 VM_THROW_EXCEPTION();
2358 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
2360 STUB_INIT_STACK_FRAME(stackFrame);
2362 CallFrame* callFrame = stackFrame.callFrame;
2363 JSGlobalData* globalData = stackFrame.globalData;
2365 JSValue baseValue = stackFrame.args[0].jsValue();
2366 JSValue subscript = stackFrame.args[1].jsValue();
2368 if (LIKELY(baseValue.isCell() && subscript.isString())) {
2369 Identifier propertyName(callFrame, asString(subscript)->value(callFrame));
2370 PropertySlot slot(baseValue.asCell());
2371 // JSString::value may have thrown, but we shouldn't find a property with a null identifier,
2372 // so we should miss this case and wind up in the CHECK_FOR_EXCEPTION_AT_END, below.
2373 if (baseValue.asCell()->fastGetOwnPropertySlot(callFrame, propertyName, slot)) {
2374 JSValue result = slot.getValue(callFrame, propertyName);
2375 CHECK_FOR_EXCEPTION();
2376 return JSValue::encode(result);
2380 if (subscript.isUInt32()) {
2381 uint32_t i = subscript.asUInt32();
2382 if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
2383 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
2384 JSValue result = asString(baseValue)->getIndex(callFrame, i);
2385 CHECK_FOR_EXCEPTION();
2386 return JSValue::encode(result);
2388 if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2389 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2390 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
2391 return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
2393 JSValue result = baseValue.get(callFrame, i);
2394 CHECK_FOR_EXCEPTION();
2395 return JSValue::encode(result);
2398 Identifier property(callFrame, subscript.toString(callFrame));
2399 JSValue result = baseValue.get(callFrame, property);
2400 CHECK_FOR_EXCEPTION_AT_END();
2401 return JSValue::encode(result);
2404 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
2406 STUB_INIT_STACK_FRAME(stackFrame);
2408 CallFrame* callFrame = stackFrame.callFrame;
2409 JSGlobalData* globalData = stackFrame.globalData;
2411 JSValue baseValue = stackFrame.args[0].jsValue();
2412 JSValue subscript = stackFrame.args[1].jsValue();
2416 if (LIKELY(subscript.isUInt32())) {
2417 uint32_t i = subscript.asUInt32();
2418 if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
2419 result = asString(baseValue)->getIndex(callFrame, i);
2421 result = baseValue.get(callFrame, i);
2422 if (!isJSString(globalData, baseValue))
2423 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
2426 Identifier property(callFrame, subscript.toString(callFrame));
2427 result = baseValue.get(callFrame, property);
2430 CHECK_FOR_EXCEPTION_AT_END();
2431 return JSValue::encode(result);
2434 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_byte_array)
2436 STUB_INIT_STACK_FRAME(stackFrame);
2438 CallFrame* callFrame = stackFrame.callFrame;
2439 JSGlobalData* globalData = stackFrame.globalData;
2441 JSValue baseValue = stackFrame.args[0].jsValue();
2442 JSValue subscript = stackFrame.args[1].jsValue();
2446 if (LIKELY(subscript.isUInt32())) {
2447 uint32_t i = subscript.asUInt32();
2448 if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2449 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2450 return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
2453 result = baseValue.get(callFrame, i);
2454 if (!isJSByteArray(globalData, baseValue))
2455 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
2457 Identifier property(callFrame, subscript.toString(callFrame));
2458 result = baseValue.get(callFrame, property);
2461 CHECK_FOR_EXCEPTION_AT_END();
2462 return JSValue::encode(result);
2465 DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub)
2467 STUB_INIT_STACK_FRAME(stackFrame);
2469 JSValue src1 = stackFrame.args[0].jsValue();
2470 JSValue src2 = stackFrame.args[1].jsValue();
2474 if (src1.getNumber(left) && src2.getNumber(right))
2475 return JSValue::encode(jsNumber(left - right));
2477 CallFrame* callFrame = stackFrame.callFrame;
2478 JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
2479 CHECK_FOR_EXCEPTION_AT_END();
2480 return JSValue::encode(result);
2483 DEFINE_STUB_FUNCTION(void, op_put_by_val)
2485 STUB_INIT_STACK_FRAME(stackFrame);
2487 CallFrame* callFrame = stackFrame.callFrame;
2488 JSGlobalData* globalData = stackFrame.globalData;
2490 JSValue baseValue = stackFrame.args[0].jsValue();
2491 JSValue subscript = stackFrame.args[1].jsValue();
2492 JSValue value = stackFrame.args[2].jsValue();
2494 if (LIKELY(subscript.isUInt32())) {
2495 uint32_t i = subscript.asUInt32();
2496 if (isJSArray(globalData, baseValue)) {
2497 JSArray* jsArray = asArray(baseValue);
2498 if (jsArray->canSetIndex(i))
2499 jsArray->setIndex(i, value);
2501 jsArray->JSArray::put(callFrame, i, value);
2502 } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2503 JSByteArray* jsByteArray = asByteArray(baseValue);
2504 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_byte_array));
2505 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2506 if (value.isInt32()) {
2507 jsByteArray->setIndex(i, value.asInt32());
2511 if (value.getNumber(dValue)) {
2512 jsByteArray->setIndex(i, dValue);
2517 baseValue.put(callFrame, i, value);
2519 baseValue.put(callFrame, i, value);
2521 Identifier property(callFrame, subscript.toString(callFrame));
2522 if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
2523 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
2524 baseValue.put(callFrame, property, value, slot);
2528 CHECK_FOR_EXCEPTION_AT_END();
2531 DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array)
2533 STUB_INIT_STACK_FRAME(stackFrame);
2535 CallFrame* callFrame = stackFrame.callFrame;
2536 JSGlobalData* globalData = stackFrame.globalData;
2538 JSValue baseValue = stackFrame.args[0].jsValue();
2539 JSValue subscript = stackFrame.args[1].jsValue();
2540 JSValue value = stackFrame.args[2].jsValue();
2542 if (LIKELY(subscript.isUInt32())) {
2543 uint32_t i = subscript.asUInt32();
2544 if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2545 JSByteArray* jsByteArray = asByteArray(baseValue);
2547 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2548 if (value.isInt32()) {
2549 jsByteArray->setIndex(i, value.asInt32());
2553 if (value.getNumber(dValue)) {
2554 jsByteArray->setIndex(i, dValue);
2560 if (!isJSByteArray(globalData, baseValue))
2561 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
2562 baseValue.put(callFrame, i, value);
2564 Identifier property(callFrame, subscript.toString(callFrame));
2565 if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
2566 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
2567 baseValue.put(callFrame, property, value, slot);
2571 CHECK_FOR_EXCEPTION_AT_END();
2574 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
2576 STUB_INIT_STACK_FRAME(stackFrame);
2578 CallFrame* callFrame = stackFrame.callFrame;
2579 JSValue result = jsBoolean(jsLessEq(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
2580 CHECK_FOR_EXCEPTION_AT_END();
2581 return JSValue::encode(result);
2584 DEFINE_STUB_FUNCTION(int, op_load_varargs)
2586 STUB_INIT_STACK_FRAME(stackFrame);
2588 CallFrame* callFrame = stackFrame.callFrame;
2589 RegisterFile* registerFile = stackFrame.registerFile;
2590 int argsOffset = stackFrame.args[0].int32();
2591 JSValue arguments = callFrame->registers()[argsOffset].jsValue();
2592 uint32_t argCount = 0;
2594 int providedParams = callFrame->registers()[RegisterFile::ArgumentCount].i() - 1;
2595 argCount = providedParams;
2596 argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
2597 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
2598 Register* newEnd = callFrame->registers() + sizeDelta;
2599 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
2600 stackFrame.globalData->exception = createStackOverflowError(callFrame);
2601 VM_THROW_EXCEPTION();
2603 int32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
2604 int32_t inplaceArgs = min(providedParams, expectedParams);
2606 Register* inplaceArgsDst = callFrame->registers() + argsOffset;
2608 Register* inplaceArgsEnd = inplaceArgsDst + inplaceArgs;
2609 Register* inplaceArgsEnd2 = inplaceArgsDst + providedParams;
2611 Register* inplaceArgsSrc = callFrame->registers() - RegisterFile::CallFrameHeaderSize - expectedParams;
2612 Register* inplaceArgsSrc2 = inplaceArgsSrc - providedParams - 1 + inplaceArgs;
2614 // First step is to copy the "expected" parameters from their normal location relative to the callframe
2615 while (inplaceArgsDst < inplaceArgsEnd)
2616 *inplaceArgsDst++ = *inplaceArgsSrc++;
2618 // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
2619 while (inplaceArgsDst < inplaceArgsEnd2)
2620 *inplaceArgsDst++ = *inplaceArgsSrc2++;
2622 } else if (!arguments.isUndefinedOrNull()) {
2623 if (!arguments.isObject()) {
2624 CodeBlock* codeBlock = callFrame->codeBlock();
2625 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
2626 stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
2627 VM_THROW_EXCEPTION();
2629 if (asObject(arguments)->classInfo() == &Arguments::info) {
2630 Arguments* argsObject = asArguments(arguments);
2631 argCount = argsObject->numProvidedArguments(callFrame);
2632 argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
2633 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
2634 Register* newEnd = callFrame->registers() + sizeDelta;
2635 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
2636 stackFrame.globalData->exception = createStackOverflowError(callFrame);
2637 VM_THROW_EXCEPTION();
2639 argsObject->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
2640 } else if (isJSArray(&callFrame->globalData(), arguments)) {
2641 JSArray* array = asArray(arguments);
2642 argCount = array->length();
2643 argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
2644 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
2645 Register* newEnd = callFrame->registers() + sizeDelta;
2646 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
2647 stackFrame.globalData->exception = createStackOverflowError(callFrame);
2648 VM_THROW_EXCEPTION();
2650 array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
2651 } else if (asObject(arguments)->inherits(&JSArray::info)) {
2652 JSObject* argObject = asObject(arguments);
2653 argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
2654 argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
2655 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
2656 Register* newEnd = callFrame->registers() + sizeDelta;
2657 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
2658 stackFrame.globalData->exception = createStackOverflowError(callFrame);
2659 VM_THROW_EXCEPTION();
2661 Register* argsBuffer = callFrame->registers() + argsOffset;
2662 for (unsigned i = 0; i < argCount; ++i) {
2663 argsBuffer[i] = asObject(arguments)->get(callFrame, i);
2664 CHECK_FOR_EXCEPTION();
2667 CodeBlock* codeBlock = callFrame->codeBlock();
2668 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
2669 stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
2670 VM_THROW_EXCEPTION();
2674 return argCount + 1;
2677 DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate)
2679 STUB_INIT_STACK_FRAME(stackFrame);
2681 JSValue src = stackFrame.args[0].jsValue();
2684 if (src.getNumber(v))
2685 return JSValue::encode(jsNumber(-v));
2687 CallFrame* callFrame = stackFrame.callFrame;
2688 JSValue result = jsNumber(-src.toNumber(callFrame));
2689 CHECK_FOR_EXCEPTION_AT_END();
2690 return JSValue::encode(result);
2693 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base)
2695 STUB_INIT_STACK_FRAME(stackFrame);
2697 return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain(), false));
2700 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base_strict_put)
2702 STUB_INIT_STACK_FRAME(stackFrame);
2703 JSValue base = JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain(), true);
2705 stackFrame.globalData->exception = createErrorForInvalidGlobalAssignment(stackFrame.callFrame, stackFrame.args[0].identifier().ustring());
2706 VM_THROW_EXCEPTION();
2708 return JSValue::encode(base);
2711 DEFINE_STUB_FUNCTION(EncodedJSValue, op_ensure_property_exists)
2713 STUB_INIT_STACK_FRAME(stackFrame);
2714 JSValue base = stackFrame.callFrame->r(stackFrame.args[0].int32()).jsValue();
2715 JSObject* object = asObject(base);
2716 PropertySlot slot(object);
2717 ASSERT(stackFrame.callFrame->codeBlock()->isStrictMode());
2718 if (!object->getPropertySlot(stackFrame.callFrame, stackFrame.args[1].identifier(), slot)) {
2719 stackFrame.globalData->exception = createErrorForInvalidGlobalAssignment(stackFrame.callFrame, stackFrame.args[1].identifier().ustring());
2720 VM_THROW_EXCEPTION();
2723 return JSValue::encode(base);
2726 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
2728 STUB_INIT_STACK_FRAME(stackFrame);
2730 CallFrame* callFrame = stackFrame.callFrame;
2731 ScopeChainNode* scopeChain = callFrame->scopeChain();
2733 int skip = stackFrame.args[1].int32();
2735 ScopeChainIterator iter = scopeChain->begin();
2736 ScopeChainIterator end = scopeChain->end();
2737 ASSERT(iter != end);
2738 CodeBlock* codeBlock = callFrame->codeBlock();
2739 bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
2740 ASSERT(skip || !checkTopLevel);
2741 if (checkTopLevel && skip--) {
2742 if (callFrame->r(codeBlock->activationRegister()).jsValue())
2747 ASSERT(iter != end);
2749 Identifier& ident = stackFrame.args[0].identifier();
2751 JSObject* o = *iter;
2752 PropertySlot slot(o);
2753 if (o->getPropertySlot(callFrame, ident, slot)) {
2754 JSValue result = slot.getValue(callFrame, ident);
2755 CHECK_FOR_EXCEPTION_AT_END();
2756 return JSValue::encode(result);
2758 } while (++iter != end);
2760 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
2761 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
2762 VM_THROW_EXCEPTION();
2765 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
2767 STUB_INIT_STACK_FRAME(stackFrame);
2769 CallFrame* callFrame = stackFrame.callFrame;
2770 CodeBlock* codeBlock = callFrame->codeBlock();
2771 JSGlobalObject* globalObject = codeBlock->globalObject();
2772 Identifier& ident = stackFrame.args[0].identifier();
2773 unsigned globalResolveInfoIndex = stackFrame.args[1].int32();
2774 ASSERT(globalObject->isGlobalObject());
2776 PropertySlot slot(globalObject);
2777 if (globalObject->getPropertySlot(callFrame, ident, slot)) {
2778 JSValue result = slot.getValue(callFrame, ident);
2779 if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
2780 GlobalResolveInfo& globalResolveInfo = codeBlock->globalResolveInfo(globalResolveInfoIndex);
2781 if (globalResolveInfo.structure)
2782 globalResolveInfo.structure->deref();
2783 globalObject->structure()->ref();
2784 globalResolveInfo.structure = globalObject->structure();
2785 globalResolveInfo.offset = slot.cachedOffset();
2786 return JSValue::encode(result);
2789 CHECK_FOR_EXCEPTION_AT_END();
2790 return JSValue::encode(result);
2793 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
2794 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
2795 VM_THROW_EXCEPTION();
2798 DEFINE_STUB_FUNCTION(EncodedJSValue, op_div)
2800 STUB_INIT_STACK_FRAME(stackFrame);
2802 JSValue src1 = stackFrame.args[0].jsValue();
2803 JSValue src2 = stackFrame.args[1].jsValue();
2807 if (src1.getNumber(left) && src2.getNumber(right))
2808 return JSValue::encode(jsNumber(left / right));
2810 CallFrame* callFrame = stackFrame.callFrame;
2811 JSValue result = jsNumber(src1.toNumber(callFrame) / src2.toNumber(callFrame));
2812 CHECK_FOR_EXCEPTION_AT_END();
2813 return JSValue::encode(result);
2816 DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_dec)
2818 STUB_INIT_STACK_FRAME(stackFrame);
2820 JSValue v = stackFrame.args[0].jsValue();
2822 CallFrame* callFrame = stackFrame.callFrame;
2823 JSValue result = jsNumber(v.toNumber(callFrame) - 1);
2824 CHECK_FOR_EXCEPTION_AT_END();
2825 return JSValue::encode(result);
2828 DEFINE_STUB_FUNCTION(int, op_jless)
2830 STUB_INIT_STACK_FRAME(stackFrame);
2832 JSValue src1 = stackFrame.args[0].jsValue();
2833 JSValue src2 = stackFrame.args[1].jsValue();
2834 CallFrame* callFrame = stackFrame.callFrame;
2836 bool result = jsLess(callFrame, src1, src2);
2837 CHECK_FOR_EXCEPTION_AT_END();
2841 DEFINE_STUB_FUNCTION(int, op_jlesseq)
2843 STUB_INIT_STACK_FRAME(stackFrame);
2845 JSValue src1 = stackFrame.args[0].jsValue();
2846 JSValue src2 = stackFrame.args[1].jsValue();
2847 CallFrame* callFrame = stackFrame.callFrame;
2849 bool result = jsLessEq(callFrame, src1, src2);
2850 CHECK_FOR_EXCEPTION_AT_END();
2854 DEFINE_STUB_FUNCTION(EncodedJSValue, op_not)
2856 STUB_INIT_STACK_FRAME(stackFrame);
2858 JSValue src = stackFrame.args[0].jsValue();
2860 CallFrame* callFrame = stackFrame.callFrame;
2862 JSValue result = jsBoolean(!src.toBoolean(callFrame));
2863 CHECK_FOR_EXCEPTION_AT_END();
2864 return JSValue::encode(result);
2867 DEFINE_STUB_FUNCTION(int, op_jtrue)
2869 STUB_INIT_STACK_FRAME(stackFrame);
2871 JSValue src1 = stackFrame.args[0].jsValue();
2873 CallFrame* callFrame = stackFrame.callFrame;
2875 bool result = src1.toBoolean(callFrame);
2876 CHECK_FOR_EXCEPTION_AT_END();
2880 DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_inc)
2882 STUB_INIT_STACK_FRAME(stackFrame);
2884 JSValue v = stackFrame.args[0].jsValue();
2886 CallFrame* callFrame = stackFrame.callFrame;
2888 JSValue number = v.toJSNumber(callFrame);
2889 CHECK_FOR_EXCEPTION_AT_END();
2891 callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number.uncheckedGetNumber() + 1);
2892 return JSValue::encode(number);
2895 DEFINE_STUB_FUNCTION(int, op_eq)
2897 STUB_INIT_STACK_FRAME(stackFrame);
2899 JSValue src1 = stackFrame.args[0].jsValue();
2900 JSValue src2 = stackFrame.args[1].jsValue();
2902 #if USE(JSVALUE32_64)
2904 if (src2.isUndefined()) {
2905 return src1.isNull() ||
2906 (src1.isCell() && src1.asCell()->structure()->typeInfo().masqueradesAsUndefined())
2907 || src1.isUndefined();
2910 if (src2.isNull()) {
2911 return src1.isUndefined() ||
2912 (src1.isCell() && src1.asCell()->structure()->typeInfo().masqueradesAsUndefined())
2916 if (src1.isInt32()) {
2917 if (src2.isDouble())
2918 return src1.asInt32() == src2.asDouble();
2919 double d = src2.toNumber(stackFrame.callFrame);
2920 CHECK_FOR_EXCEPTION();
2921 return src1.asInt32() == d;
2924 if (src1.isDouble()) {
2926 return src1.asDouble() == src2.asInt32();
2927 double d = src2.toNumber(stackFrame.callFrame);
2928 CHECK_FOR_EXCEPTION();
2929 return src1.asDouble() == d;
2932 if (src1.isTrue()) {
2935 double d = src2.toNumber(stackFrame.callFrame);
2936 CHECK_FOR_EXCEPTION();
2940 if (src1.isFalse()) {
2943 double d = src2.toNumber(stackFrame.callFrame);
2944 CHECK_FOR_EXCEPTION();
2948 if (src1.isUndefined())
2949 return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
2952 return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
2954 JSCell* cell1 = src1.asCell();
2956 if (cell1->isString()) {
2958 return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32();
2960 if (src2.isDouble())
2961 return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble();
2964 return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0;
2967 return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0;
2969 JSCell* cell2 = src2.asCell();
2970 if (cell2->isString())
2971 return static_cast<JSString*>(cell1)->value(stackFrame.callFrame) == static_cast<JSString*>(cell2)->value(stackFrame.callFrame);
2973 src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
2974 CHECK_FOR_EXCEPTION();
2978 if (src2.isObject())
2979 return asObject(cell1) == asObject(src2);
2980 src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame);
2981 CHECK_FOR_EXCEPTION();
2984 #else // USE(JSVALUE32_64)
2985 CallFrame* callFrame = stackFrame.callFrame;
2987 bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2);
2988 CHECK_FOR_EXCEPTION_AT_END();
2990 #endif // USE(JSVALUE32_64)
2993 DEFINE_STUB_FUNCTION(int, op_eq_strings)
2995 #if USE(JSVALUE32_64)
2996 STUB_INIT_STACK_FRAME(stackFrame);
2998 JSString* string1 = stackFrame.args[0].jsString();
2999 JSString* string2 = stackFrame.args[1].jsString();
3001 ASSERT(string1->isString());
3002 ASSERT(string2->isString());
3003 return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame);
3006 ASSERT_NOT_REACHED();
3011 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift)
3013 STUB_INIT_STACK_FRAME(stackFrame);
3015 JSValue val = stackFrame.args[0].jsValue();
3016 JSValue shift = stackFrame.args[1].jsValue();
3018 CallFrame* callFrame = stackFrame.callFrame;
3019 JSValue result = jsNumber((val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
3020 CHECK_FOR_EXCEPTION_AT_END();
3021 return JSValue::encode(result);
3024 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitand)
3026 STUB_INIT_STACK_FRAME(stackFrame);
3028 JSValue src1 = stackFrame.args[0].jsValue();
3029 JSValue src2 = stackFrame.args[1].jsValue();
3031 ASSERT(!src1.isInt32() || !src2.isInt32());
3032 CallFrame* callFrame = stackFrame.callFrame;
3033 JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame));
3034 CHECK_FOR_EXCEPTION_AT_END();
3035 return JSValue::encode(result);
3038 DEFINE_STUB_FUNCTION(EncodedJSValue, op_rshift)
3040 STUB_INIT_STACK_FRAME(stackFrame);
3042 JSValue val = stackFrame.args[0].jsValue();
3043 JSValue shift = stackFrame.args[1].jsValue();
3045 CallFrame* callFrame = stackFrame.callFrame;
3046 JSValue result = jsNumber((val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
3048 CHECK_FOR_EXCEPTION_AT_END();
3049 return JSValue::encode(result);
3052 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitnot)
3054 STUB_INIT_STACK_FRAME(stackFrame);
3056 JSValue src = stackFrame.args[0].jsValue();
3058 ASSERT(!src.isInt32());
3059 CallFrame* callFrame = stackFrame.callFrame;
3060 JSValue result = jsNumber(~src.toInt32(callFrame));
3061 CHECK_FOR_EXCEPTION_AT_END();
3062 return JSValue::encode(result);
3065 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base)
3067 STUB_INIT_STACK_FRAME(stackFrame);
3069 CallFrame* callFrame = stackFrame.callFrame;
3070 ScopeChainNode* scopeChain = callFrame->scopeChain();
3072 ScopeChainIterator iter = scopeChain->begin();
3073 ScopeChainIterator end = scopeChain->end();
3075 // FIXME: add scopeDepthIsZero optimization
3077 ASSERT(iter != end);
3079 Identifier& ident = stackFrame.args[0].identifier();
3083 PropertySlot slot(base);
3084 if (base->getPropertySlot(callFrame, ident, slot)) {
3085 JSValue result = slot.getValue(callFrame, ident);
3086 CHECK_FOR_EXCEPTION_AT_END();
3088 callFrame->registers()[stackFrame.args[1].int32()] = JSValue(base);
3089 return JSValue::encode(result);
3092 } while (iter != end);
3094 CodeBlock* codeBlock = callFrame->codeBlock();
3095 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
3096 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
3097 VM_THROW_EXCEPTION_AT_END();
3098 return JSValue::encode(JSValue());
3101 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
3103 STUB_INIT_STACK_FRAME(stackFrame);
3104 CallFrame* callFrame = stackFrame.callFrame;
3106 FunctionExecutable* function = stackFrame.args[0].function();
3107 JSFunction* func = function->make(callFrame, callFrame->scopeChain());
3108 ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->r(callFrame->codeBlock()->activationRegister()).jsValue());
3111 The Identifier in a FunctionExpression can be referenced from inside
3112 the FunctionExpression's FunctionBody to allow the function to call
3113 itself recursively. However, unlike in a FunctionDeclaration, the
3114 Identifier in a FunctionExpression cannot be referenced from and
3115 does not affect the scope enclosing the FunctionExpression.
3117 if (!function->name().isNull()) {
3118 JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
3119 func->scope().push(functionScopeObject);
3125 DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod)
3127 STUB_INIT_STACK_FRAME(stackFrame);
3129 JSValue dividendValue = stackFrame.args[0].jsValue();
3130 JSValue divisorValue = stackFrame.args[1].jsValue();
3132 CallFrame* callFrame = stackFrame.callFrame;
3133 double d = dividendValue.toNumber(callFrame);
3134 JSValue result = jsNumber(fmod(d, divisorValue.toNumber(callFrame)));
3135 CHECK_FOR_EXCEPTION_AT_END();
3136 return JSValue::encode(result);
3139 DEFINE_STUB_FUNCTION(EncodedJSValue, op_less)
3141 STUB_INIT_STACK_FRAME(stackFrame);
3143 CallFrame* callFrame = stackFrame.callFrame;
3144 JSValue result = jsBoolean(jsLess(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
3145 CHECK_FOR_EXCEPTION_AT_END();
3146 return JSValue::encode(result);
3149 DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_dec)
3151 STUB_INIT_STACK_FRAME(stackFrame);
3153 JSValue v = stackFrame.args[0].jsValue();
3155 CallFrame* callFrame = stackFrame.callFrame;
3157 JSValue number = v.toJSNumber(callFrame);
3158 CHECK_FOR_EXCEPTION_AT_END();
3160 callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number.uncheckedGetNumber() - 1);
3161 return JSValue::encode(number);
3164 DEFINE_STUB_FUNCTION(EncodedJSValue, op_urshift)
3166 STUB_INIT_STACK_FRAME(stackFrame);
3168 JSValue val = stackFrame.args[0].jsValue();
3169 JSValue shift = stackFrame.args[1].jsValue();
3171 CallFrame* callFrame = stackFrame.callFrame;
3172 JSValue result = jsNumber((val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
3173 CHECK_FOR_EXCEPTION_AT_END();
3174 return JSValue::encode(result);
3177 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitxor)
3179 STUB_INIT_STACK_FRAME(stackFrame);
3181 JSValue src1 = stackFrame.args[0].jsValue();
3182 JSValue src2 = stackFrame.args[1].jsValue();
3184 CallFrame* callFrame = stackFrame.callFrame;
3186 JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
3187 CHECK_FOR_EXCEPTION_AT_END();
3188 return JSValue::encode(result);
3191 DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp)
3193 STUB_INIT_STACK_FRAME(stackFrame);
3195 return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), stackFrame.args[0].regExp());
3198 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
3200 STUB_INIT_STACK_FRAME(stackFrame);
3202 JSValue src1 = stackFrame.args[0].jsValue();
3203 JSValue src2 = stackFrame.args[1].jsValue();
3205 CallFrame* callFrame = stackFrame.callFrame;
3207 JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame));
3208 CHECK_FOR_EXCEPTION_AT_END();
3209 return JSValue::encode(result);
3212 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
3214 STUB_INIT_STACK_FRAME(stackFrame);
3215 ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->r(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
3217 CallFrame* callFrame = stackFrame.callFrame;
3218 RegisterFile* registerFile = stackFrame.registerFile;
3220 Interpreter* interpreter = stackFrame.globalData->interpreter;
3222 JSValue funcVal = stackFrame.args[0].jsValue();
3223 int registerOffset = stackFrame.args[1].int32();
3224 int argCount = stackFrame.args[2].int32();
3226 Register* newCallFrame = callFrame->registers() + registerOffset;
3227 Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
3228 JSValue baseValue = argv[0].jsValue();
3229 JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
3231 if (baseValue == globalObject && funcVal == globalObject->evalFunction()) {
3232 JSValue result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset);
3233 CHECK_FOR_EXCEPTION_AT_END();
3234 return JSValue::encode(result);
3237 return JSValue::encode(JSValue());
3240 DEFINE_STUB_FUNCTION(void*, op_throw)
3242 STUB_INIT_STACK_FRAME(stackFrame);
3243 ExceptionHandler handler = jitThrow(stackFrame.globalData, stackFrame.callFrame, stackFrame.args[0].jsValue(), STUB_RETURN_ADDRESS, true);
3244 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
3245 return handler.callFrame;
3248 DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
3250 STUB_INIT_STACK_FRAME(stackFrame);
3252 CallFrame* callFrame = stackFrame.callFrame;
3253 JSObject* o = stackFrame.args[0].jsObject();
3254 Structure* structure = o->structure();
3255 JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
3256 if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
3257 jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
3258 return jsPropertyNameIterator;
3261 DEFINE_STUB_FUNCTION(int, has_property)
3263 STUB_INIT_STACK_FRAME(stackFrame);
3265 JSObject* base = stackFrame.args[0].jsObject();
3266 JSString* property = stackFrame.args[1].jsString();
3267 int result = base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame)));
3268 CHECK_FOR_EXCEPTION_AT_END();
3272 DEFINE_STUB_FUNCTION(JSObject*, op_push_scope)
3274 STUB_INIT_STACK_FRAME(stackFrame);
3276 JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame);
3277 CHECK_FOR_EXCEPTION();
3278 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(o));
3282 DEFINE_STUB_FUNCTION(void, op_pop_scope)
3284 STUB_INIT_STACK_FRAME(stackFrame);
3286 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->pop());
3289 DEFINE_STUB_FUNCTION(EncodedJSValue, op_typeof)
3291 STUB_INIT_STACK_FRAME(stackFrame);
3293 return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue()));
3296 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_undefined)
3298 STUB_INIT_STACK_FRAME(stackFrame);
3300 JSValue v = stackFrame.args[0].jsValue();
3301 return JSValue::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
3304 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_boolean)
3306 STUB_INIT_STACK_FRAME(stackFrame);
3308 return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isBoolean()));
3311 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_number)
3313 STUB_INIT_STACK_FRAME(stackFrame);
3315 return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isNumber()));
3318 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_string)
3320 STUB_INIT_STACK_FRAME(stackFrame);
3322 return JSValue::encode(jsBoolean(isJSString(stackFrame.globalData, stackFrame.args[0].jsValue())));
3325 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object)
3327 STUB_INIT_STACK_FRAME(stackFrame);
3329 return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame.args[0].jsValue())));
3332 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_function)
3334 STUB_INIT_STACK_FRAME(stackFrame);
3336 return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame.args[0].jsValue())));
3339 DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq)
3341 STUB_INIT_STACK_FRAME(stackFrame);
3343 JSValue src1 = stackFrame.args[0].jsValue();
3344 JSValue src2 = stackFrame.args[1].jsValue();
3346 bool result = JSValue::strictEqual(stackFrame.callFrame, src1, src2);
3347 CHECK_FOR_EXCEPTION_AT_END();
3348 return JSValue::encode(jsBoolean(result));
3351 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive)
3353 STUB_INIT_STACK_FRAME(stackFrame);
3355 return JSValue::encode(stackFrame.args[0].jsValue().toPrimitive(stackFrame.callFrame));
3358 DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat)
3360 STUB_INIT_STACK_FRAME(stackFrame);
3362 JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
3363 CHECK_FOR_EXCEPTION_AT_END();
3364 return JSValue::encode(result);
3367 DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq)
3369 STUB_INIT_STACK_FRAME(stackFrame);
3371 JSValue src1 = stackFrame.args[0].jsValue();
3372 JSValue src2 = stackFrame.args[1].jsValue();
3374 bool result = !JSValue::strictEqual(stackFrame.callFrame, src1, src2);
3375 CHECK_FOR_EXCEPTION_AT_END();
3376 return JSValue::encode(jsBoolean(result));
3379 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber)
3381 STUB_INIT_STACK_FRAME(stackFrame);
3383 JSValue src = stackFrame.args[0].jsValue();
3384 CallFrame* callFrame = stackFrame.callFrame;
3386 JSValue result = src.toJSNumber(callFrame);
3387 CHECK_FOR_EXCEPTION_AT_END();
3388 return JSValue::encode(result);
3391 DEFINE_STUB_FUNCTION(EncodedJSValue, op_in)
3393 STUB_INIT_STACK_FRAME(stackFrame);
3395 CallFrame* callFrame = stackFrame.callFrame;
3396 JSValue baseVal = stackFrame.args[1].jsValue();
3398 if (!baseVal.isObject()) {
3399 CallFrame* callFrame = stackFrame.callFrame;
3400 CodeBlock* codeBlock = callFrame->codeBlock();
3401 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
3402 stackFrame.globalData->exception = createInvalidParamError(callFrame, "in", baseVal, vPCIndex, codeBlock);
3403 VM_THROW_EXCEPTION();
3406 JSValue propName = stackFrame.args[0].jsValue();
3407 JSObject* baseObj = asObject(baseVal);
3410 if (propName.getUInt32(i))
3411 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
3413 Identifier property(callFrame, propName.toString(callFrame));
3414 CHECK_FOR_EXCEPTION();
3415 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
3418 DEFINE_STUB_FUNCTION(JSObject*, op_push_new_scope)
3420 STUB_INIT_STACK_FRAME(stackFrame);
3422 JSObject* scope = new (stackFrame.globalData) JSStaticScopeObject(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), DontDelete);
3424 CallFrame* callFrame = stackFrame.callFrame;
3425 callFrame->setScopeChain(callFrame->scopeChain()->push(scope));
3429 DEFINE_STUB_FUNCTION(void, op_jmp_scopes)
3431 STUB_INIT_STACK_FRAME(stackFrame);
3433 unsigned count = stackFrame.args[0].int32();
3434 CallFrame* callFrame = stackFrame.callFrame;
3436 ScopeChainNode* tmp = callFrame->scopeChain();
3439 callFrame->setScopeChain(tmp);
3442 DEFINE_STUB_FUNCTION(void, op_put_by_index)
3444 STUB_INIT_STACK_FRAME(stackFrame);
3446 CallFrame* callFrame = stackFrame.callFrame;
3447 unsigned property = stackFrame.args[1].int32();
3449 stackFrame.args[0].jsValue().put(callFrame, property, stackFrame.args[2].jsValue());
3452 DEFINE_STUB_FUNCTION(void*, op_switch_imm)
3454 STUB_INIT_STACK_FRAME(stackFrame);
3456 JSValue scrutinee = stackFrame.args[0].jsValue();
3457 unsigned tableIndex = stackFrame.args[1].int32();
3458 CallFrame* callFrame = stackFrame.callFrame;
3459 CodeBlock* codeBlock = callFrame->codeBlock();
3461 if (scrutinee.isInt32())
3462 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
3466 if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
3467 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(intValue).executableAddress();
3469 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
3473 DEFINE_STUB_FUNCTION(void*, op_switch_char)
3475 STUB_INIT_STACK_FRAME(stackFrame);
3477 JSValue scrutinee = stackFrame.args[0].jsValue();
3478 unsigned tableIndex = stackFrame.args[1].int32();
3479 CallFrame* callFrame = stackFrame.callFrame;
3480 CodeBlock* codeBlock = callFrame->codeBlock();
3482 void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
3484 if (scrutinee.isString()) {
3485 StringImpl* value = asString(scrutinee)->value(callFrame).impl();
3486 if (value->length() == 1)
3487 result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->characters()[0]).executableAddress();
3490 CHECK_FOR_EXCEPTION_AT_END();
3494 DEFINE_STUB_FUNCTION(void*, op_switch_string)
3496 STUB_INIT_STACK_FRAME(stackFrame);
3498 JSValue scrutinee = stackFrame.args[0].jsValue();
3499 unsigned tableIndex = stackFrame.args[1].int32();
3500 CallFrame* callFrame = stackFrame.callFrame;
3501 CodeBlock* codeBlock = callFrame->codeBlock();
3503 void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
3505 if (scrutinee.isString()) {
3506 StringImpl* value = asString(scrutinee)->value(callFrame).impl();
3507 result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
3510 CHECK_FOR_EXCEPTION_AT_END();
3514 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val)
3516 STUB_INIT_STACK_FRAME(stackFrame);
3518 CallFrame* callFrame = stackFrame.callFrame;
3520 JSValue baseValue = stackFrame.args[0].jsValue();
3521 JSObject* baseObj = baseValue.toObject(callFrame); // may throw
3523 JSValue subscript = stackFrame.args[1].jsValue();
3526 if (subscript.getUInt32(i))
3527 result = baseObj->deleteProperty(callFrame, i);
3529 CHECK_FOR_EXCEPTION();
3530 Identifier property(callFrame, subscript.toString(callFrame));
3531 CHECK_FOR_EXCEPTION();
3532 result = baseObj->deleteProperty(callFrame, property);
3535 if (!result && callFrame->codeBlock()->isStrictMode())
3536 stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
3538 CHECK_FOR_EXCEPTION_AT_END();
3539 return JSValue::encode(jsBoolean(result));
3542 DEFINE_STUB_FUNCTION(void, op_put_getter)
3544 STUB_INIT_STACK_FRAME(stackFrame);
3546 CallFrame* callFrame = stackFrame.callFrame;
3548 ASSERT(stackFrame.args[0].jsValue().isObject());
3549 JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
3550 ASSERT(stackFrame.args[2].jsValue().isObject());
3551 baseObj->defineGetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
3554 DEFINE_STUB_FUNCTION(void, op_put_setter)
3556 STUB_INIT_STACK_FRAME(stackFrame);
3558 CallFrame* callFrame = stackFrame.callFrame;
3560 ASSERT(stackFrame.args[0].jsValue().isObject());
3561 JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
3562 ASSERT(stackFrame.args[2].jsValue().isObject());
3563 baseObj->defineSetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
3566 DEFINE_STUB_FUNCTION(JSObject*, op_new_error)
3568 STUB_INIT_STACK_FRAME(stackFrame);
3570 CallFrame* callFrame = stackFrame.callFrame;
3571 CodeBlock* codeBlock = callFrame->codeBlock();
3572 unsigned isReference = stackFrame.args[0].int32();
3573 UString message = stackFrame.args[1].jsValue().toString(callFrame);
3574 unsigned bytecodeOffset = stackFrame.args[2].int32();
3576 JSObject* error = isReference ? createReferenceError(callFrame, message) : createSyntaxError(callFrame, message);
3577 unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
3578 return addErrorInfo(stackFrame.globalData, error, lineNumber, codeBlock->ownerExecutable()->source());
3581 DEFINE_STUB_FUNCTION(void, op_debug)
3583 STUB_INIT_STACK_FRAME(stackFrame);
3585 CallFrame* callFrame = stackFrame.callFrame;
3587 int debugHookID = stackFrame.args[0].int32();
3588 int firstLine = stackFrame.args[1].int32();
3589 int lastLine = stackFrame.args[2].int32();
3591 stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
3594 DEFINE_STUB_FUNCTION(void*, vm_throw)
3596 STUB_INIT_STACK_FRAME(stackFrame);
3597 JSGlobalData* globalData = stackFrame.globalData;
3598 ExceptionHandler handler = jitThrow(globalData, stackFrame.callFrame, globalData->exception, globalData->exceptionLocation, false);
3599 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
3600 return handler.callFrame;
3603 DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
3605 STUB_INIT_STACK_FRAME(stackFrame);
3607 CallFrame* callFrame = stackFrame.callFrame;
3608 return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
3611 MacroAssemblerCodePtr JITThunks::ctiStub(JSGlobalData* globalData, ThunkGenerator generator)
3613 std::pair<CTIStubMap::iterator, bool> entry = m_ctiStubMap.add(generator, MacroAssemblerCodePtr());
3615 entry.first->second = generator(globalData, m_executablePool.get());
3616 return entry.first->second;
3619 PassRefPtr<NativeExecutable> JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function)
3621 std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap.add(function, 0);
3623 entry.first->second = NativeExecutable::create(JIT::compileCTINativeCall(globalData, m_executablePool, function), function, ctiNativeConstruct(), callHostFunctionAsConstructor);
3624 return entry.first->second;
3627 PassRefPtr<NativeExecutable> JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator)
3629 std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap.add(function, 0);
3631 MacroAssemblerCodePtr code = globalData->canUseJIT() ? generator(globalData, m_executablePool.get()) : MacroAssemblerCodePtr();
3632 entry.first->second = NativeExecutable::create(code, function, ctiNativeConstruct(), callHostFunctionAsConstructor);
3634 return entry.first->second;
3639 #endif // ENABLE(JIT)