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