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