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

source code of qtscript/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubs.cpp