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