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 
67 using namespace std;
68 
69 namespace 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.
114 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
115 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
116 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
117 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
118 
119 asm volatile (
120 ".text\n"
121 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
122 HIDE_SYMBOL(ctiTrampoline) "\n"
123 SYMBOL_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 
141 asm volatile (
142 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
143 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
144 SYMBOL_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 
157 asm volatile (
158 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
159 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
160 SYMBOL_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.
177 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment);
178 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
179 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
180 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline);
181 
182 asm volatile (
183 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
184 HIDE_SYMBOL(ctiTrampoline) "\n"
185 SYMBOL_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 
209 asm volatile (
210 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
211 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
212 SYMBOL_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 
225 asm volatile (
226 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
227 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
228 SYMBOL_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 
245 asm volatile (
246 ".text" "\n"
247 ".align 2" "\n"
248 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
249 HIDE_SYMBOL(ctiTrampoline) "\n"
250 ".thumb" "\n"
251 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
252 SYMBOL_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 
272 asm volatile (
273 ".text" "\n"
274 ".align 2" "\n"
275 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
276 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
277 ".thumb" "\n"
278 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
279 SYMBOL_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 
290 asm volatile (
291 ".text" "\n"
292 ".align 2" "\n"
293 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
294 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
295 ".thumb" "\n"
296 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
297 SYMBOL_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 
308 asm volatile (
309 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
310 HIDE_SYMBOL(ctiTrampoline) "\n"
311 SYMBOL_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 
326 asm volatile (
327 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
328 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
329 SYMBOL_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"
335 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
336 SYMBOL_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.
351 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
352 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
353 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
354 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
355 
356 extern "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.
417 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
418 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline);
419 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
420 
421 asm volatile (
422 ".text\n"
423 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
424 HIDE_SYMBOL(ctiTrampoline) "\n"
425 SYMBOL_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 
443 asm volatile (
444 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
445 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
446 SYMBOL_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 
459 asm volatile (
460 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
461 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
462 SYMBOL_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.
479 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
480 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline);
481 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
482 
483 asm volatile (
484 ".text\n"
485 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
486 HIDE_SYMBOL(ctiTrampoline) "\n"
487 SYMBOL_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 
518 asm volatile (
519 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
520 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
521 SYMBOL_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 
534 asm volatile (
535 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
536 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
537 SYMBOL_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 
554 asm volatile (
555 ".text" "\n"
556 ".align 2" "\n"
557 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
558 HIDE_SYMBOL(ctiTrampoline) "\n"
559 ".thumb" "\n"
560 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n"
561 SYMBOL_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 
581 asm volatile (
582 ".text" "\n"
583 ".align 2" "\n"
584 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
585 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
586 ".thumb" "\n"
587 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
588 SYMBOL_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 
599 asm volatile (
600 ".text" "\n"
601 ".align 2" "\n"
602 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
603 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
604 ".thumb" "\n"
605 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
606 SYMBOL_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 
617 asm volatile (
618 ".text\n"
619 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
620 HIDE_SYMBOL(ctiTrampoline) "\n"
621 SYMBOL_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 
635 asm volatile (
636 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
637 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
638 SYMBOL_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"
644 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
645 SYMBOL_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.
699 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
700 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline);
701 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
702 
703 extern "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 
JITThunks(JSGlobalData * globalData)766 JITThunks::JITThunks(JSGlobalData* globalData)
767 {
768     JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &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 
tryCachePutByID(CallFrame * callFrame,CodeBlock * codeBlock,ReturnAddressPtr returnAddress,JSValue baseValue,const PutPropertySlot & slot,StructureStubInfo * stubInfo)791 NEVER_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, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
801         return;
802     }
803 
804     JSCell* baseCell = asCell(baseValue);
805     Structure* structure = baseCell->structure();
806 
807     if (structure->isUncacheableDictionary()) {
808         ctiPatchCallByReturnAddress(codeBlock, returnAddress, 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, returnAddress, 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, returnAddress, 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, baseCell);
829 
830         StructureChain* prototypeChain = structure->prototypeChain(callFrame);
831         stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
832         JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress);
833         return;
834     }
835 
836     stubInfo->initPutByIdReplace(structure);
837 
838     JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
839 }
840 
tryCacheGetByID(CallFrame * callFrame,CodeBlock * codeBlock,ReturnAddressPtr returnAddress,JSValue baseValue,const Identifier & propertyName,const PropertySlot & slot,StructureStubInfo * stubInfo)841 NEVER_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, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
849         return;
850     }
851 
852     JSGlobalData* globalData = &callFrame->globalData();
853 
854     if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
855         JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
856         return;
857     }
858 
859     if (isJSString(globalData, 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, returnAddress, globalData->jitStubs.ctiStringLengthTrampoline());
863         return;
864     }
865 
866     // Uncacheable: give up.
867     if (!slot.isCacheable()) {
868         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
869         return;
870     }
871 
872     JSCell* baseCell = asCell(baseValue);
873     Structure* structure = baseCell->structure();
874 
875     if (structure->isUncacheableDictionary()) {
876         ctiPatchCallByReturnAddress(codeBlock, returnAddress, 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(structure);
885 
886         JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
887         return;
888     }
889 
890     if (structure->isDictionary()) {
891         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
892         return;
893     }
894 
895     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
896         ASSERT(slot.slotBase().isObject());
897 
898         JSObject* slotBaseObject = asObject(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(structure, slotBaseObject->structure());
909 
910         ASSERT(!structure->isDictionary());
911         ASSERT(!slotBaseObject->structure()->isDictionary());
912         JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), offset, returnAddress);
913         return;
914     }
915 
916     size_t offset = slot.cachedOffset();
917     size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
918     if (!count) {
919         stubInfo->accessType = access_get_by_id_generic;
920         return;
921     }
922 
923     StructureChain* prototypeChain = structure->prototypeChain(callFrame);
924     stubInfo->initGetByIdChain(structure, prototypeChain);
925     JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, 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 
938 extern "C" {
939 
jscGeneratedNativeCode()940 static 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 
949 struct StackHack {
StackHackJSC::StackHack950     ALWAYS_INLINE StackHack(JITStackFrame& stackFrame)
951         : stackFrame(stackFrame)
952         , savedReturnAddress(*stackFrame.returnAddressSlot())
953     {
954         *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
955     }
956 
~StackHackJSC::StackHack957     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.
returnToThrowTrampoline(JSGlobalData * globalData,ReturnAddressPtr exceptionLocation,ReturnAddressPtr & returnAddressSlot)982 static 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 
throwStackOverflowError(CallFrame * callFrame,JSGlobalData * globalData,ReturnAddressPtr exceptionLocation,ReturnAddressPtr & returnAddressSlot)989 static 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 volatile ( \
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 
1050 COMPILE_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 volatile ( \
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 /*
1077 RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
1078 RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
1079 RVCT({)
1080 RVCT(    ARM)
1081 RVCT(    IMPORT JITStubThunked_#op#)
1082 RVCT(    str lr, [sp, #32])
1083 RVCT(    bl JITStubThunked_#op#)
1084 RVCT(    ldr lr, [sp, #32])
1085 RVCT(    bx lr)
1086 RVCT(})
1087 RVCT()
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 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_convert_this)1101 DEFINE_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(callFrame);
1109     CHECK_FOR_EXCEPTION_AT_END();
1110     return JSValue::encode(result);
1111 }
1112 
DEFINE_STUB_FUNCTION(void,op_end)1113 DEFINE_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 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_add)1122 DEFINE_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(callFrame, asString(v1), asString(v2))
1133             : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
1134         CHECK_FOR_EXCEPTION_AT_END();
1135         return JSValue::encode(result);
1136     }
1137 
1138     double left = 0.0, right;
1139     if (v1.getNumber(left) && v2.getNumber(right))
1140         return JSValue::encode(jsNumber(stackFrame.globalData, 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(result);
1146 }
1147 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_pre_inc)1148 DEFINE_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(stackFrame.globalData, v.toNumber(callFrame) + 1);
1156     CHECK_FOR_EXCEPTION_AT_END();
1157     return JSValue::encode(result);
1158 }
1159 
DEFINE_STUB_FUNCTION(int,timeout_check)1160 DEFINE_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 QtScript'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 
DEFINE_STUB_FUNCTION(void,register_file_check)1185 DEFINE_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(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS);
1197 }
1198 
DEFINE_STUB_FUNCTION(int,op_loop_if_lesseq)1199 DEFINE_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, src1, src2);
1208     CHECK_FOR_EXCEPTION_AT_END();
1209     return result;
1210 }
1211 
DEFINE_STUB_FUNCTION(JSObject *,op_new_object)1212 DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
1213 {
1214     STUB_INIT_STACK_FRAME(stackFrame);
1215 
1216     return constructEmptyObject(stackFrame.callFrame);
1217 }
1218 
DEFINE_STUB_FUNCTION(void,op_put_by_id_generic)1219 DEFINE_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(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
1225     CHECK_FOR_EXCEPTION_AT_END();
1226 }
1227 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_id_generic)1228 DEFINE_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(callFrame, ident, slot);
1238 
1239     CHECK_FOR_EXCEPTION_AT_END();
1240     return JSValue::encode(result);
1241 }
1242 
1243 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1244 
DEFINE_STUB_FUNCTION(void,op_put_by_id)1245 DEFINE_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(callFrame, ident, 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, stackFrame.args[0].jsValue(), slot, stubInfo);
1260 
1261     CHECK_FOR_EXCEPTION_AT_END();
1262 }
1263 
DEFINE_STUB_FUNCTION(void,op_put_by_id_fail)1264 DEFINE_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(callFrame, ident, stackFrame.args[2].jsValue(), slot);
1273 
1274     CHECK_FOR_EXCEPTION_AT_END();
1275 }
1276 
DEFINE_STUB_FUNCTION(JSObject *,op_put_by_id_transition_realloc)1277 DEFINE_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(baseValue);
1287     base->allocatePropertyStorage(oldSize, newSize);
1288 
1289     return base;
1290 }
1291 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_id_method_check)1292 DEFINE_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(callFrame, 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(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(baseValue)->structure())->isUncacheableDictionary()
1328         && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, 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(callFrame)) {
1344             JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
1345             return JSValue::encode(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, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
1356             return JSValue::encode(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, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
1362     return JSValue::encode(result);
1363 }
1364 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_id)1365 DEFINE_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(callFrame, 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, ident, slot, stubInfo);
1381 
1382     CHECK_FOR_EXCEPTION_AT_END();
1383     return JSValue::encode(result);
1384 }
1385 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_id_self_fail)1386 DEFINE_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(callFrame, ident, slot);
1396 
1397     CHECK_FOR_EXCEPTION();
1398 
1399     if (baseValue.isCell()
1400         && slot.isCacheable()
1401         && !asCell(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(polymorphicStructureList, 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(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset());
1423 
1424         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1425             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
1426     } else
1427         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
1428     return JSValue::encode(result);
1429 }
1430 
getPolymorphicAccessStructureListSlot(StructureStubInfo * stubInfo,int & listIndex)1431 static 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(prototypeStructureList, 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(prototypeStructureList, 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 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_id_proto_list)1460 DEFINE_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(callFrame, propertyName, slot);
1470 
1471     CHECK_FOR_EXCEPTION();
1472 
1473     if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
1474         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1475         return JSValue::encode(result);
1476     }
1477 
1478     Structure* structure = asCell(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(slot.slotBase());
1484 
1485     size_t offset = slot.cachedOffset();
1486 
1487     if (slot.slotBase() == baseValue)
1488         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1489     else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(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(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), offset);
1502 
1503         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1504             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
1505     } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
1506         ASSERT(!asCell(baseValue)->structure()->isDictionary());
1507         int listIndex;
1508         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
1509 
1510         StructureChain* protoChain = structure->prototypeChain(callFrame);
1511         JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, offset);
1512 
1513         if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
1514             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
1515     } else
1516         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
1517 
1518     return JSValue::encode(result);
1519 }
1520 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_id_proto_list_full)1521 DEFINE_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(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1528 
1529     CHECK_FOR_EXCEPTION_AT_END();
1530     return JSValue::encode(result);
1531 }
1532 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_id_proto_fail)1533 DEFINE_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(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1540 
1541     CHECK_FOR_EXCEPTION_AT_END();
1542     return JSValue::encode(result);
1543 }
1544 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_id_array_fail)1545 DEFINE_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(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1552 
1553     CHECK_FOR_EXCEPTION_AT_END();
1554     return JSValue::encode(result);
1555 }
1556 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_id_string_fail)1557 DEFINE_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(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
1564 
1565     CHECK_FOR_EXCEPTION_AT_END();
1566     return JSValue::encode(result);
1567 }
1568 
1569 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1570 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_instanceof)1571 DEFINE_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(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, "instanceof", baseVal, 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(jsBoolean(false));
1601 
1602         if (!proto.isObject()) {
1603             throwError(callFrame, TypeError, "instanceof called on an object with an invalid prototype property.");
1604             VM_THROW_EXCEPTION();
1605         }
1606     }
1607 
1608     JSValue result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
1609     CHECK_FOR_EXCEPTION_AT_END();
1610 
1611     return JSValue::encode(result);
1612 }
1613 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_del_by_id)1614 DEFINE_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(callFrame);
1621 
1622     JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier()));
1623     CHECK_FOR_EXCEPTION_AT_END();
1624     return JSValue::encode(result);
1625 }
1626 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_mul)1627 DEFINE_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(left) && src2.getNumber(right))
1637         return JSValue::encode(jsNumber(stackFrame.globalData, left * right));
1638 
1639     CallFrame* callFrame = stackFrame.callFrame;
1640     JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) * src2.toNumber(callFrame));
1641     CHECK_FOR_EXCEPTION_AT_END();
1642     return JSValue::encode(result);
1643 }
1644 
DEFINE_STUB_FUNCTION(JSObject *,op_new_func)1645 DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
1646 {
1647     STUB_INIT_STACK_FRAME(stackFrame);
1648 
1649     return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
1650 }
1651 
DEFINE_STUB_FUNCTION(void *,op_call_JSFunction)1652 DEFINE_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(stackFrame.args[0].jsValue());
1662     ASSERT(!function->isHostFunction());
1663     FunctionExecutable* executable = function->jsExecutable();
1664     ScopeChainNode* callDataScopeChain = function->scope().node();
1665     executable->jitCode(stackFrame.callFrame, callDataScopeChain);
1666 
1667     return function;
1668 }
1669 
DEFINE_STUB_FUNCTION(VoidPtrPair,op_call_arityCheck)1670 DEFINE_STUB_FUNCTION(VoidPtrPair, op_call_arityCheck)
1671 {
1672     STUB_INIT_STACK_FRAME(stackFrame);
1673 
1674     CallFrame* callFrame = stackFrame.callFrame;
1675     JSFunction* callee = asFunction(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(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(oldCallFrame, stackFrame.globalData, 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(r);
1711         callFrame->setCallerFrame(oldCallFrame);
1712     }
1713 
1714     RETURN_POINTER_PAIR(callee, callFrame);
1715 }
1716 
1717 #if ENABLE(JIT_OPTIMIZE_CALL)
DEFINE_STUB_FUNCTION(void *,vm_lazyLinkCall)1718 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
1719 {
1720     STUB_INIT_STACK_FRAME(stackFrame);
1721     JSFunction* callee = asFunction(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(stackFrame.callFrame, callee->scope().node());
1728     CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress());
1729 
1730     if (!callLinkInfo->seenOnce())
1731         callLinkInfo->setSeen();
1732     else
1733         JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData);
1734 
1735     return jitCode.addressForCall().executableAddress();
1736 }
1737 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
1738 
DEFINE_STUB_FUNCTION(JSObject *,op_push_activation)1739 DEFINE_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(activation));
1745     return activation;
1746 }
1747 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_call_NotJSFunction)1748 DEFINE_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(previousCallFrame->registers() + registerOffset);
1764 
1765         callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0);
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(funcVal), thisValue, argList);
1781         }
1782         stackFrame.callFrame = previousCallFrame;
1783         CHECK_FOR_EXCEPTION();
1784 
1785         return JSValue::encode(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, vPCIndex, codeBlock);
1794     VM_THROW_EXCEPTION();
1795 }
1796 
DEFINE_STUB_FUNCTION(void,op_create_arguments)1797 DEFINE_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 
DEFINE_STUB_FUNCTION(void,op_create_arguments_no_params)1806 DEFINE_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 
DEFINE_STUB_FUNCTION(void,op_tear_off_activation)1815 DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
1816 {
1817     STUB_INIT_STACK_FRAME(stackFrame);
1818 
1819     ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
1820     asActivation(stackFrame.args[0].jsValue())->copyRegisters(stackFrame.callFrame->optionalCalleeArguments());
1821 }
1822 
DEFINE_STUB_FUNCTION(void,op_tear_off_arguments)1823 DEFINE_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 
DEFINE_STUB_FUNCTION(void,op_profile_will_call)1832 DEFINE_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, stackFrame.args[0].jsValue());
1838 }
1839 
DEFINE_STUB_FUNCTION(void,op_profile_did_call)1840 DEFINE_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, stackFrame.args[0].jsValue());
1846 }
1847 
DEFINE_STUB_FUNCTION(void,op_ret_scopeChain)1848 DEFINE_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 
DEFINE_STUB_FUNCTION(JSObject *,op_new_array)1856 DEFINE_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(stackFrame.callFrame, argList);
1862 }
1863 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_resolve)1864 DEFINE_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(callFrame, ident, slot)) {
1880             JSValue result = slot.getValue(callFrame, ident);
1881             CHECK_FOR_EXCEPTION_AT_END();
1882             return JSValue::encode(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, vPCIndex, codeBlock);
1889     VM_THROW_EXCEPTION();
1890 }
1891 
DEFINE_STUB_FUNCTION(JSObject *,op_construct_JSConstruct)1892 DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct)
1893 {
1894     STUB_INIT_STACK_FRAME(stackFrame);
1895 
1896     JSFunction* constructor = asFunction(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, 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(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 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_construct_NotJSConstruct)1922 DEFINE_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(constrVal), argList);
1942         }
1943         CHECK_FOR_EXCEPTION();
1944 
1945         return JSValue::encode(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, vPCIndex, codeBlock);
1953     VM_THROW_EXCEPTION();
1954 }
1955 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_val)1956 DEFINE_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, baseValue)) {
1971             JSArray* jsArray = asArray(baseValue);
1972             if (jsArray->canGetIndex(i))
1973                 result = jsArray->getIndex(i);
1974             else
1975                 result = jsArray->JSArray::get(callFrame, i);
1976         } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
1977             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1978             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
1979             result = asString(baseValue)->getIndex(callFrame, i);
1980         } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
1981             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
1982             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
1983             return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
1984         } else
1985             result = baseValue.get(callFrame, i);
1986     } else {
1987         Identifier property(callFrame, subscript.toString(callFrame));
1988         result = baseValue.get(callFrame, property);
1989     }
1990 
1991     CHECK_FOR_EXCEPTION_AT_END();
1992     return JSValue::encode(result);
1993 }
1994 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_val_string)1995 DEFINE_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, baseValue) && asString(baseValue)->canGetIndex(i))
2010             result = asString(baseValue)->getIndex(callFrame, i);
2011         else {
2012             result = baseValue.get(callFrame, i);
2013             if (!isJSString(globalData, baseValue))
2014                 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
2015         }
2016     } else {
2017         Identifier property(callFrame, subscript.toString(callFrame));
2018         result = baseValue.get(callFrame, property);
2019     }
2020 
2021     CHECK_FOR_EXCEPTION_AT_END();
2022     return JSValue::encode(result);
2023 }
2024 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_get_by_val_byte_array)2025 DEFINE_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, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2040             // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
2041             return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
2042         }
2043 
2044         result = baseValue.get(callFrame, i);
2045         if (!isJSByteArray(globalData, baseValue))
2046             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
2047     } else {
2048         Identifier property(callFrame, subscript.toString(callFrame));
2049         result = baseValue.get(callFrame, property);
2050     }
2051 
2052     CHECK_FOR_EXCEPTION_AT_END();
2053     return JSValue::encode(result);
2054 }
2055 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_sub)2056 DEFINE_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(left) && src2.getNumber(right))
2066         return JSValue::encode(jsNumber(stackFrame.globalData, left - right));
2067 
2068     CallFrame* callFrame = stackFrame.callFrame;
2069     JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) - src2.toNumber(callFrame));
2070     CHECK_FOR_EXCEPTION_AT_END();
2071     return JSValue::encode(result);
2072 }
2073 
DEFINE_STUB_FUNCTION(void,op_put_by_val)2074 DEFINE_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, baseValue)) {
2088             JSArray* jsArray = asArray(baseValue);
2089             if (jsArray->canSetIndex(i))
2090                 jsArray->setIndex(i, value);
2091             else
2092                 jsArray->JSArray::put(callFrame, i, value);
2093         } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2094             JSByteArray* jsByteArray = asByteArray(baseValue);
2095             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, 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.asInt32());
2099                 return;
2100             } else {
2101                 double dValue = 0;
2102                 if (value.getNumber(dValue)) {
2103                     jsByteArray->setIndex(i, dValue);
2104                     return;
2105                 }
2106             }
2107 
2108             baseValue.put(callFrame, i, value);
2109         } else
2110             baseValue.put(callFrame, i, value);
2111     } else {
2112         Identifier property(callFrame, subscript.toString(callFrame));
2113         if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
2114             PutPropertySlot slot;
2115             baseValue.put(callFrame, property, value, slot);
2116         }
2117     }
2118 
2119     CHECK_FOR_EXCEPTION_AT_END();
2120 }
2121 
DEFINE_STUB_FUNCTION(void,op_put_by_val_byte_array)2122 DEFINE_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, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2136             JSByteArray* jsByteArray = asByteArray(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.asInt32());
2141                 return;
2142             } else {
2143                 double dValue = 0;
2144                 if (value.getNumber(dValue)) {
2145                     jsByteArray->setIndex(i, dValue);
2146                     return;
2147                 }
2148             }
2149         }
2150 
2151         if (!isJSByteArray(globalData, baseValue))
2152             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
2153         baseValue.put(callFrame, i, value);
2154     } else {
2155         Identifier property(callFrame, subscript.toString(callFrame));
2156         if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
2157             PutPropertySlot slot;
2158             baseValue.put(callFrame, property, value, slot);
2159         }
2160     }
2161 
2162     CHECK_FOR_EXCEPTION_AT_END();
2163 }
2164 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_lesseq)2165 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
2166 {
2167     STUB_INIT_STACK_FRAME(stackFrame);
2168 
2169     CallFrame* callFrame = stackFrame.callFrame;
2170     JSValue result = jsBoolean(jsLessEq(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
2171     CHECK_FOR_EXCEPTION_AT_END();
2172     return JSValue::encode(result);
2173 }
2174 
DEFINE_STUB_FUNCTION(int,op_load_varargs)2175 DEFINE_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(callFrame->callee())->jsExecutable()->parameterCount();
2194         int32_t inplaceArgs = min(providedParams, 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, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
2217             VM_THROW_EXCEPTION();
2218         }
2219         if (asObject(arguments)->classInfo() == &Arguments::info) {
2220             Arguments* argsObject = asArguments(arguments);
2221             argCount = argsObject->numProvidedArguments(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(callFrame, callFrame->registers() + argsOffset, argCount);
2229         } else if (isJSArray(&callFrame->globalData(), arguments)) {
2230             JSArray* array = asArray(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(arguments)->inherits(&JSArray::info)) {
2240             JSObject* argObject = asObject(arguments);
2241             argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(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(arguments)->get(callFrame, 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, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
2257             VM_THROW_EXCEPTION();
2258         }
2259     }
2260 
2261     return argCount + 1;
2262 }
2263 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_negate)2264 DEFINE_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(v))
2272         return JSValue::encode(jsNumber(stackFrame.globalData, -v));
2273 
2274     CallFrame* callFrame = stackFrame.callFrame;
2275     JSValue result = jsNumber(stackFrame.globalData, -src.toNumber(callFrame));
2276     CHECK_FOR_EXCEPTION_AT_END();
2277     return JSValue::encode(result);
2278 }
2279 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_resolve_base)2280 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base)
2281 {
2282     STUB_INIT_STACK_FRAME(stackFrame);
2283 
2284     return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain()));
2285 }
2286 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_resolve_skip)2287 DEFINE_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(callFrame, ident, slot)) {
2308             JSValue result = slot.getValue(callFrame, ident);
2309             CHECK_FOR_EXCEPTION_AT_END();
2310             return JSValue::encode(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, vPCIndex, codeBlock);
2317     VM_THROW_EXCEPTION();
2318 }
2319 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_resolve_global)2320 DEFINE_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(callFrame, ident, slot)) {
2332         JSValue result = slot.getValue(callFrame, ident);
2333         if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
2334             GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(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(result);
2341         }
2342 
2343         CHECK_FOR_EXCEPTION_AT_END();
2344         return JSValue::encode(result);
2345     }
2346 
2347     unsigned vPCIndex = callFrame->codeBlock()->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
2348     stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, callFrame->codeBlock());
2349     VM_THROW_EXCEPTION();
2350 }
2351 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_div)2352 DEFINE_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(left) && src2.getNumber(right))
2362         return JSValue::encode(jsNumber(stackFrame.globalData, left / right));
2363 
2364     CallFrame* callFrame = stackFrame.callFrame;
2365     JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) / src2.toNumber(callFrame));
2366     CHECK_FOR_EXCEPTION_AT_END();
2367     return JSValue::encode(result);
2368 }
2369 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_pre_dec)2370 DEFINE_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(stackFrame.globalData, v.toNumber(callFrame) - 1);
2378     CHECK_FOR_EXCEPTION_AT_END();
2379     return JSValue::encode(result);
2380 }
2381 
DEFINE_STUB_FUNCTION(int,op_jless)2382 DEFINE_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, src1, src2);
2391     CHECK_FOR_EXCEPTION_AT_END();
2392     return result;
2393 }
2394 
DEFINE_STUB_FUNCTION(int,op_jlesseq)2395 DEFINE_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, src1, src2);
2404     CHECK_FOR_EXCEPTION_AT_END();
2405     return result;
2406 }
2407 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_not)2408 DEFINE_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(!src.toBoolean(callFrame));
2417     CHECK_FOR_EXCEPTION_AT_END();
2418     return JSValue::encode(result);
2419 }
2420 
DEFINE_STUB_FUNCTION(int,op_jtrue)2421 DEFINE_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(callFrame);
2430     CHECK_FOR_EXCEPTION_AT_END();
2431     return result;
2432 }
2433 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_post_inc)2434 DEFINE_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(callFrame);
2443     CHECK_FOR_EXCEPTION_AT_END();
2444 
2445     callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(stackFrame.globalData, number.uncheckedGetNumber() + 1);
2446     return JSValue::encode(number);
2447 }
2448 
DEFINE_STUB_FUNCTION(int,op_eq)2449 DEFINE_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(callFrame, src1, src2);
2547     CHECK_FOR_EXCEPTION_AT_END();
2548     return result;
2549 #endif // USE(JSVALUE32_64)
2550 }
2551 
2552 #if USE(JSVALUE32_64)
2553 
DEFINE_STUB_FUNCTION(int,op_eq_strings)2554 DEFINE_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 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_lshift)2568 DEFINE_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(stackFrame.globalData, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
2577     CHECK_FOR_EXCEPTION_AT_END();
2578     return JSValue::encode(result);
2579 }
2580 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_bitand)2581 DEFINE_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(stackFrame.globalData, src1.toInt32(callFrame) & src2.toInt32(callFrame));
2591     CHECK_FOR_EXCEPTION_AT_END();
2592     return JSValue::encode(result);
2593 }
2594 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_rshift)2595 DEFINE_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(stackFrame.globalData, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
2604 
2605     CHECK_FOR_EXCEPTION_AT_END();
2606     return JSValue::encode(result);
2607 }
2608 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_bitnot)2609 DEFINE_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(stackFrame.globalData, ~src.toInt32(callFrame));
2618     CHECK_FOR_EXCEPTION_AT_END();
2619     return JSValue::encode(result);
2620 }
2621 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_resolve_with_base)2622 DEFINE_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(callFrame, ident, slot)) {
2642             JSValue result = slot.getValue(callFrame, ident);
2643             CHECK_FOR_EXCEPTION_AT_END();
2644 
2645             callFrame->registers()[stackFrame.args[1].int32()] = JSValue(base);
2646             return JSValue::encode(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, vPCIndex, codeBlock);
2654     VM_THROW_EXCEPTION_AT_END();
2655     return JSValue::encode(JSValue());
2656 }
2657 
DEFINE_STUB_FUNCTION(JSObject *,op_new_func_exp)2658 DEFINE_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(callFrame, 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(functionScopeObject);
2676     }
2677 
2678     return func;
2679 }
2680 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_mod)2681 DEFINE_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(callFrame);
2690     JSValue result = jsNumber(stackFrame.globalData, fmod(d, divisorValue.toNumber(callFrame)));
2691     CHECK_FOR_EXCEPTION_AT_END();
2692     return JSValue::encode(result);
2693 }
2694 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_less)2695 DEFINE_STUB_FUNCTION(EncodedJSValue, op_less)
2696 {
2697     STUB_INIT_STACK_FRAME(stackFrame);
2698 
2699     CallFrame* callFrame = stackFrame.callFrame;
2700     JSValue result = jsBoolean(jsLess(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
2701     CHECK_FOR_EXCEPTION_AT_END();
2702     return JSValue::encode(result);
2703 }
2704 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_post_dec)2705 DEFINE_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(callFrame);
2714     CHECK_FOR_EXCEPTION_AT_END();
2715 
2716     callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(stackFrame.globalData, number.uncheckedGetNumber() - 1);
2717     return JSValue::encode(number);
2718 }
2719 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_urshift)2720 DEFINE_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(stackFrame.globalData, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
2729     CHECK_FOR_EXCEPTION_AT_END();
2730     return JSValue::encode(result);
2731 }
2732 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_bitxor)2733 DEFINE_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(stackFrame.globalData, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
2743     CHECK_FOR_EXCEPTION_AT_END();
2744     return JSValue::encode(result);
2745 }
2746 
DEFINE_STUB_FUNCTION(JSObject *,op_new_regexp)2747 DEFINE_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 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_bitor)2754 DEFINE_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(stackFrame.globalData, src1.toInt32(callFrame) | src2.toInt32(callFrame));
2764     CHECK_FOR_EXCEPTION_AT_END();
2765     return JSValue::encode(result);
2766 }
2767 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_call_eval)2768 DEFINE_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, argCount, registerOffset, exceptionValue);
2789         if (UNLIKELY(exceptionValue)) {
2790             stackFrame.globalData->exception = exceptionValue;
2791             VM_THROW_EXCEPTION_AT_END();
2792         }
2793         return JSValue::encode(result);
2794     }
2795 
2796     return JSValue::encode(JSValue());
2797 }
2798 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_throw)2799 DEFINE_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, vPCIndex, true);
2812 
2813     if (!handler) {
2814         *stackFrame.exception = exceptionValue;
2815         STUB_SET_RETURN_ADDRESS(FunctionPtr(ctiOpThrowNotCaught).value());
2816         return JSValue::encode(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(exceptionValue);
2824 }
2825 
DEFINE_STUB_FUNCTION(JSPropertyNameIterator *,op_get_pnames)2826 DEFINE_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(callFrame))
2835         jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
2836     return jsPropertyNameIterator;
2837 }
2838 
DEFINE_STUB_FUNCTION(int,has_property)2839 DEFINE_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, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame)));
2846 }
2847 
DEFINE_STUB_FUNCTION(JSObject *,op_push_scope)2848 DEFINE_STUB_FUNCTION(JSObject*, op_push_scope)
2849 {
2850     STUB_INIT_STACK_FRAME(stackFrame);
2851 
2852     JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame);
2853     CHECK_FOR_EXCEPTION();
2854     stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(o));
2855     return o;
2856 }
2857 
DEFINE_STUB_FUNCTION(void,op_pop_scope)2858 DEFINE_STUB_FUNCTION(void, op_pop_scope)
2859 {
2860     STUB_INIT_STACK_FRAME(stackFrame);
2861 
2862     stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->pop());
2863 }
2864 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_typeof)2865 DEFINE_STUB_FUNCTION(EncodedJSValue, op_typeof)
2866 {
2867     STUB_INIT_STACK_FRAME(stackFrame);
2868 
2869     return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue()));
2870 }
2871 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_is_undefined)2872 DEFINE_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(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
2878 }
2879 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_is_boolean)2880 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_boolean)
2881 {
2882     STUB_INIT_STACK_FRAME(stackFrame);
2883 
2884     return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isBoolean()));
2885 }
2886 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_is_number)2887 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_number)
2888 {
2889     STUB_INIT_STACK_FRAME(stackFrame);
2890 
2891     return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isNumber()));
2892 }
2893 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_is_string)2894 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_string)
2895 {
2896     STUB_INIT_STACK_FRAME(stackFrame);
2897 
2898     return JSValue::encode(jsBoolean(isJSString(stackFrame.globalData, stackFrame.args[0].jsValue())));
2899 }
2900 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_is_object)2901 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object)
2902 {
2903     STUB_INIT_STACK_FRAME(stackFrame);
2904 
2905     return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame.args[0].jsValue())));
2906 }
2907 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_is_function)2908 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_function)
2909 {
2910     STUB_INIT_STACK_FRAME(stackFrame);
2911 
2912     return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame.args[0].jsValue())));
2913 }
2914 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_stricteq)2915 DEFINE_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(jsBoolean(JSValue::strictEqual(stackFrame.callFrame, src1, src2)));
2923 }
2924 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_to_primitive)2925 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive)
2926 {
2927     STUB_INIT_STACK_FRAME(stackFrame);
2928 
2929     return JSValue::encode(stackFrame.args[0].jsValue().toPrimitive(stackFrame.callFrame));
2930 }
2931 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_strcat)2932 DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat)
2933 {
2934     STUB_INIT_STACK_FRAME(stackFrame);
2935 
2936     JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
2937     CHECK_FOR_EXCEPTION_AT_END();
2938     return JSValue::encode(result);
2939 }
2940 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_nstricteq)2941 DEFINE_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(jsBoolean(!JSValue::strictEqual(stackFrame.callFrame, src1, src2)));
2949 }
2950 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_to_jsnumber)2951 DEFINE_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(callFrame);
2959     CHECK_FOR_EXCEPTION_AT_END();
2960     return JSValue::encode(result);
2961 }
2962 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_in)2963 DEFINE_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, "in", baseVal, vPCIndex, codeBlock);
2975         VM_THROW_EXCEPTION();
2976     }
2977 
2978     JSValue propName = stackFrame.args[0].jsValue();
2979     JSObject* baseObj = asObject(baseVal);
2980 
2981     uint32_t i;
2982     if (propName.getUInt32(i))
2983         return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
2984 
2985     Identifier property(callFrame, propName.toString(callFrame));
2986     CHECK_FOR_EXCEPTION();
2987     return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
2988 }
2989 
DEFINE_STUB_FUNCTION(JSObject *,op_push_new_scope)2990 DEFINE_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(scope));
2998     return scope;
2999 }
3000 
DEFINE_STUB_FUNCTION(void,op_jmp_scopes)3001 DEFINE_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 
DEFINE_STUB_FUNCTION(void,op_put_by_index)3014 DEFINE_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(callFrame, property, stackFrame.args[2].jsValue());
3022 }
3023 
DEFINE_STUB_FUNCTION(void *,op_switch_imm)3024 DEFINE_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(scrutinee.asInt32()).executableAddress();
3035     else {
3036         double value;
3037         int32_t intValue;
3038         if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
3039             return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(intValue).executableAddress();
3040         else
3041             return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
3042     }
3043 }
3044 
DEFINE_STUB_FUNCTION(void *,op_switch_char)3045 DEFINE_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(scrutinee)->value(callFrame).rep();
3058         if (value->size() == 1)
3059             result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]).executableAddress();
3060     }
3061 
3062     return result;
3063 }
3064 
DEFINE_STUB_FUNCTION(void *,op_switch_string)3065 DEFINE_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(scrutinee)->value(callFrame).rep();
3078         result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
3079     }
3080 
3081     return result;
3082 }
3083 
DEFINE_STUB_FUNCTION(EncodedJSValue,op_del_by_val)3084 DEFINE_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(callFrame); // may throw
3092 
3093     JSValue subscript = stackFrame.args[1].jsValue();
3094     JSValue result;
3095     uint32_t i;
3096     if (subscript.getUInt32(i))
3097         result = jsBoolean(baseObj->deleteProperty(callFrame, i));
3098     else {
3099         CHECK_FOR_EXCEPTION();
3100         Identifier property(callFrame, subscript.toString(callFrame));
3101         CHECK_FOR_EXCEPTION();
3102         result = jsBoolean(baseObj->deleteProperty(callFrame, property));
3103     }
3104 
3105     CHECK_FOR_EXCEPTION_AT_END();
3106     return JSValue::encode(result);
3107 }
3108 
DEFINE_STUB_FUNCTION(void,op_put_getter)3109 DEFINE_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(stackFrame.args[0].jsValue());
3117     ASSERT(stackFrame.args[2].jsValue().isObject());
3118     baseObj->defineGetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
3119 }
3120 
DEFINE_STUB_FUNCTION(void,op_put_setter)3121 DEFINE_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(stackFrame.args[0].jsValue());
3129     ASSERT(stackFrame.args[2].jsValue().isObject());
3130     baseObj->defineSetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
3131 }
3132 
DEFINE_STUB_FUNCTION(JSObject *,op_new_error)3133 DEFINE_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.toString(callFrame), lineNumber, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
3145 }
3146 
DEFINE_STUB_FUNCTION(void,op_debug)3147 DEFINE_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
DEFINE_STUB_FUNCTION(void,op_debug_catch)3161 DEFINE_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(stackFrame.args[0].int32()).jsValue();
3167         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
3168         debugger->exceptionCatch(debuggerCallFrame, callFrame->codeBlock()->source()->asID());
3169     }
3170 }
3171 
DEFINE_STUB_FUNCTION(void,op_debug_return)3172 DEFINE_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(stackFrame.args[0].int32()).jsValue();
3178         intptr_t sourceID = callFrame->codeBlock()->source()->asID();
3179         debugger->functionExit(returnValue, sourceID);
3180     }
3181 }
3182 
3183 #endif
3184 
DEFINE_STUB_FUNCTION(EncodedJSValue,vm_throw)3185 DEFINE_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, globalData->exceptionLocation);
3194 
3195     JSValue exceptionValue = globalData->exception;
3196     ASSERT(exceptionValue);
3197     globalData->exception = JSValue();
3198 
3199     HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false);
3200 
3201     if (!handler) {
3202         *stackFrame.exception = exceptionValue;
3203         return JSValue::encode(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(exceptionValue);
3211 }
3212 
DEFINE_STUB_FUNCTION(EncodedJSValue,to_object)3213 DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
3214 {
3215     STUB_INIT_STACK_FRAME(stackFrame);
3216 
3217     CallFrame* callFrame = stackFrame.callFrame;
3218     return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
3219 }
3220 
3221 #if COMPILER(GCC)
3222 #pragma GCC visibility pop
3223 #endif
3224 
3225 } // namespace JSC
3226 
3227 #endif // ENABLE(JIT)
3228