source: webkit/trunk/JavaScriptCore/jit/JITStubs.cpp@ 44844

Last change on this file since 44844 was 44844, checked in by [email protected], 16 years ago

Bug 26532: Native functions do not correctly unlink from optimised callsites when they're collected
<https://bugs.webkit.org/show_bug.cgi?id=26532> <rdar://problem/6625385>

Reviewed by Gavin "Viceroy of Venezuela" Barraclough.

We need to make sure that each native function instance correctly unlinks any references to it
when it is collected. Allowing this to happen required a few changes:

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