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

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

Bug 43817 - Remove UString::Rep
UString::Rep has for a long time been replaced by UStringImpl (Rep
remaining as a typedef). UStringImpl has since been removed too
(unified with StringImpl). Remove Rep, rename rep() to impl() and
m_rep to m_impl. Also add impl() method to Identifier, and rename
its UString member from _ustring to m_string.

Rubber stamped by Sam Weinig

JavaScriptCore:

  • API/JSCallbackObject.h:

(JSC::JSCallbackObjectData::JSPrivatePropertyMap::getPrivateProperty):
(JSC::JSCallbackObjectData::JSPrivatePropertyMap::setPrivateProperty):
(JSC::JSCallbackObjectData::JSPrivatePropertyMap::deletePrivateProperty):

  • API/JSCallbackObjectFunctions.h:

(JSC::::getOwnPropertySlot):
(JSC::::put):
(JSC::::deleteProperty):
(JSC::::getOwnPropertyNames):
(JSC::::staticValueGetter):
(JSC::::staticFunctionGetter):

  • API/JSClassRef.cpp:

(tryCreateStringFromUTF8):
(OpaqueJSClass::OpaqueJSClass):
(OpaqueJSClass::~OpaqueJSClass):
(OpaqueJSClassContextData::OpaqueJSClassContextData):

  • API/JSClassRef.h:
  • API/OpaqueJSString.cpp:

(OpaqueJSString::ustring):

  • bytecode/EvalCodeCache.h:

(JSC::EvalCodeCache::get):

  • bytecode/JumpTable.h:

(JSC::StringJumpTable::offsetForValue):
(JSC::StringJumpTable::ctiForValue):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::addVar):
(JSC::BytecodeGenerator::addGlobalVar):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::addParameter):
(JSC::BytecodeGenerator::registerFor):
(JSC::BytecodeGenerator::willResolveToArguments):
(JSC::BytecodeGenerator::uncheckedRegisterForArguments):
(JSC::BytecodeGenerator::constRegisterFor):
(JSC::BytecodeGenerator::isLocal):
(JSC::BytecodeGenerator::isLocalConstant):
(JSC::BytecodeGenerator::addConstant):
(JSC::BytecodeGenerator::emitLoad):
(JSC::BytecodeGenerator::findScopedProperty):
(JSC::keyForCharacterSwitch):
(JSC::prepareJumpTableForStringSwitch):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::processClauseList):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::privateExecute):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • parser/JSParser.cpp:

(JSC::JSParser::parseStrictObjectLiteral):

  • pcre/pcre_exec.cpp:

(Histogram::add):

  • profiler/CallIdentifier.h:

(JSC::CallIdentifier::Hash::hash):

  • profiler/Profile.cpp:
  • profiler/ProfileNode.cpp:

(JSC::ProfileNode::debugPrintDataSampleStyle):

  • profiler/ProfileNode.h:
  • runtime/ArrayPrototype.cpp:

(JSC::arrayProtoFuncToString):

  • runtime/Identifier.cpp:

(JSC::Identifier::equal):
(JSC::IdentifierCStringTranslator::hash):
(JSC::IdentifierCStringTranslator::equal):
(JSC::IdentifierCStringTranslator::translate):
(JSC::Identifier::add):
(JSC::IdentifierUCharBufferTranslator::hash):
(JSC::IdentifierUCharBufferTranslator::equal):
(JSC::IdentifierUCharBufferTranslator::translate):
(JSC::Identifier::addSlowCase):

  • runtime/Identifier.h:

(JSC::Identifier::Identifier):
(JSC::Identifier::ustring):
(JSC::Identifier::impl):
(JSC::Identifier::data):
(JSC::Identifier::size):
(JSC::Identifier::ascii):
(JSC::Identifier::isNull):
(JSC::Identifier::isEmpty):
(JSC::Identifier::toUInt32):
(JSC::Identifier::toStrictUInt32):
(JSC::Identifier::toArrayIndex):
(JSC::Identifier::toDouble):
(JSC::Identifier::equal):
(JSC::Identifier::add):

  • runtime/InitializeThreading.cpp:

(JSC::initializeThreadingOnce):

  • runtime/InternalFunction.cpp:

(JSC::InternalFunction::displayName):

  • runtime/JSFunction.cpp:

(JSC::JSFunction::displayName):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::addStaticGlobals):

  • runtime/JSStaticScopeObject.h:

(JSC::JSStaticScopeObject::JSStaticScopeObject):

  • runtime/JSString.h:

