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