2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4 * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "Arguments.h"
37 #include "CallFrame.h"
38 #include "CodeBlock.h"
41 #include "ExceptionHelpers.h"
42 #include "GetterSetter.h"
43 #include "GlobalEvalFunction.h"
45 #include "JSActivation.h"
47 #include "JSByteArray.h"
48 #include "JSFunction.h"
49 #include "JSGlobalObjectFunctions.h"
50 #include "JSNotAnObject.h"
51 #include "JSPropertyNameIterator.h"
52 #include "JSStaticScopeObject.h"
54 #include "ObjectPrototype.h"
55 #include "Operations.h"
58 #include "RegExpObject.h"
59 #include "RegExpPrototype.h"
61 #include "SamplingTool.h"
62 #include <wtf/StdLibExtras.h>
70 #if OS(DARWIN) || OS(WINDOWS)
71 #define SYMBOL_STRING(name) "_" #name
73 #define SYMBOL_STRING(name) #name
77 #define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name)
79 #define THUMB_FUNC_PARAM(name)
82 #if (OS(LINUX) || OS(FREEBSD)) && CPU(X86_64)
83 #define SYMBOL_STRING_RELOCATION(name) #name "@plt"
85 #define SYMBOL_STRING_RELOCATION(name) "_" #name
86 #elif CPU(X86) && COMPILER(MINGW)
87 #define SYMBOL_STRING_RELOCATION(name) "@" #name "@4"
89 #define SYMBOL_STRING_RELOCATION(name) #name
94 #define HIDE_SYMBOL(name) ".private_extern _" #name
96 // IBM's own file format
97 #define HIDE_SYMBOL(name) ".lglobl " #name
102 || (OS(HPUX) && CPU(IA64)) \
106 #define HIDE_SYMBOL(name) ".hidden " #name
108 #define HIDE_SYMBOL(name)
111 #if USE(JSVALUE32_64)
113 #if COMPILER(GCC) && CPU(X86)
115 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
116 // need to change the assembly trampolines below to match.
117 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
118 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
119 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
120 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
124 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
125 HIDE_SYMBOL(ctiTrampoline) "\n"
126 SYMBOL_STRING(ctiTrampoline) ":" "\n"
128 "movl %esp, %ebp" "\n"
132 "subl $0x3c, %esp" "\n"
133 "movl $512, %esi" "\n"
134 "movl 0x58(%esp), %edi" "\n"
135 "call *0x50(%esp)" "\n"
136 "addl $0x3c, %esp" "\n"
145 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
146 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
147 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
148 "movl %esp, %ecx" "\n"
149 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
154 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
155 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
156 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
157 "addl $0x3c, %esp" "\n"
165 #elif COMPILER(GCC) && CPU(X86_64)
167 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
168 // need to change the assembly trampolines below to match.
169 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment);
170 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
171 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
172 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline);
175 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
176 HIDE_SYMBOL(ctiTrampoline) "\n"
177 SYMBOL_STRING(ctiTrampoline) ":" "\n"
179 "movq %rsp, %rbp" "\n"
185 "subq $0x48, %rsp" "\n"
186 "movq $512, %r12" "\n"
187 "movq $0xFFFF000000000000, %r14" "\n"
188 "movq $0xFFFF000000000002, %r15" "\n"
189 "movq 0x90(%rsp), %r13" "\n"
190 "call *0x80(%rsp)" "\n"
191 "addq $0x48, %rsp" "\n"
202 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
203 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
204 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
205 "movq %rsp, %rdi" "\n"
206 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
211 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
212 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
213 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
214 "addq $0x48, %rsp" "\n"
224 #elif (COMPILER(GCC) || COMPILER(RVCT)) && CPU(ARM_THUMB2)
226 #define THUNK_RETURN_ADDRESS_OFFSET 0x38
227 #define PRESERVED_RETURN_ADDRESS_OFFSET 0x3C
228 #define PRESERVED_R4_OFFSET 0x40
229 #define PRESERVED_R5_OFFSET 0x44
230 #define PRESERVED_R6_OFFSET 0x48
231 #define REGISTER_FILE_OFFSET 0x4C
232 #define CALLFRAME_OFFSET 0x50
233 #define EXCEPTION_OFFSET 0x54
234 #define ENABLE_PROFILER_REFERENCE_OFFSET 0x58
236 #elif (COMPILER(GCC) || COMPILER(MSVC) || COMPILER(RVCT)) && CPU(ARM_TRADITIONAL)
238 // Also update the MSVC section (defined at DEFINE_STUB_FUNCTION)
239 // when changing one of the following values.
240 #define THUNK_RETURN_ADDRESS_OFFSET 64
241 #define PRESERVEDR4_OFFSET 68
243 #elif COMPILER(MSVC) && CPU(X86)
245 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
246 // need to change the assembly trampolines below to match.
247 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
248 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
249 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
250 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
254 __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
265 mov edi, [esp + 0x58];
276 __declspec(naked) void ctiVMThrowTrampoline()
290 __declspec(naked) void ctiOpThrowNotCaught()
305 #define PRESERVED_GP_OFFSET 60
306 #define PRESERVED_S0_OFFSET 64
307 #define PRESERVED_S1_OFFSET 68
308 #define PRESERVED_S2_OFFSET 72
309 #define PRESERVED_RETURN_ADDRESS_OFFSET 76
310 #define THUNK_RETURN_ADDRESS_OFFSET 80
311 #define REGISTER_FILE_OFFSET 84
312 #define CALLFRAME_OFFSET 88
313 #define EXCEPTION_OFFSET 92
314 #define ENABLE_PROFILER_REFERENCE_OFFSET 96
315 #define GLOBAL_DATA_OFFSET 100
316 #define STACK_LENGTH 104
319 #error "JIT not supported on this platform."
322 #else // USE(JSVALUE32_64)
324 #if COMPILER(GCC) && CPU(X86_64)
326 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
327 // need to change the assembly trampolines below to match.
328 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
329 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline);
330 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
334 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
335 HIDE_SYMBOL(ctiTrampoline) "\n"
336 SYMBOL_STRING(ctiTrampoline) ":" "\n"
338 "movq %rsp, %rbp" "\n"
344 // Form the JIT stubs area
351 "subq $0x48, %rsp" "\n"
352 "movq $512, %r12" "\n"
353 "movq $0xFFFF000000000000, %r14" "\n"
354 "movq $0xFFFF000000000002, %r15" "\n"
355 "movq %rdx, %r13" "\n"
357 "addq $0x78, %rsp" "\n"
368 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
369 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
370 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
371 "movq %rsp, %rdi" "\n"
372 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
377 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
378 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
379 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
380 "addq $0x78, %rsp" "\n"
391 #error "JIT not supported on this platform."
394 #endif // USE(JSVALUE32_64)
400 ".set noreorder" "\n"
403 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
404 ".ent " SYMBOL_STRING(ctiTrampoline) "\n"
405 SYMBOL_STRING(ctiTrampoline) ":" "\n"
406 "addiu $29,$29,-" STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
407 "sw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
408 "sw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
409 "sw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
410 "sw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
412 "sw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n"
414 "move $16,$6 # set callFrameRegister" "\n"
415 "li $17,512 # set timeoutCheckRegister" "\n"
416 "move $25,$4 # move executableAddress to t9" "\n"
417 "sw $5," STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "($29) # store registerFile to current stack" "\n"
418 "sw $6," STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "($29) # store callFrame to curent stack" "\n"
419 "sw $7," STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "($29) # store exception to current stack" "\n"
420 "lw $8," STRINGIZE_VALUE_OF(STACK_LENGTH + 16) "($29) # load enableProfilerReference from previous stack" "\n"
421 "lw $9," STRINGIZE_VALUE_OF(STACK_LENGTH + 20) "($29) # load globalData from previous stack" "\n"
422 "sw $8," STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "($29) # store enableProfilerReference to current stack" "\n"
424 "sw $9," STRINGIZE_VALUE_OF(GLOBAL_DATA_OFFSET) "($29) # store globalData to current stack" "\n"
425 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
426 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
427 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
428 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
430 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
433 ".end " SYMBOL_STRING(ctiTrampoline) "\n"
439 ".set noreorder" "\n"
442 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
443 ".ent " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
444 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
446 "lw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n"
448 "la $25," SYMBOL_STRING(cti_vm_throw) "\n"
450 "bal " SYMBOL_STRING(cti_vm_throw) "\n"
453 "jal " SYMBOL_STRING(cti_vm_throw) "\n"
456 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
457 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
458 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
459 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
461 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
464 ".end " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
470 ".set noreorder" "\n"
473 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
474 ".ent " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
475 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
476 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
477 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
478 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
479 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
481 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
484 ".end " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
488 #if COMPILER(GCC) && CPU(ARM_THUMB2)
493 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
494 HIDE_SYMBOL(ctiTrampoline) "\n"
496 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
497 SYMBOL_STRING(ctiTrampoline) ":" "\n"
498 "sub sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
499 "str lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
500 "str r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
501 "str r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
502 "str r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
503 "str r1, [sp, #" STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "]" "\n"
504 "str r2, [sp, #" STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "]" "\n"
505 "str r3, [sp, #" STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "]" "\n"
509 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
510 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
511 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
512 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
513 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
520 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
521 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
523 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
524 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
526 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
527 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
528 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
529 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
530 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
531 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
538 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
539 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
541 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
542 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
543 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
544 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
545 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
546 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
547 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
551 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
554 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
555 HIDE_SYMBOL(ctiTrampoline) "\n"
556 SYMBOL_STRING(ctiTrampoline) ":" "\n"
557 "stmdb sp!, {r1-r3}" "\n"
558 "stmdb sp!, {r4-r8, lr}" "\n"
559 "sub sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n"
562 // r0 contains the code
565 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n"
566 "ldmia sp!, {r4-r8, lr}" "\n"
567 "add sp, sp, #12" "\n"
572 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
573 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
574 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
576 "bl " SYMBOL_STRING(cti_vm_throw) "\n"
578 // Both has the same return sequence
579 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
580 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
581 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
582 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n"
583 "ldmia sp!, {r4-r8, lr}" "\n"
584 "add sp, sp, #12" "\n"
588 #elif COMPILER(RVCT) && CPU(ARM_THUMB2)
590 __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*)
593 sub sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
594 str lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
595 str r4, [sp, # PRESERVED_R4_OFFSET ]
596 str r5, [sp, # PRESERVED_R5_OFFSET ]
597 str r6, [sp, # PRESERVED_R6_OFFSET ]
598 str r1, [sp, # REGISTER_FILE_OFFSET ]
599 str r2, [sp, # CALLFRAME_OFFSET ]
600 str r3, [sp, # EXCEPTION_OFFSET ]
604 ldr r6, [sp, # PRESERVED_R6_OFFSET ]
605 ldr r5, [sp, # PRESERVED_R5_OFFSET ]
606 ldr r4, [sp, # PRESERVED_R4_OFFSET ]
607 ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
608 add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
612 __asm void ctiVMThrowTrampoline()
617 ldr r6, [sp, # PRESERVED_R6_OFFSET ]
618 ldr r5, [sp, # PRESERVED_R5_OFFSET ]
619 ldr r4, [sp, # PRESERVED_R4_OFFSET ]
620 ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
621 add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
625 __asm void ctiOpThrowNotCaught()
628 ldr r6, [sp, # PRESERVED_R6_OFFSET ]
629 ldr r5, [sp, # PRESERVED_R5_OFFSET ]
630 ldr r4, [sp, # PRESERVED_R4_OFFSET ]
631 ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
632 add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
636 #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
638 __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
642 stmdb sp!, {r4-r8, lr}
643 sub sp, sp, # PRESERVEDR4_OFFSET
648 add sp, sp, # PRESERVEDR4_OFFSET
649 ldmia sp!, {r4-r8, lr}
654 __asm void ctiVMThrowTrampoline()
660 add sp, sp, # PRESERVEDR4_OFFSET
661 ldmia sp!, {r4-r8, lr}
666 __asm void ctiOpThrowNotCaught()
669 add sp, sp, # PRESERVEDR4_OFFSET
670 ldmia sp!, {r4-r8, lr}
676 #if ENABLE(OPCODE_SAMPLING)
677 #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler()
679 #define CTI_SAMPLER 0
682 JITThunks::JITThunks(JSGlobalData* globalData)
684 if (!globalData->executableAllocator.isValid())
687 JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_trampolineStructure);
688 ASSERT(m_executablePool);
690 // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
691 // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
693 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET);
694 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVED_R4_OFFSET);
695 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == PRESERVED_R5_OFFSET);
696 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == PRESERVED_R6_OFFSET);
698 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET);
699 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET);
700 // The fifth argument is the first item already on the stack.
701 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET);
703 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
705 #elif CPU(ARM_TRADITIONAL)
707 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
708 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVEDR4_OFFSET);
712 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedGP) == PRESERVED_GP_OFFSET);
713 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS0) == PRESERVED_S0_OFFSET);
714 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS1) == PRESERVED_S1_OFFSET);
715 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS2) == PRESERVED_S2_OFFSET);
716 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET);
717 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
718 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET);
719 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET);
720 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == EXCEPTION_OFFSET);
721 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET);
722 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, globalData) == GLOBAL_DATA_OFFSET);
727 JITThunks::~JITThunks()
731 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
733 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct)
735 // The interpreter checks for recursion here; I do not believe this can occur in CTI.
737 if (!baseValue.isCell())
740 // Uncacheable: give up.
741 if (!slot.isCacheable()) {
742 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
746 JSCell* baseCell = baseValue.asCell();
747 Structure* structure = baseCell->structure();
749 if (structure->isUncacheableDictionary()) {
750 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
754 // If baseCell != base, then baseCell must be a proxy for another object.
755 if (baseCell != slot.base()) {
756 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
760 // Cache hit: Specialize instruction and ref Structures.
762 // Structure transition, cache transition info
763 if (slot.type() == PutPropertySlot::NewProperty) {
764 if (structure->isDictionary()) {
765 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
769 // put_by_id_transition checks the prototype chain for setters.
770 normalizePrototypeChain(callFrame, baseCell);
772 StructureChain* prototypeChain = structure->prototypeChain(callFrame);
773 stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
774 JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct);
778 stubInfo->initPutByIdReplace(structure);
780 JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct);
783 NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
785 // FIXME: Write a test that proves we need to check for recursion here just
786 // like the interpreter does, then add a check for recursion.
788 // FIXME: Cache property access for immediates.
789 if (!baseValue.isCell()) {
790 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
794 JSGlobalData* globalData = &callFrame->globalData();
796 if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
797 JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
801 if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
802 // The tradeoff of compiling an patched inline string length access routine does not seem
803 // to pay off, so we currently only do this for arrays.
804 ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs->ctiStringLengthTrampoline());
808 // Uncacheable: give up.
809 if (!slot.isCacheable()) {
810 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
814 JSCell* baseCell = baseValue.asCell();
815 Structure* structure = baseCell->structure();
817 if (structure->isUncacheableDictionary()) {
818 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
822 // Cache hit: Specialize instruction and ref Structures.
824 if (slot.slotBase() == baseValue) {
825 // set this up, so derefStructures can do it's job.
826 stubInfo->initGetByIdSelf(structure);
827 if (slot.cachedPropertyType() != PropertySlot::Value)
828 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
830 JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
834 if (structure->isDictionary()) {
835 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
839 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
840 ASSERT(slot.slotBase().isObject());
842 JSObject* slotBaseObject = asObject(slot.slotBase());
843 size_t offset = slot.cachedOffset();
845 // Since we're accessing a prototype in a loop, it's a good bet that it
846 // should not be treated as a dictionary.
847 if (slotBaseObject->structure()->isDictionary()) {
848 slotBaseObject->flattenDictionaryObject(callFrame->globalData());
849 offset = slotBaseObject->structure()->get(propertyName);
852 stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
854 ASSERT(!structure->isDictionary());
855 ASSERT(!slotBaseObject->structure()->isDictionary());
856 JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), propertyName, slot, offset, returnAddress);
860 size_t offset = slot.cachedOffset();
861 size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
863 stubInfo->accessType = access_get_by_id_generic;
867 StructureChain* prototypeChain = structure->prototypeChain(callFrame);
868 stubInfo->initGetByIdChain(structure, prototypeChain);
869 JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
872 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
878 static void jscGeneratedNativeCode()
880 // When executing a JIT stub function (which might do an allocation), we hack the return address
881 // to pretend to be executing this function, to keep stack logging tools from blowing out
888 ALWAYS_INLINE StackHack(JITStackFrame& stackFrame)
889 : stackFrame(stackFrame)
890 , savedReturnAddress(*stackFrame.returnAddressSlot())
892 *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
895 ALWAYS_INLINE ~StackHack()
897 *stackFrame.returnAddressSlot() = savedReturnAddress;
900 JITStackFrame& stackFrame;
901 ReturnAddressPtr savedReturnAddress;
904 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
905 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
906 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
910 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS)
911 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
912 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
916 // The reason this is not inlined is to avoid having to do a PIC branch
917 // to get the address of the ctiVMThrowTrampoline function. It's also
918 // good to keep the code size down by leaving as much of the exception
919 // handling code out of line as possible.
920 static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
922 ASSERT(globalData->exception);
923 globalData->exceptionLocation = exceptionLocation;
924 returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline));
927 static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
929 globalData->exception = createStackOverflowError(callFrame);
930 returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot);
933 #define VM_THROW_EXCEPTION() \
935 VM_THROW_EXCEPTION_AT_END(); \
938 #define VM_THROW_EXCEPTION_AT_END() \
940 returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\
943 #define CHECK_FOR_EXCEPTION() \
945 if (UNLIKELY(stackFrame.globalData->exception.get())) \
946 VM_THROW_EXCEPTION(); \
948 #define CHECK_FOR_EXCEPTION_AT_END() \
950 if (UNLIKELY(stackFrame.globalData->exception.get())) \
951 VM_THROW_EXCEPTION_AT_END(); \
953 #define CHECK_FOR_EXCEPTION_VOID() \
955 if (UNLIKELY(stackFrame.globalData->exception.get())) { \
956 VM_THROW_EXCEPTION_AT_END(); \
961 struct ExceptionHandler {
963 CallFrame* callFrame;
965 static ExceptionHandler jitThrow(JSGlobalData* globalData, CallFrame* callFrame, JSValue exceptionValue, ReturnAddressPtr faultLocation)
967 ASSERT(exceptionValue);
969 unsigned vPCIndex = callFrame->codeBlock()->bytecodeOffset(faultLocation);
970 globalData->exception = JSValue();
971 HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex); // This may update callFrame & exceptionValue!
972 globalData->exception = exceptionValue;
974 void* catchRoutine = handler ? handler->nativeCode.executableAddress() : FunctionPtr(ctiOpThrowNotCaught).value();
975 ASSERT(catchRoutine);
976 ExceptionHandler exceptionHandler = { catchRoutine, callFrame };
977 return exceptionHandler;
982 #define DEFINE_STUB_FUNCTION(rtype, op) \
984 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
989 ".globl " SYMBOL_STRING(cti_##op) "\n" \
990 HIDE_SYMBOL(cti_##op) "\n" \
992 ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \
993 SYMBOL_STRING(cti_##op) ":" "\n" \
994 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
995 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
996 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
999 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
1003 #define DEFINE_STUB_FUNCTION(rtype, op) \
1005 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1010 ".set noreorder" "\n" \
1011 ".set nomacro" "\n" \
1012 ".set nomips16" "\n" \
1013 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1014 ".ent " SYMBOL_STRING(cti_##op) "\n" \
1015 SYMBOL_STRING(cti_##op) ":" "\n" \
1016 "lw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n" \
1017 "sw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1019 "la $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \
1020 ".set nomacro" "\n" \
1021 "bal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1023 "lw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1026 ".set reorder" "\n" \
1028 ".end " SYMBOL_STRING(cti_##op) "\n" \
1030 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1032 #else // WTF_MIPS_PIC
1033 #define DEFINE_STUB_FUNCTION(rtype, op) \
1035 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1040 ".set noreorder" "\n" \
1041 ".set nomacro" "\n" \
1042 ".set nomips16" "\n" \
1043 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1044 ".ent " SYMBOL_STRING(cti_##op) "\n" \
1045 SYMBOL_STRING(cti_##op) ":" "\n" \
1046 "sw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1047 "jal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1049 "lw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
1052 ".set reorder" "\n" \
1054 ".end " SYMBOL_STRING(cti_##op) "\n" \
1056 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1060 #elif CPU(ARM_TRADITIONAL) && COMPILER(GCC)
1062 #define DEFINE_STUB_FUNCTION(rtype, op) \
1064 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1067 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1068 SYMBOL_STRING(cti_##op) ":" "\n" \
1069 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1070 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1071 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1074 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1076 #elif CPU(ARM_TRADITIONAL) && COMPILER(RVCT)
1078 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1080 /* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */
1082 /* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */
1083 /* The pattern "#xxx#" will be replaced with "xxx" */
1086 RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
1087 RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
1090 RVCT( IMPORT JITStubThunked_#op#)
1091 RVCT( str lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
1092 RVCT( bl JITStubThunked_#op#)
1093 RVCT( ldr lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
1099 /* Include the generated file */
1100 #include "GeneratedJITStubs_RVCT.h"
1102 #elif CPU(ARM_TRADITIONAL) && COMPILER(MSVC)
1104 #define DEFINE_STUB_FUNCTION(rtype, op) extern "C" rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1106 /* The following is a workaround for MSVC toolchain; inline assembler is not supported */
1108 /* The following section is a template to generate code for GeneratedJITStubs_MSVC.asm */
1109 /* The pattern "#xxx#" will be replaced with "xxx" */
1112 MSVC_BEGIN( AREA Trampoline, CODE)
1114 MSVC_BEGIN( EXPORT ctiTrampoline)
1115 MSVC_BEGIN( EXPORT ctiVMThrowTrampoline)
1116 MSVC_BEGIN( EXPORT ctiOpThrowNotCaught)
1118 MSVC_BEGIN(ctiTrampoline PROC)
1119 MSVC_BEGIN( stmdb sp!, {r1-r3})
1120 MSVC_BEGIN( stmdb sp!, {r4-r8, lr})
1121 MSVC_BEGIN( sub sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1122 MSVC_BEGIN( mov r4, r2)
1123 MSVC_BEGIN( mov r5, #512)
1124 MSVC_BEGIN( ; r0 contains the code)
1125 MSVC_BEGIN( mov lr, pc)
1127 MSVC_BEGIN( add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1128 MSVC_BEGIN( ldmia sp!, {r4-r8, lr})
1129 MSVC_BEGIN( add sp, sp, #12)
1131 MSVC_BEGIN(ctiTrampoline ENDP)
1133 MSVC_BEGIN(ctiVMThrowTrampoline PROC)
1134 MSVC_BEGIN( mov r0, sp)
1135 MSVC_BEGIN( mov lr, pc)
1136 MSVC_BEGIN( bl cti_vm_throw)
1137 MSVC_BEGIN(ctiOpThrowNotCaught)
1138 MSVC_BEGIN( add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1139 MSVC_BEGIN( ldmia sp!, {r4-r8, lr})
1140 MSVC_BEGIN( add sp, sp, #12)
1142 MSVC_BEGIN(ctiVMThrowTrampoline ENDP)
1145 MSVC( EXPORT cti_#op#)
1146 MSVC( IMPORT JITStubThunked_#op#)
1148 MSVC( str lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET)
1149 MSVC( bl JITStubThunked_#op#)
1150 MSVC( ldr lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET)
1159 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
1162 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_this)
1164 STUB_INIT_STACK_FRAME(stackFrame);
1165 CallFrame* callFrame = stackFrame.callFrame;
1167 JSFunction* constructor = asFunction(callFrame->callee());
1168 #if !ASSERT_DISABLED
1169 ConstructData constructData;
1170 ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
1173 Structure* structure;
1174 JSValue proto = stackFrame.args[0].jsValue();
1175 if (proto.isObject())
1176 structure = asObject(proto)->inheritorID();
1178 structure = constructor->scope().node()->globalObject->emptyObjectStructure();
1179 JSValue result = new (&callFrame->globalData()) JSObject(structure);
1181 return JSValue::encode(result);
1184 DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this)
1186 STUB_INIT_STACK_FRAME(stackFrame);
1188 JSValue v1 = stackFrame.args[0].jsValue();
1189 CallFrame* callFrame = stackFrame.callFrame;
1191 JSObject* result = v1.toThisObject(callFrame);
1192 CHECK_FOR_EXCEPTION_AT_END();
1193 return JSValue::encode(result);
1196 DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this_strict)
1198 STUB_INIT_STACK_FRAME(stackFrame);
1200 JSValue v1 = stackFrame.args[0].jsValue();
1201 CallFrame* callFrame = stackFrame.callFrame;
1202 ASSERT(v1.asCell()->structure()->typeInfo().needsThisConversion());
1203 JSValue result = v1.toStrictThisObject(callFrame);
1204 CHECK_FOR_EXCEPTION_AT_END();
1205 return JSValue::encode(result);
1208 DEFINE_STUB_FUNCTION(void, op_end)
1210 STUB_INIT_STACK_FRAME(stackFrame);
1212 ScopeChainNode* scopeChain = stackFrame.callFrame->scopeChain();
1213 ASSERT(scopeChain->refCount > 1);
1214 scopeChain->deref();
1217 DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
1219 STUB_INIT_STACK_FRAME(stackFrame);
1221 JSValue v1 = stackFrame.args[0].jsValue();
1222 JSValue v2 = stackFrame.args[1].jsValue();
1223 CallFrame* callFrame = stackFrame.callFrame;
1225 if (v1.isString()) {
1226 JSValue result = v2.isString()
1227 ? jsString(callFrame, asString(v1), asString(v2))
1228 : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
1229 CHECK_FOR_EXCEPTION_AT_END();
1230 return JSValue::encode(result);
1233 double left = 0.0, right;
1234 if (v1.getNumber(left) && v2.getNumber(right))
1235 return JSValue::encode(jsNumber(left + right));
1237 // All other cases are pretty uncommon
1238 JSValue result = jsAddSlowCase(callFrame, v1, v2);
1239 CHECK_FOR_EXCEPTION_AT_END();
1240 return JSValue::encode(result);
1243 DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_inc)
1245 STUB_INIT_STACK_FRAME(stackFrame);
1247 JSValue v = stackFrame.args[0].jsValue();
1249 CallFrame* callFrame = stackFrame.callFrame;
1250 JSValue result = jsNumber(v.toNumber(callFrame) + 1);
1251 CHECK_FOR_EXCEPTION_AT_END();
1252 return JSValue::encode(result);
1255 DEFINE_STUB_FUNCTION(int, timeout_check)
1257 STUB_INIT_STACK_FRAME(stackFrame);
1259 JSGlobalData* globalData = stackFrame.globalData;
1260 TimeoutChecker& timeoutChecker = globalData->timeoutChecker;
1262 if (globalData->terminator.shouldTerminate()) {
1263 globalData->exception = createTerminatedExecutionException(globalData);
1264 VM_THROW_EXCEPTION_AT_END();
1265 } else if (timeoutChecker.didTimeOut(stackFrame.callFrame)) {
1266 globalData->exception = createInterruptedExecutionException(globalData);
1267 VM_THROW_EXCEPTION_AT_END();
1270 return timeoutChecker.ticksUntilNextCheck();
1273 DEFINE_STUB_FUNCTION(void*, register_file_check)
1275 STUB_INIT_STACK_FRAME(stackFrame);
1276 CallFrame* callFrame = stackFrame.callFrame;
1278 if (UNLIKELY(!stackFrame.registerFile->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters]))) {
1279 // Rewind to the previous call frame because op_call already optimistically
1280 // moved the call frame forward.
1281 CallFrame* oldCallFrame = callFrame->callerFrame();
1282 ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), ReturnAddressPtr(callFrame->returnPC()));
1283 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1284 callFrame = handler.callFrame;
1290 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
1292 STUB_INIT_STACK_FRAME(stackFrame);
1294 JSValue src1 = stackFrame.args[0].jsValue();
1295 JSValue src2 = stackFrame.args[1].jsValue();
1296 CallFrame* callFrame = stackFrame.callFrame;
1298 bool result = jsLessEq(callFrame, src1, src2);
1299 CHECK_FOR_EXCEPTION_AT_END();
1303 DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
1305 STUB_INIT_STACK_FRAME(stackFrame);
1307 return constructEmptyObject(stackFrame.callFrame);
1310 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
1312 STUB_INIT_STACK_FRAME(stackFrame);
1314 PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
1315 stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
1316 CHECK_FOR_EXCEPTION_AT_END();
1319 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
1321 STUB_INIT_STACK_FRAME(stackFrame);
1323 PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
1324 stackFrame.args[0].jsValue().putDirect(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
1325 CHECK_FOR_EXCEPTION_AT_END();
1328 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
1330 STUB_INIT_STACK_FRAME(stackFrame);
1332 CallFrame* callFrame = stackFrame.callFrame;
1333 Identifier& ident = stackFrame.args[1].identifier();
1335 JSValue baseValue = stackFrame.args[0].jsValue();
1336 PropertySlot slot(baseValue);
1337 JSValue result = baseValue.get(callFrame, ident, slot);
1339 CHECK_FOR_EXCEPTION_AT_END();
1340 return JSValue::encode(result);
1343 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1345 DEFINE_STUB_FUNCTION(void, op_put_by_id)
1347 STUB_INIT_STACK_FRAME(stackFrame);
1348 CallFrame* callFrame = stackFrame.callFrame;
1349 Identifier& ident = stackFrame.args[1].identifier();
1351 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1352 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
1354 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1355 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1356 if (!stubInfo->seenOnce())
1357 stubInfo->setSeen();
1359 JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false);
1361 CHECK_FOR_EXCEPTION_AT_END();
1364 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
1366 STUB_INIT_STACK_FRAME(stackFrame);
1367 CallFrame* callFrame = stackFrame.callFrame;
1368 Identifier& ident = stackFrame.args[1].identifier();
1370 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1371 stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
1373 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1374 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1375 if (!stubInfo->seenOnce())
1376 stubInfo->setSeen();
1378 JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true);
1380 CHECK_FOR_EXCEPTION_AT_END();
1383 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
1385 STUB_INIT_STACK_FRAME(stackFrame);
1387 CallFrame* callFrame = stackFrame.callFrame;
1388 Identifier& ident = stackFrame.args[1].identifier();
1390 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1391 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
1393 CHECK_FOR_EXCEPTION_AT_END();
1396 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
1398 STUB_INIT_STACK_FRAME(stackFrame);
1400 CallFrame* callFrame = stackFrame.callFrame;
1401 Identifier& ident = stackFrame.args[1].identifier();
1403 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1404 stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
1406 CHECK_FOR_EXCEPTION_AT_END();
1409 DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
1411 STUB_INIT_STACK_FRAME(stackFrame);
1413 JSValue baseValue = stackFrame.args[0].jsValue();
1414 int32_t oldSize = stackFrame.args[3].int32();
1415 int32_t newSize = stackFrame.args[4].int32();
1417 ASSERT(baseValue.isObject());
1418 JSObject* base = asObject(baseValue);
1419 base->allocatePropertyStorage(oldSize, newSize);
1424 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
1426 STUB_INIT_STACK_FRAME(stackFrame);
1428 CallFrame* callFrame = stackFrame.callFrame;
1429 Identifier& ident = stackFrame.args[1].identifier();
1431 JSValue baseValue = stackFrame.args[0].jsValue();
1432 PropertySlot slot(baseValue);
1433 JSValue result = baseValue.get(callFrame, ident, slot);
1434 CHECK_FOR_EXCEPTION();
1436 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1437 MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
1439 if (!methodCallLinkInfo.seenOnce()) {
1440 methodCallLinkInfo.setSeen();
1441 return JSValue::encode(result);
1444 // If we successfully got something, then the base from which it is being accessed must
1445 // be an object. (Assertion to ensure asObject() call below is safe, which comes after
1446 // an isCacheable() chceck.
1447 ASSERT(!slot.isCacheableValue() || slot.slotBase().isObject());
1450 // * We're dealing with a JSCell,
1451 // * the property is cachable,
1452 // * it's not a dictionary
1453 // * there is a function cached.
1454 Structure* structure;
1456 JSObject* slotBaseObject;
1457 if (baseValue.isCell()
1458 && slot.isCacheableValue()
1459 && !(structure = baseValue.asCell()->structure())->isUncacheableDictionary()
1460 && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
1464 JSFunction* callee = (JSFunction*)specific;
1466 // Since we're accessing a prototype in a loop, it's a good bet that it
1467 // should not be treated as a dictionary.
1468 if (slotBaseObject->structure()->isDictionary())
1469 slotBaseObject->flattenDictionaryObject(callFrame->globalData());
1471 // The result fetched should always be the callee!
1472 ASSERT(result == JSValue(callee));
1474 // Check to see if the function is on the object's prototype. Patch up the code to optimize.
1475 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
1476 JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
1477 return JSValue::encode(result);
1480 // Check to see if the function is on the object itself.
1481 // Since we generate the method-check to check both the structure and a prototype-structure (since this
1482 // is the common case) we have a problem - we need to patch the prototype structure check to do something
1483 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler
1484 // for now. For now it performs a check on a special object on the global object only used for this
1485 // purpose. The object is in no way exposed, and as such the check will always pass.
1486 if (slot.slotBase() == baseValue) {
1487 JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
1488 return JSValue::encode(result);
1492 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
1493 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
1494 return JSValue::encode(result);
1497 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
1499 STUB_INIT_STACK_FRAME(stackFrame);
1500 CallFrame* callFrame = stackFrame.callFrame;
1501 Identifier& ident = stackFrame.args[1].identifier();
1503 JSValue baseValue = stackFrame.args[0].jsValue();
1504 PropertySlot slot(baseValue);
1505 JSValue result = baseValue.get(callFrame, ident, slot);
1507 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1508 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1509 if (!stubInfo->seenOnce())
1510 stubInfo->setSeen();
1512 JITThunks::tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo);
1514 CHECK_FOR_EXCEPTION_AT_END();
1515 return JSValue::encode(result);
1518 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
1520 STUB_INIT_STACK_FRAME(stackFrame);
1522 CallFrame* callFrame = stackFrame.callFrame;
1523 Identifier& ident = stackFrame.args[1].identifier();
1525 JSValue baseValue = stackFrame.args[0].jsValue();
1526 PropertySlot slot(baseValue);
1527 JSValue result = baseValue.get(callFrame, ident, slot);
1529 CHECK_FOR_EXCEPTION();
1531 if (baseValue.isCell()
1532 && slot.isCacheable()
1533 && !baseValue.asCell()->structure()->isUncacheableDictionary()
1534 && slot.slotBase() == baseValue) {
1536 CodeBlock* codeBlock = callFrame->codeBlock();
1537 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1539 ASSERT(slot.slotBase().isObject());
1541 PolymorphicAccessStructureList* polymorphicStructureList;
1544 if (stubInfo->accessType == access_get_by_id_self) {
1545 ASSERT(!stubInfo->stubRoutine);
1546 polymorphicStructureList = new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure);
1547 stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
1549 polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
1550 listIndex = stubInfo->u.getByIdSelfList.listSize;
1552 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
1553 stubInfo->u.getByIdSelfList.listSize++;
1554 JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, baseValue.asCell()->structure(), ident, slot, slot.cachedOffset());
1556 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1557 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
1560 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
1561 return JSValue::encode(result);
1564 static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex)
1566 PolymorphicAccessStructureList* prototypeStructureList = 0;
1569 switch (stubInfo->accessType) {
1570 case access_get_by_id_proto:
1571 prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
1572 stubInfo->stubRoutine = CodeLocationLabel();
1573 stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
1575 case access_get_by_id_chain:
1576 prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
1577 stubInfo->stubRoutine = CodeLocationLabel();
1578 stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
1580 case access_get_by_id_proto_list:
1581 prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
1582 listIndex = stubInfo->u.getByIdProtoList.listSize;
1583 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE)
1584 stubInfo->u.getByIdProtoList.listSize++;
1587 ASSERT_NOT_REACHED();
1590 ASSERT(listIndex <= POLYMORPHIC_LIST_CACHE_SIZE);
1591 return prototypeStructureList;
1594 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_getter_stub)
1596 STUB_INIT_STACK_FRAME(stackFrame);
1597 CallFrame* callFrame = stackFrame.callFrame;
1598 GetterSetter* getterSetter = asGetterSetter(stackFrame.args[0].jsObject());
1599 if (!getterSetter->getter())
1600 return JSValue::encode(jsUndefined());
1601 JSObject* getter = asObject(getterSetter->getter());
1603 CallType callType = getter->getCallData(callData);
1604 JSValue result = call(callFrame, getter, callType, callData, stackFrame.args[1].jsObject(), ArgList());
1605 if (callFrame->hadException())
1606 returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS);
1608 return JSValue::encode(result);
1611 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_custom_stub)
1613 STUB_INIT_STACK_FRAME(stackFrame);
1614 CallFrame* callFrame = stackFrame.callFrame;
1615 JSObject* slotBase = stackFrame.args[0].jsObject();
1616 PropertySlot::GetValueFunc getter = reinterpret_cast<PropertySlot::GetValueFunc>(stackFrame.args[1].asPointer);
1617 const Identifier& ident = stackFrame.args[2].identifier();
1618 JSValue result = getter(callFrame, slotBase, ident);
1619 if (callFrame->hadException())
1620 returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[3].returnAddress(), STUB_RETURN_ADDRESS);
1622 return JSValue::encode(result);
1625 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
1627 STUB_INIT_STACK_FRAME(stackFrame);
1629 CallFrame* callFrame = stackFrame.callFrame;
1630 const Identifier& propertyName = stackFrame.args[1].identifier();
1632 JSValue baseValue = stackFrame.args[0].jsValue();
1633 PropertySlot slot(baseValue);
1634 JSValue result = baseValue.get(callFrame, propertyName, slot);
1636 CHECK_FOR_EXCEPTION();
1638 if (!baseValue.isCell() || !slot.isCacheable() || baseValue.asCell()->structure()->isDictionary()) {
1639 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1640 return JSValue::encode(result);
1643 Structure* structure = baseValue.asCell()->structure();
1644 CodeBlock* codeBlock = callFrame->codeBlock();
1645 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1647 ASSERT(slot.slotBase().isObject());
1648 JSObject* slotBaseObject = asObject(slot.slotBase());
1650 size_t offset = slot.cachedOffset();
1652 if (slot.slotBase() == baseValue)
1653 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1654 else if (slot.slotBase() == baseValue.asCell()->structure()->prototypeForLookup(callFrame)) {
1655 ASSERT(!baseValue.asCell()->structure()->isDictionary());
1656 // Since we're accessing a prototype in a loop, it's a good bet that it
1657 // should not be treated as a dictionary.
1658 if (slotBaseObject->structure()->isDictionary()) {
1659 slotBaseObject->flattenDictionaryObject(callFrame->globalData());
1660 offset = slotBaseObject->structure()->get(propertyName);
1664 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
1665 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
1666 JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset);
1668 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1669 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
1671 } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
1672 ASSERT(!baseValue.asCell()->structure()->isDictionary());
1674 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
1676 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
1677 StructureChain* protoChain = structure->prototypeChain(callFrame);
1678 JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, propertyName, slot, offset);
1680 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1681 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
1684 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1686 return JSValue::encode(result);
1689 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full)
1691 STUB_INIT_STACK_FRAME(stackFrame);
1693 JSValue baseValue = stackFrame.args[0].jsValue();
1694 PropertySlot slot(baseValue);
1695 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1697 CHECK_FOR_EXCEPTION_AT_END();
1698 return JSValue::encode(result);
1701 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_fail)
1703 STUB_INIT_STACK_FRAME(stackFrame);
1705 JSValue baseValue = stackFrame.args[0].jsValue();
1706 PropertySlot slot(baseValue);
1707 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1709 CHECK_FOR_EXCEPTION_AT_END();
1710 return JSValue::encode(result);
1713 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_array_fail)
1715 STUB_INIT_STACK_FRAME(stackFrame);
1717 JSValue baseValue = stackFrame.args[0].jsValue();
1718 PropertySlot slot(baseValue);
1719 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1721 CHECK_FOR_EXCEPTION_AT_END();
1722 return JSValue::encode(result);
1725 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
1727 STUB_INIT_STACK_FRAME(stackFrame);
1729 JSValue baseValue = stackFrame.args[0].jsValue();
1730 PropertySlot slot(baseValue);
1731 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1733 CHECK_FOR_EXCEPTION_AT_END();
1734 return JSValue::encode(result);
1737 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1739 DEFINE_STUB_FUNCTION(void, op_check_has_instance)
1741 STUB_INIT_STACK_FRAME(stackFrame);
1743 CallFrame* callFrame = stackFrame.callFrame;
1744 JSValue baseVal = stackFrame.args[0].jsValue();
1746 // ECMA-262 15.3.5.3:
1747 // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
1749 TypeInfo typeInfo(UnspecifiedType);
1750 ASSERT(!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance());
1752 stackFrame.globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal);
1753 VM_THROW_EXCEPTION_AT_END();
1756 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
1758 STUB_INIT_STACK_FRAME(stackFrame);
1760 CallFrame* callFrame = stackFrame.callFrame;
1761 JSValue value = stackFrame.args[0].jsValue();
1762 JSValue baseVal = stackFrame.args[1].jsValue();
1763 JSValue proto = stackFrame.args[2].jsValue();
1765 // At least one of these checks must have failed to get to the slow case.
1766 ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
1767 || !value.isObject() || !baseVal.isObject() || !proto.isObject()
1768 || (asObject(baseVal)->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance);
1771 // ECMA-262 15.3.5.3:
1772 // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
1773 TypeInfo typeInfo(UnspecifiedType);
1774 if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) {
1775 stackFrame.globalData->exception = createInvalidParamError(stackFrame.callFrame, "instanceof", baseVal);
1776 VM_THROW_EXCEPTION();
1778 ASSERT(typeInfo.type() != UnspecifiedType);
1780 if (!typeInfo.overridesHasInstance()) {
1781 if (!value.isObject())
1782 return JSValue::encode(jsBoolean(false));
1784 if (!proto.isObject()) {
1785 throwError(callFrame, createTypeError(callFrame, "instanceof called on an object with an invalid prototype property."));
1786 VM_THROW_EXCEPTION();
1790 JSValue result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
1791 CHECK_FOR_EXCEPTION_AT_END();
1793 return JSValue::encode(result);
1796 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
1798 STUB_INIT_STACK_FRAME(stackFrame);
1800 CallFrame* callFrame = stackFrame.callFrame;
1802 JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
1804 bool couldDelete = baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier());
1805 JSValue result = jsBoolean(couldDelete);
1806 if (!couldDelete && callFrame->codeBlock()->isStrictMode())
1807 stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
1809 CHECK_FOR_EXCEPTION_AT_END();
1810 return JSValue::encode(result);
1813 DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul)
1815 STUB_INIT_STACK_FRAME(stackFrame);
1817 JSValue src1 = stackFrame.args[0].jsValue();
1818 JSValue src2 = stackFrame.args[1].jsValue();
1822 if (src1.getNumber(left) && src2.getNumber(right))
1823 return JSValue::encode(jsNumber(left * right));
1825 CallFrame* callFrame = stackFrame.callFrame;
1826 JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
1827 CHECK_FOR_EXCEPTION_AT_END();
1828 return JSValue::encode(result);
1831 DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
1833 STUB_INIT_STACK_FRAME(stackFrame);
1835 ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
1836 return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
1839 DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
1841 STUB_INIT_STACK_FRAME(stackFrame);
1843 #if !ASSERT_DISABLED
1845 ASSERT(stackFrame.callFrame->callee()->getCallData(callData) == CallTypeJS);
1848 JSFunction* function = asFunction(stackFrame.callFrame->callee());
1849 ASSERT(!function->isHostFunction());
1850 FunctionExecutable* executable = function->jsExecutable();
1851 ScopeChainNode* callDataScopeChain = function->scope().node();
1852 JSObject* error = executable->compileForCall(stackFrame.callFrame, callDataScopeChain);
1854 stackFrame.callFrame->globalData().exception = error;
1860 DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
1862 STUB_INIT_STACK_FRAME(stackFrame);
1864 #if !ASSERT_DISABLED
1865 ConstructData constructData;
1866 ASSERT(asFunction(stackFrame.callFrame->callee())->getConstructData(constructData) == ConstructTypeJS);
1869 JSFunction* function = asFunction(stackFrame.callFrame->callee());
1870 ASSERT(!function->isHostFunction());
1871 FunctionExecutable* executable = function->jsExecutable();
1872 ScopeChainNode* callDataScopeChain = function->scope().node();
1873 JSObject* error = executable->compileForConstruct(stackFrame.callFrame, callDataScopeChain);
1875 stackFrame.callFrame->globalData().exception = error;
1881 DEFINE_STUB_FUNCTION(void*, op_call_arityCheck)
1883 STUB_INIT_STACK_FRAME(stackFrame);
1885 CallFrame* callFrame = stackFrame.callFrame;
1886 JSFunction* callee = asFunction(callFrame->callee());
1887 ASSERT(!callee->isHostFunction());
1888 CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeForCall();
1889 int argCount = callFrame->argumentCountIncludingThis();
1890 ReturnAddressPtr pc = callFrame->returnPC();
1892 ASSERT(argCount != newCodeBlock->m_numParameters);
1894 CallFrame* oldCallFrame = callFrame->callerFrame();
1897 if (argCount > newCodeBlock->m_numParameters) {
1898 size_t numParameters = newCodeBlock->m_numParameters;
1899 r = callFrame->registers() + numParameters;
1900 Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
1901 if (!stackFrame.registerFile->grow(newEnd)) {
1902 // Rewind to the previous call frame because op_call already optimistically
1903 // moved the call frame forward.
1904 ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc);
1905 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1906 return handler.callFrame;
1909 Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
1910 for (size_t i = 0; i < numParameters; ++i)
1911 argv[i + argCount] = argv[i];
1913 size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
1914 r = callFrame->registers() + omittedArgCount;
1915 Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
1916 if (!stackFrame.registerFile->grow(newEnd)) {
1917 // Rewind to the previous call frame because op_call already optimistically
1918 // moved the call frame forward.
1919 ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc);
1920 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1921 return handler.callFrame;
1924 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
1925 for (size_t i = 0; i < omittedArgCount; ++i)
1926 argv[i] = jsUndefined();
1929 callFrame = CallFrame::create(r);
1930 callFrame->setCallerFrame(oldCallFrame);
1931 callFrame->setArgumentCountIncludingThis(argCount);
1932 callFrame->setCallee(callee);
1933 callFrame->setScopeChain(callee->scope().node());
1934 callFrame->setReturnPC(pc.value());
1936 ASSERT((void*)callFrame <= stackFrame.registerFile->end());
1940 DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck)
1942 STUB_INIT_STACK_FRAME(stackFrame);
1944 CallFrame* callFrame = stackFrame.callFrame;
1945 JSFunction* callee = asFunction(callFrame->callee());
1946 ASSERT(!callee->isHostFunction());
1947 CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeForConstruct();
1948 int argCount = callFrame->argumentCountIncludingThis();
1949 ReturnAddressPtr pc = callFrame->returnPC();
1951 ASSERT(argCount != newCodeBlock->m_numParameters);
1953 CallFrame* oldCallFrame = callFrame->callerFrame();
1956 if (argCount > newCodeBlock->m_numParameters) {
1957 size_t numParameters = newCodeBlock->m_numParameters;
1958 r = callFrame->registers() + numParameters;
1959 Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
1960 if (!stackFrame.registerFile->grow(newEnd)) {
1961 // Rewind to the previous call frame because op_call already optimistically
1962 // moved the call frame forward.
1963 ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc);
1964 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1965 return handler.callFrame;
1968 Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
1969 for (size_t i = 0; i < numParameters; ++i)
1970 argv[i + argCount] = argv[i];
1972 size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
1973 r = callFrame->registers() + omittedArgCount;
1974 Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
1975 if (!stackFrame.registerFile->grow(newEnd)) {
1976 // Rewind to the previous call frame because op_call already optimistically
1977 // moved the call frame forward.
1978 ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc);
1979 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1980 return handler.callFrame;
1983 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
1984 for (size_t i = 0; i < omittedArgCount; ++i)
1985 argv[i] = jsUndefined();
1988 callFrame = CallFrame::create(r);
1989 callFrame->setCallerFrame(oldCallFrame);
1990 callFrame->setArgumentCountIncludingThis(argCount);
1991 callFrame->setCallee(callee);
1992 callFrame->setScopeChain(callee->scope().node());
1993 callFrame->setReturnPC(pc.value());
1995 ASSERT((void*)callFrame <= stackFrame.registerFile->end());
1999 #if ENABLE(JIT_OPTIMIZE_CALL)
2000 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
2002 STUB_INIT_STACK_FRAME(stackFrame);
2003 CallFrame* callFrame = stackFrame.callFrame;
2004 JSFunction* callee = asFunction(callFrame->callee());
2005 ExecutableBase* executable = callee->executable();
2007 MacroAssemblerCodePtr codePtr;
2008 CodeBlock* codeBlock = 0;
2009 if (executable->isHostFunction())
2010 codePtr = executable->generatedJITCodeForCall().addressForCall();
2012 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
2013 JSObject* error = functionExecutable->compileForCall(callFrame, callee->scope().node());
2015 callFrame->globalData().exception = createStackOverflowError(callFrame);
2018 codeBlock = &functionExecutable->generatedBytecodeForCall();
2019 if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
2020 codePtr = functionExecutable->generatedJITCodeForCall().addressForCall();
2022 codePtr = functionExecutable->generatedJITCodeForCallWithArityCheck();
2024 CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
2026 if (!callLinkInfo->seenOnce())
2027 callLinkInfo->setSeen();
2029 JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, callFrame->argumentCountIncludingThis(), stackFrame.globalData);
2031 return codePtr.executableAddress();
2034 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
2036 STUB_INIT_STACK_FRAME(stackFrame);
2037 CallFrame* callFrame = stackFrame.callFrame;
2038 JSFunction* callee = asFunction(callFrame->callee());
2039 ExecutableBase* executable = callee->executable();
2041 MacroAssemblerCodePtr codePtr;
2042 CodeBlock* codeBlock = 0;
2043 if (executable->isHostFunction())
2044 codePtr = executable->generatedJITCodeForConstruct().addressForCall();
2046 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
2047 JSObject* error = functionExecutable->compileForConstruct(callFrame, callee->scope().node());
2049 throwStackOverflowError(callFrame, stackFrame.globalData, ReturnAddressPtr(callFrame->returnPC()), STUB_RETURN_ADDRESS);
2052 codeBlock = &functionExecutable->generatedBytecodeForConstruct();
2053 if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
2054 codePtr = functionExecutable->generatedJITCodeForConstruct().addressForCall();
2056 codePtr = functionExecutable->generatedJITCodeForConstructWithArityCheck();
2058 CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
2060 if (!callLinkInfo->seenOnce())
2061 callLinkInfo->setSeen();
2063 JIT::linkConstruct(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, callFrame->argumentCountIncludingThis(), stackFrame.globalData);
2065 return codePtr.executableAddress();
2067 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
2069 DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
2071 STUB_INIT_STACK_FRAME(stackFrame);
2073 JSActivation* activation = new (stackFrame.globalData) JSActivation(stackFrame.callFrame, static_cast<FunctionExecutable*>(stackFrame.callFrame->codeBlock()->ownerExecutable()));
2074 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->copy()->push(activation));
2078 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
2080 STUB_INIT_STACK_FRAME(stackFrame);
2082 JSValue funcVal = stackFrame.args[0].jsValue();
2085 CallType callType = getCallData(funcVal, callData);
2087 ASSERT(callType != CallTypeJS);
2089 if (callType == CallTypeHost) {
2090 int registerOffset = stackFrame.args[1].int32();
2091 int argCount = stackFrame.args[2].int32();
2092 CallFrame* previousCallFrame = stackFrame.callFrame;
2093 CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
2094 if (!stackFrame.registerFile->grow(callFrame->registers())) {
2095 throwStackOverflowError(previousCallFrame, stackFrame.globalData, callFrame->returnPC(), STUB_RETURN_ADDRESS);
2096 VM_THROW_EXCEPTION();
2099 callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(funcVal));
2101 EncodedJSValue returnValue;
2103 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
2104 returnValue = callData.native.function(callFrame);
2107 CHECK_FOR_EXCEPTION_AT_END();
2111 ASSERT(callType == CallTypeNone);
2113 stackFrame.globalData->exception = createNotAFunctionError(stackFrame.callFrame, funcVal);
2114 VM_THROW_EXCEPTION();
2117 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
2119 STUB_INIT_STACK_FRAME(stackFrame);
2121 Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame);
2122 return JSValue::encode(JSValue(arguments));
2125 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments_no_params)
2127 STUB_INIT_STACK_FRAME(stackFrame);
2129 Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame, Arguments::NoParameters);
2130 return JSValue::encode(JSValue(arguments));
2133 DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
2135 STUB_INIT_STACK_FRAME(stackFrame);
2137 ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
2138 JSValue activationValue = stackFrame.args[0].jsValue();
2139 if (!activationValue) {
2140 if (JSValue v = stackFrame.args[1].jsValue()) {
2141 if (!stackFrame.callFrame->codeBlock()->isStrictMode())
2142 asArguments(v)->copyRegisters();
2146 JSActivation* activation = asActivation(stackFrame.args[0].jsValue());
2147 activation->copyRegisters();
2148 if (JSValue v = stackFrame.args[1].jsValue()) {
2149 if (!stackFrame.callFrame->codeBlock()->isStrictMode())
2150 asArguments(v)->setActivation(*stackFrame.globalData, activation);
2154 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
2156 STUB_INIT_STACK_FRAME(stackFrame);
2158 ASSERT(stackFrame.callFrame->codeBlock()->usesArguments() && !stackFrame.callFrame->codeBlock()->needsFullScopeChain());
2159 asArguments(stackFrame.args[0].jsValue())->copyRegisters();
2162 DEFINE_STUB_FUNCTION(void, op_profile_will_call)
2164 STUB_INIT_STACK_FRAME(stackFrame);
2166 ASSERT(*stackFrame.enabledProfilerReference);
2167 (*stackFrame.enabledProfilerReference)->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
2170 DEFINE_STUB_FUNCTION(void, op_profile_did_call)
2172 STUB_INIT_STACK_FRAME(stackFrame);
2174 ASSERT(*stackFrame.enabledProfilerReference);
2175 (*stackFrame.enabledProfilerReference)->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
2178 DEFINE_STUB_FUNCTION(void, op_ret_scopeChain)
2180 STUB_INIT_STACK_FRAME(stackFrame);
2182 ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
2183 stackFrame.callFrame->scopeChain()->deref();
2186 DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
2188 STUB_INIT_STACK_FRAME(stackFrame);
2190 ArgList argList(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
2191 return constructArray(stackFrame.callFrame, argList);
2194 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
2196 STUB_INIT_STACK_FRAME(stackFrame);
2198 CallFrame* callFrame = stackFrame.callFrame;
2199 ScopeChainNode* scopeChain = callFrame->scopeChain();
2201 ScopeChainIterator iter = scopeChain->begin();
2202 ScopeChainIterator end = scopeChain->end();
2203 ASSERT(iter != end);
2205 Identifier& ident = stackFrame.args[0].identifier();
2207 JSObject* o = iter->get();
2208 PropertySlot slot(o);
2209 if (o->getPropertySlot(callFrame, ident, slot)) {
2210 JSValue result = slot.getValue(callFrame, ident);
2211 CHECK_FOR_EXCEPTION_AT_END();
2212 return JSValue::encode(result);
2214 } while (++iter != end);
2216 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
2217 VM_THROW_EXCEPTION();
2220 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
2222 STUB_INIT_STACK_FRAME(stackFrame);
2224 JSValue constrVal = stackFrame.args[0].jsValue();
2226 ConstructData constructData;
2227 ConstructType constructType = getConstructData(constrVal, constructData);
2229 ASSERT(constructType != ConstructTypeJS);
2231 if (constructType == ConstructTypeHost) {
2232 int registerOffset = stackFrame.args[1].int32();
2233 int argCount = stackFrame.args[2].int32();
2234 CallFrame* previousCallFrame = stackFrame.callFrame;
2235 CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
2236 if (!stackFrame.registerFile->grow(callFrame->registers())) {
2237 throwStackOverflowError(previousCallFrame, stackFrame.globalData, callFrame->returnPC(), STUB_RETURN_ADDRESS);
2238 VM_THROW_EXCEPTION();
2241 callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(constrVal));
2243 EncodedJSValue returnValue;
2245 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
2246 returnValue = constructData.native.function(callFrame);
2249 CHECK_FOR_EXCEPTION_AT_END();
2253 ASSERT(constructType == ConstructTypeNone);
2255 stackFrame.globalData->exception = createNotAConstructorError(stackFrame.callFrame, constrVal);
2256 VM_THROW_EXCEPTION();
2259 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
2261 STUB_INIT_STACK_FRAME(stackFrame);
2263 CallFrame* callFrame = stackFrame.callFrame;
2264 JSGlobalData* globalData = stackFrame.globalData;
2266 JSValue baseValue = stackFrame.args[0].jsValue();
2267 JSValue subscript = stackFrame.args[1].jsValue();
2269 if (LIKELY(baseValue.isCell() && subscript.isString())) {
2270 Identifier propertyName(callFrame, asString(subscript)->value(callFrame));
2271 PropertySlot slot(baseValue.asCell());
2272 // JSString::value may have thrown, but we shouldn't find a property with a null identifier,
2273 // so we should miss this case and wind up in the CHECK_FOR_EXCEPTION_AT_END, below.
2274 if (baseValue.asCell()->fastGetOwnPropertySlot(callFrame, propertyName, slot)) {
2275 JSValue result = slot.getValue(callFrame, propertyName);
2276 CHECK_FOR_EXCEPTION();
2277 return JSValue::encode(result);
2281 if (subscript.isUInt32()) {
2282 uint32_t i = subscript.asUInt32();
2283 if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
2284 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
2285 JSValue result = asString(baseValue)->getIndex(callFrame, i);
2286 CHECK_FOR_EXCEPTION();
2287 return JSValue::encode(result);
2289 if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2290 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2291 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
2292 return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
2294 JSValue result = baseValue.get(callFrame, i);
2295 CHECK_FOR_EXCEPTION();
2296 return JSValue::encode(result);
2299 Identifier property(callFrame, subscript.toString(callFrame));
2300 JSValue result = baseValue.get(callFrame, property);
2301 CHECK_FOR_EXCEPTION_AT_END();
2302 return JSValue::encode(result);
2305 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
2307 STUB_INIT_STACK_FRAME(stackFrame);
2309 CallFrame* callFrame = stackFrame.callFrame;
2310 JSGlobalData* globalData = stackFrame.globalData;
2312 JSValue baseValue = stackFrame.args[0].jsValue();
2313 JSValue subscript = stackFrame.args[1].jsValue();
2317 if (LIKELY(subscript.isUInt32())) {
2318 uint32_t i = subscript.asUInt32();
2319 if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
2320 result = asString(baseValue)->getIndex(callFrame, i);
2322 result = baseValue.get(callFrame, i);
2323 if (!isJSString(globalData, baseValue))
2324 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
2327 Identifier property(callFrame, subscript.toString(callFrame));
2328 result = baseValue.get(callFrame, property);
2331 CHECK_FOR_EXCEPTION_AT_END();
2332 return JSValue::encode(result);
2335 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_byte_array)
2337 STUB_INIT_STACK_FRAME(stackFrame);
2339 CallFrame* callFrame = stackFrame.callFrame;
2340 JSGlobalData* globalData = stackFrame.globalData;
2342 JSValue baseValue = stackFrame.args[0].jsValue();
2343 JSValue subscript = stackFrame.args[1].jsValue();
2347 if (LIKELY(subscript.isUInt32())) {
2348 uint32_t i = subscript.asUInt32();
2349 if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2350 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2351 return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
2354 result = baseValue.get(callFrame, i);
2355 if (!isJSByteArray(globalData, baseValue))
2356 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
2358 Identifier property(callFrame, subscript.toString(callFrame));
2359 result = baseValue.get(callFrame, property);
2362 CHECK_FOR_EXCEPTION_AT_END();
2363 return JSValue::encode(result);
2366 DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub)
2368 STUB_INIT_STACK_FRAME(stackFrame);
2370 JSValue src1 = stackFrame.args[0].jsValue();
2371 JSValue src2 = stackFrame.args[1].jsValue();
2375 if (src1.getNumber(left) && src2.getNumber(right))
2376 return JSValue::encode(jsNumber(left - right));
2378 CallFrame* callFrame = stackFrame.callFrame;
2379 JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
2380 CHECK_FOR_EXCEPTION_AT_END();
2381 return JSValue::encode(result);
2384 DEFINE_STUB_FUNCTION(void, op_put_by_val)
2386 STUB_INIT_STACK_FRAME(stackFrame);
2388 CallFrame* callFrame = stackFrame.callFrame;
2389 JSGlobalData* globalData = stackFrame.globalData;
2391 JSValue baseValue = stackFrame.args[0].jsValue();
2392 JSValue subscript = stackFrame.args[1].jsValue();
2393 JSValue value = stackFrame.args[2].jsValue();
2395 if (LIKELY(subscript.isUInt32())) {
2396 uint32_t i = subscript.asUInt32();
2397 if (isJSArray(globalData, baseValue)) {
2398 JSArray* jsArray = asArray(baseValue);
2399 if (jsArray->canSetIndex(i))
2400 jsArray->setIndex(*globalData, i, value);
2402 jsArray->JSArray::put(callFrame, i, value);
2403 } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2404 JSByteArray* jsByteArray = asByteArray(baseValue);
2405 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_byte_array));
2406 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2407 if (value.isInt32()) {
2408 jsByteArray->setIndex(i, value.asInt32());
2412 if (value.getNumber(dValue)) {
2413 jsByteArray->setIndex(i, dValue);
2418 baseValue.put(callFrame, i, value);
2420 baseValue.put(callFrame, i, value);
2422 Identifier property(callFrame, subscript.toString(callFrame));
2423 if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
2424 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
2425 baseValue.put(callFrame, property, value, slot);
2429 CHECK_FOR_EXCEPTION_AT_END();
2432 DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array)
2434 STUB_INIT_STACK_FRAME(stackFrame);
2436 CallFrame* callFrame = stackFrame.callFrame;
2437 JSGlobalData* globalData = stackFrame.globalData;
2439 JSValue baseValue = stackFrame.args[0].jsValue();
2440 JSValue subscript = stackFrame.args[1].jsValue();
2441 JSValue value = stackFrame.args[2].jsValue();
2443 if (LIKELY(subscript.isUInt32())) {
2444 uint32_t i = subscript.asUInt32();
2445 if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2446 JSByteArray* jsByteArray = asByteArray(baseValue);
2448 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2449 if (value.isInt32()) {
2450 jsByteArray->setIndex(i, value.asInt32());
2454 if (value.getNumber(dValue)) {
2455 jsByteArray->setIndex(i, dValue);
2461 if (!isJSByteArray(globalData, baseValue))
2462 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
2463 baseValue.put(callFrame, i, value);
2465 Identifier property(callFrame, subscript.toString(callFrame));
2466 if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
2467 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
2468 baseValue.put(callFrame, property, value, slot);
2472 CHECK_FOR_EXCEPTION_AT_END();
2475 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
2477 STUB_INIT_STACK_FRAME(stackFrame);
2479 CallFrame* callFrame = stackFrame.callFrame;
2480 JSValue result = jsBoolean(jsLessEq(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
2481 CHECK_FOR_EXCEPTION_AT_END();
2482 return JSValue::encode(result);
2485 DEFINE_STUB_FUNCTION(int, op_load_varargs)
2487 STUB_INIT_STACK_FRAME(stackFrame);
2489 CallFrame* callFrame = stackFrame.callFrame;
2490 RegisterFile* registerFile = stackFrame.registerFile;
2491 int argsOffset = stackFrame.args[0].int32();
2492 JSValue arguments = callFrame->registers()[argsOffset].jsValue();
2493 uint32_t argCount = 0;
2495 int providedParams = callFrame->registers()[RegisterFile::ArgumentCount].i() - 1;
2496 argCount = providedParams;
2497 argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
2498 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
2499 Register* newEnd = callFrame->registers() + sizeDelta;
2500 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
2501 stackFrame.globalData->exception = createStackOverflowError(callFrame);
2502 VM_THROW_EXCEPTION();
2504 int32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
2505 int32_t inplaceArgs = min(providedParams, expectedParams);
2507 Register* inplaceArgsDst = callFrame->registers() + argsOffset;
2509 Register* inplaceArgsEnd = inplaceArgsDst + inplaceArgs;
2510 Register* inplaceArgsEnd2 = inplaceArgsDst + providedParams;
2512 Register* inplaceArgsSrc = callFrame->registers() - RegisterFile::CallFrameHeaderSize - expectedParams;
2513 Register* inplaceArgsSrc2 = inplaceArgsSrc - providedParams - 1 + inplaceArgs;
2515 // First step is to copy the "expected" parameters from their normal location relative to the callframe
2516 while (inplaceArgsDst < inplaceArgsEnd)
2517 *inplaceArgsDst++ = *inplaceArgsSrc++;
2519 // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
2520 while (inplaceArgsDst < inplaceArgsEnd2)
2521 *inplaceArgsDst++ = *inplaceArgsSrc2++;
2523 } else if (!arguments.isUndefinedOrNull()) {
2524 if (!arguments.isObject()) {
2525 stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
2526 VM_THROW_EXCEPTION();
2528 if (asObject(arguments)->classInfo() == &Arguments::info) {
2529 Arguments* argsObject = asArguments(arguments);
2530 argCount = argsObject->numProvidedArguments(callFrame);
2531 argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
2532 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
2533 Register* newEnd = callFrame->registers() + sizeDelta;
2534 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
2535 stackFrame.globalData->exception = createStackOverflowError(callFrame);
2536 VM_THROW_EXCEPTION();
2538 argsObject->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
2539 } else if (isJSArray(&callFrame->globalData(), arguments)) {
2540 JSArray* array = asArray(arguments);
2541 argCount = array->length();
2542 argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
2543 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
2544 Register* newEnd = callFrame->registers() + sizeDelta;
2545 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
2546 stackFrame.globalData->exception = createStackOverflowError(callFrame);
2547 VM_THROW_EXCEPTION();
2549 array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
2550 } else if (asObject(arguments)->inherits(&JSArray::info)) {
2551 JSObject* argObject = asObject(arguments);
2552 argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
2553 argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
2554 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
2555 Register* newEnd = callFrame->registers() + sizeDelta;
2556 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
2557 stackFrame.globalData->exception = createStackOverflowError(callFrame);
2558 VM_THROW_EXCEPTION();
2560 Register* argsBuffer = callFrame->registers() + argsOffset;
2561 for (unsigned i = 0; i < argCount; ++i) {
2562 argsBuffer[i] = asObject(arguments)->get(callFrame, i);
2563 CHECK_FOR_EXCEPTION();
2566 stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
2567 VM_THROW_EXCEPTION();
2571 return argCount + 1;
2574 DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate)
2576 STUB_INIT_STACK_FRAME(stackFrame);
2578 JSValue src = stackFrame.args[0].jsValue();
2581 if (src.getNumber(v))
2582 return JSValue::encode(jsNumber(-v));
2584 CallFrame* callFrame = stackFrame.callFrame;
2585 JSValue result = jsNumber(-src.toNumber(callFrame));
2586 CHECK_FOR_EXCEPTION_AT_END();
2587 return JSValue::encode(result);
2590 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base)
2592 STUB_INIT_STACK_FRAME(stackFrame);
2594 return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain(), false));
2597 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base_strict_put)
2599 STUB_INIT_STACK_FRAME(stackFrame);
2600 JSValue base = JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain(), true);
2602 stackFrame.globalData->exception = createErrorForInvalidGlobalAssignment(stackFrame.callFrame, stackFrame.args[0].identifier().ustring());
2603 VM_THROW_EXCEPTION();
2605 return JSValue::encode(base);
2608 DEFINE_STUB_FUNCTION(EncodedJSValue, op_ensure_property_exists)
2610 STUB_INIT_STACK_FRAME(stackFrame);
2611 JSValue base = stackFrame.callFrame->r(stackFrame.args[0].int32()).jsValue();
2612 JSObject* object = asObject(base);
2613 PropertySlot slot(object);
2614 ASSERT(stackFrame.callFrame->codeBlock()->isStrictMode());
2615 if (!object->getPropertySlot(stackFrame.callFrame, stackFrame.args[1].identifier(), slot)) {
2616 stackFrame.globalData->exception = createErrorForInvalidGlobalAssignment(stackFrame.callFrame, stackFrame.args[1].identifier().ustring());
2617 VM_THROW_EXCEPTION();
2620 return JSValue::encode(base);
2623 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
2625 STUB_INIT_STACK_FRAME(stackFrame);
2627 CallFrame* callFrame = stackFrame.callFrame;
2628 ScopeChainNode* scopeChain = callFrame->scopeChain();
2630 int skip = stackFrame.args[1].int32();
2632 ScopeChainIterator iter = scopeChain->begin();
2633 ScopeChainIterator end = scopeChain->end();
2634 ASSERT(iter != end);
2635 CodeBlock* codeBlock = callFrame->codeBlock();
2636 bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
2637 ASSERT(skip || !checkTopLevel);
2638 if (checkTopLevel && skip--) {
2639 if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
2644 ASSERT(iter != end);
2646 Identifier& ident = stackFrame.args[0].identifier();
2648 JSObject* o = iter->get();
2649 PropertySlot slot(o);
2650 if (o->getPropertySlot(callFrame, ident, slot)) {
2651 JSValue result = slot.getValue(callFrame, ident);
2652 CHECK_FOR_EXCEPTION_AT_END();
2653 return JSValue::encode(result);
2655 } while (++iter != end);
2657 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
2658 VM_THROW_EXCEPTION();
2661 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
2663 STUB_INIT_STACK_FRAME(stackFrame);
2665 CallFrame* callFrame = stackFrame.callFrame;
2666 CodeBlock* codeBlock = callFrame->codeBlock();
2667 JSGlobalObject* globalObject = codeBlock->globalObject();
2668 Identifier& ident = stackFrame.args[0].identifier();
2669 unsigned globalResolveInfoIndex = stackFrame.args[1].int32();
2670 ASSERT(globalObject->isGlobalObject());
2672 PropertySlot slot(globalObject);
2673 if (globalObject->getPropertySlot(callFrame, ident, slot)) {
2674 JSValue result = slot.getValue(callFrame, ident);
2675 if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
2676 GlobalResolveInfo& globalResolveInfo = codeBlock->globalResolveInfo(globalResolveInfoIndex);
2677 if (globalResolveInfo.structure)
2678 globalResolveInfo.structure->deref();
2679 globalObject->structure()->ref();
2680 globalResolveInfo.structure = globalObject->structure();
2681 globalResolveInfo.offset = slot.cachedOffset();
2682 return JSValue::encode(result);
2685 CHECK_FOR_EXCEPTION_AT_END();
2686 return JSValue::encode(result);
2689 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
2690 VM_THROW_EXCEPTION();
2693 DEFINE_STUB_FUNCTION(EncodedJSValue, op_div)
2695 STUB_INIT_STACK_FRAME(stackFrame);
2697 JSValue src1 = stackFrame.args[0].jsValue();
2698 JSValue src2 = stackFrame.args[1].jsValue();
2702 if (src1.getNumber(left) && src2.getNumber(right))
2703 return JSValue::encode(jsNumber(left / right));
2705 CallFrame* callFrame = stackFrame.callFrame;
2706 JSValue result = jsNumber(src1.toNumber(callFrame) / src2.toNumber(callFrame));
2707 CHECK_FOR_EXCEPTION_AT_END();
2708 return JSValue::encode(result);
2711 DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_dec)
2713 STUB_INIT_STACK_FRAME(stackFrame);
2715 JSValue v = stackFrame.args[0].jsValue();
2717 CallFrame* callFrame = stackFrame.callFrame;
2718 JSValue result = jsNumber(v.toNumber(callFrame) - 1);
2719 CHECK_FOR_EXCEPTION_AT_END();
2720 return JSValue::encode(result);
2723 DEFINE_STUB_FUNCTION(int, op_jless)
2725 STUB_INIT_STACK_FRAME(stackFrame);
2727 JSValue src1 = stackFrame.args[0].jsValue();
2728 JSValue src2 = stackFrame.args[1].jsValue();
2729 CallFrame* callFrame = stackFrame.callFrame;
2731 bool result = jsLess(callFrame, src1, src2);
2732 CHECK_FOR_EXCEPTION_AT_END();
2736 DEFINE_STUB_FUNCTION(int, op_jlesseq)
2738 STUB_INIT_STACK_FRAME(stackFrame);
2740 JSValue src1 = stackFrame.args[0].jsValue();
2741 JSValue src2 = stackFrame.args[1].jsValue();
2742 CallFrame* callFrame = stackFrame.callFrame;
2744 bool result = jsLessEq(callFrame, src1, src2);
2745 CHECK_FOR_EXCEPTION_AT_END();
2749 DEFINE_STUB_FUNCTION(EncodedJSValue, op_not)
2751 STUB_INIT_STACK_FRAME(stackFrame);
2753 JSValue src = stackFrame.args[0].jsValue();
2755 CallFrame* callFrame = stackFrame.callFrame;
2757 JSValue result = jsBoolean(!src.toBoolean(callFrame));
2758 CHECK_FOR_EXCEPTION_AT_END();
2759 return JSValue::encode(result);
2762 DEFINE_STUB_FUNCTION(int, op_jtrue)
2764 STUB_INIT_STACK_FRAME(stackFrame);
2766 JSValue src1 = stackFrame.args[0].jsValue();
2768 CallFrame* callFrame = stackFrame.callFrame;
2770 bool result = src1.toBoolean(callFrame);
2771 CHECK_FOR_EXCEPTION_AT_END();
2775 DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_inc)
2777 STUB_INIT_STACK_FRAME(stackFrame);
2779 JSValue v = stackFrame.args[0].jsValue();
2781 CallFrame* callFrame = stackFrame.callFrame;
2783 JSValue number = v.toJSNumber(callFrame);
2784 CHECK_FOR_EXCEPTION_AT_END();
2786 callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number.uncheckedGetNumber() + 1);
2787 return JSValue::encode(number);
2790 DEFINE_STUB_FUNCTION(int, op_eq)
2792 STUB_INIT_STACK_FRAME(stackFrame);
2794 JSValue src1 = stackFrame.args[0].jsValue();
2795 JSValue src2 = stackFrame.args[1].jsValue();
2797 #if USE(JSVALUE32_64)
2799 if (src2.isUndefined()) {
2800 return src1.isNull() ||
2801 (src1.isCell() && src1.asCell()->structure()->typeInfo().masqueradesAsUndefined())
2802 || src1.isUndefined();
2805 if (src2.isNull()) {
2806 return src1.isUndefined() ||
2807 (src1.isCell() && src1.asCell()->structure()->typeInfo().masqueradesAsUndefined())
2811 if (src1.isInt32()) {
2812 if (src2.isDouble())
2813 return src1.asInt32() == src2.asDouble();
2814 double d = src2.toNumber(stackFrame.callFrame);
2815 CHECK_FOR_EXCEPTION();
2816 return src1.asInt32() == d;
2819 if (src1.isDouble()) {
2821 return src1.asDouble() == src2.asInt32();
2822 double d = src2.toNumber(stackFrame.callFrame);
2823 CHECK_FOR_EXCEPTION();
2824 return src1.asDouble() == d;
2827 if (src1.isTrue()) {
2830 double d = src2.toNumber(stackFrame.callFrame);
2831 CHECK_FOR_EXCEPTION();
2835 if (src1.isFalse()) {
2838 double d = src2.toNumber(stackFrame.callFrame);
2839 CHECK_FOR_EXCEPTION();
2843 if (src1.isUndefined())
2844 return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
2847 return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
2849 JSCell* cell1 = src1.asCell();
2851 if (cell1->isString()) {
2853 return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32();
2855 if (src2.isDouble())
2856 return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble();
2859 return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0;
2862 return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0;
2864 JSCell* cell2 = src2.asCell();
2865 if (cell2->isString())
2866 return static_cast<JSString*>(cell1)->value(stackFrame.callFrame) == static_cast<JSString*>(cell2)->value(stackFrame.callFrame);
2868 src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
2869 CHECK_FOR_EXCEPTION();
2873 if (src2.isObject())
2874 return asObject(cell1) == asObject(src2);
2875 src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame);
2876 CHECK_FOR_EXCEPTION();
2879 #else // USE(JSVALUE32_64)
2880 CallFrame* callFrame = stackFrame.callFrame;
2882 bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2);
2883 CHECK_FOR_EXCEPTION_AT_END();
2885 #endif // USE(JSVALUE32_64)
2888 DEFINE_STUB_FUNCTION(int, op_eq_strings)
2890 #if USE(JSVALUE32_64)
2891 STUB_INIT_STACK_FRAME(stackFrame);
2893 JSString* string1 = stackFrame.args[0].jsString();
2894 JSString* string2 = stackFrame.args[1].jsString();
2896 ASSERT(string1->isString());
2897 ASSERT(string2->isString());
2898 return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame);
2901 ASSERT_NOT_REACHED();
2906 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift)
2908 STUB_INIT_STACK_FRAME(stackFrame);
2910 JSValue val = stackFrame.args[0].jsValue();
2911 JSValue shift = stackFrame.args[1].jsValue();
2913 CallFrame* callFrame = stackFrame.callFrame;
2914 JSValue result = jsNumber((val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
2915 CHECK_FOR_EXCEPTION_AT_END();
2916 return JSValue::encode(result);
2919 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitand)
2921 STUB_INIT_STACK_FRAME(stackFrame);
2923 JSValue src1 = stackFrame.args[0].jsValue();
2924 JSValue src2 = stackFrame.args[1].jsValue();
2926 ASSERT(!src1.isInt32() || !src2.isInt32());
2927 CallFrame* callFrame = stackFrame.callFrame;
2928 JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame));
2929 CHECK_FOR_EXCEPTION_AT_END();
2930 return JSValue::encode(result);
2933 DEFINE_STUB_FUNCTION(EncodedJSValue, op_rshift)
2935 STUB_INIT_STACK_FRAME(stackFrame);
2937 JSValue val = stackFrame.args[0].jsValue();
2938 JSValue shift = stackFrame.args[1].jsValue();
2940 CallFrame* callFrame = stackFrame.callFrame;
2941 JSValue result = jsNumber((val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
2943 CHECK_FOR_EXCEPTION_AT_END();
2944 return JSValue::encode(result);
2947 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitnot)
2949 STUB_INIT_STACK_FRAME(stackFrame);
2951 JSValue src = stackFrame.args[0].jsValue();
2953 ASSERT(!src.isInt32());
2954 CallFrame* callFrame = stackFrame.callFrame;
2955 JSValue result = jsNumber(~src.toInt32(callFrame));
2956 CHECK_FOR_EXCEPTION_AT_END();
2957 return JSValue::encode(result);
2960 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base)
2962 STUB_INIT_STACK_FRAME(stackFrame);
2964 CallFrame* callFrame = stackFrame.callFrame;
2965 ScopeChainNode* scopeChain = callFrame->scopeChain();
2967 ScopeChainIterator iter = scopeChain->begin();
2968 ScopeChainIterator end = scopeChain->end();
2970 // FIXME: add scopeDepthIsZero optimization
2972 ASSERT(iter != end);
2974 Identifier& ident = stackFrame.args[0].identifier();
2978 PropertySlot slot(base);
2979 if (base->getPropertySlot(callFrame, ident, slot)) {
2980 JSValue result = slot.getValue(callFrame, ident);
2981 CHECK_FOR_EXCEPTION_AT_END();
2983 callFrame->registers()[stackFrame.args[1].int32()] = JSValue(base);
2984 return JSValue::encode(result);
2987 } while (iter != end);
2989 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
2990 VM_THROW_EXCEPTION_AT_END();
2991 return JSValue::encode(JSValue());
2994 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
2996 STUB_INIT_STACK_FRAME(stackFrame);
2997 CallFrame* callFrame = stackFrame.callFrame;
2999 FunctionExecutable* function = stackFrame.args[0].function();
3000 JSFunction* func = function->make(callFrame, callFrame->scopeChain());
3001 ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue());
3004 The Identifier in a FunctionExpression can be referenced from inside
3005 the FunctionExpression's FunctionBody to allow the function to call
3006 itself recursively. However, unlike in a FunctionDeclaration, the
3007 Identifier in a FunctionExpression cannot be referenced from and
3008 does not affect the scope enclosing the FunctionExpression.
3010 if (!function->name().isNull()) {
3011 JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
3012 func->scope().push(functionScopeObject);
3018 DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod)
3020 STUB_INIT_STACK_FRAME(stackFrame);
3022 JSValue dividendValue = stackFrame.args[0].jsValue();
3023 JSValue divisorValue = stackFrame.args[1].jsValue();
3025 CallFrame* callFrame = stackFrame.callFrame;
3026 double d = dividendValue.toNumber(callFrame);
3027 JSValue result = jsNumber(fmod(d, divisorValue.toNumber(callFrame)));
3028 CHECK_FOR_EXCEPTION_AT_END();
3029 return JSValue::encode(result);
3032 DEFINE_STUB_FUNCTION(EncodedJSValue, op_less)
3034 STUB_INIT_STACK_FRAME(stackFrame);
3036 CallFrame* callFrame = stackFrame.callFrame;
3037 JSValue result = jsBoolean(jsLess(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
3038 CHECK_FOR_EXCEPTION_AT_END();
3039 return JSValue::encode(result);
3042 DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_dec)
3044 STUB_INIT_STACK_FRAME(stackFrame);
3046 JSValue v = stackFrame.args[0].jsValue();
3048 CallFrame* callFrame = stackFrame.callFrame;
3050 JSValue number = v.toJSNumber(callFrame);
3051 CHECK_FOR_EXCEPTION_AT_END();
3053 callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number.uncheckedGetNumber() - 1);
3054 return JSValue::encode(number);
3057 DEFINE_STUB_FUNCTION(EncodedJSValue, op_urshift)
3059 STUB_INIT_STACK_FRAME(stackFrame);
3061 JSValue val = stackFrame.args[0].jsValue();
3062 JSValue shift = stackFrame.args[1].jsValue();
3064 CallFrame* callFrame = stackFrame.callFrame;
3065 JSValue result = jsNumber((val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
3066 CHECK_FOR_EXCEPTION_AT_END();
3067 return JSValue::encode(result);
3070 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitxor)
3072 STUB_INIT_STACK_FRAME(stackFrame);
3074 JSValue src1 = stackFrame.args[0].jsValue();
3075 JSValue src2 = stackFrame.args[1].jsValue();
3077 CallFrame* callFrame = stackFrame.callFrame;
3079 JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
3080 CHECK_FOR_EXCEPTION_AT_END();
3081 return JSValue::encode(result);
3084 DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp)
3086 STUB_INIT_STACK_FRAME(stackFrame);
3088 return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), stackFrame.args[0].regExp());
3091 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
3093 STUB_INIT_STACK_FRAME(stackFrame);
3095 JSValue src1 = stackFrame.args[0].jsValue();
3096 JSValue src2 = stackFrame.args[1].jsValue();
3098 CallFrame* callFrame = stackFrame.callFrame;
3100 JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame));
3101 CHECK_FOR_EXCEPTION_AT_END();
3102 return JSValue::encode(result);
3105 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
3107 STUB_INIT_STACK_FRAME(stackFrame);
3108 ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
3110 CallFrame* callFrame = stackFrame.callFrame;
3111 RegisterFile* registerFile = stackFrame.registerFile;
3113 Interpreter* interpreter = stackFrame.globalData->interpreter;
3115 JSValue funcVal = stackFrame.args[0].jsValue();
3116 int registerOffset = stackFrame.args[1].int32();
3117 int argCount = stackFrame.args[2].int32();
3119 Register* newCallFrame = callFrame->registers() + registerOffset;
3120 Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
3121 JSValue baseValue = argv[0].jsValue();
3122 JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
3124 if (baseValue == globalObject && funcVal == globalObject->evalFunction()) {
3125 JSValue result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset);
3126 CHECK_FOR_EXCEPTION_AT_END();
3127 return JSValue::encode(result);
3130 return JSValue::encode(JSValue());
3133 DEFINE_STUB_FUNCTION(void*, op_throw)
3135 STUB_INIT_STACK_FRAME(stackFrame);
3136 ExceptionHandler handler = jitThrow(stackFrame.globalData, stackFrame.callFrame, stackFrame.args[0].jsValue(), STUB_RETURN_ADDRESS);
3137 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
3138 return handler.callFrame;
3141 DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
3143 STUB_INIT_STACK_FRAME(stackFrame);
3145 CallFrame* callFrame = stackFrame.callFrame;
3146 JSObject* o = stackFrame.args[0].jsObject();
3147 Structure* structure = o->structure();
3148 JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
3149 if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
3150 jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
3151 return jsPropertyNameIterator;
3154 DEFINE_STUB_FUNCTION(int, has_property)
3156 STUB_INIT_STACK_FRAME(stackFrame);
3158 JSObject* base = stackFrame.args[0].jsObject();
3159 JSString* property = stackFrame.args[1].jsString();
3160 int result = base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame)));
3161 CHECK_FOR_EXCEPTION_AT_END();
3165 DEFINE_STUB_FUNCTION(JSObject*, op_push_scope)
3167 STUB_INIT_STACK_FRAME(stackFrame);
3169 JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame);
3170 CHECK_FOR_EXCEPTION();
3171 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(o));
3175 DEFINE_STUB_FUNCTION(void, op_pop_scope)
3177 STUB_INIT_STACK_FRAME(stackFrame);
3179 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->pop());
3182 DEFINE_STUB_FUNCTION(EncodedJSValue, op_typeof)
3184 STUB_INIT_STACK_FRAME(stackFrame);
3186 return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue()));
3189 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_undefined)
3191 STUB_INIT_STACK_FRAME(stackFrame);
3193 JSValue v = stackFrame.args[0].jsValue();
3194 return JSValue::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
3197 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_boolean)
3199 STUB_INIT_STACK_FRAME(stackFrame);
3201 return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isBoolean()));
3204 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_number)
3206 STUB_INIT_STACK_FRAME(stackFrame);
3208 return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isNumber()));
3211 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_string)
3213 STUB_INIT_STACK_FRAME(stackFrame);
3215 return JSValue::encode(jsBoolean(isJSString(stackFrame.globalData, stackFrame.args[0].jsValue())));
3218 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object)
3220 STUB_INIT_STACK_FRAME(stackFrame);
3222 return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame.args[0].jsValue())));
3225 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_function)
3227 STUB_INIT_STACK_FRAME(stackFrame);
3229 return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame.args[0].jsValue())));
3232 DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq)
3234 STUB_INIT_STACK_FRAME(stackFrame);
3236 JSValue src1 = stackFrame.args[0].jsValue();
3237 JSValue src2 = stackFrame.args[1].jsValue();
3239 bool result = JSValue::strictEqual(stackFrame.callFrame, src1, src2);
3240 CHECK_FOR_EXCEPTION_AT_END();
3241 return JSValue::encode(jsBoolean(result));
3244 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive)
3246 STUB_INIT_STACK_FRAME(stackFrame);
3248 return JSValue::encode(stackFrame.args[0].jsValue().toPrimitive(stackFrame.callFrame));
3251 DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat)
3253 STUB_INIT_STACK_FRAME(stackFrame);
3255 JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
3256 CHECK_FOR_EXCEPTION_AT_END();
3257 return JSValue::encode(result);
3260 DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq)
3262 STUB_INIT_STACK_FRAME(stackFrame);
3264 JSValue src1 = stackFrame.args[0].jsValue();
3265 JSValue src2 = stackFrame.args[1].jsValue();
3267 bool result = !JSValue::strictEqual(stackFrame.callFrame, src1, src2);
3268 CHECK_FOR_EXCEPTION_AT_END();
3269 return JSValue::encode(jsBoolean(result));
3272 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber)
3274 STUB_INIT_STACK_FRAME(stackFrame);
3276 JSValue src = stackFrame.args[0].jsValue();
3277 CallFrame* callFrame = stackFrame.callFrame;
3279 JSValue result = src.toJSNumber(callFrame);
3280 CHECK_FOR_EXCEPTION_AT_END();
3281 return JSValue::encode(result);
3284 DEFINE_STUB_FUNCTION(EncodedJSValue, op_in)
3286 STUB_INIT_STACK_FRAME(stackFrame);
3288 CallFrame* callFrame = stackFrame.callFrame;
3289 JSValue baseVal = stackFrame.args[1].jsValue();
3291 if (!baseVal.isObject()) {
3292 stackFrame.globalData->exception = createInvalidParamError(stackFrame.callFrame, "in", baseVal);
3293 VM_THROW_EXCEPTION();
3296 JSValue propName = stackFrame.args[0].jsValue();
3297 JSObject* baseObj = asObject(baseVal);
3300 if (propName.getUInt32(i))
3301 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
3303 Identifier property(callFrame, propName.toString(callFrame));
3304 CHECK_FOR_EXCEPTION();
3305 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
3308 DEFINE_STUB_FUNCTION(JSObject*, op_push_new_scope)
3310 STUB_INIT_STACK_FRAME(stackFrame);
3312 JSObject* scope = new (stackFrame.globalData) JSStaticScopeObject(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), DontDelete);
3314 CallFrame* callFrame = stackFrame.callFrame;
3315 callFrame->setScopeChain(callFrame->scopeChain()->push(scope));
3319 DEFINE_STUB_FUNCTION(void, op_jmp_scopes)
3321 STUB_INIT_STACK_FRAME(stackFrame);
3323 unsigned count = stackFrame.args[0].int32();
3324 CallFrame* callFrame = stackFrame.callFrame;
3326 ScopeChainNode* tmp = callFrame->scopeChain();
3329 callFrame->setScopeChain(tmp);
3332 DEFINE_STUB_FUNCTION(void, op_put_by_index)
3334 STUB_INIT_STACK_FRAME(stackFrame);
3336 CallFrame* callFrame = stackFrame.callFrame;
3337 unsigned property = stackFrame.args[1].int32();
3339 stackFrame.args[0].jsValue().put(callFrame, property, stackFrame.args[2].jsValue());
3342 DEFINE_STUB_FUNCTION(void*, op_switch_imm)
3344 STUB_INIT_STACK_FRAME(stackFrame);
3346 JSValue scrutinee = stackFrame.args[0].jsValue();
3347 unsigned tableIndex = stackFrame.args[1].int32();
3348 CallFrame* callFrame = stackFrame.callFrame;
3349 CodeBlock* codeBlock = callFrame->codeBlock();
3351 if (scrutinee.isInt32())
3352 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
3356 if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
3357 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(intValue).executableAddress();
3359 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
3363 DEFINE_STUB_FUNCTION(void*, op_switch_char)
3365 STUB_INIT_STACK_FRAME(stackFrame);
3367 JSValue scrutinee = stackFrame.args[0].jsValue();
3368 unsigned tableIndex = stackFrame.args[1].int32();
3369 CallFrame* callFrame = stackFrame.callFrame;
3370 CodeBlock* codeBlock = callFrame->codeBlock();
3372 void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
3374 if (scrutinee.isString()) {
3375 StringImpl* value = asString(scrutinee)->value(callFrame).impl();
3376 if (value->length() == 1)
3377 result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->characters()[0]).executableAddress();
3380 CHECK_FOR_EXCEPTION_AT_END();
3384 DEFINE_STUB_FUNCTION(void*, op_switch_string)
3386 STUB_INIT_STACK_FRAME(stackFrame);
3388 JSValue scrutinee = stackFrame.args[0].jsValue();
3389 unsigned tableIndex = stackFrame.args[1].int32();
3390 CallFrame* callFrame = stackFrame.callFrame;
3391 CodeBlock* codeBlock = callFrame->codeBlock();
3393 void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
3395 if (scrutinee.isString()) {
3396 StringImpl* value = asString(scrutinee)->value(callFrame).impl();
3397 result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
3400 CHECK_FOR_EXCEPTION_AT_END();
3404 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val)
3406 STUB_INIT_STACK_FRAME(stackFrame);
3408 CallFrame* callFrame = stackFrame.callFrame;
3410 JSValue baseValue = stackFrame.args[0].jsValue();
3411 JSObject* baseObj = baseValue.toObject(callFrame); // may throw
3413 JSValue subscript = stackFrame.args[1].jsValue();
3416 if (subscript.getUInt32(i))
3417 result = baseObj->deleteProperty(callFrame, i);
3419 CHECK_FOR_EXCEPTION();
3420 Identifier property(callFrame, subscript.toString(callFrame));
3421 CHECK_FOR_EXCEPTION();
3422 result = baseObj->deleteProperty(callFrame, property);
3425 if (!result && callFrame->codeBlock()->isStrictMode())
3426 stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
3428 CHECK_FOR_EXCEPTION_AT_END();
3429 return JSValue::encode(jsBoolean(result));
3432 DEFINE_STUB_FUNCTION(void, op_put_getter)
3434 STUB_INIT_STACK_FRAME(stackFrame);
3436 CallFrame* callFrame = stackFrame.callFrame;
3438 ASSERT(stackFrame.args[0].jsValue().isObject());
3439 JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
3440 ASSERT(stackFrame.args[2].jsValue().isObject());
3441 baseObj->defineGetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
3444 DEFINE_STUB_FUNCTION(void, op_put_setter)
3446 STUB_INIT_STACK_FRAME(stackFrame);
3448 CallFrame* callFrame = stackFrame.callFrame;
3450 ASSERT(stackFrame.args[0].jsValue().isObject());
3451 JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
3452 ASSERT(stackFrame.args[2].jsValue().isObject());
3453 baseObj->defineSetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
3456 DEFINE_STUB_FUNCTION(void, op_throw_reference_error)
3458 STUB_INIT_STACK_FRAME(stackFrame);
3460 CallFrame* callFrame = stackFrame.callFrame;
3461 UString message = stackFrame.args[0].jsValue().toString(callFrame);
3462 stackFrame.globalData->exception = createReferenceError(callFrame, message);
3463 VM_THROW_EXCEPTION_AT_END();
3466 DEFINE_STUB_FUNCTION(void, op_debug)
3468 STUB_INIT_STACK_FRAME(stackFrame);
3470 CallFrame* callFrame = stackFrame.callFrame;
3472 int debugHookID = stackFrame.args[0].int32();
3473 int firstLine = stackFrame.args[1].int32();
3474 int lastLine = stackFrame.args[2].int32();
3476 stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
3479 DEFINE_STUB_FUNCTION(void*, vm_throw)
3481 STUB_INIT_STACK_FRAME(stackFrame);
3482 JSGlobalData* globalData = stackFrame.globalData;
3483 ExceptionHandler handler = jitThrow(globalData, stackFrame.callFrame, globalData->exception.get(), globalData->exceptionLocation);
3484 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
3485 return handler.callFrame;
3488 DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
3490 STUB_INIT_STACK_FRAME(stackFrame);
3492 CallFrame* callFrame = stackFrame.callFrame;
3493 return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
3496 MacroAssemblerCodePtr JITThunks::ctiStub(JSGlobalData* globalData, ThunkGenerator generator)
3498 std::pair<CTIStubMap::iterator, bool> entry = m_ctiStubMap.add(generator, MacroAssemblerCodePtr());
3500 entry.first->second = generator(globalData, m_executablePool.get());
3501 return entry.first->second;
3504 PassRefPtr<NativeExecutable> JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function)
3506 std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap.add(function, 0);
3508 entry.first->second = NativeExecutable::create(JIT::compileCTINativeCall(globalData, m_executablePool, function), function, ctiNativeConstruct(), callHostFunctionAsConstructor);
3509 return entry.first->second;
3512 PassRefPtr<NativeExecutable> JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator)
3514 std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap.add(function, 0);
3516 MacroAssemblerCodePtr code = globalData->canUseJIT() ? generator(globalData, m_executablePool.get()) : MacroAssemblerCodePtr();
3517 entry.first->second = NativeExecutable::create(code, function, ctiNativeConstruct(), call