(JSC::):
(JSC::RopeBuilder::appendStringInConstruct):
(JSC::RopeBuilder::appendValueInConstructAndIncrementLength):
(JSC::jsSingleCharacterSubstring):
(JSC::jsSubstring):

  • runtime/JSVariableObject.cpp:

(JSC::JSVariableObject::deleteProperty):
(JSC::JSVariableObject::symbolTableGet):

  • runtime/JSVariableObject.h:

(JSC::JSVariableObject::symbolTableGet):
(JSC::JSVariableObject::symbolTablePut):
(JSC::JSVariableObject::symbolTablePutWithAttributes):

  • runtime/Lookup.cpp:

(JSC::HashTable::createTable):
(JSC::HashTable::deleteTable):

  • runtime/Lookup.h:

(JSC::HashEntry::initialize):
(JSC::HashEntry::setKey):
(JSC::HashEntry::key):
(JSC::HashTable::entry):

  • runtime/PropertyMapHashTable.h:

(JSC::PropertyMapEntry::PropertyMapEntry):

  • runtime/PropertyNameArray.cpp:

(JSC::PropertyNameArray::add):

  • runtime/PropertyNameArray.h:

(JSC::PropertyNameArray::add):
(JSC::PropertyNameArray::addKnownUnique):

  • runtime/RegExp.cpp:

(JSC::RegExp::match):

  • runtime/RegExpCache.cpp:

(JSC::RegExpCache::create):

  • runtime/RegExpKey.h:

(JSC::RegExpKey::RegExpKey):

  • runtime/SmallStrings.cpp:

(JSC::SmallStringsStorage::rep):
(JSC::SmallStrings::singleCharacterStringRep):

  • runtime/SmallStrings.h:
  • runtime/StringPrototype.cpp:

(JSC::jsSpliceSubstringsWithSeparators):
(JSC::stringProtoFuncMatch):
(JSC::stringProtoFuncSearch):

  • runtime/Structure.cpp:

(JSC::Structure::~Structure):
(JSC::Structure::despecifyDictionaryFunction):
(JSC::Structure::addPropertyTransitionToExistingStructure):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::copyPropertyTable):
(JSC::Structure::get):
(JSC::Structure::despecifyFunction):
(JSC::Structure::put):
(JSC::Structure::hasTransition):
(JSC::Structure::remove):
(JSC::Structure::checkConsistency):

  • runtime/Structure.h:

(JSC::Structure::get):
(JSC::Structure::hasTransition):

  • runtime/StructureTransitionTable.h:
  • runtime/SymbolTable.h:
  • runtime/UString.cpp:

(JSC::UString::UString):
(JSC::UString::toStrictUInt32):
(JSC::UString::substr):

  • runtime/UString.h:

(JSC::UString::UString):
(JSC::UString::adopt):
(JSC::UString::data):
(JSC::UString::size):
(JSC::UString::isNull):
(JSC::UString::isEmpty):
(JSC::UString::impl):
(JSC::UString::cost):
(JSC::operator==):
(JSC::codePointCompare):
(JSC::IdentifierRepHash::hash):
(WTF::):

WebCore:

  • bindings/js/JSDOMBinding.cpp:

(WebCore::findAtomicString):

  • bindings/js/JSDOMBinding.h:

(WebCore::ustringToString):
(WebCore::identifierToString):
(WebCore::ustringToAtomicString):
(WebCore::identifierToAtomicString):

  • bindings/js/SerializedScriptValue.h:

(WebCore::SerializedScriptValueData::SerializedScriptValueData):

  • bridge/IdentifierRep.cpp:

(WebCore::IdentifierRep::get):

  • bridge/c/c_class.cpp:

(JSC::Bindings::CClass::methodsNamed):
(JSC::Bindings::CClass::fieldNamed):

  • bridge/jni/jsc/JavaClassJSC.cpp:

(JavaClass::JavaClass):
(JavaClass::methodsNamed):
(JavaClass::fieldNamed):

  • bridge/jni/jsc/JavaStringJSC.h:

(JSC::Bindings::JavaStringImpl::~JavaStringImpl):
(JSC::Bindings::JavaStringImpl::init):
(JSC::Bindings::JavaStringImpl::UTF8String):
(JSC::Bindings::JavaStringImpl::uchars):
(JSC::Bindings::JavaStringImpl::length):
(JSC::Bindings::JavaStringImpl::uString):

  • bridge/jsc/BridgeJSC.h:

WebKit/mac:

  • Plugins/Hosted/ProxyInstance.mm:

(WebKit::ProxyInstance::methodsNamed):
(WebKit::ProxyInstance::fieldNamed):

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