]> git.saurik.com Git - apple/javascriptcore.git/blame - jit/JITStubs.cpp
JavaScriptCore-1097.3.tar.gz
[apple/javascriptcore.git] / jit / JITStubs.cpp
CommitLineData
ba379fdc
A
1/*
2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
14957cd0 4 * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved.
ba379fdc
A
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
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.
18 *
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.
29 */
30
31#include "config.h"
ba379fdc
A
32
33#if ENABLE(JIT)
14957cd0 34#include "JITStubs.h"
ba379fdc 35
6fe7ccc8 36#include "CommonSlowPaths.h"
ba379fdc
A
37#include "Arguments.h"
38#include "CallFrame.h"
39#include "CodeBlock.h"
6fe7ccc8
A
40#include "CodeProfiling.h"
41#include "DFGOSREntry.h"
ba379fdc
A
42#include "Debugger.h"
43#include "ExceptionHelpers.h"
4e4e5a6f 44#include "GetterSetter.h"
6fe7ccc8
A
45#include "Heap.h"
46#include <wtf/InlineASM.h>
ba379fdc 47#include "JIT.h"
6fe7ccc8 48#include "JITExceptions.h"
ba379fdc
A
49#include "JSActivation.h"
50#include "JSArray.h"
ba379fdc 51#include "JSFunction.h"
14957cd0 52#include "JSGlobalObjectFunctions.h"
ba379fdc
A
53#include "JSNotAnObject.h"
54#include "JSPropertyNameIterator.h"
55#include "JSStaticScopeObject.h"
56#include "JSString.h"
57#include "ObjectPrototype.h"
58#include "Operations.h"
59#include "Parser.h"
60#include "Profiler.h"
61#include "RegExpObject.h"
62#include "RegExpPrototype.h"
63#include "Register.h"
64#include "SamplingTool.h"
6fe7ccc8 65#include "Strong.h"
f9bf01c6 66#include <wtf/StdLibExtras.h>
ba379fdc
A
67#include <stdarg.h>
68#include <stdio.h>
69
70using namespace std;
71
72namespace JSC {
73
ba379fdc
A
74#if USE(JSVALUE32_64)
75
f9bf01c6 76#if COMPILER(GCC) && CPU(X86)
ba379fdc
A
77
78// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
79// need to change the assembly trampolines below to match.
80COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
81COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
82COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
83COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
84
14957cd0 85asm (
f9bf01c6 86".text\n"
ba379fdc 87".globl " SYMBOL_STRING(ctiTrampoline) "\n"
f9bf01c6 88HIDE_SYMBOL(ctiTrampoline) "\n"
ba379fdc
A
89SYMBOL_STRING(ctiTrampoline) ":" "\n"
90 "pushl %ebp" "\n"
91 "movl %esp, %ebp" "\n"
92 "pushl %esi" "\n"
93 "pushl %edi" "\n"
94 "pushl %ebx" "\n"
95 "subl $0x3c, %esp" "\n"
ba379fdc
A
96 "movl 0x58(%esp), %edi" "\n"
97 "call *0x50(%esp)" "\n"
98 "addl $0x3c, %esp" "\n"
99 "popl %ebx" "\n"
100 "popl %edi" "\n"
101 "popl %esi" "\n"
102 "popl %ebp" "\n"
103 "ret" "\n"
6fe7ccc8
A
104".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
105HIDE_SYMBOL(ctiTrampolineEnd) "\n"
106SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
ba379fdc
A
107);
108
14957cd0 109asm (
ba379fdc 110".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
f9bf01c6 111HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
ba379fdc 112SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
ba379fdc 113 "movl %esp, %ecx" "\n"
f9bf01c6 114 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
14957cd0 115 "int3" "\n"
ba379fdc
A
116);
117
14957cd0 118asm (
ba379fdc 119".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
f9bf01c6 120HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
ba379fdc
A
121SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
122 "addl $0x3c, %esp" "\n"
123 "popl %ebx" "\n"
124 "popl %edi" "\n"
125 "popl %esi" "\n"
126 "popl %ebp" "\n"
127 "ret" "\n"
128);
129
f9bf01c6 130#elif COMPILER(GCC) && CPU(X86_64)
ba379fdc 131
ba379fdc
A
132// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
133// need to change the assembly trampolines below to match.
134COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment);
135COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
136COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
137COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline);
138
14957cd0 139asm (
ba379fdc 140".globl " SYMBOL_STRING(ctiTrampoline) "\n"
f9bf01c6 141HIDE_SYMBOL(ctiTrampoline) "\n"
ba379fdc
A
142SYMBOL_STRING(ctiTrampoline) ":" "\n"
143 "pushq %rbp" "\n"
144 "movq %rsp, %rbp" "\n"
145 "pushq %r12" "\n"
146 "pushq %r13" "\n"
147 "pushq %r14" "\n"
148 "pushq %r15" "\n"
149 "pushq %rbx" "\n"
150 "subq $0x48, %rsp" "\n"
151 "movq $512, %r12" "\n"
152 "movq $0xFFFF000000000000, %r14" "\n"
153 "movq $0xFFFF000000000002, %r15" "\n"
154 "movq 0x90(%rsp), %r13" "\n"
155 "call *0x80(%rsp)" "\n"
156 "addq $0x48, %rsp" "\n"
157 "popq %rbx" "\n"
158 "popq %r15" "\n"
159 "popq %r14" "\n"
160 "popq %r13" "\n"
161 "popq %r12" "\n"
162 "popq %rbp" "\n"
163 "ret" "\n"
6fe7ccc8
A
164".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
165HIDE_SYMBOL(ctiTrampolineEnd) "\n"
166SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
ba379fdc
A
167);
168
14957cd0 169asm (
ba379fdc 170".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
f9bf01c6 171HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
ba379fdc
A
172SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
173 "movq %rsp, %rdi" "\n"
f9bf01c6 174 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
14957cd0 175 "int3" "\n"
ba379fdc
A
176);
177
14957cd0 178asm (
ba379fdc 179".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
f9bf01c6 180HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
ba379fdc
A
181SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
182 "addq $0x48, %rsp" "\n"
183 "popq %rbx" "\n"
184 "popq %r15" "\n"
185 "popq %r14" "\n"
186 "popq %r13" "\n"
187 "popq %r12" "\n"
188 "popq %rbp" "\n"
189 "ret" "\n"
190);
191
14957cd0 192#elif (COMPILER(GCC) || COMPILER(RVCT)) && CPU(ARM_THUMB2)
ba379fdc 193
14957cd0
A
194#define THUNK_RETURN_ADDRESS_OFFSET 0x38
195#define PRESERVED_RETURN_ADDRESS_OFFSET 0x3C
196#define PRESERVED_R4_OFFSET 0x40
197#define PRESERVED_R5_OFFSET 0x44
198#define PRESERVED_R6_OFFSET 0x48
6fe7ccc8
A
199#define PRESERVED_R7_OFFSET 0x4C
200#define PRESERVED_R8_OFFSET 0x50
201#define PRESERVED_R9_OFFSET 0x54
202#define PRESERVED_R10_OFFSET 0x58
203#define PRESERVED_R11_OFFSET 0x5C
204#define REGISTER_FILE_OFFSET 0x60
205#define CALLFRAME_OFFSET 0x64
206#define EXCEPTION_OFFSET 0x64
207#define ENABLE_PROFILER_REFERENCE_OFFSET 0x68
ba379fdc 208
14957cd0 209#elif (COMPILER(GCC) || COMPILER(MSVC) || COMPILER(RVCT)) && CPU(ARM_TRADITIONAL)
f9bf01c6 210
14957cd0
A
211// Also update the MSVC section (defined at DEFINE_STUB_FUNCTION)
212// when changing one of the following values.
4e4e5a6f
A
213#define THUNK_RETURN_ADDRESS_OFFSET 64
214#define PRESERVEDR4_OFFSET 68
f9bf01c6
A
215
216#elif COMPILER(MSVC) && CPU(X86)
ba379fdc 217
ba379fdc
A
218// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
219// need to change the assembly trampolines below to match.
220COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
221COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
222COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
223COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
224
225extern "C" {
226
14957cd0 227 __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
ba379fdc
A
228 {
229 __asm {
230 push ebp;
231 mov ebp, esp;
232 push esi;
233 push edi;
234 push ebx;
235 sub esp, 0x3c;
ba379fdc
A
236 mov ecx, esp;
237 mov edi, [esp + 0x58];
238 call [esp + 0x50];
239 add esp, 0x3c;
240 pop ebx;
241 pop edi;
242 pop esi;
243 pop ebp;
244 ret;
245 }
246 }
247
248 __declspec(naked) void ctiVMThrowTrampoline()
249 {
250 __asm {
251 mov ecx, esp;
252 call cti_vm_throw;
253 add esp, 0x3c;
254 pop ebx;
255 pop edi;
256 pop esi;
257 pop ebp;
258 ret;
259 }
260 }
261
262 __declspec(naked) void ctiOpThrowNotCaught()
263 {
264 __asm {
265 add esp, 0x3c;
266 pop ebx;
267 pop edi;
268 pop esi;
269 pop ebp;
270 ret;
271 }
272 }
273}
274
14957cd0 275#elif CPU(MIPS)
ba379fdc 276
14957cd0
A
277#define PRESERVED_GP_OFFSET 60
278#define PRESERVED_S0_OFFSET 64
279#define PRESERVED_S1_OFFSET 68
280#define PRESERVED_S2_OFFSET 72
281#define PRESERVED_RETURN_ADDRESS_OFFSET 76
282#define THUNK_RETURN_ADDRESS_OFFSET 80
283#define REGISTER_FILE_OFFSET 84
284#define CALLFRAME_OFFSET 88
285#define EXCEPTION_OFFSET 92
286#define ENABLE_PROFILER_REFERENCE_OFFSET 96
287#define GLOBAL_DATA_OFFSET 100
288#define STACK_LENGTH 104
289#elif CPU(SH4)
290#define SYMBOL_STRING(name) #name
291/* code (r4), RegisterFile* (r5), CallFrame* (r6), JSValue* exception (r7), Profiler**(sp), JSGlobalData (sp)*/
ba379fdc
A
292
293asm volatile (
f9bf01c6 294".text\n"
ba379fdc 295".globl " SYMBOL_STRING(ctiTrampoline) "\n"
f9bf01c6 296HIDE_SYMBOL(ctiTrampoline) "\n"
ba379fdc 297SYMBOL_STRING(ctiTrampoline) ":" "\n"
14957cd0
A
298 "mov.l r7, @-r15" "\n"
299 "mov.l r6, @-r15" "\n"
300 "mov.l r5, @-r15" "\n"
301 "mov.l r8, @-r15" "\n"
302 "mov #127, r8" "\n"
303 "mov.l r14, @-r15" "\n"
304 "sts.l pr, @-r15" "\n"
305 "mov.l r13, @-r15" "\n"
306 "mov.l r11, @-r15" "\n"
307 "mov.l r10, @-r15" "\n"
308 "add #-60, r15" "\n"
309 "mov r6, r14" "\n"
310 "jsr @r4" "\n"
311 "nop" "\n"
312 "add #60, r15" "\n"
313 "mov.l @r15+,r10" "\n"
314 "mov.l @r15+,r11" "\n"
315 "mov.l @r15+,r13" "\n"
316 "lds.l @r15+,pr" "\n"
317 "mov.l @r15+,r14" "\n"
318 "mov.l @r15+,r8" "\n"
319 "add #12, r15" "\n"
320 "rts" "\n"
321 "nop" "\n"
ba379fdc
A
322);
323
324asm volatile (
325".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
f9bf01c6 326HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
ba379fdc 327SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
14957cd0
A
328 "mov.l .L2"SYMBOL_STRING(cti_vm_throw)",r0" "\n"
329 "mov r15, r4" "\n"
330 "mov.l @(r0,r12),r11" "\n"
331 "jsr @r11" "\n"
332 "nop" "\n"
333 "add #60, r15" "\n"
334 "mov.l @r15+,r10" "\n"
335 "mov.l @r15+,r11" "\n"
336 "mov.l @r15+,r13" "\n"
337 "lds.l @r15+,pr" "\n"
338 "mov.l @r15+,r14" "\n"
339 "mov.l @r15+,r8" "\n"
340 "add #12, r15" "\n"
341 "rts" "\n"
342 "nop" "\n"
343 ".align 2" "\n"
344 ".L2"SYMBOL_STRING(cti_vm_throw)":.long " SYMBOL_STRING(cti_vm_throw)"@GOT \n"
ba379fdc 345);
14957cd0 346
ba379fdc
A
347asm volatile (
348".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
f9bf01c6 349HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
ba379fdc 350SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
14957cd0
A
351 "add #60, r15" "\n"
352 "mov.l @r15+,r10" "\n"
353 "mov.l @r15+,r11" "\n"
354 "mov.l @r15+,r13" "\n"
355 "lds.l @r15+,pr" "\n"
356 "mov.l @r15+,r14" "\n"
357 "mov.l @r15+,r8" "\n"
358 "add #12, r15" "\n"
359 "rts" "\n"
360 "nop" "\n"
ba379fdc 361);
14957cd0
A
362#else
363 #error "JIT not supported on this platform."
ba379fdc
A
364#endif
365
14957cd0
A
366#else // USE(JSVALUE32_64)
367
368#if COMPILER(GCC) && CPU(X86_64)
369
ba379fdc
A
370// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
371// need to change the assembly trampolines below to match.
f9bf01c6
A
372COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
373COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline);
374COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
ba379fdc 375
14957cd0 376asm (
f9bf01c6 377".text\n"
ba379fdc 378".globl " SYMBOL_STRING(ctiTrampoline) "\n"
f9bf01c6 379HIDE_SYMBOL(ctiTrampoline) "\n"
ba379fdc
A
380SYMBOL_STRING(ctiTrampoline) ":" "\n"
381 "pushq %rbp" "\n"
382 "movq %rsp, %rbp" "\n"
383 "pushq %r12" "\n"
384 "pushq %r13" "\n"
385 "pushq %r14" "\n"
386 "pushq %r15" "\n"
387 "pushq %rbx" "\n"
f9bf01c6
A
388 // Form the JIT stubs area
389 "pushq %r9" "\n"
390 "pushq %r8" "\n"
391 "pushq %rcx" "\n"
392 "pushq %rdx" "\n"
393 "pushq %rsi" "\n"
394 "pushq %rdi" "\n"
ba379fdc
A
395 "subq $0x48, %rsp" "\n"
396 "movq $512, %r12" "\n"
397 "movq $0xFFFF000000000000, %r14" "\n"
398 "movq $0xFFFF000000000002, %r15" "\n"
f9bf01c6
A
399 "movq %rdx, %r13" "\n"
400 "call *%rdi" "\n"
401 "addq $0x78, %rsp" "\n"
ba379fdc
A
402 "popq %rbx" "\n"
403 "popq %r15" "\n"
404 "popq %r14" "\n"
405 "popq %r13" "\n"
406 "popq %r12" "\n"
407 "popq %rbp" "\n"
408 "ret" "\n"
6fe7ccc8
A
409".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
410HIDE_SYMBOL(ctiTrampolineEnd) "\n"
411SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
ba379fdc
A
412);
413
14957cd0 414asm (
ba379fdc 415".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
f9bf01c6 416HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
ba379fdc
A
417SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
418 "movq %rsp, %rdi" "\n"
f9bf01c6 419 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
14957cd0 420 "int3" "\n"
ba379fdc
A
421);
422
14957cd0 423asm (
ba379fdc 424".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
f9bf01c6 425HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
ba379fdc 426SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
f9bf01c6 427 "addq $0x78, %rsp" "\n"
ba379fdc
A
428 "popq %rbx" "\n"
429 "popq %r15" "\n"
430 "popq %r14" "\n"
431 "popq %r13" "\n"
432 "popq %r12" "\n"
433 "popq %rbp" "\n"
434 "ret" "\n"
435);
436
14957cd0
A
437#else
438 #error "JIT not supported on this platform."
ba379fdc
A
439#endif
440
14957cd0 441#endif // USE(JSVALUE32_64)
4e4e5a6f 442
14957cd0
A
443#if CPU(MIPS)
444asm (
ba379fdc
A
445".text" "\n"
446".align 2" "\n"
4e4e5a6f
A
447".set noreorder" "\n"
448".set nomacro" "\n"
449".set nomips16" "\n"
ba379fdc 450".globl " SYMBOL_STRING(ctiTrampoline) "\n"
4e4e5a6f 451".ent " SYMBOL_STRING(ctiTrampoline) "\n"
ba379fdc 452SYMBOL_STRING(ctiTrampoline) ":" "\n"
14957cd0
A
453 "addiu $29,$29,-" STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
454 "sw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
455 "sw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
456 "sw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
457 "sw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
4e4e5a6f 458#if WTF_MIPS_PIC
14957cd0 459 "sw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n"
4e4e5a6f
A
460#endif
461 "move $16,$6 # set callFrameRegister" "\n"
462 "li $17,512 # set timeoutCheckRegister" "\n"
463 "move $25,$4 # move executableAddress to t9" "\n"
14957cd0
A
464 "sw $5," STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "($29) # store registerFile to current stack" "\n"
465 "sw $6," STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "($29) # store callFrame to curent stack" "\n"
466 "sw $7," STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "($29) # store exception to current stack" "\n"
467 "lw $8," STRINGIZE_VALUE_OF(STACK_LENGTH + 16) "($29) # load enableProfilerReference from previous stack" "\n"
468 "lw $9," STRINGIZE_VALUE_OF(STACK_LENGTH + 20) "($29) # load globalData from previous stack" "\n"
469 "sw $8," STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "($29) # store enableProfilerReference to current stack" "\n"
4e4e5a6f 470 "jalr $25" "\n"
14957cd0
A
471 "sw $9," STRINGIZE_VALUE_OF(GLOBAL_DATA_OFFSET) "($29) # store globalData to current stack" "\n"
472 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
473 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
474 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
475 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
4e4e5a6f 476 "jr $31" "\n"
14957cd0 477 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
4e4e5a6f
A
478".set reorder" "\n"
479".set macro" "\n"
480".end " SYMBOL_STRING(ctiTrampoline) "\n"
ba379fdc
A
481);
482
14957cd0 483asm (
ba379fdc
A
484".text" "\n"
485".align 2" "\n"
4e4e5a6f
A
486".set noreorder" "\n"
487".set nomacro" "\n"
488".set nomips16" "\n"
ba379fdc 489".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
4e4e5a6f 490".ent " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
ba379fdc 491SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
4e4e5a6f 492#if WTF_MIPS_PIC
14957cd0 493 "lw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n"
4e4e5a6f
A
494".set macro" "\n"
495 "la $25," SYMBOL_STRING(cti_vm_throw) "\n"
496".set nomacro" "\n"
497 "bal " SYMBOL_STRING(cti_vm_throw) "\n"
498 "move $4,$29" "\n"
499#else
500 "jal " SYMBOL_STRING(cti_vm_throw) "\n"
501 "move $4,$29" "\n"
502#endif
14957cd0
A
503 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
504 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
505 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
506 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
4e4e5a6f 507 "jr $31" "\n"
14957cd0 508 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
4e4e5a6f
A
509".set reorder" "\n"
510".set macro" "\n"
511".end " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
ba379fdc
A
512);
513
14957cd0 514asm (
ba379fdc
A
515".text" "\n"
516".align 2" "\n"
4e4e5a6f
A
517".set noreorder" "\n"
518".set nomacro" "\n"
519".set nomips16" "\n"
ba379fdc 520".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
4e4e5a6f 521".ent " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
ba379fdc 522SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
14957cd0
A
523 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
524 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
525 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
526 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
4e4e5a6f 527 "jr $31" "\n"
14957cd0 528 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
4e4e5a6f
A
529".set reorder" "\n"
530".set macro" "\n"
531".end " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
f9bf01c6 532);
f9bf01c6 533#endif
ba379fdc 534
4e4e5a6f
A
535#if COMPILER(GCC) && CPU(ARM_THUMB2)
536
14957cd0 537asm (
4e4e5a6f
A
538".text" "\n"
539".align 2" "\n"
540".globl " SYMBOL_STRING(ctiTrampoline) "\n"
541HIDE_SYMBOL(ctiTrampoline) "\n"
542".thumb" "\n"
543".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
544SYMBOL_STRING(ctiTrampoline) ":" "\n"
545 "sub sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
546 "str lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
547 "str r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
548 "str r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
549 "str r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
6fe7ccc8
A
550 "str r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n"
551 "str r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n"
552 "str r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n"
553 "str r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n"
554 "str r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n"
4e4e5a6f
A
555 "str r1, [sp, #" STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "]" "\n"
556 "str r2, [sp, #" STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "]" "\n"
557 "str r3, [sp, #" STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "]" "\n"
6fe7ccc8 558 "mov r5, r2" "\n"
4e4e5a6f
A
559 "mov r6, #512" "\n"
560 "blx r0" "\n"
6fe7ccc8
A
561 "ldr r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n"
562 "ldr r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n"
563 "ldr r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n"
564 "ldr r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n"
565 "ldr r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n"
4e4e5a6f
A
566 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
567 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
568 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
569 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
570 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
571 "bx lr" "\n"
6fe7ccc8
A
572".align 2" "\n"
573".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
574HIDE_SYMBOL(ctiTrampolineEnd) "\n"
575".thumb" "\n"
576".thumb_func " THUMB_FUNC_PARAM(ctiTrampolineEnd) "\n"
577SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
4e4e5a6f
A
578);
579
14957cd0 580asm (
4e4e5a6f
A
581".text" "\n"
582".align 2" "\n"
583".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
584HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
585".thumb" "\n"
586".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
587SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
6fe7ccc8 588 "mov r0, sp" "\n"
4e4e5a6f 589 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
6fe7ccc8
A
590 "ldr r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n"
591 "ldr r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n"
592 "ldr r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n"
593 "ldr r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n"
594 "ldr r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n"
4e4e5a6f
A
595 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
596 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
597 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
598 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
599 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
600 "bx lr" "\n"
601);
602
14957cd0 603asm (
4e4e5a6f
A
604".text" "\n"
605".align 2" "\n"
606".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
607HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
608".thumb" "\n"
609".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
610SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
6fe7ccc8
A
611 "ldr r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n"
612 "ldr r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n"
613 "ldr r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n"
614 "ldr r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n"
615 "ldr r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n"
4e4e5a6f
A
616 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
617 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
618 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
619 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
620 "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
621 "bx lr" "\n"
622);
623
624#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
625
14957cd0 626asm (
4e4e5a6f
A
627".globl " SYMBOL_STRING(ctiTrampoline) "\n"
628HIDE_SYMBOL(ctiTrampoline) "\n"
629SYMBOL_STRING(ctiTrampoline) ":" "\n"
630 "stmdb sp!, {r1-r3}" "\n"
631 "stmdb sp!, {r4-r8, lr}" "\n"
632 "sub sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n"
633 "mov r4, r2" "\n"
634 "mov r5, #512" "\n"
635 // r0 contains the code
636 "mov lr, pc" "\n"
637 "mov pc, r0" "\n"
638 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n"
639 "ldmia sp!, {r4-r8, lr}" "\n"
640 "add sp, sp, #12" "\n"
641 "mov pc, lr" "\n"
642);
643
14957cd0 644asm (
4e4e5a6f
A
645".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
646HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
647SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
648 "mov r0, sp" "\n"
649 "bl " SYMBOL_STRING(cti_vm_throw) "\n"
650
651// Both has the same return sequence
652".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
653HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
654SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
655 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n"
656 "ldmia sp!, {r4-r8, lr}" "\n"
657 "add sp, sp, #12" "\n"
658 "mov pc, lr" "\n"
659);
660
14957cd0
A
661#elif COMPILER(RVCT) && CPU(ARM_THUMB2)
662
663__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*)
664{
665 PRESERVE8
666 sub sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
667 str lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
668 str r4, [sp, # PRESERVED_R4_OFFSET ]
669 str r5, [sp, # PRESERVED_R5_OFFSET ]
670 str r6, [sp, # PRESERVED_R6_OFFSET ]
6fe7ccc8
A
671 str r7, [sp, # PRESERVED_R7_OFFSET ]
672 str r8, [sp, # PRESERVED_R8_OFFSET ]
673 str r9, [sp, # PRESERVED_R9_OFFSET ]
674 str r10, [sp, # PRESERVED_R10_OFFSET ]
675 str r11, [sp, # PRESERVED_R11_OFFSET ]
14957cd0
A
676 str r1, [sp, # REGISTER_FILE_OFFSET ]
677 str r2, [sp, # CALLFRAME_OFFSET ]
678 str r3, [sp, # EXCEPTION_OFFSET ]
6fe7ccc8 679 mov r5, r2
14957cd0
A
680 mov r6, #512
681 blx r0
6fe7ccc8
A
682 ldr r11, [sp, # PRESERVED_R11_OFFSET ]
683 ldr r10, [sp, # PRESERVED_R10_OFFSET ]
684 ldr r9, [sp, # PRESERVED_R9_OFFSET ]
685 ldr r8, [sp, # PRESERVED_R8_OFFSET ]
686 ldr r7, [sp, # PRESERVED_R7_OFFSET ]
14957cd0
A
687 ldr r6, [sp, # PRESERVED_R6_OFFSET ]
688 ldr r5, [sp, # PRESERVED_R5_OFFSET ]
689 ldr r4, [sp, # PRESERVED_R4_OFFSET ]
690 ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
691 add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
692 bx lr
693}
694
695__asm void ctiVMThrowTrampoline()
696{
697 PRESERVE8
6fe7ccc8 698 mov r0, sp
14957cd0 699 bl cti_vm_throw
6fe7ccc8
A
700 ldr r11, [sp, # PRESERVED_R11_OFFSET ]
701 ldr r10, [sp, # PRESERVED_R10_OFFSET ]
702 ldr r9, [sp, # PRESERVED_R9_OFFSET ]
703 ldr r8, [sp, # PRESERVED_R8_OFFSET ]
704 ldr r7, [sp, # PRESERVED_R7_OFFSET ]
705 ldr r6, [sp, # PRESERVED_R6_OFFSET ]
14957cd0
A
706 ldr r6, [sp, # PRESERVED_R6_OFFSET ]
707 ldr r5, [sp, # PRESERVED_R5_OFFSET ]
708 ldr r4, [sp, # PRESERVED_R4_OFFSET ]
709 ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
710 add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
711 bx lr
712}
713
714__asm void ctiOpThrowNotCaught()
715{
716 PRESERVE8
6fe7ccc8
A
717 ldr r11, [sp, # PRESERVED_R11_OFFSET ]
718 ldr r10, [sp, # PRESERVED_R10_OFFSET ]
719 ldr r9, [sp, # PRESERVED_R9_OFFSET ]
720 ldr r8, [sp, # PRESERVED_R8_OFFSET ]
721 ldr r7, [sp, # PRESERVED_R7_OFFSET ]
722 ldr r6, [sp, # PRESERVED_R6_OFFSET ]
14957cd0
A
723 ldr r6, [sp, # PRESERVED_R6_OFFSET ]
724 ldr r5, [sp, # PRESERVED_R5_OFFSET ]
725 ldr r4, [sp, # PRESERVED_R4_OFFSET ]
726 ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
727 add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
728 bx lr
729}
730
731#elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
732
733__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
734{
735 ARM
736 stmdb sp!, {r1-r3}
737 stmdb sp!, {r4-r8, lr}
738 sub sp, sp, # PRESERVEDR4_OFFSET
739 mov r4, r2
740 mov r5, #512
741 mov lr, pc
742 bx r0
743 add sp, sp, # PRESERVEDR4_OFFSET
744 ldmia sp!, {r4-r8, lr}
745 add sp, sp, #12
746 bx lr
747}
748
749__asm void ctiVMThrowTrampoline()
750{
751 ARM
752 PRESERVE8
753 mov r0, sp
754 bl cti_vm_throw
755 add sp, sp, # PRESERVEDR4_OFFSET
756 ldmia sp!, {r4-r8, lr}
757 add sp, sp, #12
758 bx lr
759}
760
761__asm void ctiOpThrowNotCaught()
762{
763 ARM
764 add sp, sp, # PRESERVEDR4_OFFSET
765 ldmia sp!, {r4-r8, lr}
766 add sp, sp, #12
767 bx lr
768}
4e4e5a6f
A
769#endif
770
ba379fdc
A
771#if ENABLE(OPCODE_SAMPLING)
772 #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler()
773#else
774 #define CTI_SAMPLER 0
775#endif
776
777JITThunks::JITThunks(JSGlobalData* globalData)
14957cd0 778 : m_hostFunctionStubMap(adoptPtr(new HostFunctionStubMap))
ba379fdc 779{
6fe7ccc8 780 if (!globalData->canUseJIT())
14957cd0 781 return;
ba379fdc 782
6fe7ccc8
A
783 m_executableMemory = JIT::compileCTIMachineTrampolines(globalData, &m_trampolineStructure);
784 ASSERT(!!m_executableMemory);
f9bf01c6 785#if CPU(ARM_THUMB2)
ba379fdc
A
786 // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
787 // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
788 // macros.
4e4e5a6f
A
789 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET);
790 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVED_R4_OFFSET);
791 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == PRESERVED_R5_OFFSET);
792 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == PRESERVED_R6_OFFSET);
6fe7ccc8
A
793 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR7) == PRESERVED_R7_OFFSET);
794 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR8) == PRESERVED_R8_OFFSET);
795 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR9) == PRESERVED_R9_OFFSET);
796 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR10) == PRESERVED_R10_OFFSET);
797 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR11) == PRESERVED_R11_OFFSET);
4e4e5a6f
A
798
799 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET);
800 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET);
ba379fdc 801 // The fifth argument is the first item already on the stack.
4e4e5a6f
A
802 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET);
803
804 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
805
806#elif CPU(ARM_TRADITIONAL)
807
808 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
809 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVEDR4_OFFSET);
810
811
812#elif CPU(MIPS)
14957cd0
A
813 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedGP) == PRESERVED_GP_OFFSET);
814 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS0) == PRESERVED_S0_OFFSET);
815 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS1) == PRESERVED_S1_OFFSET);
816 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS2) == PRESERVED_S2_OFFSET);
817 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET);
818 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
819 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET);
820 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET);
821 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, unused1) == EXCEPTION_OFFSET);
822 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET);
823 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, globalData) == GLOBAL_DATA_OFFSET);
ba379fdc 824
ba379fdc
A
825#endif
826}
827
4e4e5a6f
A
828JITThunks::~JITThunks()
829{
830}
831
4e4e5a6f 832NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct)
ba379fdc
A
833{
834 // The interpreter checks for recursion here; I do not believe this can occur in CTI.
835
836 if (!baseValue.isCell())
837 return;
838
839 // Uncacheable: give up.
840 if (!slot.isCacheable()) {
4e4e5a6f 841 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
ba379fdc
A
842 return;
843 }
844
14957cd0 845 JSCell* baseCell = baseValue.asCell();
ba379fdc
A
846 Structure* structure = baseCell->structure();
847
14957cd0 848 if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
4e4e5a6f 849 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
ba379fdc
A
850 return;
851 }
852
853 // If baseCell != base, then baseCell must be a proxy for another object.
854 if (baseCell != slot.base()) {
4e4e5a6f 855 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
ba379fdc
A
856 return;
857 }
858
ba379fdc
A
859 // Cache hit: Specialize instruction and ref Structures.
860
861 // Structure transition, cache transition info
862 if (slot.type() == PutPropertySlot::NewProperty) {
f9bf01c6 863 if (structure->isDictionary()) {
4e4e5a6f 864 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
ba379fdc
A
865 return;
866 }
f9bf01c6
A
867
868 // put_by_id_transition checks the prototype chain for setters.
869 normalizePrototypeChain(callFrame, baseCell);
870
871 StructureChain* prototypeChain = structure->prototypeChain(callFrame);
6fe7ccc8 872 stubInfo->initPutByIdTransition(callFrame->globalData(), codeBlock->ownerExecutable(), structure->previousID(), structure, prototypeChain, direct);
4e4e5a6f 873 JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct);
ba379fdc
A
874 return;
875 }
876
14957cd0 877 stubInfo->initPutByIdReplace(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
ba379fdc 878
4e4e5a6f 879 JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct);
ba379fdc
A
880}
881
f9bf01c6 882NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
ba379fdc
A
883{
884 // FIXME: Write a test that proves we need to check for recursion here just
885 // like the interpreter does, then add a check for recursion.
886
887 // FIXME: Cache property access for immediates.
888 if (!baseValue.isCell()) {
889 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
890 return;
891 }
892
893 JSGlobalData* globalData = &callFrame->globalData();
894
6fe7ccc8 895 if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
ba379fdc
A
896 JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
897 return;
898 }
899
6fe7ccc8 900 if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
ba379fdc
A
901 // The tradeoff of compiling an patched inline string length access routine does not seem
902 // to pay off, so we currently only do this for arrays.
4e4e5a6f 903 ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs->ctiStringLengthTrampoline());
ba379fdc
A
904 return;
905 }
906
907 // Uncacheable: give up.
908 if (!slot.isCacheable()) {
909 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
910 return;
911 }
912
14957cd0 913 JSCell* baseCell = baseValue.asCell();
ba379fdc
A
914 Structure* structure = baseCell->structure();
915
14957cd0 916 if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
ba379fdc
A
917 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
918 return;
919 }
920
ba379fdc
A
921 // Cache hit: Specialize instruction and ref Structures.
922
923 if (slot.slotBase() == baseValue) {
924 // set this up, so derefStructures can do it's job.
14957cd0
A
925 stubInfo->initGetByIdSelf(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
926 if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset))
4e4e5a6f
A
927 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
928 else
929 JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
ba379fdc
A
930 return;
931 }
932
933 if (structure->isDictionary()) {
934 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
935 return;
936 }
937
938 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
939 ASSERT(slot.slotBase().isObject());
940
941 JSObject* slotBaseObject = asObject(slot.slotBase());
942 size_t offset = slot.cachedOffset();
943
944 // Since we're accessing a prototype in a loop, it's a good bet that it
945 // should not be treated as a dictionary.
946 if (slotBaseObject->structure()->isDictionary()) {
14957cd0
A
947 slotBaseObject->flattenDictionaryObject(callFrame->globalData());
948 offset = slotBaseObject->structure()->get(callFrame->globalData(), propertyName);
ba379fdc
A
949 }
950
14957cd0 951 stubInfo->initGetByIdProto(callFrame->globalData(), codeBlock->ownerExecutable(), structure, slotBaseObject->structure());
ba379fdc 952
f9bf01c6
A
953 ASSERT(!structure->isDictionary());
954 ASSERT(!slotBaseObject->structure()->isDictionary());
4e4e5a6f 955 JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), propertyName, slot, offset, returnAddress);
ba379fdc
A
956 return;
957 }
958
959 size_t offset = slot.cachedOffset();
960 size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
961 if (!count) {
f9bf01c6 962 stubInfo->accessType = access_get_by_id_generic;
ba379fdc
A
963 return;
964 }
965
966 StructureChain* prototypeChain = structure->prototypeChain(callFrame);
14957cd0 967 stubInfo->initGetByIdChain(callFrame->globalData(), codeBlock->ownerExecutable(), structure, prototypeChain);
4e4e5a6f 968 JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
ba379fdc
A
969}
970
6fe7ccc8 971#if !defined(NDEBUG)
ba379fdc
A
972
973extern "C" {
974
975static void jscGeneratedNativeCode()
976{
977 // When executing a JIT stub function (which might do an allocation), we hack the return address
978 // to pretend to be executing this function, to keep stack logging tools from blowing out
979 // memory.
980}
981
982}
983
984struct StackHack {
985 ALWAYS_INLINE StackHack(JITStackFrame& stackFrame)
986 : stackFrame(stackFrame)
987 , savedReturnAddress(*stackFrame.returnAddressSlot())
988 {
6fe7ccc8
A
989 if (!CodeProfiling::enabled())
990 *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
ba379fdc
A
991 }
992
993 ALWAYS_INLINE ~StackHack()
994 {
995 *stackFrame.returnAddressSlot() = savedReturnAddress;
996 }
997
998 JITStackFrame& stackFrame;
999 ReturnAddressPtr savedReturnAddress;
1000};
1001
14957cd0 1002#define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
ba379fdc
A
1003#define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
1004#define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
1005
1006#else
1007
14957cd0 1008#define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS)
ba379fdc
A
1009#define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
1010#define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
1011
1012#endif
1013
1014// The reason this is not inlined is to avoid having to do a PIC branch
1015// to get the address of the ctiVMThrowTrampoline function. It's also
1016// good to keep the code size down by leaving as much of the exception
1017// handling code out of line as possible.
1018static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
1019{
1020 ASSERT(globalData->exception);
1021 globalData->exceptionLocation = exceptionLocation;
1022 returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline));
1023}
1024
ba379fdc
A
1025#define VM_THROW_EXCEPTION() \
1026 do { \
1027 VM_THROW_EXCEPTION_AT_END(); \
1028 return 0; \
1029 } while (0)
1030#define VM_THROW_EXCEPTION_AT_END() \
14957cd0
A
1031 do {\
1032 returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\
1033 } while (0)
ba379fdc
A
1034
1035#define CHECK_FOR_EXCEPTION() \
1036 do { \
1037 if (UNLIKELY(stackFrame.globalData->exception)) \
1038 VM_THROW_EXCEPTION(); \
1039 } while (0)
1040#define CHECK_FOR_EXCEPTION_AT_END() \
1041 do { \
1042 if (UNLIKELY(stackFrame.globalData->exception)) \
1043 VM_THROW_EXCEPTION_AT_END(); \
1044 } while (0)
1045#define CHECK_FOR_EXCEPTION_VOID() \
1046 do { \
1047 if (UNLIKELY(stackFrame.globalData->exception)) { \
1048 VM_THROW_EXCEPTION_AT_END(); \
1049 return; \
1050 } \
1051 } while (0)
1052
6fe7ccc8
A
1053// Helper function for JIT stubs that may throw an exception in the middle of
1054// processing a function call. This function rolls back the register file to
1055// our caller, so exception processing can proceed from a valid state.
1056template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot)
14957cd0 1057{
6fe7ccc8
A
1058 CallFrame* callFrame = newCallFrame->callerFrame();
1059 ASSERT(callFrame->globalData().exception);
1060 jitStackFrame.callFrame = callFrame;
1061 callFrame->globalData().topCallFrame = callFrame;
1062 returnToThrowTrampoline(&callFrame->globalData(), ReturnAddressPtr(newCallFrame->returnPC()), returnAddressSlot);
1063 return T();
1064}
14957cd0 1065
6fe7ccc8
A
1066template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot, JSValue exception)
1067{
1068 newCallFrame->callerFrame()->globalData().exception = exception;
1069 return throwExceptionFromOpCall<T>(jitStackFrame, newCallFrame, returnAddressSlot);
14957cd0
A
1070}
1071
1072#if CPU(ARM_THUMB2) && COMPILER(GCC)
ba379fdc
A
1073
1074#define DEFINE_STUB_FUNCTION(rtype, op) \
1075 extern "C" { \
1076 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1077 }; \
14957cd0 1078 asm ( \
ba379fdc
A
1079 ".text" "\n" \
1080 ".align 2" "\n" \
1081 ".globl " SYMBOL_STRING(cti_##op) "\n" \
f9bf01c6 1082 HIDE_SYMBOL(cti_##op) "\n" \
ba379fdc 1083 ".thumb" "\n" \
f9bf01c6 1084 ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \
ba379fdc 1085 SYMBOL_STRING(cti_##op) ":" "\n" \
4e4e5a6f 1086 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
ba379fdc 1087 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
4e4e5a6f 1088 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
ba379fdc
A
1089 "bx lr" "\n" \
1090 ); \
1091 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \
1092
4e4e5a6f
A
1093#elif CPU(MIPS)
1094#if WTF_MIPS_PIC
1095#define DEFINE_STUB_FUNCTION(rtype, op) \
1096 extern "C" { \
1097 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1098 }; \
14957cd0 1099 asm ( \
4e4e5a6f
A
1100 ".text" "\n" \
1101 ".align 2" "\n" \
1102 ".set noreorder" "\n" \
1103 ".set nomacro" "\n" \
1104 ".set nomips16" "\n" \
1105 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1106 ".ent " SYMBOL_STRING(cti_##op) "\n" \
1107 SYMBOL_STRING(cti_##op) ":" "\n" \
14957cd0
A
1108 "lw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n" \
1109 "sw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
4e4e5a6f
A
1110 ".set macro" "\n" \
1111 "la $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \
1112 ".set nomacro" "\n" \
6fe7ccc8
A
1113 ".reloc 1f,R_MIPS_JALR," SYMBOL_STRING(JITStubThunked_##op) "\n" \
1114 "1: jalr $25" "\n" \
4e4e5a6f 1115 "nop" "\n" \
14957cd0 1116 "lw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
4e4e5a6f
A
1117 "jr $31" "\n" \
1118 "nop" "\n" \
1119 ".set reorder" "\n" \
1120 ".set macro" "\n" \
1121 ".end " SYMBOL_STRING(cti_##op) "\n" \
1122 ); \
1123 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1124
1125#else // WTF_MIPS_PIC
1126#define DEFINE_STUB_FUNCTION(rtype, op) \
1127 extern "C" { \
1128 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1129 }; \
14957cd0 1130 asm ( \
4e4e5a6f
A
1131 ".text" "\n" \
1132 ".align 2" "\n" \
1133 ".set noreorder" "\n" \
1134 ".set nomacro" "\n" \
1135 ".set nomips16" "\n" \
1136 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1137 ".ent " SYMBOL_STRING(cti_##op) "\n" \
1138 SYMBOL_STRING(cti_##op) ":" "\n" \
14957cd0 1139 "sw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
4e4e5a6f
A
1140 "jal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1141 "nop" "\n" \
14957cd0 1142 "lw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
4e4e5a6f
A
1143 "jr $31" "\n" \
1144 "nop" "\n" \
1145 ".set reorder" "\n" \
1146 ".set macro" "\n" \
1147 ".end " SYMBOL_STRING(cti_##op) "\n" \
1148 ); \
1149 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
f9bf01c6 1150
f9bf01c6
A
1151#endif
1152
4e4e5a6f 1153#elif CPU(ARM_TRADITIONAL) && COMPILER(GCC)
f9bf01c6
A
1154
1155#define DEFINE_STUB_FUNCTION(rtype, op) \
1156 extern "C" { \
1157 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1158 }; \
14957cd0 1159 asm ( \
f9bf01c6
A
1160 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1161 SYMBOL_STRING(cti_##op) ":" "\n" \
1162 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1163 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \
1164 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
1165 "mov pc, lr" "\n" \
1166 ); \
1167 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1168
14957cd0 1169#elif (CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)) && COMPILER(RVCT)
f9bf01c6
A
1170
1171#define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1172
1173/* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */
1174
1175/* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */
1176/* The pattern "#xxx#" will be replaced with "xxx" */
1177
1178/*
1179RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
1180RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
1181RVCT({)
14957cd0 1182RVCT( PRESERVE8)
f9bf01c6 1183RVCT( IMPORT JITStubThunked_#op#)
14957cd0 1184RVCT( str lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
f9bf01c6 1185RVCT( bl JITStubThunked_#op#)
14957cd0 1186RVCT( ldr lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
f9bf01c6
A
1187RVCT( bx lr)
1188RVCT(})
1189RVCT()
1190*/
1191
1192/* Include the generated file */
1193#include "GeneratedJITStubs_RVCT.h"
1194
14957cd0
A
1195#elif CPU(ARM_TRADITIONAL) && COMPILER(MSVC)
1196
1197#define DEFINE_STUB_FUNCTION(rtype, op) extern "C" rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
1198
1199/* The following is a workaround for MSVC toolchain; inline assembler is not supported */
1200
1201/* The following section is a template to generate code for GeneratedJITStubs_MSVC.asm */
1202/* The pattern "#xxx#" will be replaced with "xxx" */
1203
1204/*
1205MSVC_BEGIN( AREA Trampoline, CODE)
1206MSVC_BEGIN()
1207MSVC_BEGIN( EXPORT ctiTrampoline)
1208MSVC_BEGIN( EXPORT ctiVMThrowTrampoline)
1209MSVC_BEGIN( EXPORT ctiOpThrowNotCaught)
1210MSVC_BEGIN()
1211MSVC_BEGIN(ctiTrampoline PROC)
1212MSVC_BEGIN( stmdb sp!, {r1-r3})
1213MSVC_BEGIN( stmdb sp!, {r4-r8, lr})
1214MSVC_BEGIN( sub sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1215MSVC_BEGIN( mov r4, r2)
1216MSVC_BEGIN( mov r5, #512)
1217MSVC_BEGIN( ; r0 contains the code)
1218MSVC_BEGIN( mov lr, pc)
1219MSVC_BEGIN( bx r0)
1220MSVC_BEGIN( add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1221MSVC_BEGIN( ldmia sp!, {r4-r8, lr})
1222MSVC_BEGIN( add sp, sp, #12)
1223MSVC_BEGIN( bx lr)
1224MSVC_BEGIN(ctiTrampoline ENDP)
1225MSVC_BEGIN()
1226MSVC_BEGIN(ctiVMThrowTrampoline PROC)
1227MSVC_BEGIN( mov r0, sp)
1228MSVC_BEGIN( mov lr, pc)
1229MSVC_BEGIN( bl cti_vm_throw)
1230MSVC_BEGIN(ctiOpThrowNotCaught)
1231MSVC_BEGIN( add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
1232MSVC_BEGIN( ldmia sp!, {r4-r8, lr})
1233MSVC_BEGIN( add sp, sp, #12)
1234MSVC_BEGIN( bx lr)
1235MSVC_BEGIN(ctiVMThrowTrampoline ENDP)
1236MSVC_BEGIN()
1237
1238MSVC( EXPORT cti_#op#)
1239MSVC( IMPORT JITStubThunked_#op#)
1240MSVC(cti_#op# PROC)
1241MSVC( str lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET)
1242MSVC( bl JITStubThunked_#op#)
1243MSVC( ldr lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET)
1244MSVC( bx lr)
1245MSVC(cti_#op# ENDP)
1246MSVC()
1247
1248MSVC_END( END)
1249*/
1250
1251#elif CPU(SH4)
1252#define DEFINE_STUB_FUNCTION(rtype, op) \
1253 extern "C" { \
1254 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
1255 }; \
1256 asm volatile( \
1257 ".align 2" "\n" \
1258 ".globl " SYMBOL_STRING(cti_##op) "\n" \
1259 SYMBOL_STRING(cti_##op) ":" "\n" \
1260 "sts pr, r11" "\n" \
1261 "mov.l r11, @(0x38, r15)" "\n" \
1262 "mov.l .L2"SYMBOL_STRING(JITStubThunked_##op)",r0" "\n" \
1263 "mov.l @(r0,r12),r11" "\n" \
1264 "jsr @r11" "\n" \
1265 "nop" "\n" \
1266 "mov.l @(0x38, r15), r11 " "\n" \
1267 "lds r11, pr " "\n" \
1268 "rts" "\n" \
1269 "nop" "\n" \
1270 ".align 2" "\n" \
1271 ".L2"SYMBOL_STRING(JITStubThunked_##op)":.long " SYMBOL_STRING(JITStubThunked_##op)"@GOT \n" \
1272 ); \
1273 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
ba379fdc
A
1274#else
1275#define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
1276#endif
1277
14957cd0
A
1278DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_this)
1279{
1280 STUB_INIT_STACK_FRAME(stackFrame);
1281 CallFrame* callFrame = stackFrame.callFrame;
1282
6fe7ccc8 1283 JSFunction* constructor = jsCast<JSFunction*>(callFrame->callee());
14957cd0
A
1284#if !ASSERT_DISABLED
1285 ConstructData constructData;
6fe7ccc8 1286 ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
14957cd0
A
1287#endif
1288
1289 Structure* structure;
1290 JSValue proto = stackFrame.args[0].jsValue();
1291 if (proto.isObject())
1292 structure = asObject(proto)->inheritorID(*stackFrame.globalData);
1293 else
1294 structure = constructor->scope()->globalObject->emptyObjectStructure();
1295 JSValue result = constructEmptyObject(callFrame, structure);
1296
1297 return JSValue::encode(result);
1298}
1299
ba379fdc
A
1300DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this)
1301{
1302 STUB_INIT_STACK_FRAME(stackFrame);
1303
1304 JSValue v1 = stackFrame.args[0].jsValue();
1305 CallFrame* callFrame = stackFrame.callFrame;
1306
6fe7ccc8 1307 ASSERT(v1.isPrimitive());
ba379fdc 1308
6fe7ccc8 1309 JSObject* result = v1.toThisObject(callFrame);
14957cd0
A
1310 CHECK_FOR_EXCEPTION_AT_END();
1311 return JSValue::encode(result);
ba379fdc
A
1312}
1313
1314DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
1315{
1316 STUB_INIT_STACK_FRAME(stackFrame);
1317
1318 JSValue v1 = stackFrame.args[0].jsValue();
1319 JSValue v2 = stackFrame.args[1].jsValue();
ba379fdc
A
1320 CallFrame* callFrame = stackFrame.callFrame;
1321
6fe7ccc8
A
1322 if (v1.isString() && !v2.isObject()) {
1323 JSValue result = jsString(callFrame, asString(v1), v2.toString(callFrame));
f9bf01c6
A
1324 CHECK_FOR_EXCEPTION_AT_END();
1325 return JSValue::encode(result);
ba379fdc
A
1326 }
1327
6fe7ccc8
A
1328 if (v1.isNumber() && v2.isNumber())
1329 return JSValue::encode(jsNumber(v1.asNumber() + v2.asNumber()));
ba379fdc
A
1330
1331 // All other cases are pretty uncommon
1332 JSValue result = jsAddSlowCase(callFrame, v1, v2);
1333 CHECK_FOR_EXCEPTION_AT_END();
1334 return JSValue::encode(result);
1335}
1336
1337DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_inc)
1338{
1339 STUB_INIT_STACK_FRAME(stackFrame);
1340
1341 JSValue v = stackFrame.args[0].jsValue();
1342
1343 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 1344 JSValue result = jsNumber(v.toNumber(callFrame) + 1);
ba379fdc
A
1345 CHECK_FOR_EXCEPTION_AT_END();
1346 return JSValue::encode(result);
1347}
1348
1349DEFINE_STUB_FUNCTION(int, timeout_check)
1350{
1351 STUB_INIT_STACK_FRAME(stackFrame);
4e4e5a6f 1352
ba379fdc
A
1353 JSGlobalData* globalData = stackFrame.globalData;
1354 TimeoutChecker& timeoutChecker = globalData->timeoutChecker;
1355
4e4e5a6f
A
1356 if (globalData->terminator.shouldTerminate()) {
1357 globalData->exception = createTerminatedExecutionException(globalData);
1358 VM_THROW_EXCEPTION_AT_END();
1359 } else if (timeoutChecker.didTimeOut(stackFrame.callFrame)) {
ba379fdc
A
1360 globalData->exception = createInterruptedExecutionException(globalData);
1361 VM_THROW_EXCEPTION_AT_END();
1362 }
4e4e5a6f 1363
ba379fdc
A
1364 return timeoutChecker.ticksUntilNextCheck();
1365}
1366
14957cd0 1367DEFINE_STUB_FUNCTION(void*, register_file_check)
ba379fdc
A
1368{
1369 STUB_INIT_STACK_FRAME(stackFrame);
14957cd0 1370 CallFrame* callFrame = stackFrame.callFrame;
ba379fdc 1371
6fe7ccc8
A
1372 if (UNLIKELY(!stackFrame.registerFile->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters])))
1373 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
ba379fdc 1374
14957cd0 1375 return callFrame;
ba379fdc
A
1376}
1377
ba379fdc
A
1378DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
1379{
1380 STUB_INIT_STACK_FRAME(stackFrame);
1381
1382 return constructEmptyObject(stackFrame.callFrame);
1383}
1384
1385DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
1386{
1387 STUB_INIT_STACK_FRAME(stackFrame);
1388
14957cd0 1389 PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
ba379fdc
A
1390 stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
1391 CHECK_FOR_EXCEPTION_AT_END();
1392}
1393
4e4e5a6f
A
1394DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
1395{
1396 STUB_INIT_STACK_FRAME(stackFrame);
1397
14957cd0 1398 PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
6fe7ccc8
A
1399 JSValue baseValue = stackFrame.args[0].jsValue();
1400 ASSERT(baseValue.isObject());
1401 asObject(baseValue)->putDirect(stackFrame.callFrame->globalData(), stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
4e4e5a6f
A
1402 CHECK_FOR_EXCEPTION_AT_END();
1403}
1404
ba379fdc
A
1405DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
1406{
1407 STUB_INIT_STACK_FRAME(stackFrame);
1408
1409 CallFrame* callFrame = stackFrame.callFrame;
1410 Identifier& ident = stackFrame.args[1].identifier();
1411
1412 JSValue baseValue = stackFrame.args[0].jsValue();
1413 PropertySlot slot(baseValue);
1414 JSValue result = baseValue.get(callFrame, ident, slot);
1415
1416 CHECK_FOR_EXCEPTION_AT_END();
1417 return JSValue::encode(result);
1418}
1419
ba379fdc
A
1420DEFINE_STUB_FUNCTION(void, op_put_by_id)
1421{
1422 STUB_INIT_STACK_FRAME(stackFrame);
ba379fdc
A
1423 CallFrame* callFrame = stackFrame.callFrame;
1424 Identifier& ident = stackFrame.args[1].identifier();
4e4e5a6f 1425
14957cd0 1426 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
ba379fdc 1427 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
4e4e5a6f 1428
f9bf01c6
A
1429 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1430 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1431 if (!stubInfo->seenOnce())
1432 stubInfo->setSeen();
1433 else
4e4e5a6f
A
1434 JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false);
1435
1436 CHECK_FOR_EXCEPTION_AT_END();
1437}
ba379fdc 1438
4e4e5a6f
A
1439DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
1440{
1441 STUB_INIT_STACK_FRAME(stackFrame);
1442 CallFrame* callFrame = stackFrame.callFrame;
1443 Identifier& ident = stackFrame.args[1].identifier();
1444
14957cd0 1445 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
6fe7ccc8
A
1446 JSValue baseValue = stackFrame.args[0].jsValue();
1447 ASSERT(baseValue.isObject());
1448
1449 asObject(baseValue)->putDirect(callFrame->globalData(), ident, stackFrame.args[2].jsValue(), slot);
4e4e5a6f
A
1450
1451 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1452 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1453 if (!stubInfo->seenOnce())
1454 stubInfo->setSeen();
1455 else
1456 JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true);
1457
ba379fdc
A
1458 CHECK_FOR_EXCEPTION_AT_END();
1459}
1460
1461DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
1462{
1463 STUB_INIT_STACK_FRAME(stackFrame);
1464
1465 CallFrame* callFrame = stackFrame.callFrame;
1466 Identifier& ident = stackFrame.args[1].identifier();
14957cd0
A
1467
1468 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
ba379fdc
A
1469 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
1470
1471 CHECK_FOR_EXCEPTION_AT_END();
1472}
1473
4e4e5a6f
A
1474DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
1475{
1476 STUB_INIT_STACK_FRAME(stackFrame);
1477
1478 CallFrame* callFrame = stackFrame.callFrame;
1479 Identifier& ident = stackFrame.args[1].identifier();
1480
14957cd0 1481 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
6fe7ccc8
A
1482 JSValue baseValue = stackFrame.args[0].jsValue();
1483 ASSERT(baseValue.isObject());
1484 asObject(baseValue)->putDirect(callFrame->globalData(), ident, stackFrame.args[2].jsValue(), slot);
4e4e5a6f
A
1485
1486 CHECK_FOR_EXCEPTION_AT_END();
1487}
1488
ba379fdc
A
1489DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
1490{
1491 STUB_INIT_STACK_FRAME(stackFrame);
1492
1493 JSValue baseValue = stackFrame.args[0].jsValue();
1494 int32_t oldSize = stackFrame.args[3].int32();
6fe7ccc8
A
1495 Structure* newStructure = stackFrame.args[4].structure();
1496 int32_t newSize = newStructure->propertyStorageCapacity();
ba379fdc
A
1497
1498 ASSERT(baseValue.isObject());
1499 JSObject* base = asObject(baseValue);
6fe7ccc8
A
1500 JSGlobalData& globalData = *stackFrame.globalData;
1501 PropertyStorage newStorage = base->growPropertyStorage(globalData, oldSize, newSize);
1502 base->setPropertyStorage(globalData, newStorage, newStructure);
ba379fdc
A
1503
1504 return base;
1505}
1506
ba379fdc
A
1507DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
1508{
1509 STUB_INIT_STACK_FRAME(stackFrame);
1510
1511 CallFrame* callFrame = stackFrame.callFrame;
1512 Identifier& ident = stackFrame.args[1].identifier();
1513
1514 JSValue baseValue = stackFrame.args[0].jsValue();
1515 PropertySlot slot(baseValue);
1516 JSValue result = baseValue.get(callFrame, ident, slot);
f9bf01c6 1517 CHECK_FOR_EXCEPTION();
ba379fdc 1518
f9bf01c6
A
1519 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1520 MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
6fe7ccc8 1521 StructureStubInfo& stubInfo = codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
ba379fdc 1522
f9bf01c6
A
1523 if (!methodCallLinkInfo.seenOnce()) {
1524 methodCallLinkInfo.setSeen();
1525 return JSValue::encode(result);
1526 }
ba379fdc
A
1527
1528 // If we successfully got something, then the base from which it is being accessed must
1529 // be an object. (Assertion to ensure asObject() call below is safe, which comes after
1530 // an isCacheable() chceck.
4e4e5a6f 1531 ASSERT(!slot.isCacheableValue() || slot.slotBase().isObject());
ba379fdc
A
1532
1533 // Check that:
1534 // * We're dealing with a JSCell,
1535 // * the property is cachable,
1536 // * it's not a dictionary
1537 // * there is a function cached.
1538 Structure* structure;
1539 JSCell* specific;
1540 JSObject* slotBaseObject;
1541 if (baseValue.isCell()
4e4e5a6f 1542 && slot.isCacheableValue()
14957cd0 1543 && !(structure = baseValue.asCell()->structure())->isUncacheableDictionary()
ba379fdc
A
1544 && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
1545 && specific
1546 ) {
1547
6fe7ccc8 1548 JSObject* callee = asObject(specific);
ba379fdc
A
1549
1550 // Since we're accessing a prototype in a loop, it's a good bet that it
1551 // should not be treated as a dictionary.
1552 if (slotBaseObject->structure()->isDictionary())
14957cd0 1553 slotBaseObject->flattenDictionaryObject(callFrame->globalData());
ba379fdc
A
1554
1555 // The result fetched should always be the callee!
1556 ASSERT(result == JSValue(callee));
ba379fdc
A
1557
1558 // Check to see if the function is on the object's prototype. Patch up the code to optimize.
f9bf01c6 1559 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
6fe7ccc8 1560 JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
f9bf01c6
A
1561 return JSValue::encode(result);
1562 }
1563
ba379fdc
A
1564 // Check to see if the function is on the object itself.
1565 // Since we generate the method-check to check both the structure and a prototype-structure (since this
1566 // is the common case) we have a problem - we need to patch the prototype structure check to do something
1567 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler
1568 // for now. For now it performs a check on a special object on the global object only used for this
1569 // purpose. The object is in no way exposed, and as such the check will always pass.
f9bf01c6 1570 if (slot.slotBase() == baseValue) {
6fe7ccc8 1571 JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
f9bf01c6
A
1572 return JSValue::encode(result);
1573 }
ba379fdc
A
1574 }
1575
1576 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
f9bf01c6 1577 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
ba379fdc
A
1578 return JSValue::encode(result);
1579}
1580
6fe7ccc8
A
1581DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_update)
1582{
1583 STUB_INIT_STACK_FRAME(stackFrame);
1584
1585 CallFrame* callFrame = stackFrame.callFrame;
1586 Identifier& ident = stackFrame.args[1].identifier();
1587
1588 JSValue baseValue = stackFrame.args[0].jsValue();
1589 PropertySlot slot(baseValue);
1590 JSValue result = baseValue.get(callFrame, ident, slot);
1591 CHECK_FOR_EXCEPTION();
1592
1593 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1594 MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
1595 StructureStubInfo& stubInfo = codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1596
1597 ASSERT(methodCallLinkInfo.seenOnce());
1598
1599 // If we successfully got something, then the base from which it is being accessed must
1600 // be an object. (Assertion to ensure asObject() call below is safe, which comes after
1601 // an isCacheable() chceck.
1602 ASSERT(!slot.isCacheableValue() || slot.slotBase().isObject());
1603
1604 // Check that:
1605 // * We're dealing with a JSCell,
1606 // * the property is cachable,
1607 // * it's not a dictionary
1608 // * there is a function cached.
1609 Structure* structure;
1610 JSCell* specific;
1611 JSObject* slotBaseObject;
1612 if (!(baseValue.isCell()
1613 && slot.isCacheableValue()
1614 && !(structure = baseValue.asCell()->structure())->isUncacheableDictionary()
1615 && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
1616 && specific
1617 )
1618 || (slot.slotBase() != structure->prototypeForLookup(callFrame)
1619 && slot.slotBase() != baseValue)) {
1620 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
1621 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
1622 return JSValue::encode(result);
1623 }
1624
1625 // Now check if the situation has changed sufficiently that we should bail out of
1626 // doing method_check optimizations entirely, or if it changed only slightly, in
1627 // which case we can just repatch.
1628
1629 JSValue proto = structure->prototypeForLookup(callFrame);
1630
1631 bool previousWasProto = methodCallLinkInfo.cachedPrototype.get() != codeBlock->globalObject()->methodCallDummy();
1632 bool currentIsProto = slot.slotBase() == proto;
1633
1634 JSObject* callee = asObject(specific);
1635
1636 if (previousWasProto != currentIsProto
1637 || !structure->transitivelyTransitionedFrom(methodCallLinkInfo.cachedStructure.get())
1638 || (previousWasProto && !slotBaseObject->structure()->transitivelyTransitionedFrom(methodCallLinkInfo.cachedPrototypeStructure.get()))
1639 || specific != methodCallLinkInfo.cachedFunction.get()) {
1640 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
1641 return JSValue::encode(result);
1642 }
1643
1644 // It makes sense to simply repatch the method_check.
1645
1646 // Since we're accessing a prototype in a loop, it's a good bet that it
1647 // should not be treated as a dictionary.
1648 if (slotBaseObject->structure()->isDictionary())
1649 slotBaseObject->flattenDictionaryObject(callFrame->globalData());
1650
1651 // The result fetched should always be the callee!
1652 ASSERT(result == JSValue(callee));
1653
1654 // Check to see if the function is on the object's prototype. Patch up the code to optimize.
1655 if (slot.slotBase() == proto) {
1656 JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
1657 return JSValue::encode(result);
1658 }
1659
1660 ASSERT(slot.slotBase() == baseValue);
1661
1662 // Since we generate the method-check to check both the structure and a prototype-structure (since this
1663 // is the common case) we have a problem - we need to patch the prototype structure check to do something
1664 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler
1665 // for now. For now it performs a check on a special object on the global object only used for this
1666 // purpose. The object is in no way exposed, and as such the check will always pass.
1667 JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
1668 return JSValue::encode(result);
1669}
1670
f9bf01c6 1671DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
ba379fdc
A
1672{
1673 STUB_INIT_STACK_FRAME(stackFrame);
ba379fdc
A
1674 CallFrame* callFrame = stackFrame.callFrame;
1675 Identifier& ident = stackFrame.args[1].identifier();
1676
1677 JSValue baseValue = stackFrame.args[0].jsValue();
1678 PropertySlot slot(baseValue);
1679 JSValue result = baseValue.get(callFrame, ident, slot);
1680
f9bf01c6
A
1681 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
1682 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1683 if (!stubInfo->seenOnce())
1684 stubInfo->setSeen();
1685 else
1686 JITThunks::tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo);
ba379fdc
A
1687
1688 CHECK_FOR_EXCEPTION_AT_END();
1689 return JSValue::encode(result);
1690}
1691
1692DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
1693{
1694 STUB_INIT_STACK_FRAME(stackFrame);
1695
1696 CallFrame* callFrame = stackFrame.callFrame;
1697 Identifier& ident = stackFrame.args[1].identifier();
1698
1699 JSValue baseValue = stackFrame.args[0].jsValue();
1700 PropertySlot slot(baseValue);
1701 JSValue result = baseValue.get(callFrame, ident, slot);
1702
1703 CHECK_FOR_EXCEPTION();
1704
1705 if (baseValue.isCell()
1706 && slot.isCacheable()
14957cd0 1707 && !baseValue.asCell()->structure()->isUncacheableDictionary()
ba379fdc
A
1708 && slot.slotBase() == baseValue) {
1709
1710 CodeBlock* codeBlock = callFrame->codeBlock();
1711 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1712
1713 ASSERT(slot.slotBase().isObject());
1714
1715 PolymorphicAccessStructureList* polymorphicStructureList;
1716 int listIndex = 1;
1717
f9bf01c6 1718 if (stubInfo->accessType == access_get_by_id_self) {
ba379fdc 1719 ASSERT(!stubInfo->stubRoutine);
6fe7ccc8 1720 polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->globalData(), codeBlock->ownerExecutable(), MacroAssemblerCodeRef(), stubInfo->u.getByIdSelf.baseObjectStructure.get(), true);
4e4e5a6f 1721 stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
ba379fdc
A
1722 } else {
1723 polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
1724 listIndex = stubInfo->u.getByIdSelfList.listSize;
ba379fdc 1725 }
4e4e5a6f
A
1726 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
1727 stubInfo->u.getByIdSelfList.listSize++;
14957cd0 1728 JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, baseValue.asCell()->structure(), ident, slot, slot.cachedOffset());
ba379fdc 1729
4e4e5a6f
A
1730 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1731 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
1732 }
ba379fdc
A
1733 } else
1734 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
1735 return JSValue::encode(result);
1736}
1737
14957cd0 1738static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(JSGlobalData& globalData, ScriptExecutable* owner, StructureStubInfo* stubInfo, int& listIndex)
ba379fdc
A
1739{
1740 PolymorphicAccessStructureList* prototypeStructureList = 0;
1741 listIndex = 1;
1742
f9bf01c6
A
1743 switch (stubInfo->accessType) {
1744 case access_get_by_id_proto:
6fe7ccc8
A
1745 prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get(), true);
1746 stubInfo->stubRoutine = MacroAssemblerCodeRef();
ba379fdc
A
1747 stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
1748 break;
f9bf01c6 1749 case access_get_by_id_chain:
6fe7ccc8
A
1750 prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get(), true);
1751 stubInfo->stubRoutine = MacroAssemblerCodeRef();
ba379fdc
A
1752 stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
1753 break;
f9bf01c6 1754 case access_get_by_id_proto_list:
ba379fdc
A
1755 prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
1756 listIndex = stubInfo->u.getByIdProtoList.listSize;
4e4e5a6f
A
1757 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE)
1758 stubInfo->u.getByIdProtoList.listSize++;
ba379fdc
A
1759 break;
1760 default:
1761 ASSERT_NOT_REACHED();
1762 }
1763
4e4e5a6f 1764 ASSERT(listIndex <= POLYMORPHIC_LIST_CACHE_SIZE);
ba379fdc
A
1765 return prototypeStructureList;
1766}
1767
4e4e5a6f
A
1768DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_getter_stub)
1769{
1770 STUB_INIT_STACK_FRAME(stackFrame);
1771 CallFrame* callFrame = stackFrame.callFrame;
1772 GetterSetter* getterSetter = asGetterSetter(stackFrame.args[0].jsObject());
1773 if (!getterSetter->getter())
1774 return JSValue::encode(jsUndefined());
1775 JSObject* getter = asObject(getterSetter->getter());
1776 CallData callData;
6fe7ccc8 1777 CallType callType = getter->methodTable()->getCallData(getter, callData);
4e4e5a6f
A
1778 JSValue result = call(callFrame, getter, callType, callData, stackFrame.args[1].jsObject(), ArgList());
1779 if (callFrame->hadException())
1780 returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS);
1781
1782 return JSValue::encode(result);
1783}
1784
1785DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_custom_stub)
1786{
1787 STUB_INIT_STACK_FRAME(stackFrame);
1788 CallFrame* callFrame = stackFrame.callFrame;
1789 JSObject* slotBase = stackFrame.args[0].jsObject();
1790 PropertySlot::GetValueFunc getter = reinterpret_cast<PropertySlot::GetValueFunc>(stackFrame.args[1].asPointer);
1791 const Identifier& ident = stackFrame.args[2].identifier();
1792 JSValue result = getter(callFrame, slotBase, ident);
1793 if (callFrame->hadException())
1794 returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[3].returnAddress(), STUB_RETURN_ADDRESS);
1795
1796 return JSValue::encode(result);
1797}
1798
ba379fdc
A
1799DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
1800{
1801 STUB_INIT_STACK_FRAME(stackFrame);
1802
1803 CallFrame* callFrame = stackFrame.callFrame;
1804 const Identifier& propertyName = stackFrame.args[1].identifier();
1805
1806 JSValue baseValue = stackFrame.args[0].jsValue();
1807 PropertySlot slot(baseValue);
1808 JSValue result = baseValue.get(callFrame, propertyName, slot);
1809
1810 CHECK_FOR_EXCEPTION();
1811
14957cd0 1812 if (!baseValue.isCell() || !slot.isCacheable() || baseValue.asCell()->structure()->isDictionary() || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) {
ba379fdc
A
1813 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1814 return JSValue::encode(result);
1815 }
1816
14957cd0 1817 Structure* structure = baseValue.asCell()->structure();
ba379fdc
A
1818 CodeBlock* codeBlock = callFrame->codeBlock();
1819 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
1820
1821 ASSERT(slot.slotBase().isObject());
1822 JSObject* slotBaseObject = asObject(slot.slotBase());
1823
1824 size_t offset = slot.cachedOffset();
1825
1826 if (slot.slotBase() == baseValue)
1827 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
14957cd0
A
1828 else if (slot.slotBase() == baseValue.asCell()->structure()->prototypeForLookup(callFrame)) {
1829 ASSERT(!baseValue.asCell()->structure()->isDictionary());
ba379fdc
A
1830 // Since we're accessing a prototype in a loop, it's a good bet that it
1831 // should not be treated as a dictionary.
1832 if (slotBaseObject->structure()->isDictionary()) {
14957cd0
A
1833 slotBaseObject->flattenDictionaryObject(callFrame->globalData());
1834 offset = slotBaseObject->structure()->get(callFrame->globalData(), propertyName);
ba379fdc
A
1835 }
1836
1837 int listIndex;
14957cd0 1838 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->globalData(), codeBlock->ownerExecutable(), stubInfo, listIndex);
4e4e5a6f
A
1839 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
1840 JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset);
ba379fdc 1841
4e4e5a6f
A
1842 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1843 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
1844 }
ba379fdc 1845 } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
14957cd0 1846 ASSERT(!baseValue.asCell()->structure()->isDictionary());
ba379fdc 1847 int listIndex;
14957cd0 1848 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->globalData(), codeBlock->ownerExecutable(), stubInfo, listIndex);
4e4e5a6f
A
1849
1850 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
1851 StructureChain* protoChain = structure->prototypeChain(callFrame);
1852 JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, propertyName, slot, offset);
f9bf01c6 1853
4e4e5a6f
A
1854 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1855 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
1856 }
ba379fdc
A
1857 } else
1858 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1859
1860 return JSValue::encode(result);
1861}
1862
1863DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full)
1864{
1865 STUB_INIT_STACK_FRAME(stackFrame);
1866
1867 JSValue baseValue = stackFrame.args[0].jsValue();
1868 PropertySlot slot(baseValue);
1869 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1870
1871 CHECK_FOR_EXCEPTION_AT_END();
1872 return JSValue::encode(result);
1873}
1874
1875DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_fail)
1876{
1877 STUB_INIT_STACK_FRAME(stackFrame);
1878
1879 JSValue baseValue = stackFrame.args[0].jsValue();
1880 PropertySlot slot(baseValue);
1881 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1882
1883 CHECK_FOR_EXCEPTION_AT_END();
1884 return JSValue::encode(result);
1885}
1886
1887DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_array_fail)
1888{
1889 STUB_INIT_STACK_FRAME(stackFrame);
1890
1891 JSValue baseValue = stackFrame.args[0].jsValue();
1892 PropertySlot slot(baseValue);
1893 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1894
1895 CHECK_FOR_EXCEPTION_AT_END();
1896 return JSValue::encode(result);
1897}
1898
1899DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
1900{
1901 STUB_INIT_STACK_FRAME(stackFrame);
1902
1903 JSValue baseValue = stackFrame.args[0].jsValue();
1904 PropertySlot slot(baseValue);
1905 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1906
1907 CHECK_FOR_EXCEPTION_AT_END();
1908 return JSValue::encode(result);
1909}
1910
14957cd0
A
1911DEFINE_STUB_FUNCTION(void, op_check_has_instance)
1912{
1913 STUB_INIT_STACK_FRAME(stackFrame);
1914
1915 CallFrame* callFrame = stackFrame.callFrame;
1916 JSValue baseVal = stackFrame.args[0].jsValue();
1917
1918 // ECMA-262 15.3.5.3:
1919 // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
1920#ifndef NDEBUG
1921 TypeInfo typeInfo(UnspecifiedType);
1922 ASSERT(!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance());
1923#endif
1924 stackFrame.globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal);
1925 VM_THROW_EXCEPTION_AT_END();
1926}
1927
6fe7ccc8
A
1928#if ENABLE(DFG_JIT)
1929DEFINE_STUB_FUNCTION(void, optimize_from_loop)
ba379fdc
A
1930{
1931 STUB_INIT_STACK_FRAME(stackFrame);
6fe7ccc8 1932
ba379fdc 1933 CallFrame* callFrame = stackFrame.callFrame;
6fe7ccc8
A
1934 CodeBlock* codeBlock = callFrame->codeBlock();
1935
1936 unsigned bytecodeIndex = stackFrame.args[0].int32();
1937
1938#if ENABLE(JIT_VERBOSE_OSR)
1939 dataLog("%p: Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
1940#endif
ba379fdc 1941
6fe7ccc8
A
1942 if (!codeBlock->checkIfOptimizationThresholdReached())
1943 return;
ba379fdc 1944
6fe7ccc8
A
1945 if (codeBlock->hasOptimizedReplacement()) {
1946#if ENABLE(JIT_VERBOSE_OSR)
1947 dataLog("Considering loop OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
1948#endif
1949 if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
1950#if ENABLE(JIT_VERBOSE_OSR)
1951 dataLog("Triggering reoptimization of %p(%p) (in loop).\n", codeBlock, codeBlock->replacement());
1952#endif
1953 codeBlock->reoptimize();
1954 return;
1955 }
1956 } else {
1957 if (!codeBlock->shouldOptimizeNow()) {
1958#if ENABLE(JIT_VERBOSE_OSR)
1959 dataLog("Delaying optimization for %p (in loop) because of insufficient profiling.\n", codeBlock);
1960#endif
1961 return;
1962 }
1963
1964 ScopeChainNode* scopeChain = callFrame->scopeChain();
1965
1966 JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain);
1967#if ENABLE(JIT_VERBOSE_OSR)
1968 if (error)
1969 dataLog("WARNING: optimized compilation from loop failed.\n");
1970#else
1971 UNUSED_PARAM(error);
1972#endif
1973
1974 if (codeBlock->replacement() == codeBlock) {
1975#if ENABLE(JIT_VERBOSE_OSR)
1976 dataLog("Optimizing %p from loop failed.\n", codeBlock);
1977#endif
1978
1979 ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
1980 codeBlock->dontOptimizeAnytimeSoon();
1981 return;
1982 }
1983 }
1984
1985 CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1986 ASSERT(optimizedCodeBlock->getJITType() == JITCode::DFGJIT);
1987
1988 if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) {
1989#if ENABLE(JIT_VERBOSE_OSR)
1990 dataLog("Optimizing %p from loop succeeded, performing OSR after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
1991#endif
ba379fdc 1992
6fe7ccc8
A
1993 codeBlock->optimizeSoon();
1994 optimizedCodeBlock->countSpeculationSuccess();
1995 STUB_SET_RETURN_ADDRESS(address);
1996 return;
ba379fdc 1997 }
6fe7ccc8
A
1998
1999#if ENABLE(JIT_VERBOSE_OSR)
2000 dataLog("Optimizing %p from loop succeeded, OSR failed, after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
2001#endif
ba379fdc 2002
6fe7ccc8
A
2003 // Count the OSR failure as a speculation failure. If this happens a lot, then
2004 // reoptimize.
2005 optimizedCodeBlock->countSpeculationFailure();
2006
2007#if ENABLE(JIT_VERBOSE_OSR)
2008 dataLog("Encountered loop OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
2009#endif
ba379fdc 2010
6fe7ccc8
A
2011 // We are a lot more conservative about triggering reoptimization after OSR failure than
2012 // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
2013 // already, then we really would like to reoptimize immediately. But this case covers
2014 // something else: there weren't many (or any) speculation failures before, but we just
2015 // failed to enter the speculative code because some variable had the wrong value or
2016 // because the OSR code decided for any spurious reason that it did not want to OSR
2017 // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
2018 // reoptimization trigger.
2019 if (optimizedCodeBlock->shouldReoptimizeNow()) {
2020#if ENABLE(JIT_VERBOSE_OSR)
2021 dataLog("Triggering reoptimization of %p(%p) (in loop after OSR fail).\n", codeBlock, codeBlock->replacement());
2022#endif
2023 codeBlock->reoptimize();
2024 return;
2025 }
2026
2027 // OSR failed this time, but it might succeed next time! Let the code run a bit
2028 // longer and then try again.
2029 codeBlock->optimizeAfterWarmUp();
2030}
2031
2032DEFINE_STUB_FUNCTION(void, optimize_from_ret)
2033{
2034 STUB_INIT_STACK_FRAME(stackFrame);
2035
2036 CallFrame* callFrame = stackFrame.callFrame;
2037 CodeBlock* codeBlock = callFrame->codeBlock();
2038
2039#if ENABLE(JIT_VERBOSE_OSR)
2040 dataLog("Entered optimize_from_ret with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
2041#endif
2042
2043 if (!codeBlock->checkIfOptimizationThresholdReached())
2044 return;
2045
2046 if (codeBlock->hasOptimizedReplacement()) {
2047#if ENABLE(JIT_VERBOSE_OSR)
2048 dataLog("Returning from old JIT call frame with optimized replacement %p(%p), with success/fail %u/%u", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
2049 CallFrame* callerFrame = callFrame->callerFrame();
2050 if (callerFrame)
2051 dataLog(", callerFrame = %p, returnPC = %p, caller code block = %p", callerFrame, callFrame->returnPC().value(), callerFrame->codeBlock());
2052 dataLog("\n");
2053#endif
2054 if (codeBlock->replacement()->shouldReoptimizeNow()) {
2055#if ENABLE(JIT_VERBOSE_OSR)
2056 dataLog("Triggering reoptimization of %p(%p) (in return).\n", codeBlock, codeBlock->replacement());
2057#endif
2058 codeBlock->reoptimize();
ba379fdc 2059 }
6fe7ccc8
A
2060
2061 codeBlock->optimizeSoon();
2062 return;
ba379fdc 2063 }
6fe7ccc8
A
2064
2065 if (!codeBlock->shouldOptimizeNow()) {
2066#if ENABLE(JIT_VERBOSE_OSR)
2067 dataLog("Delaying optimization for %p (in return) because of insufficient profiling.\n", codeBlock);
2068#endif
2069 return;
2070 }
2071
2072 ScopeChainNode* scopeChain = callFrame->scopeChain();
ba379fdc 2073
6fe7ccc8
A
2074 JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain);
2075 if (error)
2076 dataLog("WARNING: optimized compilation from ret failed.\n");
2077
2078 if (codeBlock->replacement() == codeBlock) {
2079#if ENABLE(JIT_VERBOSE_OSR)
2080 dataLog("Optimizing %p from return failed.\n", codeBlock);
2081#endif
ba379fdc 2082
6fe7ccc8
A
2083 ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
2084 codeBlock->dontOptimizeAnytimeSoon();
2085 return;
2086 }
2087
2088 ASSERT(codeBlock->replacement()->getJITType() == JITCode::DFGJIT);
2089
2090#if ENABLE(JIT_VERBOSE_OSR)
2091 dataLog("Optimizing %p from return succeeded after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
2092#endif
2093
2094 codeBlock->optimizeSoon();
2095}
2096#endif // ENABLE(DFG_JIT)
2097
2098DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
2099{
2100 STUB_INIT_STACK_FRAME(stackFrame);
2101
2102 CallFrame* callFrame = stackFrame.callFrame;
2103 JSValue value = stackFrame.args[0].jsValue();
2104 JSValue baseVal = stackFrame.args[1].jsValue();
2105 JSValue proto = stackFrame.args[2].jsValue();
2106
2107 bool result = CommonSlowPaths::opInstanceOfSlow(callFrame, value, baseVal, proto);
2108 CHECK_FOR_EXCEPTION_AT_END();
2109 return JSValue::encode(jsBoolean(result));
ba379fdc
A
2110}
2111
2112DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
2113{
2114 STUB_INIT_STACK_FRAME(stackFrame);
2115
2116 CallFrame* callFrame = stackFrame.callFrame;
2117
2118 JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
2119
6fe7ccc8 2120 bool couldDelete = baseObj->methodTable()->deleteProperty(baseObj, callFrame, stackFrame.args[1].identifier());
14957cd0
A
2121 JSValue result = jsBoolean(couldDelete);
2122 if (!couldDelete && callFrame->codeBlock()->isStrictMode())
2123 stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
2124
ba379fdc
A
2125 CHECK_FOR_EXCEPTION_AT_END();
2126 return JSValue::encode(result);
2127}
2128
2129DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul)
2130{
2131 STUB_INIT_STACK_FRAME(stackFrame);
2132
2133 JSValue src1 = stackFrame.args[0].jsValue();
2134 JSValue src2 = stackFrame.args[1].jsValue();
2135
6fe7ccc8
A
2136 if (src1.isNumber() && src2.isNumber())
2137 return JSValue::encode(jsNumber(src1.asNumber() * src2.asNumber()));
ba379fdc
A
2138
2139 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 2140 JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
ba379fdc
A
2141 CHECK_FOR_EXCEPTION_AT_END();
2142 return JSValue::encode(result);
2143}
2144
2145DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
2146{
2147 STUB_INIT_STACK_FRAME(stackFrame);
14957cd0
A
2148
2149 ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
f9bf01c6 2150 return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
ba379fdc
A
2151}
2152
6fe7ccc8
A
2153inline void* jitCompileFor(CallFrame* callFrame, CodeSpecializationKind kind)
2154{
2155 JSFunction* function = jsCast<JSFunction*>(callFrame->callee());
2156 ASSERT(!function->isHostFunction());
2157 FunctionExecutable* executable = function->jsExecutable();
2158 ScopeChainNode* callDataScopeChain = function->scope();
2159 JSObject* error = executable->compileFor(callFrame, callDataScopeChain, kind);
2160 if (!error)
2161 return function;
2162 callFrame->globalData().exception = error;
2163 return 0;
2164}
2165
14957cd0 2166DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
ba379fdc
A
2167{
2168 STUB_INIT_STACK_FRAME(stackFrame);
2169
f9bf01c6 2170#if !ASSERT_DISABLED
ba379fdc 2171 CallData callData;
6fe7ccc8 2172 ASSERT(stackFrame.callFrame->callee()->methodTable()->getCallData(stackFrame.callFrame->callee(), callData) == CallTypeJS);
ba379fdc 2173#endif
6fe7ccc8
A
2174
2175 CallFrame* callFrame = stackFrame.callFrame;
2176 void* result = jitCompileFor(callFrame, CodeForCall);
2177 if (!result)
2178 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
ba379fdc 2179
6fe7ccc8 2180 return result;
14957cd0
A
2181}
2182
2183DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
2184{
2185 STUB_INIT_STACK_FRAME(stackFrame);
2186
2187#if !ASSERT_DISABLED
2188 ConstructData constructData;
6fe7ccc8 2189 ASSERT(jsCast<JSFunction*>(stackFrame.callFrame->callee())->methodTable()->getConstructData(stackFrame.callFrame->callee(), constructData) == ConstructTypeJS);
14957cd0 2190#endif
ba379fdc 2191
6fe7ccc8
A
2192 CallFrame* callFrame = stackFrame.callFrame;
2193 void* result = jitCompileFor(callFrame, CodeForConstruct);
2194 if (!result)
2195 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
2196
2197 return result;
ba379fdc
A
2198}
2199
14957cd0 2200DEFINE_STUB_FUNCTION(void*, op_call_arityCheck)
ba379fdc
A
2201{
2202 STUB_INIT_STACK_FRAME(stackFrame);
2203
2204 CallFrame* callFrame = stackFrame.callFrame;
ba379fdc 2205
6fe7ccc8
A
2206 CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForCall);
2207 if (!newCallFrame)
2208 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
14957cd0 2209
6fe7ccc8 2210 return newCallFrame;
14957cd0
A
2211}
2212
2213DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck)
2214{
2215 STUB_INIT_STACK_FRAME(stackFrame);
2216
2217 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 2218
6fe7ccc8
A
2219 CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForConstruct);
2220 if (!newCallFrame)
2221 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
14957cd0 2222
6fe7ccc8 2223 return newCallFrame;
ba379fdc
A
2224}
2225
6fe7ccc8 2226inline void* lazyLinkFor(CallFrame* callFrame, CodeSpecializationKind kind)
ba379fdc 2227{
6fe7ccc8 2228 JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
f9bf01c6 2229 ExecutableBase* executable = callee->executable();
14957cd0
A
2230
2231 MacroAssemblerCodePtr codePtr;
2232 CodeBlock* codeBlock = 0;
6fe7ccc8
A
2233 CallLinkInfo* callLinkInfo = &callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
2234
14957cd0 2235 if (executable->isHostFunction())
6fe7ccc8 2236 codePtr = executable->generatedJITCodeFor(kind).addressForCall();
14957cd0
A
2237 else {
2238 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
6fe7ccc8
A
2239 if (JSObject* error = functionExecutable->compileFor(callFrame, callee->scope(), kind)) {
2240 callFrame->globalData().exception = error;
14957cd0
A
2241 return 0;
2242 }
6fe7ccc8
A
2243 codeBlock = &functionExecutable->generatedBytecodeFor(kind);
2244 if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())
2245 || callLinkInfo->callType == CallLinkInfo::CallVarargs)
2246 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
14957cd0 2247 else
6fe7ccc8 2248 codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
14957cd0 2249 }
14957cd0
A
2250
2251 if (!callLinkInfo->seenOnce())
2252 callLinkInfo->setSeen();
2253 else
6fe7ccc8 2254 JIT::linkFor(callee, callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, &callFrame->globalData(), kind);
14957cd0
A
2255
2256 return codePtr.executableAddress();
2257}
2258
6fe7ccc8 2259DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
14957cd0
A
2260{
2261 STUB_INIT_STACK_FRAME(stackFrame);
6fe7ccc8 2262
14957cd0 2263 CallFrame* callFrame = stackFrame.callFrame;
6fe7ccc8
A
2264 void* result = lazyLinkFor(callFrame, CodeForCall);
2265 if (!result)
2266 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
14957cd0 2267
6fe7ccc8
A
2268 return result;
2269}
f9bf01c6 2270
6fe7ccc8
A
2271DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
2272{
2273 STUB_INIT_STACK_FRAME(stackFrame);
ba379fdc 2274
6fe7ccc8
A
2275 CallFrame* callFrame = stackFrame.callFrame;
2276 void* result = lazyLinkFor(callFrame, CodeForConstruct);
2277 if (!result)
2278 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
2279
2280 return result;
ba379fdc 2281}
ba379fdc
A
2282
2283DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
2284{
2285 STUB_INIT_STACK_FRAME(stackFrame);
2286
6fe7ccc8 2287 JSActivation* activation = JSActivation::create(stackFrame.callFrame->globalData(), stackFrame.callFrame, static_cast<FunctionExecutable*>(stackFrame.callFrame->codeBlock()->ownerExecutable()));
14957cd0 2288 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(activation));
ba379fdc
A
2289 return activation;
2290}
2291
2292DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
2293{
2294 STUB_INIT_STACK_FRAME(stackFrame);
2295
6fe7ccc8
A
2296 CallFrame* callFrame = stackFrame.callFrame;
2297
2298 JSValue callee = callFrame->calleeAsValue();
ba379fdc
A
2299
2300 CallData callData;
6fe7ccc8 2301 CallType callType = getCallData(callee, callData);
ba379fdc
A
2302
2303 ASSERT(callType != CallTypeJS);
6fe7ccc8
A
2304 if (callType != CallTypeHost) {
2305 ASSERT(callType == CallTypeNone);
2306 return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createNotAFunctionError(callFrame->callerFrame(), callee));
2307 }
ba379fdc 2308
6fe7ccc8
A
2309 EncodedJSValue returnValue;
2310 {
2311 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
2312 returnValue = callData.native.function(callFrame);
ba379fdc
A
2313 }
2314
6fe7ccc8
A
2315 if (stackFrame.globalData->exception)
2316 return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
ba379fdc 2317
6fe7ccc8 2318 return returnValue;
ba379fdc
A
2319}
2320
14957cd0 2321DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
ba379fdc
A
2322{
2323 STUB_INIT_STACK_FRAME(stackFrame);
2324
6fe7ccc8 2325 Arguments* arguments = Arguments::create(*stackFrame.globalData, stackFrame.callFrame);
14957cd0 2326 return JSValue::encode(JSValue(arguments));
ba379fdc
A
2327}
2328
2329DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
2330{
2331 STUB_INIT_STACK_FRAME(stackFrame);
2332
6fe7ccc8
A
2333 CallFrame* callFrame = stackFrame.callFrame;
2334 ASSERT(callFrame->codeBlock()->needsFullScopeChain());
14957cd0
A
2335 JSValue activationValue = stackFrame.args[0].jsValue();
2336 if (!activationValue) {
2337 if (JSValue v = stackFrame.args[1].jsValue()) {
6fe7ccc8
A
2338 if (!callFrame->codeBlock()->isStrictMode())
2339 asArguments(v)->tearOff(callFrame);
14957cd0
A
2340 }
2341 return;
2342 }
2343 JSActivation* activation = asActivation(stackFrame.args[0].jsValue());
6fe7ccc8
A
2344 activation->tearOff(*stackFrame.globalData);
2345 if (JSValue v = stackFrame.args[1].jsValue())
2346 asArguments(v)->didTearOffActivation(*stackFrame.globalData, activation);
ba379fdc
A
2347}
2348
2349DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
2350{
2351 STUB_INIT_STACK_FRAME(stackFrame);
2352
6fe7ccc8
A
2353 CallFrame* callFrame = stackFrame.callFrame;
2354 ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
2355 asArguments(stackFrame.args[0].jsValue())->tearOff(callFrame);
ba379fdc
A
2356}
2357
2358DEFINE_STUB_FUNCTION(void, op_profile_will_call)
2359{
2360 STUB_INIT_STACK_FRAME(stackFrame);
2361
2362 ASSERT(*stackFrame.enabledProfilerReference);
2363 (*stackFrame.enabledProfilerReference)->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
2364}
2365
2366DEFINE_STUB_FUNCTION(void, op_profile_did_call)
2367{
2368 STUB_INIT_STACK_FRAME(stackFrame);
2369
2370 ASSERT(*stackFrame.enabledProfilerReference);
2371 (*stackFrame.enabledProfilerReference)->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
2372}
2373
14957cd0 2374DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
ba379fdc
A
2375{
2376 STUB_INIT_STACK_FRAME(stackFrame);
2377
6fe7ccc8 2378 return constructArray(stackFrame.callFrame, reinterpret_cast<JSValue*>(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()]), stackFrame.args[1].int32());
ba379fdc
A
2379}
2380
14957cd0 2381DEFINE_STUB_FUNCTION(JSObject*, op_new_array_buffer)
ba379fdc
A
2382{
2383 STUB_INIT_STACK_FRAME(stackFrame);
14957cd0 2384
6fe7ccc8 2385 return constructArray(stackFrame.callFrame, stackFrame.callFrame->codeBlock()->constantBuffer(stackFrame.args[0].int32()), stackFrame.args[1].int32());
ba379fdc
A
2386}
2387
2388DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
2389{
2390 STUB_INIT_STACK_FRAME(stackFrame);
2391
2392 CallFrame* callFrame = stackFrame.callFrame;
ba379fdc 2393
6fe7ccc8
A
2394 JSValue result = CommonSlowPaths::opResolve(callFrame, stackFrame.args[0].identifier());
2395 CHECK_FOR_EXCEPTION_AT_END();
2396 return JSValue::encode(result);
ba379fdc
A
2397}
2398
ba379fdc
A
2399DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
2400{
2401 STUB_INIT_STACK_FRAME(stackFrame);
2402
6fe7ccc8
A
2403 CallFrame* callFrame = stackFrame.callFrame;
2404 JSValue callee = callFrame->calleeAsValue();
ba379fdc
A
2405
2406 ConstructData constructData;
6fe7ccc8 2407 ConstructType constructType = getConstructData(callee, constructData);
14957cd0
A
2408
2409 ASSERT(constructType != ConstructTypeJS);
6fe7ccc8
A
2410 if (constructType != ConstructTypeHost) {
2411 ASSERT(constructType == ConstructTypeNone);
2412 return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createNotAConstructorError(callFrame->callerFrame(), callee));
2413 }
ba379fdc 2414
6fe7ccc8
A
2415 EncodedJSValue returnValue;
2416 {
2417 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
2418 returnValue = constructData.native.function(callFrame);
ba379fdc
A
2419 }
2420
6fe7ccc8
A
2421 if (stackFrame.globalData->exception)
2422 return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
ba379fdc 2423
6fe7ccc8 2424 return returnValue;
ba379fdc
A
2425}
2426
2427DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
2428{
2429 STUB_INIT_STACK_FRAME(stackFrame);
2430
2431 CallFrame* callFrame = stackFrame.callFrame;
ba379fdc
A
2432
2433 JSValue baseValue = stackFrame.args[0].jsValue();
2434 JSValue subscript = stackFrame.args[1].jsValue();
2435
4e4e5a6f 2436 if (LIKELY(baseValue.isCell() && subscript.isString())) {
6fe7ccc8 2437 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame))) {
4e4e5a6f
A
2438 CHECK_FOR_EXCEPTION();
2439 return JSValue::encode(result);
2440 }
2441 }
ba379fdc 2442
4e4e5a6f 2443 if (subscript.isUInt32()) {
ba379fdc 2444 uint32_t i = subscript.asUInt32();
6fe7ccc8 2445 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
ba379fdc 2446 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
4e4e5a6f
A
2447 JSValue result = asString(baseValue)->getIndex(callFrame, i);
2448 CHECK_FOR_EXCEPTION();
2449 return JSValue::encode(result);
2450 }
4e4e5a6f
A
2451 JSValue result = baseValue.get(callFrame, i);
2452 CHECK_FOR_EXCEPTION();
2453 return JSValue::encode(result);
ba379fdc 2454 }
4e4e5a6f 2455
6fe7ccc8 2456 Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
4e4e5a6f 2457 JSValue result = baseValue.get(callFrame, property);
ba379fdc
A
2458 CHECK_FOR_EXCEPTION_AT_END();
2459 return JSValue::encode(result);
2460}
2461
2462DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
2463{
2464 STUB_INIT_STACK_FRAME(stackFrame);
2465
2466 CallFrame* callFrame = stackFrame.callFrame;
ba379fdc
A
2467
2468 JSValue baseValue = stackFrame.args[0].jsValue();
2469 JSValue subscript = stackFrame.args[1].jsValue();
2470
2471 JSValue result;
2472
2473 if (LIKELY(subscript.isUInt32())) {
2474 uint32_t i = subscript.asUInt32();
6fe7ccc8 2475 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
f9bf01c6 2476 result = asString(baseValue)->getIndex(callFrame, i);
ba379fdc
A
2477 else {
2478 result = baseValue.get(callFrame, i);
6fe7ccc8 2479 if (!isJSString(baseValue))
ba379fdc
A
2480 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
2481 }
2482 } else {
6fe7ccc8 2483 Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
ba379fdc
A
2484 result = baseValue.get(callFrame, property);
2485 }
2486
2487 CHECK_FOR_EXCEPTION_AT_END();
2488 return JSValue::encode(result);
2489}
2490
ba379fdc
A
2491DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub)
2492{
2493 STUB_INIT_STACK_FRAME(stackFrame);
2494
2495 JSValue src1 = stackFrame.args[0].jsValue();
2496 JSValue src2 = stackFrame.args[1].jsValue();
2497
6fe7ccc8
A
2498 if (src1.isNumber() && src2.isNumber())
2499 return JSValue::encode(jsNumber(src1.asNumber() - src2.asNumber()));
ba379fdc
A
2500
2501 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 2502 JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
ba379fdc
A
2503 CHECK_FOR_EXCEPTION_AT_END();
2504 return JSValue::encode(result);
2505}
2506
2507DEFINE_STUB_FUNCTION(void, op_put_by_val)
2508{
2509 STUB_INIT_STACK_FRAME(stackFrame);
2510
2511 CallFrame* callFrame = stackFrame.callFrame;
2512 JSGlobalData* globalData = stackFrame.globalData;
2513
2514 JSValue baseValue = stackFrame.args[0].jsValue();
2515 JSValue subscript = stackFrame.args[1].jsValue();
2516 JSValue value = stackFrame.args[2].jsValue();
2517
2518 if (LIKELY(subscript.isUInt32())) {
2519 uint32_t i = subscript.asUInt32();
6fe7ccc8 2520 if (isJSArray(baseValue)) {
ba379fdc
A
2521 JSArray* jsArray = asArray(baseValue);
2522 if (jsArray->canSetIndex(i))
14957cd0 2523 jsArray->setIndex(*globalData, i, value);
ba379fdc 2524 else
6fe7ccc8 2525 JSArray::putByIndex(jsArray, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
ba379fdc 2526 } else
6fe7ccc8 2527 baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
ba379fdc 2528 } else {
6fe7ccc8 2529 Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
ba379fdc 2530 if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
14957cd0 2531 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
ba379fdc
A
2532 baseValue.put(callFrame, property, value, slot);
2533 }
2534 }
2535
2536 CHECK_FOR_EXCEPTION_AT_END();
2537}
2538
6fe7ccc8 2539DEFINE_STUB_FUNCTION(EncodedJSValue, op_less)
ba379fdc
A
2540{
2541 STUB_INIT_STACK_FRAME(stackFrame);
ba379fdc 2542
6fe7ccc8
A
2543 CallFrame* callFrame = stackFrame.callFrame;
2544 JSValue result = jsBoolean(jsLess<true>(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
ba379fdc 2545 CHECK_FOR_EXCEPTION_AT_END();
6fe7ccc8 2546 return JSValue::encode(result);
ba379fdc
A
2547}
2548
2549DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
2550{
2551 STUB_INIT_STACK_FRAME(stackFrame);
2552
2553 CallFrame* callFrame = stackFrame.callFrame;
6fe7ccc8 2554 JSValue result = jsBoolean(jsLessEq<true>(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
ba379fdc
A
2555 CHECK_FOR_EXCEPTION_AT_END();
2556 return JSValue::encode(result);
2557}
2558
6fe7ccc8
A
2559DEFINE_STUB_FUNCTION(EncodedJSValue, op_greater)
2560{
2561 STUB_INIT_STACK_FRAME(stackFrame);
2562
2563 CallFrame* callFrame = stackFrame.callFrame;
2564 JSValue result = jsBoolean(jsLess<false>(callFrame, stackFrame.args[1].jsValue(), stackFrame.args[0].jsValue()));
2565 CHECK_FOR_EXCEPTION_AT_END();
2566 return JSValue::encode(result);
2567}
2568
2569DEFINE_STUB_FUNCTION(EncodedJSValue, op_greatereq)
2570{
2571 STUB_INIT_STACK_FRAME(stackFrame);
2572
2573 CallFrame* callFrame = stackFrame.callFrame;
2574 JSValue result = jsBoolean(jsLessEq<false>(callFrame, stackFrame.args[1].jsValue(), stackFrame.args[0].jsValue()));
2575 CHECK_FOR_EXCEPTION_AT_END();
2576 return JSValue::encode(result);
2577}
2578
2579DEFINE_STUB_FUNCTION(void*, op_load_varargs)
ba379fdc
A
2580{
2581 STUB_INIT_STACK_FRAME(stackFrame);
2582
2583 CallFrame* callFrame = stackFrame.callFrame;
2584 RegisterFile* registerFile = stackFrame.registerFile;
6fe7ccc8
A
2585 JSValue thisValue = stackFrame.args[0].jsValue();
2586 JSValue arguments = stackFrame.args[1].jsValue();
2587 int firstFreeRegister = stackFrame.args[2].int32();
ba379fdc 2588
6fe7ccc8
A
2589 CallFrame* newCallFrame = loadVarargs(callFrame, registerFile, thisValue, arguments, firstFreeRegister);
2590 if (!newCallFrame)
2591 VM_THROW_EXCEPTION();
2592 return newCallFrame;
ba379fdc
A
2593}
2594
2595DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate)
2596{
2597 STUB_INIT_STACK_FRAME(stackFrame);
2598
2599 JSValue src = stackFrame.args[0].jsValue();
2600
6fe7ccc8
A
2601 if (src.isNumber())
2602 return JSValue::encode(jsNumber(-src.asNumber()));
ba379fdc
A
2603
2604 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 2605 JSValue result = jsNumber(-src.toNumber(callFrame));
ba379fdc
A
2606 CHECK_FOR_EXCEPTION_AT_END();
2607 return JSValue::encode(result);
2608}
2609
2610DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base)
2611{
2612 STUB_INIT_STACK_FRAME(stackFrame);
2613
14957cd0
A
2614 return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain(), false));
2615}
2616
2617DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base_strict_put)
2618{
2619 STUB_INIT_STACK_FRAME(stackFrame);
2620 JSValue base = JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain(), true);
2621 if (!base) {
2622 stackFrame.globalData->exception = createErrorForInvalidGlobalAssignment(stackFrame.callFrame, stackFrame.args[0].identifier().ustring());
2623 VM_THROW_EXCEPTION();
2624 }
2625 return JSValue::encode(base);
ba379fdc
A
2626}
2627
14957cd0
A
2628DEFINE_STUB_FUNCTION(EncodedJSValue, op_ensure_property_exists)
2629{
2630 STUB_INIT_STACK_FRAME(stackFrame);
2631 JSValue base = stackFrame.callFrame->r(stackFrame.args[0].int32()).jsValue();
2632 JSObject* object = asObject(base);
2633 PropertySlot slot(object);
2634 ASSERT(stackFrame.callFrame->codeBlock()->isStrictMode());
2635 if (!object->getPropertySlot(stackFrame.callFrame, stackFrame.args[1].identifier(), slot)) {
2636 stackFrame.globalData->exception = createErrorForInvalidGlobalAssignment(stackFrame.callFrame, stackFrame.args[1].identifier().ustring());
2637 VM_THROW_EXCEPTION();
2638 }
2639
2640 return JSValue::encode(base);
2641}
2642
ba379fdc
A
2643DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
2644{
2645 STUB_INIT_STACK_FRAME(stackFrame);
2646
6fe7ccc8
A
2647 JSValue result = CommonSlowPaths::opResolveSkip(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].int32());
2648 CHECK_FOR_EXCEPTION_AT_END();
2649 return JSValue::encode(result);
ba379fdc
A
2650}
2651
2652DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
2653{
2654 STUB_INIT_STACK_FRAME(stackFrame);
2655
2656 CallFrame* callFrame = stackFrame.callFrame;
14957cd0
A
2657 CodeBlock* codeBlock = callFrame->codeBlock();
2658 JSGlobalObject* globalObject = codeBlock->globalObject();
2659 Identifier& ident = stackFrame.args[0].identifier();
2660 unsigned globalResolveInfoIndex = stackFrame.args[1].int32();
ba379fdc
A
2661 ASSERT(globalObject->isGlobalObject());
2662
2663 PropertySlot slot(globalObject);
2664 if (globalObject->getPropertySlot(callFrame, ident, slot)) {
2665 JSValue result = slot.getValue(callFrame, ident);
4e4e5a6f 2666 if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
14957cd0
A
2667 GlobalResolveInfo& globalResolveInfo = codeBlock->globalResolveInfo(globalResolveInfoIndex);
2668 globalResolveInfo.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
ba379fdc
A
2669 globalResolveInfo.offset = slot.cachedOffset();
2670 return JSValue::encode(result);
2671 }
2672
2673 CHECK_FOR_EXCEPTION_AT_END();
2674 return JSValue::encode(result);
2675 }
2676
14957cd0 2677 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
ba379fdc
A
2678 VM_THROW_EXCEPTION();
2679}
2680
2681DEFINE_STUB_FUNCTION(EncodedJSValue, op_div)
2682{
2683 STUB_INIT_STACK_FRAME(stackFrame);
2684
2685 JSValue src1 = stackFrame.args[0].jsValue();
2686 JSValue src2 = stackFrame.args[1].jsValue();
2687
6fe7ccc8
A
2688 if (src1.isNumber() && src2.isNumber())
2689 return JSValue::encode(jsNumber(src1.asNumber() / src2.asNumber()));
ba379fdc
A
2690
2691 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 2692 JSValue result = jsNumber(src1.toNumber(callFrame) / src2.toNumber(callFrame));
ba379fdc
A
2693 CHECK_FOR_EXCEPTION_AT_END();
2694 return JSValue::encode(result);
2695}
2696
2697DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_dec)
2698{
2699 STUB_INIT_STACK_FRAME(stackFrame);
2700
2701 JSValue v = stackFrame.args[0].jsValue();
2702
2703 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 2704 JSValue result = jsNumber(v.toNumber(callFrame) - 1);
ba379fdc
A
2705 CHECK_FOR_EXCEPTION_AT_END();
2706 return JSValue::encode(result);
2707}
2708
2709DEFINE_STUB_FUNCTION(int, op_jless)
2710{
2711 STUB_INIT_STACK_FRAME(stackFrame);
2712
2713 JSValue src1 = stackFrame.args[0].jsValue();
2714 JSValue src2 = stackFrame.args[1].jsValue();
2715 CallFrame* callFrame = stackFrame.callFrame;
2716
6fe7ccc8 2717 bool result = jsLess<true>(callFrame, src1, src2);
ba379fdc
A
2718 CHECK_FOR_EXCEPTION_AT_END();
2719 return result;
2720}
2721
2722DEFINE_STUB_FUNCTION(int, op_jlesseq)
2723{
2724 STUB_INIT_STACK_FRAME(stackFrame);
2725
2726 JSValue src1 = stackFrame.args[0].jsValue();
2727 JSValue src2 = stackFrame.args[1].jsValue();
2728 CallFrame* callFrame = stackFrame.callFrame;
2729
6fe7ccc8
A
2730 bool result = jsLessEq<true>(callFrame, src1, src2);
2731 CHECK_FOR_EXCEPTION_AT_END();
2732 return result;
2733}
2734
2735DEFINE_STUB_FUNCTION(int, op_jgreater)
2736{
2737 STUB_INIT_STACK_FRAME(stackFrame);
2738
2739 JSValue src1 = stackFrame.args[0].jsValue();
2740 JSValue src2 = stackFrame.args[1].jsValue();
2741 CallFrame* callFrame = stackFrame.callFrame;
2742
2743 bool result = jsLess<false>(callFrame, src2, src1);
2744 CHECK_FOR_EXCEPTION_AT_END();
2745 return result;
2746}
2747
2748DEFINE_STUB_FUNCTION(int, op_jgreatereq)
2749{
2750 STUB_INIT_STACK_FRAME(stackFrame);
2751
2752 JSValue src1 = stackFrame.args[0].jsValue();
2753 JSValue src2 = stackFrame.args[1].jsValue();
2754 CallFrame* callFrame = stackFrame.callFrame;
2755
2756 bool result = jsLessEq<false>(callFrame, src2, src1);
ba379fdc
A
2757 CHECK_FOR_EXCEPTION_AT_END();
2758 return result;
2759}
2760
2761DEFINE_STUB_FUNCTION(EncodedJSValue, op_not)
2762{
2763 STUB_INIT_STACK_FRAME(stackFrame);
2764
2765 JSValue src = stackFrame.args[0].jsValue();
2766
2767 CallFrame* callFrame = stackFrame.callFrame;
2768
2769 JSValue result = jsBoolean(!src.toBoolean(callFrame));
2770 CHECK_FOR_EXCEPTION_AT_END();
2771 return JSValue::encode(result);
2772}
2773
2774DEFINE_STUB_FUNCTION(int, op_jtrue)
2775{
2776 STUB_INIT_STACK_FRAME(stackFrame);
2777
2778 JSValue src1 = stackFrame.args[0].jsValue();
2779
2780 CallFrame* callFrame = stackFrame.callFrame;
2781
2782 bool result = src1.toBoolean(callFrame);
2783 CHECK_FOR_EXCEPTION_AT_END();
2784 return result;
2785}
2786
2787DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_inc)
2788{
2789 STUB_INIT_STACK_FRAME(stackFrame);
2790
2791 JSValue v = stackFrame.args[0].jsValue();
2792
2793 CallFrame* callFrame = stackFrame.callFrame;
2794
6fe7ccc8 2795 double number = v.toNumber(callFrame);
ba379fdc
A
2796 CHECK_FOR_EXCEPTION_AT_END();
2797
6fe7ccc8
A
2798 callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number + 1);
2799 return JSValue::encode(jsNumber(number));
ba379fdc
A
2800}
2801
ba379fdc
A
2802DEFINE_STUB_FUNCTION(int, op_eq)
2803{
2804 STUB_INIT_STACK_FRAME(stackFrame);
2805
2806 JSValue src1 = stackFrame.args[0].jsValue();
2807 JSValue src2 = stackFrame.args[1].jsValue();
2808
f9bf01c6 2809#if USE(JSVALUE32_64)
ba379fdc
A
2810 start:
2811 if (src2.isUndefined()) {
2812 return src1.isNull() ||
14957cd0
A
2813 (src1.isCell() && src1.asCell()->structure()->typeInfo().masqueradesAsUndefined())
2814 || src1.isUndefined();
ba379fdc
A
2815 }
2816
2817 if (src2.isNull()) {
2818 return src1.isUndefined() ||
14957cd0
A
2819 (src1.isCell() && src1.asCell()->structure()->typeInfo().masqueradesAsUndefined())
2820 || src1.isNull();
ba379fdc
A
2821 }
2822
2823 if (src1.isInt32()) {
2824 if (src2.isDouble())
2825 return src1.asInt32() == src2.asDouble();
2826 double d = src2.toNumber(stackFrame.callFrame);
2827 CHECK_FOR_EXCEPTION();
2828 return src1.asInt32() == d;
2829 }
2830
2831 if (src1.isDouble()) {
2832 if (src2.isInt32())
2833 return src1.asDouble() == src2.asInt32();
2834 double d = src2.toNumber(stackFrame.callFrame);
2835 CHECK_FOR_EXCEPTION();
2836 return src1.asDouble() == d;
2837 }
2838
2839 if (src1.isTrue()) {
2840 if (src2.isFalse())
2841 return false;
2842 double d = src2.toNumber(stackFrame.callFrame);
2843 CHECK_FOR_EXCEPTION();
2844 return d == 1.0;
2845 }
2846
2847 if (src1.isFalse()) {
2848 if (src2.isTrue())
2849 return false;
2850 double d = src2.toNumber(stackFrame.callFrame);
2851 CHECK_FOR_EXCEPTION();
2852 return d == 0.0;
2853 }
2854
2855 if (src1.isUndefined())
14957cd0 2856 return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
ba379fdc
A
2857
2858 if (src1.isNull())
14957cd0 2859 return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
ba379fdc 2860
14957cd0 2861 JSCell* cell1 = src1.asCell();
ba379fdc
A
2862
2863 if (cell1->isString()) {
2864 if (src2.isInt32())
6fe7ccc8 2865 return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32();
ba379fdc
A
2866
2867 if (src2.isDouble())
6fe7ccc8 2868 return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble();
ba379fdc
A
2869
2870 if (src2.isTrue())
6fe7ccc8 2871 return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0;
ba379fdc
A
2872
2873 if (src2.isFalse())
6fe7ccc8 2874 return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0;
ba379fdc 2875
14957cd0 2876 JSCell* cell2 = src2.asCell();
ba379fdc 2877 if (cell2->isString())
6fe7ccc8 2878 return jsCast<JSString*>(cell1)->value(stackFrame.callFrame) == jsCast<JSString*>(cell2)->value(stackFrame.callFrame);
ba379fdc 2879
f9bf01c6 2880 src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
ba379fdc
A
2881 CHECK_FOR_EXCEPTION();
2882 goto start;
2883 }
2884
ba379fdc 2885 if (src2.isObject())
f9bf01c6
A
2886 return asObject(cell1) == asObject(src2);
2887 src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame);
ba379fdc
A
2888 CHECK_FOR_EXCEPTION();
2889 goto start;
f9bf01c6
A
2890
2891#else // USE(JSVALUE32_64)
2892 CallFrame* callFrame = stackFrame.callFrame;
2893
2894 bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2);
2895 CHECK_FOR_EXCEPTION_AT_END();
2896 return result;
2897#endif // USE(JSVALUE32_64)
ba379fdc
A
2898}
2899
2900DEFINE_STUB_FUNCTION(int, op_eq_strings)
2901{
4e4e5a6f 2902#if USE(JSVALUE32_64)
ba379fdc
A
2903 STUB_INIT_STACK_FRAME(stackFrame);
2904
2905 JSString* string1 = stackFrame.args[0].jsString();
2906 JSString* string2 = stackFrame.args[1].jsString();
2907
2908 ASSERT(string1->isString());
2909 ASSERT(string2->isString());
f9bf01c6 2910 return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame);
4e4e5a6f
A
2911#else
2912 UNUSED_PARAM(args);
2913 ASSERT_NOT_REACHED();
2914 return 0;
f9bf01c6 2915#endif
4e4e5a6f 2916}
ba379fdc
A
2917
2918DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift)
2919{
2920 STUB_INIT_STACK_FRAME(stackFrame);
2921
2922 JSValue val = stackFrame.args[0].jsValue();
2923 JSValue shift = stackFrame.args[1].jsValue();
2924
2925 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 2926 JSValue result = jsNumber((val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
ba379fdc
A
2927 CHECK_FOR_EXCEPTION_AT_END();
2928 return JSValue::encode(result);
2929}
2930
2931DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitand)
2932{
2933 STUB_INIT_STACK_FRAME(stackFrame);
2934
2935 JSValue src1 = stackFrame.args[0].jsValue();
2936 JSValue src2 = stackFrame.args[1].jsValue();
2937
2938 ASSERT(!src1.isInt32() || !src2.isInt32());
2939 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 2940 JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame));
ba379fdc
A
2941 CHECK_FOR_EXCEPTION_AT_END();
2942 return JSValue::encode(result);
2943}
2944
2945DEFINE_STUB_FUNCTION(EncodedJSValue, op_rshift)
2946{
2947 STUB_INIT_STACK_FRAME(stackFrame);
2948
2949 JSValue val = stackFrame.args[0].jsValue();
2950 JSValue shift = stackFrame.args[1].jsValue();
2951
2952 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 2953 JSValue result = jsNumber((val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
ba379fdc
A
2954
2955 CHECK_FOR_EXCEPTION_AT_END();
2956 return JSValue::encode(result);
2957}
2958
6fe7ccc8 2959DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base)
ba379fdc
A
2960{
2961 STUB_INIT_STACK_FRAME(stackFrame);
2962
ba379fdc 2963 CallFrame* callFrame = stackFrame.callFrame;
6fe7ccc8 2964 JSValue result = CommonSlowPaths::opResolveWithBase(callFrame, stackFrame.args[0].identifier(), callFrame->registers()[stackFrame.args[1].int32()]);
ba379fdc
A
2965 CHECK_FOR_EXCEPTION_AT_END();
2966 return JSValue::encode(result);
2967}
2968
6fe7ccc8 2969DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_this)
ba379fdc
A
2970{
2971 STUB_INIT_STACK_FRAME(stackFrame);
2972
2973 CallFrame* callFrame = stackFrame.callFrame;
6fe7ccc8
A
2974 JSValue result = CommonSlowPaths::opResolveWithThis(callFrame, stackFrame.args[0].identifier(), callFrame->registers()[stackFrame.args[1].int32()]);
2975 CHECK_FOR_EXCEPTION_AT_END();
2976 return JSValue::encode(result);
ba379fdc
A
2977}
2978
2979DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
2980{
2981 STUB_INIT_STACK_FRAME(stackFrame);
f9bf01c6 2982 CallFrame* callFrame = stackFrame.callFrame;
ba379fdc 2983
f9bf01c6
A
2984 FunctionExecutable* function = stackFrame.args[0].function();
2985 JSFunction* func = function->make(callFrame, callFrame->scopeChain());
14957cd0 2986 ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue());
f9bf01c6
A
2987
2988 /*
2989 The Identifier in a FunctionExpression can be referenced from inside
2990 the FunctionExpression's FunctionBody to allow the function to call
2991 itself recursively. However, unlike in a FunctionDeclaration, the
2992 Identifier in a FunctionExpression cannot be referenced from and
2993 does not affect the scope enclosing the FunctionExpression.
2994 */
2995 if (!function->name().isNull()) {
6fe7ccc8 2996 JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create(callFrame, function->name(), func, ReadOnly | DontDelete);
14957cd0 2997 func->setScope(callFrame->globalData(), func->scope()->push(functionScopeObject));
f9bf01c6
A
2998 }
2999
3000 return func;
ba379fdc
A
3001}
3002
3003DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod)
3004{
3005 STUB_INIT_STACK_FRAME(stackFrame);
3006
3007 JSValue dividendValue = stackFrame.args[0].jsValue();
3008 JSValue divisorValue = stackFrame.args[1].jsValue();
3009
3010 CallFrame* callFrame = stackFrame.callFrame;
3011 double d = dividendValue.toNumber(callFrame);
14957cd0 3012 JSValue result = jsNumber(fmod(d, divisorValue.toNumber(callFrame)));
ba379fdc
A
3013 CHECK_FOR_EXCEPTION_AT_END();
3014 return JSValue::encode(result);
3015}
3016
ba379fdc
A
3017DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_dec)
3018{
3019 STUB_INIT_STACK_FRAME(stackFrame);
3020
3021 JSValue v = stackFrame.args[0].jsValue();
3022
3023 CallFrame* callFrame = stackFrame.callFrame;
3024
6fe7ccc8 3025 double number = v.toNumber(callFrame);
ba379fdc
A
3026 CHECK_FOR_EXCEPTION_AT_END();
3027
6fe7ccc8
A
3028 callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number - 1);
3029 return JSValue::encode(jsNumber(number));
ba379fdc
A
3030}
3031
3032DEFINE_STUB_FUNCTION(EncodedJSValue, op_urshift)
3033{
3034 STUB_INIT_STACK_FRAME(stackFrame);
3035
3036 JSValue val = stackFrame.args[0].jsValue();
3037 JSValue shift = stackFrame.args[1].jsValue();
3038
3039 CallFrame* callFrame = stackFrame.callFrame;
14957cd0 3040 JSValue result = jsNumber((val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
ba379fdc
A
3041 CHECK_FOR_EXCEPTION_AT_END();
3042 return JSValue::encode(result);
3043}
3044
3045DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitxor)
3046{
3047 STUB_INIT_STACK_FRAME(stackFrame);
3048
3049 JSValue src1 = stackFrame.args[0].jsValue();
3050 JSValue src2 = stackFrame.args[1].jsValue();
3051
3052 CallFrame* callFrame = stackFrame.callFrame;
3053
14957cd0 3054 JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
ba379fdc
A
3055 CHECK_FOR_EXCEPTION_AT_END();
3056 return JSValue::encode(result);
3057}
3058
3059DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp)
3060{
3061 STUB_INIT_STACK_FRAME(stackFrame);
3062
14957cd0
A
3063 CallFrame* callFrame = stackFrame.callFrame;
3064
3065 RegExp* regExp = stackFrame.args[0].regExp();
3066 if (!regExp->isValid()) {
3067 stackFrame.globalData->exception = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor.");
3068 VM_THROW_EXCEPTION();
3069 }
3070
6fe7ccc8 3071 return RegExpObject::create(*stackFrame.globalData, stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), regExp);
ba379fdc
A
3072}
3073
3074DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
3075{
3076 STUB_INIT_STACK_FRAME(stackFrame);
3077
3078 JSValue src1 = stackFrame.args[0].jsValue();
3079 JSValue src2 = stackFrame.args[1].jsValue();
3080
3081 CallFrame* callFrame = stackFrame.callFrame;
3082
14957cd0 3083 JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame));
ba379fdc
A
3084 CHECK_FOR_EXCEPTION_AT_END();
3085 return JSValue::encode(result);
3086}
3087
3088DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
3089{
3090 STUB_INIT_STACK_FRAME(stackFrame);
3091
3092 CallFrame* callFrame = stackFrame.callFrame;
6fe7ccc8
A
3093 CallFrame* callerFrame = callFrame->callerFrame();
3094 ASSERT(callFrame->callerFrame()->codeBlock()->codeType() != FunctionCode
3095 || !callFrame->callerFrame()->codeBlock()->needsFullScopeChain()
3096 || callFrame->callerFrame()->uncheckedR(callFrame->callerFrame()->codeBlock()->activationRegister()).jsValue());
ba379fdc 3097
6fe7ccc8
A
3098 callFrame->setScopeChain(callerFrame->scopeChain());
3099 callFrame->setReturnPC(static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()));
3100 callFrame->setCodeBlock(0);
ba379fdc 3101
6fe7ccc8
A
3102 if (!isHostFunction(callFrame->calleeAsValue(), globalFuncEval))
3103 return JSValue::encode(JSValue());
14957cd0 3104
6fe7ccc8
A
3105 JSValue result = eval(callFrame);
3106 if (stackFrame.globalData->exception)
3107 return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
ba379fdc 3108
6fe7ccc8 3109 return JSValue::encode(result);
ba379fdc
A
3110}
3111
14957cd0 3112DEFINE_STUB_FUNCTION(void*, op_throw)
ba379fdc
A
3113{
3114 STUB_INIT_STACK_FRAME(stackFrame);
14957cd0
A
3115 ExceptionHandler handler = jitThrow(stackFrame.globalData, stackFrame.callFrame, stackFrame.args[0].jsValue(), STUB_RETURN_ADDRESS);
3116 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
3117 return handler.callFrame;
ba379fdc
A
3118}
3119
3120DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
3121{
3122 STUB_INIT_STACK_FRAME(stackFrame);
3123
f9bf01c6
A
3124 CallFrame* callFrame = stackFrame.callFrame;
3125 JSObject* o = stackFrame.args[0].jsObject();
3126 Structure* structure = o->structure();
3127 JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
3128 if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
3129 jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
3130 return jsPropertyNameIterator;
ba379fdc
A
3131}
3132
f9bf01c6 3133DEFINE_STUB_FUNCTION(int, has_property)
ba379fdc
A
3134{
3135 STUB_INIT_STACK_FRAME(stackFrame);
3136
f9bf01c6
A
3137 JSObject* base = stackFrame.args[0].jsObject();
3138 JSString* property = stackFrame.args[1].jsString();
4e4e5a6f
A
3139 int result = base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame)));
3140 CHECK_FOR_EXCEPTION_AT_END();
3141 return result;
ba379fdc
A
3142}
3143
3144DEFINE_STUB_FUNCTION(JSObject*, op_push_scope)
3145{
3146 STUB_INIT_STACK_FRAME(stackFrame);
3147
3148 JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame);
3149 CHECK_FOR_EXCEPTION();
3150 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(o));
3151 return o;
3152}
3153
3154DEFINE_STUB_FUNCTION(void, op_pop_scope)
3155{
3156 STUB_INIT_STACK_FRAME(stackFrame);
3157
3158 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->pop());
3159}
3160
3161DEFINE_STUB_FUNCTION(EncodedJSValue, op_typeof)
3162{
3163 STUB_INIT_STACK_FRAME(stackFrame);
3164
3165 return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue()));
3166}
3167
ba379fdc
A
3168DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object)
3169{
3170 STUB_INIT_STACK_FRAME(stackFrame);
3171
3172 return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame.args[0].jsValue())));
3173}
3174
3175DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_function)
3176{
3177 STUB_INIT_STACK_FRAME(stackFrame);
3178
3179 return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame.args[0].jsValue())));
3180}
3181
3182DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq)
3183{
3184 STUB_INIT_STACK_FRAME(stackFrame);
3185
3186 JSValue src1 = stackFrame.args[0].jsValue();
3187 JSValue src2 = stackFrame.args[1].jsValue();
6fe7ccc8 3188
4e4e5a6f
A
3189 bool result = JSValue::strictEqual(stackFrame.callFrame, src1, src2);
3190 CHECK_FOR_EXCEPTION_AT_END();
3191 return JSValue::encode(jsBoolean(result));
ba379fdc
A
3192}
3193
3194DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive)
3195{
3196 STUB_INIT_STACK_FRAME(stackFrame);
3197
3198 return JSValue::encode(stackFrame.args[0].jsValue().toPrimitive(stackFrame.callFrame));
3199}
3200
3201DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat)
3202{
3203 STUB_INIT_STACK_FRAME(stackFrame);
3204
f9bf01c6
A
3205 JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
3206 CHECK_FOR_EXCEPTION_AT_END();
3207 return JSValue::encode(result);
ba379fdc
A
3208}
3209
3210DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq)
3211{
3212 STUB_INIT_STACK_FRAME(stackFrame);
3213
3214 JSValue src1 = stackFrame.args[0].jsValue();
3215 JSValue src2 = stackFrame.args[1].jsValue();
3216
4e4e5a6f
A
3217 bool result = !JSValue::strictEqual(stackFrame.callFrame, src1, src2);
3218 CHECK_FOR_EXCEPTION_AT_END();
3219 return JSValue::encode(jsBoolean(result));
ba379fdc
A
3220}
3221
3222DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber)
3223{
3224 STUB_INIT_STACK_FRAME(stackFrame);
3225
3226 JSValue src = stackFrame.args[0].jsValue();
3227 CallFrame* callFrame = stackFrame.callFrame;
3228
6fe7ccc8 3229 double number = src.toNumber(callFrame);
ba379fdc 3230 CHECK_FOR_EXCEPTION_AT_END();
6fe7ccc8 3231 return JSValue::encode(jsNumber(number));
ba379fdc
A
3232}
3233
3234DEFINE_STUB_FUNCTION(EncodedJSValue, op_in)
3235{
3236 STUB_INIT_STACK_FRAME(stackFrame);
3237
3238 CallFrame* callFrame = stackFrame.callFrame;
3239 JSValue baseVal = stackFrame.args[1].jsValue();
3240
3241 if (!baseVal.isObject()) {
14957cd0 3242 stackFrame.globalData->exception = createInvalidParamError(stackFrame.callFrame, "in", baseVal);
ba379fdc
A
3243 VM_THROW_EXCEPTION();
3244 }
3245
3246 JSValue propName = stackFrame.args[0].jsValue();
3247 JSObject* baseObj = asObject(baseVal);
3248
3249 uint32_t i;
3250 if (propName.getUInt32(i))
3251 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
3252
6fe7ccc8 3253 Identifier property(callFrame, propName.toString(callFrame)->value(callFrame));
ba379fdc
A
3254 CHECK_FOR_EXCEPTION();
3255 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
3256}
3257
3258DEFINE_STUB_FUNCTION(JSObject*, op_push_new_scope)
3259{
3260 STUB_INIT_STACK_FRAME(stackFrame);
3261
6fe7ccc8 3262 JSObject* scope = JSStaticScopeObject::create(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), DontDelete);
ba379fdc
A
3263
3264 CallFrame* callFrame = stackFrame.callFrame;
3265 callFrame->setScopeChain(callFrame->scopeChain()->push(scope));
3266 return scope;
3267}
3268
3269DEFINE_STUB_FUNCTION(void, op_jmp_scopes)
3270{
3271 STUB_INIT_STACK_FRAME(stackFrame);
3272
3273 unsigned count = stackFrame.args[0].int32();
3274 CallFrame* callFrame = stackFrame.callFrame;
3275
3276 ScopeChainNode* tmp = callFrame->scopeChain();
3277 while (count--)
3278 tmp = tmp->pop();
3279 callFrame->setScopeChain(tmp);
3280}
3281
3282DEFINE_STUB_FUNCTION(void, op_put_by_index)
3283{
3284 STUB_INIT_STACK_FRAME(stackFrame);
3285
3286 CallFrame* callFrame = stackFrame.callFrame;
3287 unsigned property = stackFrame.args[1].int32();
3288
6fe7ccc8
A
3289 JSValue arrayValue = stackFrame.args[0].jsValue();
3290 ASSERT(isJSArray(arrayValue));
3291 asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue(), false);
ba379fdc
A
3292}
3293
3294DEFINE_STUB_FUNCTION(void*, op_switch_imm)
3295{
3296 STUB_INIT_STACK_FRAME(stackFrame);
3297
3298 JSValue scrutinee = stackFrame.args[0].jsValue();
3299 unsigned tableIndex = stackFrame.args[1].int32();
3300 CallFrame* callFrame = stackFrame.callFrame;
3301 CodeBlock* codeBlock = callFrame->codeBlock();
3302
3303 if (scrutinee.isInt32())
3304 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
6fe7ccc8
A
3305 if (scrutinee.isDouble() && scrutinee.asDouble() == static_cast<int32_t>(scrutinee.asDouble()))
3306 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(static_cast<int32_t>(scrutinee.asDouble())).executableAddress();
3307 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
ba379fdc
A
3308}
3309
3310DEFINE_STUB_FUNCTION(void*, op_switch_char)
3311{
3312 STUB_INIT_STACK_FRAME(stackFrame);
3313
3314 JSValue scrutinee = stackFrame.args[0].jsValue();
3315 unsigned tableIndex = stackFrame.args[1].int32();
3316 CallFrame* callFrame = stackFrame.callFrame;
3317 CodeBlock* codeBlock = callFrame->codeBlock();
3318
3319 void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
3320
3321 if (scrutinee.isString()) {
14957cd0 3322 StringImpl* value = asString(scrutinee)->value(callFrame).impl();
4e4e5a6f 3323 if (value->length() == 1)
6fe7ccc8 3324 result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue((*value)[0]).executableAddress();
ba379fdc
A
3325 }
3326
4e4e5a6f 3327 CHECK_FOR_EXCEPTION_AT_END();
ba379fdc
A
3328 return result;
3329}
3330
3331DEFINE_STUB_FUNCTION(void*, op_switch_string)
3332{
3333 STUB_INIT_STACK_FRAME(stackFrame);
3334
3335 JSValue scrutinee = stackFrame.args[0].jsValue();
3336 unsigned tableIndex = stackFrame.args[1].int32();
3337 CallFrame* callFrame = stackFrame.callFrame;
3338 CodeBlock* codeBlock = callFrame->codeBlock();
3339
3340 void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
3341
3342 if (scrutinee.isString()) {
14957cd0 3343 StringImpl* value = asString(scrutinee)->value(callFrame).impl();
ba379fdc
A
3344 result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
3345 }
3346
4e4e5a6f 3347 CHECK_FOR_EXCEPTION_AT_END();
ba379fdc
A
3348 return result;
3349}
3350
3351DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val)
3352{
3353 STUB_INIT_STACK_FRAME(stackFrame);
3354
3355 CallFrame* callFrame = stackFrame.callFrame;
3356
3357 JSValue baseValue = stackFrame.args[0].jsValue();
3358 JSObject* baseObj = baseValue.toObject(callFrame); // may throw
3359
3360 JSValue subscript = stackFrame.args[1].jsValue();
14957cd0 3361 bool result;
ba379fdc
A
3362 uint32_t i;
3363 if (subscript.getUInt32(i))
6fe7ccc8 3364 result = baseObj->methodTable()->deletePropertyByIndex(baseObj, callFrame, i);
ba379fdc
A
3365 else {
3366 CHECK_FOR_EXCEPTION();
6fe7ccc8 3367 Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
ba379fdc 3368 CHECK_FOR_EXCEPTION();
6fe7ccc8 3369 result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, property);
ba379fdc
A
3370 }
3371
14957cd0
A
3372 if (!result && callFrame->codeBlock()->isStrictMode())
3373 stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
3374
ba379fdc 3375 CHECK_FOR_EXCEPTION_AT_END();
14957cd0 3376 return JSValue::encode(jsBoolean(result));
ba379fdc
A
3377}
3378
6fe7ccc8 3379DEFINE_STUB_FUNCTION(void, op_put_getter_setter)
ba379fdc
A
3380{
3381 STUB_INIT_STACK_FRAME(stackFrame);
3382
3383 CallFrame* callFrame = stackFrame.callFrame;
3384
3385 ASSERT(stackFrame.args[0].jsValue().isObject());
3386 JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
ba379fdc 3387
6fe7ccc8 3388 GetterSetter* accessor = GetterSetter::create(callFrame);
ba379fdc 3389
6fe7ccc8
A
3390 JSValue getter = stackFrame.args[2].jsValue();
3391 JSValue setter = stackFrame.args[3].jsValue();
3392 ASSERT(getter.isObject() || getter.isUndefined());
3393 ASSERT(setter.isObject() || setter.isUndefined());
3394 ASSERT(getter.isObject() || setter.isObject());
ba379fdc 3395
6fe7ccc8
A
3396 if (!getter.isUndefined())
3397 accessor->setGetter(callFrame->globalData(), asObject(getter));
3398 if (!setter.isUndefined())
3399 accessor->setSetter(callFrame->globalData(), asObject(setter));
3400 baseObj->putDirectAccessor(callFrame->globalData(), stackFrame.args[1].identifier(), accessor, Accessor);
ba379fdc
A
3401}
3402
14957cd0 3403DEFINE_STUB_FUNCTION(void, op_throw_reference_error)
ba379fdc
A
3404{
3405 STUB_INIT_STACK_FRAME(stackFrame);
3406
3407 CallFrame* callFrame = stackFrame.callFrame;
6fe7ccc8 3408 UString message = stackFrame.args[0].jsValue().toString(callFrame)->value(callFrame);
14957cd0
A
3409 stackFrame.globalData->exception = createReferenceError(callFrame, message);
3410 VM_THROW_EXCEPTION_AT_END();
ba379fdc
A
3411}
3412
3413DEFINE_STUB_FUNCTION(void, op_debug)
3414{
3415 STUB_INIT_STACK_FRAME(stackFrame);
3416
3417 CallFrame* callFrame = stackFrame.callFrame;
3418
3419 int debugHookID = stackFrame.args[0].int32();
3420 int firstLine = stackFrame.args[1].int32();
3421 int lastLine = stackFrame.args[2].int32();
3422
3423 stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
3424}
3425
14957cd0 3426DEFINE_STUB_FUNCTION(void*, vm_throw)
ba379fdc
A
3427{
3428 STUB_INIT_STACK_FRAME(stackFrame);
ba379fdc 3429 JSGlobalData* globalData = stackFrame.globalData;
14957cd0
A
3430 ExceptionHandler handler = jitThrow(globalData, stackFrame.callFrame, globalData->exception, globalData->exceptionLocation);
3431 STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
3432 return handler.callFrame;
ba379fdc
A
3433}
3434
f9bf01c6
A
3435DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
3436{
3437 STUB_INIT_STACK_FRAME(stackFrame);
3438
3439 CallFrame* callFrame = stackFrame.callFrame;
3440 return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
3441}
3442
6fe7ccc8 3443MacroAssemblerCodeRef JITThunks::ctiStub(JSGlobalData* globalData, ThunkGenerator generator)
14957cd0 3444{
6fe7ccc8
A
3445 CTIStubMap::AddResult entry = m_ctiStubMap.add(generator, MacroAssemblerCodeRef());
3446 if (entry.isNewEntry)
3447 entry.iterator->second = generator(globalData);
3448 return entry.iterator->second;
14957cd0
A
3449}
3450
6fe7ccc8 3451NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, NativeFunction constructor)
4e4e5a6f 3452{
6fe7ccc8
A
3453 HostFunctionStubMap::AddResult result = m_hostFunctionStubMap->add(function, PassWeak<NativeExecutable>());
3454 if (!result.iterator->second)
3455 result.iterator->second = PassWeak<NativeExecutable>(NativeExecutable::create(*globalData, JIT::compileCTINativeCall(globalData, function), function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), constructor, NoIntrinsic));
3456 return result.iterator->second.get();
4e4e5a6f
A
3457}
3458
6fe7ccc8 3459NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator, Intrinsic intrinsic)
14957cd0 3460{
6fe7ccc8
A
3461 HostFunctionStubMap::AddResult entry = m_hostFunctionStubMap->add(function, PassWeak<NativeExecutable>());
3462 if (!entry.iterator->second) {
3463 MacroAssemblerCodeRef code;
3464 if (generator) {
3465 if (globalData->canUseJIT())
3466 code = generator(globalData);
3467 else
3468 code = MacroAssemblerCodeRef();
3469 } else
3470 code = JIT::compileCTINativeCall(globalData, function);
3471 entry.iterator->second = PassWeak<NativeExecutable>(NativeExecutable::create(*globalData, code, function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), callHostFunctionAsConstructor, intrinsic));
14957cd0 3472 }
6fe7ccc8 3473 return entry.iterator->second.get();
14957cd0
A
3474}
3475
3476void JITThunks::clearHostFunctionStubs()
3477{
3478 m_hostFunctionStubMap.clear();
3479}
3480
ba379fdc
A
3481} // namespace JSC
3482
3483#endif // ENABLE(JIT)