2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
33 #include "CodeBlock.h"
34 #include "DebuggerCallFrame.h"
35 #include "ExceptionHelpers.h"
36 #include "ExecState.h"
37 #include "GlobalEvalFunction.h"
38 #include "JSActivation.h"
40 #include "JSFunction.h"
41 #include "JSNotAnObject.h"
42 #include "JSPropertyNameIterator.h"
43 #include "JSStaticScopeObject.h"
45 #include "ObjectPrototype.h"
48 #include "RegExpObject.h"
49 #include "RegExpPrototype.h"
51 #include "collector.h"
53 #include "operations.h"
54 #include "SamplingTool.h"
73 // Default number of ticks before a timeout check should be done.
74 static const int initialTickCountThreshold = 255;
76 // Preferred number of milliseconds between each timeout check
77 static const int preferredScriptCheckTimeInterval = 1000;
79 #if HAVE(COMPUTED_GOTO)
80 static void* op_throw_end_indirect;
81 static void* op_call_indirect;
84 // Returns the depth of the scope chain within a given call frame.
85 static int depth(ScopeChain& sc)
88 ScopeChainIterator iter = sc.begin();
89 ScopeChainIterator end = sc.end();
90 while (!(*iter)->isActivationObject()) {
99 static inline bool jsLess(ExecState* exec, JSValue* v1, JSValue* v2)
101 if (JSImmediate::areBothImmediateNumbers(v1, v2))
102 return JSImmediate::getTruncatedInt32(v1) < JSImmediate::getTruncatedInt32(v2);
108 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
109 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
111 if (wasNotString1 | wasNotString2)
114 return static_cast<const JSString*>(p1)->value() < static_cast<const JSString*>(p2)->value();
117 static inline bool jsLessEq(ExecState* exec, JSValue* v1, JSValue* v2)
119 if (JSImmediate::areBothImmediateNumbers(v1, v2))
120 return JSImmediate::getTruncatedInt32(v1) <= JSImmediate::getTruncatedInt32(v2);
126 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
127 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
129 if (wasNotString1 | wasNotString2)
132 return !(static_cast<const JSString*>(p2)->value() < static_cast<const JSString*>(p1)->value());
135 static JSValue* jsAddSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
137 // exception for the Date exception in defaultValue()
138 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
139 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
141 if (p1->isString() || p2->isString()) {
142 UString value = p1->toString(exec) + p2->toString(exec);
144 return throwOutOfMemoryError(exec);
145 return jsString(exec, value);
148 return jsNumber(exec, p1->toNumber(exec) + p2->toNumber(exec));
151 // Fast-path choices here are based on frequency data from SunSpider:
152 // <times> Add case: <t1> <t2>
153 // ---------------------------
154 // 5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
155 // 247412 Add case: 5 5
156 // 20900 Add case: 5 6
157 // 13962 Add case: 5 3
158 // 4000 Add case: 3 5
160 static inline JSValue* jsAdd(ExecState* exec, JSValue* v1, JSValue* v2)
162 JSType t1 = v1->type();
163 JSType t2 = v2->type();
164 const unsigned bothTypes = (t1 << 3) | t2;
166 if (bothTypes == ((NumberType << 3) | NumberType))
167 return jsNumber(exec, v1->uncheckedGetNumber() + v2->uncheckedGetNumber());
168 if (bothTypes == ((StringType << 3) | StringType)) {
169 UString value = static_cast<JSString*>(v1)->value() + static_cast<JSString*>(v2)->value();
171 return throwOutOfMemoryError(exec);
172 return jsString(exec, value);
175 // All other cases are pretty uncommon
176 return jsAddSlowCase(exec, v1, v2);
179 static JSValue* jsTypeStringForValue(ExecState* exec, JSValue* v)
183 return jsString(exec, "undefined");
185 return jsString(exec, "object");
187 return jsString(exec, "boolean");
189 return jsString(exec, "number");
191 return jsString(exec, "string");
194 // Return "undefined" for objects that should be treated
195 // as null when doing comparisons.
196 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
197 return jsString(exec, "undefined");
199 if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
200 return jsString(exec, "function");
203 return jsString(exec, "object");
207 static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
209 int dst = (vPC + 1)->u.operand;
210 int property = (vPC + 2)->u.operand;
212 ScopeChainIterator iter = scopeChain->begin();
213 ScopeChainIterator end = scopeChain->end();
216 Identifier& ident = codeBlock->identifiers[property];
219 PropertySlot slot(o);
220 if (o->getPropertySlot(exec, ident, slot)) {
221 JSValue* result = slot.getValue(exec, ident);
222 exceptionValue = exec->exception();
228 } while (++iter != end);
229 exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
233 static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
235 int dst = (vPC + 1)->u.operand;
236 int property = (vPC + 2)->u.operand;
237 int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain;
239 ScopeChainIterator iter = scopeChain->begin();
240 ScopeChainIterator end = scopeChain->end();
246 Identifier& ident = codeBlock->identifiers[property];
249 PropertySlot slot(o);
250 if (o->getPropertySlot(exec, ident, slot)) {
251 JSValue* result = slot.getValue(exec, ident);
252 exceptionValue = exec->exception();
258 } while (++iter != end);
259 exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
263 static void NEVER_INLINE resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
265 int dst = (vPC + 1)->u.operand;
266 int property = (vPC + 2)->u.operand;
268 ScopeChainIterator iter = scopeChain->begin();
269 ScopeChainIterator next = iter;
271 ScopeChainIterator end = scopeChain->end();
275 Identifier& ident = codeBlock->identifiers[property];
279 if (next == end || base->getPropertySlot(exec, ident, slot)) {
288 static bool NEVER_INLINE resolveBaseAndProperty(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
290 int baseDst = (vPC + 1)->u.operand;
291 int propDst = (vPC + 2)->u.operand;
292 int property = (vPC + 3)->u.operand;
294 ScopeChainIterator iter = scopeChain->begin();
295 ScopeChainIterator end = scopeChain->end();
297 // FIXME: add scopeDepthIsZero optimization
301 Identifier& ident = codeBlock->identifiers[property];
305 PropertySlot slot(base);
306 if (base->getPropertySlot(exec, ident, slot)) {
307 JSValue* result = slot.getValue(exec, ident);
308 exceptionValue = exec->exception();
316 } while (iter != end);
318 exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
322 static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
324 int baseDst = (vPC + 1)->u.operand;
325 int funcDst = (vPC + 2)->u.operand;
326 int property = (vPC + 3)->u.operand;
328 ScopeChainIterator iter = scopeChain->begin();
329 ScopeChainIterator end = scopeChain->end();
331 // FIXME: add scopeDepthIsZero optimization
335 Identifier& ident = codeBlock->identifiers[property];
339 PropertySlot slot(base);
340 if (base->getPropertySlot(exec, ident, slot)) {
341 // ECMA 11.2.3 says that if we hit an activation the this value should be null.
342 // However, section 10.2.3 says that in the case where the value provided
343 // by the caller is null, the global object should be used. It also says
344 // that the section does not apply to internal functions, but for simplicity
345 // of implementation we use the global object anyway here. This guarantees
346 // that in host objects you always get a valid object for this.
347 // We also handle wrapper substitution for the global object at the same time.
348 JSObject* thisObj = base->toThisObject(exec);
349 JSValue* result = slot.getValue(exec, ident);
350 exceptionValue = exec->exception();
354 r[baseDst] = thisObj;
359 } while (iter != end);
361 exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
365 ALWAYS_INLINE void Machine::initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, Register* r, int returnValueRegister, int argv, int argc, int calledAsConstructor, JSValue* function)
367 callFrame[RegisterFile::CallerCodeBlock] = codeBlock;
368 callFrame[RegisterFile::ReturnVPC] = vPC + 1;
369 callFrame[RegisterFile::CallerScopeChain] = scopeChain;
370 callFrame[RegisterFile::CallerRegisters] = r;
371 callFrame[RegisterFile::ReturnValueRegister] = returnValueRegister;
372 callFrame[RegisterFile::ArgumentStartRegister] = argv; // original argument vector (for the sake of the "arguments" object)
373 callFrame[RegisterFile::ArgumentCount] = argc; // original argument count (for the sake of the "arguments" object)
374 callFrame[RegisterFile::CalledAsConstructor] = calledAsConstructor;
375 callFrame[RegisterFile::Callee] = function;
376 callFrame[RegisterFile::OptionalCalleeActivation] = nullJSValue;
379 ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register* registerBase, Register* r, int argv, int argc, JSValue*& exceptionValue)
381 size_t registerOffset = argv + newCodeBlock->numLocals;
382 size_t size = r - registerBase + registerOffset + newCodeBlock->numConstants + newCodeBlock->numTemporaries;
384 if (argc == newCodeBlock->numParameters) { // correct number of arguments
385 if (!registerFile->grow(size)) {
386 exceptionValue = createStackOverflowError(exec);
390 } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks
391 if (!registerFile->grow(size)) {
392 exceptionValue = createStackOverflowError(exec);
397 int omittedArgCount = newCodeBlock->numParameters - argc;
398 Register* endOfParams = r - newCodeBlock->numVars;
399 for (Register* it = endOfParams - omittedArgCount; it != endOfParams; ++it)
400 (*it) = jsUndefined();
401 } else { // too many arguments -- copy return info and expected arguments, leaving the extra arguments behind
402 int shift = argc + RegisterFile::CallFrameHeaderSize;
403 registerOffset += shift;
406 if (!registerFile->grow(size)) {
407 exceptionValue = createStackOverflowError(exec);
412 Register* it = r - newCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize - shift;
413 Register* end = it + RegisterFile::CallFrameHeaderSize + newCodeBlock->numParameters;
414 for ( ; it != end; ++it)
418 // initialize local variable slots
419 for (Register* it = r - newCodeBlock->numVars; it != r; ++it)
420 (*it) = jsUndefined();
423 for (size_t i = 0; i < newCodeBlock->constantRegisters.size(); ++i)
424 r[i] = newCodeBlock->constantRegisters[i];
429 ALWAYS_INLINE ScopeChainNode* scopeChainForCall(ExecState* exec, FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register* r)
431 if (newCodeBlock->needsFullScopeChain) {
432 JSActivation* activation = new (exec) JSActivation(functionBodyNode, r);
433 r[RegisterFile::OptionalCalleeActivation - RegisterFile::CallFrameHeaderSize - newCodeBlock->numLocals] = activation;
435 return callDataScopeChain->copy()->push(activation);
438 return callDataScopeChain;
441 static NEVER_INLINE bool isNotObject(ExecState* exec, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValue* value, JSValue*& exceptionData)
443 if (value->isObject())
445 exceptionData = createInvalidParamError(exec, forInstanceOf ? "instanceof" : "in" , value, vPC, codeBlock);
449 NEVER_INLINE JSValue* Machine::callEval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
452 return jsUndefined();
454 JSValue* program = r[argv + 1].jsValue(exec);
456 if (!program->isString())
459 Profiler** profiler = Profiler::enabledProfilerReference();
461 (*profiler)->willExecute(exec, scopeChain->globalObject()->evalFunction());
466 RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(static_cast<JSString*>(program)->value()), &sourceId, &errLine, &errMsg);
469 exceptionValue = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
471 (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
475 JSValue* result = exec->globalData().machine->execute(evalNode.get(), exec, thisObj, r - registerFile->base() + argv + argc, scopeChain, &exceptionValue);
478 (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
487 , m_timeAtLastCheckTimeout(0)
489 , m_timeoutCheckCount(0)
490 , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold)
492 privateExecute(InitializeAndReturn);
494 // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
495 void* storage = fastMalloc(sizeof(CollectorBlock));
497 JSArray* jsArray = new (storage) JSArray(jsNull(), 0);
498 m_jsArrayVptr = jsArray->vptr();
499 static_cast<JSCell*>(jsArray)->~JSCell();
501 JSString* jsString = new (storage) JSString("");
502 m_jsStringVptr = jsString->vptr();
503 static_cast<JSCell*>(jsString)->~JSCell();
508 void Machine::dumpCallFrame(const CodeBlock* codeBlock, ScopeChainNode* scopeChain, RegisterFile* registerFile, const Register* r)
510 ScopeChain sc(scopeChain);
511 JSGlobalObject* globalObject = sc.globalObject();
512 codeBlock->dump(globalObject->globalExec());
513 dumpRegisters(codeBlock, registerFile, r);
516 void Machine::dumpRegisters(const CodeBlock* codeBlock, RegisterFile* registerFile, const Register* r)
518 printf("Register frame: \n\n");
519 printf("----------------------------------------------------\n");
520 printf(" use | address | value \n");
521 printf("----------------------------------------------------\n");
526 if (codeBlock->codeType == GlobalCode) {
527 it = registerFile->lastGlobal();
528 end = it + registerFile->numGlobals();
530 printf("[global var] | %10p | %10p \n", it, (*it).v());
533 printf("----------------------------------------------------\n");
536 it = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
537 printf("[CallerCodeBlock] | %10p | %10p \n", it, (*it).v()); ++it;
538 printf("[ReturnVPC] | %10p | %10p \n", it, (*it).v()); ++it;
539 printf("[CallerScopeChain] | %10p | %10p \n", it, (*it).v()); ++it;
540 printf("[CallerRegisterOffset] | %10p | %10p \n", it, (*it).v()); ++it;
541 printf("[ReturnValueRegister] | %10p | %10p \n", it, (*it).v()); ++it;
542 printf("[ArgumentStartRegister] | %10p | %10p \n", it, (*it).v()); ++it;
543 printf("[ArgumentCount] | %10p | %10p \n", it, (*it).v()); ++it;
544 printf("[CalledAsConstructor] | %10p | %10p \n", it, (*it).v()); ++it;
545 printf("[Callee] | %10p | %10p \n", it, (*it).v()); ++it;
546 printf("[OptionalCalleeActivation] | %10p | %10p \n", it, (*it).v()); ++it;
547 printf("----------------------------------------------------\n");
549 printf("[this] | %10p | %10p \n", it, (*it).v()); ++it;
550 end = it + max(codeBlock->numParameters - 1, 0); // - 1 to skip "this"
553 printf("[param] | %10p | %10p \n", it, (*it).v());
557 printf("----------------------------------------------------\n");
559 if (codeBlock->codeType != GlobalCode) {
560 end = it + codeBlock->numVars;
563 printf("[var] | %10p | %10p \n", it, (*it).v());
566 printf("----------------------------------------------------\n");
570 end = it + codeBlock->numTemporaries;
573 printf("[temp] | %10p | %10p \n", it, (*it).v());
579 bool Machine::isOpcode(Opcode opcode)
581 #if HAVE(COMPUTED_GOTO)
582 return opcode != HashTraits<Opcode>::emptyValue()
583 && !HashTraits<Opcode>::isDeletedValue(opcode)
584 && m_opcodeIDTable.contains(opcode);
586 return opcode >= 0 && opcode <= op_end;
590 NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r)
592 CodeBlock* oldCodeBlock = codeBlock;
593 Register* callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
595 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
596 DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
597 if (callFrame[RegisterFile::Callee].jsValue(exec))
598 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
600 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
603 if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
604 if (callFrame[RegisterFile::Callee].jsValue(exec))
605 profiler->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
607 profiler->didExecute(exec, codeBlock->ownerNode->sourceURL(), codeBlock->ownerNode->lineNo());
610 if (oldCodeBlock->needsFullScopeChain)
613 // If this call frame created an activation, tear it off.
614 if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
615 ASSERT(activation->isActivationObject());
616 activation->copyRegisters();
619 codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
623 scopeChain = callFrame[RegisterFile::CallerScopeChain].scopeChain();
624 r = callFrame[RegisterFile::CallerRegisters].r();
625 exec->m_callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
626 vPC = callFrame[RegisterFile::ReturnVPC].vPC();
631 NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue*& exceptionValue, const Instruction* vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r, bool explicitThrow)
633 // Set up the exception object
635 if (exceptionValue->isObject()) {
636 JSObject* exception = static_cast<JSObject*>(exceptionValue);
637 if (exception->isNotAnObjectErrorStub()) {
638 exception = createNotAnObjectError(exec, static_cast<JSNotAnObjectErrorStub*>(exception), vPC, codeBlock);
639 exceptionValue = exception;
641 if (!exception->hasProperty(exec, Identifier(exec, "line")) &&
642 !exception->hasProperty(exec, Identifier(exec, "sourceId")) &&
643 !exception->hasProperty(exec, Identifier(exec, "sourceURL")) &&
644 !exception->hasProperty(exec, Identifier(exec, expressionBeginOffsetPropertyName)) &&
645 !exception->hasProperty(exec, Identifier(exec, expressionCaretOffsetPropertyName)) &&
646 !exception->hasProperty(exec, Identifier(exec, expressionEndOffsetPropertyName))) {
651 int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset);
652 exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, line), ReadOnly | DontDelete);
654 // We only hit this path for error messages and throw statements, which don't have a specific failure position
655 // So we just give the full range of the error/throw statement.
656 exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
657 exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
659 exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, codeBlock->lineNumberForVPC(vPC)), ReadOnly | DontDelete);
660 exception->putWithAttributes(exec, Identifier(exec, "sourceId"), jsNumber(exec, codeBlock->ownerNode->sourceId()), ReadOnly | DontDelete);
661 exception->putWithAttributes(exec, Identifier(exec, "sourceURL"), jsOwnedString(exec, codeBlock->ownerNode->sourceURL()), ReadOnly | DontDelete);
664 if (exception->isWatchdogException()) {
665 while (unwindCallFrame(exec, exceptionValue, vPC, codeBlock, scopeChain, r)) {
666 // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
673 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
674 DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
675 debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->lineNumberForVPC(vPC));
678 // Calculate an exception handler vPC, unwinding call frames as necessary.
681 Instruction* handlerVPC;
683 while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) {
684 if (!unwindCallFrame(exec, exceptionValue, vPC, codeBlock, scopeChain, r))
688 // Now unwind the scope chain within the exception handler's call frame.
690 ScopeChain sc(scopeChain);
691 int scopeDelta = depth(sc) - scopeDepth;
692 ASSERT(scopeDelta >= 0);
695 setScopeChain(exec, scopeChain, sc.node());
700 JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue** exception)
702 if (m_reentryDepth >= MaxReentryDepth) {
703 *exception = createStackOverflowError(exec);
707 CodeBlock* codeBlock = &programNode->byteCode(scopeChain);
709 size_t oldSize = m_registerFile.size();
710 size_t newSize = oldSize + RegisterFile::CallFrameHeaderSize + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries;
711 if (!m_registerFile.grow(newSize)) {
712 *exception = createStackOverflowError(exec);
716 JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
717 JSGlobalObject* globalObject = exec->dynamicGlobalObject();
718 globalObject->copyGlobalsTo(m_registerFile);
720 Register* callFrame = m_registerFile.base() + oldSize;
722 // a 0 codeBlock indicates a built-in caller
723 initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
725 Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
726 r[codeBlock->thisRegister] = thisObj;
728 for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
729 r[i] = codeBlock->constantRegisters[i];
731 if (codeBlock->needsFullScopeChain)
732 scopeChain = scopeChain->copy();
734 ExecState newExec(exec, &m_registerFile, scopeChain, 0);
736 Profiler** profiler = Profiler::enabledProfilerReference();
738 (*profiler)->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
741 JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
744 MACHINE_SAMPLING_privateExecuteReturned();
747 (*profiler)->didExecute(exec, programNode->sourceURL(), programNode->lineNo());
749 (*profiler)->didFinishAllExecution(exec);
752 if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
753 lastGlobalObject->copyGlobalsTo(m_registerFile);
755 m_registerFile.shrink(oldSize);
759 JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue** exception)
761 if (m_reentryDepth >= MaxReentryDepth) {
762 *exception = createStackOverflowError(exec);
766 int argv = RegisterFile::CallFrameHeaderSize;
767 int argc = args.size() + 1; // implicit "this" parameter
769 size_t oldSize = m_registerFile.size();
770 if (!m_registerFile.grow(oldSize + RegisterFile::CallFrameHeaderSize + argc)) {
771 *exception = createStackOverflowError(exec);
775 Register* callFrame = m_registerFile.base() + oldSize;
777 // put args in place, including "this"
778 Register* dst = callFrame + RegisterFile::CallFrameHeaderSize;
781 ArgList::const_iterator end = args.end();
782 for (ArgList::const_iterator it = args.begin(); it != end; ++it)
785 // a 0 codeBlock indicates a built-in caller
786 initializeCallFrame(callFrame, 0, 0, 0, callFrame, 0, argv, argc, 0, function);
788 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(scopeChain);
789 Register* r = slideRegisterWindowForCall(exec, newCodeBlock, &m_registerFile, m_registerFile.base(), callFrame, argv, argc, *exception);
791 m_registerFile.shrink(oldSize);
795 scopeChain = scopeChainForCall(exec, functionBodyNode, newCodeBlock, scopeChain, r);
797 ExecState newExec(exec, &m_registerFile, scopeChain, callFrame);
799 Profiler** profiler = Profiler::enabledProfilerReference();
801 (*profiler)->willExecute(exec, function);
804 JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
807 MACHINE_SAMPLING_privateExecuteReturned();
809 if (*profiler && !m_reentryDepth)
810 (*profiler)->didFinishAllExecution(exec);
812 m_registerFile.shrink(oldSize);
816 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
818 if (m_reentryDepth >= MaxReentryDepth) {
819 *exception = createStackOverflowError(exec);
823 EvalCodeBlock* codeBlock = &evalNode->byteCode(scopeChain);
825 JSVariableObject* variableObject;
826 for (ScopeChainNode* node = scopeChain; ; node = node->next) {
828 if (node->object->isVariableObject()) {
829 variableObject = static_cast<JSVariableObject*>(node->object);
834 const Node::VarStack& varStack = codeBlock->ownerNode->varStack();
835 Node::VarStack::const_iterator varStackEnd = varStack.end();
836 for (Node::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
837 const Identifier& ident = (*it).first;
838 if (!variableObject->hasProperty(exec, ident))
839 variableObject->put(exec, ident, jsUndefined());
842 const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack();
843 Node::FunctionStack::const_iterator functionStackEnd = functionStack.end();
844 for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it)
845 variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain));
847 size_t oldSize = m_registerFile.size();
848 size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries + RegisterFile::CallFrameHeaderSize;
849 if (!m_registerFile.grow(newSize)) {
850 *exception = createStackOverflowError(exec);
854 Register* callFrame = m_registerFile.base() + registerOffset;
856 // a 0 codeBlock indicates a built-in caller
857 initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
859 Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
860 r[codeBlock->thisRegister] = thisObj;
862 for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
863 r[i] = codeBlock->constantRegisters[i];
865 if (codeBlock->needsFullScopeChain)
866 scopeChain = scopeChain->copy();
868 ExecState newExec(exec, &m_registerFile, scopeChain, 0);
870 Profiler** profiler = Profiler::enabledProfilerReference();
872 (*profiler)->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
875 JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
878 MACHINE_SAMPLING_privateExecuteReturned();
881 (*profiler)->didExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
883 (*profiler)->didFinishAllExecution(exec);
886 m_registerFile.shrink(oldSize);
890 ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scopeChain, ScopeChainNode* newScopeChain)
892 scopeChain = newScopeChain;
893 exec->m_scopeChain = newScopeChain;
896 NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r)
898 int debugHookID = (++vPC)->u.operand;
899 int firstLine = (++vPC)->u.operand;
900 int lastLine = (++vPC)->u.operand;
902 Debugger* debugger = exec->dynamicGlobalObject()->debugger();
906 DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, r, 0);
908 switch((DebugHookID)debugHookID) {
909 case DidEnterCallFrame: {
910 debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
913 case WillLeaveCallFrame: {
914 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
917 case WillExecuteStatement: {
918 debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
921 case WillExecuteProgram: {
922 debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
925 case DidExecuteProgram: {
926 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
929 case DidReachBreakpoint: {
930 debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
936 void Machine::resetTimeoutCheck()
938 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
939 m_timeAtLastCheckTimeout = 0;
943 // Returns the current time in milliseconds
944 // It doesn't matter what "current time" is here, just as long as
945 // it's possible to measure the time difference correctly.
946 // In an ideal world this would just be getCurrentUTCTimeWithMicroseconds
947 // from DateMath.h, but unfortunately there's a slowdown if we use tha.
948 static inline unsigned getCurrentTime()
952 gettimeofday(&tv, 0);
953 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
955 QDateTime t = QDateTime::currentDateTime();
956 return t.toTime_t() * 1000 + t.time().msec();
957 #elif PLATFORM(WIN_OS)
958 return timeGetTime();
960 #error Platform does not have getCurrentTime function
964 // We have to return a JSValue here, gcc seems to produce worse code if
965 // we attempt to return a bool
966 ALWAYS_INLINE JSValue* Machine::checkTimeout(JSGlobalObject* globalObject)
968 unsigned currentTime = getCurrentTime();
970 if (!m_timeAtLastCheckTimeout) {
971 // Suspicious amount of looping in a script -- start timing it
972 m_timeAtLastCheckTimeout = currentTime;
976 unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
981 m_timeExecuting += timeDiff;
982 m_timeAtLastCheckTimeout = currentTime;
984 // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
985 // preferredScriptCheckTimeInterval
986 m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck);
987 // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
988 // preferred script check time interval.
989 if (m_ticksUntilNextTimeoutCheck == 0)
990 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
992 if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
993 if (globalObject->shouldInterruptScript())
994 return jsNull(); // Appeasing GCC, all we need is a non-null js value.
1002 static int32_t offsetForStringSwitch(StringJumpTable& jumpTable, JSValue* scrutinee, int32_t defaultOffset) {
1003 StringJumpTable::const_iterator end = jumpTable.end();
1004 UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
1005 StringJumpTable::const_iterator loc = jumpTable.find(value);
1007 return defaultOffset;
1011 static NEVER_INLINE ScopeChainNode* createExceptionScope(ExecState* exec, CodeBlock* codeBlock, const Instruction* vPC, Register* r, ScopeChainNode* scopeChain)
1013 int dst = (++vPC)->u.operand;
1014 Identifier& property = codeBlock->identifiers[(++vPC)->u.operand];
1015 JSValue* value = r[(++vPC)->u.operand].jsValue(exec);
1016 JSObject* scope = new (exec) JSStaticScopeObject(property, value, DontDelete);
1018 return scopeChain->push(scope);
1021 JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
1023 // One-time initialization of our address tables. We have to put this code
1024 // here because our labels are only in scope inside this function.
1025 if (flag == InitializeAndReturn) {
1026 #if HAVE(COMPUTED_GOTO)
1027 #define ADD_OPCODE(id) m_opcodeTable[id] = &&id;
1028 FOR_EACH_OPCODE_ID(ADD_OPCODE);
1031 #define ADD_OPCODE_ID(id) m_opcodeIDTable.add(&&id, id);
1032 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
1033 #undef ADD_OPCODE_ID
1034 ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
1035 op_throw_end_indirect = &&op_throw_end;
1036 op_call_indirect = &&op_call;
1037 #endif // HAVE(COMPUTED_GOTO)
1041 JSValue* exceptionValue = 0;
1042 Instruction* handlerVPC = 0;
1044 Register* registerBase = registerFile->base();
1045 Instruction* vPC = codeBlock->instructions.begin();
1046 Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
1047 unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
1049 #define VM_CHECK_EXCEPTION() \
1051 if (UNLIKELY(exec->hadException())) { \
1052 exceptionValue = exec->exception(); \
1057 #if DUMP_OPCODE_STATS
1058 OpcodeStats::resetLastInstruction();
1061 #define CHECK_FOR_TIMEOUT() \
1062 if (!--tickCount) { \
1063 if ((exceptionValue = checkTimeout(exec->dynamicGlobalObject()))) \
1065 tickCount = m_ticksUntilNextTimeoutCheck; \
1068 #if HAVE(COMPUTED_GOTO)
1069 #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); goto *vPC->u.opcode
1070 #if DUMP_OPCODE_STATS
1071 #define BEGIN_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
1073 #define BEGIN_OPCODE(opcode) opcode:
1077 #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); continue
1078 #if DUMP_OPCODE_STATS
1079 #define BEGIN_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
1081 #define BEGIN_OPCODE(opcode) case opcode:
1083 while (1) // iterator loop begins
1084 switch (vPC->u.opcode)
1087 BEGIN_OPCODE(op_new_object) {
1088 /* new_object dst(r)
1090 Constructs a new empty Object instance using the original
1091 constructor, and puts the result in register dst.
1093 int dst = (++vPC)->u.operand;
1094 r[dst] = constructEmptyObject(exec);
1099 BEGIN_OPCODE(op_new_array) {
1100 /* new_array dst(r) firstArg(r) argCount(n)
1102 Constructs a new Array instance using the original
1103 constructor, and puts the result in register dst.
1104 The array will contain argCount elements with values
1105 taken from registers starting at register firstArg.
1107 int dst = (++vPC)->u.operand;
1108 int firstArg = (++vPC)->u.operand;
1109 int argCount = (++vPC)->u.operand;
1110 ArgList args(r + firstArg, argCount);
1111 r[dst] = constructArray(exec, args);
1116 BEGIN_OPCODE(op_new_regexp) {
1117 /* new_regexp dst(r) regExp(re)
1119 Constructs a new RegExp instance using the original
1120 constructor from regexp regExp, and puts the result in
1123 int dst = (++vPC)->u.operand;
1124 int regExp = (++vPC)->u.operand;
1125 r[dst] = new (exec) RegExpObject(scopeChain->globalObject()->regExpPrototype(), codeBlock->regexps[regExp]);
1130 BEGIN_OPCODE(op_mov) {
1131 /* mov dst(r) src(r)
1133 Copies register src to register dst.
1135 int dst = (++vPC)->u.operand;
1136 int src = (++vPC)->u.operand;
1142 BEGIN_OPCODE(op_eq) {
1143 /* eq dst(r) src1(r) src2(r)
1145 Checks whether register src1 and register src2 are equal,
1146 as with the ECMAScript '==' operator, and puts the result
1147 as a boolean in register dst.
1149 int dst = (++vPC)->u.operand;
1150 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1151 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1152 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1153 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1155 JSValue* result = jsBoolean(equal(exec, src1, src2));
1156 VM_CHECK_EXCEPTION();
1163 BEGIN_OPCODE(op_neq) {
1164 /* neq dst(r) src1(r) src2(r)
1166 Checks whether register src1 and register src2 are not
1167 equal, as with the ECMAScript '!=' operator, and puts the
1168 result as a boolean in register dst.
1170 int dst = (++vPC)->u.operand;
1171 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1172 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1173 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1174 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1176 JSValue* result = jsBoolean(!equal(exec, src1, src2));
1177 VM_CHECK_EXCEPTION();
1184 BEGIN_OPCODE(op_stricteq) {
1185 /* stricteq dst(r) src1(r) src2(r)
1187 Checks whether register src1 and register src2 are strictly
1188 equal, as with the ECMAScript '===' operator, and puts the
1189 result as a boolean in register dst.
1191 int dst = (++vPC)->u.operand;
1192 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1193 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1194 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1195 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1197 r[dst] = jsBoolean(strictEqual(src1, src2));
1202 BEGIN_OPCODE(op_nstricteq) {
1203 /* nstricteq dst(r) src1(r) src2(r)
1205 Checks whether register src1 and register src2 are not
1206 strictly equal, as with the ECMAScript '!==' operator, and
1207 puts the result as a boolean in register dst.
1209 int dst = (++vPC)->u.operand;
1210 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1211 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1212 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1213 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1215 r[dst] = jsBoolean(!strictEqual(src1, src2));
1220 BEGIN_OPCODE(op_less) {
1221 /* less dst(r) src1(r) src2(r)
1223 Checks whether register src1 is less than register src2, as
1224 with the ECMAScript '<' operator, and puts the result as
1225 a boolean in register dst.
1227 int dst = (++vPC)->u.operand;
1228 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1229 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1230 JSValue* result = jsBoolean(jsLess(exec, src1, src2));
1231 VM_CHECK_EXCEPTION();
1237 BEGIN_OPCODE(op_lesseq) {
1238 /* lesseq dst(r) src1(r) src2(r)
1240 Checks whether register src1 is less than or equal to
1241 register src2, as with the ECMAScript '<=' operator, and
1242 puts the result as a boolean in register dst.
1244 int dst = (++vPC)->u.operand;
1245 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1246 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1247 JSValue* result = jsBoolean(jsLessEq(exec, src1, src2));
1248 VM_CHECK_EXCEPTION();
1254 BEGIN_OPCODE(op_pre_inc) {
1255 /* pre_inc srcDst(r)
1257 Converts register srcDst to number, adds one, and puts the result
1258 back in register srcDst.
1260 int srcDst = (++vPC)->u.operand;
1261 JSValue* v = r[srcDst].jsValue(exec);
1262 if (JSImmediate::canDoFastAdditiveOperations(v))
1263 r[srcDst] = JSImmediate::incImmediateNumber(v);
1265 JSValue* result = jsNumber(exec, v->toNumber(exec) + 1);
1266 VM_CHECK_EXCEPTION();
1273 BEGIN_OPCODE(op_pre_dec) {
1274 /* pre_dec srcDst(r)
1276 Converts register srcDst to number, subtracts one, and puts the result
1277 back in register srcDst.
1279 int srcDst = (++vPC)->u.operand;
1280 JSValue* v = r[srcDst].jsValue(exec);
1281 if (JSImmediate::canDoFastAdditiveOperations(v))
1282 r[srcDst] = JSImmediate::decImmediateNumber(v);
1284 JSValue* result = jsNumber(exec, v->toNumber(exec) - 1);
1285 VM_CHECK_EXCEPTION();
1292 BEGIN_OPCODE(op_post_inc) {
1293 /* post_inc dst(r) srcDst(r)
1295 Converts register srcDst to number. The number itself is
1296 written to register dst, and the number plus one is written
1297 back to register srcDst.
1299 int dst = (++vPC)->u.operand;
1300 int srcDst = (++vPC)->u.operand;
1301 JSValue* v = r[srcDst].jsValue(exec);
1302 if (JSImmediate::canDoFastAdditiveOperations(v)) {
1304 r[srcDst] = JSImmediate::incImmediateNumber(v);
1306 JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1307 VM_CHECK_EXCEPTION();
1309 r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() + 1);
1315 BEGIN_OPCODE(op_post_dec) {
1316 /* post_dec dst(r) srcDst(r)
1318 Converts register srcDst to number. The number itself is
1319 written to register dst, and the number minus one is written
1320 back to register srcDst.
1322 int dst = (++vPC)->u.operand;
1323 int srcDst = (++vPC)->u.operand;
1324 JSValue* v = r[srcDst].jsValue(exec);
1325 if (JSImmediate::canDoFastAdditiveOperations(v)) {
1327 r[srcDst] = JSImmediate::decImmediateNumber(v);
1329 JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1330 VM_CHECK_EXCEPTION();
1332 r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() - 1);
1338 BEGIN_OPCODE(op_to_jsnumber) {
1339 /* to_jsnumber dst(r) src(r)
1341 Converts register src to number, and puts the result
1344 int dst = (++vPC)->u.operand;
1345 int src = (++vPC)->u.operand;
1346 JSValue* result = r[src].jsValue(exec)->toJSNumber(exec);
1347 VM_CHECK_EXCEPTION();
1354 BEGIN_OPCODE(op_negate) {
1355 /* negate dst(r) src(r)
1357 Converts register src to number, negates it, and puts the
1358 result in register dst.
1360 int dst = (++vPC)->u.operand;
1361 int src = (++vPC)->u.operand;
1362 JSValue* result = jsNumber(exec, -r[src].jsValue(exec)->toNumber(exec));
1363 VM_CHECK_EXCEPTION();
1369 BEGIN_OPCODE(op_add) {
1370 /* add dst(r) src1(r) src2(r)
1372 Adds register src1 and register src2, and puts the result
1373 in register dst. (JS add may be string concatenation or
1374 numeric add, depending on the types of the operands.)
1376 int dst = (++vPC)->u.operand;
1377 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1378 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1379 if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1380 r[dst] = JSImmediate::addImmediateNumbers(src1, src2);
1382 JSValue* result = jsAdd(exec, src1, src2);
1383 VM_CHECK_EXCEPTION();
1389 BEGIN_OPCODE(op_mul) {
1390 /* mul dst(r) src1(r) src2(r)
1392 Multiplies register src1 and register src2 (converted to
1393 numbers), and puts the product in register dst.
1395 int dst = (++vPC)->u.operand;
1396 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1397 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1398 JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
1399 VM_CHECK_EXCEPTION();
1405 BEGIN_OPCODE(op_div) {
1406 /* div dst(r) dividend(r) divisor(r)
1408 Divides register dividend (converted to number) by the
1409 register divisor (converted to number), and puts the
1410 quotient in register dst.
1412 int dst = (++vPC)->u.operand;
1413 int dividend = (++vPC)->u.operand;
1414 int divisor = (++vPC)->u.operand;
1415 JSValue* result = jsNumber(exec, r[dividend].jsValue(exec)->toNumber(exec) / r[divisor].jsValue(exec)->toNumber(exec));
1416 VM_CHECK_EXCEPTION();
1421 BEGIN_OPCODE(op_mod) {
1422 /* mod dst(r) dividend(r) divisor(r)
1424 Divides register dividend (converted to number) by
1425 register divisor (converted to number), and puts the
1426 remainder in register dst.
1428 int dst = (++vPC)->u.operand;
1429 int dividend = (++vPC)->u.operand;
1430 int divisor = (++vPC)->u.operand;
1432 JSValue* dividendValue = r[dividend].jsValue(exec);
1433 JSValue* divisorValue = r[divisor].jsValue(exec);
1435 if (JSImmediate::areBothImmediateNumbers(dividendValue, divisorValue) && divisorValue != JSImmediate::from(0)) {
1436 r[dst] = JSImmediate::from(JSImmediate::getTruncatedInt32(dividendValue) % JSImmediate::getTruncatedInt32(divisorValue));
1441 double d = dividendValue->toNumber(exec);
1442 JSValue* result = jsNumber(exec, fmod(d, divisorValue->toNumber(exec)));
1443 VM_CHECK_EXCEPTION();
1448 BEGIN_OPCODE(op_sub) {
1449 /* sub dst(r) src1(r) src2(r)
1451 Subtracts register src2 (converted to number) from register
1452 src1 (converted to number), and puts the difference in
1455 int dst = (++vPC)->u.operand;
1456 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1457 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1458 if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1459 r[dst] = JSImmediate::subImmediateNumbers(src1, src2);
1461 JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
1462 VM_CHECK_EXCEPTION();
1468 BEGIN_OPCODE(op_lshift) {
1469 /* lshift dst(r) val(r) shift(r)
1471 Performs left shift of register val (converted to int32) by
1472 register shift (converted to uint32), and puts the result
1475 int dst = (++vPC)->u.operand;
1476 JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1477 JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1478 if (JSImmediate::areBothImmediateNumbers(val, shift))
1479 r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::toTruncatedUInt32(shift) & 0x1f));
1481 JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
1482 VM_CHECK_EXCEPTION();
1489 BEGIN_OPCODE(op_rshift) {
1490 /* rshift dst(r) val(r) shift(r)
1492 Performs arithmetic right shift of register val (converted
1493 to int32) by register shift (converted to
1494 uint32), and puts the result in register dst.
1496 int dst = (++vPC)->u.operand;
1497 JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1498 JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1499 if (JSImmediate::areBothImmediateNumbers(val, shift))
1500 r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1502 JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1503 VM_CHECK_EXCEPTION();
1510 BEGIN_OPCODE(op_urshift) {
1511 /* rshift dst(r) val(r) shift(r)
1513 Performs logical right shift of register val (converted
1514 to uint32) by register shift (converted to
1515 uint32), and puts the result in register dst.
1517 int dst = (++vPC)->u.operand;
1518 JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1519 JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1520 if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
1521 r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1523 JSValue* result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1524 VM_CHECK_EXCEPTION();
1531 BEGIN_OPCODE(op_bitand) {
1532 /* bitand dst(r) src1(r) src2(r)
1534 Computes bitwise AND of register src1 (converted to int32)
1535 and register src2 (converted to int32), and puts the result
1538 int dst = (++vPC)->u.operand;
1539 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1540 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1541 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1542 r[dst] = JSImmediate::andImmediateNumbers(src1, src2);
1544 JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
1545 VM_CHECK_EXCEPTION();
1552 BEGIN_OPCODE(op_bitxor) {
1553 /* bitxor dst(r) src1(r) src2(r)
1555 Computes bitwise XOR of register src1 (converted to int32)
1556 and register src2 (converted to int32), and puts the result
1559 int dst = (++vPC)->u.operand;
1560 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1561 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1562 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1563 r[dst] = JSImmediate::xorImmediateNumbers(src1, src2);
1565 JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
1566 VM_CHECK_EXCEPTION();
1573 BEGIN_OPCODE(op_bitor) {
1574 /* bitor dst(r) src1(r) src2(r)
1576 Computes bitwise OR of register src1 (converted to int32)
1577 and register src2 (converted to int32), and puts the
1578 result in register dst.
1580 int dst = (++vPC)->u.operand;
1581 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1582 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1583 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1584 r[dst] = JSImmediate::orImmediateNumbers(src1, src2);
1586 JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
1587 VM_CHECK_EXCEPTION();
1594 BEGIN_OPCODE(op_bitnot) {
1595 /* bitnot dst(r) src(r)
1597 Computes bitwise NOT of register src1 (converted to int32),
1598 and puts the result in register dst.
1600 int dst = (++vPC)->u.operand;
1601 int src = (++vPC)->u.operand;
1602 JSValue* result = jsNumber(exec, ~r[src].jsValue(exec)->toInt32(exec));
1603 VM_CHECK_EXCEPTION();
1609 BEGIN_OPCODE(op_not) {
1610 /* not dst(r) src(r)
1612 Computes logical NOT of register src (converted to
1613 boolean), and puts the result in register dst.
1615 int dst = (++vPC)->u.operand;
1616 int src = (++vPC)->u.operand;
1617 JSValue* result = jsBoolean(!r[src].jsValue(exec)->toBoolean(exec));
1618 VM_CHECK_EXCEPTION();
1624 BEGIN_OPCODE(op_instanceof) {
1625 /* instanceof dst(r) value(r) constructor(r)
1627 Tests whether register value is an instance of register
1628 constructor, and puts the boolean result in register dst.
1630 Raises an exception if register constructor is not an
1633 int dst = (++vPC)->u.operand;
1634 int value = (++vPC)->u.operand;
1635 int base = (++vPC)->u.operand;
1637 JSValue* baseVal = r[base].jsValue(exec);
1639 if (isNotObject(exec, true, codeBlock, vPC, baseVal, exceptionValue))
1642 JSObject* baseObj = static_cast<JSObject*>(baseVal);
1643 r[dst] = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec)) : false);
1648 BEGIN_OPCODE(op_typeof) {
1649 /* typeof dst(r) src(r)
1651 Determines the type string for src according to ECMAScript
1652 rules, and puts the result in register dst.
1654 int dst = (++vPC)->u.operand;
1655 int src = (++vPC)->u.operand;
1656 r[dst] = jsTypeStringForValue(exec, r[src].jsValue(exec));
1661 BEGIN_OPCODE(op_in) {
1662 /* in dst(r) property(r) base(r)
1664 Tests whether register base has a property named register
1665 property, and puts the boolean result in register dst.
1667 Raises an exception if register constructor is not an
1670 int dst = (++vPC)->u.operand;
1671 int property = (++vPC)->u.operand;
1672 int base = (++vPC)->u.operand;
1674 JSValue* baseVal = r[base].jsValue(exec);
1675 if (isNotObject(exec, false, codeBlock, vPC, baseVal, exceptionValue))
1678 JSObject* baseObj = static_cast<JSObject*>(baseVal);
1680 JSValue* propName = r[property].jsValue(exec);
1683 if (propName->getUInt32(i))
1684 r[dst] = jsBoolean(baseObj->hasProperty(exec, i));
1686 Identifier property(exec, propName->toString(exec));
1687 VM_CHECK_EXCEPTION();
1688 r[dst] = jsBoolean(baseObj->hasProperty(exec, property));
1694 BEGIN_OPCODE(op_resolve) {
1695 /* resolve dst(r) property(id)
1697 Looks up the property named by identifier property in the
1698 scope chain, and writes the resulting value to register
1699 dst. If the property is not found, raises an exception.
1701 if (UNLIKELY(!resolve(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1707 BEGIN_OPCODE(op_resolve_skip) {
1708 /* resolve_skip dst(r) property(id) skip(n)
1710 Looks up the property named by identifier property in the
1711 scope chain skipping the top 'skip' levels, and writes the resulting
1712 value to register dst. If the property is not found, raises an exception.
1714 if (UNLIKELY(!resolve_skip(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1721 BEGIN_OPCODE(op_get_scoped_var) {
1722 /* get_scoped_var dst(r) index(n) skip(n)
1724 Loads the contents of the index-th local from the scope skip nodes from
1725 the top of the scope chain, and places it in register dst
1727 int dst = (++vPC)->u.operand;
1728 int index = (++vPC)->u.operand;
1729 int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1731 ScopeChainIterator iter = scopeChain->begin();
1732 ScopeChainIterator end = scopeChain->end();
1733 ASSERT(iter != end);
1736 ASSERT(iter != end);
1739 ASSERT((*iter)->isVariableObject());
1740 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1741 r[dst] = scope->registerAt(index);
1745 BEGIN_OPCODE(op_put_scoped_var) {
1746 /* put_scoped_var index(n) skip(n) value(r)
1749 int index = (++vPC)->u.operand;
1750 int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1751 int value = (++vPC)->u.operand;
1753 ScopeChainIterator iter = scopeChain->begin();
1754 ScopeChainIterator end = scopeChain->end();
1755 ASSERT(iter != end);
1758 ASSERT(iter != end);
1761 ASSERT((*iter)->isVariableObject());
1762 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1763 scope->registerAt(index) = r[value].jsValue(exec);
1767 BEGIN_OPCODE(op_resolve_base) {
1768 /* resolve_base dst(r) property(id)
1770 Searches the scope chain for an object containing
1771 identifier property, and if one is found, writes it to
1772 register dst. If none is found, the outermost scope (which
1773 will be the global object) is stored in register dst.
1775 resolveBase(exec, vPC, r, scopeChain, codeBlock);
1780 BEGIN_OPCODE(op_resolve_with_base) {
1781 /* resolve_with_base baseDst(r) propDst(r) property(id)
1783 Searches the scope chain for an object containing
1784 identifier property, and if one is found, writes it to
1785 register srcDst, and the retrieved property value to register
1786 propDst. If the property is not found, raises an exception.
1788 This is more efficient than doing resolve_base followed by
1789 resolve, or resolve_base followed by get_by_id, as it
1790 avoids duplicate hash lookups.
1792 if (UNLIKELY(!resolveBaseAndProperty(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1798 BEGIN_OPCODE(op_resolve_func) {
1799 /* resolve_func baseDst(r) funcDst(r) property(id)
1801 Searches the scope chain for an object containing
1802 identifier property, and if one is found, writes the
1803 appropriate object to use as "this" when calling its
1804 properties to register baseDst; and the retrieved property
1805 value to register propDst. If the property is not found,
1806 raises an exception.
1808 This differs from resolve_with_base, because the
1809 global this value will be substituted for activations or
1810 the global object, which is the right behavior for function
1811 calls but not for other property lookup.
1813 if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1819 BEGIN_OPCODE(op_get_by_id) {
1820 /* get_by_id dst(r) base(r) property(id)
1822 Converts register base to Object, gets the property
1823 named by identifier property from the object, and puts the
1824 result in register dst.
1826 int dst = (++vPC)->u.operand;
1827 int base = (++vPC)->u.operand;
1828 int property = (++vPC)->u.operand;
1830 Identifier& ident = codeBlock->identifiers[property];
1831 JSValue *result = r[base].jsValue(exec)->get(exec, ident);
1832 VM_CHECK_EXCEPTION();
1837 BEGIN_OPCODE(op_put_by_id) {
1838 /* put_by_id base(r) property(id) value(r)
1840 Sets register value on register base as the property named
1841 by identifier property. Base is converted to object first.
1843 Unlike many opcodes, this one does not write any output to
1846 int base = (++vPC)->u.operand;
1847 int property = (++vPC)->u.operand;
1848 int value = (++vPC)->u.operand;
1850 Identifier& ident = codeBlock->identifiers[property];
1851 r[base].jsValue(exec)->put(exec, ident, r[value].jsValue(exec));
1853 VM_CHECK_EXCEPTION();
1857 BEGIN_OPCODE(op_del_by_id) {
1858 /* del_by_id dst(r) base(r) property(id)
1860 Converts register base to Object, deletes the property
1861 named by identifier property from the object, and writes a
1862 boolean indicating success (if true) or failure (if false)
1865 int dst = (++vPC)->u.operand;
1866 int base = (++vPC)->u.operand;
1867 int property = (++vPC)->u.operand;
1869 JSObject* baseObj = r[base].jsValue(exec)->toObject(exec);
1871 Identifier& ident = codeBlock->identifiers[property];
1872 JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
1873 VM_CHECK_EXCEPTION();
1878 BEGIN_OPCODE(op_get_by_val) {
1879 /* get_by_val dst(r) base(r) property(r)
1881 Converts register base to Object, gets the property named
1882 by register property from the object, and puts the result
1883 in register dst. property is nominally converted to string
1884 but numbers are treated more efficiently.
1886 int dst = (++vPC)->u.operand;
1887 int base = (++vPC)->u.operand;
1888 int property = (++vPC)->u.operand;
1890 JSValue* baseValue = r[base].jsValue(exec);
1891 JSValue* subscript = r[property].jsValue(exec);
1896 bool isUInt32 = JSImmediate::getUInt32(subscript, i);
1897 if (LIKELY(isUInt32)) {
1898 if (isJSArray(baseValue)) {
1899 JSArray* jsArray = static_cast<JSArray*>(baseValue);
1900 if (jsArray->canGetIndex(i))
1901 result = jsArray->getIndex(i);
1903 result = jsArray->JSArray::get(exec, i);
1904 } else if (isJSString(baseValue) && static_cast<JSString*>(baseValue)->canGetIndex(i))
1905 result = static_cast<JSString*>(baseValue)->getIndex(exec, i);
1907 result = baseValue->get(exec, i);
1909 Identifier property(exec, subscript->toString(exec));
1910 result = baseValue->get(exec, property);
1913 VM_CHECK_EXCEPTION();
1918 BEGIN_OPCODE(op_put_by_val) {
1919 /* put_by_val base(r) property(r) value(r)
1921 Sets register value on register base as the property named
1922 by register property. Base is converted to object
1923 first. register property is nominally converted to string
1924 but numbers are treated more efficiently.
1926 Unlike many opcodes, this one does not write any output to
1929 int base = (++vPC)->u.operand;
1930 int property = (++vPC)->u.operand;
1931 int value = (++vPC)->u.operand;
1933 JSValue* baseValue = r[base].jsValue(exec);
1934 JSValue* subscript = r[property].jsValue(exec);
1938 bool isUInt32 = JSImmediate::getUInt32(subscript, i);
1939 if (LIKELY(isUInt32)) {
1940 if (isJSArray(baseValue)) {
1941 JSArray* jsArray = static_cast<JSArray*>(baseValue);
1942 if (jsArray->canSetIndex(i))
1943 jsArray->setIndex(i, r[value].jsValue(exec));
1945 jsArray->JSArray::put(exec, i, r[value].jsValue(exec));
1947 baseValue->put(exec, i, r[value].jsValue(exec));
1949 Identifier property(exec, subscript->toString(exec));
1950 if (!exec->hadException()) // Don't put to an object if toString threw an exception.
1951 baseValue->put(exec, property, r[value].jsValue(exec));
1954 VM_CHECK_EXCEPTION();
1958 BEGIN_OPCODE(op_del_by_val) {
1959 /* del_by_val dst(r) base(r) property(r)
1961 Converts register base to Object, deletes the property
1962 named by register property from the object, and writes a
1963 boolean indicating success (if true) or failure (if false)
1966 int dst = (++vPC)->u.operand;
1967 int base = (++vPC)->u.operand;
1968 int property = (++vPC)->u.operand;
1970 JSObject* baseObj = r[base].jsValue(exec)->toObject(exec); // may throw
1972 JSValue* subscript = r[property].jsValue(exec);
1975 if (subscript->getUInt32(i))
1976 result = jsBoolean(baseObj->deleteProperty(exec, i));
1978 VM_CHECK_EXCEPTION();
1979 Identifier property(exec, subscript->toString(exec));
1980 VM_CHECK_EXCEPTION();
1981 result = jsBoolean(baseObj->deleteProperty(exec, property));
1984 VM_CHECK_EXCEPTION();
1989 BEGIN_OPCODE(op_put_by_index) {
1990 /* put_by_index base(r) property(n) value(r)
1992 Sets register value on register base as the property named
1993 by the immediate number property. Base is converted to
1996 Unlike many opcodes, this one does not write any output to
1999 This opcode is mainly used to initialize array literals.
2001 int base = (++vPC)->u.operand;
2002 unsigned property = (++vPC)->u.operand;
2003 int value = (++vPC)->u.operand;
2005 r[base].jsValue(exec)->put(exec, property, r[value].jsValue(exec));
2010 BEGIN_OPCODE(op_loop) {
2011 /* loop target(offset)
2013 Jumps unconditionally to offset target from the current
2016 Additionally this loop instruction may terminate JS execution is
2017 the JS timeout is reached.
2019 #if DUMP_OPCODE_STATS
2020 OpcodeStats::resetLastInstruction();
2022 int target = (++vPC)->u.operand;
2023 CHECK_FOR_TIMEOUT();
2027 BEGIN_OPCODE(op_jmp) {
2028 /* jmp target(offset)
2030 Jumps unconditionally to offset target from the current
2033 #if DUMP_OPCODE_STATS
2034 OpcodeStats::resetLastInstruction();
2036 int target = (++vPC)->u.operand;
2041 BEGIN_OPCODE(op_loop_if_true) {
2042 /* loop_if_true cond(r) target(offset)
2044 Jumps to offset target from the current instruction, if and
2045 only if register cond converts to boolean as true.
2047 Additionally this loop instruction may terminate JS execution is
2048 the JS timeout is reached.
2050 int cond = (++vPC)->u.operand;
2051 int target = (++vPC)->u.operand;
2052 if (r[cond].jsValue(exec)->toBoolean(exec)) {
2054 CHECK_FOR_TIMEOUT();
2061 BEGIN_OPCODE(op_jtrue) {
2062 /* jtrue cond(r) target(offset)
2064 Jumps to offset target from the current instruction, if and
2065 only if register cond converts to boolean as true.
2067 int cond = (++vPC)->u.operand;
2068 int target = (++vPC)->u.operand;
2069 if (r[cond].jsValue(exec)->toBoolean(exec)) {
2077 BEGIN_OPCODE(op_jfalse) {
2078 /* jfalse cond(r) target(offset)
2080 Jumps to offset target from the current instruction, if and
2081 only if register cond converts to boolean as false.
2083 int cond = (++vPC)->u.operand;
2084 int target = (++vPC)->u.operand;
2085 if (!r[cond].jsValue(exec)->toBoolean(exec)) {
2093 BEGIN_OPCODE(op_loop_if_less) {
2094 /* loop_if_less src1(r) src2(r) target(offset)
2096 Checks whether register src1 is less than register src2, as
2097 with the ECMAScript '<' operator, and then jumps to offset
2098 target from the current instruction, if and only if the
2099 result of the comparison is true.
2101 Additionally this loop instruction may terminate JS execution is
2102 the JS timeout is reached.
2104 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2105 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2106 int target = (++vPC)->u.operand;
2108 bool result = jsLess(exec, src1, src2);
2109 VM_CHECK_EXCEPTION();
2113 CHECK_FOR_TIMEOUT();
2120 BEGIN_OPCODE(op_jless) {
2121 /* jless src1(r) src2(r) target(offset)
2123 Checks whether register src1 is less than register src2, as
2124 with the ECMAScript '<' operator, and then jumps to offset
2125 target from the current instruction, if and only if the
2126 result of the comparison is true.
2128 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2129 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2130 int target = (++vPC)->u.operand;
2132 bool result = jsLess(exec, src1, src2);
2133 VM_CHECK_EXCEPTION();
2143 BEGIN_OPCODE(op_jnless) {
2144 /* jnless src1(r) src2(r) target(offset)
2146 Checks whether register src1 is less than register src2, as
2147 with the ECMAScript '<' operator, and then jumps to offset
2148 target from the current instruction, if and only if the
2149 result of the comparison is false.
2151 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2152 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2153 int target = (++vPC)->u.operand;
2155 bool result = jsLess(exec, src1, src2);
2156 VM_CHECK_EXCEPTION();
2166 BEGIN_OPCODE(op_switch_imm) {
2167 /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
2169 Performs a range checked switch on the scrutinee value, using
2170 the tableIndex-th immediate switch jump table. If the scrutinee value
2171 is an immediate number in the range covered by the referenced jump
2172 table, and the value at jumpTable[scrutinee value] is non-zero, then
2173 that value is used as the jump offset, otherwise defaultOffset is used.
2175 int tableIndex = (++vPC)->u.operand;
2176 int defaultOffset = (++vPC)->u.operand;
2177 JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2178 if (!JSImmediate::isNumber(scrutinee))
2179 vPC += defaultOffset;
2181 int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
2182 vPC += codeBlock->immediateSwitchJumpTables[tableIndex].offsetForValue(value, defaultOffset);
2186 BEGIN_OPCODE(op_switch_char) {
2187 /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
2189 Performs a range checked switch on the scrutinee value, using
2190 the tableIndex-th character switch jump table. If the scrutinee value
2191 is a single character string in the range covered by the referenced jump
2192 table, and the value at jumpTable[scrutinee value] is non-zero, then
2193 that value is used as the jump offset, otherwise defaultOffset is used.
2195 int tableIndex = (++vPC)->u.operand;
2196 int defaultOffset = (++vPC)->u.operand;
2197 JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2198 if (scrutinee->type() != StringType)
2199 vPC += defaultOffset;
2201 UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
2202 if (value->size() != 1)
2203 vPC += defaultOffset;
2205 vPC += codeBlock->characterSwitchJumpTables[tableIndex].offsetForValue(value->data()[0], defaultOffset);
2209 BEGIN_OPCODE(op_switch_string) {
2210 /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
2212 Performs a sparse hashmap based switch on the value in the scrutinee
2213 register, using the tableIndex-th string switch jump table. If the
2214 scrutinee value is a string that exists as a key in the referenced
2215 jump table, then the value associated with the string is used as the
2216 jump offset, otherwise defaultOffset is used.
2218 int tableIndex = (++vPC)->u.operand;
2219 int defaultOffset = (++vPC)->u.operand;
2220 JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2221 if (scrutinee->type() != StringType)
2222 vPC += defaultOffset;
2224 vPC += offsetForStringSwitch(codeBlock->stringSwitchJumpTables[tableIndex], scrutinee, defaultOffset);
2227 BEGIN_OPCODE(op_new_func) {
2228 /* new_func dst(r) func(f)
2230 Constructs a new Function instance from function func and
2231 the current scope chain using the original Function
2232 constructor, using the rules for function declarations, and
2233 puts the result in register dst.
2235 int dst = (++vPC)->u.operand;
2236 int func = (++vPC)->u.operand;
2238 r[dst] = codeBlock->functions[func]->makeFunction(exec, scopeChain);
2243 BEGIN_OPCODE(op_new_func_exp) {
2244 /* new_func_exp dst(r) func(f)
2246 Constructs a new Function instance from function func and
2247 the current scope chain using the original Function
2248 constructor, using the rules for function expressions, and
2249 puts the result in register dst.
2251 int dst = (++vPC)->u.operand;
2252 int func = (++vPC)->u.operand;
2254 r[dst] = codeBlock->functionExpressions[func]->makeFunction(exec, scopeChain);
2259 BEGIN_OPCODE(op_call_eval) {
2260 /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2262 Call a function named "eval" with no explicit "this" value
2263 (which may therefore be the eval operator). If register
2264 thisVal is the global object, and register func contains
2265 that global object's original global eval function, then
2266 perform the eval operator in local scope (interpreting
2267 the argument registers as for the "call"
2268 opcode). Otherwise, act exactly as the "call" opcode would.
2271 int dst = (++vPC)->u.operand;
2272 int func = (++vPC)->u.operand;
2273 int thisVal = (++vPC)->u.operand;
2274 int firstArg = (++vPC)->u.operand;
2275 int argCount = (++vPC)->u.operand;
2277 JSValue* funcVal = r[func].jsValue(exec);
2278 JSValue* baseVal = r[thisVal].jsValue(exec);
2280 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
2281 JSObject* thisObject = static_cast<JSObject*>(r[codeBlock->thisRegister].jsValue(exec));
2282 JSValue* result = callEval(exec, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
2292 // We didn't find the blessed version of eval, so reset vPC and process
2293 // this instruction as a normal function call, supplying the proper 'this'
2296 r[thisVal] = baseVal->toThisObject(exec);
2298 #if HAVE(COMPUTED_GOTO)
2299 // Hack around gcc performance quirk by performing an indirect goto
2300 // in order to set the vPC -- attempting to do so directly results in a
2301 // significant regression.
2302 goto *op_call_indirect; // indirect goto -> op_call
2304 // fall through to op_call
2306 BEGIN_OPCODE(op_call) {
2307 /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2309 Perform a function call. Specifically, call register func
2310 with a "this" value of register thisVal, and put the result
2313 The arguments start at register firstArg and go up to
2314 argCount, but the "this" value is considered an implicit
2315 first argument, so the argCount should be one greater than
2316 the number of explicit arguments passed, and the register
2317 after firstArg should contain the actual first
2318 argument. This opcode will copy from the thisVal register
2319 to the firstArg register, unless the register index of
2320 thisVal is the special missing this object marker, which is
2321 2^31-1; in that case, the global object will be used as the
2324 If func is a native code function, then this opcode calls
2325 it and returns the value immediately.
2327 But if it is a JS function, then the current scope chain
2328 and code block is set to the function's, and we slide the
2329 register window so that the arguments would form the first
2330 few local registers of the called function's register
2331 window. In addition, a call frame header is written
2332 immediately before the arguments; see the call frame
2333 documentation for an explanation of how many registers a
2334 call frame takes and what they contain. That many registers
2335 before the firstArg register will be overwritten by the
2336 call. In addition, any registers higher than firstArg +
2337 argCount may be overwritten. Once this setup is complete,
2338 execution continues from the called function's first
2339 argument, and does not return until a "ret" opcode is
2343 int dst = (++vPC)->u.operand;
2344 int func = (++vPC)->u.operand;
2345 int thisVal = (++vPC)->u.operand;
2346 int firstArg = (++vPC)->u.operand;
2347 int argCount = (++vPC)->u.operand;
2349 JSValue* v = r[func].jsValue(exec);
2352 CallType callType = v->getCallData(callData);
2354 if (callType == CallTypeJS) {
2355 if (*enabledProfilerReference)
2356 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2358 ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
2359 FunctionBodyNode* functionBodyNode = callData.js.functionBody;
2360 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
2362 r[firstArg] = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
2364 Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
2365 initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 0, v);
2366 exec->m_callFrame = callFrame;
2368 r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
2369 if (UNLIKELY(exceptionValue != 0))
2372 codeBlock = newCodeBlock;
2373 setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
2374 vPC = codeBlock->instructions.begin();
2376 #if DUMP_OPCODE_STATS
2377 OpcodeStats::resetLastInstruction();
2383 if (callType == CallTypeHost) {
2384 if (*enabledProfilerReference)
2385 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2387 JSValue* thisValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
2388 ArgList args(r + firstArg + 1, argCount - 1);
2390 MACHINE_SAMPLING_callingHostFunction();
2392 JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(v), thisValue, args);
2393 VM_CHECK_EXCEPTION();
2395 r[dst] = returnValue;
2397 if (*enabledProfilerReference)
2398 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
2404 ASSERT(callType == CallTypeNone);
2406 exceptionValue = createNotAFunctionError(exec, v, vPC, codeBlock);
2409 BEGIN_OPCODE(op_ret) {
2412 Return register result as the return value of the current
2413 function call, writing it into the caller's expected return
2414 value register. In addition, unwind one call frame and
2415 restore the scope chain, code block instruction pointer and
2416 register base to those of the calling function.
2419 int result = (++vPC)->u.operand;
2421 Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2422 if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
2423 ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
2424 ASSERT(activation->isActivationObject());
2425 activation->copyRegisters();
2428 if (*enabledProfilerReference)
2429 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
2431 if (codeBlock->needsFullScopeChain)
2432 scopeChain->deref();
2434 JSValue* returnValue = r[result].jsValue(exec);
2435 if (callFrame[RegisterFile::CalledAsConstructor].i() && !returnValue->isObject()) {
2436 JSValue* thisObject = callFrame[RegisterFile::CallFrameHeaderSize].jsValue(exec);
2437 returnValue = thisObject;
2440 codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
2444 vPC = callFrame[RegisterFile::ReturnVPC].vPC();
2445 setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].scopeChain());
2446 r = callFrame[RegisterFile::CallerRegisters].r();
2447 exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2448 int dst = callFrame[RegisterFile::ReturnValueRegister].i();
2449 r[dst] = returnValue;
2453 BEGIN_OPCODE(op_construct) {
2454 /* construct dst(r) constr(r) firstArg(r) argCount(n)
2456 Invoke register "constr" as a constructor. For JS
2457 functions, the calling convention is exactly as for the
2458 "call" opcode, except that the "this" value is a newly
2459 created Object. For native constructors, a null "this"
2460 value is passed. In either case, the firstArg and argCount
2461 registers are interpreted as for the "call" opcode.
2464 int dst = (++vPC)->u.operand;
2465 int constr = (++vPC)->u.operand;
2466 int firstArg = (++vPC)->u.operand;
2467 int argCount = (++vPC)->u.operand;
2469 JSValue* constrVal = r[constr].jsValue(exec);
2471 ConstructData constructData;
2472 ConstructType constructType = constrVal->getConstructData(constructData);
2474 // Removing this line of code causes a measurable regression on squirrelfish.
2475 JSObject* constructor = static_cast<JSObject*>(constrVal);
2477 if (constructType == ConstructTypeJS) {
2478 if (*enabledProfilerReference)
2479 (*enabledProfilerReference)->willExecute(exec, constructor);
2481 JSObject* prototype;
2482 JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
2484 prototype = static_cast<JSObject*>(p);
2486 prototype = scopeChain->globalObject()->objectPrototype();
2487 JSObject* newObject = new (exec) JSObject(prototype);
2489 ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
2490 FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
2491 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
2493 r[firstArg] = newObject; // "this" value
2495 Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
2496 initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 1, constructor);
2497 exec->m_callFrame = callFrame;
2499 r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
2503 codeBlock = newCodeBlock;
2504 setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
2505 vPC = codeBlock->instructions.begin();
2510 if (constructType == ConstructTypeHost) {
2511 if (*enabledProfilerReference)
2512 (*enabledProfilerReference)->willExecute(exec, constructor);
2514 ArgList args(r + firstArg + 1, argCount - 1);
2516 MACHINE_SAMPLING_callingHostFunction();
2518 JSValue* returnValue = constructData.native.function(exec, constructor, args);
2520 VM_CHECK_EXCEPTION();
2521 r[dst] = returnValue;
2523 if (*enabledProfilerReference)
2524 (*enabledProfilerReference)->didExecute(exec, constructor);
2530 ASSERT(constructType == ConstructTypeNone);
2532 exceptionValue = createNotAConstructorError(exec, constrVal, vPC, codeBlock);
2535 BEGIN_OPCODE(op_push_scope) {
2536 /* push_scope scope(r)
2538 Converts register scope to object, and pushes it onto the top
2539 of the current scope chain.
2541 int scope = (++vPC)->u.operand;
2542 JSValue* v = r[scope].jsValue(exec);
2543 JSObject* o = v->toObject(exec);
2544 VM_CHECK_EXCEPTION();
2546 setScopeChain(exec, scopeChain, scopeChain->push(o));
2551 BEGIN_OPCODE(op_pop_scope) {
2554 Removes the top item from the current scope chain.
2556 setScopeChain(exec, scopeChain, scopeChain->pop());
2561 BEGIN_OPCODE(op_get_pnames) {
2562 /* get_pnames dst(r) base(r)
2564 Creates a property name list for register base and puts it
2565 in register dst. This is not a true JavaScript value, just
2566 a synthetic value used to keep the iteration state in a
2569 int dst = (++vPC)->u.operand;
2570 int base = (++vPC)->u.operand;
2572 r[dst] = JSPropertyNameIterator::create(exec, r[base].jsValue(exec));
2576 BEGIN_OPCODE(op_next_pname) {
2577 /* next_pname dst(r) iter(r) target(offset)
2579 Tries to copies the next name from property name list in
2580 register iter. If there are names left, then copies one to
2581 register dst, and jumps to offset target. If there are none
2582 left, invalidates the iterator and continues to the next
2585 int dst = (++vPC)->u.operand;
2586 int iter = (++vPC)->u.operand;
2587 int target = (++vPC)->u.operand;
2589 JSPropertyNameIterator* it = r[iter].jsPropertyNameIterator();
2590 if (JSValue* temp = it->next(exec)) {
2591 CHECK_FOR_TIMEOUT();
2601 BEGIN_OPCODE(op_jmp_scopes) {
2602 /* jmp_scopes count(n) target(offset)
2604 Removes the a number of items from the current scope chain
2605 specified by immediate number count, then jumps to offset
2608 int count = (++vPC)->u.operand;
2609 int target = (++vPC)->u.operand;
2611 ScopeChainNode* tmp = scopeChain;
2614 setScopeChain(exec, scopeChain, tmp);
2619 #if HAVE(COMPUTED_GOTO)
2621 goto *(&&skip_new_scope);
2623 BEGIN_OPCODE(op_push_new_scope) {
2624 /* new_scope dst(r) property(id) value(r)
2626 Constructs a new StaticScopeObject with property set to value. That scope
2627 object is then pushed onto the ScopeChain. The scope object is then stored
2630 setScopeChain(exec, scopeChain, createExceptionScope(exec, codeBlock, vPC, r, scopeChain));
2634 #if HAVE(COMPUTED_GOTO)
2637 BEGIN_OPCODE(op_catch) {
2640 Retrieves the VMs current exception and puts it in register
2641 ex. This is only valid after an exception has been raised,
2642 and usually forms the beginning of an exception handler.
2644 ASSERT(exceptionValue);
2645 ASSERT(!exec->hadException());
2646 int ex = (++vPC)->u.operand;
2647 r[ex] = exceptionValue;
2653 BEGIN_OPCODE(op_throw) {
2656 Throws register ex as an exception. This involves three
2657 steps: first, it is set as the current exception in the
2658 VM's internal state, then the stack is unwound until an
2659 exception handler or a native code boundary is found, and
2660 then control resumes at the exception handler if any or
2661 else the script returns control to the nearest native caller.
2664 int ex = (++vPC)->u.operand;
2665 exceptionValue = r[ex].jsValue(exec);
2667 handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, scopeChain, r, true);
2669 *exception = exceptionValue;
2673 #if HAVE(COMPUTED_GOTO)
2674 // Hack around gcc performance quirk by performing an indirect goto
2675 // in order to set the vPC -- attempting to do so directly results in a
2676 // significant regression.
2677 goto *op_throw_end_indirect; // indirect goto -> op_throw_end
2685 BEGIN_OPCODE(op_unexpected_load) {
2686 /* unexpected_load load dst(r) src(k)
2688 Copies constant src to register dst.
2690 int dst = (++vPC)->u.operand;
2691 int src = (++vPC)->u.operand;
2692 r[dst] = codeBlock->unexpectedConstants[src];
2697 BEGIN_OPCODE(op_new_error) {
2698 /* new_error dst(r) type(n) message(k)
2700 Constructs a new Error instance using the original
2701 constructor, using immediate number n as the type and
2702 constant message as the message string. The result is
2703 written to register dst.
2705 int dst = (++vPC)->u.operand;
2706 int type = (++vPC)->u.operand;
2707 int message = (++vPC)->u.operand;
2709 r[dst] = Error::create(exec, (ErrorType)type, codeBlock->unexpectedConstants[message]->toString(exec), codeBlock->lineNumberForVPC(vPC), codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
2714 BEGIN_OPCODE(op_end) {
2717 Return register result as the value of a global or eval
2718 program. Return control to the calling native code.
2721 if (codeBlock->needsFullScopeChain) {
2722 ASSERT(scopeChain->refCount > 1);
2723 scopeChain->deref();
2725 int result = (++vPC)->u.operand;
2726 return r[result].jsValue(exec);
2728 BEGIN_OPCODE(op_put_getter) {
2729 /* put_getter base(r) property(id) function(r)
2731 Sets register function on register base as the getter named
2732 by identifier property. Base and function are assumed to be
2733 objects as this op should only be used for getters defined
2734 in object literal form.
2736 Unlike many opcodes, this one does not write any output to
2739 int base = (++vPC)->u.operand;
2740 int property = (++vPC)->u.operand;
2741 int function = (++vPC)->u.operand;
2743 ASSERT(r[base].jsValue(exec)->isObject());
2744 JSObject* baseObj = static_cast<JSObject*>(r[base].jsValue(exec));
2745 Identifier& ident = codeBlock->identifiers[property];
2746 ASSERT(r[function].jsValue(exec)->isObject());
2747 baseObj->defineGetter(exec, ident, static_cast<JSObject*>(r[function].jsValue(exec)));
2752 BEGIN_OPCODE(op_put_setter) {
2753 /* put_setter base(r) property(id) function(r)
2755 Sets register function on register base as the setter named
2756 by identifier property. Base and function are assumed to be
2757 objects as this op should only be used for setters defined
2758 in object literal form.
2760 Unlike many opcodes, this one does not write any output to
2763 int base = (++vPC)->u.operand;
2764 int property = (++vPC)->u.operand;
2765 int function = (++vPC)->u.operand;
2767 ASSERT(r[base].jsValue(exec)->isObject());
2768 JSObject* baseObj = static_cast<JSObject*>(r[base].jsValue(exec));
2769 Identifier& ident = codeBlock->identifiers[property];
2770 ASSERT(r[function].jsValue(exec)->isObject());
2771 baseObj->defineSetter(exec, ident, static_cast<JSObject*>(r[function].jsValue(exec)));
2776 BEGIN_OPCODE(op_jsr) {
2777 /* jsr retAddrDst(r) target(offset)
2779 Places the address of the next instruction into the retAddrDst
2780 register and jumps to offset target from the current instruction.
2782 int retAddrDst = (++vPC)->u.operand;
2783 int target = (++vPC)->u.operand;
2784 r[retAddrDst] = vPC + 1;
2789 BEGIN_OPCODE(op_sret) {
2790 /* sret retAddrSrc(r)
2792 Jumps to the address stored in the retAddrSrc register. This
2793 differs from op_jmp because the target address is stored in a
2794 register, not as an immediate.
2796 int retAddrSrc = (++vPC)->u.operand;
2797 vPC = r[retAddrSrc].vPC();
2800 BEGIN_OPCODE(op_debug) {
2801 /* debug debugHookID(n) firstLine(n) lastLine(n)
2803 Notifies the debugger of the current state of execution. This opcode
2804 is only generated while the debugger is attached.
2807 debug(exec, vPC, codeBlock, scopeChain, r);
2813 exec->clearException();
2815 // The exceptionValue is a lie! (GCC produces bad code for reasons I
2816 // cannot fathom if we don't assign to the exceptionValue before branching)
2817 exceptionValue = createInterruptedExecutionException(exec);
2819 handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, scopeChain, r, false);
2821 *exception = exceptionValue;
2830 #undef VM_CHECK_EXCEPTION
2833 JSValue* Machine::retrieveArguments(ExecState* exec, JSFunction* function) const
2835 Register* callFrame = this->callFrame(exec, function);
2839 JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec));
2841 CodeBlock* codeBlock = &function->m_body->generatedByteCode();
2842 activation = new (exec) JSActivation(function->m_body, callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numLocals);
2843 callFrame[RegisterFile::OptionalCalleeActivation] = activation;
2846 return activation->get(exec, exec->propertyNames().arguments);
2849 JSValue* Machine::retrieveCaller(ExecState* exec, JSFunction* function) const
2851 Register* callFrame = this->callFrame(exec, function);
2855 CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
2856 if (!callerCodeBlock)
2859 Register* callerCallFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2860 if (JSValue* caller = callerCallFrame[RegisterFile::Callee].jsValue(exec))
2866 Register* Machine::callFrame(ExecState* exec, JSFunction* function) const
2868 Register* callFrame = exec->m_callFrame;
2871 while (!callFrame) {
2872 exec = exec->m_prev;
2875 callFrame = exec->m_callFrame;
2878 if (callFrame[RegisterFile::Callee].jsValue(exec) == function)
2881 CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
2882 if (!callerCodeBlock) {
2887 callFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2891 void Machine::getArgumentsData(Register* callFrame, JSFunction*& function, Register*& argv, int& argc)
2893 function = static_cast<JSFunction*>(callFrame[RegisterFile::Callee].getJSValue());
2894 ASSERT(function->inherits(&JSFunction::info));
2896 argv = callFrame[RegisterFile::CallerRegisters].r() + callFrame[RegisterFile::ArgumentStartRegister].i() + 1; // + 1 to skip "this"
2897 argc = callFrame[RegisterFile::ArgumentCount].i() - 1; // - 1 to skip "this"