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"
66 #if PLATFORM(DARWIN) || PLATFORM(WIN_OS)
67 #define SYMBOL_STRING(name) "_" #name
69 #define SYMBOL_STRING(name) #name
74 #if COMPILER(GCC) && PLATFORM(X86)
76 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
77 // need to change the assembly trampolines below to match.
78 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment
);
79 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
80 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
81 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline
);
84 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
85 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
87 "movl %esp, %ebp" "\n"
91 "subl $0x3c, %esp" "\n"
92 "movl $512, %esi" "\n"
93 "movl 0x58(%esp), %edi" "\n"
94 "call *0x50(%esp)" "\n"
95 "addl $0x3c, %esp" "\n"
104 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
105 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
106 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
107 "movl %esp, %ecx" "\n"
109 "call " SYMBOL_STRING(cti_vm_throw
) "\n"
110 "addl $0x3c, %esp" "\n"
119 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
120 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
121 "addl $0x3c, %esp" "\n"
129 #elif COMPILER(GCC) && PLATFORM(X86_64)
131 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
132 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
135 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
136 // need to change the assembly trampolines below to match.
137 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment
);
138 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedRBX
) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
139 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
140 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline
);
143 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
144 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
146 "movq %rsp, %rbp" "\n"
152 "subq $0x48, %rsp" "\n"
153 "movq $512, %r12" "\n"
154 "movq $0xFFFF000000000000, %r14" "\n"
155 "movq $0xFFFF000000000002, %r15" "\n"
156 "movq 0x90(%rsp), %r13" "\n"
157 "call *0x80(%rsp)" "\n"
158 "addq $0x48, %rsp" "\n"
169 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
170 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
171 "movq %rsp, %rdi" "\n"
172 "call " SYMBOL_STRING(cti_vm_throw
) "\n"
173 "addq $0x48, %rsp" "\n"
184 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
185 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
186 "addq $0x48, %rsp" "\n"
196 #elif COMPILER(GCC) && PLATFORM_ARM_ARCH(7)
198 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
199 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
205 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
207 ".thumb_func " SYMBOL_STRING(ctiTrampoline
) "\n"
208 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
209 "sub sp, sp, #0x3c" "\n"
210 "str lr, [sp, #0x20]" "\n"
211 "str r4, [sp, #0x24]" "\n"
212 "str r5, [sp, #0x28]" "\n"
213 "str r6, [sp, #0x2c]" "\n"
214 "str r1, [sp, #0x30]" "\n"
215 "str r2, [sp, #0x34]" "\n"
216 "str r3, [sp, #0x38]" "\n"
220 "ldr r6, [sp, #0x2c]" "\n"
221 "ldr r5, [sp, #0x28]" "\n"
222 "ldr r4, [sp, #0x24]" "\n"
223 "ldr lr, [sp, #0x20]" "\n"
224 "add sp, sp, #0x3c" "\n"
231 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
233 ".thumb_func " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
234 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
236 "bl " SYMBOL_STRING(cti_vm_throw
) "\n"
237 "ldr r6, [sp, #0x2c]" "\n"
238 "ldr r5, [sp, #0x28]" "\n"
239 "ldr r4, [sp, #0x24]" "\n"
240 "ldr lr, [sp, #0x20]" "\n"
241 "add sp, sp, #0x3c" "\n"
248 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
250 ".thumb_func " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
251 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
252 "ldr r6, [sp, #0x2c]" "\n"
253 "ldr r5, [sp, #0x28]" "\n"
254 "ldr r4, [sp, #0x24]" "\n"
255 "ldr lr, [sp, #0x20]" "\n"
256 "add sp, sp, #0x3c" "\n"
262 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
263 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
266 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
267 // need to change the assembly trampolines below to match.
268 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment
);
269 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
270 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
271 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline
);
275 __declspec(naked
) EncodedJSValue
ctiTrampoline(void* code
, RegisterFile
*, CallFrame
*, JSValue
* exception
, Profiler
**, JSGlobalData
*)
286 mov edi
, [esp
+ 0x58];
297 __declspec(naked
) void ctiVMThrowTrampoline()
311 __declspec(naked
) void ctiOpThrowNotCaught()
324 #endif // COMPILER(GCC) && PLATFORM(X86)
326 #else // USE(JSVALUE32_64)
328 #if COMPILER(GCC) && PLATFORM(X86)
330 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
331 // need to change the assembly trampolines below to match.
332 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
333 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline
);
334 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
337 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
338 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
340 "movl %esp, %ebp" "\n"
344 "subl $0x1c, %esp" "\n"
345 "movl $512, %esi" "\n"
346 "movl 0x38(%esp), %edi" "\n"
347 "call *0x30(%esp)" "\n"
348 "addl $0x1c, %esp" "\n"
357 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
358 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
359 #if !USE(JIT_STUB_ARGUMENT_VA_LIST)
360 "movl %esp, %ecx" "\n"
362 "call " SYMBOL_STRING(cti_vm_throw
) "\n"
363 "addl $0x1c, %esp" "\n"
372 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
373 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
374 "addl $0x1c, %esp" "\n"
382 #elif COMPILER(GCC) && PLATFORM(X86_64)
384 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
385 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
388 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
389 // need to change the assembly trampolines below to match.
390 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
391 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline
);
392 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedRBX
) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
395 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
396 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
398 "movq %rsp, %rbp" "\n"
404 "subq $0x48, %rsp" "\n"
405 "movq $512, %r12" "\n"
406 "movq $0xFFFF000000000000, %r14" "\n"
407 "movq $0xFFFF000000000002, %r15" "\n"
408 "movq 0x90(%rsp), %r13" "\n"
409 "call *0x80(%rsp)" "\n"
410 "addq $0x48, %rsp" "\n"
421 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
422 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
423 "movq %rsp, %rdi" "\n"
424 "call " SYMBOL_STRING(cti_vm_throw
) "\n"
425 "addq $0x48, %rsp" "\n"
436 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
437 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
438 "addq $0x48, %rsp" "\n"
448 #elif COMPILER(GCC) && PLATFORM_ARM_ARCH(7)
450 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
451 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
457 ".globl " SYMBOL_STRING(ctiTrampoline
) "\n"
459 ".thumb_func " SYMBOL_STRING(ctiTrampoline
) "\n"
460 SYMBOL_STRING(ctiTrampoline
) ":" "\n"
461 "sub sp, sp, #0x3c" "\n"
462 "str lr, [sp, #0x20]" "\n"
463 "str r4, [sp, #0x24]" "\n"
464 "str r5, [sp, #0x28]" "\n"
465 "str r6, [sp, #0x2c]" "\n"
466 "str r1, [sp, #0x30]" "\n"
467 "str r2, [sp, #0x34]" "\n"
468 "str r3, [sp, #0x38]" "\n"
472 "ldr r6, [sp, #0x2c]" "\n"
473 "ldr r5, [sp, #0x28]" "\n"
474 "ldr r4, [sp, #0x24]" "\n"
475 "ldr lr, [sp, #0x20]" "\n"
476 "add sp, sp, #0x3c" "\n"
483 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
485 ".thumb_func " SYMBOL_STRING(ctiVMThrowTrampoline
) "\n"
486 SYMBOL_STRING(ctiVMThrowTrampoline
) ":" "\n"
488 "bl " SYMBOL_STRING(cti_vm_throw
) "\n"
489 "ldr r6, [sp, #0x2c]" "\n"
490 "ldr r5, [sp, #0x28]" "\n"
491 "ldr r4, [sp, #0x24]" "\n"
492 "ldr lr, [sp, #0x20]" "\n"
493 "add sp, sp, #0x3c" "\n"
500 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
502 ".thumb_func " SYMBOL_STRING(ctiOpThrowNotCaught
) "\n"
503 SYMBOL_STRING(ctiOpThrowNotCaught
) ":" "\n"
504 "ldr r6, [sp, #0x2c]" "\n"
505 "ldr r5, [sp, #0x28]" "\n"
506 "ldr r4, [sp, #0x24]" "\n"
507 "ldr lr, [sp, #0x20]" "\n"
508 "add sp, sp, #0x3c" "\n"
514 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
515 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
518 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
519 // need to change the assembly trampolines below to match.
520 COMPILE_ASSERT(offsetof(struct JITStackFrame
, callFrame
) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline
);
521 COMPILE_ASSERT(offsetof(struct JITStackFrame
, code
) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline
);
522 COMPILE_ASSERT(offsetof(struct JITStackFrame
, savedEBX
) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline
);
526 __declspec(naked
) EncodedJSValue
ctiTrampoline(void* code
, RegisterFile
*, CallFrame
*, JSValue
* exception
, Profiler
**, JSGlobalData
*)
537 mov edi
, [esp
+ 0x38];
548 __declspec(naked
) void ctiVMThrowTrampoline()
562 __declspec(naked
) void ctiOpThrowNotCaught()
575 #endif // COMPILER(GCC) && PLATFORM(X86)
577 #endif // USE(JSVALUE32_64)
579 #if ENABLE(OPCODE_SAMPLING)
580 #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler()
582 #define CTI_SAMPLER 0
585 JITThunks::JITThunks(JSGlobalData
* globalData
)
587 JIT::compileCTIMachineTrampolines(globalData
, &m_executablePool
, &m_ctiStringLengthTrampoline
, &m_ctiVirtualCallPreLink
, &m_ctiVirtualCallLink
, &m_ctiVirtualCall
, &m_ctiNativeCallThunk
);
589 #if PLATFORM_ARM_ARCH(7)
590 // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
591 // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
593 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedReturnAddress
) == 0x20);
594 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR4
) == 0x24);
595 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR5
) == 0x28);
596 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, preservedR6
) == 0x2c);
598 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, registerFile
) == 0x30);
599 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, callFrame
) == 0x34);
600 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, exception
) == 0x38);
601 // The fifth argument is the first item already on the stack.
602 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, enabledProfilerReference
) == 0x3c);
604 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame
, thunkReturnAddress
) == 0x1C);
608 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
610 NEVER_INLINE
void JITThunks::tryCachePutByID(CallFrame
* callFrame
, CodeBlock
* codeBlock
, ReturnAddressPtr returnAddress
, JSValue baseValue
, const PutPropertySlot
& slot
)
612 // The interpreter checks for recursion here; I do not believe this can occur in CTI.
614 if (!baseValue
.isCell())
617 // Uncacheable: give up.
618 if (!slot
.isCacheable()) {
619 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_put_by_id_generic
));
623 JSCell
* baseCell
= asCell(baseValue
);
624 Structure
* structure
= baseCell
->structure();
626 if (structure
->isUncacheableDictionary()) {
627 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_put_by_id_generic
));
631 // If baseCell != base, then baseCell must be a proxy for another object.
632 if (baseCell
!= slot
.base()) {
633 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_put_by_id_generic
));
637 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(returnAddress
);
639 // Cache hit: Specialize instruction and ref Structures.
641 // Structure transition, cache transition info
642 if (slot
.type() == PutPropertySlot::NewProperty
) {
643 StructureChain
* prototypeChain
= structure
->prototypeChain(callFrame
);
644 if (!prototypeChain
->isCacheable() || structure
->isDictionary()) {
645 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_put_by_id_generic
));
648 stubInfo
->initPutByIdTransition(structure
->previousID(), structure
, prototypeChain
);
649 JIT::compilePutByIdTransition(callFrame
->scopeChain()->globalData
, codeBlock
, stubInfo
, structure
->previousID(), structure
, slot
.cachedOffset(), prototypeChain
, returnAddress
);
653 stubInfo
->initPutByIdReplace(structure
);
655 JIT::patchPutByIdReplace(codeBlock
, stubInfo
, structure
, slot
.cachedOffset(), returnAddress
);
658 NEVER_INLINE
void JITThunks::tryCacheGetByID(CallFrame
* callFrame
, CodeBlock
* codeBlock
, ReturnAddressPtr returnAddress
, JSValue baseValue
, const Identifier
& propertyName
, const PropertySlot
& slot
)
660 // FIXME: Write a test that proves we need to check for recursion here just
661 // like the interpreter does, then add a check for recursion.
663 // FIXME: Cache property access for immediates.
664 if (!baseValue
.isCell()) {
665 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
669 JSGlobalData
* globalData
= &callFrame
->globalData();
671 if (isJSArray(globalData
, baseValue
) && propertyName
== callFrame
->propertyNames().length
) {
672 JIT::compilePatchGetArrayLength(callFrame
->scopeChain()->globalData
, codeBlock
, returnAddress
);
676 if (isJSString(globalData
, baseValue
) && propertyName
== callFrame
->propertyNames().length
) {
677 // The tradeoff of compiling an patched inline string length access routine does not seem
678 // to pay off, so we currently only do this for arrays.
679 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, globalData
->jitStubs
.ctiStringLengthTrampoline());
683 // Uncacheable: give up.
684 if (!slot
.isCacheable()) {
685 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
689 JSCell
* baseCell
= asCell(baseValue
);
690 Structure
* structure
= baseCell
->structure();
692 if (structure
->isUncacheableDictionary()) {
693 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
697 // In the interpreter the last structure is trapped here; in CTI we use the
698 // *_second method to achieve a similar (but not quite the same) effect.
700 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(returnAddress
);
702 // Cache hit: Specialize instruction and ref Structures.
704 if (slot
.slotBase() == baseValue
) {
705 // set this up, so derefStructures can do it's job.
706 stubInfo
->initGetByIdSelf(structure
);
708 JIT::patchGetByIdSelf(codeBlock
, stubInfo
, structure
, slot
.cachedOffset(), returnAddress
);
712 if (structure
->isDictionary()) {
713 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
717 if (slot
.slotBase() == structure
->prototypeForLookup(callFrame
)) {
718 ASSERT(slot
.slotBase().isObject());
720 JSObject
* slotBaseObject
= asObject(slot
.slotBase());
721 size_t offset
= slot
.cachedOffset();
723 // Since we're accessing a prototype in a loop, it's a good bet that it
724 // should not be treated as a dictionary.
725 if (slotBaseObject
->structure()->isDictionary()) {
726 slotBaseObject
->flattenDictionaryObject();
727 offset
= slotBaseObject
->structure()->get(propertyName
);
730 stubInfo
->initGetByIdProto(structure
, slotBaseObject
->structure());
732 JIT::compileGetByIdProto(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, structure
, slotBaseObject
->structure(), offset
, returnAddress
);
736 size_t offset
= slot
.cachedOffset();
737 size_t count
= normalizePrototypeChain(callFrame
, baseValue
, slot
.slotBase(), propertyName
, offset
);
739 stubInfo
->opcodeID
= op_get_by_id_generic
;
743 StructureChain
* prototypeChain
= structure
->prototypeChain(callFrame
);
744 if (!prototypeChain
->isCacheable()) {
745 ctiPatchCallByReturnAddress(codeBlock
, returnAddress
, FunctionPtr(cti_op_get_by_id_generic
));
748 stubInfo
->initGetByIdChain(structure
, prototypeChain
);
749 JIT::compileGetByIdChain(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, structure
, prototypeChain
, count
, offset
, returnAddress
);
752 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
754 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
755 #define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args)
757 #define SETUP_VA_LISTL_ARGS
764 static void jscGeneratedNativeCode()
766 // When executing a JIT stub function (which might do an allocation), we hack the return address
767 // to pretend to be executing this function, to keep stack logging tools from blowing out
774 ALWAYS_INLINE
StackHack(JITStackFrame
& stackFrame
)
775 : stackFrame(stackFrame
)
776 , savedReturnAddress(*stackFrame
.returnAddressSlot())
778 *stackFrame
.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode
));
781 ALWAYS_INLINE
~StackHack()
783 *stackFrame
.returnAddressSlot() = savedReturnAddress
;
786 JITStackFrame
& stackFrame
;
787 ReturnAddressPtr savedReturnAddress
;
790 #define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
791 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
792 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
796 #define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS)
797 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
798 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
802 // The reason this is not inlined is to avoid having to do a PIC branch
803 // to get the address of the ctiVMThrowTrampoline function. It's also
804 // good to keep the code size down by leaving as much of the exception
805 // handling code out of line as possible.
806 static NEVER_INLINE
void returnToThrowTrampoline(JSGlobalData
* globalData
, ReturnAddressPtr exceptionLocation
, ReturnAddressPtr
& returnAddressSlot
)
808 ASSERT(globalData
->exception
);
809 globalData
->exceptionLocation
= exceptionLocation
;
810 returnAddressSlot
= ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline
));
813 static NEVER_INLINE
void throwStackOverflowError(CallFrame
* callFrame
, JSGlobalData
* globalData
, ReturnAddressPtr exceptionLocation
, ReturnAddressPtr
& returnAddressSlot
)
815 globalData
->exception
= createStackOverflowError(callFrame
);
816 returnToThrowTrampoline(globalData
, exceptionLocation
, returnAddressSlot
);
819 #define VM_THROW_EXCEPTION() \
821 VM_THROW_EXCEPTION_AT_END(); \
824 #define VM_THROW_EXCEPTION_AT_END() \
825 returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS)
827 #define CHECK_FOR_EXCEPTION() \
829 if (UNLIKELY(stackFrame.globalData->exception)) \
830 VM_THROW_EXCEPTION(); \
832 #define CHECK_FOR_EXCEPTION_AT_END() \
834 if (UNLIKELY(stackFrame.globalData->exception)) \
835 VM_THROW_EXCEPTION_AT_END(); \
837 #define CHECK_FOR_EXCEPTION_VOID() \
839 if (UNLIKELY(stackFrame.globalData->exception)) { \
840 VM_THROW_EXCEPTION_AT_END(); \
845 #if PLATFORM_ARM_ARCH(7)
847 #define DEFINE_STUB_FUNCTION(rtype, op) \
849 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
854 ".globl " SYMBOL_STRING(cti_##op) "\n" \
856 ".thumb_func " SYMBOL_STRING(cti_##op) "\n" \
857 SYMBOL_STRING(cti_##op) ":" "\n" \
858 "str lr, [sp, #0x1c]" "\n" \
859 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
860 "ldr lr, [sp, #0x1c]" "\n" \
863 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
866 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
869 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_convert_this
)
871 STUB_INIT_STACK_FRAME(stackFrame
);
873 JSValue v1
= stackFrame
.args
[0].jsValue();
874 CallFrame
* callFrame
= stackFrame
.callFrame
;
876 JSObject
* result
= v1
.toThisObject(callFrame
);
877 CHECK_FOR_EXCEPTION_AT_END();
878 return JSValue::encode(result
);
881 DEFINE_STUB_FUNCTION(void, op_end
)
883 STUB_INIT_STACK_FRAME(stackFrame
);
885 ScopeChainNode
* scopeChain
= stackFrame
.callFrame
->scopeChain();
886 ASSERT(scopeChain
->refCount
> 1);
890 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_add
)
892 STUB_INIT_STACK_FRAME(stackFrame
);
894 JSValue v1
= stackFrame
.args
[0].jsValue();
895 JSValue v2
= stackFrame
.args
[1].jsValue();
900 bool rightIsNumber
= v2
.getNumber(right
);
901 if (rightIsNumber
&& v1
.getNumber(left
))
902 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
+ right
));
904 CallFrame
* callFrame
= stackFrame
.callFrame
;
906 bool leftIsString
= v1
.isString();
907 if (leftIsString
&& v2
.isString()) {
908 RefPtr
<UString::Rep
> value
= concatenate(asString(v1
)->value().rep(), asString(v2
)->value().rep());
909 if (UNLIKELY(!value
)) {
910 throwOutOfMemoryError(callFrame
);
911 VM_THROW_EXCEPTION();
914 return JSValue::encode(jsString(stackFrame
.globalData
, value
.release()));
917 if (rightIsNumber
& leftIsString
) {
918 RefPtr
<UString::Rep
> value
= v2
.isInt32() ?
919 concatenate(asString(v1
)->value().rep(), v2
.asInt32()) :
920 concatenate(asString(v1
)->value().rep(), right
);
922 if (UNLIKELY(!value
)) {
923 throwOutOfMemoryError(callFrame
);
924 VM_THROW_EXCEPTION();
926 return JSValue::encode(jsString(stackFrame
.globalData
, value
.release()));
929 // All other cases are pretty uncommon
930 JSValue result
= jsAddSlowCase(callFrame
, v1
, v2
);
931 CHECK_FOR_EXCEPTION_AT_END();
932 return JSValue::encode(result
);
935 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_pre_inc
)
937 STUB_INIT_STACK_FRAME(stackFrame
);
939 JSValue v
= stackFrame
.args
[0].jsValue();
941 CallFrame
* callFrame
= stackFrame
.callFrame
;
942 JSValue result
= jsNumber(stackFrame
.globalData
, v
.toNumber(callFrame
) + 1);
943 CHECK_FOR_EXCEPTION_AT_END();
944 return JSValue::encode(result
);
947 DEFINE_STUB_FUNCTION(int, timeout_check
)
949 STUB_INIT_STACK_FRAME(stackFrame
);
951 JSGlobalData
* globalData
= stackFrame
.globalData
;
952 TimeoutChecker
& timeoutChecker
= globalData
->timeoutChecker
;
954 if (timeoutChecker
.didTimeOut(stackFrame
.callFrame
)) {
955 globalData
->exception
= createInterruptedExecutionException(globalData
);
956 VM_THROW_EXCEPTION_AT_END();
959 return timeoutChecker
.ticksUntilNextCheck();
962 DEFINE_STUB_FUNCTION(void, register_file_check
)
964 STUB_INIT_STACK_FRAME(stackFrame
);
966 if (LIKELY(stackFrame
.registerFile
->grow(&stackFrame
.callFrame
->registers()[stackFrame
.callFrame
->codeBlock()->m_numCalleeRegisters
])))
969 // Rewind to the previous call frame because op_call already optimistically
970 // moved the call frame forward.
971 CallFrame
* oldCallFrame
= stackFrame
.callFrame
->callerFrame();
972 stackFrame
.callFrame
= oldCallFrame
;
973 throwStackOverflowError(oldCallFrame
, stackFrame
.globalData
, ReturnAddressPtr(oldCallFrame
->returnPC()), STUB_RETURN_ADDRESS
);
976 DEFINE_STUB_FUNCTION(int, op_loop_if_less
)
978 STUB_INIT_STACK_FRAME(stackFrame
);
980 JSValue src1
= stackFrame
.args
[0].jsValue();
981 JSValue src2
= stackFrame
.args
[1].jsValue();
982 CallFrame
* callFrame
= stackFrame
.callFrame
;
984 bool result
= jsLess(callFrame
, src1
, src2
);
985 CHECK_FOR_EXCEPTION_AT_END();
989 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq
)
991 STUB_INIT_STACK_FRAME(stackFrame
);
993 JSValue src1
= stackFrame
.args
[0].jsValue();
994 JSValue src2
= stackFrame
.args
[1].jsValue();
995 CallFrame
* callFrame
= stackFrame
.callFrame
;
997 bool result
= jsLessEq(callFrame
, src1
, src2
);
998 CHECK_FOR_EXCEPTION_AT_END();
1002 DEFINE_STUB_FUNCTION(JSObject
*, op_new_object
)
1004 STUB_INIT_STACK_FRAME(stackFrame
);
1006 return constructEmptyObject(stackFrame
.callFrame
);
1009 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic
)
1011 STUB_INIT_STACK_FRAME(stackFrame
);
1013 PutPropertySlot slot
;
1014 stackFrame
.args
[0].jsValue().put(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), stackFrame
.args
[2].jsValue(), slot
);
1015 CHECK_FOR_EXCEPTION_AT_END();
1018 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_generic
)
1020 STUB_INIT_STACK_FRAME(stackFrame
);
1022 CallFrame
* callFrame
= stackFrame
.callFrame
;
1023 Identifier
& ident
= stackFrame
.args
[1].identifier();
1025 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1026 PropertySlot
slot(baseValue
);
1027 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1029 CHECK_FOR_EXCEPTION_AT_END();
1030 return JSValue::encode(result
);
1033 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1035 DEFINE_STUB_FUNCTION(void, op_put_by_id
)
1037 STUB_INIT_STACK_FRAME(stackFrame
);
1039 CallFrame
* callFrame
= stackFrame
.callFrame
;
1040 Identifier
& ident
= stackFrame
.args
[1].identifier();
1042 PutPropertySlot slot
;
1043 stackFrame
.args
[0].jsValue().put(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1045 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_put_by_id_second
));
1047 CHECK_FOR_EXCEPTION_AT_END();
1050 DEFINE_STUB_FUNCTION(void, op_put_by_id_second
)
1052 STUB_INIT_STACK_FRAME(stackFrame
);
1054 PutPropertySlot slot
;
1055 stackFrame
.args
[0].jsValue().put(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), stackFrame
.args
[2].jsValue(), slot
);
1056 JITThunks::tryCachePutByID(stackFrame
.callFrame
, stackFrame
.callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, stackFrame
.args
[0].jsValue(), slot
);
1057 CHECK_FOR_EXCEPTION_AT_END();
1060 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail
)
1062 STUB_INIT_STACK_FRAME(stackFrame
);
1064 CallFrame
* callFrame
= stackFrame
.callFrame
;
1065 Identifier
& ident
= stackFrame
.args
[1].identifier();
1067 PutPropertySlot slot
;
1068 stackFrame
.args
[0].jsValue().put(callFrame
, ident
, stackFrame
.args
[2].jsValue(), slot
);
1070 CHECK_FOR_EXCEPTION_AT_END();
1073 DEFINE_STUB_FUNCTION(JSObject
*, op_put_by_id_transition_realloc
)
1075 STUB_INIT_STACK_FRAME(stackFrame
);
1077 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1078 int32_t oldSize
= stackFrame
.args
[3].int32();
1079 int32_t newSize
= stackFrame
.args
[4].int32();
1081 ASSERT(baseValue
.isObject());
1082 JSObject
* base
= asObject(baseValue
);
1083 base
->allocatePropertyStorage(oldSize
, newSize
);
1088 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id
)
1090 STUB_INIT_STACK_FRAME(stackFrame
);
1092 CallFrame
* callFrame
= stackFrame
.callFrame
;
1093 Identifier
& ident
= stackFrame
.args
[1].identifier();
1095 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1096 PropertySlot
slot(baseValue
);
1097 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1099 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_second
));
1101 CHECK_FOR_EXCEPTION_AT_END();
1102 return JSValue::encode(result
);
1105 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_method_check
)
1107 STUB_INIT_STACK_FRAME(stackFrame
);
1109 CallFrame
* callFrame
= stackFrame
.callFrame
;
1110 Identifier
& ident
= stackFrame
.args
[1].identifier();
1112 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1113 PropertySlot
slot(baseValue
);
1114 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1116 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_method_check_second
));
1118 CHECK_FOR_EXCEPTION_AT_END();
1119 return JSValue::encode(result
);
1122 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_method_check_second
)
1124 STUB_INIT_STACK_FRAME(stackFrame
);
1126 CallFrame
* callFrame
= stackFrame
.callFrame
;
1127 Identifier
& ident
= stackFrame
.args
[1].identifier();
1129 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1130 PropertySlot
slot(baseValue
);
1131 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1133 CHECK_FOR_EXCEPTION();
1135 // If we successfully got something, then the base from which it is being accessed must
1136 // be an object. (Assertion to ensure asObject() call below is safe, which comes after
1137 // an isCacheable() chceck.
1138 ASSERT(!slot
.isCacheable() || slot
.slotBase().isObject());
1141 // * We're dealing with a JSCell,
1142 // * the property is cachable,
1143 // * it's not a dictionary
1144 // * there is a function cached.
1145 Structure
* structure
;
1147 JSObject
* slotBaseObject
;
1148 if (baseValue
.isCell()
1149 && slot
.isCacheable()
1150 && !(structure
= asCell(baseValue
)->structure())->isUncacheableDictionary()
1151 && (slotBaseObject
= asObject(slot
.slotBase()))->getPropertySpecificValue(callFrame
, ident
, specific
)
1155 JSFunction
* callee
= (JSFunction
*)specific
;
1157 // Since we're accessing a prototype in a loop, it's a good bet that it
1158 // should not be treated as a dictionary.
1159 if (slotBaseObject
->structure()->isDictionary())
1160 slotBaseObject
->flattenDictionaryObject();
1162 // The result fetched should always be the callee!
1163 ASSERT(result
== JSValue(callee
));
1164 MethodCallLinkInfo
& methodCallLinkInfo
= callFrame
->codeBlock()->getMethodCallLinkInfo(STUB_RETURN_ADDRESS
);
1166 // Check to see if the function is on the object's prototype. Patch up the code to optimize.
1167 if (slot
.slotBase() == structure
->prototypeForLookup(callFrame
))
1168 JIT::patchMethodCallProto(callFrame
->codeBlock(), methodCallLinkInfo
, callee
, structure
, slotBaseObject
);
1169 // Check to see if the function is on the object itself.
1170 // Since we generate the method-check to check both the structure and a prototype-structure (since this
1171 // is the common case) we have a problem - we need to patch the prototype structure check to do something
1172 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler
1173 // for now. For now it performs a check on a special object on the global object only used for this
1174 // purpose. The object is in no way exposed, and as such the check will always pass.
1175 else if (slot
.slotBase() == baseValue
)
1176 JIT::patchMethodCallProto(callFrame
->codeBlock(), methodCallLinkInfo
, callee
, structure
, callFrame
->scopeChain()->globalObject()->methodCallDummy());
1178 // For now let any other case be cached as a normal get_by_id.
1181 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
1182 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id
));
1184 return JSValue::encode(result
);
1187 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_second
)
1189 STUB_INIT_STACK_FRAME(stackFrame
);
1191 CallFrame
* callFrame
= stackFrame
.callFrame
;
1192 Identifier
& ident
= stackFrame
.args
[1].identifier();
1194 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1195 PropertySlot
slot(baseValue
);
1196 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1198 JITThunks::tryCacheGetByID(callFrame
, callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, baseValue
, ident
, slot
);
1200 CHECK_FOR_EXCEPTION_AT_END();
1201 return JSValue::encode(result
);
1204 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_self_fail
)
1206 STUB_INIT_STACK_FRAME(stackFrame
);
1208 CallFrame
* callFrame
= stackFrame
.callFrame
;
1209 Identifier
& ident
= stackFrame
.args
[1].identifier();
1211 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1212 PropertySlot
slot(baseValue
);
1213 JSValue result
= baseValue
.get(callFrame
, ident
, slot
);
1215 CHECK_FOR_EXCEPTION();
1217 if (baseValue
.isCell()
1218 && slot
.isCacheable()
1219 && !asCell(baseValue
)->structure()->isUncacheableDictionary()
1220 && slot
.slotBase() == baseValue
) {
1222 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1223 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1225 ASSERT(slot
.slotBase().isObject());
1227 PolymorphicAccessStructureList
* polymorphicStructureList
;
1230 if (stubInfo
->opcodeID
== op_get_by_id_self
) {
1231 ASSERT(!stubInfo
->stubRoutine
);
1232 polymorphicStructureList
= new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo
->u
.getByIdSelf
.baseObjectStructure
);
1233 stubInfo
->initGetByIdSelfList(polymorphicStructureList
, 2);
1235 polymorphicStructureList
= stubInfo
->u
.getByIdSelfList
.structureList
;
1236 listIndex
= stubInfo
->u
.getByIdSelfList
.listSize
;
1237 stubInfo
->u
.getByIdSelfList
.listSize
++;
1240 JIT::compileGetByIdSelfList(callFrame
->scopeChain()->globalData
, codeBlock
, stubInfo
, polymorphicStructureList
, listIndex
, asCell(baseValue
)->structure(), slot
.cachedOffset());
1242 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1243 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_generic
));
1245 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_generic
));
1246 return JSValue::encode(result
);
1249 static PolymorphicAccessStructureList
* getPolymorphicAccessStructureListSlot(StructureStubInfo
* stubInfo
, int& listIndex
)
1251 PolymorphicAccessStructureList
* prototypeStructureList
= 0;
1254 switch (stubInfo
->opcodeID
) {
1255 case op_get_by_id_proto
:
1256 prototypeStructureList
= new PolymorphicAccessStructureList(stubInfo
->stubRoutine
, stubInfo
->u
.getByIdProto
.baseObjectStructure
, stubInfo
->u
.getByIdProto
.prototypeStructure
);
1257 stubInfo
->stubRoutine
= CodeLocationLabel();
1258 stubInfo
->initGetByIdProtoList(prototypeStructureList
, 2);
1260 case op_get_by_id_chain
:
1261 prototypeStructureList
= new PolymorphicAccessStructureList(stubInfo
->stubRoutine
, stubInfo
->u
.getByIdChain
.baseObjectStructure
, stubInfo
->u
.getByIdChain
.chain
);
1262 stubInfo
->stubRoutine
= CodeLocationLabel();
1263 stubInfo
->initGetByIdProtoList(prototypeStructureList
, 2);
1265 case op_get_by_id_proto_list
:
1266 prototypeStructureList
= stubInfo
->u
.getByIdProtoList
.structureList
;
1267 listIndex
= stubInfo
->u
.getByIdProtoList
.listSize
;
1268 stubInfo
->u
.getByIdProtoList
.listSize
++;
1271 ASSERT_NOT_REACHED();
1274 ASSERT(listIndex
< POLYMORPHIC_LIST_CACHE_SIZE
);
1275 return prototypeStructureList
;
1278 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_list
)
1280 STUB_INIT_STACK_FRAME(stackFrame
);
1282 CallFrame
* callFrame
= stackFrame
.callFrame
;
1283 const Identifier
& propertyName
= stackFrame
.args
[1].identifier();
1285 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1286 PropertySlot
slot(baseValue
);
1287 JSValue result
= baseValue
.get(callFrame
, propertyName
, slot
);
1289 CHECK_FOR_EXCEPTION();
1291 if (!baseValue
.isCell() || !slot
.isCacheable() || asCell(baseValue
)->structure()->isUncacheableDictionary()) {
1292 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1293 return JSValue::encode(result
);
1296 Structure
* structure
= asCell(baseValue
)->structure();
1297 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1298 StructureStubInfo
* stubInfo
= &codeBlock
->getStubInfo(STUB_RETURN_ADDRESS
);
1300 ASSERT(slot
.slotBase().isObject());
1301 JSObject
* slotBaseObject
= asObject(slot
.slotBase());
1303 size_t offset
= slot
.cachedOffset();
1305 if (slot
.slotBase() == baseValue
)
1306 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1307 else if (slot
.slotBase() == asCell(baseValue
)->structure()->prototypeForLookup(callFrame
)) {
1308 // Since we're accessing a prototype in a loop, it's a good bet that it
1309 // should not be treated as a dictionary.
1310 if (slotBaseObject
->structure()->isDictionary()) {
1311 slotBaseObject
->flattenDictionaryObject();
1312 offset
= slotBaseObject
->structure()->get(propertyName
);
1316 PolymorphicAccessStructureList
* prototypeStructureList
= getPolymorphicAccessStructureListSlot(stubInfo
, listIndex
);
1318 JIT::compileGetByIdProtoList(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, prototypeStructureList
, listIndex
, structure
, slotBaseObject
->structure(), offset
);
1320 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1321 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_list_full
));
1322 } else if (size_t count
= normalizePrototypeChain(callFrame
, baseValue
, slot
.slotBase(), propertyName
, offset
)) {
1323 StructureChain
* protoChain
= structure
->prototypeChain(callFrame
);
1324 if (!protoChain
->isCacheable()) {
1325 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1326 return JSValue::encode(result
);
1330 PolymorphicAccessStructureList
* prototypeStructureList
= getPolymorphicAccessStructureListSlot(stubInfo
, listIndex
);
1331 JIT::compileGetByIdChainList(callFrame
->scopeChain()->globalData
, callFrame
, codeBlock
, stubInfo
, prototypeStructureList
, listIndex
, structure
, protoChain
, count
, offset
);
1333 if (listIndex
== (POLYMORPHIC_LIST_CACHE_SIZE
- 1))
1334 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_list_full
));
1336 ctiPatchCallByReturnAddress(codeBlock
, STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_id_proto_fail
));
1338 return JSValue::encode(result
);
1341 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_list_full
)
1343 STUB_INIT_STACK_FRAME(stackFrame
);
1345 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1346 PropertySlot
slot(baseValue
);
1347 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1349 CHECK_FOR_EXCEPTION_AT_END();
1350 return JSValue::encode(result
);
1353 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_proto_fail
)
1355 STUB_INIT_STACK_FRAME(stackFrame
);
1357 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1358 PropertySlot
slot(baseValue
);
1359 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1361 CHECK_FOR_EXCEPTION_AT_END();
1362 return JSValue::encode(result
);
1365 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_array_fail
)
1367 STUB_INIT_STACK_FRAME(stackFrame
);
1369 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1370 PropertySlot
slot(baseValue
);
1371 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1373 CHECK_FOR_EXCEPTION_AT_END();
1374 return JSValue::encode(result
);
1377 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_id_string_fail
)
1379 STUB_INIT_STACK_FRAME(stackFrame
);
1381 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1382 PropertySlot
slot(baseValue
);
1383 JSValue result
= baseValue
.get(stackFrame
.callFrame
, stackFrame
.args
[1].identifier(), slot
);
1385 CHECK_FOR_EXCEPTION_AT_END();
1386 return JSValue::encode(result
);
1389 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1391 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_instanceof
)
1393 STUB_INIT_STACK_FRAME(stackFrame
);
1395 CallFrame
* callFrame
= stackFrame
.callFrame
;
1396 JSValue value
= stackFrame
.args
[0].jsValue();
1397 JSValue baseVal
= stackFrame
.args
[1].jsValue();
1398 JSValue proto
= stackFrame
.args
[2].jsValue();
1400 // At least one of these checks must have failed to get to the slow case.
1401 ASSERT(!value
.isCell() || !baseVal
.isCell() || !proto
.isCell()
1402 || !value
.isObject() || !baseVal
.isObject() || !proto
.isObject()
1403 || (asObject(baseVal
)->structure()->typeInfo().flags() & (ImplementsHasInstance
| OverridesHasInstance
)) != ImplementsHasInstance
);
1406 // ECMA-262 15.3.5.3:
1407 // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
1408 TypeInfo
typeInfo(UnspecifiedType
, 0);
1409 if (!baseVal
.isObject() || !(typeInfo
= asObject(baseVal
)->structure()->typeInfo()).implementsHasInstance()) {
1410 CallFrame
* callFrame
= stackFrame
.callFrame
;
1411 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1412 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1413 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "instanceof", baseVal
, vPCIndex
, codeBlock
);
1414 VM_THROW_EXCEPTION();
1416 ASSERT(typeInfo
.type() != UnspecifiedType
);
1418 if (!typeInfo
.overridesHasInstance()) {
1419 if (!value
.isObject())
1420 return JSValue::encode(jsBoolean(false));
1422 if (!proto
.isObject()) {
1423 throwError(callFrame
, TypeError
, "instanceof called on an object with an invalid prototype property.");
1424 VM_THROW_EXCEPTION();
1428 JSValue result
= jsBoolean(asObject(baseVal
)->hasInstance(callFrame
, value
, proto
));
1429 CHECK_FOR_EXCEPTION_AT_END();
1431 return JSValue::encode(result
);
1434 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_del_by_id
)
1436 STUB_INIT_STACK_FRAME(stackFrame
);
1438 CallFrame
* callFrame
= stackFrame
.callFrame
;
1440 JSObject
* baseObj
= stackFrame
.args
[0].jsValue().toObject(callFrame
);
1442 JSValue result
= jsBoolean(baseObj
->deleteProperty(callFrame
, stackFrame
.args
[1].identifier()));
1443 CHECK_FOR_EXCEPTION_AT_END();
1444 return JSValue::encode(result
);
1447 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_mul
)
1449 STUB_INIT_STACK_FRAME(stackFrame
);
1451 JSValue src1
= stackFrame
.args
[0].jsValue();
1452 JSValue src2
= stackFrame
.args
[1].jsValue();
1456 if (src1
.getNumber(left
) && src2
.getNumber(right
))
1457 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
* right
));
1459 CallFrame
* callFrame
= stackFrame
.callFrame
;
1460 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toNumber(callFrame
) * src2
.toNumber(callFrame
));
1461 CHECK_FOR_EXCEPTION_AT_END();
1462 return JSValue::encode(result
);
1465 DEFINE_STUB_FUNCTION(JSObject
*, op_new_func
)
1467 STUB_INIT_STACK_FRAME(stackFrame
);
1469 return stackFrame
.args
[0].funcDeclNode()->makeFunction(stackFrame
.callFrame
, stackFrame
.callFrame
->scopeChain());
1472 DEFINE_STUB_FUNCTION(void*, op_call_JSFunction
)
1474 STUB_INIT_STACK_FRAME(stackFrame
);
1478 ASSERT(stackFrame
.args
[0].jsValue().getCallData(callData
) == CallTypeJS
);
1481 JSFunction
* function
= asFunction(stackFrame
.args
[0].jsValue());
1482 ASSERT(!function
->isHostFunction());
1483 FunctionBodyNode
* body
= function
->body();
1484 ScopeChainNode
* callDataScopeChain
= function
->scope().node();
1485 body
->jitCode(callDataScopeChain
);
1487 return &(body
->generatedBytecode());
1490 DEFINE_STUB_FUNCTION(VoidPtrPair
, op_call_arityCheck
)
1492 STUB_INIT_STACK_FRAME(stackFrame
);
1494 CallFrame
* callFrame
= stackFrame
.callFrame
;
1495 CodeBlock
* newCodeBlock
= stackFrame
.args
[3].codeBlock();
1496 ASSERT(newCodeBlock
->codeType() != NativeCode
);
1497 int argCount
= stackFrame
.args
[2].int32();
1499 ASSERT(argCount
!= newCodeBlock
->m_numParameters
);
1501 CallFrame
* oldCallFrame
= callFrame
->callerFrame();
1503 if (argCount
> newCodeBlock
->m_numParameters
) {
1504 size_t numParameters
= newCodeBlock
->m_numParameters
;
1505 Register
* r
= callFrame
->registers() + numParameters
;
1507 Register
* argv
= r
- RegisterFile::CallFrameHeaderSize
- numParameters
- argCount
;
1508 for (size_t i
= 0; i
< numParameters
; ++i
)
1509 argv
[i
+ argCount
] = argv
[i
];
1511 callFrame
= CallFrame::create(r
);
1512 callFrame
->setCallerFrame(oldCallFrame
);
1514 size_t omittedArgCount
= newCodeBlock
->m_numParameters
- argCount
;
1515 Register
* r
= callFrame
->registers() + omittedArgCount
;
1516 Register
* newEnd
= r
+ newCodeBlock
->m_numCalleeRegisters
;
1517 if (!stackFrame
.registerFile
->grow(newEnd
)) {
1518 // Rewind to the previous call frame because op_call already optimistically
1519 // moved the call frame forward.
1520 stackFrame
.callFrame
= oldCallFrame
;
1521 throwStackOverflowError(oldCallFrame
, stackFrame
.globalData
, stackFrame
.args
[1].returnAddress(), STUB_RETURN_ADDRESS
);
1522 RETURN_POINTER_PAIR(0, 0);
1525 Register
* argv
= r
- RegisterFile::CallFrameHeaderSize
- omittedArgCount
;
1526 for (size_t i
= 0; i
< omittedArgCount
; ++i
)
1527 argv
[i
] = jsUndefined();
1529 callFrame
= CallFrame::create(r
);
1530 callFrame
->setCallerFrame(oldCallFrame
);
1533 RETURN_POINTER_PAIR(newCodeBlock
, callFrame
);
1536 #if ENABLE(JIT_OPTIMIZE_CALL)
1537 DEFINE_STUB_FUNCTION(void*, vm_dontLazyLinkCall
)
1539 STUB_INIT_STACK_FRAME(stackFrame
);
1541 JSGlobalData
* globalData
= stackFrame
.globalData
;
1542 JSFunction
* callee
= asFunction(stackFrame
.args
[0].jsValue());
1544 ctiPatchNearCallByReturnAddress(stackFrame
.callFrame
->callerFrame()->codeBlock(), stackFrame
.args
[1].returnAddress(), globalData
->jitStubs
.ctiVirtualCallLink());
1546 return callee
->body()->generatedJITCode().addressForCall().executableAddress();
1549 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall
)
1551 STUB_INIT_STACK_FRAME(stackFrame
);
1553 JSFunction
* callee
= asFunction(stackFrame
.args
[0].jsValue());
1554 JITCode
& jitCode
= callee
->body()->generatedJITCode();
1556 CodeBlock
* codeBlock
= 0;
1557 if (!callee
->isHostFunction())
1558 codeBlock
= &callee
->body()->bytecode(callee
->scope().node());
1560 codeBlock
= &callee
->body()->generatedBytecode();
1562 CallLinkInfo
* callLinkInfo
= &stackFrame
.callFrame
->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame
.args
[1].returnAddress());
1563 JIT::linkCall(callee
, stackFrame
.callFrame
->callerFrame()->codeBlock(), codeBlock
, jitCode
, callLinkInfo
, stackFrame
.args
[2].int32(), stackFrame
.globalData
);
1565 return jitCode
.addressForCall().executableAddress();
1567 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
1569 DEFINE_STUB_FUNCTION(JSObject
*, op_push_activation
)
1571 STUB_INIT_STACK_FRAME(stackFrame
);
1573 JSActivation
* activation
= new (stackFrame
.globalData
) JSActivation(stackFrame
.callFrame
, static_cast<FunctionBodyNode
*>(stackFrame
.callFrame
->codeBlock()->ownerNode()));
1574 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->copy()->push(activation
));
1578 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_call_NotJSFunction
)
1580 STUB_INIT_STACK_FRAME(stackFrame
);
1582 JSValue funcVal
= stackFrame
.args
[0].jsValue();
1585 CallType callType
= funcVal
.getCallData(callData
);
1587 ASSERT(callType
!= CallTypeJS
);
1589 if (callType
== CallTypeHost
) {
1590 int registerOffset
= stackFrame
.args
[1].int32();
1591 int argCount
= stackFrame
.args
[2].int32();
1592 CallFrame
* previousCallFrame
= stackFrame
.callFrame
;
1593 CallFrame
* callFrame
= CallFrame::create(previousCallFrame
->registers() + registerOffset
);
1595 callFrame
->init(0, static_cast<Instruction
*>((STUB_RETURN_ADDRESS
).value()), previousCallFrame
->scopeChain(), previousCallFrame
, 0, argCount
, 0);
1596 stackFrame
.callFrame
= callFrame
;
1598 Register
* argv
= stackFrame
.callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- argCount
;
1599 ArgList
argList(argv
+ 1, argCount
- 1);
1601 JSValue returnValue
;
1603 SamplingTool::HostCallRecord
callRecord(CTI_SAMPLER
);
1605 // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
1606 JSValue thisValue
= argv
[0].jsValue();
1607 if (thisValue
== jsNull())
1608 thisValue
= callFrame
->globalThisValue();
1610 returnValue
= callData
.native
.function(callFrame
, asObject(funcVal
), thisValue
, argList
);
1612 stackFrame
.callFrame
= previousCallFrame
;
1613 CHECK_FOR_EXCEPTION();
1615 return JSValue::encode(returnValue
);
1618 ASSERT(callType
== CallTypeNone
);
1620 CallFrame
* callFrame
= stackFrame
.callFrame
;
1621 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1622 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1623 stackFrame
.globalData
->exception
= createNotAFunctionError(stackFrame
.callFrame
, funcVal
, vPCIndex
, codeBlock
);
1624 VM_THROW_EXCEPTION();
1627 DEFINE_STUB_FUNCTION(void, op_create_arguments
)
1629 STUB_INIT_STACK_FRAME(stackFrame
);
1631 Arguments
* arguments
= new (stackFrame
.globalData
) Arguments(stackFrame
.callFrame
);
1632 stackFrame
.callFrame
->setCalleeArguments(arguments
);
1633 stackFrame
.callFrame
[RegisterFile::ArgumentsRegister
] = JSValue(arguments
);
1636 DEFINE_STUB_FUNCTION(void, op_create_arguments_no_params
)
1638 STUB_INIT_STACK_FRAME(stackFrame
);
1640 Arguments
* arguments
= new (stackFrame
.globalData
) Arguments(stackFrame
.callFrame
, Arguments::NoParameters
);
1641 stackFrame
.callFrame
->setCalleeArguments(arguments
);
1642 stackFrame
.callFrame
[RegisterFile::ArgumentsRegister
] = JSValue(arguments
);
1645 DEFINE_STUB_FUNCTION(void, op_tear_off_activation
)
1647 STUB_INIT_STACK_FRAME(stackFrame
);
1649 ASSERT(stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
1650 asActivation(stackFrame
.args
[0].jsValue())->copyRegisters(stackFrame
.callFrame
->optionalCalleeArguments());
1653 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments
)
1655 STUB_INIT_STACK_FRAME(stackFrame
);
1657 ASSERT(stackFrame
.callFrame
->codeBlock()->usesArguments() && !stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
1658 if (stackFrame
.callFrame
->optionalCalleeArguments())
1659 stackFrame
.callFrame
->optionalCalleeArguments()->copyRegisters();
1662 DEFINE_STUB_FUNCTION(void, op_profile_will_call
)
1664 STUB_INIT_STACK_FRAME(stackFrame
);
1666 ASSERT(*stackFrame
.enabledProfilerReference
);
1667 (*stackFrame
.enabledProfilerReference
)->willExecute(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue());
1670 DEFINE_STUB_FUNCTION(void, op_profile_did_call
)
1672 STUB_INIT_STACK_FRAME(stackFrame
);
1674 ASSERT(*stackFrame
.enabledProfilerReference
);
1675 (*stackFrame
.enabledProfilerReference
)->didExecute(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue());
1678 DEFINE_STUB_FUNCTION(void, op_ret_scopeChain
)
1680 STUB_INIT_STACK_FRAME(stackFrame
);
1682 ASSERT(stackFrame
.callFrame
->codeBlock()->needsFullScopeChain());
1683 stackFrame
.callFrame
->scopeChain()->deref();
1686 DEFINE_STUB_FUNCTION(JSObject
*, op_new_array
)
1688 STUB_INIT_STACK_FRAME(stackFrame
);
1690 ArgList
argList(&stackFrame
.callFrame
->registers()[stackFrame
.args
[0].int32()], stackFrame
.args
[1].int32());
1691 return constructArray(stackFrame
.callFrame
, argList
);
1694 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve
)
1696 STUB_INIT_STACK_FRAME(stackFrame
);
1698 CallFrame
* callFrame
= stackFrame
.callFrame
;
1699 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
1701 ScopeChainIterator iter
= scopeChain
->begin();
1702 ScopeChainIterator end
= scopeChain
->end();
1703 ASSERT(iter
!= end
);
1705 Identifier
& ident
= stackFrame
.args
[0].identifier();
1707 JSObject
* o
= *iter
;
1708 PropertySlot
slot(o
);
1709 if (o
->getPropertySlot(callFrame
, ident
, slot
)) {
1710 JSValue result
= slot
.getValue(callFrame
, ident
);
1711 CHECK_FOR_EXCEPTION_AT_END();
1712 return JSValue::encode(result
);
1714 } while (++iter
!= end
);
1716 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1717 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1718 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, codeBlock
);
1719 VM_THROW_EXCEPTION();
1722 DEFINE_STUB_FUNCTION(JSObject
*, op_construct_JSConstruct
)
1724 STUB_INIT_STACK_FRAME(stackFrame
);
1726 JSFunction
* constructor
= asFunction(stackFrame
.args
[0].jsValue());
1727 if (constructor
->isHostFunction()) {
1728 CallFrame
* callFrame
= stackFrame
.callFrame
;
1729 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1730 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1731 stackFrame
.globalData
->exception
= createNotAConstructorError(callFrame
, constructor
, vPCIndex
, codeBlock
);
1732 VM_THROW_EXCEPTION();
1736 ConstructData constructData
;
1737 ASSERT(constructor
->getConstructData(constructData
) == ConstructTypeJS
);
1740 Structure
* structure
;
1741 if (stackFrame
.args
[3].jsValue().isObject())
1742 structure
= asObject(stackFrame
.args
[3].jsValue())->inheritorID();
1744 structure
= constructor
->scope().node()->globalObject()->emptyObjectStructure();
1745 return new (stackFrame
.globalData
) JSObject(structure
);
1748 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_construct_NotJSConstruct
)
1750 STUB_INIT_STACK_FRAME(stackFrame
);
1752 CallFrame
* callFrame
= stackFrame
.callFrame
;
1754 JSValue constrVal
= stackFrame
.args
[0].jsValue();
1755 int argCount
= stackFrame
.args
[2].int32();
1756 int thisRegister
= stackFrame
.args
[4].int32();
1758 ConstructData constructData
;
1759 ConstructType constructType
= constrVal
.getConstructData(constructData
);
1761 if (constructType
== ConstructTypeHost
) {
1762 ArgList
argList(callFrame
->registers() + thisRegister
+ 1, argCount
- 1);
1764 JSValue returnValue
;
1766 SamplingTool::HostCallRecord
callRecord(CTI_SAMPLER
);
1767 returnValue
= constructData
.native
.function(callFrame
, asObject(constrVal
), argList
);
1769 CHECK_FOR_EXCEPTION();
1771 return JSValue::encode(returnValue
);
1774 ASSERT(constructType
== ConstructTypeNone
);
1776 CodeBlock
* codeBlock
= callFrame
->codeBlock();
1777 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
1778 stackFrame
.globalData
->exception
= createNotAConstructorError(callFrame
, constrVal
, vPCIndex
, codeBlock
);
1779 VM_THROW_EXCEPTION();
1782 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val
)
1784 STUB_INIT_STACK_FRAME(stackFrame
);
1786 CallFrame
* callFrame
= stackFrame
.callFrame
;
1787 JSGlobalData
* globalData
= stackFrame
.globalData
;
1789 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1790 JSValue subscript
= stackFrame
.args
[1].jsValue();
1794 if (LIKELY(subscript
.isUInt32())) {
1795 uint32_t i
= subscript
.asUInt32();
1796 if (isJSArray(globalData
, baseValue
)) {
1797 JSArray
* jsArray
= asArray(baseValue
);
1798 if (jsArray
->canGetIndex(i
))
1799 result
= jsArray
->getIndex(i
);
1801 result
= jsArray
->JSArray::get(callFrame
, i
);
1802 } else if (isJSString(globalData
, baseValue
) && asString(baseValue
)->canGetIndex(i
)) {
1803 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1804 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val_string
));
1805 result
= asString(baseValue
)->getIndex(stackFrame
.globalData
, i
);
1806 } else if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
1807 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1808 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val_byte_array
));
1809 return JSValue::encode(asByteArray(baseValue
)->getIndex(callFrame
, i
));
1811 result
= baseValue
.get(callFrame
, i
);
1813 Identifier
property(callFrame
, subscript
.toString(callFrame
));
1814 result
= baseValue
.get(callFrame
, property
);
1817 CHECK_FOR_EXCEPTION_AT_END();
1818 return JSValue::encode(result
);
1821 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val_string
)
1823 STUB_INIT_STACK_FRAME(stackFrame
);
1825 CallFrame
* callFrame
= stackFrame
.callFrame
;
1826 JSGlobalData
* globalData
= stackFrame
.globalData
;
1828 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1829 JSValue subscript
= stackFrame
.args
[1].jsValue();
1833 if (LIKELY(subscript
.isUInt32())) {
1834 uint32_t i
= subscript
.asUInt32();
1835 if (isJSString(globalData
, baseValue
) && asString(baseValue
)->canGetIndex(i
))
1836 result
= asString(baseValue
)->getIndex(stackFrame
.globalData
, i
);
1838 result
= baseValue
.get(callFrame
, i
);
1839 if (!isJSString(globalData
, baseValue
))
1840 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val
));
1843 Identifier
property(callFrame
, subscript
.toString(callFrame
));
1844 result
= baseValue
.get(callFrame
, property
);
1847 CHECK_FOR_EXCEPTION_AT_END();
1848 return JSValue::encode(result
);
1851 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_get_by_val_byte_array
)
1853 STUB_INIT_STACK_FRAME(stackFrame
);
1855 CallFrame
* callFrame
= stackFrame
.callFrame
;
1856 JSGlobalData
* globalData
= stackFrame
.globalData
;
1858 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1859 JSValue subscript
= stackFrame
.args
[1].jsValue();
1863 if (LIKELY(subscript
.isUInt32())) {
1864 uint32_t i
= subscript
.asUInt32();
1865 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
1866 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1867 return JSValue::encode(asByteArray(baseValue
)->getIndex(callFrame
, i
));
1870 result
= baseValue
.get(callFrame
, i
);
1871 if (!isJSByteArray(globalData
, baseValue
))
1872 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_get_by_val
));
1874 Identifier
property(callFrame
, subscript
.toString(callFrame
));
1875 result
= baseValue
.get(callFrame
, property
);
1878 CHECK_FOR_EXCEPTION_AT_END();
1879 return JSValue::encode(result
);
1882 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_sub
)
1884 STUB_INIT_STACK_FRAME(stackFrame
);
1886 JSValue src1
= stackFrame
.args
[0].jsValue();
1887 JSValue src2
= stackFrame
.args
[1].jsValue();
1891 if (src1
.getNumber(left
) && src2
.getNumber(right
))
1892 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
- right
));
1894 CallFrame
* callFrame
= stackFrame
.callFrame
;
1895 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toNumber(callFrame
) - src2
.toNumber(callFrame
));
1896 CHECK_FOR_EXCEPTION_AT_END();
1897 return JSValue::encode(result
);
1900 DEFINE_STUB_FUNCTION(void, op_put_by_val
)
1902 STUB_INIT_STACK_FRAME(stackFrame
);
1904 CallFrame
* callFrame
= stackFrame
.callFrame
;
1905 JSGlobalData
* globalData
= stackFrame
.globalData
;
1907 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1908 JSValue subscript
= stackFrame
.args
[1].jsValue();
1909 JSValue value
= stackFrame
.args
[2].jsValue();
1911 if (LIKELY(subscript
.isUInt32())) {
1912 uint32_t i
= subscript
.asUInt32();
1913 if (isJSArray(globalData
, baseValue
)) {
1914 JSArray
* jsArray
= asArray(baseValue
);
1915 if (jsArray
->canSetIndex(i
))
1916 jsArray
->setIndex(i
, value
);
1918 jsArray
->JSArray::put(callFrame
, i
, value
);
1919 } else if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
1920 JSByteArray
* jsByteArray
= asByteArray(baseValue
);
1921 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_put_by_val_byte_array
));
1922 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1923 if (value
.isInt32()) {
1924 jsByteArray
->setIndex(i
, value
.asInt32());
1928 if (value
.getNumber(dValue
)) {
1929 jsByteArray
->setIndex(i
, dValue
);
1934 baseValue
.put(callFrame
, i
, value
);
1936 baseValue
.put(callFrame
, i
, value
);
1938 Identifier
property(callFrame
, subscript
.toString(callFrame
));
1939 if (!stackFrame
.globalData
->exception
) { // Don't put to an object if toString threw an exception.
1940 PutPropertySlot slot
;
1941 baseValue
.put(callFrame
, property
, value
, slot
);
1945 CHECK_FOR_EXCEPTION_AT_END();
1948 DEFINE_STUB_FUNCTION(void, op_put_by_val_array
)
1950 STUB_INIT_STACK_FRAME(stackFrame
);
1952 CallFrame
* callFrame
= stackFrame
.callFrame
;
1953 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1954 int i
= stackFrame
.args
[1].int32();
1955 JSValue value
= stackFrame
.args
[2].jsValue();
1957 ASSERT(isJSArray(stackFrame
.globalData
, baseValue
));
1960 asArray(baseValue
)->JSArray::put(callFrame
, i
, value
);
1962 Identifier
property(callFrame
, UString::from(i
));
1963 PutPropertySlot slot
;
1964 baseValue
.put(callFrame
, property
, value
, slot
);
1967 CHECK_FOR_EXCEPTION_AT_END();
1970 DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array
)
1972 STUB_INIT_STACK_FRAME(stackFrame
);
1974 CallFrame
* callFrame
= stackFrame
.callFrame
;
1975 JSGlobalData
* globalData
= stackFrame
.globalData
;
1977 JSValue baseValue
= stackFrame
.args
[0].jsValue();
1978 JSValue subscript
= stackFrame
.args
[1].jsValue();
1979 JSValue value
= stackFrame
.args
[2].jsValue();
1981 if (LIKELY(subscript
.isUInt32())) {
1982 uint32_t i
= subscript
.asUInt32();
1983 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
1984 JSByteArray
* jsByteArray
= asByteArray(baseValue
);
1986 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1987 if (value
.isInt32()) {
1988 jsByteArray
->setIndex(i
, value
.asInt32());
1992 if (value
.getNumber(dValue
)) {
1993 jsByteArray
->setIndex(i
, dValue
);
1999 if (!isJSByteArray(globalData
, baseValue
))
2000 ctiPatchCallByReturnAddress(callFrame
->codeBlock(), STUB_RETURN_ADDRESS
, FunctionPtr(cti_op_put_by_val
));
2001 baseValue
.put(callFrame
, i
, value
);
2003 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2004 if (!stackFrame
.globalData
->exception
) { // Don't put to an object if toString threw an exception.
2005 PutPropertySlot slot
;
2006 baseValue
.put(callFrame
, property
, value
, slot
);
2010 CHECK_FOR_EXCEPTION_AT_END();
2013 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_lesseq
)
2015 STUB_INIT_STACK_FRAME(stackFrame
);
2017 CallFrame
* callFrame
= stackFrame
.callFrame
;
2018 JSValue result
= jsBoolean(jsLessEq(callFrame
, stackFrame
.args
[0].jsValue(), stackFrame
.args
[1].jsValue()));
2019 CHECK_FOR_EXCEPTION_AT_END();
2020 return JSValue::encode(result
);
2023 DEFINE_STUB_FUNCTION(int, op_loop_if_true
)
2025 STUB_INIT_STACK_FRAME(stackFrame
);
2027 JSValue src1
= stackFrame
.args
[0].jsValue();
2029 CallFrame
* callFrame
= stackFrame
.callFrame
;
2031 bool result
= src1
.toBoolean(callFrame
);
2032 CHECK_FOR_EXCEPTION_AT_END();
2036 DEFINE_STUB_FUNCTION(int, op_load_varargs
)
2038 STUB_INIT_STACK_FRAME(stackFrame
);
2040 CallFrame
* callFrame
= stackFrame
.callFrame
;
2041 RegisterFile
* registerFile
= stackFrame
.registerFile
;
2042 int argsOffset
= stackFrame
.args
[0].int32();
2043 JSValue arguments
= callFrame
->registers()[argsOffset
].jsValue();
2044 uint32_t argCount
= 0;
2046 int providedParams
= callFrame
->registers()[RegisterFile::ArgumentCount
].i() - 1;
2047 argCount
= providedParams
;
2048 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2049 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2050 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2051 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2052 VM_THROW_EXCEPTION();
2054 int32_t expectedParams
= callFrame
->callee()->body()->parameterCount();
2055 int32_t inplaceArgs
= min(providedParams
, expectedParams
);
2057 Register
* inplaceArgsDst
= callFrame
->registers() + argsOffset
;
2059 Register
* inplaceArgsEnd
= inplaceArgsDst
+ inplaceArgs
;
2060 Register
* inplaceArgsEnd2
= inplaceArgsDst
+ providedParams
;
2062 Register
* inplaceArgsSrc
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- expectedParams
;
2063 Register
* inplaceArgsSrc2
= inplaceArgsSrc
- providedParams
- 1 + inplaceArgs
;
2065 // First step is to copy the "expected" parameters from their normal location relative to the callframe
2066 while (inplaceArgsDst
< inplaceArgsEnd
)
2067 *inplaceArgsDst
++ = *inplaceArgsSrc
++;
2069 // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
2070 while (inplaceArgsDst
< inplaceArgsEnd2
)
2071 *inplaceArgsDst
++ = *inplaceArgsSrc2
++;
2073 } else if (!arguments
.isUndefinedOrNull()) {
2074 if (!arguments
.isObject()) {
2075 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2076 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2077 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "Function.prototype.apply", arguments
, vPCIndex
, codeBlock
);
2078 VM_THROW_EXCEPTION();
2080 if (asObject(arguments
)->classInfo() == &Arguments::info
) {
2081 Arguments
* argsObject
= asArguments(arguments
);
2082 argCount
= argsObject
->numProvidedArguments(callFrame
);
2083 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2084 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2085 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2086 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2087 VM_THROW_EXCEPTION();
2089 argsObject
->copyToRegisters(callFrame
, callFrame
->registers() + argsOffset
, argCount
);
2090 } else if (isJSArray(&callFrame
->globalData(), arguments
)) {
2091 JSArray
* array
= asArray(arguments
);
2092 argCount
= array
->length();
2093 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2094 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2095 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2096 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2097 VM_THROW_EXCEPTION();
2099 array
->copyToRegisters(callFrame
, callFrame
->registers() + argsOffset
, argCount
);
2100 } else if (asObject(arguments
)->inherits(&JSArray::info
)) {
2101 JSObject
* argObject
= asObject(arguments
);
2102 argCount
= argObject
->get(callFrame
, callFrame
->propertyNames().length
).toUInt32(callFrame
);
2103 int32_t sizeDelta
= argsOffset
+ argCount
+ RegisterFile::CallFrameHeaderSize
;
2104 Register
* newEnd
= callFrame
->registers() + sizeDelta
;
2105 if (!registerFile
->grow(newEnd
) || ((newEnd
- callFrame
->registers()) != sizeDelta
)) {
2106 stackFrame
.globalData
->exception
= createStackOverflowError(callFrame
);
2107 VM_THROW_EXCEPTION();
2109 Register
* argsBuffer
= callFrame
->registers() + argsOffset
;
2110 for (unsigned i
= 0; i
< argCount
; ++i
) {
2111 argsBuffer
[i
] = asObject(arguments
)->get(callFrame
, i
);
2112 CHECK_FOR_EXCEPTION();
2115 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2116 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2117 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "Function.prototype.apply", arguments
, vPCIndex
, codeBlock
);
2118 VM_THROW_EXCEPTION();
2122 return argCount
+ 1;
2125 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_negate
)
2127 STUB_INIT_STACK_FRAME(stackFrame
);
2129 JSValue src
= stackFrame
.args
[0].jsValue();
2132 if (src
.getNumber(v
))
2133 return JSValue::encode(jsNumber(stackFrame
.globalData
, -v
));
2135 CallFrame
* callFrame
= stackFrame
.callFrame
;
2136 JSValue result
= jsNumber(stackFrame
.globalData
, -src
.toNumber(callFrame
));
2137 CHECK_FOR_EXCEPTION_AT_END();
2138 return JSValue::encode(result
);
2141 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_base
)
2143 STUB_INIT_STACK_FRAME(stackFrame
);
2145 return JSValue::encode(JSC::resolveBase(stackFrame
.callFrame
, stackFrame
.args
[0].identifier(), stackFrame
.callFrame
->scopeChain()));
2148 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_skip
)
2150 STUB_INIT_STACK_FRAME(stackFrame
);
2152 CallFrame
* callFrame
= stackFrame
.callFrame
;
2153 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
2155 int skip
= stackFrame
.args
[1].int32();
2157 ScopeChainIterator iter
= scopeChain
->begin();
2158 ScopeChainIterator end
= scopeChain
->end();
2159 ASSERT(iter
!= end
);
2162 ASSERT(iter
!= end
);
2164 Identifier
& ident
= stackFrame
.args
[0].identifier();
2166 JSObject
* o
= *iter
;
2167 PropertySlot
slot(o
);
2168 if (o
->getPropertySlot(callFrame
, ident
, slot
)) {
2169 JSValue result
= slot
.getValue(callFrame
, ident
);
2170 CHECK_FOR_EXCEPTION_AT_END();
2171 return JSValue::encode(result
);
2173 } while (++iter
!= end
);
2175 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2176 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2177 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, codeBlock
);
2178 VM_THROW_EXCEPTION();
2181 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_global
)
2183 STUB_INIT_STACK_FRAME(stackFrame
);
2185 CallFrame
* callFrame
= stackFrame
.callFrame
;
2186 JSGlobalObject
* globalObject
= stackFrame
.args
[0].globalObject();
2187 Identifier
& ident
= stackFrame
.args
[1].identifier();
2188 unsigned globalResolveInfoIndex
= stackFrame
.args
[2].int32();
2189 ASSERT(globalObject
->isGlobalObject());
2191 PropertySlot
slot(globalObject
);
2192 if (globalObject
->getPropertySlot(callFrame
, ident
, slot
)) {
2193 JSValue result
= slot
.getValue(callFrame
, ident
);
2194 if (slot
.isCacheable() && !globalObject
->structure()->isUncacheableDictionary() && slot
.slotBase() == globalObject
) {
2195 GlobalResolveInfo
& globalResolveInfo
= callFrame
->codeBlock()->globalResolveInfo(globalResolveInfoIndex
);
2196 if (globalResolveInfo
.structure
)
2197 globalResolveInfo
.structure
->deref();
2198 globalObject
->structure()->ref();
2199 globalResolveInfo
.structure
= globalObject
->structure();
2200 globalResolveInfo
.offset
= slot
.cachedOffset();
2201 return JSValue::encode(result
);
2204 CHECK_FOR_EXCEPTION_AT_END();
2205 return JSValue::encode(result
);
2208 unsigned vPCIndex
= callFrame
->codeBlock()->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2209 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, callFrame
->codeBlock());
2210 VM_THROW_EXCEPTION();
2213 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_div
)
2215 STUB_INIT_STACK_FRAME(stackFrame
);
2217 JSValue src1
= stackFrame
.args
[0].jsValue();
2218 JSValue src2
= stackFrame
.args
[1].jsValue();
2222 if (src1
.getNumber(left
) && src2
.getNumber(right
))
2223 return JSValue::encode(jsNumber(stackFrame
.globalData
, left
/ right
));
2225 CallFrame
* callFrame
= stackFrame
.callFrame
;
2226 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toNumber(callFrame
) / src2
.toNumber(callFrame
));
2227 CHECK_FOR_EXCEPTION_AT_END();
2228 return JSValue::encode(result
);
2231 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_pre_dec
)
2233 STUB_INIT_STACK_FRAME(stackFrame
);
2235 JSValue v
= stackFrame
.args
[0].jsValue();
2237 CallFrame
* callFrame
= stackFrame
.callFrame
;
2238 JSValue result
= jsNumber(stackFrame
.globalData
, v
.toNumber(callFrame
) - 1);
2239 CHECK_FOR_EXCEPTION_AT_END();
2240 return JSValue::encode(result
);
2243 DEFINE_STUB_FUNCTION(int, op_jless
)
2245 STUB_INIT_STACK_FRAME(stackFrame
);
2247 JSValue src1
= stackFrame
.args
[0].jsValue();
2248 JSValue src2
= stackFrame
.args
[1].jsValue();
2249 CallFrame
* callFrame
= stackFrame
.callFrame
;
2251 bool result
= jsLess(callFrame
, src1
, src2
);
2252 CHECK_FOR_EXCEPTION_AT_END();
2256 DEFINE_STUB_FUNCTION(int, op_jlesseq
)
2258 STUB_INIT_STACK_FRAME(stackFrame
);
2260 JSValue src1
= stackFrame
.args
[0].jsValue();
2261 JSValue src2
= stackFrame
.args
[1].jsValue();
2262 CallFrame
* callFrame
= stackFrame
.callFrame
;
2264 bool result
= jsLessEq(callFrame
, src1
, src2
);
2265 CHECK_FOR_EXCEPTION_AT_END();
2269 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_not
)
2271 STUB_INIT_STACK_FRAME(stackFrame
);
2273 JSValue src
= stackFrame
.args
[0].jsValue();
2275 CallFrame
* callFrame
= stackFrame
.callFrame
;
2277 JSValue result
= jsBoolean(!src
.toBoolean(callFrame
));
2278 CHECK_FOR_EXCEPTION_AT_END();
2279 return JSValue::encode(result
);
2282 DEFINE_STUB_FUNCTION(int, op_jtrue
)
2284 STUB_INIT_STACK_FRAME(stackFrame
);
2286 JSValue src1
= stackFrame
.args
[0].jsValue();
2288 CallFrame
* callFrame
= stackFrame
.callFrame
;
2290 bool result
= src1
.toBoolean(callFrame
);
2291 CHECK_FOR_EXCEPTION_AT_END();
2295 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_post_inc
)
2297 STUB_INIT_STACK_FRAME(stackFrame
);
2299 JSValue v
= stackFrame
.args
[0].jsValue();
2301 CallFrame
* callFrame
= stackFrame
.callFrame
;
2303 JSValue number
= v
.toJSNumber(callFrame
);
2304 CHECK_FOR_EXCEPTION_AT_END();
2306 callFrame
->registers()[stackFrame
.args
[1].int32()] = jsNumber(stackFrame
.globalData
, number
.uncheckedGetNumber() + 1);
2307 return JSValue::encode(number
);
2310 #if USE(JSVALUE32_64)
2312 DEFINE_STUB_FUNCTION(int, op_eq
)
2314 STUB_INIT_STACK_FRAME(stackFrame
);
2316 JSValue src1
= stackFrame
.args
[0].jsValue();
2317 JSValue src2
= stackFrame
.args
[1].jsValue();
2320 if (src2
.isUndefined()) {
2321 return src1
.isNull() ||
2322 (src1
.isCell() && asCell(src1
)->structure()->typeInfo().masqueradesAsUndefined()) ||
2326 if (src2
.isNull()) {
2327 return src1
.isUndefined() ||
2328 (src1
.isCell() && asCell(src1
)->structure()->typeInfo().masqueradesAsUndefined()) ||
2332 if (src1
.isInt32()) {
2333 if (src2
.isDouble())
2334 return src1
.asInt32() == src2
.asDouble();
2335 double d
= src2
.toNumber(stackFrame
.callFrame
);
2336 CHECK_FOR_EXCEPTION();
2337 return src1
.asInt32() == d
;
2340 if (src1
.isDouble()) {
2342 return src1
.asDouble() == src2
.asInt32();
2343 double d
= src2
.toNumber(stackFrame
.callFrame
);
2344 CHECK_FOR_EXCEPTION();
2345 return src1
.asDouble() == d
;
2348 if (src1
.isTrue()) {
2351 double d
= src2
.toNumber(stackFrame
.callFrame
);
2352 CHECK_FOR_EXCEPTION();
2356 if (src1
.isFalse()) {
2359 double d
= src2
.toNumber(stackFrame
.callFrame
);
2360 CHECK_FOR_EXCEPTION();
2364 if (src1
.isUndefined())
2365 return src2
.isCell() && asCell(src2
)->structure()->typeInfo().masqueradesAsUndefined();
2368 return src2
.isCell() && asCell(src2
)->structure()->typeInfo().masqueradesAsUndefined();
2370 ASSERT(src1
.isCell());
2372 JSCell
* cell1
= asCell(src1
);
2374 if (cell1
->isString()) {
2376 return static_cast<JSString
*>(cell1
)->value().toDouble() == src2
.asInt32();
2378 if (src2
.isDouble())
2379 return static_cast<JSString
*>(cell1
)->value().toDouble() == src2
.asDouble();
2382 return static_cast<JSString
*>(cell1
)->value().toDouble() == 1.0;
2385 return static_cast<JSString
*>(cell1
)->value().toDouble() == 0.0;
2387 ASSERT(src2
.isCell());
2388 JSCell
* cell2
= asCell(src2
);
2389 if (cell2
->isString())
2390 return static_cast<JSString
*>(cell1
)->value() == static_cast<JSString
*>(cell2
)->value();
2392 ASSERT(cell2
->isObject());
2393 src2
= static_cast<JSObject
*>(cell2
)->toPrimitive(stackFrame
.callFrame
);
2394 CHECK_FOR_EXCEPTION();
2398 ASSERT(cell1
->isObject());
2399 if (src2
.isObject())
2400 return static_cast<JSObject
*>(cell1
) == asObject(src2
);
2401 src1
= static_cast<JSObject
*>(cell1
)->toPrimitive(stackFrame
.callFrame
);
2402 CHECK_FOR_EXCEPTION();
2406 DEFINE_STUB_FUNCTION(int, op_eq_strings
)
2408 STUB_INIT_STACK_FRAME(stackFrame
);
2410 JSString
* string1
= stackFrame
.args
[0].jsString();
2411 JSString
* string2
= stackFrame
.args
[1].jsString();
2413 ASSERT(string1
->isString());
2414 ASSERT(string2
->isString());
2415 return string1
->value() == string2
->value();
2418 #else // USE(JSVALUE32_64)
2420 DEFINE_STUB_FUNCTION(int, op_eq
)
2422 STUB_INIT_STACK_FRAME(stackFrame
);
2424 JSValue src1
= stackFrame
.args
[0].jsValue();
2425 JSValue src2
= stackFrame
.args
[1].jsValue();
2427 CallFrame
* callFrame
= stackFrame
.callFrame
;
2429 bool result
= JSValue::equalSlowCaseInline(callFrame
, src1
, src2
);
2430 CHECK_FOR_EXCEPTION_AT_END();
2434 #endif // USE(JSVALUE32_64)
2436 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_lshift
)
2438 STUB_INIT_STACK_FRAME(stackFrame
);
2440 JSValue val
= stackFrame
.args
[0].jsValue();
2441 JSValue shift
= stackFrame
.args
[1].jsValue();
2443 CallFrame
* callFrame
= stackFrame
.callFrame
;
2444 JSValue result
= jsNumber(stackFrame
.globalData
, (val
.toInt32(callFrame
)) << (shift
.toUInt32(callFrame
) & 0x1f));
2445 CHECK_FOR_EXCEPTION_AT_END();
2446 return JSValue::encode(result
);
2449 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitand
)
2451 STUB_INIT_STACK_FRAME(stackFrame
);
2453 JSValue src1
= stackFrame
.args
[0].jsValue();
2454 JSValue src2
= stackFrame
.args
[1].jsValue();
2456 ASSERT(!src1
.isInt32() || !src2
.isInt32());
2457 CallFrame
* callFrame
= stackFrame
.callFrame
;
2458 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toInt32(callFrame
) & src2
.toInt32(callFrame
));
2459 CHECK_FOR_EXCEPTION_AT_END();
2460 return JSValue::encode(result
);
2463 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_rshift
)
2465 STUB_INIT_STACK_FRAME(stackFrame
);
2467 JSValue val
= stackFrame
.args
[0].jsValue();
2468 JSValue shift
= stackFrame
.args
[1].jsValue();
2470 CallFrame
* callFrame
= stackFrame
.callFrame
;
2471 JSValue result
= jsNumber(stackFrame
.globalData
, (val
.toInt32(callFrame
)) >> (shift
.toUInt32(callFrame
) & 0x1f));
2473 CHECK_FOR_EXCEPTION_AT_END();
2474 return JSValue::encode(result
);
2477 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitnot
)
2479 STUB_INIT_STACK_FRAME(stackFrame
);
2481 JSValue src
= stackFrame
.args
[0].jsValue();
2483 ASSERT(!src
.isInt32());
2484 CallFrame
* callFrame
= stackFrame
.callFrame
;
2485 JSValue result
= jsNumber(stackFrame
.globalData
, ~src
.toInt32(callFrame
));
2486 CHECK_FOR_EXCEPTION_AT_END();
2487 return JSValue::encode(result
);
2490 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_resolve_with_base
)
2492 STUB_INIT_STACK_FRAME(stackFrame
);
2494 CallFrame
* callFrame
= stackFrame
.callFrame
;
2495 ScopeChainNode
* scopeChain
= callFrame
->scopeChain();
2497 ScopeChainIterator iter
= scopeChain
->begin();
2498 ScopeChainIterator end
= scopeChain
->end();
2500 // FIXME: add scopeDepthIsZero optimization
2502 ASSERT(iter
!= end
);
2504 Identifier
& ident
= stackFrame
.args
[0].identifier();
2508 PropertySlot
slot(base
);
2509 if (base
->getPropertySlot(callFrame
, ident
, slot
)) {
2510 JSValue result
= slot
.getValue(callFrame
, ident
);
2511 CHECK_FOR_EXCEPTION_AT_END();
2513 callFrame
->registers()[stackFrame
.args
[1].int32()] = JSValue(base
);
2514 return JSValue::encode(result
);
2517 } while (iter
!= end
);
2519 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2520 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2521 stackFrame
.globalData
->exception
= createUndefinedVariableError(callFrame
, ident
, vPCIndex
, codeBlock
);
2522 VM_THROW_EXCEPTION_AT_END();
2523 return JSValue::encode(JSValue());
2526 DEFINE_STUB_FUNCTION(JSObject
*, op_new_func_exp
)
2528 STUB_INIT_STACK_FRAME(stackFrame
);
2530 return stackFrame
.args
[0].funcExprNode()->makeFunction(stackFrame
.callFrame
, stackFrame
.callFrame
->scopeChain());
2533 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_mod
)
2535 STUB_INIT_STACK_FRAME(stackFrame
);
2537 JSValue dividendValue
= stackFrame
.args
[0].jsValue();
2538 JSValue divisorValue
= stackFrame
.args
[1].jsValue();
2540 CallFrame
* callFrame
= stackFrame
.callFrame
;
2541 double d
= dividendValue
.toNumber(callFrame
);
2542 JSValue result
= jsNumber(stackFrame
.globalData
, fmod(d
, divisorValue
.toNumber(callFrame
)));
2543 CHECK_FOR_EXCEPTION_AT_END();
2544 return JSValue::encode(result
);
2547 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_less
)
2549 STUB_INIT_STACK_FRAME(stackFrame
);
2551 CallFrame
* callFrame
= stackFrame
.callFrame
;
2552 JSValue result
= jsBoolean(jsLess(callFrame
, stackFrame
.args
[0].jsValue(), stackFrame
.args
[1].jsValue()));
2553 CHECK_FOR_EXCEPTION_AT_END();
2554 return JSValue::encode(result
);
2557 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_post_dec
)
2559 STUB_INIT_STACK_FRAME(stackFrame
);
2561 JSValue v
= stackFrame
.args
[0].jsValue();
2563 CallFrame
* callFrame
= stackFrame
.callFrame
;
2565 JSValue number
= v
.toJSNumber(callFrame
);
2566 CHECK_FOR_EXCEPTION_AT_END();
2568 callFrame
->registers()[stackFrame
.args
[1].int32()] = jsNumber(stackFrame
.globalData
, number
.uncheckedGetNumber() - 1);
2569 return JSValue::encode(number
);
2572 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_urshift
)
2574 STUB_INIT_STACK_FRAME(stackFrame
);
2576 JSValue val
= stackFrame
.args
[0].jsValue();
2577 JSValue shift
= stackFrame
.args
[1].jsValue();
2579 CallFrame
* callFrame
= stackFrame
.callFrame
;
2580 JSValue result
= jsNumber(stackFrame
.globalData
, (val
.toUInt32(callFrame
)) >> (shift
.toUInt32(callFrame
) & 0x1f));
2581 CHECK_FOR_EXCEPTION_AT_END();
2582 return JSValue::encode(result
);
2585 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitxor
)
2587 STUB_INIT_STACK_FRAME(stackFrame
);
2589 JSValue src1
= stackFrame
.args
[0].jsValue();
2590 JSValue src2
= stackFrame
.args
[1].jsValue();
2592 CallFrame
* callFrame
= stackFrame
.callFrame
;
2594 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toInt32(callFrame
) ^ src2
.toInt32(callFrame
));
2595 CHECK_FOR_EXCEPTION_AT_END();
2596 return JSValue::encode(result
);
2599 DEFINE_STUB_FUNCTION(JSObject
*, op_new_regexp
)
2601 STUB_INIT_STACK_FRAME(stackFrame
);
2603 return new (stackFrame
.globalData
) RegExpObject(stackFrame
.callFrame
->lexicalGlobalObject()->regExpStructure(), stackFrame
.args
[0].regExp());
2606 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_bitor
)
2608 STUB_INIT_STACK_FRAME(stackFrame
);
2610 JSValue src1
= stackFrame
.args
[0].jsValue();
2611 JSValue src2
= stackFrame
.args
[1].jsValue();
2613 CallFrame
* callFrame
= stackFrame
.callFrame
;
2615 JSValue result
= jsNumber(stackFrame
.globalData
, src1
.toInt32(callFrame
) | src2
.toInt32(callFrame
));
2616 CHECK_FOR_EXCEPTION_AT_END();
2617 return JSValue::encode(result
);
2620 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_call_eval
)
2622 STUB_INIT_STACK_FRAME(stackFrame
);
2624 CallFrame
* callFrame
= stackFrame
.callFrame
;
2625 RegisterFile
* registerFile
= stackFrame
.registerFile
;
2627 Interpreter
* interpreter
= stackFrame
.globalData
->interpreter
;
2629 JSValue funcVal
= stackFrame
.args
[0].jsValue();
2630 int registerOffset
= stackFrame
.args
[1].int32();
2631 int argCount
= stackFrame
.args
[2].int32();
2633 Register
* newCallFrame
= callFrame
->registers() + registerOffset
;
2634 Register
* argv
= newCallFrame
- RegisterFile::CallFrameHeaderSize
- argCount
;
2635 JSValue thisValue
= argv
[0].jsValue();
2636 JSGlobalObject
* globalObject
= callFrame
->scopeChain()->globalObject();
2638 if (thisValue
== globalObject
&& funcVal
== globalObject
->evalFunction()) {
2639 JSValue exceptionValue
;
2640 JSValue result
= interpreter
->callEval(callFrame
, registerFile
, argv
, argCount
, registerOffset
, exceptionValue
);
2641 if (UNLIKELY(exceptionValue
)) {
2642 stackFrame
.globalData
->exception
= exceptionValue
;
2643 VM_THROW_EXCEPTION_AT_END();
2645 return JSValue::encode(result
);
2648 return JSValue::encode(JSValue());
2651 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_throw
)
2653 STUB_INIT_STACK_FRAME(stackFrame
);
2655 CallFrame
* callFrame
= stackFrame
.callFrame
;
2656 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2658 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2660 JSValue exceptionValue
= stackFrame
.args
[0].jsValue();
2661 ASSERT(exceptionValue
);
2663 HandlerInfo
* handler
= stackFrame
.globalData
->interpreter
->throwException(callFrame
, exceptionValue
, vPCIndex
, true);
2666 *stackFrame
.exception
= exceptionValue
;
2667 STUB_SET_RETURN_ADDRESS(reinterpret_cast<void*>(ctiOpThrowNotCaught
));
2668 return JSValue::encode(jsNull());
2671 stackFrame
.callFrame
= callFrame
;
2672 void* catchRoutine
= handler
->nativeCode
.executableAddress();
2673 ASSERT(catchRoutine
);
2674 STUB_SET_RETURN_ADDRESS(catchRoutine
);
2675 return JSValue::encode(exceptionValue
);
2678 DEFINE_STUB_FUNCTION(JSPropertyNameIterator
*, op_get_pnames
)
2680 STUB_INIT_STACK_FRAME(stackFrame
);
2682 return JSPropertyNameIterator::create(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue());
2685 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_next_pname
)
2687 STUB_INIT_STACK_FRAME(stackFrame
);
2689 JSPropertyNameIterator
* it
= stackFrame
.args
[0].propertyNameIterator();
2690 JSValue temp
= it
->next(stackFrame
.callFrame
);
2693 return JSValue::encode(temp
);
2696 DEFINE_STUB_FUNCTION(JSObject
*, op_push_scope
)
2698 STUB_INIT_STACK_FRAME(stackFrame
);
2700 JSObject
* o
= stackFrame
.args
[0].jsValue().toObject(stackFrame
.callFrame
);
2701 CHECK_FOR_EXCEPTION();
2702 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->push(o
));
2706 DEFINE_STUB_FUNCTION(void, op_pop_scope
)
2708 STUB_INIT_STACK_FRAME(stackFrame
);
2710 stackFrame
.callFrame
->setScopeChain(stackFrame
.callFrame
->scopeChain()->pop());
2713 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_typeof
)
2715 STUB_INIT_STACK_FRAME(stackFrame
);
2717 return JSValue::encode(jsTypeStringForValue(stackFrame
.callFrame
, stackFrame
.args
[0].jsValue()));
2720 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_undefined
)
2722 STUB_INIT_STACK_FRAME(stackFrame
);
2724 JSValue v
= stackFrame
.args
[0].jsValue();
2725 return JSValue::encode(jsBoolean(v
.isCell() ? v
.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v
.isUndefined()));
2728 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_boolean
)
2730 STUB_INIT_STACK_FRAME(stackFrame
);
2732 return JSValue::encode(jsBoolean(stackFrame
.args
[0].jsValue().isBoolean()));
2735 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_number
)
2737 STUB_INIT_STACK_FRAME(stackFrame
);
2739 return JSValue::encode(jsBoolean(stackFrame
.args
[0].jsValue().isNumber()));
2742 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_string
)
2744 STUB_INIT_STACK_FRAME(stackFrame
);
2746 return JSValue::encode(jsBoolean(isJSString(stackFrame
.globalData
, stackFrame
.args
[0].jsValue())));
2749 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_object
)
2751 STUB_INIT_STACK_FRAME(stackFrame
);
2753 return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame
.args
[0].jsValue())));
2756 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_is_function
)
2758 STUB_INIT_STACK_FRAME(stackFrame
);
2760 return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame
.args
[0].jsValue())));
2763 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_stricteq
)
2765 STUB_INIT_STACK_FRAME(stackFrame
);
2767 JSValue src1
= stackFrame
.args
[0].jsValue();
2768 JSValue src2
= stackFrame
.args
[1].jsValue();
2770 return JSValue::encode(jsBoolean(JSValue::strictEqual(src1
, src2
)));
2773 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_to_primitive
)
2775 STUB_INIT_STACK_FRAME(stackFrame
);
2777 return JSValue::encode(stackFrame
.args
[0].jsValue().toPrimitive(stackFrame
.callFrame
));
2780 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_strcat
)
2782 STUB_INIT_STACK_FRAME(stackFrame
);
2784 return JSValue::encode(concatenateStrings(stackFrame
.callFrame
, &stackFrame
.callFrame
->registers()[stackFrame
.args
[0].int32()], stackFrame
.args
[1].int32()));
2787 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_nstricteq
)
2789 STUB_INIT_STACK_FRAME(stackFrame
);
2791 JSValue src1
= stackFrame
.args
[0].jsValue();
2792 JSValue src2
= stackFrame
.args
[1].jsValue();
2794 return JSValue::encode(jsBoolean(!JSValue::strictEqual(src1
, src2
)));
2797 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_to_jsnumber
)
2799 STUB_INIT_STACK_FRAME(stackFrame
);
2801 JSValue src
= stackFrame
.args
[0].jsValue();
2802 CallFrame
* callFrame
= stackFrame
.callFrame
;
2804 JSValue result
= src
.toJSNumber(callFrame
);
2805 CHECK_FOR_EXCEPTION_AT_END();
2806 return JSValue::encode(result
);
2809 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_in
)
2811 STUB_INIT_STACK_FRAME(stackFrame
);
2813 CallFrame
* callFrame
= stackFrame
.callFrame
;
2814 JSValue baseVal
= stackFrame
.args
[1].jsValue();
2816 if (!baseVal
.isObject()) {
2817 CallFrame
* callFrame
= stackFrame
.callFrame
;
2818 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2819 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, STUB_RETURN_ADDRESS
);
2820 stackFrame
.globalData
->exception
= createInvalidParamError(callFrame
, "in", baseVal
, vPCIndex
, codeBlock
);
2821 VM_THROW_EXCEPTION();
2824 JSValue propName
= stackFrame
.args
[0].jsValue();
2825 JSObject
* baseObj
= asObject(baseVal
);
2828 if (propName
.getUInt32(i
))
2829 return JSValue::encode(jsBoolean(baseObj
->hasProperty(callFrame
, i
)));
2831 Identifier
property(callFrame
, propName
.toString(callFrame
));
2832 CHECK_FOR_EXCEPTION();
2833 return JSValue::encode(jsBoolean(baseObj
->hasProperty(callFrame
, property
)));
2836 DEFINE_STUB_FUNCTION(JSObject
*, op_push_new_scope
)
2838 STUB_INIT_STACK_FRAME(stackFrame
);
2840 JSObject
* scope
= new (stackFrame
.globalData
) JSStaticScopeObject(stackFrame
.callFrame
, stackFrame
.args
[0].identifier(), stackFrame
.args
[1].jsValue(), DontDelete
);
2842 CallFrame
* callFrame
= stackFrame
.callFrame
;
2843 callFrame
->setScopeChain(callFrame
->scopeChain()->push(scope
));
2847 DEFINE_STUB_FUNCTION(void, op_jmp_scopes
)
2849 STUB_INIT_STACK_FRAME(stackFrame
);
2851 unsigned count
= stackFrame
.args
[0].int32();
2852 CallFrame
* callFrame
= stackFrame
.callFrame
;
2854 ScopeChainNode
* tmp
= callFrame
->scopeChain();
2857 callFrame
->setScopeChain(tmp
);
2860 DEFINE_STUB_FUNCTION(void, op_put_by_index
)
2862 STUB_INIT_STACK_FRAME(stackFrame
);
2864 CallFrame
* callFrame
= stackFrame
.callFrame
;
2865 unsigned property
= stackFrame
.args
[1].int32();
2867 stackFrame
.args
[0].jsValue().put(callFrame
, property
, stackFrame
.args
[2].jsValue());
2870 DEFINE_STUB_FUNCTION(void*, op_switch_imm
)
2872 STUB_INIT_STACK_FRAME(stackFrame
);
2874 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
2875 unsigned tableIndex
= stackFrame
.args
[1].int32();
2876 CallFrame
* callFrame
= stackFrame
.callFrame
;
2877 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2879 if (scrutinee
.isInt32())
2880 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiForValue(scrutinee
.asInt32()).executableAddress();
2884 if (scrutinee
.getNumber(value
) && ((intValue
= static_cast<int32_t>(value
)) == value
))
2885 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiForValue(intValue
).executableAddress();
2887 return codeBlock
->immediateSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
2891 DEFINE_STUB_FUNCTION(void*, op_switch_char
)
2893 STUB_INIT_STACK_FRAME(stackFrame
);
2895 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
2896 unsigned tableIndex
= stackFrame
.args
[1].int32();
2897 CallFrame
* callFrame
= stackFrame
.callFrame
;
2898 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2900 void* result
= codeBlock
->characterSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
2902 if (scrutinee
.isString()) {
2903 UString::Rep
* value
= asString(scrutinee
)->value().rep();
2904 if (value
->size() == 1)
2905 result
= codeBlock
->characterSwitchJumpTable(tableIndex
).ctiForValue(value
->data()[0]).executableAddress();
2911 DEFINE_STUB_FUNCTION(void*, op_switch_string
)
2913 STUB_INIT_STACK_FRAME(stackFrame
);
2915 JSValue scrutinee
= stackFrame
.args
[0].jsValue();
2916 unsigned tableIndex
= stackFrame
.args
[1].int32();
2917 CallFrame
* callFrame
= stackFrame
.callFrame
;
2918 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2920 void* result
= codeBlock
->stringSwitchJumpTable(tableIndex
).ctiDefault
.executableAddress();
2922 if (scrutinee
.isString()) {
2923 UString::Rep
* value
= asString(scrutinee
)->value().rep();
2924 result
= codeBlock
->stringSwitchJumpTable(tableIndex
).ctiForValue(value
).executableAddress();
2930 DEFINE_STUB_FUNCTION(EncodedJSValue
, op_del_by_val
)
2932 STUB_INIT_STACK_FRAME(stackFrame
);
2934 CallFrame
* callFrame
= stackFrame
.callFrame
;
2936 JSValue baseValue
= stackFrame
.args
[0].jsValue();
2937 JSObject
* baseObj
= baseValue
.toObject(callFrame
); // may throw
2939 JSValue subscript
= stackFrame
.args
[1].jsValue();
2942 if (subscript
.getUInt32(i
))
2943 result
= jsBoolean(baseObj
->deleteProperty(callFrame
, i
));
2945 CHECK_FOR_EXCEPTION();
2946 Identifier
property(callFrame
, subscript
.toString(callFrame
));
2947 CHECK_FOR_EXCEPTION();
2948 result
= jsBoolean(baseObj
->deleteProperty(callFrame
, property
));
2951 CHECK_FOR_EXCEPTION_AT_END();
2952 return JSValue::encode(result
);
2955 DEFINE_STUB_FUNCTION(void, op_put_getter
)
2957 STUB_INIT_STACK_FRAME(stackFrame
);
2959 CallFrame
* callFrame
= stackFrame
.callFrame
;
2961 ASSERT(stackFrame
.args
[0].jsValue().isObject());
2962 JSObject
* baseObj
= asObject(stackFrame
.args
[0].jsValue());
2963 ASSERT(stackFrame
.args
[2].jsValue().isObject());
2964 baseObj
->defineGetter(callFrame
, stackFrame
.args
[1].identifier(), asObject(stackFrame
.args
[2].jsValue()));
2967 DEFINE_STUB_FUNCTION(void, op_put_setter
)
2969 STUB_INIT_STACK_FRAME(stackFrame
);
2971 CallFrame
* callFrame
= stackFrame
.callFrame
;
2973 ASSERT(stackFrame
.args
[0].jsValue().isObject());
2974 JSObject
* baseObj
= asObject(stackFrame
.args
[0].jsValue());
2975 ASSERT(stackFrame
.args
[2].jsValue().isObject());
2976 baseObj
->defineSetter(callFrame
, stackFrame
.args
[1].identifier(), asObject(stackFrame
.args
[2].jsValue()));
2979 DEFINE_STUB_FUNCTION(JSObject
*, op_new_error
)
2981 STUB_INIT_STACK_FRAME(stackFrame
);
2983 CallFrame
* callFrame
= stackFrame
.callFrame
;
2984 CodeBlock
* codeBlock
= callFrame
->codeBlock();
2985 unsigned type
= stackFrame
.args
[0].int32();
2986 JSValue message
= stackFrame
.args
[1].jsValue();
2987 unsigned bytecodeOffset
= stackFrame
.args
[2].int32();
2989 unsigned lineNumber
= codeBlock
->lineNumberForBytecodeOffset(callFrame
, bytecodeOffset
);
2990 return Error::create(callFrame
, static_cast<ErrorType
>(type
), message
.toString(callFrame
), lineNumber
, codeBlock
->ownerNode()->sourceID(), codeBlock
->ownerNode()->sourceURL());
2993 DEFINE_STUB_FUNCTION(void, op_debug
)
2995 STUB_INIT_STACK_FRAME(stackFrame
);
2997 CallFrame
* callFrame
= stackFrame
.callFrame
;
2999 int debugHookID
= stackFrame
.args
[0].int32();
3000 int firstLine
= stackFrame
.args
[1].int32();
3001 int lastLine
= stackFrame
.args
[2].int32();
3003 stackFrame
.globalData
->interpreter
->debug(callFrame
, static_cast<DebugHookID
>(debugHookID
), firstLine
, lastLine
);
3006 DEFINE_STUB_FUNCTION(EncodedJSValue
, vm_throw
)
3008 STUB_INIT_STACK_FRAME(stackFrame
);
3010 CallFrame
* callFrame
= stackFrame
.callFrame
;
3011 CodeBlock
* codeBlock
= callFrame
->codeBlock();
3012 JSGlobalData
* globalData
= stackFrame
.globalData
;
3014 unsigned vPCIndex
= codeBlock
->getBytecodeIndex(callFrame
, globalData
->exceptionLocation
);
3016 JSValue exceptionValue
= globalData
->exception
;
3017 ASSERT(exceptionValue
);
3018 globalData
->exception
= JSValue();
3020 HandlerInfo
* handler
= globalData
->interpreter
->throwException(callFrame
, exceptionValue
, vPCIndex
, false);
3023 *stackFrame
.exception
= exceptionValue
;
3024 return JSValue::encode(jsNull());
3027 stackFrame
.callFrame
= callFrame
;
3028 void* catchRoutine
= handler
->nativeCode
.executableAddress();
3029 ASSERT(catchRoutine
);
3030 STUB_SET_RETURN_ADDRESS(catchRoutine
);
3031 return JSValue::encode(exceptionValue
);
3036 #endif // ENABLE(JIT)