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 "GlobalEvalFunction.h"
43 #include "JSActivation.h"
45 #include "JSByteArray.h"
46 #include "JSFunction.h"
47 #include "JSNotAnObject.h"
48 #include "JSPropertyNameIterator.h"
49 #include "JSStaticScopeObject.h"
51 #include "ObjectPrototype.h"
52 #include "Operations.h"
55 #include "RegExpObject.h"
56 #include "RegExpPrototype.h"
58 #include "SamplingTool.h"
59 #include <wtf/StdLibExtras.h>
67 #if OS(DARWIN) || OS(WINDOWS)
68 #define SYMBOL_STRING(name) "_" #name
70 #define SYMBOL_STRING(name) #name
74 #define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name)
76 #define THUMB_FUNC_PARAM(name)
79 #if OS(LINUX) && CPU(X86_64)
80 #define SYMBOL_STRING_RELOCATION(name) #name "@plt"
82 #define SYMBOL_STRING_RELOCATION(name) SYMBOL_STRING(name)
87 #define HIDE_SYMBOL(name) ".private_extern _" #name
89 // IBM's own file format
90 #define HIDE_SYMBOL(name) ".lglobl " #name
95 || (OS(HPUX) && CPU(IA64)) \
99 #define HIDE_SYMBOL(name) ".hidden " #name
101 #define HIDE_SYMBOL(name)
104 #if USE(JSVALUE32_64)
106 #if COMPILER(GCC) && CPU(X86)
108 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
109 // need to change the assembly trampolines below to match.
110 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment
);
111 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
112 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
113 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline
);
117 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
118 HIDE_SYMBOL(ctiTrampoline
) "\n"
119 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
121 "movl %esp, %ebp" "\n"
125 "subl $0x3c, %esp" "\n"
126 "movl $512, %esi" "\n"
127 "movl 0x58(%esp), %edi" "\n"
128 "call *0x50(%esp)" "\n"
129 "addl $0x3c, %esp" "\n"
138 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
139 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
140 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
141 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
142 "movl %esp, %ecx" "\n"
144 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
145 "addl $0x3c, %esp" "\n"
154 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
155 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
156 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
157 "addl $0x3c, %esp" "\n"
165 #elif COMPILER(GCC) && CPU(X86_64)
167 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
168 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
171 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
172 // need to change the assembly trampolines below to match.
173 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment
);
174 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedRBX
) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
175 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
176 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline
);
179 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
180 HIDE_SYMBOL(ctiTrampoline
) "\n"
181 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
183 "movq %rsp, %rbp" "\n"
189 "subq $0x48, %rsp" "\n"
190 "movq $512, %r12" "\n"
191 "movq $0xFFFF000000000000, %r14" "\n"
192 "movq $0xFFFF000000000002, %r15" "\n"
193 "movq 0x90(%rsp), %r13" "\n"
194 "call *0x80(%rsp)" "\n"
195 "addq $0x48, %rsp" "\n"
206 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
207 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
208 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
209 "movq %rsp, %rdi" "\n"
210 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
211 "addq $0x48, %rsp" "\n"
222 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
223 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
224 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
225 "addq $0x48, %rsp" "\n"
235 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
237 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
238 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
244 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
245 HIDE_SYMBOL(ctiTrampoline
) "\n"
247 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline
) "\n"
248 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
249 "sub sp, sp, #0x3c" "\n"
250 "str lr, [sp, #0x20]" "\n"
251 "str r4, [sp, #0x24]" "\n"
252 "str r5, [sp, #0x28]" "\n"
253 "str r6, [sp, #0x2c]" "\n"
254 "str r1, [sp, #0x30]" "\n"
255 "str r2, [sp, #0x34]" "\n"
256 "str r3, [sp, #0x38]" "\n"
260 "ldr r6, [sp, #0x2c]" "\n"
261 "ldr r5, [sp, #0x28]" "\n"
262 "ldr r4, [sp, #0x24]" "\n"
263 "ldr lr, [sp, #0x20]" "\n"
264 "add sp, sp, #0x3c" "\n"
271 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
272 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
274 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline
) "\n"
275 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
277 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
278 "ldr r6, [sp, #0x2c]" "\n"
279 "ldr r5, [sp, #0x28]" "\n"
280 "ldr r4, [sp, #0x24]" "\n"
281 "ldr lr, [sp, #0x20]" "\n"
282 "add sp, sp, #0x3c" "\n"
289 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
291 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught
) "\n"
292 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
293 "ldr r6, [sp, #0x2c]" "\n"
294 "ldr r5, [sp, #0x28]" "\n"
295 "ldr r4, [sp, #0x24]" "\n"
296 "ldr lr, [sp, #0x20]" "\n"
297 "add sp, sp, #0x3c" "\n"
301 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
304 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
305 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
306 "stmdb sp!, {r1-r3}" "\n"
307 "stmdb sp!, {r4-r8, lr}" "\n"
308 "sub sp, sp, #68" "\n"
311 // r0 contains the code
314 "add sp, sp, #68" "\n"
315 "ldmia sp!, {r4-r8, lr}" "\n"
316 "add sp, sp, #12" "\n"
321 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
322 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
324 "bl " SYMBOL_STRING(cti_vm_throw
) "\n"
326 // Both has the same return sequence
327 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
328 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
329 "add sp, sp, #68" "\n"
330 "ldmia sp!, {r4-r8, lr}" "\n"
331 "add sp, sp, #12" "\n"
335 #elif COMPILER(MSVC) && CPU(X86)
337 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
338 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
341 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
342 // need to change the assembly trampolines below to match.
343 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment
);
344 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
345 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
346 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline
);
350 __declspec(naked
) EncodedJSValue
ctiTrampoline(void* code
, RegisterFile
*, CallFrame
*, JSValue
* exception
, Profiler
**, JSGlobalData
*)
361 mov edi
, [esp
+ 0x58];
372 __declspec(naked
) void ctiVMThrowTrampoline()
386 __declspec(naked
) void ctiOpThrowNotCaught()
400 #error "JIT not supported on this platform."
403 #else // USE(JSVALUE32_64)
405 #if COMPILER(GCC) && CPU(X86)
407 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
408 // need to change the assembly trampolines below to match.
409 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
410 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline
);
411 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
415 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
416 HIDE_SYMBOL(ctiTrampoline
) "\n"
417 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
419 "movl %esp, %ebp" "\n"
423 "subl $0x1c, %esp" "\n"
424 "movl $512, %esi" "\n"
425 "movl 0x38(%esp), %edi" "\n"
426 "call *0x30(%esp)" "\n"
427 "addl $0x1c, %esp" "\n"
436 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
437 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
438 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
439 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
440 "movl %esp, %ecx" "\n"
442 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
443 "addl $0x1c, %esp" "\n"
452 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
453 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
454 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
455 "addl $0x1c, %esp" "\n"
463 #elif COMPILER(GCC) && CPU(X86_64)
465 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
466 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
469 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
470 // need to change the assembly trampolines below to match.
471 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
472 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline
);
473 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedRBX
) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
477 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
478 HIDE_SYMBOL(ctiTrampoline
) "\n"
479 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
481 "movq %rsp, %rbp" "\n"
487 // Form the JIT stubs area
494 "subq $0x48, %rsp" "\n"
495 "movq $512, %r12" "\n"
496 "movq $0xFFFF000000000000, %r14" "\n"
497 "movq $0xFFFF000000000002, %r15" "\n"
498 "movq %rdx, %r13" "\n"
500 "addq $0x78, %rsp" "\n"
511 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
512 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
513 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
514 "movq %rsp, %rdi" "\n"
515 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
516 "addq $0x78, %rsp" "\n"
527 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
528 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
529 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
530 "addq $0x78, %rsp" "\n"
540 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
542 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
543 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
549 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
550 HIDE_SYMBOL(ctiTrampoline
) "\n"
552 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline
) "\n"
553 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
554 "sub sp, sp, #0x40" "\n"
555 "str lr, [sp, #0x20]" "\n"
556 "str r4, [sp, #0x24]" "\n"
557 "str r5, [sp, #0x28]" "\n"
558 "str r6, [sp, #0x2c]" "\n"
559 "str r1, [sp, #0x30]" "\n"
560 "str r2, [sp, #0x34]" "\n"
561 "str r3, [sp, #0x38]" "\n"
565 "ldr r6, [sp, #0x2c]" "\n"
566 "ldr r5, [sp, #0x28]" "\n"
567 "ldr r4, [sp, #0x24]" "\n"
568 "ldr lr, [sp, #0x20]" "\n"
569 "add sp, sp, #0x40" "\n"
576 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
577 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
579 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline
) "\n"
580 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
582 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
583 "ldr r6, [sp, #0x2c]" "\n"
584 "ldr r5, [sp, #0x28]" "\n"
585 "ldr r4, [sp, #0x24]" "\n"
586 "ldr lr, [sp, #0x20]" "\n"
587 "add sp, sp, #0x40" "\n"
594 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
595 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
597 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught
) "\n"
598 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
599 "ldr r6, [sp, #0x2c]" "\n"
600 "ldr r5, [sp, #0x28]" "\n"
601 "ldr r4, [sp, #0x24]" "\n"
602 "ldr lr, [sp, #0x20]" "\n"
603 "add sp, sp, #0x3c" "\n"
607 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
611 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
612 HIDE_SYMBOL(ctiTrampoline
) "\n"
613 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
614 "stmdb sp!, {r1-r3}" "\n"
615 "stmdb sp!, {r4-r8, lr}" "\n"
616 "sub sp, sp, #36" "\n"
621 "add sp, sp, #36" "\n"
622 "ldmia sp!, {r4-r8, lr}" "\n"
623 "add sp, sp, #12" "\n"
628 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
629 HIDE_SYMBOL(ctiVMThrowTrampoline
) "\n"
630 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
632 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw
) "\n"
634 // Both has the same return sequence
635 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
636 HIDE_SYMBOL(ctiOpThrowNotCaught
) "\n"
637 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
638 "add sp, sp, #36" "\n"
639 "ldmia sp!, {r4-r8, lr}" "\n"
640 "add sp, sp, #12" "\n"
644 #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
646 __asm EncodedJSValue
ctiTrampoline(void*, RegisterFile
*, CallFrame
*, JSValue
*, Profiler
**, JSGlobalData
*)
650 stmdb sp
!, {r4
-r8
, lr
}
657 ldmia sp
!, {r4
-r8
, lr
}
662 __asm
void ctiVMThrowTrampoline()
669 ldmia sp
!, {r4
-r8
, lr
}
674 __asm
void ctiOpThrowNotCaught()
678 ldmia sp
!, {r4
-r8
, lr
}
683 #elif COMPILER(MSVC) && CPU(X86)
685 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
686 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
689 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
690 // need to change the assembly trampolines below to match.
691 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
692 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline
);
693 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
697 __declspec(naked
) EncodedJSValue
ctiTrampoline(void* code
, RegisterFile
*, CallFrame
*, JSValue
* exception
, Profiler
**, JSGlobalData
*)
708 mov edi
, [esp
+ 0x38];
719 __declspec(naked
) void ctiVMThrowTrampoline()
733 __declspec(naked
) void ctiOpThrowNotCaught()
747 #error "JIT not supported on this platform."
750 #endif // USE(JSVALUE32_64)
752 #if ENABLE(OPCODE_SAMPLING)
753 #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler()
755 #define CTI_SAMPLER 0
758 JITThunks::JITThunks(JSGlobalData
* globalData
)
760 JIT::compileCTIMachineTrampolines(globalData
, &m_executablePool
, &m_ctiStringLengthTrampoline
, &m_ctiVirtualCallLink
, &m_ctiVirtualCall
, &m_ctiNativeCallThunk
);
763 // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
764 // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
766 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedReturnAddress
) == 0x20);
767 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR4
) == 0x24);
768 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR5
) == 0x28);
769 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR6
) == 0x2c);
771 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, registerFile
) == 0x30);
772 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, callFrame
) == 0x34);
773 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, exception
) == 0x38);
774 // The fifth argument is the first item already on the stack.
775 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, enabledProfilerReference
) == 0x40);
777 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, thunkReturnAddress
) == 0x1C);
781 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
783 NEVER_INLINE
void JITThunks::tryCachePutByID(CallFrame
* callFrame
, CodeBlock
* codeBlock
, ReturnAddressPtr returnAddress
, JSValue baseValue
, const PutPropertySlot
& slot
, StructureStubInfo
* stubInfo
)
785 // The interpreter checks for recursion here; I do not believe this can occur in CTI.
787 if (!baseValue
.isCell())
790 // Uncacheable: give up.
791 if (!slot
.isCacheable()) {
792 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_put_by_id_generic
));
796 JSCell
* baseCell
= asCell(baseValue
);
797 Structure
* structure
= baseCell
->structure();
799 if (structure
->isUncacheableDictionary()) {
800 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_put_by_id_generic
));
804 // If baseCell != base, then baseCell must be a proxy for another object.
805 if (baseCell
!= slot
.base()) {
806 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_put_by_id_generic
));
810 // Cache hit: Specialize instruction and ref Structures.
812 // Structure transition, cache transition info
813 if (slot
.type() == PutPropertySlot::NewProperty
) {
814 if (structure
->isDictionary()) {
815 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_put_by_id_generic
));
819 // put_by_id_transition checks the prototype chain for setters.
820 normalizePrototypeChain(callFrame
, baseCell
);
822 StructureChain
* prototypeChain
= structure
->prototypeChain(callFrame
);
823 stubInfo
->initPutByIdTransition(structure
->previousID(), structure
, prototypeChain
);
824 JIT::compilePutByIdTransition(callFrame
->scopeChain()->globalData
, codeBlock
, stubInfo
, structure
->previousID(), structure
, slot
.cachedOffset(), prototypeChain
, returnAddress
);
828 stubInfo
->initPutByIdReplace(structure
);
830 JIT::patchPutByIdReplace(codeBlock
, stubInfo
, structure
, slot
.cachedOffset(), returnAddress
);
833 NEVER_INLINE
void JITThunks::tryCacheGetByID(CallFrame
* callFrame
, CodeBlock
* codeBlock
, ReturnAddressPtr returnAddress
, JSValue baseValue
, const Identifier
& propertyName
, const PropertySlot
& slot
, StructureStubInfo
* stubInfo
)
835 // FIXME: Write a test that proves we need to check for recursion here just
836 // like the interpreter does, then add a check for recursion.
838 // FIXME: Cache property access for immediates.
839 if (!baseValue
.isCell()) {
840 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
844 JSGlobalData
* globalData
= &callFrame
->globalData();
846 if (isJSArray(globalData
, baseValue
) && propertyName
== callFrame
->propertyNames().length
) {
847 JIT::compilePatchGetArrayLength(callFrame
->scopeChain()->globalData
, codeBlock
, returnAddress
);
851 if (isJSString(globalData
, baseValue
) && propertyName
== callFrame
->propertyNames().length
) {
852 // The tradeoff of compiling an patched inline string length access routine does not seem
853 // to pay off, so we currently only do this for arrays.
854 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, globalData
->jitStubs
.ctiStringLengthTrampoline());
858 // Uncacheable: give up.
859 if (!slot
.isCacheable()) {
860 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
864 JSCell
* baseCell
= asCell(baseValue
);
865 Structure
* structure
= baseCell
->structure();
867 if (structure
->isUncacheableDictionary()) {
868 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
872 // Cache hit: Specialize instruction and ref Structures.
874 if (slot
.slotBase() == baseValue
) {
875 // set this up, so derefStructures can do it's job.
876 stubInfo
->initGetByIdSelf(structure
);
878 JIT::patchGetByIdSelf(codeBlock
, stubInfo
, structure
, slot
.cachedOffset(), returnAddress
);
882 if (structure
->isDictionary()) {
883 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
887 if (slot
.slotBase() == structure
->prototypeForLookup(callFrame
)) {
888 ASSERT(slot
.slotBase().isObject());
890 JSObject
* slotBaseObject
= asObject(slot
.slotBase());
891 size_t offset
= slot
.cachedOffset();
893 // Since we're accessing a prototype in a loop, it's a good bet that it
894 // should not be treated as a dictionary.
895 if (slotBaseObject
->structure()->isDictionary()) {
896 slotBaseObject
->flattenDictionaryObject();
897 offset
= slotBaseObject
->structure()->get(propertyName
);
900 stubInfo
->initGetByIdProto(structure
, slotBaseObject
->structure());
902 ASSERT(!structure
->isDictionary());
903 ASSERT(!slotBaseObject
->structure()->isDictionary());
904 JIT::compileGetByIdProto(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, structure
, slotBaseObject
->structure(), offset
, returnAddress
);
908 size_t offset
= slot
.cachedOffset();
909 size_t count
= normalizePrototypeChain(callFrame
, baseValue
, slot
.slotBase(), propertyName
, offset
);
911 stubInfo
->accessType
= access_get_by_id_generic
;
915 StructureChain
* prototypeChain
= structure
->prototypeChain(callFrame
);
916 stubInfo
->initGetByIdChain(structure
, prototypeChain
);
917 JIT::compileGetByIdChain(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, structure
, prototypeChain
, count
, offset
, returnAddress
);
920 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
922 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
923 #define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args)
925 #define SETUP_VA_LISTL_ARGS
932 static void jscGeneratedNativeCode()
934 // When executing a JIT stub function (which might do an allocation), we hack the return address
935 // to pretend to be executing this function, to keep stack logging tools from blowing out
942 ALWAYS_INLINE
StackHack(JITStackFrame
& stackFrame
)
943 : stackFrame(stackFrame
)
944 , savedReturnAddress(*stackFrame
.returnAddressSlot())
946 *stackFrame
.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode
));
949 ALWAYS_INLINE
~StackHack()
951 *stackFrame
.returnAddressSlot() = savedReturnAddress
;
954 JITStackFrame
& stackFrame
;
955 ReturnAddressPtr savedReturnAddress
;
958 #define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
959 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
960 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
964 #define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS)
965 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
966 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
970 // The reason this is not inlined is to avoid having to do a PIC branch
971 // to get the address of the ctiVMThrowTrampoline function. It's also
972 // good to keep the code size down by leaving as much of the exception
973 // handling code out of line as possible.
974 static NEVER_INLINE
void returnToThrowTrampoline(JSGlobalData
* globalData
, ReturnAddressPtr exceptionLocation
, ReturnAddressPtr
& returnAddressSlot
)
976 ASSERT(globalData
->exception
);
977 globalData
->exceptionLocation
= exceptionLocation
;
978 returnAddressSlot
= ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline
));
981 static NEVER_INLINE
void throwStackOverflowError(CallFrame
* callFrame
, JSGlobalData
* globalData
, ReturnAddressPtr exceptionLocation
, ReturnAddressPtr
& returnAddressSlot
)
983 globalData
->exception
= createStackOverflowError(callFrame
);
984 returnToThrowTrampoline(globalData
, exceptionLocation
, returnAddressSlot
);
987 #define VM_THROW_EXCEPTION() \
989 VM_THROW_EXCEPTION_AT_END(); \
992 #define VM_THROW_EXCEPTION_AT_END() \
993 returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS)
995 #define CHECK_FOR_EXCEPTION() \
997 if (UNLIKELY(stackFrame.globalData->exception)) \
998 VM_THROW_EXCEPTION(); \
1000 #define CHECK_FOR_EXCEPTION_AT_END() \
1002 if (UNLIKELY(stackFrame.globalData->exception)) \
1003 VM_THROW_EXCEPTION_AT_END(); \
1005 #define CHECK_FOR_EXCEPTION_VOID() \
1007 if (UNLIKELY(stackFrame.globalData->exception)) { \
1008 VM_THROW_EXCEPTION_AT_END(); \
1015 #define DEFINE_STUB_FUNCTION(rtype, op) \
1017 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1022 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1023 HIDE_SYMBOL(cti_##op) "\n" \
1025 ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \
1026 SYMBOL_STRING(cti_##op) ":" "\n" \
1027 "str lr, [sp, #0x1c]" "\n" \
1028 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1029 "ldr lr, [sp, #0x1c]" "\n" \
1032 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
1034 #elif CPU(ARM_TRADITIONAL) && COMPILER(GCC)
1036 #if USE(JSVALUE32_64)
1037 #define THUNK_RETURN_ADDRESS_OFFSET 64
1039 #define THUNK_RETURN_ADDRESS_OFFSET 32
1042 COMPILE_ASSERT(offsetof(struct JITStackFrame
, thunkReturnAddress
) == THUNK_RETURN_ADDRESS_OFFSET
, JITStackFrame_thunkReturnAddress_offset_mismatch
);
1044 #define DEFINE_STUB_FUNCTION(rtype, op) \
1046 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1049 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1050 SYMBOL_STRING(cti_##op) ":" "\n" \
1051 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1052 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1053 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1056 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1058 #elif CPU(ARM_TRADITIONAL) && COMPILER(RVCT)
1060 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1062 /* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */
1064 /* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */
1065 /* The pattern "#xxx#" will be replaced with "xxx" */
1068 RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
1069 RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
1072 RVCT( IMPORT JITStubThunked_#op#)
1073 RVCT( str lr, [sp, #32])
1074 RVCT( bl JITStubThunked_#op#)
1075 RVCT( ldr lr, [sp, #32])
1081 /* Include the generated file */
1082 #include "GeneratedJITStubs_RVCT.h"
1085 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
1088 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_convert_this
)
1090 STUB_INIT_STACK_FRAME(stackFrame
);
1092 JSValue v1
= stackFrame
.args
[0].jsValue();
1093 CallFrame
* callFrame
= stackFrame
.callFrame
;
1095 JSObject
* result
= v1
.toThisObject(callFrame
);
1096 CHECK_FOR_EXCEPTION_AT_END();
1097 return JSValue::encode(result
);
1100 DEFINE_STUB_FUNCTION(void, op_end
)
1102 STUB_INIT_STACK_FRAME(stackFrame
);
1104 ScopeChainNode
* scopeChain
= stackFrame
.callFrame
->scopeChain();
1105 ASSERT(scopeChain
->refCount
> 1);
1106 scopeChain
->deref();
1109 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_add
)
1111 STUB_INIT_STACK_FRAME(stackFrame
);
1113 JSValue v1
= stackFrame
.args
[0].jsValue();
1114 JSValue v2
= stackFrame
.args
[1].jsValue();
1115 CallFrame
* callFrame
= stackFrame
.callFrame
;
1117 if (v1
.isString()) {
1118 JSValue result
= v2
.isString()
1119 ? jsString(callFrame
, asString(v1
), asString(v2
))
1120 : jsString(callFrame
, asString(v1
), v2
.toPrimitiveString(callFrame
));
1121 CHECK_FOR_EXCEPTION_AT_END();
1122 return JSValue::encode(result
);
1125 double left
= 0.0, right
;
1126 if (v1
.getNumber(left
) && v2
.getNumber(right
))
1127 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
+ right
));
1129 // All other cases are pretty uncommon
1130 JSValue result
= jsAddSlowCase(callFrame
, v1
, v2
);
1131 CHECK_FOR_EXCEPTION_AT_END();
1132 return JSValue::encode(result
);
1135 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_pre_inc
)
1137 STUB_INIT_STACK_FRAME(stackFrame
);
1139 JSValue v
= stackFrame
.args
[0].jsValue();
1141 CallFrame
* callFrame
= stackFrame
.callFrame
;
1142 JSValue result
= jsNumber(stackFrame
.globalData
, v
.toNumber(callFrame
) + 1);
1143 CHECK_FOR_EXCEPTION_AT_END();
1144 return JSValue::encode(result
);
1147 DEFINE_STUB_FUNCTION(int, timeout_check
)
1149 STUB_INIT_STACK_FRAME(stackFrame
);
1151 JSGlobalData
* globalData
= stackFrame
.globalData
;
1152 TimeoutChecker
& timeoutChecker
= globalData
->timeoutChecker
;
1154 if (timeoutChecker
.didTimeOut(stackFrame
.callFrame
)) {
1155 globalData
->exception
= createInterruptedExecutionException(globalData
);
1156 VM_THROW_EXCEPTION_AT_END();
1159 return timeoutChecker
.ticksUntilNextCheck();
1162 DEFINE_STUB_FUNCTION(void, register_file_check
)
1164 STUB_INIT_STACK_FRAME(stackFrame
);
1166 if (LIKELY(stackFrame
.registerFile
->grow(&stackFrame
.callFrame
->registers()[stackFrame
.callFrame
->codeBlock()->m_numCalleeRegisters
])))
1169 // Rewind to the previous call frame because op_call already optimistically
1170 // moved the call frame forward.
1171 CallFrame
* oldCallFrame
= stackFrame
.callFrame
->callerFrame();
1172 stackFrame
.callFrame
= oldCallFrame
;
1173 throwStackOverflowError(oldCallFrame
, stackFrame
.globalData
, ReturnAddressPtr(oldCallFrame
->returnPC()), STUB_RETURN_ADDRESS
);
1176 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq
)
1178 STUB_INIT_STACK_FRAME(stackFrame
);
1180 JSValue src1
= stackFrame
.args
[0].jsValue();
1181 JSValue src2
= stackFrame
.args
[1].jsValue();
1182 CallFrame
* callFrame
= stackFrame
.callFrame
;
1184 bool result
= jsLessEq(callFrame
, src1
, src2
);
1185 CHECK_FOR_EXCEPTION_AT_END();
1189 DEFINE_STUB_FUNCTION(JSObject
*, op_new_object
)
1191 STUB_INIT_STACK_FRAME(stackFrame
);
1193 return constructEmptyObject(stackFrame
.callFrame
);
1196 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic
)
1198 STUB_INIT_STACK_FRAME(stackFrame
);
1200 PutPropertySlot slot
;
1201 stackFrame
.args
[0].jsValue().put(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), stackFrame
.args
[2].jsValue(), slot
);
1202 CHECK_FOR_EXCEPTION_AT_END();
1205 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_generic
)
1207 STUB_INIT_STACK_FRAME(stackFrame
);
1209 CallFrame
* callFrame
= stackFrame
.callFrame
;
1210 Identifier
& ident
= stackFrame
.args
[1].identifier();
1212 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1213 PropertySlot
slot(baseValue
);
1214 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1216 CHECK_FOR_EXCEPTION_AT_END();
1217 return JSValue::encode(result
);
1220 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1222 DEFINE_STUB_FUNCTION(void, op_put_by_id
)
1224 STUB_INIT_STACK_FRAME(stackFrame
);
1225 CallFrame
* callFrame
= stackFrame
.callFrame
;
1226 Identifier
& ident
= stackFrame
.args
[1].identifier();
1228 PutPropertySlot slot
;
1229 stackFrame
.args
[0].jsValue().put(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1231 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1232 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1233 if (!stubInfo
->seenOnce())
1234 stubInfo
->setSeen();
1236 JITThunks::tryCachePutByID(callFrame
, codeBlock
, STUB_RETURN_ADDRESS
, stackFrame
.args
[0].jsValue(), slot
, stubInfo
);
1238 CHECK_FOR_EXCEPTION_AT_END();
1241 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail
)
1243 STUB_INIT_STACK_FRAME(stackFrame
);
1245 CallFrame
* callFrame
= stackFrame
.callFrame
;
1246 Identifier
& ident
= stackFrame
.args
[1].identifier();
1248 PutPropertySlot slot
;
1249 stackFrame
.args
[0].jsValue().put(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1251 CHECK_FOR_EXCEPTION_AT_END();
1254 DEFINE_STUB_FUNCTION(JSObject
*, op_put_by_id_transition_realloc
)
1256 STUB_INIT_STACK_FRAME(stackFrame
);
1258 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1259 int32_t oldSize
= stackFrame
.args
[3].int32();
1260 int32_t newSize
= stackFrame
.args
[4].int32();
1262 ASSERT(baseValue
.isObject());
1263 JSObject
* base
= asObject(baseValue
);
1264 base
->allocatePropertyStorage(oldSize
, newSize
);
1269 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_method_check
)
1271 STUB_INIT_STACK_FRAME(stackFrame
);
1273 CallFrame
* callFrame
= stackFrame
.callFrame
;
1274 Identifier
& ident
= stackFrame
.args
[1].identifier();
1276 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1277 PropertySlot
slot(baseValue
);
1278 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1279 CHECK_FOR_EXCEPTION();
1281 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1282 MethodCallLinkInfo
& methodCallLinkInfo
= codeBlock
->getMethodCallLinkInfo(STUB_RETURN_ADDRESS
);
1284 if (!methodCallLinkInfo
.seenOnce()) {
1285 methodCallLinkInfo
.setSeen();
1286 return JSValue::encode(result
);
1289 // If we successfully got something, then the base from which it is being accessed must
1290 // be an object. (Assertion to ensure asObject() call below is safe, which comes after
1291 // an isCacheable() chceck.
1292 ASSERT(!slot
.isCacheable() || slot
.slotBase().isObject());
1295 // * We're dealing with a JSCell,
1296 // * the property is cachable,
1297 // * it's not a dictionary
1298 // * there is a function cached.
1299 Structure
* structure
;
1301 JSObject
* slotBaseObject
;
1302 if (baseValue
.isCell()
1303 && slot
.isCacheable()
1304 && !(structure
= asCell(baseValue
)->structure())->isUncacheableDictionary()
1305 && (slotBaseObject
= asObject(slot
.slotBase()))->getPropertySpecificValue(callFrame
, ident
, specific
)
1309 JSFunction
* callee
= (JSFunction
*)specific
;
1311 // Since we're accessing a prototype in a loop, it's a good bet that it
1312 // should not be treated as a dictionary.
1313 if (slotBaseObject
->structure()->isDictionary())
1314 slotBaseObject
->flattenDictionaryObject();
1316 // The result fetched should always be the callee!
1317 ASSERT(result
== JSValue(callee
));
1319 // Check to see if the function is on the object's prototype. Patch up the code to optimize.
1320 if (slot
.slotBase() == structure
->prototypeForLookup(callFrame
)) {
1321 JIT::patchMethodCallProto(codeBlock
, methodCallLinkInfo
, callee
, structure
, slotBaseObject
, STUB_RETURN_ADDRESS
);
1322 return JSValue::encode(result
);
1325 // Check to see if the function is on the object itself.
1326 // Since we generate the method-check to check both the structure and a prototype-structure (since this
1327 // is the common case) we have a problem - we need to patch the prototype structure check to do something
1328 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler
1329 // for now. For now it performs a check on a special object on the global object only used for this
1330 // purpose. The object is in no way exposed, and as such the check will always pass.
1331 if (slot
.slotBase() == baseValue
) {
1332 JIT::patchMethodCallProto(codeBlock
, methodCallLinkInfo
, callee
, structure
, callFrame
->scopeChain()->globalObject
->methodCallDummy(), STUB_RETURN_ADDRESS
);
1333 return JSValue::encode(result
);
1337 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
1338 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id
));
1339 return JSValue::encode(result
);
1342 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id
)
1344 STUB_INIT_STACK_FRAME(stackFrame
);
1345 CallFrame
* callFrame
= stackFrame
.callFrame
;
1346 Identifier
& ident
= stackFrame
.args
[1].identifier();
1348 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1349 PropertySlot
slot(baseValue
);
1350 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1352 CodeBlock
* codeBlock
= stackFrame
.callFrame
->codeBlock();
1353 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1354 if (!stubInfo
->seenOnce())
1355 stubInfo
->setSeen();
1357 JITThunks::tryCacheGetByID(callFrame
, codeBlock
, STUB_RETURN_ADDRESS
, baseValue
, ident
, slot
, stubInfo
);
1359 CHECK_FOR_EXCEPTION_AT_END();
1360 return JSValue::encode(result
);
1363 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_self_fail
)
1365 STUB_INIT_STACK_FRAME(stackFrame
);
1367 CallFrame
* callFrame
= stackFrame
.callFrame
;
1368 Identifier
& ident
= stackFrame
.args
[1].identifier();
1370 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1371 PropertySlot
slot(baseValue
);
1372 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1374 CHECK_FOR_EXCEPTION();
1376 if (baseValue
.isCell()
1377 && slot
.isCacheable()
1378 && !asCell(baseValue
)->structure()->isUncacheableDictionary()
1379 && slot
.slotBase() == baseValue
) {
1381 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1382 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1384 ASSERT(slot
.slotBase().isObject());
1386 PolymorphicAccessStructureList
* polymorphicStructureList
;
1389 if (stubInfo
->accessType
== access_get_by_id_self
) {
1390 ASSERT(!stubInfo
->stubRoutine
);
1391 polymorphicStructureList
= new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo
->u
.getByIdSelf
.baseObjectStructure
);
1392 stubInfo
->initGetByIdSelfList(polymorphicStructureList
, 2);
1394 polymorphicStructureList
= stubInfo
->u
.getByIdSelfList
.structureList
;
1395 listIndex
= stubInfo
->u
.getByIdSelfList
.listSize
;
1396 stubInfo
->u
.getByIdSelfList
.listSize
++;
1399 JIT::compileGetByIdSelfList(callFrame
->scopeChain()->globalData
, codeBlock
, stubInfo
, polymorphicStructureList
, listIndex
, asCell(baseValue
)->structure(), slot
.cachedOffset());
1401 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1402 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_generic
));
1404 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_generic
));
1405 return JSValue::encode(result
);
1408 static PolymorphicAccessStructureList
* getPolymorphicAccessStructureListSlot(StructureStubInfo
* stubInfo
, int& listIndex
)
1410 PolymorphicAccessStructureList
* prototypeStructureList
= 0;
1413 switch (stubInfo
->accessType
) {
1414 case access_get_by_id_proto
:
1415 prototypeStructureList
= new PolymorphicAccessStructureList(stubInfo
->stubRoutine
, stubInfo
->u
.getByIdProto
.baseObjectStructure
, stubInfo
->u
.getByIdProto
.prototypeStructure
);
1416 stubInfo
->stubRoutine
= CodeLocationLabel();
1417 stubInfo
->initGetByIdProtoList(prototypeStructureList
, 2);
1419 case access_get_by_id_chain
:
1420 prototypeStructureList
= new PolymorphicAccessStructureList(stubInfo
->stubRoutine
, stubInfo
->u
.getByIdChain
.baseObjectStructure
, stubInfo
->u
.getByIdChain
.chain
);
1421 stubInfo
->stubRoutine
= CodeLocationLabel();
1422 stubInfo
->initGetByIdProtoList(prototypeStructureList
, 2);
1424 case access_get_by_id_proto_list
:
1425 prototypeStructureList
= stubInfo
->u
.getByIdProtoList
.structureList
;
1426 listIndex
= stubInfo
->u
.getByIdProtoList
.listSize
;
1427 stubInfo
->u
.getByIdProtoList
.listSize
++;
1430 ASSERT_NOT_REACHED();
1433 ASSERT(listIndex
< POLYMORPHIC_LIST_CACHE_SIZE
);
1434 return prototypeStructureList
;
1437 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_list
)
1439 STUB_INIT_STACK_FRAME(stackFrame
);
1441 CallFrame
* callFrame
= stackFrame
.callFrame
;
1442 const Identifier
& propertyName
= stackFrame
.args
[1].identifier();
1444 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1445 PropertySlot
slot(baseValue
);
1446 JSValue result
= baseValue
.get(callFrame
, propertyName
, slot
);
1448 CHECK_FOR_EXCEPTION();
1450 if (!baseValue
.isCell() || !slot
.isCacheable() || asCell(baseValue
)->structure()->isDictionary()) {
1451 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1452 return JSValue::encode(result
);
1455 Structure
* structure
= asCell(baseValue
)->structure();
1456 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1457 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1459 ASSERT(slot
.slotBase().isObject());
1460 JSObject
* slotBaseObject
= asObject(slot
.slotBase());
1462 size_t offset
= slot
.cachedOffset();
1464 if (slot
.slotBase() == baseValue
)
1465 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1466 else if (slot
.slotBase() == asCell(baseValue
)->structure()->prototypeForLookup(callFrame
)) {
1467 ASSERT(!asCell(baseValue
)->structure()->isDictionary());
1468 // Since we're accessing a prototype in a loop, it's a good bet that it
1469 // should not be treated as a dictionary.
1470 if (slotBaseObject
->structure()->isDictionary()) {
1471 slotBaseObject
->flattenDictionaryObject();
1472 offset
= slotBaseObject
->structure()->get(propertyName
);
1476 PolymorphicAccessStructureList
* prototypeStructureList
= getPolymorphicAccessStructureListSlot(stubInfo
, listIndex
);
1478 JIT::compileGetByIdProtoList(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, prototypeStructureList
, listIndex
, structure
, slotBaseObject
->structure(), offset
);
1480 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1481 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_list_full
));
1482 } else if (size_t count
= normalizePrototypeChain(callFrame
, baseValue
, slot
.slotBase(), propertyName
, offset
)) {
1483 ASSERT(!asCell(baseValue
)->structure()->isDictionary());
1485 PolymorphicAccessStructureList
* prototypeStructureList
= getPolymorphicAccessStructureListSlot(stubInfo
, listIndex
);
1487 StructureChain
* protoChain
= structure
->prototypeChain(callFrame
);
1488 JIT::compileGetByIdChainList(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, prototypeStructureList
, listIndex
, structure
, protoChain
, count
, offset
);
1490 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1491 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_list_full
));
1493 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1495 return JSValue::encode(result
);
1498 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_list_full
)
1500 STUB_INIT_STACK_FRAME(stackFrame
);
1502 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1503 PropertySlot
slot(baseValue
);
1504 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1506 CHECK_FOR_EXCEPTION_AT_END();
1507 return JSValue::encode(result
);
1510 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_fail
)
1512 STUB_INIT_STACK_FRAME(stackFrame
);
1514 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1515 PropertySlot
slot(baseValue
);
1516 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1518 CHECK_FOR_EXCEPTION_AT_END();
1519 return JSValue::encode(result
);
1522 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_array_fail
)
1524 STUB_INIT_STACK_FRAME(stackFrame
);
1526 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1527 PropertySlot
slot(baseValue
);
1528 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1530 CHECK_FOR_EXCEPTION_AT_END();
1531 return JSValue::encode(result
);
1534 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_string_fail
)
1536 STUB_INIT_STACK_FRAME(stackFrame
);
1538 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1539 PropertySlot
slot(baseValue
);
1540 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1542 CHECK_FOR_EXCEPTION_AT_END();
1543 return JSValue::encode(result
);
1546 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1548 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_instanceof
)
1550 STUB_INIT_STACK_FRAME(stackFrame
);
1552 CallFrame
* callFrame
= stackFrame
.callFrame
;
1553 JSValue value
= stackFrame
.args
[0].jsValue();
1554 JSValue baseVal
= stackFrame
.args
[1].jsValue();
1555 JSValue proto
= stackFrame
.args
[2].jsValue();
1557 // At least one of these checks must have failed to get to the slow case.
1558 ASSERT(!value
.isCell() || !baseVal
.isCell() || !proto
.isCell()
1559 || !value
.isObject() || !baseVal
.isObject() || !proto
.isObject()
1560 || (asObject(baseVal
)->structure()->typeInfo().flags() & (ImplementsHasInstance
| OverridesHasInstance
)) != ImplementsHasInstance
);
1563 // ECMA-262 15.3.5.3:
1564 // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
1565 TypeInfo
typeInfo(UnspecifiedType
);
1566 if (!baseVal
.isObject() || !(typeInfo
= asObject(baseVal
)->structure()->typeInfo()).implementsHasInstance()) {
1567 CallFrame
* callFrame
= stackFrame
.callFrame
;
1568 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1569 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1570 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "instanceof", baseVal
, vPCIndex
, codeBlock
);
1571 VM_THROW_EXCEPTION();
1573 ASSERT(typeInfo
.type() != UnspecifiedType
);
1575 if (!typeInfo
.overridesHasInstance()) {
1576 if (!value
.isObject())
1577 return JSValue::encode(jsBoolean(false));
1579 if (!proto
.isObject()) {
1580 throwError(callFrame
, TypeError
, "instanceof called on an object with an invalid prototype property.");
1581 VM_THROW_EXCEPTION();
1585 JSValue result
= jsBoolean(asObject(baseVal
)->hasInstance(callFrame
, value
, proto
));
1586 CHECK_FOR_EXCEPTION_AT_END();
1588 return JSValue::encode(result
);
1591 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_del_by_id
)
1593 STUB_INIT_STACK_FRAME(stackFrame
);
1595 CallFrame
* callFrame
= stackFrame
.callFrame
;
1597 JSObject
* baseObj
= stackFrame
.args
[0].jsValue().toObject(callFrame
);
1599 JSValue result
= jsBoolean(baseObj
->deleteProperty(callFrame
, stackFrame
.args
[1].identifier()));
1600 CHECK_FOR_EXCEPTION_AT_END();
1601 return JSValue::encode(result
);
1604 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_mul
)
1606 STUB_INIT_STACK_FRAME(stackFrame
);
1608 JSValue src1
= stackFrame
.args
[0].jsValue();
1609 JSValue src2
= stackFrame
.args
[1].jsValue();
1613 if (src1
.getNumber(left
) && src2
.getNumber(right
))
1614 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
* right
));
1616 CallFrame
* callFrame
= stackFrame
.callFrame
;
1617 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toNumber(callFrame
) * src2
.toNumber(callFrame
));
1618 CHECK_FOR_EXCEPTION_AT_END();
1619 return JSValue::encode(result
);
1622 DEFINE_STUB_FUNCTION(JSObject
*, op_new_func
)
1624 STUB_INIT_STACK_FRAME(stackFrame
);
1626 return stackFrame
.args
[0].function()->make(stackFrame
.callFrame
, stackFrame
.callFrame
->scopeChain());
1629 DEFINE_STUB_FUNCTION(void*, op_call_JSFunction
)
1631 STUB_INIT_STACK_FRAME(stackFrame
);
1633 #if !ASSERT_DISABLED
1635 ASSERT(stackFrame
.args
[0].jsValue().getCallData(callData
) == CallTypeJS
);
1638 JSFunction
* function
= asFunction(stackFrame
.args
[0].jsValue());
1639 ASSERT(!function
->isHostFunction());
1640 FunctionExecutable
* executable
= function
->jsExecutable();
1641 ScopeChainNode
* callDataScopeChain
= function
->scope().node();
1642 executable
->jitCode(stackFrame
.callFrame
, callDataScopeChain
);
1647 DEFINE_STUB_FUNCTION(VoidPtrPair
, op_call_arityCheck
)
1649 STUB_INIT_STACK_FRAME(stackFrame
);
1651 CallFrame
* callFrame
= stackFrame
.callFrame
;
1652 JSFunction
* callee
= asFunction(stackFrame
.args
[0].jsValue());
1653 ASSERT(!callee
->isHostFunction());
1654 CodeBlock
* newCodeBlock
= &callee
->jsExecutable()->generatedBytecode();
1655 int argCount
= stackFrame
.args
[2].int32();
1657 ASSERT(argCount
!= newCodeBlock
->m_numParameters
);
1659 CallFrame
* oldCallFrame
= callFrame
->callerFrame();
1661 if (argCount
> newCodeBlock
->m_numParameters
) {
1662 size_t numParameters
= newCodeBlock
->m_numParameters
;
1663 Register
* r
= callFrame
->registers() + numParameters
;
1665 Register
* argv
= r
- RegisterFile::CallFrameHeaderSize
- numParameters
- argCount
;
1666 for (size_t i
= 0; i
< numParameters
; ++i
)
1667 argv
[i
+ argCount
] = argv
[i
];
1669 callFrame
= CallFrame::create(r
);
1670 callFrame
->setCallerFrame(oldCallFrame
);
1672 size_t omittedArgCount
= newCodeBlock
->m_numParameters
- argCount
;
1673 Register
* r
= callFrame
->registers() + omittedArgCount
;
1674 Register
* newEnd
= r
+ newCodeBlock
->m_numCalleeRegisters
;
1675 if (!stackFrame
.registerFile
->grow(newEnd
)) {
1676 // Rewind to the previous call frame because op_call already optimistically
1677 // moved the call frame forward.
1678 stackFrame
.callFrame
= oldCallFrame
;
1679 throwStackOverflowError(oldCallFrame
, stackFrame
.globalData
, stackFrame
.args
[1].returnAddress(), STUB_RETURN_ADDRESS
);
1680 RETURN_POINTER_PAIR(0, 0);
1683 Register
* argv
= r
- RegisterFile::CallFrameHeaderSize
- omittedArgCount
;
1684 for (size_t i
= 0; i
< omittedArgCount
; ++i
)
1685 argv
[i
] = jsUndefined();
1687 callFrame
= CallFrame::create(r
);
1688 callFrame
->setCallerFrame(oldCallFrame
);
1691 RETURN_POINTER_PAIR(callee
, callFrame
);
1694 #if ENABLE(JIT_OPTIMIZE_CALL)
1695 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall
)
1697 STUB_INIT_STACK_FRAME(stackFrame
);
1698 JSFunction
* callee
= asFunction(stackFrame
.args
[0].jsValue());
1699 ExecutableBase
* executable
= callee
->executable();
1700 JITCode
& jitCode
= executable
->generatedJITCode();
1702 CodeBlock
* codeBlock
= 0;
1703 if (!executable
->isHostFunction())
1704 codeBlock
= &static_cast<FunctionExecutable
*>(executable
)->bytecode(stackFrame
.callFrame
, callee
->scope().node());
1705 CallLinkInfo
* callLinkInfo
= &stackFrame
.callFrame
->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame
.args
[1].returnAddress());
1707 if (!callLinkInfo
->seenOnce())
1708 callLinkInfo
->setSeen();
1710 JIT::linkCall(callee
, stackFrame
.callFrame
->callerFrame()->codeBlock(), codeBlock
, jitCode
, callLinkInfo
, stackFrame
.args
[2].int32(), stackFrame
.globalData
);
1712 return jitCode
.addressForCall().executableAddress();
1714 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
1716 DEFINE_STUB_FUNCTION(JSObject
*, op_push_activation
)
1718 STUB_INIT_STACK_FRAME(stackFrame
);
1720 JSActivation
* activation
= new (stackFrame
.globalData
) JSActivation(stackFrame
.callFrame
, static_cast<FunctionExecutable
*>(stackFrame
.callFrame
->codeBlock()->ownerExecutable()));
1721 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->copy()->push(activation
));
1725 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_call_NotJSFunction
)
1727 STUB_INIT_STACK_FRAME(stackFrame
);
1729 JSValue funcVal
= stackFrame
.args
[0].jsValue();
1732 CallType callType
= funcVal
.getCallData(callData
);
1734 ASSERT(callType
!= CallTypeJS
);
1736 if (callType
== CallTypeHost
) {
1737 int registerOffset
= stackFrame
.args
[1].int32();
1738 int argCount
= stackFrame
.args
[2].int32();
1739 CallFrame
* previousCallFrame
= stackFrame
.callFrame
;
1740 CallFrame
* callFrame
= CallFrame::create(previousCallFrame
->registers() + registerOffset
);
1742 callFrame
->init(0, static_cast<Instruction
*>((STUB_RETURN_ADDRESS
).value()), previousCallFrame
->scopeChain(), previousCallFrame
, 0, argCount
, 0);
1743 stackFrame
.callFrame
= callFrame
;
1745 Register
* argv
= stackFrame
.callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- argCount
;
1746 ArgList
argList(argv
+ 1, argCount
- 1);
1748 JSValue returnValue
;
1750 SamplingTool::HostCallRecord
callRecord(CTI_SAMPLER
);
1752 // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
1753 JSValue thisValue
= argv
[0].jsValue();
1754 if (thisValue
== jsNull())
1755 thisValue
= callFrame
->globalThisValue();
1757 returnValue
= callData
.native
.function(callFrame
, asObject(funcVal
), thisValue
, argList
);
1759 stackFrame
.callFrame
= previousCallFrame
;
1760 CHECK_FOR_EXCEPTION();
1762 return JSValue::encode(returnValue
);
1765 ASSERT(callType
== CallTypeNone
);
1767 CallFrame
* callFrame
= stackFrame
.callFrame
;
1768 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1769 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1770 stackFrame
.globalData
->exception
= createNotAFunctionError(stackFrame
.callFrame
, funcVal
, vPCIndex
, codeBlock
);
1771 VM_THROW_EXCEPTION();
1774 DEFINE_STUB_FUNCTION(void, op_create_arguments
)
1776 STUB_INIT_STACK_FRAME(stackFrame
);
1778 Arguments
* arguments
= new (stackFrame
.globalData
) Arguments(stackFrame
.callFrame
);
1779 stackFrame
.callFrame
->setCalleeArguments(arguments
);
1780 stackFrame
.callFrame
[RegisterFile::ArgumentsRegister
] = JSValue(arguments
);
1783 DEFINE_STUB_FUNCTION(void, op_create_arguments_no_params
)
1785 STUB_INIT_STACK_FRAME(stackFrame
);
1787 Arguments
* arguments
= new (stackFrame
.globalData
) Arguments(stackFrame
.callFrame
, Arguments::NoParameters
);
1788 stackFrame
.callFrame
->setCalleeArguments(arguments
);
1789 stackFrame
.callFrame
[RegisterFile::ArgumentsRegister
] = JSValue(arguments
);
1792 DEFINE_STUB_FUNCTION(void, op_tear_off_activation
)
1794 STUB_INIT_STACK_FRAME(stackFrame
);
1796 ASSERT(stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
1797 asActivation(stackFrame
.args
[0].jsValue())->copyRegisters(stackFrame
.callFrame
->optionalCalleeArguments());
1800 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments
)
1802 STUB_INIT_STACK_FRAME(stackFrame
);
1804 ASSERT(stackFrame
.callFrame
->codeBlock()->usesArguments() && !stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
1805 if (stackFrame
.callFrame
->optionalCalleeArguments())
1806 stackFrame
.callFrame
->optionalCalleeArguments()->copyRegisters();
1809 DEFINE_STUB_FUNCTION(void, op_profile_will_call
)
1811 STUB_INIT_STACK_FRAME(stackFrame
);
1813 ASSERT(*stackFrame
.enabledProfilerReference
);
1814 (*stackFrame
.enabledProfilerReference
)->willExecute(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue());
1817 DEFINE_STUB_FUNCTION(void, op_profile_did_call
)
1819 STUB_INIT_STACK_FRAME(stackFrame
);
1821 ASSERT(*stackFrame
.enabledProfilerReference
);
1822 (*stackFrame
.enabledProfilerReference
)->didExecute(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue());
1825 DEFINE_STUB_FUNCTION(void, op_ret_scopeChain
)
1827 STUB_INIT_STACK_FRAME(stackFrame
);
1829 ASSERT(stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
1830 stackFrame
.callFrame
->scopeChain()->deref();
1833 DEFINE_STUB_FUNCTION(JSObject
*, op_new_array
)
1835 STUB_INIT_STACK_FRAME(stackFrame
);
1837 ArgList
argList(&stackFrame
.callFrame
->registers()[stackFrame
.args
[0].int32()], stackFrame
.args
[1].int32());
1838 return constructArray(stackFrame
.callFrame
, argList
);
1841 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve
)
1843 STUB_INIT_STACK_FRAME(stackFrame
);
1845 CallFrame
* callFrame
= stackFrame
.callFrame
;
1846 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
1848 ScopeChainIterator iter
= scopeChain
->begin();
1849 ScopeChainIterator end
= scopeChain
->end();
1850 ASSERT(iter
!= end
);
1852 Identifier
& ident
= stackFrame
.args
[0].identifier();
1854 JSObject
* o
= *iter
;
1855 PropertySlot
slot(o
);
1856 if (o
->getPropertySlot(callFrame
, ident
, slot
)) {
1857 JSValue result
= slot
.getValue(callFrame
, ident
);
1858 CHECK_FOR_EXCEPTION_AT_END();
1859 return JSValue::encode(result
);
1861 } while (++iter
!= end
);
1863 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1864 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1865 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, codeBlock
);
1866 VM_THROW_EXCEPTION();
1869 DEFINE_STUB_FUNCTION(JSObject
*, op_construct_JSConstruct
)
1871 STUB_INIT_STACK_FRAME(stackFrame
);
1873 JSFunction
* constructor
= asFunction(stackFrame
.args
[0].jsValue());
1874 if (constructor
->isHostFunction()) {
1875 CallFrame
* callFrame
= stackFrame
.callFrame
;
1876 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1877 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1878 stackFrame
.globalData
->exception
= createNotAConstructorError(callFrame
, constructor
, vPCIndex
, codeBlock
);
1879 VM_THROW_EXCEPTION();
1882 #if !ASSERT_DISABLED
1883 ConstructData constructData
;
1884 ASSERT(constructor
->getConstructData(constructData
) == ConstructTypeJS
);
1887 Structure
* structure
;
1888 if (stackFrame
.args
[3].jsValue().isObject())
1889 structure
= asObject(stackFrame
.args
[3].jsValue())->inheritorID();
1891 structure
= constructor
->scope().node()->globalObject
->emptyObjectStructure();
1892 return new (stackFrame
.globalData
) JSObject(structure
);
1895 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_construct_NotJSConstruct
)
1897 STUB_INIT_STACK_FRAME(stackFrame
);
1899 CallFrame
* callFrame
= stackFrame
.callFrame
;
1901 JSValue constrVal
= stackFrame
.args
[0].jsValue();
1902 int argCount
= stackFrame
.args
[2].int32();
1903 int thisRegister
= stackFrame
.args
[4].int32();
1905 ConstructData constructData
;
1906 ConstructType constructType
= constrVal
.getConstructData(constructData
);
1908 if (constructType
== ConstructTypeHost
) {
1909 ArgList
argList(callFrame
->registers() + thisRegister
+ 1, argCount
- 1);
1911 JSValue returnValue
;
1913 SamplingTool::HostCallRecord
callRecord(CTI_SAMPLER
);
1914 returnValue
= constructData
.native
.function(callFrame
, asObject(constrVal
), argList
);
1916 CHECK_FOR_EXCEPTION();
1918 return JSValue::encode(returnValue
);
1921 ASSERT(constructType
== ConstructTypeNone
);
1923 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1924 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1925 stackFrame
.globalData
->exception
= createNotAConstructorError(callFrame
, constrVal
, vPCIndex
, codeBlock
);
1926 VM_THROW_EXCEPTION();
1929 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val
)
1931 STUB_INIT_STACK_FRAME(stackFrame
);
1933 CallFrame
* callFrame
= stackFrame
.callFrame
;
1934 JSGlobalData
* globalData
= stackFrame
.globalData
;
1936 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1937 JSValue subscript
= stackFrame
.args
[1].jsValue();
1941 if (LIKELY(subscript
.isUInt32())) {
1942 uint32_t i
= subscript
.asUInt32();
1943 if (isJSArray(globalData
, baseValue
)) {
1944 JSArray
* jsArray
= asArray(baseValue
);
1945 if (jsArray
->canGetIndex(i
))
1946 result
= jsArray
->getIndex(i
);
1948 result
= jsArray
->JSArray::get(callFrame
, i
);
1949 } else if (isJSString(globalData
, baseValue
) && asString(baseValue
)->canGetIndex(i
)) {
1950 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1951 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val_string
));
1952 result
= asString(baseValue
)->getIndex(callFrame
, i
);
1953 } else if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
1954 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1955 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val_byte_array
));
1956 return JSValue::encode(asByteArray(baseValue
)->getIndex(callFrame
, i
));
1958 result
= baseValue
.get(callFrame
, i
);
1960 Identifier
property(callFrame
, subscript
.toString(callFrame
));
1961 result
= baseValue
.get(callFrame
, property
);
1964 CHECK_FOR_EXCEPTION_AT_END();
1965 return JSValue::encode(result
);
1968 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val_string
)
1970 STUB_INIT_STACK_FRAME(stackFrame
);
1972 CallFrame
* callFrame
= stackFrame
.callFrame
;
1973 JSGlobalData
* globalData
= stackFrame
.globalData
;
1975 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1976 JSValue subscript
= stackFrame
.args
[1].jsValue();
1980 if (LIKELY(subscript
.isUInt32())) {
1981 uint32_t i
= subscript
.asUInt32();
1982 if (isJSString(globalData
, baseValue
) && asString(baseValue
)->canGetIndex(i
))
1983 result
= asString(baseValue
)->getIndex(callFrame
, i
);
1985 result
= baseValue
.get(callFrame
, i
);
1986 if (!isJSString(globalData
, baseValue
))
1987 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val
));
1990 Identifier
property(callFrame
, subscript
.toString(callFrame
));
1991 result
= baseValue
.get(callFrame
, property
);
1994 CHECK_FOR_EXCEPTION_AT_END();
1995 return JSValue::encode(result
);
1998 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val_byte_array
)
2000 STUB_INIT_STACK_FRAME(stackFrame
);
2002 CallFrame
* callFrame
= stackFrame
.callFrame
;
2003 JSGlobalData
* globalData
= stackFrame
.globalData
;
2005 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2006 JSValue subscript
= stackFrame
.args
[1].jsValue();
2010 if (LIKELY(subscript
.isUInt32())) {
2011 uint32_t i
= subscript
.asUInt32();
2012 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2013 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2014 return JSValue::encode(asByteArray(baseValue
)->getIndex(callFrame
, i
));
2017 result
= baseValue
.get(callFrame
, i
);
2018 if (!isJSByteArray(globalData
, baseValue
))
2019 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val
));
2021 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2022 result
= baseValue
.get(callFrame
, property
);
2025 CHECK_FOR_EXCEPTION_AT_END();
2026 return JSValue::encode(result
);
2029 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_sub
)
2031 STUB_INIT_STACK_FRAME(stackFrame
);
2033 JSValue src1
= stackFrame
.args
[0].jsValue();
2034 JSValue src2
= stackFrame
.args
[1].jsValue();
2038 if (src1
.getNumber(left
) && src2
.getNumber(right
))
2039 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
- right
));
2041 CallFrame
* callFrame
= stackFrame
.callFrame
;
2042 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toNumber(callFrame
) - src2
.toNumber(callFrame
));
2043 CHECK_FOR_EXCEPTION_AT_END();
2044 return JSValue::encode(result
);
2047 DEFINE_STUB_FUNCTION(void, op_put_by_val
)
2049 STUB_INIT_STACK_FRAME(stackFrame
);
2051 CallFrame
* callFrame
= stackFrame
.callFrame
;
2052 JSGlobalData
* globalData
= stackFrame
.globalData
;
2054 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2055 JSValue subscript
= stackFrame
.args
[1].jsValue();
2056 JSValue value
= stackFrame
.args
[2].jsValue();
2058 if (LIKELY(subscript
.isUInt32())) {
2059 uint32_t i
= subscript
.asUInt32();
2060 if (isJSArray(globalData
, baseValue
)) {
2061 JSArray
* jsArray
= asArray(baseValue
);
2062 if (jsArray
->canSetIndex(i
))
2063 jsArray
->setIndex(i
, value
);
2065 jsArray
->JSArray::put(callFrame
, i
, value
);
2066 } else if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2067 JSByteArray
* jsByteArray
= asByteArray(baseValue
);
2068 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_put_by_val_byte_array
));
2069 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2070 if (value
.isInt32()) {
2071 jsByteArray
->setIndex(i
, value
.asInt32());
2075 if (value
.getNumber(dValue
)) {
2076 jsByteArray
->setIndex(i
, dValue
);
2081 baseValue
.put(callFrame
, i
, value
);
2083 baseValue
.put(callFrame
, i
, value
);
2085 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2086 if (!stackFrame
.globalData
->exception
) { // Don't put to an object if toString threw an exception.
2087 PutPropertySlot slot
;
2088 baseValue
.put(callFrame
, property
, value
, slot
);
2092 CHECK_FOR_EXCEPTION_AT_END();
2095 DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array
)
2097 STUB_INIT_STACK_FRAME(stackFrame
);
2099 CallFrame
* callFrame
= stackFrame
.callFrame
;
2100 JSGlobalData
* globalData
= stackFrame
.globalData
;
2102 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2103 JSValue subscript
= stackFrame
.args
[1].jsValue();
2104 JSValue value
= stackFrame
.args
[2].jsValue();
2106 if (LIKELY(subscript
.isUInt32())) {
2107 uint32_t i
= subscript
.asUInt32();
2108 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
2109 JSByteArray
* jsByteArray
= asByteArray(baseValue
);
2111 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2112 if (value
.isInt32()) {
2113 jsByteArray
->setIndex(i
, value
.asInt32());
2117 if (value
.getNumber(dValue
)) {
2118 jsByteArray
->setIndex(i
, dValue
);
2124 if (!isJSByteArray(globalData
, baseValue
))
2125 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_put_by_val
));
2126 baseValue
.put(callFrame
, i
, value
);
2128 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2129 if (!stackFrame
.globalData
->exception
) { // Don't put to an object if toString threw an exception.
2130 PutPropertySlot slot
;
2131 baseValue
.put(callFrame
, property
, value
, slot
);
2135 CHECK_FOR_EXCEPTION_AT_END();
2138 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_lesseq
)
2140 STUB_INIT_STACK_FRAME(stackFrame
);
2142 CallFrame
* callFrame
= stackFrame
.callFrame
;
2143 JSValue result
= jsBoolean(jsLessEq(callFrame
, stackFrame
.args
[0].jsValue(), stackFrame
.args
[1].jsValue()));
2144 CHECK_FOR_EXCEPTION_AT_END();
2145 return JSValue::encode(result
);
2148 DEFINE_STUB_FUNCTION(int, op_load_varargs
)
2150 STUB_INIT_STACK_FRAME(stackFrame
);
2152 CallFrame
* callFrame
= stackFrame
.callFrame
;
2153 RegisterFile
* registerFile
= stackFrame
.registerFile
;
2154 int argsOffset
= stackFrame
.args
[0].int32();
2155 JSValue arguments
= callFrame
->registers()[argsOffset
].jsValue();
2156 uint32_t argCount
= 0;
2158 int providedParams
= callFrame
->registers()[RegisterFile::ArgumentCount
].i() - 1;
2159 argCount
= providedParams
;
2160 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2161 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2162 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2163 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2164 VM_THROW_EXCEPTION();
2166 int32_t expectedParams
= callFrame
->callee()->jsExecutable()->parameterCount();
2167 int32_t inplaceArgs
= min(providedParams
, expectedParams
);
2169 Register
* inplaceArgsDst
= callFrame
->registers() + argsOffset
;
2171 Register
* inplaceArgsEnd
= inplaceArgsDst
+ inplaceArgs
;
2172 Register
* inplaceArgsEnd2
= inplaceArgsDst
+ providedParams
;
2174 Register
* inplaceArgsSrc
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- expectedParams
;
2175 Register
* inplaceArgsSrc2
= inplaceArgsSrc
- providedParams
- 1 + inplaceArgs
;
2177 // First step is to copy the "expected" parameters from their normal location relative to the callframe
2178 while (inplaceArgsDst
< inplaceArgsEnd
)
2179 *inplaceArgsDst
++ = *inplaceArgsSrc
++;
2181 // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
2182 while (inplaceArgsDst
< inplaceArgsEnd2
)
2183 *inplaceArgsDst
++ = *inplaceArgsSrc2
++;
2185 } else if (!arguments
.isUndefinedOrNull()) {
2186 if (!arguments
.isObject()) {
2187 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2188 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2189 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "Function.prototype.apply", arguments
, vPCIndex
, codeBlock
);
2190 VM_THROW_EXCEPTION();
2192 if (asObject(arguments
)->classInfo() == &Arguments::info
) {
2193 Arguments
* argsObject
= asArguments(arguments
);
2194 argCount
= argsObject
->numProvidedArguments(callFrame
);
2195 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2196 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2197 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2198 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2199 VM_THROW_EXCEPTION();
2201 argsObject
->copyToRegisters(callFrame
, callFrame
->registers() + argsOffset
, argCount
);
2202 } else if (isJSArray(&callFrame
->globalData(), arguments
)) {
2203 JSArray
* array
= asArray(arguments
);
2204 argCount
= array
->length();
2205 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2206 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2207 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2208 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2209 VM_THROW_EXCEPTION();
2211 array
->copyToRegisters(callFrame
, callFrame
->registers() + argsOffset
, argCount
);
2212 } else if (asObject(arguments
)->inherits(&JSArray::info
)) {
2213 JSObject
* argObject
= asObject(arguments
);
2214 argCount
= argObject
->get(callFrame
, callFrame
->propertyNames().length
).toUInt32(callFrame
);
2215 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2216 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2217 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2218 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2219 VM_THROW_EXCEPTION();
2221 Register
* argsBuffer
= callFrame
->registers() + argsOffset
;
2222 for (unsigned i
= 0; i
< argCount
; ++i
) {
2223 argsBuffer
[i
] = asObject(arguments
)->get(callFrame
, i
);
2224 CHECK_FOR_EXCEPTION();
2227 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2228 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2229 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "Function.prototype.apply", arguments
, vPCIndex
, codeBlock
);
2230 VM_THROW_EXCEPTION();
2234 return argCount
+ 1;
2237 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_negate
)
2239 STUB_INIT_STACK_FRAME(stackFrame
);
2241 JSValue src
= stackFrame
.args
[0].jsValue();
2244 if (src
.getNumber(v
))
2245 return JSValue::encode(jsNumber(stackFrame
.globalData
, -v
));
2247 CallFrame
* callFrame
= stackFrame
.callFrame
;
2248 JSValue result
= jsNumber(stackFrame
.globalData
, -src
.toNumber(callFrame
));
2249 CHECK_FOR_EXCEPTION_AT_END();
2250 return JSValue::encode(result
);
2253 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_base
)
2255 STUB_INIT_STACK_FRAME(stackFrame
);
2257 return JSValue::encode(JSC::resolveBase(stackFrame
.callFrame
, stackFrame
.args
[0].identifier(), stackFrame
.callFrame
->scopeChain()));
2260 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_skip
)
2262 STUB_INIT_STACK_FRAME(stackFrame
);
2264 CallFrame
* callFrame
= stackFrame
.callFrame
;
2265 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
2267 int skip
= stackFrame
.args
[1].int32();
2269 ScopeChainIterator iter
= scopeChain
->begin();
2270 ScopeChainIterator end
= scopeChain
->end();
2271 ASSERT(iter
!= end
);
2274 ASSERT(iter
!= end
);
2276 Identifier
& ident
= stackFrame
.args
[0].identifier();
2278 JSObject
* o
= *iter
;
2279 PropertySlot
slot(o
);
2280 if (o
->getPropertySlot(callFrame
, ident
, slot
)) {
2281 JSValue result
= slot
.getValue(callFrame
, ident
);
2282 CHECK_FOR_EXCEPTION_AT_END();
2283 return JSValue::encode(result
);
2285 } while (++iter
!= end
);
2287 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2288 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2289 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, codeBlock
);
2290 VM_THROW_EXCEPTION();
2293 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_global
)
2295 STUB_INIT_STACK_FRAME(stackFrame
);
2297 CallFrame
* callFrame
= stackFrame
.callFrame
;
2298 JSGlobalObject
* globalObject
= stackFrame
.args
[0].globalObject();
2299 Identifier
& ident
= stackFrame
.args
[1].identifier();
2300 unsigned globalResolveInfoIndex
= stackFrame
.args
[2].int32();
2301 ASSERT(globalObject
->isGlobalObject());
2303 PropertySlot
slot(globalObject
);
2304 if (globalObject
->getPropertySlot(callFrame
, ident
, slot
)) {
2305 JSValue result
= slot
.getValue(callFrame
, ident
);
2306 if (slot
.isCacheable() && !globalObject
->structure()->isUncacheableDictionary() && slot
.slotBase() == globalObject
) {
2307 GlobalResolveInfo
& globalResolveInfo
= callFrame
->codeBlock()->globalResolveInfo(globalResolveInfoIndex
);
2308 if (globalResolveInfo
.structure
)
2309 globalResolveInfo
.structure
->deref();
2310 globalObject
->structure()->ref();
2311 globalResolveInfo
.structure
= globalObject
->structure();
2312 globalResolveInfo
.offset
= slot
.cachedOffset();
2313 return JSValue::encode(result
);
2316 CHECK_FOR_EXCEPTION_AT_END();
2317 return JSValue::encode(result
);
2320 unsigned vPCIndex
= callFrame
->codeBlock()->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2321 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, callFrame
->codeBlock());
2322 VM_THROW_EXCEPTION();
2325 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_div
)
2327 STUB_INIT_STACK_FRAME(stackFrame
);
2329 JSValue src1
= stackFrame
.args
[0].jsValue();
2330 JSValue src2
= stackFrame
.args
[1].jsValue();
2334 if (src1
.getNumber(left
) && src2
.getNumber(right
))
2335 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
/ right
));
2337 CallFrame
* callFrame
= stackFrame
.callFrame
;
2338 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toNumber(callFrame
) / src2
.toNumber(callFrame
));
2339 CHECK_FOR_EXCEPTION_AT_END();
2340 return JSValue::encode(result
);
2343 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_pre_dec
)
2345 STUB_INIT_STACK_FRAME(stackFrame
);
2347 JSValue v
= stackFrame
.args
[0].jsValue();
2349 CallFrame
* callFrame
= stackFrame
.callFrame
;
2350 JSValue result
= jsNumber(stackFrame
.globalData
, v
.toNumber(callFrame
) - 1);
2351 CHECK_FOR_EXCEPTION_AT_END();
2352 return JSValue::encode(result
);
2355 DEFINE_STUB_FUNCTION(int, op_jless
)
2357 STUB_INIT_STACK_FRAME(stackFrame
);
2359 JSValue src1
= stackFrame
.args
[0].jsValue();
2360 JSValue src2
= stackFrame
.args
[1].jsValue();
2361 CallFrame
* callFrame
= stackFrame
.callFrame
;
2363 bool result
= jsLess(callFrame
, src1
, src2
);
2364 CHECK_FOR_EXCEPTION_AT_END();
2368 DEFINE_STUB_FUNCTION(int, op_jlesseq
)
2370 STUB_INIT_STACK_FRAME(stackFrame
);
2372 JSValue src1
= stackFrame
.args
[0].jsValue();
2373 JSValue src2
= stackFrame
.args
[1].jsValue();
2374 CallFrame
* callFrame
= stackFrame
.callFrame
;
2376 bool result
= jsLessEq(callFrame
, src1
, src2
);
2377 CHECK_FOR_EXCEPTION_AT_END();
2381 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_not
)
2383 STUB_INIT_STACK_FRAME(stackFrame
);
2385 JSValue src
= stackFrame
.args
[0].jsValue();
2387 CallFrame
* callFrame
= stackFrame
.callFrame
;
2389 JSValue result
= jsBoolean(!src
.toBoolean(callFrame
));
2390 CHECK_FOR_EXCEPTION_AT_END();
2391 return JSValue::encode(result
);
2394 DEFINE_STUB_FUNCTION(int, op_jtrue
)
2396 STUB_INIT_STACK_FRAME(stackFrame
);
2398 JSValue src1
= stackFrame
.args
[0].jsValue();
2400 CallFrame
* callFrame
= stackFrame
.callFrame
;
2402 bool result
= src1
.toBoolean(callFrame
);
2403 CHECK_FOR_EXCEPTION_AT_END();
2407 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_post_inc
)
2409 STUB_INIT_STACK_FRAME(stackFrame
);
2411 JSValue v
= stackFrame
.args
[0].jsValue();
2413 CallFrame
* callFrame
= stackFrame
.callFrame
;
2415 JSValue number
= v
.toJSNumber(callFrame
);
2416 CHECK_FOR_EXCEPTION_AT_END();
2418 callFrame
->registers()[stackFrame
.args
[1].int32()] = jsNumber(stackFrame
.globalData
, number
.uncheckedGetNumber() + 1);
2419 return JSValue::encode(number
);
2422 DEFINE_STUB_FUNCTION(int, op_eq
)
2424 STUB_INIT_STACK_FRAME(stackFrame
);
2426 JSValue src1
= stackFrame
.args
[0].jsValue();
2427 JSValue src2
= stackFrame
.args
[1].jsValue();
2429 #if USE(JSVALUE32_64)
2431 if (src2
.isUndefined()) {
2432 return src1
.isNull() ||
2433 (src1
.isCell() && asCell(src1
)->structure()->typeInfo().masqueradesAsUndefined()) ||
2437 if (src2
.isNull()) {
2438 return src1
.isUndefined() ||
2439 (src1
.isCell() && asCell(src1
)->structure()->typeInfo().masqueradesAsUndefined()) ||
2443 if (src1
.isInt32()) {
2444 if (src2
.isDouble())
2445 return src1
.asInt32() == src2
.asDouble();
2446 double d
= src2
.toNumber(stackFrame
.callFrame
);
2447 CHECK_FOR_EXCEPTION();
2448 return src1
.asInt32() == d
;
2451 if (src1
.isDouble()) {
2453 return src1
.asDouble() == src2
.asInt32();
2454 double d
= src2
.toNumber(stackFrame
.callFrame
);
2455 CHECK_FOR_EXCEPTION();
2456 return src1
.asDouble() == d
;
2459 if (src1
.isTrue()) {
2462 double d
= src2
.toNumber(stackFrame
.callFrame
);
2463 CHECK_FOR_EXCEPTION();
2467 if (src1
.isFalse()) {
2470 double d
= src2
.toNumber(stackFrame
.callFrame
);
2471 CHECK_FOR_EXCEPTION();
2475 if (src1
.isUndefined())
2476 return src2
.isCell() && asCell(src2
)->structure()->typeInfo().masqueradesAsUndefined();
2479 return src2
.isCell() && asCell(src2
)->structure()->typeInfo().masqueradesAsUndefined();
2481 JSCell
* cell1
= asCell(src1
);
2483 if (cell1
->isString()) {
2485 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
).toDouble() == src2
.asInt32();
2487 if (src2
.isDouble())
2488 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
).toDouble() == src2
.asDouble();
2491 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
).toDouble() == 1.0;
2494 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
).toDouble() == 0.0;
2496 JSCell
* cell2
= asCell(src2
);
2497 if (cell2
->isString())
2498 return static_cast<JSString
*>(cell1
)->value(stackFrame
.callFrame
) == static_cast<JSString
*>(cell2
)->value(stackFrame
.callFrame
);
2500 src2
= asObject(cell2
)->toPrimitive(stackFrame
.callFrame
);
2501 CHECK_FOR_EXCEPTION();
2505 if (src2
.isObject())
2506 return asObject(cell1
) == asObject(src2
);
2507 src1
= asObject(cell1
)->toPrimitive(stackFrame
.callFrame
);
2508 CHECK_FOR_EXCEPTION();
2511 #else // USE(JSVALUE32_64)
2512 CallFrame
* callFrame
= stackFrame
.callFrame
;
2514 bool result
= JSValue::equalSlowCaseInline(callFrame
, src1
, src2
);
2515 CHECK_FOR_EXCEPTION_AT_END();
2517 #endif // USE(JSVALUE32_64)
2520 #if USE(JSVALUE32_64)
2522 DEFINE_STUB_FUNCTION(int, op_eq_strings
)
2524 STUB_INIT_STACK_FRAME(stackFrame
);
2526 JSString
* string1
= stackFrame
.args
[0].jsString();
2527 JSString
* string2
= stackFrame
.args
[1].jsString();
2529 ASSERT(string1
->isString());
2530 ASSERT(string2
->isString());
2531 return string1
->value(stackFrame
.callFrame
) == string2
->value(stackFrame
.callFrame
);
2536 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_lshift
)
2538 STUB_INIT_STACK_FRAME(stackFrame
);
2540 JSValue val
= stackFrame
.args
[0].jsValue();
2541 JSValue shift
= stackFrame
.args
[1].jsValue();
2543 CallFrame
* callFrame
= stackFrame
.callFrame
;
2544 JSValue result
= jsNumber(stackFrame
.globalData
, (val
.toInt32(callFrame
)) << (shift
.toUInt32(callFrame
) & 0x1f));
2545 CHECK_FOR_EXCEPTION_AT_END();
2546 return JSValue::encode(result
);
2549 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitand
)
2551 STUB_INIT_STACK_FRAME(stackFrame
);
2553 JSValue src1
= stackFrame
.args
[0].jsValue();
2554 JSValue src2
= stackFrame
.args
[1].jsValue();
2556 ASSERT(!src1
.isInt32() || !src2
.isInt32());
2557 CallFrame
* callFrame
= stackFrame
.callFrame
;
2558 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toInt32(callFrame
) & src2
.toInt32(callFrame
));
2559 CHECK_FOR_EXCEPTION_AT_END();
2560 return JSValue::encode(result
);
2563 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_rshift
)
2565 STUB_INIT_STACK_FRAME(stackFrame
);
2567 JSValue val
= stackFrame
.args
[0].jsValue();
2568 JSValue shift
= stackFrame
.args
[1].jsValue();
2570 CallFrame
* callFrame
= stackFrame
.callFrame
;
2571 JSValue result
= jsNumber(stackFrame
.globalData
, (val
.toInt32(callFrame
)) >> (shift
.toUInt32(callFrame
) & 0x1f));
2573 CHECK_FOR_EXCEPTION_AT_END();
2574 return JSValue::encode(result
);
2577 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitnot
)
2579 STUB_INIT_STACK_FRAME(stackFrame
);
2581 JSValue src
= stackFrame
.args
[0].jsValue();
2583 ASSERT(!src
.isInt32());
2584 CallFrame
* callFrame
= stackFrame
.callFrame
;
2585 JSValue result
= jsNumber(stackFrame
.globalData
, ~src
.toInt32(callFrame
));
2586 CHECK_FOR_EXCEPTION_AT_END();
2587 return JSValue::encode(result
);
2590 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_with_base
)
2592 STUB_INIT_STACK_FRAME(stackFrame
);
2594 CallFrame
* callFrame
= stackFrame
.callFrame
;
2595 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
2597 ScopeChainIterator iter
= scopeChain
->begin();
2598 ScopeChainIterator end
= scopeChain
->end();
2600 // FIXME: add scopeDepthIsZero optimization
2602 ASSERT(iter
!= end
);
2604 Identifier
& ident
= stackFrame
.args
[0].identifier();
2608 PropertySlot
slot(base
);
2609 if (base
->getPropertySlot(callFrame
, ident
, slot
)) {
2610 JSValue result
= slot
.getValue(callFrame
, ident
);
2611 CHECK_FOR_EXCEPTION_AT_END();
2613 callFrame
->registers()[stackFrame
.args
[1].int32()] = JSValue(base
);
2614 return JSValue::encode(result
);
2617 } while (iter
!= end
);
2619 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2620 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2621 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, codeBlock
);
2622 VM_THROW_EXCEPTION_AT_END();
2623 return JSValue::encode(JSValue());
2626 DEFINE_STUB_FUNCTION(JSObject
*, op_new_func_exp
)
2628 STUB_INIT_STACK_FRAME(stackFrame
);
2629 CallFrame
* callFrame
= stackFrame
.callFrame
;
2631 FunctionExecutable
* function
= stackFrame
.args
[0].function();
2632 JSFunction
* func
= function
->make(callFrame
, callFrame
->scopeChain());
2635 The Identifier in a FunctionExpression can be referenced from inside
2636 the FunctionExpression's FunctionBody to allow the function to call
2637 itself recursively. However, unlike in a FunctionDeclaration, the
2638 Identifier in a FunctionExpression cannot be referenced from and
2639 does not affect the scope enclosing the FunctionExpression.
2641 if (!function
->name().isNull()) {
2642 JSStaticScopeObject
* functionScopeObject
= new (callFrame
) JSStaticScopeObject(callFrame
, function
->name(), func
, ReadOnly
| DontDelete
);
2643 func
->scope().push(functionScopeObject
);
2649 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_mod
)
2651 STUB_INIT_STACK_FRAME(stackFrame
);
2653 JSValue dividendValue
= stackFrame
.args
[0].jsValue();
2654 JSValue divisorValue
= stackFrame
.args
[1].jsValue();
2656 CallFrame
* callFrame
= stackFrame
.callFrame
;
2657 double d
= dividendValue
.toNumber(callFrame
);
2658 JSValue result
= jsNumber(stackFrame
.globalData
, fmod(d
, divisorValue
.toNumber(callFrame
)));
2659 CHECK_FOR_EXCEPTION_AT_END();
2660 return JSValue::encode(result
);
2663 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_less
)
2665 STUB_INIT_STACK_FRAME(stackFrame
);
2667 CallFrame
* callFrame
= stackFrame
.callFrame
;
2668 JSValue result
= jsBoolean(jsLess(callFrame
, stackFrame
.args
[0].jsValue(), stackFrame
.args
[1].jsValue()));
2669 CHECK_FOR_EXCEPTION_AT_END();
2670 return JSValue::encode(result
);
2673 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_post_dec
)
2675 STUB_INIT_STACK_FRAME(stackFrame
);
2677 JSValue v
= stackFrame
.args
[0].jsValue();
2679 CallFrame
* callFrame
= stackFrame
.callFrame
;
2681 JSValue number
= v
.toJSNumber(callFrame
);
2682 CHECK_FOR_EXCEPTION_AT_END();
2684 callFrame
->registers()[stackFrame
.args
[1].int32()] = jsNumber(stackFrame
.globalData
, number
.uncheckedGetNumber() - 1);
2685 return JSValue::encode(number
);
2688 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_urshift
)
2690 STUB_INIT_STACK_FRAME(stackFrame
);
2692 JSValue val
= stackFrame
.args
[0].jsValue();
2693 JSValue shift
= stackFrame
.args
[1].jsValue();
2695 CallFrame
* callFrame
= stackFrame
.callFrame
;
2696 JSValue result
= jsNumber(stackFrame
.globalData
, (val
.toUInt32(callFrame
)) >> (shift
.toUInt32(callFrame
) & 0x1f));
2697 CHECK_FOR_EXCEPTION_AT_END();
2698 return JSValue::encode(result
);
2701 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitxor
)
2703 STUB_INIT_STACK_FRAME(stackFrame
);
2705 JSValue src1
= stackFrame
.args
[0].jsValue();
2706 JSValue src2
= stackFrame
.args
[1].jsValue();
2708 CallFrame
* callFrame
= stackFrame
.callFrame
;
2710 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toInt32(callFrame
) ^ src2
.toInt32(callFrame
));
2711 CHECK_FOR_EXCEPTION_AT_END();
2712 return JSValue::encode(result
);
2715 DEFINE_STUB_FUNCTION(JSObject
*, op_new_regexp
)
2717 STUB_INIT_STACK_FRAME(stackFrame
);
2719 return new (stackFrame
.globalData
) RegExpObject(stackFrame
.callFrame
->lexicalGlobalObject()->regExpStructure(), stackFrame
.args
[0].regExp());
2722 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitor
)
2724 STUB_INIT_STACK_FRAME(stackFrame
);
2726 JSValue src1
= stackFrame
.args
[0].jsValue();
2727 JSValue src2
= stackFrame
.args
[1].jsValue();
2729 CallFrame
* callFrame
= stackFrame
.callFrame
;
2731 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toInt32(callFrame
) | src2
.toInt32(callFrame
));
2732 CHECK_FOR_EXCEPTION_AT_END();
2733 return JSValue::encode(result
);
2736 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_call_eval
)
2738 STUB_INIT_STACK_FRAME(stackFrame
);
2740 CallFrame
* callFrame
= stackFrame
.callFrame
;
2741 RegisterFile
* registerFile
= stackFrame
.registerFile
;
2743 Interpreter
* interpreter
= stackFrame
.globalData
->interpreter
;
2745 JSValue funcVal
= stackFrame
.args
[0].jsValue();
2746 int registerOffset
= stackFrame
.args
[1].int32();
2747 int argCount
= stackFrame
.args
[2].int32();
2749 Register
* newCallFrame
= callFrame
->registers() + registerOffset
;
2750 Register
* argv
= newCallFrame
- RegisterFile::CallFrameHeaderSize
- argCount
;
2751 JSValue thisValue
= argv
[0].jsValue();
2752 JSGlobalObject
* globalObject
= callFrame
->scopeChain()->globalObject
;
2754 if (thisValue
== globalObject
&& funcVal
== globalObject
->evalFunction()) {
2755 JSValue exceptionValue
;
2756 JSValue result
= interpreter
->callEval(callFrame
, registerFile
, argv
, argCount
, registerOffset
, exceptionValue
);
2757 if (UNLIKELY(exceptionValue
)) {
2758 stackFrame
.globalData
->exception
= exceptionValue
;
2759 VM_THROW_EXCEPTION_AT_END();
2761 return JSValue::encode(result
);
2764 return JSValue::encode(JSValue());
2767 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_throw
)
2769 STUB_INIT_STACK_FRAME(stackFrame
);
2771 CallFrame
* callFrame
= stackFrame
.callFrame
;
2772 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2774 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2776 JSValue exceptionValue
= stackFrame
.args
[0].jsValue();
2777 ASSERT(exceptionValue
);
2779 HandlerInfo
* handler
= stackFrame
.globalData
->interpreter
->throwException(callFrame
, exceptionValue
, vPCIndex
, true);
2782 *stackFrame
.exception
= exceptionValue
;
2783 STUB_SET_RETURN_ADDRESS(FunctionPtr(ctiOpThrowNotCaught
).value());
2784 return JSValue::encode(jsNull());
2787 stackFrame
.callFrame
= callFrame
;
2788 void* catchRoutine
= handler
->nativeCode
.executableAddress();
2789 ASSERT(catchRoutine
);
2790 STUB_SET_RETURN_ADDRESS(catchRoutine
);
2791 return JSValue::encode(exceptionValue
);
2794 DEFINE_STUB_FUNCTION(JSPropertyNameIterator
*, op_get_pnames
)
2796 STUB_INIT_STACK_FRAME(stackFrame
);
2798 CallFrame
* callFrame
= stackFrame
.callFrame
;
2799 JSObject
* o
= stackFrame
.args
[0].jsObject();
2800 Structure
* structure
= o
->structure();
2801 JSPropertyNameIterator
* jsPropertyNameIterator
= structure
->enumerationCache();
2802 if (!jsPropertyNameIterator
|| jsPropertyNameIterator
->cachedPrototypeChain() != structure
->prototypeChain(callFrame
))
2803 jsPropertyNameIterator
= JSPropertyNameIterator::create(callFrame
, o
);
2804 return jsPropertyNameIterator
;
2807 DEFINE_STUB_FUNCTION(int, has_property
)
2809 STUB_INIT_STACK_FRAME(stackFrame
);
2811 JSObject
* base
= stackFrame
.args
[0].jsObject();
2812 JSString
* property
= stackFrame
.args
[1].jsString();
2813 return base
->hasProperty(stackFrame
.callFrame
, Identifier(stackFrame
.callFrame
, property
->value(stackFrame
.callFrame
)));
2816 DEFINE_STUB_FUNCTION(JSObject
*, op_push_scope
)
2818 STUB_INIT_STACK_FRAME(stackFrame
);
2820 JSObject
* o
= stackFrame
.args
[0].jsValue().toObject(stackFrame
.callFrame
);
2821 CHECK_FOR_EXCEPTION();
2822 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->push(o
));
2826 DEFINE_STUB_FUNCTION(void, op_pop_scope
)
2828 STUB_INIT_STACK_FRAME(stackFrame
);
2830 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->pop());
2833 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_typeof
)
2835 STUB_INIT_STACK_FRAME(stackFrame
);
2837 return JSValue::encode(jsTypeStringForValue(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue()));
2840 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_undefined
)
2842 STUB_INIT_STACK_FRAME(stackFrame
);
2844 JSValue v
= stackFrame
.args
[0].jsValue();
2845 return JSValue::encode(jsBoolean(v
.isCell() ? v
.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v
.isUndefined()));
2848 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_boolean
)
2850 STUB_INIT_STACK_FRAME(stackFrame
);
2852 return JSValue::encode(jsBoolean(stackFrame
.args
[0].jsValue().isBoolean()));
2855 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_number
)
2857 STUB_INIT_STACK_FRAME(stackFrame
);
2859 return JSValue::encode(jsBoolean(stackFrame
.args
[0].jsValue().isNumber()));
2862 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_string
)
2864 STUB_INIT_STACK_FRAME(stackFrame
);
2866 return JSValue::encode(jsBoolean(isJSString(stackFrame
.globalData
, stackFrame
.args
[0].jsValue())));
2869 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_object
)
2871 STUB_INIT_STACK_FRAME(stackFrame
);
2873 return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame
.args
[0].jsValue())));
2876 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_function
)
2878 STUB_INIT_STACK_FRAME(stackFrame
);
2880 return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame
.args
[0].jsValue())));
2883 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_stricteq
)
2885 STUB_INIT_STACK_FRAME(stackFrame
);
2887 JSValue src1
= stackFrame
.args
[0].jsValue();
2888 JSValue src2
= stackFrame
.args
[1].jsValue();
2890 return JSValue::encode(jsBoolean(JSValue::strictEqual(stackFrame
.callFrame
, src1
, src2
)));
2893 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_to_primitive
)
2895 STUB_INIT_STACK_FRAME(stackFrame
);
2897 return JSValue::encode(stackFrame
.args
[0].jsValue().toPrimitive(stackFrame
.callFrame
));
2900 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_strcat
)
2902 STUB_INIT_STACK_FRAME(stackFrame
);
2904 JSValue result
= jsString(stackFrame
.callFrame
, &stackFrame
.callFrame
->registers()[stackFrame
.args
[0].int32()], stackFrame
.args
[1].int32());
2905 CHECK_FOR_EXCEPTION_AT_END();
2906 return JSValue::encode(result
);
2909 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_nstricteq
)
2911 STUB_INIT_STACK_FRAME(stackFrame
);
2913 JSValue src1
= stackFrame
.args
[0].jsValue();
2914 JSValue src2
= stackFrame
.args
[1].jsValue();
2916 return JSValue::encode(jsBoolean(!JSValue::strictEqual(stackFrame
.callFrame
, src1
, src2
)));
2919 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_to_jsnumber
)
2921 STUB_INIT_STACK_FRAME(stackFrame
);
2923 JSValue src
= stackFrame
.args
[0].jsValue();
2924 CallFrame
* callFrame
= stackFrame
.callFrame
;
2926 JSValue result
= src
.toJSNumber(callFrame
);
2927 CHECK_FOR_EXCEPTION_AT_END();
2928 return JSValue::encode(result
);
2931 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_in
)
2933 STUB_INIT_STACK_FRAME(stackFrame
);
2935 CallFrame
* callFrame
= stackFrame
.callFrame
;
2936 JSValue baseVal
= stackFrame
.args
[1].jsValue();
2938 if (!baseVal
.isObject()) {
2939 CallFrame
* callFrame
= stackFrame
.callFrame
;
2940 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2941 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2942 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "in", baseVal
, vPCIndex
, codeBlock
);
2943 VM_THROW_EXCEPTION();
2946 JSValue propName
= stackFrame
.args
[0].jsValue();
2947 JSObject
* baseObj
= asObject(baseVal
);
2950 if (propName
.getUInt32(i
))
2951 return JSValue::encode(jsBoolean(baseObj
->hasProperty(callFrame
, i
)));
2953 Identifier
property(callFrame
, propName
.toString(callFrame
));
2954 CHECK_FOR_EXCEPTION();
2955 return JSValue::encode(jsBoolean(baseObj
->hasProperty(callFrame
, property
)));
2958 DEFINE_STUB_FUNCTION(JSObject
*, op_push_new_scope
)
2960 STUB_INIT_STACK_FRAME(stackFrame
);
2962 JSObject
* scope
= new (stackFrame
.globalData
) JSStaticScopeObject(stackFrame
.callFrame
, stackFrame
.args
[0].identifier(), stackFrame
.args
[1].jsValue(), DontDelete
);
2964 CallFrame
* callFrame
= stackFrame
.callFrame
;
2965 callFrame
->setScopeChain(callFrame
->scopeChain()->push(scope
));
2969 DEFINE_STUB_FUNCTION(void, op_jmp_scopes
)
2971 STUB_INIT_STACK_FRAME(stackFrame
);
2973 unsigned count
= stackFrame
.args
[0].int32();
2974 CallFrame
* callFrame
= stackFrame
.callFrame
;
2976 ScopeChainNode
* tmp
= callFrame
->scopeChain();
2979 callFrame
->setScopeChain(tmp
);
2982 DEFINE_STUB_FUNCTION(void, op_put_by_index
)
2984 STUB_INIT_STACK_FRAME(stackFrame
);
2986 CallFrame
* callFrame
= stackFrame
.callFrame
;
2987 unsigned property
= stackFrame
.args
[1].int32();
2989 stackFrame
.args
[0].jsValue().put(callFrame
, property
, stackFrame
.args
[2].jsValue());
2992 DEFINE_STUB_FUNCTION(void*, op_switch_imm
)
2994 STUB_INIT_STACK_FRAME(stackFrame
);
2996 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
2997 unsigned tableIndex
= stackFrame
.args
[1].int32();
2998 CallFrame
* callFrame
= stackFrame
.callFrame
;
2999 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3001 if (scrutinee
.isInt32())
3002 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiForValue(scrutinee
.asInt32()).executableAddress();
3006 if (scrutinee
.getNumber(value
) && ((intValue
= static_cast<int32_t>(value
)) == value
))
3007 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiForValue(intValue
).executableAddress();
3009 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
3013 DEFINE_STUB_FUNCTION(void*, op_switch_char
)
3015 STUB_INIT_STACK_FRAME(stackFrame
);
3017 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
3018 unsigned tableIndex
= stackFrame
.args
[1].int32();
3019 CallFrame
* callFrame
= stackFrame
.callFrame
;
3020 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3022 void* result
= codeBlock
->characterSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
3024 if (scrutinee
.isString()) {
3025 UString::Rep
* value
= asString(scrutinee
)->value(callFrame
).rep();
3026 if (value
->size() == 1)
3027 result
= codeBlock
->characterSwitchJumpTable(tableIndex
).ctiForValue(value
->data()[0]).executableAddress();
3033 DEFINE_STUB_FUNCTION(void*, op_switch_string
)
3035 STUB_INIT_STACK_FRAME(stackFrame
);
3037 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
3038 unsigned tableIndex
= stackFrame
.args
[1].int32();
3039 CallFrame
* callFrame
= stackFrame
.callFrame
;
3040 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3042 void* result
= codeBlock
->stringSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
3044 if (scrutinee
.isString()) {
3045 UString::Rep
* value
= asString(scrutinee
)->value(callFrame
).rep();
3046 result
= codeBlock
->stringSwitchJumpTable(tableIndex
).ctiForValue(value
).executableAddress();
3052 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_del_by_val
)
3054 STUB_INIT_STACK_FRAME(stackFrame
);
3056 CallFrame
* callFrame
= stackFrame
.callFrame
;
3058 JSValue baseValue
= stackFrame
.args
[0].jsValue();
3059 JSObject
* baseObj
= baseValue
.toObject(callFrame
); // may throw
3061 JSValue subscript
= stackFrame
.args
[1].jsValue();
3064 if (subscript
.getUInt32(i
))
3065 result
= jsBoolean(baseObj
->deleteProperty(callFrame
, i
));
3067 CHECK_FOR_EXCEPTION();
3068 Identifier
property(callFrame
, subscript
.toString(callFrame
));
3069 CHECK_FOR_EXCEPTION();
3070 result
= jsBoolean(baseObj
->deleteProperty(callFrame
, property
));
3073 CHECK_FOR_EXCEPTION_AT_END();
3074 return JSValue::encode(result
);
3077 DEFINE_STUB_FUNCTION(void, op_put_getter
)
3079 STUB_INIT_STACK_FRAME(stackFrame
);
3081 CallFrame
* callFrame
= stackFrame
.callFrame
;
3083 ASSERT(stackFrame
.args
[0].jsValue().isObject());
3084 JSObject
* baseObj
= asObject(stackFrame
.args
[0].jsValue());
3085 ASSERT(stackFrame
.args
[2].jsValue().isObject());
3086 baseObj
->defineGetter(callFrame
, stackFrame
.args
[1].identifier(), asObject(stackFrame
.args
[2].jsValue()));
3089 DEFINE_STUB_FUNCTION(void, op_put_setter
)
3091 STUB_INIT_STACK_FRAME(stackFrame
);
3093 CallFrame
* callFrame
= stackFrame
.callFrame
;
3095 ASSERT(stackFrame
.args
[0].jsValue().isObject());
3096 JSObject
* baseObj
= asObject(stackFrame
.args
[0].jsValue());
3097 ASSERT(stackFrame
.args
[2].jsValue().isObject());
3098 baseObj
->defineSetter(callFrame
, stackFrame
.args
[1].identifier(), asObject(stackFrame
.args
[2].jsValue()));
3101 DEFINE_STUB_FUNCTION(JSObject
*, op_new_error
)
3103 STUB_INIT_STACK_FRAME(stackFrame
);
3105 CallFrame
* callFrame
= stackFrame
.callFrame
;
3106 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3107 unsigned type
= stackFrame
.args
[0].int32();
3108 JSValue message
= stackFrame
.args
[1].jsValue();
3109 unsigned bytecodeOffset
= stackFrame
.args
[2].int32();
3111 unsigned lineNumber
= codeBlock
->lineNumberForBytecodeOffset(callFrame
, bytecodeOffset
);
3112 return Error::create(callFrame
, static_cast<ErrorType
>(type
), message
.toString(callFrame
), lineNumber
, codeBlock
->ownerExecutable()->sourceID(), codeBlock
->ownerExecutable()->sourceURL());
3115 DEFINE_STUB_FUNCTION(void, op_debug
)
3117 STUB_INIT_STACK_FRAME(stackFrame
);
3119 CallFrame
* callFrame
= stackFrame
.callFrame
;
3121 int debugHookID
= stackFrame
.args
[0].int32();
3122 int firstLine
= stackFrame
.args
[1].int32();
3123 int lastLine
= stackFrame
.args
[2].int32();
3125 stackFrame
.globalData
->interpreter
->debug(callFrame
, static_cast<DebugHookID
>(debugHookID
), firstLine
, lastLine
);
3128 DEFINE_STUB_FUNCTION(EncodedJSValue
, vm_throw
)
3130 STUB_INIT_STACK_FRAME(stackFrame
);
3132 CallFrame
* callFrame
= stackFrame
.callFrame
;
3133 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3134 JSGlobalData
* globalData
= stackFrame
.globalData
;
3136 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, globalData
->exceptionLocation
);
3138 JSValue exceptionValue
= globalData
->exception
;
3139 ASSERT(exceptionValue
);
3140 globalData
->exception
= JSValue();
3142 HandlerInfo
* handler
= globalData
->interpreter
->throwException(callFrame
, exceptionValue
, vPCIndex
, false);
3145 *stackFrame
.exception
= exceptionValue
;
3146 return JSValue::encode(jsNull());
3149 stackFrame
.callFrame
= callFrame
;
3150 void* catchRoutine
= handler
->nativeCode
.executableAddress();
3151 ASSERT(catchRoutine
);
3152 STUB_SET_RETURN_ADDRESS(catchRoutine
);
3153 return JSValue::encode(exceptionValue
);
3156 DEFINE_STUB_FUNCTION(EncodedJSValue
, to_object
)
3158 STUB_INIT_STACK_FRAME(stackFrame
);
3160 CallFrame
* callFrame
= stackFrame
.callFrame
;
3161 return JSValue::encode(stackFrame
.args
[0].jsValue().toObject(callFrame
));
3166 #endif // ENABLE(JIT)