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->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();
425 ALWAYS_INLINE ScopeChainNode* scopeChainForCall(ExecState* exec, FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register* r)
427 if (newCodeBlock->needsFullScopeChain) {
428 JSActivation* activation = new (exec) JSActivation(functionBodyNode, r);
429 r[RegisterFile::OptionalCalleeActivation - RegisterFile::CallFrameHeaderSize - newCodeBlock->numLocals] = activation;
431 return callDataScopeChain->copy()->push(activation);
434 return callDataScopeChain;
437 static NEVER_INLINE bool isNotObject(ExecState* exec, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValue* value, JSValue*& exceptionData)
439 if (value->isObject())
441 exceptionData = createInvalidParamError(exec, forInstanceOf ? "instanceof" : "in" , value, vPC, codeBlock);
445 NEVER_INLINE JSValue* Machine::callEval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
448 return jsUndefined();
450 JSValue* program = r[argv + 1].jsValue(exec);
452 if (!program->isString())
455 Profiler** profiler = Profiler::enabledProfilerReference();
457 (*profiler)->willExecute(exec, scopeChain->globalObject()->evalFunction());
462 RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(static_cast<JSString*>(program)->value()), &sourceId, &errLine, &errMsg);
465 exceptionValue = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
467 (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
471 JSValue* result = exec->globalData().machine->execute(evalNode.get(), exec, thisObj, r - registerFile->base() + argv + argc, scopeChain, &exceptionValue);
474 (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
483 , m_timeAtLastCheckTimeout(0)
485 , m_timeoutCheckCount(0)
486 , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold)
488 privateExecute(InitializeAndReturn);
490 // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
491 void* storage = fastMalloc(sizeof(CollectorBlock));
493 JSArray* jsArray = new (storage) JSArray(jsNull(), 0);
494 m_jsArrayVptr = jsArray->vptr();
495 static_cast<JSCell*>(jsArray)->~JSCell();
497 JSString* jsString = new (storage) JSString("");
498 m_jsStringVptr = jsString->vptr();
499 static_cast<JSCell*>(jsString)->~JSCell();
504 void Machine::dumpCallFrame(const CodeBlock* codeBlock, ScopeChainNode* scopeChain, RegisterFile* registerFile, const Register* r)
506 ScopeChain sc(scopeChain);
507 JSGlobalObject* globalObject = sc.globalObject();
508 codeBlock->dump(globalObject->globalExec());
509 dumpRegisters(codeBlock, registerFile, r);
512 void Machine::dumpRegisters(const CodeBlock* codeBlock, RegisterFile* registerFile, const Register* r)
514 printf("Register frame: \n\n");
515 printf("----------------------------------------------------\n");
516 printf(" use | address | value \n");
517 printf("----------------------------------------------------\n");
522 if (codeBlock->codeType == GlobalCode) {
523 it = registerFile->lastGlobal();
524 end = it + registerFile->numGlobals();
526 printf("[global var] | %10p | %10p \n", it, (*it).v());
529 printf("----------------------------------------------------\n");
532 it = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
533 printf("[CallerCodeBlock] | %10p | %10p \n", it, (*it).v()); ++it;
534 printf("[ReturnVPC] | %10p | %10p \n", it, (*it).v()); ++it;
535 printf("[CallerScopeChain] | %10p | %10p \n", it, (*it).v()); ++it;
536 printf("[CallerRegisterOffset] | %10p | %10p \n", it, (*it).v()); ++it;
537 printf("[ReturnValueRegister] | %10p | %10p \n", it, (*it).v()); ++it;
538 printf("[ArgumentStartRegister] | %10p | %10p \n", it, (*it).v()); ++it;
539 printf("[ArgumentCount] | %10p | %10p \n", it, (*it).v()); ++it;
540 printf("[CalledAsConstructor] | %10p | %10p \n", it, (*it).v()); ++it;
541 printf("[Callee] | %10p | %10p \n", it, (*it).v()); ++it;
542 printf("[OptionalCalleeActivation] | %10p | %10p \n", it, (*it).v()); ++it;
543 printf("----------------------------------------------------\n");
545 printf("[this] | %10p | %10p \n", it, (*it).v()); ++it;
546 end = it + max(codeBlock->numParameters - 1, 0); // - 1 to skip "this"
549 printf("[param] | %10p | %10p \n", it, (*it).v());
553 printf("----------------------------------------------------\n");
555 if (codeBlock->codeType != GlobalCode) {
556 end = it + codeBlock->numVars;
559 printf("[var] | %10p | %10p \n", it, (*it).v());
562 printf("----------------------------------------------------\n");
566 end = it + codeBlock->numTemporaries;
569 printf("[temp] | %10p | %10p \n", it, (*it).v());
575 bool Machine::isOpcode(Opcode opcode)
577 #if HAVE(COMPUTED_GOTO)
578 return opcode != HashTraits<Opcode>::emptyValue()
579 && !HashTraits<Opcode>::isDeletedValue(opcode)
580 && m_opcodeIDTable.contains(opcode);
582 return opcode >= 0 && opcode <= op_end;
586 NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock, Register*& k, ScopeChainNode*& scopeChain, Register*& r)
588 CodeBlock* oldCodeBlock = codeBlock;
589 Register* callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
591 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
592 DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
593 if (callFrame[RegisterFile::Callee].jsValue(exec))
594 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
596 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
599 if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
600 if (callFrame[RegisterFile::Callee].jsValue(exec))
601 profiler->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
603 profiler->didExecute(exec, codeBlock->ownerNode->sourceURL(), codeBlock->ownerNode->lineNo());
606 if (oldCodeBlock->needsFullScopeChain)
609 // If this call frame created an activation, tear it off.
610 if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
611 ASSERT(activation->isActivationObject());
612 activation->copyRegisters();
615 codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
619 k = codeBlock->registers.data();
620 scopeChain = callFrame[RegisterFile::CallerScopeChain].scopeChain();
621 r = callFrame[RegisterFile::CallerRegisters].r();
622 exec->m_callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
623 vPC = callFrame[RegisterFile::ReturnVPC].vPC();
628 NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue*& exceptionValue, const Instruction* vPC, CodeBlock*& codeBlock, Register*& k, ScopeChainNode*& scopeChain, Register*& r, bool explicitThrow)
630 // Set up the exception object
632 if (exceptionValue->isObject()) {
633 JSObject* exception = static_cast<JSObject*>(exceptionValue);
634 if (exception->isNotAnObjectErrorStub()) {
635 exception = createNotAnObjectError(exec, static_cast<JSNotAnObjectErrorStub*>(exception), vPC, codeBlock);
636 exceptionValue = exception;
638 if (!exception->hasProperty(exec, Identifier(exec, "line")) &&
639 !exception->hasProperty(exec, Identifier(exec, "sourceId")) &&
640 !exception->hasProperty(exec, Identifier(exec, "sourceURL")) &&
641 !exception->hasProperty(exec, Identifier(exec, expressionBeginOffsetPropertyName)) &&
642 !exception->hasProperty(exec, Identifier(exec, expressionCaretOffsetPropertyName)) &&
643 !exception->hasProperty(exec, Identifier(exec, expressionEndOffsetPropertyName))) {
648 int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset);
649 exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, line), ReadOnly | DontDelete);
651 // We only hit this path for error messages and throw statements, which don't have a specific failure position
652 // So we just give the full range of the error/throw statement.
653 exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
654 exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
656 exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, codeBlock->lineNumberForVPC(vPC)), ReadOnly | DontDelete);
657 exception->putWithAttributes(exec, Identifier(exec, "sourceId"), jsNumber(exec, codeBlock->ownerNode->sourceId()), ReadOnly | DontDelete);
658 exception->putWithAttributes(exec, Identifier(exec, "sourceURL"), jsOwnedString(exec, codeBlock->ownerNode->sourceURL()), ReadOnly | DontDelete);
661 if (exception->isWatchdogException()) {
662 while (unwindCallFrame(exec, exceptionValue, vPC, codeBlock, k, scopeChain, r)) {
663 // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
670 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
671 DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
672 debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->lineNumberForVPC(vPC));
675 // Calculate an exception handler vPC, unwinding call frames as necessary.
678 Instruction* handlerVPC;
680 while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) {
681 if (!unwindCallFrame(exec, exceptionValue, vPC, codeBlock, k, scopeChain, r))
685 // Now unwind the scope chain within the exception handler's call frame.
687 ScopeChain sc(scopeChain);
688 int scopeDelta = depth(sc) - scopeDepth;
689 ASSERT(scopeDelta >= 0);
692 setScopeChain(exec, scopeChain, sc.node());
697 JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue** exception)
699 if (m_reentryDepth >= MaxReentryDepth) {
700 *exception = createStackOverflowError(exec);
704 CodeBlock* codeBlock = &programNode->byteCode(scopeChain);
706 size_t oldSize = m_registerFile.size();
707 size_t newSize = oldSize + RegisterFile::CallFrameHeaderSize + codeBlock->numVars + codeBlock->numTemporaries;
708 if (!m_registerFile.grow(newSize)) {
709 *exception = createStackOverflowError(exec);
713 JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
714 JSGlobalObject* globalObject = exec->dynamicGlobalObject();
715 globalObject->copyGlobalsTo(m_registerFile);
717 Register* callFrame = m_registerFile.base() + oldSize;
719 // a 0 codeBlock indicates a built-in caller
720 initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
722 Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
723 r[codeBlock->thisRegister] = thisObj;
725 if (codeBlock->needsFullScopeChain)
726 scopeChain = scopeChain->copy();
728 ExecState newExec(exec, &m_registerFile, scopeChain, 0);
730 Profiler** profiler = Profiler::enabledProfilerReference();
732 (*profiler)->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
735 JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
738 MACHINE_SAMPLING_privateExecuteReturned();
741 (*profiler)->didExecute(exec, programNode->sourceURL(), programNode->lineNo());
743 (*profiler)->didFinishAllExecution(exec);
746 if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
747 lastGlobalObject->copyGlobalsTo(m_registerFile);
749 m_registerFile.shrink(oldSize);
753 JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue** exception)
755 if (m_reentryDepth >= MaxReentryDepth) {
756 *exception = createStackOverflowError(exec);
760 int argv = RegisterFile::CallFrameHeaderSize;
761 int argc = args.size() + 1; // implicit "this" parameter
763 size_t oldSize = m_registerFile.size();
764 if (!m_registerFile.grow(oldSize + RegisterFile::CallFrameHeaderSize + argc)) {
765 *exception = createStackOverflowError(exec);
769 Register* callFrame = m_registerFile.base() + oldSize;
771 // put args in place, including "this"
772 Register* dst = callFrame + RegisterFile::CallFrameHeaderSize;
775 ArgList::const_iterator end = args.end();
776 for (ArgList::const_iterator it = args.begin(); it != end; ++it)
779 // a 0 codeBlock indicates a built-in caller
780 initializeCallFrame(callFrame, 0, 0, 0, callFrame, 0, argv, argc, 0, function);
782 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(scopeChain);
783 Register* r = slideRegisterWindowForCall(exec, newCodeBlock, &m_registerFile, m_registerFile.base(), callFrame, argv, argc, *exception);
785 m_registerFile.shrink(oldSize);
789 scopeChain = scopeChainForCall(exec, functionBodyNode, newCodeBlock, scopeChain, r);
791 ExecState newExec(exec, &m_registerFile, scopeChain, callFrame);
793 Profiler** profiler = Profiler::enabledProfilerReference();
795 (*profiler)->willExecute(exec, function);
798 JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
801 MACHINE_SAMPLING_privateExecuteReturned();
803 if (*profiler && !m_reentryDepth)
804 (*profiler)->didFinishAllExecution(exec);
806 m_registerFile.shrink(oldSize);
810 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
812 if (m_reentryDepth >= MaxReentryDepth) {
813 *exception = createStackOverflowError(exec);
817 EvalCodeBlock* codeBlock = &evalNode->byteCode(scopeChain);
819 JSVariableObject* variableObject;
820 for (ScopeChainNode* node = scopeChain; ; node = node->next) {
822 if (node->object->isVariableObject()) {
823 variableObject = static_cast<JSVariableObject*>(node->object);
828 const Node::VarStack& varStack = codeBlock->ownerNode->varStack();
829 Node::VarStack::const_iterator varStackEnd = varStack.end();
830 for (Node::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
831 const Identifier& ident = (*it).first;
832 if (!variableObject->hasProperty(exec, ident))
833 variableObject->put(exec, ident, jsUndefined());
836 const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack();
837 Node::FunctionStack::const_iterator functionStackEnd = functionStack.end();
838 for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it)
839 variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain));
841 size_t oldSize = m_registerFile.size();
842 size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numTemporaries + RegisterFile::CallFrameHeaderSize;
843 if (!m_registerFile.grow(newSize)) {
844 *exception = createStackOverflowError(exec);
848 Register* callFrame = m_registerFile.base() + registerOffset;
850 // a 0 codeBlock indicates a built-in caller
851 initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
853 Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
854 r[codeBlock->thisRegister] = thisObj;
856 if (codeBlock->needsFullScopeChain)
857 scopeChain = scopeChain->copy();
859 ExecState newExec(exec, &m_registerFile, scopeChain, 0);
861 Profiler** profiler = Profiler::enabledProfilerReference();
863 (*profiler)->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
866 JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
869 MACHINE_SAMPLING_privateExecuteReturned();
872 (*profiler)->didExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
874 (*profiler)->didFinishAllExecution(exec);
877 m_registerFile.shrink(oldSize);
881 ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scopeChain, ScopeChainNode* newScopeChain)
883 scopeChain = newScopeChain;
884 exec->m_scopeChain = newScopeChain;
887 NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r)
889 int debugHookID = (++vPC)->u.operand;
890 int firstLine = (++vPC)->u.operand;
891 int lastLine = (++vPC)->u.operand;
893 Debugger* debugger = exec->dynamicGlobalObject()->debugger();
897 DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, r, 0);
899 switch((DebugHookID)debugHookID) {
900 case DidEnterCallFrame: {
901 debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
904 case WillLeaveCallFrame: {
905 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
908 case WillExecuteStatement: {
909 debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
912 case WillExecuteProgram: {
913 debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
916 case DidExecuteProgram: {
917 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
920 case DidReachBreakpoint: {
921 debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
927 void Machine::resetTimeoutCheck()
929 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
930 m_timeAtLastCheckTimeout = 0;
934 // Returns the current time in milliseconds
935 // It doesn't matter what "current time" is here, just as long as
936 // it's possible to measure the time difference correctly.
937 // In an ideal world this would just be getCurrentUTCTimeWithMicroseconds
938 // from DateMath.h, but unfortunately there's a slowdown if we use tha.
939 static inline unsigned getCurrentTime()
943 gettimeofday(&tv, 0);
944 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
946 QDateTime t = QDateTime::currentDateTime();
947 return t.toTime_t() * 1000 + t.time().msec();
948 #elif PLATFORM(WIN_OS)
949 return timeGetTime();
951 #error Platform does not have getCurrentTime function
955 // We have to return a JSValue here, gcc seems to produce worse code if
956 // we attempt to return a bool
957 ALWAYS_INLINE JSValue* Machine::checkTimeout(JSGlobalObject* globalObject)
959 unsigned currentTime = getCurrentTime();
961 if (!m_timeAtLastCheckTimeout) {
962 // Suspicious amount of looping in a script -- start timing it
963 m_timeAtLastCheckTimeout = currentTime;
967 unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
972 m_timeExecuting += timeDiff;
973 m_timeAtLastCheckTimeout = currentTime;
975 // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
976 // preferredScriptCheckTimeInterval
977 m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck);
978 // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
979 // preferred script check time interval.
980 if (m_ticksUntilNextTimeoutCheck == 0)
981 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
983 if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
984 if (globalObject->shouldInterruptScript())
985 return jsNull(); // Appeasing GCC, all we need is a non-null js value.
993 static int32_t offsetForStringSwitch(StringJumpTable& jumpTable, JSValue* scrutinee, int32_t defaultOffset) {
994 StringJumpTable::const_iterator end = jumpTable.end();
995 UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
996 StringJumpTable::const_iterator loc = jumpTable.find(value);
998 return defaultOffset;
1002 static NEVER_INLINE ScopeChainNode* createExceptionScope(ExecState* exec, CodeBlock* codeBlock, const Instruction* vPC, Register* r, ScopeChainNode* scopeChain)
1004 int dst = (++vPC)->u.operand;
1005 Identifier& property = codeBlock->identifiers[(++vPC)->u.operand];
1006 JSValue* value = r[(++vPC)->u.operand].jsValue(exec);
1007 JSObject* scope = new (exec) JSStaticScopeObject(property, value, DontDelete);
1009 return scopeChain->push(scope);
1012 JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
1014 // One-time initialization of our address tables. We have to put this code
1015 // here because our labels are only in scope inside this function.
1016 if (flag == InitializeAndReturn) {
1017 #if HAVE(COMPUTED_GOTO)
1018 #define ADD_OPCODE(id) m_opcodeTable[id] = &&id;
1019 FOR_EACH_OPCODE_ID(ADD_OPCODE);
1022 #define ADD_OPCODE_ID(id) m_opcodeIDTable.add(&&id, id);
1023 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
1025 ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
1026 op_throw_end_indirect = &&op_throw_end;
1027 op_call_indirect = &&op_call;
1028 #endif // HAVE(COMPUTED_GOTO)
1032 JSValue* exceptionValue = 0;
1033 Instruction* handlerVPC = 0;
1035 Register* registerBase = registerFile->base();
1036 Instruction* vPC = codeBlock->instructions.begin();
1037 Register* k = codeBlock->registers.data();
1038 Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
1039 unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
1041 #define VM_CHECK_EXCEPTION() \
1043 if (UNLIKELY(exec->hadException())) { \
1044 exceptionValue = exec->exception(); \
1049 #if DUMP_OPCODE_STATS
1050 OpcodeStats::resetLastInstruction();
1053 #define CHECK_FOR_TIMEOUT() \
1054 if (!--tickCount) { \
1055 if ((exceptionValue = checkTimeout(exec->dynamicGlobalObject()))) \
1057 tickCount = m_ticksUntilNextTimeoutCheck; \
1060 #if HAVE(COMPUTED_GOTO)
1061 #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); goto *vPC->u.opcode
1062 #if DUMP_OPCODE_STATS
1063 #define BEGIN_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
1065 #define BEGIN_OPCODE(opcode) opcode:
1069 #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); continue
1070 #if DUMP_OPCODE_STATS
1071 #define BEGIN_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
1073 #define BEGIN_OPCODE(opcode) case opcode:
1075 while (1) // iterator loop begins
1076 switch (vPC->u.opcode)
1079 BEGIN_OPCODE(op_load) {
1080 /* load dst(r) src(k)
1082 Copies constant src to register dst.
1084 int dst = (++vPC)->u.operand;
1085 int src = (++vPC)->u.operand;
1091 BEGIN_OPCODE(op_new_object) {
1092 /* new_object dst(r)
1094 Constructs a new empty Object instance using the original
1095 constructor, and puts the result in register dst.
1097 int dst = (++vPC)->u.operand;
1098 r[dst] = constructEmptyObject(exec);
1103 BEGIN_OPCODE(op_new_array) {
1104 /* new_array dst(r) firstArg(r) argCount(n)
1106 Constructs a new Array instance using the original
1107 constructor, and puts the result in register dst.
1108 The array will contain argCount elements with values
1109 taken from registers starting at register firstArg.
1111 int dst = (++vPC)->u.operand;
1112 int firstArg = (++vPC)->u.operand;
1113 int argCount = (++vPC)->u.operand;
1114 ArgList args(r + firstArg, argCount);
1115 r[dst] = constructArray(exec, args);
1120 BEGIN_OPCODE(op_new_regexp) {
1121 /* new_regexp dst(r) regExp(re)
1123 Constructs a new RegExp instance using the original
1124 constructor from regexp regExp, and puts the result in
1127 int dst = (++vPC)->u.operand;
1128 int regExp = (++vPC)->u.operand;
1129 r[dst] = new (exec) RegExpObject(scopeChain->globalObject()->regExpPrototype(), codeBlock->regexps[regExp]);
1134 BEGIN_OPCODE(op_mov) {
1135 /* mov dst(r) src(r)
1137 Copies register src to register dst.
1139 int dst = (++vPC)->u.operand;
1140 int src = (++vPC)->u.operand;
1146 BEGIN_OPCODE(op_eq) {
1147 /* eq dst(r) src1(r) src2(r)
1149 Checks whether register src1 and register src2 are equal,
1150 as with the ECMAScript '==' operator, and puts the result
1151 as a boolean in register dst.
1153 int dst = (++vPC)->u.operand;
1154 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1155 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1156 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1157 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1159 JSValue* result = jsBoolean(equal(exec, src1, src2));
1160 VM_CHECK_EXCEPTION();
1167 BEGIN_OPCODE(op_neq) {
1168 /* neq dst(r) src1(r) src2(r)
1170 Checks whether register src1 and register src2 are not
1171 equal, as with the ECMAScript '!=' operator, and puts the
1172 result as a boolean in register dst.
1174 int dst = (++vPC)->u.operand;
1175 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1176 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1177 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1178 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1180 JSValue* result = jsBoolean(!equal(exec, src1, src2));
1181 VM_CHECK_EXCEPTION();
1188 BEGIN_OPCODE(op_stricteq) {
1189 /* stricteq dst(r) src1(r) src2(r)
1191 Checks whether register src1 and register src2 are strictly
1192 equal, as with the ECMAScript '===' operator, and puts the
1193 result as a boolean in register dst.
1195 int dst = (++vPC)->u.operand;
1196 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1197 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1198 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1199 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1201 r[dst] = jsBoolean(strictEqual(src1, src2));
1206 BEGIN_OPCODE(op_nstricteq) {
1207 /* nstricteq dst(r) src1(r) src2(r)
1209 Checks whether register src1 and register src2 are not
1210 strictly equal, as with the ECMAScript '!==' operator, and
1211 puts the result as a boolean in register dst.
1213 int dst = (++vPC)->u.operand;
1214 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1215 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1216 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1217 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1219 r[dst] = jsBoolean(!strictEqual(src1, src2));
1224 BEGIN_OPCODE(op_less) {
1225 /* less dst(r) src1(r) src2(r)
1227 Checks whether register src1 is less than register src2, as
1228 with the ECMAScript '<' operator, and puts the result as
1229 a boolean in register dst.
1231 int dst = (++vPC)->u.operand;
1232 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1233 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1234 JSValue* result = jsBoolean(jsLess(exec, src1, src2));
1235 VM_CHECK_EXCEPTION();
1241 BEGIN_OPCODE(op_lesseq) {
1242 /* lesseq dst(r) src1(r) src2(r)
1244 Checks whether register src1 is less than or equal to
1245 register src2, as with the ECMAScript '<=' operator, and
1246 puts the result as a boolean in register dst.
1248 int dst = (++vPC)->u.operand;
1249 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1250 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1251 JSValue* result = jsBoolean(jsLessEq(exec, src1, src2));
1252 VM_CHECK_EXCEPTION();
1258 BEGIN_OPCODE(op_pre_inc) {
1259 /* pre_inc srcDst(r)
1261 Converts register srcDst to number, adds one, and puts the result
1262 back in register srcDst.
1264 int srcDst = (++vPC)->u.operand;
1265 JSValue* v = r[srcDst].jsValue(exec);
1266 if (JSImmediate::canDoFastAdditiveOperations(v))
1267 r[srcDst] = JSImmediate::incImmediateNumber(v);
1269 JSValue* result = jsNumber(exec, v->toNumber(exec) + 1);
1270 VM_CHECK_EXCEPTION();
1277 BEGIN_OPCODE(op_pre_dec) {
1278 /* pre_dec srcDst(r)
1280 Converts register srcDst to number, subtracts one, and puts the result
1281 back in register srcDst.
1283 int srcDst = (++vPC)->u.operand;
1284 JSValue* v = r[srcDst].jsValue(exec);
1285 if (JSImmediate::canDoFastAdditiveOperations(v))
1286 r[srcDst] = JSImmediate::decImmediateNumber(v);
1288 JSValue* result = jsNumber(exec, v->toNumber(exec) - 1);
1289 VM_CHECK_EXCEPTION();
1296 BEGIN_OPCODE(op_post_inc) {
1297 /* post_inc dst(r) srcDst(r)
1299 Converts register srcDst to number. The number itself is
1300 written to register dst, and the number plus one is written
1301 back to register srcDst.
1303 int dst = (++vPC)->u.operand;
1304 int srcDst = (++vPC)->u.operand;
1305 JSValue* v = r[srcDst].jsValue(exec);
1306 if (JSImmediate::canDoFastAdditiveOperations(v)) {
1308 r[srcDst] = JSImmediate::incImmediateNumber(v);
1310 JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1311 VM_CHECK_EXCEPTION();
1313 r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() + 1);
1319 BEGIN_OPCODE(op_post_dec) {
1320 /* post_dec dst(r) srcDst(r)
1322 Converts register srcDst to number. The number itself is
1323 written to register dst, and the number minus one is written
1324 back to register srcDst.
1326 int dst = (++vPC)->u.operand;
1327 int srcDst = (++vPC)->u.operand;
1328 JSValue* v = r[srcDst].jsValue(exec);
1329 if (JSImmediate::canDoFastAdditiveOperations(v)) {
1331 r[srcDst] = JSImmediate::decImmediateNumber(v);
1333 JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1334 VM_CHECK_EXCEPTION();
1336 r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() - 1);
1342 BEGIN_OPCODE(op_to_jsnumber) {
1343 /* to_jsnumber dst(r) src(r)
1345 Converts register src to number, and puts the result
1348 int dst = (++vPC)->u.operand;
1349 int src = (++vPC)->u.operand;
1350 JSValue* result = r[src].jsValue(exec)->toJSNumber(exec);
1351 VM_CHECK_EXCEPTION();
1358 BEGIN_OPCODE(op_negate) {
1359 /* negate dst(r) src(r)
1361 Converts register src to number, negates it, and puts the
1362 result in register dst.
1364 int dst = (++vPC)->u.operand;
1365 int src = (++vPC)->u.operand;
1366 JSValue* result = jsNumber(exec, -r[src].jsValue(exec)->toNumber(exec));
1367 VM_CHECK_EXCEPTION();
1373 BEGIN_OPCODE(op_add) {
1374 /* add dst(r) src1(r) src2(r)
1376 Adds register src1 and register src2, and puts the result
1377 in register dst. (JS add may be string concatenation or
1378 numeric add, depending on the types of the operands.)
1380 int dst = (++vPC)->u.operand;
1381 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1382 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1383 if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1384 r[dst] = JSImmediate::addImmediateNumbers(src1, src2);
1386 JSValue* result = jsAdd(exec, src1, src2);
1387 VM_CHECK_EXCEPTION();
1393 BEGIN_OPCODE(op_mul) {
1394 /* mul dst(r) src1(r) src2(r)
1396 Multiplies register src1 and register src2 (converted to
1397 numbers), and puts the product in register dst.
1399 int dst = (++vPC)->u.operand;
1400 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1401 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1402 JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
1403 VM_CHECK_EXCEPTION();
1409 BEGIN_OPCODE(op_div) {
1410 /* div dst(r) dividend(r) divisor(r)
1412 Divides register dividend (converted to number) by the
1413 register divisor (converted to number), and puts the
1414 quotient in register dst.
1416 int dst = (++vPC)->u.operand;
1417 int dividend = (++vPC)->u.operand;
1418 int divisor = (++vPC)->u.operand;
1419 JSValue* result = jsNumber(exec, r[dividend].jsValue(exec)->toNumber(exec) / r[divisor].jsValue(exec)->toNumber(exec));
1420 VM_CHECK_EXCEPTION();
1425 BEGIN_OPCODE(op_mod) {
1426 /* mod dst(r) dividend(r) divisor(r)
1428 Divides register dividend (converted to number) by
1429 register divisor (converted to number), and puts the
1430 remainder in register dst.
1432 int dst = (++vPC)->u.operand;
1433 int dividend = (++vPC)->u.operand;
1434 int divisor = (++vPC)->u.operand;
1436 JSValue* dividendValue = r[dividend].jsValue(exec);
1437 JSValue* divisorValue = r[divisor].jsValue(exec);
1439 if (JSImmediate::areBothImmediateNumbers(dividendValue, divisorValue) && divisorValue != JSImmediate::from(0)) {
1440 r[dst] = JSImmediate::from(JSImmediate::getTruncatedInt32(dividendValue) % JSImmediate::getTruncatedInt32(divisorValue));
1445 double d = dividendValue->toNumber(exec);
1446 JSValue* result = jsNumber(exec, fmod(d, divisorValue->toNumber(exec)));
1447 VM_CHECK_EXCEPTION();
1452 BEGIN_OPCODE(op_sub) {
1453 /* sub dst(r) src1(r) src2(r)
1455 Subtracts register src2 (converted to number) from register
1456 src1 (converted to number), and puts the difference in
1459 int dst = (++vPC)->u.operand;
1460 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1461 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1462 if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1463 r[dst] = JSImmediate::subImmediateNumbers(src1, src2);
1465 JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
1466 VM_CHECK_EXCEPTION();
1472 BEGIN_OPCODE(op_lshift) {
1473 /* lshift dst(r) val(r) shift(r)
1475 Performs left shift of register val (converted to int32) by
1476 register shift (converted to uint32), and puts the result
1479 int dst = (++vPC)->u.operand;
1480 JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1481 JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1482 if (JSImmediate::areBothImmediateNumbers(val, shift))
1483 r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::toTruncatedUInt32(shift) & 0x1f));
1485 JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
1486 VM_CHECK_EXCEPTION();
1493 BEGIN_OPCODE(op_rshift) {
1494 /* rshift dst(r) val(r) shift(r)
1496 Performs arithmetic right shift of register val (converted
1497 to int32) by register shift (converted to
1498 uint32), and puts the result in register dst.
1500 int dst = (++vPC)->u.operand;
1501 JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1502 JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1503 if (JSImmediate::areBothImmediateNumbers(val, shift))
1504 r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1506 JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1507 VM_CHECK_EXCEPTION();
1514 BEGIN_OPCODE(op_urshift) {
1515 /* rshift dst(r) val(r) shift(r)
1517 Performs logical right shift of register val (converted
1518 to uint32) by register shift (converted to
1519 uint32), and puts the result in register dst.
1521 int dst = (++vPC)->u.operand;
1522 JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1523 JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1524 if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
1525 r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1527 JSValue* result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1528 VM_CHECK_EXCEPTION();
1535 BEGIN_OPCODE(op_bitand) {
1536 /* bitand dst(r) src1(r) src2(r)
1538 Computes bitwise AND of register src1 (converted to int32)
1539 and register src2 (converted to int32), and puts the result
1542 int dst = (++vPC)->u.operand;
1543 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1544 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1545 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1546 r[dst] = JSImmediate::andImmediateNumbers(src1, src2);
1548 JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
1549 VM_CHECK_EXCEPTION();
1556 BEGIN_OPCODE(op_bitxor) {
1557 /* bitxor dst(r) src1(r) src2(r)
1559 Computes bitwise XOR of register src1 (converted to int32)
1560 and register src2 (converted to int32), and puts the result
1563 int dst = (++vPC)->u.operand;
1564 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1565 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1566 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1567 r[dst] = JSImmediate::xorImmediateNumbers(src1, src2);
1569 JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
1570 VM_CHECK_EXCEPTION();
1577 BEGIN_OPCODE(op_bitor) {
1578 /* bitor dst(r) src1(r) src2(r)
1580 Computes bitwise OR of register src1 (converted to int32)
1581 and register src2 (converted to int32), and puts the
1582 result in register dst.
1584 int dst = (++vPC)->u.operand;
1585 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1586 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1587 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1588 r[dst] = JSImmediate::orImmediateNumbers(src1, src2);
1590 JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
1591 VM_CHECK_EXCEPTION();
1598 BEGIN_OPCODE(op_bitnot) {
1599 /* bitnot dst(r) src(r)
1601 Computes bitwise NOT of register src1 (converted to int32),
1602 and puts the result in register dst.
1604 int dst = (++vPC)->u.operand;
1605 int src = (++vPC)->u.operand;
1606 JSValue* result = jsNumber(exec, ~r[src].jsValue(exec)->toInt32(exec));
1607 VM_CHECK_EXCEPTION();
1613 BEGIN_OPCODE(op_not) {
1614 /* not dst(r) src1(r) src2(r)
1616 Computes logical NOT of register src1 (converted to
1617 boolean), and puts the result in register dst.
1619 int dst = (++vPC)->u.operand;
1620 int src = (++vPC)->u.operand;
1621 JSValue* result = jsBoolean(!r[src].jsValue(exec)->toBoolean(exec));
1622 VM_CHECK_EXCEPTION();
1628 BEGIN_OPCODE(op_instanceof) {
1629 /* instanceof dst(r) value(r) constructor(r)
1631 Tests whether register value is an instance of register
1632 constructor, and puts the boolean result in register dst.
1634 Raises an exception if register constructor is not an
1637 int dst = (++vPC)->u.operand;
1638 int value = (++vPC)->u.operand;
1639 int base = (++vPC)->u.operand;
1641 JSValue* baseVal = r[base].jsValue(exec);
1643 if (isNotObject(exec, true, codeBlock, vPC, baseVal, exceptionValue))
1646 JSObject* baseObj = static_cast<JSObject*>(baseVal);
1647 r[dst] = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec)) : false);
1652 BEGIN_OPCODE(op_typeof) {
1653 /* typeof dst(r) src(r)
1655 Determines the type string for src according to ECMAScript
1656 rules, and puts the result in register dst.
1658 int dst = (++vPC)->u.operand;
1659 int src = (++vPC)->u.operand;
1660 r[dst] = jsTypeStringForValue(exec, r[src].jsValue(exec));
1665 BEGIN_OPCODE(op_in) {
1666 /* in dst(r) property(r) base(r)
1668 Tests whether register base has a property named register
1669 property, and puts the boolean result in register dst.
1671 Raises an exception if register constructor is not an
1674 int dst = (++vPC)->u.operand;
1675 int property = (++vPC)->u.operand;
1676 int base = (++vPC)->u.operand;
1678 JSValue* baseVal = r[base].jsValue(exec);
1679 if (isNotObject(exec, false, codeBlock, vPC, baseVal, exceptionValue))
1682 JSObject* baseObj = static_cast<JSObject*>(baseVal);
1684 JSValue* propName = r[property].jsValue(exec);
1687 if (propName->getUInt32(i))
1688 r[dst] = jsBoolean(baseObj->hasProperty(exec, i));
1690 Identifier property(exec, propName->toString(exec));
1691 VM_CHECK_EXCEPTION();
1692 r[dst] = jsBoolean(baseObj->hasProperty(exec, property));
1698 BEGIN_OPCODE(op_resolve) {
1699 /* resolve dst(r) property(id)
1701 Looks up the property named by identifier property in the
1702 scope chain, and writes the resulting value to register
1703 dst. If the property is not found, raises an exception.
1705 if (UNLIKELY(!resolve(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1711 BEGIN_OPCODE(op_resolve_skip) {
1712 /* resolve_skip dst(r) property(id) skip(n)
1714 Looks up the property named by identifier property in the
1715 scope chain skipping the top 'skip' levels, and writes the resulting
1716 value to register dst. If the property is not found, raises an exception.
1718 if (UNLIKELY(!resolve_skip(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1725 BEGIN_OPCODE(op_get_scoped_var) {
1726 /* get_scoped_var dst(r) index(n) skip(n)
1728 Loads the contents of the index-th local from the scope skip nodes from
1729 the top of the scope chain, and places it in register dst
1731 int dst = (++vPC)->u.operand;
1732 int index = (++vPC)->u.operand;
1733 int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1735 ScopeChainIterator iter = scopeChain->begin();
1736 ScopeChainIterator end = scopeChain->end();
1737 ASSERT(iter != end);
1740 ASSERT(iter != end);
1743 ASSERT((*iter)->isVariableObject());
1744 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1745 r[dst] = scope->registerAt(index);
1749 BEGIN_OPCODE(op_put_scoped_var) {
1750 /* put_scoped_var index(n) skip(n) value(r)
1753 int index = (++vPC)->u.operand;
1754 int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1755 int value = (++vPC)->u.operand;
1757 ScopeChainIterator iter = scopeChain->begin();
1758 ScopeChainIterator end = scopeChain->end();
1759 ASSERT(iter != end);
1762 ASSERT(iter != end);
1765 ASSERT((*iter)->isVariableObject());
1766 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1767 scope->registerAt(index) = r[value].jsValue(exec);
1771 BEGIN_OPCODE(op_resolve_base) {
1772 /* resolve_base dst(r) property(id)
1774 Searches the scope chain for an object containing
1775 identifier property, and if one is found, writes it to
1776 register dst. If none is found, the outermost scope (which
1777 will be the global object) is stored in register dst.
1779 resolveBase(exec, vPC, r, scopeChain, codeBlock);
1784 BEGIN_OPCODE(op_resolve_with_base) {
1785 /* resolve_with_base baseDst(r) propDst(r) property(id)
1787 Searches the scope chain for an object containing
1788 identifier property, and if one is found, writes it to
1789 register srcDst, and the retrieved property value to register
1790 propDst. If the property is not found, raises an exception.
1792 This is more efficient than doing resolve_base followed by
1793 resolve, or resolve_base followed by get_by_id, as it
1794 avoids duplicate hash lookups.
1796 if (UNLIKELY(!resolveBaseAndProperty(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1802 BEGIN_OPCODE(op_resolve_func) {
1803 /* resolve_func baseDst(r) funcDst(r) property(id)
1805 Searches the scope chain for an object containing
1806 identifier property, and if one is found, writes the
1807 appropriate object to use as "this" when calling its
1808 properties to register baseDst; and the retrieved property
1809 value to register propDst. If the property is not found,
1810 raises an exception.
1812 This differs from resolve_with_base, because the
1813 global this value will be substituted for activations or
1814 the global object, which is the right behavior for function
1815 calls but not for other property lookup.
1817 if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1823 BEGIN_OPCODE(op_get_by_id) {
1824 /* get_by_id dst(r) base(r) property(id)
1826 Converts register base to Object, gets the property
1827 named by identifier property from the object, and puts the
1828 result in register dst.
1830 int dst = (++vPC)->u.operand;
1831 int base = (++vPC)->u.operand;
1832 int property = (++vPC)->u.operand;
1834 Identifier& ident = codeBlock->identifiers[property];
1835 JSValue *result = r[base].jsValue(exec)->get(exec, ident);
1836 VM_CHECK_EXCEPTION();
1841 BEGIN_OPCODE(op_put_by_id) {
1842 /* put_by_id base(r) property(id) value(r)
1844 Sets register value on register base as the property named
1845 by identifier property. Base is converted to object first.
1847 Unlike many opcodes, this one does not write any output to
1850 int base = (++vPC)->u.operand;
1851 int property = (++vPC)->u.operand;
1852 int value = (++vPC)->u.operand;
1854 Identifier& ident = codeBlock->identifiers[property];
1855 r[base].jsValue(exec)->put(exec, ident, r[value].jsValue(exec));
1857 VM_CHECK_EXCEPTION();
1861 BEGIN_OPCODE(op_del_by_id) {
1862 /* del_by_id dst(r) base(r) property(id)
1864 Converts register base to Object, deletes the property
1865 named by identifier property from the object, and writes a
1866 boolean indicating success (if true) or failure (if false)
1869 int dst = (++vPC)->u.operand;
1870 int base = (++vPC)->u.operand;
1871 int property = (++vPC)->u.operand;
1873 JSObject* baseObj = r[base].jsValue(exec)->toObject(exec);
1875 Identifier& ident = codeBlock->identifiers[property];
1876 JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
1877 VM_CHECK_EXCEPTION();
1882 BEGIN_OPCODE(op_get_by_val) {
1883 /* get_by_val dst(r) base(r) property(r)
1885 Converts register base to Object, gets the property named
1886 by register property from the object, and puts the result
1887 in register dst. property is nominally converted to string
1888 but numbers are treated more efficiently.
1890 int dst = (++vPC)->u.operand;
1891 int base = (++vPC)->u.operand;
1892 int property = (++vPC)->u.operand;
1894 JSValue* baseValue = r[base].jsValue(exec);
1895 JSValue* subscript = r[property].jsValue(exec);
1900 bool isUInt32 = JSImmediate::getUInt32(subscript, i);
1901 if (LIKELY(isUInt32)) {
1902 if (isJSArray(baseValue)) {
1903 JSArray* jsArray = static_cast<JSArray*>(baseValue);
1904 if (jsArray->canGetIndex(i))
1905 result = jsArray->getIndex(i);
1907 result = jsArray->JSArray::get(exec, i);
1908 } else if (isJSString(baseValue) && static_cast<JSString*>(baseValue)->canGetIndex(i))
1909 result = static_cast<JSString*>(baseValue)->getIndex(exec, i);
1911 result = baseValue->get(exec, i);
1913 Identifier property(exec, subscript->toString(exec));
1914 result = baseValue->get(exec, property);
1917 VM_CHECK_EXCEPTION();
1922 BEGIN_OPCODE(op_put_by_val) {
1923 /* put_by_val base(r) property(r) value(r)
1925 Sets register value on register base as the property named
1926 by register property. Base is converted to object
1927 first. register property is nominally converted to string
1928 but numbers are treated more efficiently.
1930 Unlike many opcodes, this one does not write any output to
1933 int base = (++vPC)->u.operand;
1934 int property = (++vPC)->u.operand;
1935 int value = (++vPC)->u.operand;
1937 JSValue* baseValue = r[base].jsValue(exec);
1938 JSValue* subscript = r[property].jsValue(exec);
1942 bool isUInt32 = JSImmediate::getUInt32(subscript, i);
1943 if (LIKELY(isUInt32)) {
1944 if (isJSArray(baseValue)) {
1945 JSArray* jsArray = static_cast<JSArray*>(baseValue);
1946 if (jsArray->canSetIndex(i))
1947 jsArray->setIndex(i, r[value].jsValue(exec));
1949 jsArray->JSArray::put(exec, i, r[value].jsValue(exec));
1951 baseValue->put(exec, i, r[value].jsValue(exec));
1953 Identifier property(exec, subscript->toString(exec));
1954 if (!exec->hadException()) // Don't put to an object if toString threw an exception.
1955 baseValue->put(exec, property, r[value].jsValue(exec));
1958 VM_CHECK_EXCEPTION();
1962 BEGIN_OPCODE(op_del_by_val) {
1963 /* del_by_val dst(r) base(r) property(r)
1965 Converts register base to Object, deletes the property
1966 named by register property from the object, and writes a
1967 boolean indicating success (if true) or failure (if false)
1970 int dst = (++vPC)->u.operand;
1971 int base = (++vPC)->u.operand;
1972 int property = (++vPC)->u.operand;
1974 JSObject* baseObj = r[base].jsValue(exec)->toObject(exec); // may throw
1976 JSValue* subscript = r[property].jsValue(exec);
1979 if (subscript->getUInt32(i))
1980 result = jsBoolean(baseObj->deleteProperty(exec, i));
1982 VM_CHECK_EXCEPTION();
1983 Identifier property(exec, subscript->toString(exec));
1984 VM_CHECK_EXCEPTION();
1985 result = jsBoolean(baseObj->deleteProperty(exec, property));
1988 VM_CHECK_EXCEPTION();
1993 BEGIN_OPCODE(op_put_by_index) {
1994 /* put_by_index base(r) property(n) value(r)
1996 Sets register value on register base as the property named
1997 by the immediate number property. Base is converted to
2000 Unlike many opcodes, this one does not write any output to
2003 This opcode is mainly used to initialize array literals.
2005 int base = (++vPC)->u.operand;
2006 unsigned property = (++vPC)->u.operand;
2007 int value = (++vPC)->u.operand;
2009 r[base].jsValue(exec)->put(exec, property, r[value].jsValue(exec));
2014 BEGIN_OPCODE(op_loop) {
2015 /* loop target(offset)
2017 Jumps unconditionally to offset target from the current
2020 Additionally this loop instruction may terminate JS execution is
2021 the JS timeout is reached.
2023 #if DUMP_OPCODE_STATS
2024 OpcodeStats::resetLastInstruction();
2026 int target = (++vPC)->u.operand;
2027 CHECK_FOR_TIMEOUT();
2031 BEGIN_OPCODE(op_jmp) {
2032 /* jmp target(offset)
2034 Jumps unconditionally to offset target from the current
2037 #if DUMP_OPCODE_STATS
2038 OpcodeStats::resetLastInstruction();
2040 int target = (++vPC)->u.operand;
2045 BEGIN_OPCODE(op_loop_if_true) {
2046 /* loop_if_true cond(r) target(offset)
2048 Jumps to offset target from the current instruction, if and
2049 only if register cond converts to boolean as true.
2051 Additionally this loop instruction may terminate JS execution is
2052 the JS timeout is reached.
2054 int cond = (++vPC)->u.operand;
2055 int target = (++vPC)->u.operand;
2056 if (r[cond].jsValue(exec)->toBoolean(exec)) {
2058 CHECK_FOR_TIMEOUT();
2065 BEGIN_OPCODE(op_jtrue) {
2066 /* jtrue cond(r) target(offset)
2068 Jumps to offset target from the current instruction, if and
2069 only if register cond converts to boolean as true.
2071 int cond = (++vPC)->u.operand;
2072 int target = (++vPC)->u.operand;
2073 if (r[cond].jsValue(exec)->toBoolean(exec)) {
2081 BEGIN_OPCODE(op_jfalse) {
2082 /* jfalse cond(r) target(offset)
2084 Jumps to offset target from the current instruction, if and
2085 only if register cond converts to boolean as false.
2087 int cond = (++vPC)->u.operand;
2088 int target = (++vPC)->u.operand;
2089 if (!r[cond].jsValue(exec)->toBoolean(exec)) {
2097 BEGIN_OPCODE(op_loop_if_less) {
2098 /* loop_if_less src1(r) src2(r) target(offset)
2100 Checks whether register src1 is less than register src2, as
2101 with the ECMAScript '<' operator, and then jumps to offset
2102 target from the current instruction, if and only if the
2103 result of the comparison is true.
2105 Additionally this loop instruction may terminate JS execution is
2106 the JS timeout is reached.
2108 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2109 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2110 int target = (++vPC)->u.operand;
2112 bool result = jsLess(exec, src1, src2);
2113 VM_CHECK_EXCEPTION();
2117 CHECK_FOR_TIMEOUT();
2124 BEGIN_OPCODE(op_jless) {
2125 /* jless src1(r) src2(r) target(offset)
2127 Checks whether register src1 is less than register src2, as
2128 with the ECMAScript '<' operator, and then jumps to offset
2129 target from the current instruction, if and only if the
2130 result of the comparison is true.
2132 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2133 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2134 int target = (++vPC)->u.operand;
2136 bool result = jsLess(exec, src1, src2);
2137 VM_CHECK_EXCEPTION();
2147 BEGIN_OPCODE(op_jnless) {
2148 /* jnless src1(r) src2(r) target(offset)
2150 Checks whether register src1 is less than register src2, as
2151 with the ECMAScript '<' operator, and then jumps to offset
2152 target from the current instruction, if and only if the
2153 result of the comparison is false.
2155 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2156 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2157 int target = (++vPC)->u.operand;
2159 bool result = jsLess(exec, src1, src2);
2160 VM_CHECK_EXCEPTION();
2170 BEGIN_OPCODE(op_switch_imm) {
2171 /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
2173 Performs a range checked switch on the scrutinee value, using
2174 the tableIndex-th immediate switch jump table. If the scrutinee value
2175 is an immediate number in the range covered by the referenced jump
2176 table, and the value at jumpTable[scrutinee value] is non-zero, then
2177 that value is used as the jump offset, otherwise defaultOffset is used.
2179 int tableIndex = (++vPC)->u.operand;
2180 int defaultOffset = (++vPC)->u.operand;
2181 JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2182 if (!JSImmediate::isNumber(scrutinee))
2183 vPC += defaultOffset;
2185 int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
2186 vPC += codeBlock->immediateSwitchJumpTables[tableIndex].offsetForValue(value, defaultOffset);
2190 BEGIN_OPCODE(op_switch_char) {
2191 /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
2193 Performs a range checked switch on the scrutinee value, using
2194 the tableIndex-th character switch jump table. If the scrutinee value
2195 is a single character string in the range covered by the referenced jump
2196 table, and the value at jumpTable[scrutinee value] is non-zero, then
2197 that value is used as the jump offset, otherwise defaultOffset is used.
2199 int tableIndex = (++vPC)->u.operand;
2200 int defaultOffset = (++vPC)->u.operand;
2201 JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2202 if (scrutinee->type() != StringType)
2203 vPC += defaultOffset;
2205 UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
2206 if (value->size() != 1)
2207 vPC += defaultOffset;
2209 vPC += codeBlock->characterSwitchJumpTables[tableIndex].offsetForValue(value->data()[0], defaultOffset);
2213 BEGIN_OPCODE(op_switch_string) {
2214 /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
2216 Performs a sparse hashmap based switch on the value in the scrutinee
2217 register, using the tableIndex-th string switch jump table. If the
2218 scrutinee value is a string that exists as a key in the referenced
2219 jump table, then the value associated with the string is used as the
2220 jump offset, otherwise defaultOffset is used.
2222 int tableIndex = (++vPC)->u.operand;
2223 int defaultOffset = (++vPC)->u.operand;
2224 JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2225 if (scrutinee->type() != StringType)
2226 vPC += defaultOffset;
2228 vPC += offsetForStringSwitch(codeBlock->stringSwitchJumpTables[tableIndex], scrutinee, defaultOffset);
2231 BEGIN_OPCODE(op_new_func) {
2232 /* new_func dst(r) func(f)
2234 Constructs a new Function instance from function func and
2235 the current scope chain using the original Function
2236 constructor, using the rules for function declarations, and
2237 puts the result in register dst.
2239 int dst = (++vPC)->u.operand;
2240 int func = (++vPC)->u.operand;
2242 r[dst] = codeBlock->functions[func]->makeFunction(exec, scopeChain);
2247 BEGIN_OPCODE(op_new_func_exp) {
2248 /* new_func_exp dst(r) func(f)
2250 Constructs a new Function instance from function func and
2251 the current scope chain using the original Function
2252 constructor, using the rules for function expressions, and
2253 puts the result in register dst.
2255 int dst = (++vPC)->u.operand;
2256 int func = (++vPC)->u.operand;
2258 r[dst] = codeBlock->functionExpressions[func]->makeFunction(exec, scopeChain);
2263 BEGIN_OPCODE(op_call_eval) {
2264 /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2266 Call a function named "eval" with no explicit "this" value
2267 (which may therefore be the eval operator). If register
2268 thisVal is the global object, and register func contains
2269 that global object's original global eval function, then
2270 perform the eval operator in local scope (interpreting
2271 the argument registers as for the "call"
2272 opcode). Otherwise, act exactly as the "call" opcode would.
2275 int dst = (++vPC)->u.operand;
2276 int func = (++vPC)->u.operand;
2277 int thisVal = (++vPC)->u.operand;
2278 int firstArg = (++vPC)->u.operand;
2279 int argCount = (++vPC)->u.operand;
2281 JSValue* funcVal = r[func].jsValue(exec);
2282 JSValue* baseVal = r[thisVal].jsValue(exec);
2284 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
2285 JSObject* thisObject = static_cast<JSObject*>(r[codeBlock->thisRegister].jsValue(exec));
2286 JSValue* result = callEval(exec, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
2296 // We didn't find the blessed version of eval, so reset vPC and process
2297 // this instruction as a normal function call, supplying the proper 'this'
2300 r[thisVal] = baseVal->toThisObject(exec);
2302 #if HAVE(COMPUTED_GOTO)
2303 // Hack around gcc performance quirk by performing an indirect goto
2304 // in order to set the vPC -- attempting to do so directly results in a
2305 // significant regression.
2306 goto *op_call_indirect; // indirect goto -> op_call
2308 // fall through to op_call
2310 BEGIN_OPCODE(op_call) {
2311 /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2313 Perform a function call. Specifically, call register func
2314 with a "this" value of register thisVal, and put the result
2317 The arguments start at register firstArg and go up to
2318 argCount, but the "this" value is considered an implicit
2319 first argument, so the argCount should be one greater than
2320 the number of explicit arguments passed, and the register
2321 after firstArg should contain the actual first
2322 argument. This opcode will copy from the thisVal register
2323 to the firstArg register, unless the register index of
2324 thisVal is the special missing this object marker, which is
2325 2^31-1; in that case, the global object will be used as the
2328 If func is a native code function, then this opcode calls
2329 it and returns the value immediately.
2331 But if it is a JS function, then the current scope chain
2332 and code block is set to the function's, and we slide the
2333 register window so that the arguments would form the first
2334 few local registers of the called function's register
2335 window. In addition, a call frame header is written
2336 immediately before the arguments; see the call frame
2337 documentation for an explanation of how many registers a
2338 call frame takes and what they contain. That many registers
2339 before the firstArg register will be overwritten by the
2340 call. In addition, any registers higher than firstArg +
2341 argCount may be overwritten. Once this setup is complete,
2342 execution continues from the called function's first
2343 argument, and does not return until a "ret" opcode is
2347 int dst = (++vPC)->u.operand;
2348 int func = (++vPC)->u.operand;
2349 int thisVal = (++vPC)->u.operand;
2350 int firstArg = (++vPC)->u.operand;
2351 int argCount = (++vPC)->u.operand;
2353 JSValue* v = r[func].jsValue(exec);
2356 CallType callType = v->getCallData(callData);
2358 if (callType == CallTypeJS) {
2359 if (*enabledProfilerReference)
2360 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2362 ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
2363 FunctionBodyNode* functionBodyNode = callData.js.functionBody;
2364 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
2366 r[firstArg] = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
2368 Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
2369 initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 0, v);
2370 exec->m_callFrame = callFrame;
2372 r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
2373 if (UNLIKELY(exceptionValue != 0))
2376 codeBlock = newCodeBlock;
2377 setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
2378 k = codeBlock->registers.data();
2379 vPC = codeBlock->instructions.begin();
2381 #if DUMP_OPCODE_STATS
2382 OpcodeStats::resetLastInstruction();
2388 if (callType == CallTypeHost) {
2389 if (*enabledProfilerReference)
2390 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2392 JSValue* thisValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
2393 ArgList args(r + firstArg + 1, argCount - 1);
2395 MACHINE_SAMPLING_callingHostFunction();
2397 JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(v), thisValue, args);
2398 VM_CHECK_EXCEPTION();
2400 r[dst] = returnValue;
2402 if (*enabledProfilerReference)
2403 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
2409 ASSERT(callType == CallTypeNone);
2411 exceptionValue = createNotAFunctionError(exec, v, vPC, codeBlock);
2414 BEGIN_OPCODE(op_ret) {
2417 Return register result as the return value of the current
2418 function call, writing it into the caller's expected return
2419 value register. In addition, unwind one call frame and
2420 restore the scope chain, code block instruction pointer and
2421 register base to those of the calling function.
2424 int result = (++vPC)->u.operand;
2426 Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2427 if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
2428 ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
2429 ASSERT(activation->isActivationObject());
2430 activation->copyRegisters();
2433 if (*enabledProfilerReference)
2434 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
2436 if (codeBlock->needsFullScopeChain)
2437 scopeChain->deref();
2439 JSValue* returnValue = r[result].jsValue(exec);
2440 if (callFrame[RegisterFile::CalledAsConstructor].i() && !returnValue->isObject()) {
2441 JSValue* thisObject = callFrame[RegisterFile::CallFrameHeaderSize].jsValue(exec);
2442 returnValue = thisObject;
2445 codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
2449 k = codeBlock->registers.data();
2450 vPC = callFrame[RegisterFile::ReturnVPC].vPC();
2451 setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].scopeChain());
2452 r = callFrame[RegisterFile::CallerRegisters].r();
2453 exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2454 int dst = callFrame[RegisterFile::ReturnValueRegister].i();
2455 r[dst] = returnValue;
2459 BEGIN_OPCODE(op_construct) {
2460 /* construct dst(r) constr(r) firstArg(r) argCount(n)
2462 Invoke register "constr" as a constructor. For JS
2463 functions, the calling convention is exactly as for the
2464 "call" opcode, except that the "this" value is a newly
2465 created Object. For native constructors, a null "this"
2466 value is passed. In either case, the firstArg and argCount
2467 registers are interpreted as for the "call" opcode.
2470 int dst = (++vPC)->u.operand;
2471 int constr = (++vPC)->u.operand;
2472 int firstArg = (++vPC)->u.operand;
2473 int argCount = (++vPC)->u.operand;
2475 JSValue* constrVal = r[constr].jsValue(exec);
2477 ConstructData constructData;
2478 ConstructType constructType = constrVal->getConstructData(constructData);
2480 // Removing this line of code causes a measurable regression on squirrelfish.
2481 JSObject* constructor = static_cast<JSObject*>(constrVal);
2483 if (constructType == ConstructTypeJS) {
2484 if (*enabledProfilerReference)
2485 (*enabledProfilerReference)->willExecute(exec, constructor);
2487 JSObject* prototype;
2488 JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
2490 prototype = static_cast<JSObject*>(p);
2492 prototype = scopeChain->globalObject()->objectPrototype();
2493 JSObject* newObject = new (exec) JSObject(prototype);
2495 ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
2496 FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
2497 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
2499 r[firstArg] = newObject; // "this" value
2501 Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
2502 initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 1, constructor);
2503 exec->m_callFrame = callFrame;
2505 r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
2509 codeBlock = newCodeBlock;
2510 setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
2511 k = codeBlock->registers.data();
2512 vPC = codeBlock->instructions.begin();
2517 if (constructType == ConstructTypeHost) {
2518 if (*enabledProfilerReference)
2519 (*enabledProfilerReference)->willExecute(exec, constructor);
2521 ArgList args(r + firstArg + 1, argCount - 1);
2523 MACHINE_SAMPLING_callingHostFunction();
2525 JSValue* returnValue = constructData.native.function(exec, constructor, args);
2527 VM_CHECK_EXCEPTION();
2528 r[dst] = returnValue;
2530 if (*enabledProfilerReference)
2531 (*enabledProfilerReference)->didExecute(exec, constructor);
2537 ASSERT(constructType == ConstructTypeNone);
2539 exceptionValue = createNotAConstructorError(exec, constrVal, vPC, codeBlock);
2542 BEGIN_OPCODE(op_push_scope) {
2543 /* push_scope scope(r)
2545 Converts register scope to object, and pushes it onto the top
2546 of the current scope chain.
2548 int scope = (++vPC)->u.operand;
2549 JSValue* v = r[scope].jsValue(exec);
2550 JSObject* o = v->toObject(exec);
2551 VM_CHECK_EXCEPTION();
2553 setScopeChain(exec, scopeChain, scopeChain->push(o));
2558 BEGIN_OPCODE(op_pop_scope) {
2561 Removes the top item from the current scope chain.
2563 setScopeChain(exec, scopeChain, scopeChain->pop());
2568 BEGIN_OPCODE(op_get_pnames) {
2569 /* get_pnames dst(r) base(r)
2571 Creates a property name list for register base and puts it
2572 in register dst. This is not a true JavaScript value, just
2573 a synthetic value used to keep the iteration state in a
2576 int dst = (++vPC)->u.operand;
2577 int base = (++vPC)->u.operand;
2579 r[dst] = JSPropertyNameIterator::create(exec, r[base].jsValue(exec));
2583 BEGIN_OPCODE(op_next_pname) {
2584 /* next_pname dst(r) iter(r) target(offset)
2586 Tries to copies the next name from property name list in
2587 register iter. If there are names left, then copies one to
2588 register dst, and jumps to offset target. If there are none
2589 left, invalidates the iterator and continues to the next
2592 int dst = (++vPC)->u.operand;
2593 int iter = (++vPC)->u.operand;
2594 int target = (++vPC)->u.operand;
2596 JSPropertyNameIterator* it = r[iter].jsPropertyNameIterator();
2597 if (JSValue* temp = it->next(exec)) {
2598 CHECK_FOR_TIMEOUT();
2608 BEGIN_OPCODE(op_jmp_scopes) {
2609 /* jmp_scopes count(n) target(offset)
2611 Removes the a number of items from the current scope chain
2612 specified by immediate number count, then jumps to offset
2615 int count = (++vPC)->u.operand;
2616 int target = (++vPC)->u.operand;
2618 ScopeChainNode* tmp = scopeChain;
2621 setScopeChain(exec, scopeChain, tmp);
2626 #if HAVE(COMPUTED_GOTO)
2628 goto *(&&skip_new_scope);
2630 BEGIN_OPCODE(op_push_new_scope) {
2631 /* new_scope dst(r) property(id) value(r)
2633 Constructs a new StaticScopeObject with property set to value. That scope
2634 object is then pushed onto the ScopeChain. The scope object is then stored
2637 setScopeChain(exec, scopeChain, createExceptionScope(exec, codeBlock, vPC, r, scopeChain));
2641 #if HAVE(COMPUTED_GOTO)
2644 BEGIN_OPCODE(op_catch) {
2647 Retrieves the VMs current exception and puts it in register
2648 ex. This is only valid after an exception has been raised,
2649 and usually forms the beginning of an exception handler.
2651 ASSERT(exceptionValue);
2652 ASSERT(!exec->hadException());
2653 int ex = (++vPC)->u.operand;
2654 r[ex] = exceptionValue;
2660 BEGIN_OPCODE(op_throw) {
2663 Throws register ex as an exception. This involves three
2664 steps: first, it is set as the current exception in the
2665 VM's internal state, then the stack is unwound until an
2666 exception handler or a native code boundary is found, and
2667 then control resumes at the exception handler if any or
2668 else the script returns control to the nearest native caller.
2671 int ex = (++vPC)->u.operand;
2672 exceptionValue = r[ex].jsValue(exec);
2674 handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, k, scopeChain, r, true);
2676 *exception = exceptionValue;
2680 #if HAVE(COMPUTED_GOTO)
2681 // Hack around gcc performance quirk by performing an indirect goto
2682 // in order to set the vPC -- attempting to do so directly results in a
2683 // significant regression.
2684 goto *op_throw_end_indirect; // indirect goto -> op_throw_end
2692 BEGIN_OPCODE(op_new_error) {
2693 /* new_error dst(r) type(n) message(k)
2695 Constructs a new Error instance using the original
2696 constructor, using immediate number n as the type and
2697 constant message as the message string. The result is
2698 written to register dst.
2700 int dst = (++vPC)->u.operand;
2701 int type = (++vPC)->u.operand;
2702 int message = (++vPC)->u.operand;
2704 r[dst] = Error::create(exec, (ErrorType)type, k[message].jsValue(exec)->toString(exec), codeBlock->lineNumberForVPC(vPC), codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
2709 BEGIN_OPCODE(op_end) {
2712 Return register result as the value of a global or eval
2713 program. Return control to the calling native code.
2716 if (codeBlock->needsFullScopeChain) {
2717 ASSERT(scopeChain->refCount > 1);
2718 scopeChain->deref();
2720 int result = (++vPC)->u.operand;
2721 return r[result].jsValue(exec);
2723 BEGIN_OPCODE(op_put_getter) {
2724 /* put_getter base(r) property(id) function(r)
2726 Sets register function on register base as the getter named
2727 by identifier property. Base and function are assumed to be
2728 objects as this op should only be used for getters defined
2729 in object literal form.
2731 Unlike many opcodes, this one does not write any output to
2734 int base = (++vPC)->u.operand;
2735 int property = (++vPC)->u.operand;
2736 int function = (++vPC)->u.operand;
2738 ASSERT(r[base].jsValue(exec)->isObject());
2739 JSObject* baseObj = static_cast<JSObject*>(r[base].jsValue(exec));
2740 Identifier& ident = codeBlock->identifiers[property];
2741 ASSERT(r[function].jsValue(exec)->isObject());
2742 baseObj->defineGetter(exec, ident, static_cast<JSObject*>(r[function].jsValue(exec)));
2747 BEGIN_OPCODE(op_put_setter) {
2748 /* put_setter base(r) property(id) function(r)
2750 Sets register function on register base as the setter named
2751 by identifier property. Base and function are assumed to be
2752 objects as this op should only be used for setters defined
2753 in object literal form.
2755 Unlike many opcodes, this one does not write any output to
2758 int base = (++vPC)->u.operand;
2759 int property = (++vPC)->u.operand;
2760 int function = (++vPC)->u.operand;
2762 ASSERT(r[base].jsValue(exec)->isObject());
2763 JSObject* baseObj = static_cast<JSObject*>(r[base].jsValue(exec));
2764 Identifier& ident = codeBlock->identifiers[property];
2765 ASSERT(r[function].jsValue(exec)->isObject());
2766 baseObj->defineSetter(exec, ident, static_cast<JSObject*>(r[function].jsValue(exec)));
2771 BEGIN_OPCODE(op_jsr) {
2772 /* jsr retAddrDst(r) target(offset)
2774 Places the address of the next instruction into the retAddrDst
2775 register and jumps to offset target from the current instruction.
2777 int retAddrDst = (++vPC)->u.operand;
2778 int target = (++vPC)->u.operand;
2779 r[retAddrDst] = vPC + 1;
2784 BEGIN_OPCODE(op_sret) {
2785 /* sret retAddrSrc(r)
2787 Jumps to the address stored in the retAddrSrc register. This
2788 differs from op_jmp because the target address is stored in a
2789 register, not as an immediate.
2791 int retAddrSrc = (++vPC)->u.operand;
2792 vPC = r[retAddrSrc].vPC();
2795 BEGIN_OPCODE(op_debug) {
2796 /* debug debugHookID(n) firstLine(n) lastLine(n)
2798 Notifies the debugger of the current state of execution. This opcode
2799 is only generated while the debugger is attached.
2802 debug(exec, vPC, codeBlock, scopeChain, r);
2808 exec->clearException();
2810 // The exceptionValue is a lie! (GCC produces bad code for reasons I
2811 // cannot fathom if we don't assign to the exceptionValue before branching)
2812 exceptionValue = createInterruptedExecutionException(exec);
2814 handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, k, scopeChain, r, false);
2816 *exception = exceptionValue;
2825 #undef VM_CHECK_EXCEPTION
2828 JSValue* Machine::retrieveArguments(ExecState* exec, JSFunction* function) const
2830 Register* callFrame = this->callFrame(exec, function);
2834 JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec));
2836 CodeBlock* codeBlock = &function->m_body->generatedByteCode();
2837 activation = new (exec) JSActivation(function->m_body, callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numLocals);
2838 callFrame[RegisterFile::OptionalCalleeActivation] = activation;
2841 return activation->get(exec, exec->propertyNames().arguments);
2844 JSValue* Machine::retrieveCaller(ExecState* exec, JSFunction* function) const
2846 Register* callFrame = this->callFrame(exec, function);
2850 CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
2851 if (!callerCodeBlock)
2854 Register* callerCallFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2855 if (JSValue* caller = callerCallFrame[RegisterFile::Callee].jsValue(exec))
2861 Register* Machine::callFrame(ExecState* exec, JSFunction* function) const
2863 Register* callFrame = exec->m_callFrame;
2866 while (!callFrame) {
2867 exec = exec->m_prev;
2870 callFrame = exec->m_callFrame;
2873 if (callFrame[RegisterFile::Callee].jsValue(exec) == function)
2876 CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
2877 if (!callerCodeBlock) {
2882 callFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2886 void Machine::getArgumentsData(Register* callFrame, JSFunction*& function, Register*& argv, int& argc)
2888 function = static_cast<JSFunction*>(callFrame[RegisterFile::Callee].getJSValue());
2889 ASSERT(function->inherits(&JSFunction::info));
2891 argv = callFrame[RegisterFile::CallerRegisters].r() + callFrame[RegisterFile::ArgumentStartRegister].i() + 1; // + 1 to skip "this"
2892 argc = callFrame[RegisterFile::ArgumentCount].i() - 1; // - 1 to skip "this"