2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "Arguments.h"
36 #include "CallFrame.h"
37 #include "CodeBlock.h"
38 #include "Collector.h"
40 #include "ExceptionHelpers.h"
41 #include "GetterSetter.h"
42 #include "GlobalEvalFunction.h"
44 #include "JSActivation.h"
46 #include "JSByteArray.h"
47 #include "JSFunction.h"
48 #include "JSNotAnObject.h"
49 #include "JSPropertyNameIterator.h"
50 #include "JSStaticScopeObject.h"
52 #include "ObjectPrototype.h"
53 #include "Operations.h"
56 #include "RegExpObject.h"
57 #include "RegExpPrototype.h"
59 #include "SamplingTool.h"
60 #include <wtf/StdLibExtras.h>
68 #if OS(DARWIN) || OS(WINDOWS)
69 #define SYMBOL_STRING(name) "_" #name
71 #define SYMBOL_STRING(name) #name
75 #define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name)
77 #define THUMB_FUNC_PARAM(name)
80 #if OS(LINUX) && CPU(X86_64)
81 #define SYMBOL_STRING_RELOCATION(name) #name "@plt"
83 #define SYMBOL_STRING_RELOCATION(name) SYMBOL_STRING(name)
88 #define HIDE_SYMBOL(name) ".private_extern _" #name
90 // IBM's own file format
91 #define HIDE_SYMBOL(name) ".lglobl " #name
96 || (OS(HPUX) && CPU(IA64)) \
100 #define HIDE_SYMBOL(name) ".hidden " #name
102 #define HIDE_SYMBOL(name)
105 #if USE(JSVALUE32_64)
107 #if COMPILER(GCC) && CPU(X86)
109 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
110 // need to change the assembly trampolines below to match.
111 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment
);
112 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
113 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
114 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline
);
118 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
119 HIDE_SYMBOL(ctiTrampoline
) "\n"
120 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
122 "movl %esp, %ebp" "\n"
126 "subl $0x3c, %esp" "\n"
127 "movl $512, %esi" "\n"
128 "movl 0x58(%esp), %edi" "\n"
129 "call *0x50(%esp)" "\n"
130 "addl $0x3c, %esp" "\n"
139 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
140 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
141 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
142 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
143 "movl %esp, %ecx" "\n"
145 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
146 "addl $0x3c, %esp" "\n"
155 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
156 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
157 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
158 "addl $0x3c, %esp" "\n"
166 #elif COMPILER(GCC) && CPU(X86_64)
168 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
169 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
172 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
173 // need to change the assembly trampolines below to match.
174 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment
);
175 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedRBX
) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
176 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
177 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline
);
180 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
181 HIDE_SYMBOL(ctiTrampoline
) "\n"
182 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
184 "movq %rsp, %rbp" "\n"
190 "subq $0x48, %rsp" "\n"
191 "movq $512, %r12" "\n"
192 "movq $0xFFFF000000000000, %r14" "\n"
193 "movq $0xFFFF000000000002, %r15" "\n"
194 "movq 0x90(%rsp), %r13" "\n"
195 "call *0x80(%rsp)" "\n"
196 "addq $0x48, %rsp" "\n"
207 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
208 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
209 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
210 "movq %rsp, %rdi" "\n"
211 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
212 "addq $0x48, %rsp" "\n"
223 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
224 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
225 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
226 "addq $0x48, %rsp" "\n"
236 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
238 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
239 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
242 #define THUNK_RETURN_ADDRESS_OFFSET 0x3C
243 #define PRESERVED_RETURN_ADDRESS_OFFSET 0x40
244 #define PRESERVED_R4_OFFSET 0x44
245 #define PRESERVED_R5_OFFSET 0x48
246 #define PRESERVED_R6_OFFSET 0x4C
247 #define REGISTER_FILE_OFFSET 0x50
248 #define CALLFRAME_OFFSET 0x54
249 #define EXCEPTION_OFFSET 0x58
250 #define ENABLE_PROFILER_REFERENCE_OFFSET 0x60
252 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
254 #define THUNK_RETURN_ADDRESS_OFFSET 64
255 #define PRESERVEDR4_OFFSET 68
257 #elif COMPILER(MSVC) && CPU(X86)
259 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
260 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
263 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
264 // need to change the assembly trampolines below to match.
265 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment
);
266 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
267 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
268 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline
);
272 __declspec(naked
) EncodedJSValue
ctiTrampoline(void* code
, RegisterFile
*, CallFrame
*, JSValue
* exception
, Profiler
**, JSGlobalData
*)
283 mov edi
, [esp
+ 0x58];
294 __declspec(naked
) void ctiVMThrowTrampoline()
308 __declspec(naked
) void ctiOpThrowNotCaught()
322 #error "JIT not supported on this platform."
325 #else // USE(JSVALUE32_64)
327 #if COMPILER(GCC) && CPU(X86)
329 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
330 // need to change the assembly trampolines below to match.
331 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
332 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline
);
333 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
337 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
338 HIDE_SYMBOL(ctiTrampoline
) "\n"
339 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
341 "movl %esp, %ebp" "\n"
345 "subl $0x1c, %esp" "\n"
346 "movl $512, %esi" "\n"
347 "movl 0x38(%esp), %edi" "\n"
348 "call *0x30(%esp)" "\n"
349 "addl $0x1c, %esp" "\n"
358 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
359 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
360 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
361 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
362 "movl %esp, %ecx" "\n"
364 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
365 "addl $0x1c, %esp" "\n"
374 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
375 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
376 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
377 "addl $0x1c, %esp" "\n"
385 #elif COMPILER(GCC) && CPU(X86_64)
387 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
388 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
391 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
392 // need to change the assembly trampolines below to match.
393 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
394 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline
);
395 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedRBX
) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
399 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
400 HIDE_SYMBOL(ctiTrampoline
) "\n"
401 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
403 "movq %rsp, %rbp" "\n"
409 // Form the JIT stubs area
416 "subq $0x48, %rsp" "\n"
417 "movq $512, %r12" "\n"
418 "movq $0xFFFF000000000000, %r14" "\n"
419 "movq $0xFFFF000000000002, %r15" "\n"
420 "movq %rdx, %r13" "\n"
422 "addq $0x78, %rsp" "\n"
433 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
434 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
435 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
436 "movq %rsp, %rdi" "\n"
437 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
438 "addq $0x78, %rsp" "\n"
449 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
450 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
451 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
452 "addq $0x78, %rsp" "\n"
462 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
464 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
465 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
468 #define THUNK_RETURN_ADDRESS_OFFSET 0x1C
469 #define PRESERVED_RETURN_ADDRESS_OFFSET 0x20
470 #define PRESERVED_R4_OFFSET 0x24
471 #define PRESERVED_R5_OFFSET 0x28
472 #define PRESERVED_R6_OFFSET 0x2C
473 #define REGISTER_FILE_OFFSET 0x30
474 #define CALLFRAME_OFFSET 0x34
475 #define EXCEPTION_OFFSET 0x38
476 #define ENABLE_PROFILER_REFERENCE_OFFSET 0x40
478 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
480 #define THUNK_RETURN_ADDRESS_OFFSET 32
481 #define PRESERVEDR4_OFFSET 36
485 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
486 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on MIPS."
492 ".set noreorder" "\n"
495 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
496 ".ent " SYMBOL_STRING(ctiTrampoline
) "\n"
497 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
498 "addiu $29,$29,-72" "\n"
499 "sw $31,44($29)" "\n"
500 "sw $18,40($29)" "\n"
501 "sw $17,36($29)" "\n"
502 "sw $16,32($29)" "\n"
504 "sw $28,28($29)" "\n"
506 "move $16,$6 # set callFrameRegister" "\n"
507 "li $17,512 # set timeoutCheckRegister" "\n"
508 "move $25,$4 # move executableAddress to t9" "\n"
509 "sw $5,52($29) # store registerFile to current stack" "\n"
510 "sw $6,56($29) # store callFrame to curent stack" "\n"
511 "sw $7,60($29) # store exception to current stack" "\n"
512 "lw $8,88($29) # load enableProfilerReference from previous stack" "\n"
513 "lw $9,92($29) # load globalData from previous stack" "\n"
514 "sw $8,64($29) # store enableProfilerReference to current stack" "\n"
516 "sw $9,68($29) # store globalData to current stack" "\n"
517 "lw $16,32($29)" "\n"
518 "lw $17,36($29)" "\n"
519 "lw $18,40($29)" "\n"
520 "lw $31,44($29)" "\n"
522 "addiu $29,$29,72" "\n"
525 ".end " SYMBOL_STRING(ctiTrampoline
) "\n"
531 ".set noreorder" "\n"
534 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
535 ".ent " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
536 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
538 "lw $28,28($29)" "\n"
540 "la $25," SYMBOL_STRING(cti_vm_throw
) "\n"
542 "bal " SYMBOL_STRING(cti_vm_throw
) "\n"
545 "jal " SYMBOL_STRING(cti_vm_throw
) "\n"
548 "lw $16,32($29)" "\n"
549 "lw $17,36($29)" "\n"
550 "lw $18,40($29)" "\n"
551 "lw $31,44($29)" "\n"
553 "addiu $29,$29,72" "\n"
556 ".end " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
562 ".set noreorder" "\n"
565 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
566 ".ent " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
567 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
568 "lw $16,32($29)" "\n"
569 "lw $17,36($29)" "\n"
570 "lw $18,40($29)" "\n"
571 "lw $31,44($29)" "\n"
573 "addiu $29,$29,72" "\n"
576 ".end " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
579 #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
581 #define THUNK_RETURN_ADDRESS_OFFSET 32
582 #define PRESERVEDR4_OFFSET 36
584 __asm EncodedJSValue
ctiTrampoline(void*, RegisterFile
*, CallFrame
*, JSValue
*, Profiler
**, JSGlobalData
*)
588 stmdb sp
!, {r4
-r8
, lr
}
595 ldmia sp
!, {r4
-r8
, lr
}
600 __asm
void ctiVMThrowTrampoline()
607 ldmia sp
!, {r4
-r8
, lr
}
612 __asm
void ctiOpThrowNotCaught()
616 ldmia sp
!, {r4
-r8
, lr
}
621 #elif COMPILER(MSVC) && CPU(X86)
623 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
624 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
627 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
628 // need to change the assembly trampolines below to match.
629 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
630 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline
);
631 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
635 __declspec(naked
) EncodedJSValue
ctiTrampoline(void* code
, RegisterFile
*, CallFrame
*, JSValue
* exception
, Profiler
**, JSGlobalData
*)
646 mov edi
, [esp
+ 0x38];
657 __declspec(naked
) void ctiVMThrowTrampoline()
671 __declspec(naked
) void ctiOpThrowNotCaught()
685 #error "JIT not supported on this platform."
688 #endif // USE(JSVALUE32_64)
690 #if COMPILER(GCC) && CPU(ARM_THUMB2)
695 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
696 HIDE_SYMBOL(ctiTrampoline
) "\n"
698 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline
) "\n"
699 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
700 "sub sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET
) "\n"
701 "str lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "]" "\n"
702 "str r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET
) "]" "\n"
703 "str r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET
) "]" "\n"
704 "str r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET
) "]" "\n"
705 "str r1, [sp, #" STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET
) "]" "\n"
706 "str r2, [sp, #" STRINGIZE_VALUE_OF(CALLFRAME_OFFSET
) "]" "\n"
707 "str r3, [sp, #" STRINGIZE_VALUE_OF(EXCEPTION_OFFSET
) "]" "\n"
711 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET
) "]" "\n"
712 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET
) "]" "\n"
713 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET
) "]" "\n"
714 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "]" "\n"
715 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET
) "\n"
722 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
723 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
725 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline
) "\n"
726 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
728 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
729 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET
) "]" "\n"
730 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET
) "]" "\n"
731 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET
) "]" "\n"
732 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "]" "\n"
733 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET
) "\n"
740 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
741 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
743 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught
) "\n"
744 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
745 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET
) "]" "\n"
746 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET
) "]" "\n"
747 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET
) "]" "\n"
748 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET
) "]" "\n"
749 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET
) "\n"
753 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
756 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
757 HIDE_SYMBOL(ctiTrampoline
) "\n"
758 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
759 "stmdb sp!, {r1-r3}" "\n"
760 "stmdb sp!, {r4-r8, lr}" "\n"
761 "sub sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET
) "\n"
764 // r0 contains the code
767 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET
) "\n"
768 "ldmia sp!, {r4-r8, lr}" "\n"
769 "add sp, sp, #12" "\n"
774 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
775 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
776 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
778 "bl " SYMBOL_STRING(cti_vm_throw
) "\n"
780 // Both has the same return sequence
781 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
782 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
783 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
784 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET
) "\n"
785 "ldmia sp!, {r4-r8, lr}" "\n"
786 "add sp, sp, #12" "\n"
792 #if ENABLE(OPCODE_SAMPLING)
793 #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler()
795 #define CTI_SAMPLER 0
798 JITThunks::JITThunks(JSGlobalData
* globalData
)
800 JIT::compileCTIMachineTrampolines(globalData
, &m_executablePool
, &m_trampolineStructure
);
803 // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
804 // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
806 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedReturnAddress
) == PRESERVED_RETURN_ADDRESS_OFFSET
);
807 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR4
) == PRESERVED_R4_OFFSET
);
808 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR5
) == PRESERVED_R5_OFFSET
);
809 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR6
) == PRESERVED_R6_OFFSET
);
811 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, registerFile
) == REGISTER_FILE_OFFSET
);
812 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, callFrame
) == CALLFRAME_OFFSET
);
813 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, exception
) == EXCEPTION_OFFSET
);
814 // The fifth argument is the first item already on the stack.
815 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, enabledProfilerReference
) == ENABLE_PROFILER_REFERENCE_OFFSET
);
817 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, thunkReturnAddress
) == THUNK_RETURN_ADDRESS_OFFSET
);
819 #elif CPU(ARM_TRADITIONAL)
821 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, thunkReturnAddress
) == THUNK_RETURN_ADDRESS_OFFSET
);
822 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR4
) == PRESERVEDR4_OFFSET
);
826 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedGP
) == 28);
827 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedS0
) == 32);
828 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedS1
) == 36);
829 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedS2
) == 40);
830 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedReturnAddress
) == 44);
831 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, thunkReturnAddress
) == 48);
832 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, registerFile
) == 52);
833 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, callFrame
) == 56);
834 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, exception
) == 60);
835 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, enabledProfilerReference
) == 64);
836 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, globalData
) == 68);
841 JITThunks::~JITThunks()
845 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
847 NEVER_INLINE
void JITThunks::tryCachePutByID(CallFrame
* callFrame
, CodeBlock
* codeBlock
, ReturnAddressPtr returnAddress
, JSValue baseValue
, const PutPropertySlot
& slot
, StructureStubInfo
* stubInfo
, bool direct
)
849 // The interpreter checks for recursion here; I do not believe this can occur in CTI.
851 if (!baseValue
.isCell())
854 // Uncacheable: give up.
855 if (!slot
.isCacheable()) {
856 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(direct
? cti_op_put_by_id_direct_generic
: cti_op_put_by_id_generic
));
860 JSCell
* baseCell
= asCell(baseValue
);
861 Structure
* structure
= baseCell
->structure();
863 if (structure
->isUncacheableDictionary()) {
864 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(direct
? cti_op_put_by_id_direct_generic
: cti_op_put_by_id_generic
));
868 // If baseCell != base, then baseCell must be a proxy for another object.
869 if (baseCell
!= slot
.base()) {
870 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(direct
? cti_op_put_by_id_direct_generic
: cti_op_put_by_id_generic
));
874 // Cache hit: Specialize instruction and ref Structures.
876 // Structure transition, cache transition info
877 if (slot
.type() == PutPropertySlot::NewProperty
) {
878 if (structure
->isDictionary()) {
879 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(direct
? cti_op_put_by_id_direct_generic
: cti_op_put_by_id_generic
));
883 // put_by_id_transition checks the prototype chain for setters.
884 normalizePrototypeChain(callFrame
, baseCell
);
886 StructureChain
* prototypeChain
= structure
->prototypeChain(callFrame
);
887 stubInfo
->initPutByIdTransition(structure
->previousID(), structure
, prototypeChain
);
888 JIT::compilePutByIdTransition(callFrame
->scopeChain()->globalData
, codeBlock
, stubInfo
, structure
->previousID(), structure
, slot
.cachedOffset(), prototypeChain
, returnAddress
, direct
);
892 stubInfo
->initPutByIdReplace(structure
);
894 JIT::patchPutByIdReplace(codeBlock
, stubInfo
, structure
, slot
.cachedOffset(), returnAddress
, direct
);
897 NEVER_INLINE
void JITThunks::tryCacheGetByID(CallFrame
* callFrame
, CodeBlock
* codeBlock
, ReturnAddressPtr returnAddress
, JSValue baseValue
, const Identifier
& propertyName
, const PropertySlot
& slot
, StructureStubInfo
* stubInfo
)
899 // FIXME: Write a test that proves we need to check for recursion here just
900 // like the interpreter does, then add a check for recursion.
902 // FIXME: Cache property access for immediates.
903 if (!baseValue
.isCell()) {
904 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
908 JSGlobalData
* globalData
= &callFrame
->globalData();
910 if (isJSArray(globalData
, baseValue
) && propertyName
== callFrame
->propertyNames().length
) {
911 JIT::compilePatchGetArrayLength(callFrame
->scopeChain()->globalData
, codeBlock
, returnAddress
);
915 if (isJSString(globalData
, baseValue
) && propertyName
== callFrame
->propertyNames().length
) {
916 // The tradeoff of compiling an patched inline string length access routine does not seem
917 // to pay off, so we currently only do this for arrays.
918 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, globalData
->jitStubs
->ctiStringLengthTrampoline());
922 // Uncacheable: give up.
923 if (!slot
.isCacheable()) {
924 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
928 JSCell
* baseCell
= asCell(baseValue
);
929 Structure
* structure
= baseCell
->structure();
931 if (structure
->isUncacheableDictionary()) {
932 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
936 // Cache hit: Specialize instruction and ref Structures.
938 if (slot
.slotBase() == baseValue
) {
939 // set this up, so derefStructures can do it's job.
940 stubInfo
->initGetByIdSelf(structure
);
941 if (slot
.cachedPropertyType() != PropertySlot::Value
)
942 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_self_fail
));
944 JIT::patchGetByIdSelf(codeBlock
, stubInfo
, structure
, slot
.cachedOffset(), returnAddress
);
948 if (structure
->isDictionary()) {
949 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
953 if (slot
.slotBase() == structure
->prototypeForLookup(callFrame
)) {
954 ASSERT(slot
.slotBase().isObject());
956 JSObject
* slotBaseObject
= asObject(slot
.slotBase());
957 size_t offset
= slot
.cachedOffset();
959 // Since we're accessing a prototype in a loop, it's a good bet that it
960 // should not be treated as a dictionary.
961 if (slotBaseObject
->structure()->isDictionary()) {
962 slotBaseObject
->flattenDictionaryObject();
963 offset
= slotBaseObject
->structure()->get(propertyName
);
966 stubInfo
->initGetByIdProto(structure
, slotBaseObject
->structure());
968 ASSERT(!structure
->isDictionary());
969 ASSERT(!slotBaseObject
->structure()->isDictionary());
970 JIT::compileGetByIdProto(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, structure
, slotBaseObject
->structure(), propertyName
, slot
, offset
, returnAddress
);
974 size_t offset
= slot
.cachedOffset();
975 size_t count
= normalizePrototypeChain(callFrame
, baseValue
, slot
.slotBase(), propertyName
, offset
);
977 stubInfo
->accessType
= access_get_by_id_generic
;
981 StructureChain
* prototypeChain
= structure
->prototypeChain(callFrame
);
982 stubInfo
->initGetByIdChain(structure
, prototypeChain
);
983 JIT::compileGetByIdChain(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, structure
, prototypeChain
, count
, propertyName
, slot
, offset
, returnAddress
);
986 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
988 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
989 #define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args)
991 #define SETUP_VA_LISTL_ARGS
998 static void jscGeneratedNativeCode()
1000 // When executing a JIT stub function (which might do an allocation), we hack the return address
1001 // to pretend to be executing this function, to keep stack logging tools from blowing out
1008 ALWAYS_INLINE
StackHack(JITStackFrame
& stackFrame
)
1009 : stackFrame(stackFrame
)
1010 , savedReturnAddress(*stackFrame
.returnAddressSlot())
1012 *stackFrame
.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode
));
1015 ALWAYS_INLINE
~StackHack()
1017 *stackFrame
.returnAddressSlot() = savedReturnAddress
;
1020 JITStackFrame
& stackFrame
;
1021 ReturnAddressPtr savedReturnAddress
;
1024 #define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
1025 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
1026 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
1030 #define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS)
1031 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
1032 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
1036 // The reason this is not inlined is to avoid having to do a PIC branch
1037 // to get the address of the ctiVMThrowTrampoline function. It's also
1038 // good to keep the code size down by leaving as much of the exception
1039 // handling code out of line as possible.
1040 static NEVER_INLINE
void returnToThrowTrampoline(JSGlobalData
* globalData
, ReturnAddressPtr exceptionLocation
, ReturnAddressPtr
& returnAddressSlot
)
1042 ASSERT(globalData
->exception
);
1043 globalData
->exceptionLocation
= exceptionLocation
;
1044 returnAddressSlot
= ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline
));
1047 static NEVER_INLINE
void throwStackOverflowError(CallFrame
* callFrame
, JSGlobalData
* globalData
, ReturnAddressPtr exceptionLocation
, ReturnAddressPtr
& returnAddressSlot
)
1049 globalData
->exception
= createStackOverflowError(callFrame
);
1050 returnToThrowTrampoline(globalData
, exceptionLocation
, returnAddressSlot
);
1053 #define VM_THROW_EXCEPTION() \
1055 VM_THROW_EXCEPTION_AT_END(); \
1058 #define VM_THROW_EXCEPTION_AT_END() \
1059 returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS)
1061 #define CHECK_FOR_EXCEPTION() \
1063 if (UNLIKELY(stackFrame.globalData->exception)) \
1064 VM_THROW_EXCEPTION(); \
1066 #define CHECK_FOR_EXCEPTION_AT_END() \
1068 if (UNLIKELY(stackFrame.globalData->exception)) \
1069 VM_THROW_EXCEPTION_AT_END(); \
1071 #define CHECK_FOR_EXCEPTION_VOID() \
1073 if (UNLIKELY(stackFrame.globalData->exception)) { \
1074 VM_THROW_EXCEPTION_AT_END(); \
1081 #define DEFINE_STUB_FUNCTION(rtype, op) \
1083 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1088 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1089 HIDE_SYMBOL(cti_##op) "\n" \
1091 ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \
1092 SYMBOL_STRING(cti_##op) ":" "\n" \
1093 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1094 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1095 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1098 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
1102 #define DEFINE_STUB_FUNCTION(rtype, op) \
1104 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1109 ".set noreorder" "\n" \
1110 ".set nomacro" "\n" \
1111 ".set nomips16" "\n" \
1112 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1113 ".ent " SYMBOL_STRING(cti_##op) "\n" \
1114 SYMBOL_STRING(cti_##op) ":" "\n" \
1115 "lw $28,28($29)" "\n" \
1116 "sw $31,48($29)" "\n" \
1118 "la $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \
1119 ".set nomacro" "\n" \
1120 "bal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1122 "lw $31,48($29)" "\n" \
1125 ".set reorder" "\n" \
1127 ".end " SYMBOL_STRING(cti_##op) "\n" \
1129 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1131 #else // WTF_MIPS_PIC
1132 #define DEFINE_STUB_FUNCTION(rtype, op) \
1134 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1139 ".set noreorder" "\n" \
1140 ".set nomacro" "\n" \
1141 ".set nomips16" "\n" \
1142 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1143 ".ent " SYMBOL_STRING(cti_##op) "\n" \
1144 SYMBOL_STRING(cti_##op) ":" "\n" \
1145 "sw $31,48($29)" "\n" \
1146 "jal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1148 "lw $31,48($29)" "\n" \
1151 ".set reorder" "\n" \
1153 ".end " SYMBOL_STRING(cti_##op) "\n" \
1155 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1159 #elif CPU(ARM_TRADITIONAL) && COMPILER(GCC)
1161 #define DEFINE_STUB_FUNCTION(rtype, op) \
1163 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1166 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1167 SYMBOL_STRING(cti_##op) ":" "\n" \
1168 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1169 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1170 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1173 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1175 #elif CPU(ARM_TRADITIONAL) && COMPILER(RVCT)
1177 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1179 /* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */
1181 /* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */
1182 /* The pattern "#xxx#" will be replaced with "xxx" */
1185 RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
1186 RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
1189 RVCT( IMPORT JITStubThunked_#op#)
1190 RVCT( str lr, [sp, ##offset#])
1191 RVCT( bl JITStubThunked_#op#)
1192 RVCT( ldr lr, [sp, ##offset#])
1198 /* Include the generated file */
1199 #include "GeneratedJITStubs_RVCT.h"
1202 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
1205 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_convert_this
)
1207 STUB_INIT_STACK_FRAME(stackFrame
);
1209 JSValue v1
= stackFrame
.args
[0].jsValue();
1210 CallFrame
* callFrame
= stackFrame
.callFrame
;
1212 JSObject
* result
= v1
.toThisObject(callFrame
);
1213 CHECK_FOR_EXCEPTION_AT_END();
1214 return JSValue::encode(result
);
1217 DEFINE_STUB_FUNCTION(void, op_end
)
1219 STUB_INIT_STACK_FRAME(stackFrame
);
1221 ScopeChainNode
* scopeChain
= stackFrame
.callFrame
->scopeChain();
1222 ASSERT(scopeChain
->refCount
> 1);
1223 scopeChain
->deref();
1226 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_add
)
1228 STUB_INIT_STACK_FRAME(stackFrame
);
1230 JSValue v1
= stackFrame
.args
[0].jsValue();
1231 JSValue v2
= stackFrame
.args
[1].jsValue();
1232 CallFrame
* callFrame
= stackFrame
.callFrame
;
1234 if (v1
.isString()) {
1235 JSValue result
= v2
.isString()
1236 ? jsString(callFrame
, asString(v1
), asString(v2
))
1237 : jsString(callFrame
, asString(v1
), v2
.toPrimitiveString(callFrame
));
1238 CHECK_FOR_EXCEPTION_AT_END();
1239 return JSValue::encode(result
);
1242 double left
= 0.0, right
;
1243 if (v1
.getNumber(left
) && v2
.getNumber(right
))
1244 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
+ right
));
1246 // All other cases are pretty uncommon
1247 JSValue result
= jsAddSlowCase(callFrame
, v1
, v2
);
1248 CHECK_FOR_EXCEPTION_AT_END();
1249 return JSValue::encode(result
);
1252 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_pre_inc
)
1254 STUB_INIT_STACK_FRAME(stackFrame
);
1256 JSValue v
= stackFrame
.args
[0].jsValue();
1258 CallFrame
* callFrame
= stackFrame
.callFrame
;
1259 JSValue result
= jsNumber(stackFrame
.globalData
, v
.toNumber(callFrame
) + 1);
1260 CHECK_FOR_EXCEPTION_AT_END();
1261 return JSValue::encode(result
);
1264 DEFINE_STUB_FUNCTION(int, timeout_check
)
1266 STUB_INIT_STACK_FRAME(stackFrame
);
1268 JSGlobalData
* globalData
= stackFrame
.globalData
;
1269 TimeoutChecker
& timeoutChecker
= globalData
->timeoutChecker
;
1271 if (globalData
->terminator
.shouldTerminate()) {
1272 globalData
->exception
= createTerminatedExecutionException(globalData
);
1273 VM_THROW_EXCEPTION_AT_END();
1274 } else if (timeoutChecker
.didTimeOut(stackFrame
.callFrame
)) {
1275 globalData
->exception
= createInterruptedExecutionException(globalData
);
1276 VM_THROW_EXCEPTION_AT_END();
1279 return timeoutChecker
.ticksUntilNextCheck();
1282 DEFINE_STUB_FUNCTION(void, register_file_check
)
1284 STUB_INIT_STACK_FRAME(stackFrame
);
1286 if (LIKELY(stackFrame
.registerFile
->grow(&stackFrame
.callFrame
->registers()[stackFrame
.callFrame
->codeBlock()->m_numCalleeRegisters
])))
1289 // Rewind to the previous call frame because op_call already optimistically
1290 // moved the call frame forward.
1291 CallFrame
* oldCallFrame
= stackFrame
.callFrame
->callerFrame();
1292 stackFrame
.callFrame
= oldCallFrame
;
1293 throwStackOverflowError(oldCallFrame
, stackFrame
.globalData
, ReturnAddressPtr(oldCallFrame
->returnPC()), STUB_RETURN_ADDRESS
);
1296 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq
)
1298 STUB_INIT_STACK_FRAME(stackFrame
);
1300 JSValue src1
= stackFrame
.args
[0].jsValue();
1301 JSValue src2
= stackFrame
.args
[1].jsValue();
1302 CallFrame
* callFrame
= stackFrame
.callFrame
;
1304 bool result
= jsLessEq(callFrame
, src1
, src2
);
1305 CHECK_FOR_EXCEPTION_AT_END();
1309 DEFINE_STUB_FUNCTION(JSObject
*, op_new_object
)
1311 STUB_INIT_STACK_FRAME(stackFrame
);
1313 return constructEmptyObject(stackFrame
.callFrame
);
1316 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic
)
1318 STUB_INIT_STACK_FRAME(stackFrame
);
1320 PutPropertySlot slot
;
1321 stackFrame
.args
[0].jsValue().put(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), stackFrame
.args
[2].jsValue(), slot
);
1322 CHECK_FOR_EXCEPTION_AT_END();
1325 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic
)
1327 STUB_INIT_STACK_FRAME(stackFrame
);
1329 PutPropertySlot slot
;
1330 stackFrame
.args
[0].jsValue().putDirect(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), stackFrame
.args
[2].jsValue(), slot
);
1331 CHECK_FOR_EXCEPTION_AT_END();
1334 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_generic
)
1336 STUB_INIT_STACK_FRAME(stackFrame
);
1338 CallFrame
* callFrame
= stackFrame
.callFrame
;
1339 Identifier
& ident
= stackFrame
.args
[1].identifier();
1341 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1342 PropertySlot
slot(baseValue
);
1343 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1345 CHECK_FOR_EXCEPTION_AT_END();
1346 return JSValue::encode(result
);
1349 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1351 DEFINE_STUB_FUNCTION(void, op_put_by_id
)
1353 STUB_INIT_STACK_FRAME(stackFrame
);
1354 CallFrame
* callFrame
= stackFrame
.callFrame
;
1355 Identifier
& ident
= stackFrame
.args
[1].identifier();
1357 PutPropertySlot slot
;
1358 stackFrame
.args
[0].jsValue().put(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1360 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1361 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1362 if (!stubInfo
->seenOnce())
1363 stubInfo
->setSeen();
1365 JITThunks::tryCachePutByID(callFrame
, codeBlock
, STUB_RETURN_ADDRESS
, stackFrame
.args
[0].jsValue(), slot
, stubInfo
, false);
1367 CHECK_FOR_EXCEPTION_AT_END();
1370 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct
)
1372 STUB_INIT_STACK_FRAME(stackFrame
);
1373 CallFrame
* callFrame
= stackFrame
.callFrame
;
1374 Identifier
& ident
= stackFrame
.args
[1].identifier();
1376 PutPropertySlot slot
;
1377 stackFrame
.args
[0].jsValue().putDirect(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1379 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1380 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1381 if (!stubInfo
->seenOnce())
1382 stubInfo
->setSeen();
1384 JITThunks::tryCachePutByID(callFrame
, codeBlock
, STUB_RETURN_ADDRESS
, stackFrame
.args
[0].jsValue(), slot
, stubInfo
, true);
1386 CHECK_FOR_EXCEPTION_AT_END();
1389 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail
)
1391 STUB_INIT_STACK_FRAME(stackFrame
);
1393 CallFrame
* callFrame
= stackFrame
.callFrame
;
1394 Identifier
& ident
= stackFrame
.args
[1].identifier();
1396 PutPropertySlot slot
;
1397 stackFrame
.args
[0].jsValue().put(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1399 CHECK_FOR_EXCEPTION_AT_END();
1402 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail
)
1404 STUB_INIT_STACK_FRAME(stackFrame
);
1406 CallFrame
* callFrame
= stackFrame
.callFrame
;
1407 Identifier
& ident
= stackFrame
.args
[1].identifier();
1409 PutPropertySlot slot
;
1410 stackFrame
.args
[0].jsValue().putDirect(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1412 CHECK_FOR_EXCEPTION_AT_END();
1415 DEFINE_STUB_FUNCTION(JSObject
*, op_put_by_id_transition_realloc
)
1417 STUB_INIT_STACK_FRAME(stackFrame
);
1419 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1420 int32_t oldSize
= stackFrame
.args
[3].int32();
1421 int32_t newSize
= stackFrame
.args
[4].int32();
1423 ASSERT(baseValue
.isObject());
1424 JSObject
* base
= asObject(baseValue
);
1425 base
->allocatePropertyStorage(oldSize
, newSize
);
1430 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_method_check
)
1432 STUB_INIT_STACK_FRAME(stackFrame
);
1434 CallFrame
* callFrame
= stackFrame
.callFrame
;
1435 Identifier
& ident
= stackFrame
.args
[1].identifier();
1437 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1438 PropertySlot
slot(baseValue
);
1439 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1440 CHECK_FOR_EXCEPTION();
1442 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1443 MethodCallLinkInfo
& methodCallLinkInfo
= codeBlock
->getMethodCallLinkInfo(STUB_RETURN_ADDRESS
);
1445 if (!methodCallLinkInfo
.seenOnce()) {
1446 methodCallLinkInfo
.setSeen();
1447 return JSValue::encode(result
);
1450 // If we successfully got something, then the base from which it is being accessed must
1451 // be an object. (Assertion to ensure asObject() call below is safe, which comes after
1452 // an isCacheable() chceck.
1453 ASSERT(!slot
.isCacheableValue() || slot
.slotBase().isObject());
1456 // * We're dealing with a JSCell,
1457 // * the property is cachable,
1458 // * it's not a dictionary
1459 // * there is a function cached.
1460 Structure
* structure
;
1462 JSObject
* slotBaseObject
;
1463 if (baseValue
.isCell()
1464 && slot
.isCacheableValue()
1465 && !(structure
= asCell(baseValue
)->structure())->isUncacheableDictionary()
1466 && (slotBaseObject
= asObject(slot
.slotBase()))->getPropertySpecificValue(callFrame
, ident
, specific
)
1470 JSFunction
* callee
= (JSFunction
*)specific
;
1472 // Since we're accessing a prototype in a loop, it's a good bet that it
1473 // should not be treated as a dictionary.
1474 if (slotBaseObject
->structure()->isDictionary())
1475 slotBaseObject
->flattenDictionaryObject();
1477 // The result fetched should always be the callee!
1478 ASSERT(result
== JSValue(callee
));
1480 // Check to see if the function is on the object's prototype. Patch up the code to optimize.
1481 if (slot
.slotBase() == structure
->prototypeForLookup(callFrame
)) {
1482 JIT::patchMethodCallProto(codeBlock
, methodCallLinkInfo
, callee
, structure
, slotBaseObject
, STUB_RETURN_ADDRESS
);
1483 return JSValue::encode(result
);
1486 // Check to see if the function is on the object itself.
1487 // Since we generate the method-check to check both the structure and a prototype-structure (since this
1488 // is the common case) we have a problem - we need to patch the prototype structure check to do something
1489 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler
1490 // for now. For now it performs a check on a special object on the global object only used for this
1491 // purpose. The object is in no way exposed, and as such the check will always pass.
1492 if (slot
.slotBase() == baseValue
) {
1493 JIT::patchMethodCallProto(codeBlock
, methodCallLinkInfo
, callee
, structure
, callFrame
->scopeChain()->globalObject
->methodCallDummy(), STUB_RETURN_ADDRESS
);
1494 return JSValue::encode(result
);
1498 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
1499 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id
));
1500 return JSValue::encode(result
);
1503 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id
)
1505 STUB_INIT_STACK_FRAME(stackFrame
);
1506 CallFrame
* callFrame
= stackFrame
.callFrame
;
1507 Identifier
& ident
= stackFrame
.args
[1].identifier();
1509 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1510 PropertySlot
slot(baseValue
);
1511 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1513 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1514 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1515 if (!stubInfo
->seenOnce())
1516 stubInfo
->setSeen();
1518 JITThunks::tryCacheGetByID(callFrame
, codeBlock
, STUB_RETURN_ADDRESS
, baseValue
, ident
, slot
, stubInfo
);
1520 CHECK_FOR_EXCEPTION_AT_END();
1521 return JSValue::encode(result
);
1524 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_self_fail
)
1526 STUB_INIT_STACK_FRAME(stackFrame
);
1528 CallFrame
* callFrame
= stackFrame
.callFrame
;
1529 Identifier
& ident
= stackFrame
.args
[1].identifier();
1531 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1532 PropertySlot
slot(baseValue
);
1533 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1535 CHECK_FOR_EXCEPTION();
1537 if (baseValue
.isCell()
1538 && slot
.isCacheable()
1539 && !asCell(baseValue
)->structure()->isUncacheableDictionary()
1540 && slot
.slotBase() == baseValue
) {
1542 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1543 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1545 ASSERT(slot
.slotBase().isObject());
1547 PolymorphicAccessStructureList
* polymorphicStructureList
;
1550 if (stubInfo
->accessType
== access_get_by_id_self
) {
1551 ASSERT(!stubInfo
->stubRoutine
);
1552 polymorphicStructureList
= new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo
->u
.getByIdSelf
.baseObjectStructure
);
1553 stubInfo
->initGetByIdSelfList(polymorphicStructureList
, 1);
1555 polymorphicStructureList
= stubInfo
->u
.getByIdSelfList
.structureList
;
1556 listIndex
= stubInfo
->u
.getByIdSelfList
.listSize
;
1558 if (listIndex
< POLYMORPHIC_LIST_CACHE_SIZE
) {
1559 stubInfo
->u
.getByIdSelfList
.listSize
++;
1560 JIT::compileGetByIdSelfList(callFrame
->scopeChain()->globalData
, codeBlock
, stubInfo
, polymorphicStructureList
, listIndex
, asCell(baseValue
)->structure(), ident
, slot
, slot
.cachedOffset());
1562 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1563 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_generic
));
1566 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_generic
));
1567 return JSValue::encode(result
);
1570 static PolymorphicAccessStructureList
* getPolymorphicAccessStructureListSlot(StructureStubInfo
* stubInfo
, int& listIndex
)
1572 PolymorphicAccessStructureList
* prototypeStructureList
= 0;
1575 switch (stubInfo
->accessType
) {
1576 case access_get_by_id_proto
:
1577 prototypeStructureList
= new PolymorphicAccessStructureList(stubInfo
->stubRoutine
, stubInfo
->u
.getByIdProto
.baseObjectStructure
, stubInfo
->u
.getByIdProto
.prototypeStructure
);
1578 stubInfo
->stubRoutine
= CodeLocationLabel();
1579 stubInfo
->initGetByIdProtoList(prototypeStructureList
, 2);
1581 case access_get_by_id_chain
:
1582 prototypeStructureList
= new PolymorphicAccessStructureList(stubInfo
->stubRoutine
, stubInfo
->u
.getByIdChain
.baseObjectStructure
, stubInfo
->u
.getByIdChain
.chain
);
1583 stubInfo
->stubRoutine
= CodeLocationLabel();
1584 stubInfo
->initGetByIdProtoList(prototypeStructureList
, 2);
1586 case access_get_by_id_proto_list
:
1587 prototypeStructureList
= stubInfo
->u
.getByIdProtoList
.structureList
;
1588 listIndex
= stubInfo
->u
.getByIdProtoList
.listSize
;
1589 if (listIndex
< POLYMORPHIC_LIST_CACHE_SIZE
)
1590 stubInfo
->u
.getByIdProtoList
.listSize
++;
1593 ASSERT_NOT_REACHED();
1596 ASSERT(listIndex
<= POLYMORPHIC_LIST_CACHE_SIZE
);
1597 return prototypeStructureList
;
1600 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_getter_stub
)
1602 STUB_INIT_STACK_FRAME(stackFrame
);
1603 CallFrame
* callFrame
= stackFrame
.callFrame
;
1604 GetterSetter
* getterSetter
= asGetterSetter(stackFrame
.args
[0].jsObject());
1605 if (!getterSetter
->getter())
1606 return JSValue::encode(jsUndefined());
1607 JSObject
* getter
= asObject(getterSetter
->getter());
1609 CallType callType
= getter
->getCallData(callData
);
1610 JSValue result
= call(callFrame
, getter
, callType
, callData
, stackFrame
.args
[1].jsObject(), ArgList());
1611 if (callFrame
->hadException())
1612 returnToThrowTrampoline(&callFrame
->globalData(), stackFrame
.args
[2].returnAddress(), STUB_RETURN_ADDRESS
);
1614 return JSValue::encode(result
);
1617 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_custom_stub
)
1619 STUB_INIT_STACK_FRAME(stackFrame
);
1620 CallFrame
* callFrame
= stackFrame
.callFrame
;
1621 JSObject
* slotBase
= stackFrame
.args
[0].jsObject();
1622 PropertySlot::GetValueFunc getter
= reinterpret_cast<PropertySlot::GetValueFunc
>(stackFrame
.args
[1].asPointer
);
1623 const Identifier
& ident
= stackFrame
.args
[2].identifier();
1624 JSValue result
= getter(callFrame
, slotBase
, ident
);
1625 if (callFrame
->hadException())
1626 returnToThrowTrampoline(&callFrame
->globalData(), stackFrame
.args
[3].returnAddress(), STUB_RETURN_ADDRESS
);
1628 return JSValue::encode(result
);
1631 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_list
)
1633 STUB_INIT_STACK_FRAME(stackFrame
);
1635 CallFrame
* callFrame
= stackFrame
.callFrame
;
1636 const Identifier
& propertyName
= stackFrame
.args
[1].identifier();
1638 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1639 PropertySlot
slot(baseValue
);
1640 JSValue result
= baseValue
.get(callFrame
, propertyName
, slot
);
1642 CHECK_FOR_EXCEPTION();
1644 if (!baseValue
.isCell() || !slot
.isCacheable() || asCell(baseValue
)->structure()->isDictionary()) {
1645 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1646 return JSValue::encode(result
);
1649 Structure
* structure
= asCell(baseValue
)->structure();
1650 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1651 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1653 ASSERT(slot
.slotBase().isObject());
1654 JSObject
* slotBaseObject
= asObject(slot
.slotBase());
1656 size_t offset
= slot
.cachedOffset();
1658 if (slot
.slotBase() == baseValue
)
1659 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1660 else if (slot
.slotBase() == asCell(baseValue
)->structure()->prototypeForLookup(callFrame
)) {
1661 ASSERT(!asCell(baseValue
)->structure()->isDictionary());
1662 // Since we're accessing a prototype in a loop, it's a good bet that it
1663 // should not be treated as a dictionary.
1664 if (slotBaseObject
->structure()->isDictionary()) {
1665 slotBaseObject
->flattenDictionaryObject();
1666 offset
= slotBaseObject
->structure()->get(propertyName
);
1670 PolymorphicAccessStructureList
* prototypeStructureList
= getPolymorphicAccessStructureListSlot(stubInfo
, listIndex
);
1671 if (listIndex
< POLYMORPHIC_LIST_CACHE_SIZE
) {
1672 JIT::compileGetByIdProtoList(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, prototypeStructureList
, listIndex
, structure
, slotBaseObject
->structure(), propertyName
, slot
, offset
);
1674 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1675 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_list_full
));
1677 } else if (size_t count
= normalizePrototypeChain(callFrame
, baseValue
, slot
.slotBase(), propertyName
, offset
)) {
1678 ASSERT(!asCell(baseValue
)->structure()->isDictionary());
1680 PolymorphicAccessStructureList
* prototypeStructureList
= getPolymorphicAccessStructureListSlot(stubInfo
, listIndex
);
1682 if (listIndex
< POLYMORPHIC_LIST_CACHE_SIZE
) {
1683 StructureChain
* protoChain
= structure
->prototypeChain(callFrame
);
1684 JIT::compileGetByIdChainList(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, prototypeStructureList
, listIndex
, structure
, protoChain
, count
, propertyName
, slot
, offset
);
1686 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1687 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_list_full
));
1690 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1692 return JSValue::encode(result
);
1695 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_list_full
)
1697 STUB_INIT_STACK_FRAME(stackFrame
);
1699 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1700 PropertySlot
slot(baseValue
);
1701 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1703 CHECK_FOR_EXCEPTION_AT_END();
1704 return JSValue::encode(result
);
1707 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_fail
)
1709 STUB_INIT_STACK_FRAME(stackFrame
);
1711 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1712 PropertySlot
slot(baseValue
);
1713 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1715 CHECK_FOR_EXCEPTION_AT_END();
1716 return JSValue::encode(result
);
1719 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_array_fail
)
1721 STUB_INIT_STACK_FRAME(stackFrame
);
1723 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1724 PropertySlot
slot(baseValue
);
1725 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1727 CHECK_FOR_EXCEPTION_AT_END();
1728 return JSValue::encode(result
);
1731 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_string_fail
)
1733 STUB_INIT_STACK_FRAME(stackFrame
);
1735 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1736 PropertySlot
slot(baseValue
);
1737 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1739 CHECK_FOR_EXCEPTION_AT_END();
1740 return JSValue::encode(result
);
1743 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1745 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_instanceof
)
1747 STUB_INIT_STACK_FRAME(stackFrame
);
1749 CallFrame
* callFrame
= stackFrame
.callFrame
;
1750 JSValue value
= stackFrame
.args
[0].jsValue();
1751 JSValue baseVal
= stackFrame
.args
[1].jsValue();
1752 JSValue proto
= stackFrame
.args
[2].jsValue();
1754 // At least one of these checks must have failed to get to the slow case.
1755 ASSERT(!value
.isCell() || !baseVal
.isCell() || !proto
.isCell()
1756 || !value
.isObject() || !baseVal
.isObject() || !proto
.isObject()
1757 || (asObject(baseVal
)->structure()->typeInfo().flags() & (ImplementsHasInstance
| OverridesHasInstance
)) != ImplementsHasInstance
);
1760 // ECMA-262 15.3.5.3:
1761 // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
1762 TypeInfo
typeInfo(UnspecifiedType
);
1763 if (!baseVal
.isObject() || !(typeInfo
= asObject(baseVal
)->structure()->typeInfo()).implementsHasInstance()) {
1764 CallFrame
* callFrame
= stackFrame
.callFrame
;
1765 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1766 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1767 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "instanceof", baseVal
, vPCIndex
, codeBlock
);
1768 VM_THROW_EXCEPTION();
1770 ASSERT(typeInfo
.type() != UnspecifiedType
);
1772 if (!typeInfo
.overridesHasInstance()) {
1773 if (!value
.isObject())
1774 return JSValue::encode(jsBoolean(false));
1776 if (!proto
.isObject()) {
1777 throwError(callFrame
, TypeError
, "instanceof called on an object with an invalid prototype property.");
1778 VM_THROW_EXCEPTION();
1782 JSValue result
= jsBoolean(asObject(baseVal
)->hasInstance(callFrame
, value
, proto
));
1783 CHECK_FOR_EXCEPTION_AT_END();
1785 return JSValue::encode(result
);
1788 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_del_by_id
)
1790 STUB_INIT_STACK_FRAME(stackFrame
);
1792 CallFrame
* callFrame
= stackFrame
.callFrame
;
1794 JSObject
* baseObj
= stackFrame
.args
[0].jsValue().toObject(callFrame
);
1796 JSValue result
= jsBoolean(baseObj
->deleteProperty(callFrame
, stackFrame
.args
[1].identifier()));
1797 CHECK_FOR_EXCEPTION_AT_END();
1798 return JSValue::encode(result
);
1801 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_mul
)
1803 STUB_INIT_STACK_FRAME(stackFrame
);
1805 JSValue src1
= stackFrame
.args
[0].jsValue();
1806 JSValue src2
= stackFrame
.args
[1].jsValue();
1810 if (src1
.getNumber(left
) && src2
.getNumber(right
))
1811 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
* right
));
1813 CallFrame
* callFrame
= stackFrame
.callFrame
;
1814 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toNumber(callFrame
) * src2
.toNumber(callFrame
));
1815 CHECK_FOR_EXCEPTION_AT_END();
1816 return JSValue::encode(result
);
1819 DEFINE_STUB_FUNCTION(JSObject
*, op_new_func
)
1821 STUB_INIT_STACK_FRAME(stackFrame
);
1823 return stackFrame
.args
[0].function()->make(stackFrame
.callFrame
, stackFrame
.callFrame
->scopeChain());
1826 DEFINE_STUB_FUNCTION(void*, op_call_JSFunction
)
1828 STUB_INIT_STACK_FRAME(stackFrame
);
1830 #if !ASSERT_DISABLED
1832 ASSERT(stackFrame
.args
[0].jsValue().getCallData(callData
) == CallTypeJS
);
1835 JSFunction
* function
= asFunction(stackFrame
.args
[0].jsValue());
1836 ASSERT(!function
->isHostFunction());
1837 FunctionExecutable
* executable
= function
->jsExecutable();
1838 ScopeChainNode
* callDataScopeChain
= function
->scope().node();
1839 executable
->jitCode(stackFrame
.callFrame
, callDataScopeChain
);
1844 DEFINE_STUB_FUNCTION(VoidPtrPair
, op_call_arityCheck
)
1846 STUB_INIT_STACK_FRAME(stackFrame
);
1848 CallFrame
* callFrame
= stackFrame
.callFrame
;
1849 JSFunction
* callee
= asFunction(stackFrame
.args
[0].jsValue());
1850 ASSERT(!callee
->isHostFunction());
1851 CodeBlock
* newCodeBlock
= &callee
->jsExecutable()->generatedBytecode();
1852 int argCount
= stackFrame
.args
[2].int32();
1854 ASSERT(argCount
!= newCodeBlock
->m_numParameters
);
1856 CallFrame
* oldCallFrame
= callFrame
->callerFrame();
1858 if (argCount
> newCodeBlock
->m_numParameters
) {
1859 size_t numParameters
= newCodeBlock
->m_numParameters
;
1860 Register
* r
= callFrame
->registers() + numParameters
;
1861 Register
* newEnd
= r
+ newCodeBlock
->m_numCalleeRegisters
;
1862 if (!stackFrame
.registerFile
->grow(newEnd
)) {
1863 // Rewind to the previous call frame because op_call already optimistically
1864 // moved the call frame forward.
1865 stackFrame
.callFrame
= oldCallFrame
;
1866 throwStackOverflowError(oldCallFrame
, stackFrame
.globalData
, stackFrame
.args
[1].returnAddress(), STUB_RETURN_ADDRESS
);
1867 RETURN_POINTER_PAIR(0, 0);
1870 Register
* argv
= r
- RegisterFile::CallFrameHeaderSize
- numParameters
- argCount
;
1871 for (size_t i
= 0; i
< numParameters
; ++i
)
1872 argv
[i
+ argCount
] = argv
[i
];
1874 callFrame
= CallFrame::create(r
);
1875 callFrame
->setCallerFrame(oldCallFrame
);
1877 size_t omittedArgCount
= newCodeBlock
->m_numParameters
- argCount
;
1878 Register
* r
= callFrame
->registers() + omittedArgCount
;
1879 Register
* newEnd
= r
+ newCodeBlock
->m_numCalleeRegisters
;
1880 if (!stackFrame
.registerFile
->grow(newEnd
)) {
1881 // Rewind to the previous call frame because op_call already optimistically
1882 // moved the call frame forward.
1883 stackFrame
.callFrame
= oldCallFrame
;
1884 throwStackOverflowError(oldCallFrame
, stackFrame
.globalData
, stackFrame
.args
[1].returnAddress(), STUB_RETURN_ADDRESS
);
1885 RETURN_POINTER_PAIR(0, 0);
1888 Register
* argv
= r
- RegisterFile::CallFrameHeaderSize
- omittedArgCount
;
1889 for (size_t i
= 0; i
< omittedArgCount
; ++i
)
1890 argv
[i
] = jsUndefined();
1892 callFrame
= CallFrame::create(r
);
1893 callFrame
->setCallerFrame(oldCallFrame
);
1896 ASSERT((void*)callFrame
<= stackFrame
.registerFile
->end());
1897 RETURN_POINTER_PAIR(callee
, callFrame
);
1900 #if ENABLE(JIT_OPTIMIZE_CALL)
1901 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall
)
1903 STUB_INIT_STACK_FRAME(stackFrame
);
1904 JSFunction
* callee
= asFunction(stackFrame
.args
[0].jsValue());
1905 ExecutableBase
* executable
= callee
->executable();
1906 JITCode
& jitCode
= executable
->generatedJITCode();
1908 CodeBlock
* codeBlock
= 0;
1909 if (!executable
->isHostFunction())
1910 codeBlock
= &static_cast<FunctionExecutable
*>(executable
)->bytecode(stackFrame
.callFrame
, callee
->scope().node());
1911 CallLinkInfo
* callLinkInfo
= &stackFrame
.callFrame
->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame
.args
[1].returnAddress());
1913 if (!callLinkInfo
->seenOnce())
1914 callLinkInfo
->setSeen();
1916 JIT::linkCall(callee
, stackFrame
.callFrame
->callerFrame()->codeBlock(), codeBlock
, jitCode
, callLinkInfo
, stackFrame
.args
[2].int32(), stackFrame
.globalData
);
1918 return jitCode
.addressForCall().executableAddress();
1920 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
1922 DEFINE_STUB_FUNCTION(JSObject
*, op_push_activation
)
1924 STUB_INIT_STACK_FRAME(stackFrame
);
1926 JSActivation
* activation
= new (stackFrame
.globalData
) JSActivation(stackFrame
.callFrame
, static_cast<FunctionExecutable
*>(stackFrame
.callFrame
->codeBlock()->ownerExecutable()));
1927 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->copy()->push(activation
));
1931 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_call_NotJSFunction
)
1933 STUB_INIT_STACK_FRAME(stackFrame
);
1935 JSValue funcVal
= stackFrame
.args
[0].jsValue();
1938 CallType callType
= funcVal
.getCallData(callData
);
1940 ASSERT(callType
!= CallTypeJS
);
1942 if (callType
== CallTypeHost
) {
1943 int registerOffset
= stackFrame
.args
[1].int32();
1944 int argCount
= stackFrame
.args
[2].int32();
1945 CallFrame
* previousCallFrame
= stackFrame
.callFrame
;
1946 CallFrame
* callFrame
= CallFrame::create(previousCallFrame
->registers() + registerOffset
);
1948 callFrame
->init(0, static_cast<Instruction
*>((STUB_RETURN_ADDRESS
).value()), previousCallFrame
->scopeChain(), previousCallFrame
, 0, argCount
, 0);
1949 stackFrame
.callFrame
= callFrame
;
1951 Register
* argv
= stackFrame
.callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- argCount
;
1952 ArgList
argList(argv
+ 1, argCount
- 1);
1954 JSValue returnValue
;
1956 SamplingTool::HostCallRecord
callRecord(CTI_SAMPLER
);
1958 // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
1959 JSValue thisValue
= argv
[0].jsValue();
1960 if (thisValue
== jsNull())
1961 thisValue
= callFrame
->globalThisValue();
1963 returnValue
= callData
.native
.function(callFrame
, asObject(funcVal
), thisValue
, argList
);
1965 stackFrame
.callFrame
= previousCallFrame
;
1966 CHECK_FOR_EXCEPTION();
1968 return JSValue::encode(returnValue
);
1971 ASSERT(callType
== CallTypeNone
);
1973 CallFrame
* callFrame
= stackFrame
.callFrame
;
1974 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1975 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1976 stackFrame
.globalData
->exception
= createNotAFunctionError(stackFrame
.callFrame
, funcVal
, vPCIndex
, codeBlock
);
1977 VM_THROW_EXCEPTION();
1980 DEFINE_STUB_FUNCTION(void, op_create_arguments
)
1982 STUB_INIT_STACK_FRAME(stackFrame
);
1984 Arguments
* arguments
= new (stackFrame
.globalData
) Arguments(stackFrame
.callFrame
);
1985 stackFrame
.callFrame
->setCalleeArguments(arguments
);
1986 stackFrame
.callFrame
[RegisterFile::ArgumentsRegister
] = JSValue(arguments
);
1989 DEFINE_STUB_FUNCTION(void, op_create_arguments_no_params
)
1991 STUB_INIT_STACK_FRAME(stackFrame
);
1993 Arguments
* arguments
= new (stackFrame
.globalData
) Arguments(stackFrame
.callFrame
, Arguments::NoParameters
);
1994 stackFrame
.callFrame
->setCalleeArguments(arguments
);
1995 stackFrame
.callFrame
[RegisterFile::ArgumentsRegister
] = JSValue(arguments
);
1998 DEFINE_STUB_FUNCTION(void, op_tear_off_activation
)
2000 STUB_INIT_STACK_FRAME(stackFrame
);
2002 ASSERT(stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
2003 asActivation(stackFrame
.args
[0].jsValue())->copyRegisters(stackFrame
.callFrame
->optionalCalleeArguments());
2006 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments
)
2008 STUB_INIT_STACK_FRAME(stackFrame
);
2010 ASSERT(stackFrame
.callFrame
->codeBlock()->usesArguments() && !stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
2011 if (stackFrame
.callFrame
->optionalCalleeArguments())
2012 stackFrame
.callFrame
->optionalCalleeArguments()->copyRegisters();
2015 DEFINE_STUB_FUNCTION(void, op_profile_will_call
)
2017 STUB_INIT_STACK_FRAME(stackFrame
);
2019 ASSERT(*stackFrame
.enabledProfilerReference
);
2020 (*stackFrame
.enabledProfilerReference
)->willExecute(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue());
2023 DEFINE_STUB_FUNCTION(void, op_profile_did_call
)
2025 STUB_INIT_STACK_FRAME(stackFrame
);
2027 ASSERT(*stackFrame
.enabledProfilerReference
);
2028 (*stackFrame
.enabledProfilerReference
)->didExecute(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue());
2031 DEFINE_STUB_FUNCTION(void, op_ret_scopeChain
)
2033 STUB_INIT_STACK_FRAME(stackFrame
);
2035 ASSERT(stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
2036 stackFrame
.callFrame
->scopeChain()->deref();
2039 DEFINE_STUB_FUNCTION(JSObject
*, op_new_array
)
2041 STUB_INIT_STACK_FRAME(stackFrame
);
2043 ArgList
argList(&stackFrame
.callFrame
->registers()[stackFrame
.args
[0].int32()], stackFrame
.args
[1].int32());
2044 return constructArray(stackFrame
.callFrame
, argList
);
2047 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve
)
2049 STUB_INIT_STACK_FRAME(stackFrame
);
2051 CallFrame
* callFrame
= stackFrame
.callFrame
;
2052 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
2054 ScopeChainIterator iter
= scopeChain
->begin();
2055 ScopeChainIterator end
= scopeChain
->end();
2056 ASSERT(iter
!= end
);
2058 Identifier
& ident
= stackFrame
.args
[0].identifier();
2060 JSObject
* o
= *iter
;
2061 PropertySlot
slot(o
);
2062 if (o
->getPropertySlot(callFrame
, ident
, slot
)) {
2063 JSValue result
= slot
.getValue(callFrame
, ident
);
2064 CHECK_FOR_EXCEPTION_AT_END();
2065 return JSValue::encode(result
);
2067 } while (++iter
!= end
);
2069 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2070 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2071 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, codeBlock
);
2072 VM_THROW_EXCEPTION();
2075 DEFINE_STUB_FUNCTION(JSObject
*, op_construct_JSConstruct
)
2077 STUB_INIT_STACK_FRAME(stackFrame
);
2079 JSFunction
* constructor
= asFunction(stackFrame
.args
[0].jsValue());
2080 if (constructor
->isHostFunction()) {
2081 CallFrame
* callFrame
= stackFrame
.callFrame
;
2082 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2083 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2084 stackFrame
.globalData
->exception
= createNotAConstructorError(callFrame
, constructor
, vPCIndex
, codeBlock
);
2085 VM_THROW_EXCEPTION();
2088 #if !ASSERT_DISABLED
2089 ConstructData constructData
;
2090 ASSERT(constructor
->getConstructData(constructData
) == ConstructTypeJS
);
2093 Structure
* structure
;
2094 if (stackFrame
.args
[3].jsValue().isObject())
2095 structure
= asObject(stackFrame
.args
[3].jsValue())->inheritorID();
2097 structure
= constructor
->scope().node()->globalObject
->emptyObjectStructure();
2098 return new (stackFrame
.globalData
) JSObject(structure
);
2101 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_construct_NotJSConstruct
)
2103 STUB_INIT_STACK_FRAME(stackFrame
);
2105 CallFrame
* callFrame
= stackFrame
.callFrame
;
2107 JSValue constrVal
= stackFrame
.args
[0].jsValue();
2108 int argCount
= stackFrame
.args
[2].int32();
2109 int thisRegister
= stackFrame
.args
[4].int32();
2111 ConstructData constructData
;
2112 ConstructType constructType
= constrVal
.getConstructData(constructData
);
2114 if (constructType
== ConstructTypeHost
) {
2115 ArgList
argList(callFrame
->registers() + thisRegister
+ 1, argCount
- 1);
2117 JSValue returnValue
;
2119 SamplingTool::HostCallRecord
callRecord(CTI_SAMPLER
);
2120 returnValue
= constructData
.native
.function(callFrame
, asObject(constrVal
), argList
);
2122 CHECK_FOR_EXCEPTION();
2124 return JSValue::encode(returnValue
);
2127 ASSERT(constructType
== ConstructTypeNone
);
2129 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2130 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2131 stackFrame
.globalData
->exception
= createNotAConstructorError(callFrame
, constrVal
, vPCIndex
, codeBlock
);
2132 VM_THROW_EXCEPTION();
2135 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val
)
2137 STUB_INIT_STACK_FRAME(stackFrame
);
2139 CallFrame
* callFrame
= stackFrame
.callFrame
;
2140 JSGlobalData
* globalData
= stackFrame
.globalData
;
2142 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2143 JSValue subscript
= stackFrame
.args
[1].jsValue();
2145 if (LIKELY(baseValue
.isCell() && subscript
.isString())) {
2146 Identifier
propertyName(callFrame
, asString(subscript
)->value(callFrame
));
2147 PropertySlot
slot(asCell(baseValue
));
2148 // JSString::value may have thrown, but we shouldn't find a property with a null identifier,
2149 // so we should miss this case and wind up in the CHECK_FOR_EXCEPTION_AT_END, below.
2150 if (asCell(baseValue
)->fastGetOwnPropertySlot(callFrame
, propertyName
, slot
)) {
2151 JSValue result
= slot
.getValue(callFrame
, propertyName
);
2152 CHECK_FOR_EXCEPTION();
2153 return JSValue::encode(result
);
2157 if (subscript
.isUInt32()) {
2158 uint32_t i
= subscript
.asUInt32();
2159 if (isJSString(globalData
, baseValue
) && asString(baseValue
)->canGetIndex(i
)) {
2160 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val_string
));
2161 JSValue result
= asString(baseValue
)->getIndex(callFrame
, i
);
2162 CHECK_FOR_EXCEPTION();
2163 return JSValue::encode(result
);
2165 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2166 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2167 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val_byte_array
));
2168 return JSValue::encode(asByteArray(baseValue
)->getIndex(callFrame
, i
));
2170 JSValue result
= baseValue
.get(callFrame
, i
);
2171 CHECK_FOR_EXCEPTION();
2172 return JSValue::encode(result
);
2175 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2176 JSValue result
= baseValue
.get(callFrame
, property
);
2177 CHECK_FOR_EXCEPTION_AT_END();
2178 return JSValue::encode(result
);
2181 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val_string
)
2183 STUB_INIT_STACK_FRAME(stackFrame
);
2185 CallFrame
* callFrame
= stackFrame
.callFrame
;
2186 JSGlobalData
* globalData
= stackFrame
.globalData
;
2188 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2189 JSValue subscript
= stackFrame
.args
[1].jsValue();
2193 if (LIKELY(subscript
.isUInt32())) {
2194 uint32_t i
= subscript
.asUInt32();
2195 if (isJSString(globalData
, baseValue
) && asString(baseValue
)->canGetIndex(i
))
2196 result
= asString(baseValue
)->getIndex(callFrame
, i
);
2198 result
= baseValue
.get(callFrame
, i
);
2199 if (!isJSString(globalData
, baseValue
))
2200 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val
));
2203 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2204 result
= baseValue
.get(callFrame
, property
);
2207 CHECK_FOR_EXCEPTION_AT_END();
2208 return JSValue::encode(result
);
2211 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val_byte_array
)
2213 STUB_INIT_STACK_FRAME(stackFrame
);
2215 CallFrame
* callFrame
= stackFrame
.callFrame
;
2216 JSGlobalData
* globalData
= stackFrame
.globalData
;
2218 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2219 JSValue subscript
= stackFrame
.args
[1].jsValue();
2223 if (LIKELY(subscript
.isUInt32())) {
2224 uint32_t i
= subscript
.asUInt32();
2225 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2226 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2227 return JSValue::encode(asByteArray(baseValue
)->getIndex(callFrame
, i
));
2230 result
= baseValue
.get(callFrame
, i
);
2231 if (!isJSByteArray(globalData
, baseValue
))
2232 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val
));
2234 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2235 result
= baseValue
.get(callFrame
, property
);
2238 CHECK_FOR_EXCEPTION_AT_END();
2239 return JSValue::encode(result
);
2242 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_sub
)
2244 STUB_INIT_STACK_FRAME(stackFrame
);
2246 JSValue src1
= stackFrame
.args
[0].jsValue();
2247 JSValue src2
= stackFrame
.args
[1].jsValue();
2251 if (src1
.getNumber(left
) && src2
.getNumber(right
))
2252 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
- right
));
2254 CallFrame
* callFrame
= stackFrame
.callFrame
;
2255 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toNumber(callFrame
) - src2
.toNumber(callFrame
));
2256 CHECK_FOR_EXCEPTION_AT_END();
2257 return JSValue::encode(result
);
2260 DEFINE_STUB_FUNCTION(void, op_put_by_val
)
2262 STUB_INIT_STACK_FRAME(stackFrame
);
2264 CallFrame
* callFrame
= stackFrame
.callFrame
;
2265 JSGlobalData
* globalData
= stackFrame
.globalData
;
2267 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2268 JSValue subscript
= stackFrame
.args
[1].jsValue();
2269 JSValue value
= stackFrame
.args
[2].jsValue();
2271 if (LIKELY(subscript
.isUInt32())) {
2272 uint32_t i
= subscript
.asUInt32();
2273 if (isJSArray(globalData
, baseValue
)) {
2274 JSArray
* jsArray
= asArray(baseValue
);
2275 if (jsArray
->canSetIndex(i
))
2276 jsArray
->setIndex(i
, value
);
2278 jsArray
->JSArray::put(callFrame
, i
, value
);
2279 } else if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2280 JSByteArray
* jsByteArray
= asByteArray(baseValue
);
2281 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_put_by_val_byte_array
));
2282 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2283 if (value
.isInt32()) {
2284 jsByteArray
->setIndex(i
, value
.asInt32());
2288 if (value
.getNumber(dValue
)) {
2289 jsByteArray
->setIndex(i
, dValue
);
2294 baseValue
.put(callFrame
, i
, value
);
2296 baseValue
.put(callFrame
, i
, value
);
2298 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2299 if (!stackFrame
.globalData
->exception
) { // Don't put to an object if toString threw an exception.
2300 PutPropertySlot slot
;
2301 baseValue
.put(callFrame
, property
, value
, slot
);
2305 CHECK_FOR_EXCEPTION_AT_END();
2308 DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array
)
2310 STUB_INIT_STACK_FRAME(stackFrame
);
2312 CallFrame
* callFrame
= stackFrame
.callFrame
;
2313 JSGlobalData
* globalData
= stackFrame
.globalData
;
2315 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2316 JSValue subscript
= stackFrame
.args
[1].jsValue();
2317 JSValue value
= stackFrame
.args
[2].jsValue();
2319 if (LIKELY(subscript
.isUInt32())) {
2320 uint32_t i
= subscript
.asUInt32();
2321 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2322 JSByteArray
* jsByteArray
= asByteArray(baseValue
);
2324 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2325 if (value
.isInt32()) {
2326 jsByteArray
->setIndex(i
, value
.asInt32());
2330 if (value
.getNumber(dValue
)) {
2331 jsByteArray
->setIndex(i
, dValue
);
2337 if (!isJSByteArray(globalData
, baseValue
))
2338 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_put_by_val
));
2339 baseValue
.put(callFrame
, i
, value
);
2341 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2342 if (!stackFrame
.globalData
->exception
) { // Don't put to an object if toString threw an exception.
2343 PutPropertySlot slot
;
2344 baseValue
.put(callFrame
, property
, value
, slot
);
2348 CHECK_FOR_EXCEPTION_AT_END();
2351 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_lesseq
)
2353 STUB_INIT_STACK_FRAME(stackFrame
);
2355 CallFrame
* callFrame
= stackFrame
.callFrame
;
2356 JSValue result
= jsBoolean(jsLessEq(callFrame
, stackFrame
.args
[0].jsValue(), stackFrame
.args
[1].jsValue()));
2357 CHECK_FOR_EXCEPTION_AT_END();
2358 return JSValue::encode(result
);
2361 DEFINE_STUB_FUNCTION(int, op_load_varargs
)
2363 STUB_INIT_STACK_FRAME(stackFrame
);
2365 CallFrame
* callFrame
= stackFrame
.callFrame
;
2366 RegisterFile
* registerFile
= stackFrame
.registerFile
;
2367 int argsOffset
= stackFrame
.args
[0].int32();
2368 JSValue arguments
= callFrame
->registers()[argsOffset
].jsValue();
2369 uint32_t argCount
= 0;
2371 int providedParams
= callFrame
->registers()[RegisterFile::ArgumentCount
].i() - 1;
2372 argCount
= providedParams
;
2373 argCount
= min(argCount
, static_cast<uint32_t>(Arguments::MaxArguments
));
2374 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2375 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2376 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2377 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2378 VM_THROW_EXCEPTION();
2380 int32_t expectedParams
= callFrame
->callee()->jsExecutable()->parameterCount();
2381 int32_t inplaceArgs
= min(providedParams
, expectedParams
);
2383 Register
* inplaceArgsDst
= callFrame
->registers() + argsOffset
;
2385 Register
* inplaceArgsEnd
= inplaceArgsDst
+ inplaceArgs
;
2386 Register
* inplaceArgsEnd2
= inplaceArgsDst
+ providedParams
;
2388 Register
* inplaceArgsSrc
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- expectedParams
;
2389 Register
* inplaceArgsSrc2
= inplaceArgsSrc
- providedParams
- 1 + inplaceArgs
;
2391 // First step is to copy the "expected" parameters from their normal location relative to the callframe
2392 while (inplaceArgsDst
< inplaceArgsEnd
)
2393 *inplaceArgsDst
++ = *inplaceArgsSrc
++;
2395 // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
2396 while (inplaceArgsDst
< inplaceArgsEnd2
)
2397 *inplaceArgsDst
++ = *inplaceArgsSrc2
++;
2399 } else if (!arguments
.isUndefinedOrNull()) {
2400 if (!arguments
.isObject()) {
2401 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2402 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2403 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "Function.prototype.apply", arguments
, vPCIndex
, codeBlock
);
2404 VM_THROW_EXCEPTION();
2406 if (asObject(arguments
)->classInfo() == &Arguments::info
) {
2407 Arguments
* argsObject
= asArguments(arguments
);
2408 argCount
= argsObject
->numProvidedArguments(callFrame
);
2409 argCount
= min(argCount
, static_cast<uint32_t>(Arguments::MaxArguments
));
2410 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2411 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2412 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2413 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2414 VM_THROW_EXCEPTION();
2416 argsObject
->copyToRegisters(callFrame
, callFrame
->registers() + argsOffset
, argCount
);
2417 } else if (isJSArray(&callFrame
->globalData(), arguments
)) {
2418 JSArray
* array
= asArray(arguments
);
2419 argCount
= array
->length();
2420 argCount
= min(argCount
, static_cast<uint32_t>(Arguments::MaxArguments
));
2421 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2422 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2423 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2424 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2425 VM_THROW_EXCEPTION();
2427 array
->copyToRegisters(callFrame
, callFrame
->registers() + argsOffset
, argCount
);
2428 } else if (asObject(arguments
)->inherits(&JSArray::info
)) {
2429 JSObject
* argObject
= asObject(arguments
);
2430 argCount
= argObject
->get(callFrame
, callFrame
->propertyNames().length
).toUInt32(callFrame
);
2431 argCount
= min(argCount
, static_cast<uint32_t>(Arguments::MaxArguments
));
2432 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2433 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2434 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2435 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2436 VM_THROW_EXCEPTION();
2438 Register
* argsBuffer
= callFrame
->registers() + argsOffset
;
2439 for (unsigned i
= 0; i
< argCount
; ++i
) {
2440 argsBuffer
[i
] = asObject(arguments
)->get(callFrame
, i
);
2441 CHECK_FOR_EXCEPTION();
2444 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2445 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2446 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "Function.prototype.apply", arguments
, vPCIndex
, codeBlock
);
2447 VM_THROW_EXCEPTION();
2451 return argCount
+ 1;
2454 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_negate
)
2456 STUB_INIT_STACK_FRAME(stackFrame
);
2458 JSValue src
= stackFrame
.args
[0].jsValue();
2461 if (src
.getNumber(v
))
2462 return JSValue::encode(jsNumber(stackFrame
.globalData
, -v
));
2464 CallFrame
* callFrame
= stackFrame
.callFrame
;
2465 JSValue result
= jsNumber(stackFrame
.globalData
, -src
.toNumber(callFrame
));
2466 CHECK_FOR_EXCEPTION_AT_END();
2467 return JSValue::encode(result
);
2470 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_base
)
2472 STUB_INIT_STACK_FRAME(stackFrame
);
2474 return JSValue::encode(JSC::resolveBase(stackFrame
.callFrame
, stackFrame
.args
[0].identifier(), stackFrame
.callFrame
->scopeChain()));
2477 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_skip
)
2479 STUB_INIT_STACK_FRAME(stackFrame
);
2481 CallFrame
* callFrame
= stackFrame
.callFrame
;
2482 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
2484 int skip
= stackFrame
.args
[1].int32();
2486 ScopeChainIterator iter
= scopeChain
->begin();
2487 ScopeChainIterator end
= scopeChain
->end();
2488 ASSERT(iter
!= end
);
2491 ASSERT(iter
!= end
);
2493 Identifier
& ident
= stackFrame
.args
[0].identifier();
2495 JSObject
* o
= *iter
;
2496 PropertySlot
slot(o
);
2497 if (o
->getPropertySlot(callFrame
, ident
, slot
)) {
2498 JSValue result
= slot
.getValue(callFrame
, ident
);
2499 CHECK_FOR_EXCEPTION_AT_END();
2500 return JSValue::encode(result
);
2502 } while (++iter
!= end
);
2504 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2505 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2506 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, codeBlock
);
2507 VM_THROW_EXCEPTION();
2510 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_global
)
2512 STUB_INIT_STACK_FRAME(stackFrame
);
2514 CallFrame
* callFrame
= stackFrame
.callFrame
;
2515 JSGlobalObject
* globalObject
= stackFrame
.args
[0].globalObject();
2516 Identifier
& ident
= stackFrame
.args
[1].identifier();
2517 unsigned globalResolveInfoIndex
= stackFrame
.args
[2].int32();
2518 ASSERT(globalObject
->isGlobalObject());
2520 PropertySlot
slot(globalObject
);
2521 if (globalObject
->getPropertySlot(callFrame
, ident
, slot
)) {
2522 JSValue result
= slot
.getValue(callFrame
, ident
);
2523 if (slot
.isCacheableValue() && !globalObject
->structure()->isUncacheableDictionary() && slot
.slotBase() == globalObject
) {
2524 GlobalResolveInfo
& globalResolveInfo
= callFrame
->codeBlock()->globalResolveInfo(globalResolveInfoIndex
);
2525 if (globalResolveInfo
.structure
)
2526 globalResolveInfo
.structure
->deref();
2527 globalObject
->structure()->ref();
2528 globalResolveInfo
.structure
= globalObject
->structure();
2529 globalResolveInfo
.offset
= slot
.cachedOffset();
2530 return JSValue::encode(result
);
2533 CHECK_FOR_EXCEPTION_AT_END();
2534 return JSValue::encode(result
);
2537 unsigned vPCIndex
= callFrame
->codeBlock()->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2538 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, callFrame
->codeBlock());
2539 VM_THROW_EXCEPTION();
2542 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_div
)
2544 STUB_INIT_STACK_FRAME(stackFrame
);
2546 JSValue src1
= stackFrame
.args
[0].jsValue();
2547 JSValue src2
= stackFrame
.args
[1].jsValue();
2551 if (src1
.getNumber(left
) && src2
.getNumber(right
))
2552 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
/ right
));
2554 CallFrame
* callFrame
= stackFrame
.callFrame
;
2555 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toNumber(callFrame
) / src2
.toNumber(callFrame
));
2556 CHECK_FOR_EXCEPTION_AT_END();
2557 return JSValue::encode(result
);
2560 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_pre_dec
)
2562 STUB_INIT_STACK_FRAME(stackFrame
);
2564 JSValue v
= stackFrame
.args
[0].jsValue();
2566 CallFrame
* callFrame
= stackFrame
.callFrame
;
2567 JSValue result
= jsNumber(stackFrame
.globalData
, v
.toNumber(callFrame
) - 1);
2568 CHECK_FOR_EXCEPTION_AT_END();
2569 return JSValue::encode(result
);
2572 DEFINE_STUB_FUNCTION(int, op_jless
)
2574 STUB_INIT_STACK_FRAME(stackFrame
);
2576 JSValue src1
= stackFrame
.args
[0].jsValue();
2577 JSValue src2
= stackFrame
.args
[1].jsValue();
2578 CallFrame
* callFrame
= stackFrame
.callFrame
;
2580 bool result
= jsLess(callFrame
, src1
, src2
);
2581 CHECK_FOR_EXCEPTION_AT_END();
2585 DEFINE_STUB_FUNCTION(int, op_jlesseq
)
2587 STUB_INIT_STACK_FRAME(stackFrame
);
2589 JSValue src1
= stackFrame
.args
[0].jsValue();
2590 JSValue src2
= stackFrame
.args
[1].jsValue();
2591 CallFrame
* callFrame
= stackFrame
.callFrame
;
2593 bool result
= jsLessEq(callFrame
, src1
, src2
);
2594 CHECK_FOR_EXCEPTION_AT_END();
2598 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_not
)
2600 STUB_INIT_STACK_FRAME(stackFrame
);
2602 JSValue src
= stackFrame
.args
[0].jsValue();
2604 CallFrame
* callFrame
= stackFrame
.callFrame
;
2606 JSValue result
= jsBoolean(!src
.toBoolean(callFrame
));
2607 CHECK_FOR_EXCEPTION_AT_END();
2608 return JSValue::encode(result
);
2611 DEFINE_STUB_FUNCTION(int, op_jtrue
)
2613 STUB_INIT_STACK_FRAME(stackFrame
);
2615 JSValue src1
= stackFrame
.args
[0].jsValue();
2617 CallFrame
* callFrame
= stackFrame
.callFrame
;
2619 bool result
= src1
.toBoolean(callFrame
);
2620 CHECK_FOR_EXCEPTION_AT_END();
2624 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_post_inc
)
2626 STUB_INIT_STACK_FRAME(stackFrame
);
2628 JSValue v
= stackFrame
.args
[0].jsValue();
2630 CallFrame
* callFrame
= stackFrame
.callFrame
;
2632 JSValue number
= v
.toJSNumber(callFrame
);
2633 CHECK_FOR_EXCEPTION_AT_END();
2635 callFrame
->registers()[stackFrame
.args
[1].int32()] = jsNumber(stackFrame
.globalData
, number
.uncheckedGetNumber() + 1);
2636 return JSValue::encode(number
);
2639 DEFINE_STUB_FUNCTION(int, op_eq
)
2641 STUB_INIT_STACK_FRAME(stackFrame
);
2643 JSValue src1
= stackFrame
.args
[0].jsValue();
2644 JSValue src2
= stackFrame
.args
[1].jsValue();
2646 #if USE(JSVALUE32_64)
2648 if (src2
.isUndefined()) {
2649 return src1
.isNull() ||
2650 (src1
.isCell() && asCell(src1
)->structure()->typeInfo().masqueradesAsUndefined()) ||
2654 if (src2
.isNull()) {
2655 return src1
.isUndefined() ||
2656 (src1
.isCell() && asCell(src1
)->structure()->typeInfo().masqueradesAsUndefined()) ||
2660 if (src1
.isInt32()) {
2661 if (src2
.isDouble())
2662 return src1
.asInt32() == src2
.asDouble();
2663 double d
= src2
.toNumber(stackFrame
.callFrame
);
2664 CHECK_FOR_EXCEPTION();
2665 return src1
.asInt32() == d
;
2668 if (src1
.isDouble()) {
2670 return src1
.asDouble() == src2
.asInt32();
2671 double d
= src2
.toNumber(stackFrame
.callFrame
);
2672 CHECK_FOR_EXCEPTION();
2673 return src1
.asDouble() == d
;
2676 if (src1
.isTrue()) {
2679 double d
= src2
.toNumber(stackFrame
.callFrame
);
2680 CHECK_FOR_EXCEPTION();
2684 if (src1
.isFalse()) {
2687 double d
= src2
.toNumber(stackFrame
.callFrame
);
2688 CHECK_FOR_EXCEPTION();
2692 if (src1
.isUndefined())
2693 return src2
.isCell() && asCell(src2
)->structure()->typeInfo().masqueradesAsUndefined();
2696 return src2
.isCell() && asCell(src2
)->structure()->typeInfo().masqueradesAsUndefined();
2698 JSCell
* cell1
= asCell(src1
);
2700 if (cell1
->isString()) {
2702 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
).toDouble() == src2
.asInt32();
2704 if (src2
.isDouble())
2705 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
).toDouble() == src2
.asDouble();
2708 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
).toDouble() == 1.0;
2711 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
).toDouble() == 0.0;
2713 JSCell
* cell2
= asCell(src2
);
2714 if (cell2
->isString())
2715 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
) == static_cast<JSString
*>(cell2
)->value(stackFrame
.callFrame
);
2717 src2
= asObject(cell2
)->toPrimitive(stackFrame
.callFrame
);
2718 CHECK_FOR_EXCEPTION();
2722 if (src2
.isObject())
2723 return asObject(cell1
) == asObject(src2
);
2724 src1
= asObject(cell1
)->toPrimitive(stackFrame
.callFrame
);
2725 CHECK_FOR_EXCEPTION();
2728 #else // USE(JSVALUE32_64)
2729 CallFrame
* callFrame
= stackFrame
.callFrame
;
2731 bool result
= JSValue::equalSlowCaseInline(callFrame
, src1
, src2
);
2732 CHECK_FOR_EXCEPTION_AT_END();
2734 #endif // USE(JSVALUE32_64)
2737 DEFINE_STUB_FUNCTION(int, op_eq_strings
)
2739 #if USE(JSVALUE32_64)
2740 STUB_INIT_STACK_FRAME(stackFrame
);
2742 JSString
* string1
= stackFrame
.args
[0].jsString();
2743 JSString
* string2
= stackFrame
.args
[1].jsString();
2745 ASSERT(string1
->isString());
2746 ASSERT(string2
->isString());
2747 return string1
->value(stackFrame
.callFrame
) == string2
->value(stackFrame
.callFrame
);
2750 ASSERT_NOT_REACHED();
2755 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_lshift
)
2757 STUB_INIT_STACK_FRAME(stackFrame
);
2759 JSValue val
= stackFrame
.args
[0].jsValue();
2760 JSValue shift
= stackFrame
.args
[1].jsValue();
2762 CallFrame
* callFrame
= stackFrame
.callFrame
;
2763 JSValue result
= jsNumber(stackFrame
.globalData
, (val
.toInt32(callFrame
)) << (shift
.toUInt32(callFrame
) & 0x1f));
2764 CHECK_FOR_EXCEPTION_AT_END();
2765 return JSValue::encode(result
);
2768 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitand
)
2770 STUB_INIT_STACK_FRAME(stackFrame
);
2772 JSValue src1
= stackFrame
.args
[0].jsValue();
2773 JSValue src2
= stackFrame
.args
[1].jsValue();
2775 ASSERT(!src1
.isInt32() || !src2
.isInt32());
2776 CallFrame
* callFrame
= stackFrame
.callFrame
;
2777 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toInt32(callFrame
) & src2
.toInt32(callFrame
));
2778 CHECK_FOR_EXCEPTION_AT_END();
2779 return JSValue::encode(result
);
2782 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_rshift
)
2784 STUB_INIT_STACK_FRAME(stackFrame
);
2786 JSValue val
= stackFrame
.args
[0].jsValue();
2787 JSValue shift
= stackFrame
.args
[1].jsValue();
2789 CallFrame
* callFrame
= stackFrame
.callFrame
;
2790 JSValue result
= jsNumber(stackFrame
.globalData
, (val
.toInt32(callFrame
)) >> (shift
.toUInt32(callFrame
) & 0x1f));
2792 CHECK_FOR_EXCEPTION_AT_END();
2793 return JSValue::encode(result
);
2796 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitnot
)
2798 STUB_INIT_STACK_FRAME(stackFrame
);
2800 JSValue src
= stackFrame
.args
[0].jsValue();
2802 ASSERT(!src
.isInt32());
2803 CallFrame
* callFrame
= stackFrame
.callFrame
;
2804 JSValue result
= jsNumber(stackFrame
.globalData
, ~src
.toInt32(callFrame
));
2805 CHECK_FOR_EXCEPTION_AT_END();
2806 return JSValue::encode(result
);
2809 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_with_base
)
2811 STUB_INIT_STACK_FRAME(stackFrame
);
2813 CallFrame
* callFrame
= stackFrame
.callFrame
;
2814 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
2816 ScopeChainIterator iter
= scopeChain
->begin();
2817 ScopeChainIterator end
= scopeChain
->end();
2819 // FIXME: add scopeDepthIsZero optimization
2821 ASSERT(iter
!= end
);
2823 Identifier
& ident
= stackFrame
.args
[0].identifier();
2827 PropertySlot
slot(base
);
2828 if (base
->getPropertySlot(callFrame
, ident
, slot
)) {
2829 JSValue result
= slot
.getValue(callFrame
, ident
);
2830 CHECK_FOR_EXCEPTION_AT_END();
2832 callFrame
->registers()[stackFrame
.args
[1].int32()] = JSValue(base
);
2833 return JSValue::encode(result
);
2836 } while (iter
!= end
);
2838 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2839 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2840 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, codeBlock
);
2841 VM_THROW_EXCEPTION_AT_END();
2842 return JSValue::encode(JSValue());
2845 DEFINE_STUB_FUNCTION(JSObject
*, op_new_func_exp
)
2847 STUB_INIT_STACK_FRAME(stackFrame
);
2848 CallFrame
* callFrame
= stackFrame
.callFrame
;
2850 FunctionExecutable
* function
= stackFrame
.args
[0].function();
2851 JSFunction
* func
= function
->make(callFrame
, callFrame
->scopeChain());
2854 The Identifier in a FunctionExpression can be referenced from inside
2855 the FunctionExpression's FunctionBody to allow the function to call
2856 itself recursively. However, unlike in a FunctionDeclaration, the
2857 Identifier in a FunctionExpression cannot be referenced from and
2858 does not affect the scope enclosing the FunctionExpression.
2860 if (!function
->name().isNull()) {
2861 JSStaticScopeObject
* functionScopeObject
= new (callFrame
) JSStaticScopeObject(callFrame
, function
->name(), func
, ReadOnly
| DontDelete
);
2862 func
->scope().push(functionScopeObject
);
2868 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_mod
)
2870 STUB_INIT_STACK_FRAME(stackFrame
);
2872 JSValue dividendValue
= stackFrame
.args
[0].jsValue();
2873 JSValue divisorValue
= stackFrame
.args
[1].jsValue();
2875 CallFrame
* callFrame
= stackFrame
.callFrame
;
2876 double d
= dividendValue
.toNumber(callFrame
);
2877 JSValue result
= jsNumber(stackFrame
.globalData
, fmod(d
, divisorValue
.toNumber(callFrame
)));
2878 CHECK_FOR_EXCEPTION_AT_END();
2879 return JSValue::encode(result
);
2882 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_less
)
2884 STUB_INIT_STACK_FRAME(stackFrame
);
2886 CallFrame
* callFrame
= stackFrame
.callFrame
;
2887 JSValue result
= jsBoolean(jsLess(callFrame
, stackFrame
.args
[0].jsValue(), stackFrame
.args
[1].jsValue()));
2888 CHECK_FOR_EXCEPTION_AT_END();
2889 return JSValue::encode(result
);
2892 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_post_dec
)
2894 STUB_INIT_STACK_FRAME(stackFrame
);
2896 JSValue v
= stackFrame
.args
[0].jsValue();
2898 CallFrame
* callFrame
= stackFrame
.callFrame
;
2900 JSValue number
= v
.toJSNumber(callFrame
);
2901 CHECK_FOR_EXCEPTION_AT_END();
2903 callFrame
->registers()[stackFrame
.args
[1].int32()] = jsNumber(stackFrame
.globalData
, number
.uncheckedGetNumber() - 1);
2904 return JSValue::encode(number
);
2907 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_urshift
)
2909 STUB_INIT_STACK_FRAME(stackFrame
);
2911 JSValue val
= stackFrame
.args
[0].jsValue();
2912 JSValue shift
= stackFrame
.args
[1].jsValue();
2914 CallFrame
* callFrame
= stackFrame
.callFrame
;
2915 JSValue result
= jsNumber(stackFrame
.globalData
, (val
.toUInt32(callFrame
)) >> (shift
.toUInt32(callFrame
) & 0x1f));
2916 CHECK_FOR_EXCEPTION_AT_END();
2917 return JSValue::encode(result
);
2920 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitxor
)
2922 STUB_INIT_STACK_FRAME(stackFrame
);
2924 JSValue src1
= stackFrame
.args
[0].jsValue();
2925 JSValue src2
= stackFrame
.args
[1].jsValue();
2927 CallFrame
* callFrame
= stackFrame
.callFrame
;
2929 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toInt32(callFrame
) ^ src2
.toInt32(callFrame
));
2930 CHECK_FOR_EXCEPTION_AT_END();
2931 return JSValue::encode(result
);
2934 DEFINE_STUB_FUNCTION(JSObject
*, op_new_regexp
)
2936 STUB_INIT_STACK_FRAME(stackFrame
);
2938 return new (stackFrame
.globalData
) RegExpObject(stackFrame
.callFrame
->lexicalGlobalObject()->regExpStructure(), stackFrame
.args
[0].regExp());
2941 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitor
)
2943 STUB_INIT_STACK_FRAME(stackFrame
);
2945 JSValue src1
= stackFrame
.args
[0].jsValue();
2946 JSValue src2
= stackFrame
.args
[1].jsValue();
2948 CallFrame
* callFrame
= stackFrame
.callFrame
;
2950 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toInt32(callFrame
) | src2
.toInt32(callFrame
));
2951 CHECK_FOR_EXCEPTION_AT_END();
2952 return JSValue::encode(result
);
2955 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_call_eval
)
2957 STUB_INIT_STACK_FRAME(stackFrame
);
2959 CallFrame
* callFrame
= stackFrame
.callFrame
;
2960 RegisterFile
* registerFile
= stackFrame
.registerFile
;
2962 Interpreter
* interpreter
= stackFrame
.globalData
->interpreter
;
2964 JSValue funcVal
= stackFrame
.args
[0].jsValue();
2965 int registerOffset
= stackFrame
.args
[1].int32();
2966 int argCount
= stackFrame
.args
[2].int32();
2968 Register
* newCallFrame
= callFrame
->registers() + registerOffset
;
2969 Register
* argv
= newCallFrame
- RegisterFile::CallFrameHeaderSize
- argCount
;
2970 JSValue thisValue
= argv
[0].jsValue();
2971 JSGlobalObject
* globalObject
= callFrame
->scopeChain()->globalObject
;
2973 if (thisValue
== globalObject
&& funcVal
== globalObject
->evalFunction()) {
2974 JSValue exceptionValue
;
2975 JSValue result
= interpreter
->callEval(callFrame
, registerFile
, argv
, argCount
, registerOffset
, exceptionValue
);
2976 if (UNLIKELY(exceptionValue
)) {
2977 stackFrame
.globalData
->exception
= exceptionValue
;
2978 VM_THROW_EXCEPTION_AT_END();
2980 return JSValue::encode(result
);
2983 return JSValue::encode(JSValue());
2986 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_throw
)
2988 STUB_INIT_STACK_FRAME(stackFrame
);
2990 CallFrame
* callFrame
= stackFrame
.callFrame
;
2991 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2993 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2995 JSValue exceptionValue
= stackFrame
.args
[0].jsValue();
2996 ASSERT(exceptionValue
);
2998 HandlerInfo
* handler
= stackFrame
.globalData
->interpreter
->throwException(callFrame
, exceptionValue
, vPCIndex
, true);
3001 *stackFrame
.exception
= exceptionValue
;
3002 STUB_SET_RETURN_ADDRESS(FunctionPtr(ctiOpThrowNotCaught
).value());
3003 return JSValue::encode(jsNull());
3006 stackFrame
.callFrame
= callFrame
;
3007 void* catchRoutine
= handler
->nativeCode
.executableAddress();
3008 ASSERT(catchRoutine
);
3009 STUB_SET_RETURN_ADDRESS(catchRoutine
);
3010 return JSValue::encode(exceptionValue
);
3013 DEFINE_STUB_FUNCTION(JSPropertyNameIterator
*, op_get_pnames
)
3015 STUB_INIT_STACK_FRAME(stackFrame
);
3017 CallFrame
* callFrame
= stackFrame
.callFrame
;
3018 JSObject
* o
= stackFrame
.args
[0].jsObject();
3019 Structure
* structure
= o
->structure();
3020 JSPropertyNameIterator
* jsPropertyNameIterator
= structure
->enumerationCache();
3021 if (!jsPropertyNameIterator
|| jsPropertyNameIterator
->cachedPrototypeChain() != structure
->prototypeChain(callFrame
))
3022 jsPropertyNameIterator
= JSPropertyNameIterator::create(callFrame
, o
);
3023 return jsPropertyNameIterator
;
3026 DEFINE_STUB_FUNCTION(int, has_property
)
3028 STUB_INIT_STACK_FRAME(stackFrame
);
3030 JSObject
* base
= stackFrame
.args
[0].jsObject();
3031 JSString
* property
= stackFrame
.args
[1].jsString();
3032 int result
= base
->hasProperty(stackFrame
.callFrame
, Identifier(stackFrame
.callFrame
, property
->value(stackFrame
.callFrame
)));
3033 CHECK_FOR_EXCEPTION_AT_END();
3037 DEFINE_STUB_FUNCTION(JSObject
*, op_push_scope
)
3039 STUB_INIT_STACK_FRAME(stackFrame
);
3041 JSObject
* o
= stackFrame
.args
[0].jsValue().toObject(stackFrame
.callFrame
);
3042 CHECK_FOR_EXCEPTION();
3043 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->push(o
));
3047 DEFINE_STUB_FUNCTION(void, op_pop_scope
)
3049 STUB_INIT_STACK_FRAME(stackFrame
);
3051 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->pop());
3054 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_typeof
)
3056 STUB_INIT_STACK_FRAME(stackFrame
);
3058 return JSValue::encode(jsTypeStringForValue(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue()));
3061 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_undefined
)
3063 STUB_INIT_STACK_FRAME(stackFrame
);
3065 JSValue v
= stackFrame
.args
[0].jsValue();
3066 return JSValue::encode(jsBoolean(v
.isCell() ? v
.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v
.isUndefined()));
3069 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_boolean
)
3071 STUB_INIT_STACK_FRAME(stackFrame
);
3073 return JSValue::encode(jsBoolean(stackFrame
.args
[0].jsValue().isBoolean()));
3076 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_number
)
3078 STUB_INIT_STACK_FRAME(stackFrame
);
3080 return JSValue::encode(jsBoolean(stackFrame
.args
[0].jsValue().isNumber()));
3083 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_string
)
3085 STUB_INIT_STACK_FRAME(stackFrame
);
3087 return JSValue::encode(jsBoolean(isJSString(stackFrame
.globalData
, stackFrame
.args
[0].jsValue())));
3090 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_object
)
3092 STUB_INIT_STACK_FRAME(stackFrame
);
3094 return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame
.args
[0].jsValue())));
3097 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_function
)
3099 STUB_INIT_STACK_FRAME(stackFrame
);
3101 return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame
.args
[0].jsValue())));
3104 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_stricteq
)
3106 STUB_INIT_STACK_FRAME(stackFrame
);
3108 JSValue src1
= stackFrame
.args
[0].jsValue();
3109 JSValue src2
= stackFrame
.args
[1].jsValue();
3111 bool result
= JSValue::strictEqual(stackFrame
.callFrame
, src1
, src2
);
3112 CHECK_FOR_EXCEPTION_AT_END();
3113 return JSValue::encode(jsBoolean(result
));
3116 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_to_primitive
)
3118 STUB_INIT_STACK_FRAME(stackFrame
);
3120 return JSValue::encode(stackFrame
.args
[0].jsValue().toPrimitive(stackFrame
.callFrame
));
3123 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_strcat
)
3125 STUB_INIT_STACK_FRAME(stackFrame
);
3127 JSValue result
= jsString(stackFrame
.callFrame
, &stackFrame
.callFrame
->registers()[stackFrame
.args
[0].int32()], stackFrame
.args
[1].int32());
3128 CHECK_FOR_EXCEPTION_AT_END();
3129 return JSValue::encode(result
);
3132 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_nstricteq
)
3134 STUB_INIT_STACK_FRAME(stackFrame
);
3136 JSValue src1
= stackFrame
.args
[0].jsValue();
3137 JSValue src2
= stackFrame
.args
[1].jsValue();
3139 bool result
= !JSValue::strictEqual(stackFrame
.callFrame
, src1
, src2
);
3140 CHECK_FOR_EXCEPTION_AT_END();
3141 return JSValue::encode(jsBoolean(result
));
3144 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_to_jsnumber
)
3146 STUB_INIT_STACK_FRAME(stackFrame
);
3148 JSValue src
= stackFrame
.args
[0].jsValue();
3149 CallFrame
* callFrame
= stackFrame
.callFrame
;
3151 JSValue result
= src
.toJSNumber(callFrame
);
3152 CHECK_FOR_EXCEPTION_AT_END();
3153 return JSValue::encode(result
);
3156 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_in
)
3158 STUB_INIT_STACK_FRAME(stackFrame
);
3160 CallFrame
* callFrame
= stackFrame
.callFrame
;
3161 JSValue baseVal
= stackFrame
.args
[1].jsValue();
3163 if (!baseVal
.isObject()) {
3164 CallFrame
* callFrame
= stackFrame
.callFrame
;
3165 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3166 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
3167 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "in", baseVal
, vPCIndex
, codeBlock
);
3168 VM_THROW_EXCEPTION();
3171 JSValue propName
= stackFrame
.args
[0].jsValue();
3172 JSObject
* baseObj
= asObject(baseVal
);
3175 if (propName
.getUInt32(i
))
3176 return JSValue::encode(jsBoolean(baseObj
->hasProperty(callFrame
, i
)));
3178 Identifier
property(callFrame
, propName
.toString(callFrame
));
3179 CHECK_FOR_EXCEPTION();
3180 return JSValue::encode(jsBoolean(baseObj
->hasProperty(callFrame
, property
)));
3183 DEFINE_STUB_FUNCTION(JSObject
*, op_push_new_scope
)
3185 STUB_INIT_STACK_FRAME(stackFrame
);
3187 JSObject
* scope
= new (stackFrame
.globalData
) JSStaticScopeObject(stackFrame
.callFrame
, stackFrame
.args
[0].identifier(), stackFrame
.args
[1].jsValue(), DontDelete
);
3189 CallFrame
* callFrame
= stackFrame
.callFrame
;
3190 callFrame
->setScopeChain(callFrame
->scopeChain()->push(scope
));
3194 DEFINE_STUB_FUNCTION(void, op_jmp_scopes
)
3196 STUB_INIT_STACK_FRAME(stackFrame
);
3198 unsigned count
= stackFrame
.args
[0].int32();
3199 CallFrame
* callFrame
= stackFrame
.callFrame
;
3201 ScopeChainNode
* tmp
= callFrame
->scopeChain();
3204 callFrame
->setScopeChain(tmp
);
3207 DEFINE_STUB_FUNCTION(void, op_put_by_index
)
3209 STUB_INIT_STACK_FRAME(stackFrame
);
3211 CallFrame
* callFrame
= stackFrame
.callFrame
;
3212 unsigned property
= stackFrame
.args
[1].int32();
3214 stackFrame
.args
[0].jsValue().put(callFrame
, property
, stackFrame
.args
[2].jsValue());
3217 DEFINE_STUB_FUNCTION(void*, op_switch_imm
)
3219 STUB_INIT_STACK_FRAME(stackFrame
);
3221 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
3222 unsigned tableIndex
= stackFrame
.args
[1].int32();
3223 CallFrame
* callFrame
= stackFrame
.callFrame
;
3224 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3226 if (scrutinee
.isInt32())
3227 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiForValue(scrutinee
.asInt32()).executableAddress();
3231 if (scrutinee
.getNumber(value
) && ((intValue
= static_cast<int32_t>(value
)) == value
))
3232 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiForValue(intValue
).executableAddress();
3234 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
3238 DEFINE_STUB_FUNCTION(void*, op_switch_char
)
3240 STUB_INIT_STACK_FRAME(stackFrame
);
3242 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
3243 unsigned tableIndex
= stackFrame
.args
[1].int32();
3244 CallFrame
* callFrame
= stackFrame
.callFrame
;
3245 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3247 void* result
= codeBlock
->characterSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
3249 if (scrutinee
.isString()) {
3250 UString::Rep
* value
= asString(scrutinee
)->value(callFrame
).rep();
3251 if (value
->length() == 1)
3252 result
= codeBlock
->characterSwitchJumpTable(tableIndex
).ctiForValue(value
->characters()[0]).executableAddress();
3255 CHECK_FOR_EXCEPTION_AT_END();
3259 DEFINE_STUB_FUNCTION(void*, op_switch_string
)
3261 STUB_INIT_STACK_FRAME(stackFrame
);
3263 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
3264 unsigned tableIndex
= stackFrame
.args
[1].int32();
3265 CallFrame
* callFrame
= stackFrame
.callFrame
;
3266 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3268 void* result
= codeBlock
->stringSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
3270 if (scrutinee
.isString()) {
3271 UString::Rep
* value
= asString(scrutinee
)->value(callFrame
).rep();
3272 result
= codeBlock
->stringSwitchJumpTable(tableIndex
).ctiForValue(value
).executableAddress();
3275 CHECK_FOR_EXCEPTION_AT_END();
3279 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_del_by_val
)
3281 STUB_INIT_STACK_FRAME(stackFrame
);
3283 CallFrame
* callFrame
= stackFrame
.callFrame
;
3285 JSValue baseValue
= stackFrame
.args
[0].jsValue();
3286 JSObject
* baseObj
= baseValue
.toObject(callFrame
); // may throw
3288 JSValue subscript
= stackFrame
.args
[1].jsValue();
3291 if (subscript
.getUInt32(i
))
3292 result
= jsBoolean(baseObj
->deleteProperty(callFrame
, i
));
3294 CHECK_FOR_EXCEPTION();
3295 Identifier
property(callFrame
, subscript
.toString(callFrame
));
3296 CHECK_FOR_EXCEPTION();
3297 result
= jsBoolean(baseObj
->deleteProperty(callFrame
, property
));
3300 CHECK_FOR_EXCEPTION_AT_END();
3301 return JSValue::encode(result
);
3304 DEFINE_STUB_FUNCTION(void, op_put_getter
)
3306 STUB_INIT_STACK_FRAME(stackFrame
);
3308 CallFrame
* callFrame
= stackFrame
.callFrame
;
3310 ASSERT(stackFrame
.args
[0].jsValue().isObject());
3311 JSObject
* baseObj
= asObject(stackFrame
.args
[0].jsValue());
3312 ASSERT(stackFrame
.args
[2].jsValue().isObject());
3313 baseObj
->defineGetter(callFrame
, stackFrame
.args
[1].identifier(), asObject(stackFrame
.args
[2].jsValue()));
3316 DEFINE_STUB_FUNCTION(void, op_put_setter
)
3318 STUB_INIT_STACK_FRAME(stackFrame
);
3320 CallFrame
* callFrame
= stackFrame
.callFrame
;
3322 ASSERT(stackFrame
.args
[0].jsValue().isObject());
3323 JSObject
* baseObj
= asObject(stackFrame
.args
[0].jsValue());
3324 ASSERT(stackFrame
.args
[2].jsValue().isObject());
3325 baseObj
->defineSetter(callFrame
, stackFrame
.args
[1].identifier(), asObject(stackFrame
.args
[2].jsValue()));
3328 DEFINE_STUB_FUNCTION(JSObject
*, op_new_error
)
3330 STUB_INIT_STACK_FRAME(stackFrame
);
3332 CallFrame
* callFrame
= stackFrame
.callFrame
;
3333 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3334 unsigned type
= stackFrame
.args
[0].int32();
3335 JSValue message
= stackFrame
.args
[1].jsValue();
3336 unsigned bytecodeOffset
= stackFrame
.args
[2].int32();
3338 unsigned lineNumber
= codeBlock
->lineNumberForBytecodeOffset(callFrame
, bytecodeOffset
);
3339 return Error::create(callFrame
, static_cast<ErrorType
>(type
), message
.toString(callFrame
), lineNumber
, codeBlock
->ownerExecutable()->sourceID(), codeBlock
->ownerExecutable()->sourceURL());
3342 DEFINE_STUB_FUNCTION(void, op_debug
)
3344 STUB_INIT_STACK_FRAME(stackFrame
);
3346 CallFrame
* callFrame
= stackFrame
.callFrame
;
3348 int debugHookID
= stackFrame
.args
[0].int32();
3349 int firstLine
= stackFrame
.args
[1].int32();
3350 int lastLine
= stackFrame
.args
[2].int32();
3352 stackFrame
.globalData
->interpreter
->debug(callFrame
, static_cast<DebugHookID
>(debugHookID
), firstLine
, lastLine
);
3355 DEFINE_STUB_FUNCTION(EncodedJSValue
, vm_throw
)
3357 STUB_INIT_STACK_FRAME(stackFrame
);
3359 CallFrame
* callFrame
= stackFrame
.callFrame
;
3360 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3361 JSGlobalData
* globalData
= stackFrame
.globalData
;
3363 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, globalData
->exceptionLocation
);
3365 JSValue exceptionValue
= globalData
->exception
;
3366 ASSERT(exceptionValue
);
3367 globalData
->exception
= JSValue();
3369 HandlerInfo
* handler
= globalData
->interpreter
->throwException(callFrame
, exceptionValue
, vPCIndex
, false);
3372 *stackFrame
.exception
= exceptionValue
;
3373 return JSValue::encode(jsNull());
3376 stackFrame
.callFrame
= callFrame
;
3377 void* catchRoutine
= handler
->nativeCode
.executableAddress();
3378 ASSERT(catchRoutine
);
3379 STUB_SET_RETURN_ADDRESS(catchRoutine
);
3380 return JSValue::encode(exceptionValue
);
3383 DEFINE_STUB_FUNCTION(EncodedJSValue
, to_object
)
3385 STUB_INIT_STACK_FRAME(stackFrame
);
3387 CallFrame
* callFrame
= stackFrame
.callFrame
;
3388 return JSValue::encode(stackFrame
.args
[0].jsValue().toObject(callFrame
));
3391 NativeExecutable
* JITThunks::specializedThunk(JSGlobalData
* globalData
, ThunkGenerator generator
)
3393 std::pair
<ThunkMap::iterator
, bool> entry
= m_thunkMap
.add(generator
, 0);
3395 return entry
.first
->second
.get();
3396 entry
.first
->second
= generator(globalData
, m_executablePool
.get());
3397 return entry
.first
->second
.get();
3402 #endif // ENABLE(JIT)