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