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 "JSActivation.h"
39 #include "JSPropertyNameIterator.h"
43 #include "ArrayPrototype.h"
45 #include "JSFunction.h"
47 #include "object_object.h"
48 #include "operations.h"
49 #include "operations.h"
50 #include "RegExpObject.h"
54 #if HAVE(COMPUTED_GOTO)
55 static void* op_throw_end_indirect;
56 static void* op_call_indirect;
59 // Retrieves the offset of a calling function within the current register file.
60 bool getCallerFunctionOffset(Register** registerBase, int callOffset, int& callerOffset)
62 Register* callFrame = (*registerBase) + callOffset;
64 CodeBlock* callerCodeBlock = callFrame[Machine::CallerCodeBlock].u.codeBlock;
65 if (!callerCodeBlock) // test for top frame of re-entrant function call
68 if (callerCodeBlock->codeType == EvalCode)
71 callerOffset = callFrame[Machine::CallerRegisterOffset].u.i - callerCodeBlock->numLocals - Machine::CallFrameHeaderSize;
72 if (callerOffset < 0) // test for global frame
78 // Returns the depth of the scope chain within a given call frame.
79 static int depth(ScopeChain& sc)
82 ScopeChainIterator iter = sc.begin();
83 ScopeChainIterator end = sc.end();
84 while (!(*iter)->isVariableObject()) {
91 static inline bool jsLess(ExecState* exec, JSValue* v1, JSValue* v2)
93 if (JSImmediate::areBothImmediateNumbers(v1, v2))
94 return JSImmediate::getTruncatedInt32(v1) < JSImmediate::getTruncatedInt32(v2);
100 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
101 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
103 if (wasNotString1 | wasNotString2)
106 return static_cast<const JSString*>(p1)->value() < static_cast<const JSString*>(p2)->value();
109 static inline bool jsLessEq(ExecState* exec, JSValue* v1, JSValue* v2)
115 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
116 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
118 if (wasNotString1 | wasNotString2)
121 return !(static_cast<const JSString*>(p2)->value() < static_cast<const JSString*>(p1)->value());
124 static JSValue* jsAddSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
126 // exception for the Date exception in defaultValue()
127 JSValue* p1 = v1->toPrimitive(exec, UnspecifiedType);
128 JSValue* p2 = v2->toPrimitive(exec, UnspecifiedType);
130 if (p1->isString() || p2->isString()) {
131 UString value = p1->toString(exec) + p2->toString(exec);
133 return throwOutOfMemoryError(exec);
134 return jsString(exec, value);
137 return jsNumber(exec, p1->toNumber(exec) + p2->toNumber(exec));
140 // Fast-path choices here are based on frequency data from SunSpider:
141 // <times> Add case: <t1> <t2>
142 // ---------------------------
143 // 5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
144 // 247412 Add case: 5 5
145 // 20900 Add case: 5 6
146 // 13962 Add case: 5 3
147 // 4000 Add case: 3 5
149 static inline JSValue* jsAdd(ExecState* exec, JSValue* v1, JSValue* v2)
151 JSType t1 = v1->type();
152 JSType t2 = v2->type();
153 const unsigned bothTypes = (t1 << 3) | t2;
155 if (bothTypes == ((NumberType << 3) | NumberType))
156 return jsNumber(exec, v1->uncheckedGetNumber() + v2->uncheckedGetNumber());
157 if (bothTypes == ((StringType << 3) | StringType)) {
158 UString value = static_cast<JSString*>(v1)->value() + static_cast<JSString*>(v2)->value();
160 return throwOutOfMemoryError(exec);
161 return jsString(exec, value);
164 // All other cases are pretty uncommon
165 return jsAddSlowCase(exec, v1, v2);
168 static JSValue* jsTypeStringForValue(ExecState* exec, JSValue* v)
172 return jsString(exec, "undefined");
174 return jsString(exec, "object");
176 return jsString(exec, "boolean");
178 return jsString(exec, "number");
180 return jsString(exec, "string");
183 // Return "undefined" for objects that should be treated
184 // as null when doing comparisons.
185 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
186 return jsString(exec, "undefined");
188 if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
189 return jsString(exec, "function");
192 return jsString(exec, "object");
196 static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
198 int dst = (vPC + 1)->u.operand;
199 int property = (vPC + 2)->u.operand;
201 ScopeChainIterator iter = scopeChain->begin();
202 ScopeChainIterator end = scopeChain->end();
205 Identifier& ident = codeBlock->identifiers[property];
208 PropertySlot slot(o);
209 if (o->getPropertySlot(exec, ident, slot)) {
210 JSValue* result = slot.getValue(exec, ident);
211 exceptionValue = exec->exception();
214 r[dst].u.jsValue = result;
217 } while (++iter != end);
218 exceptionValue = createUndefinedVariableError(exec, ident);
222 static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
224 int dst = (vPC + 1)->u.operand;
225 int property = (vPC + 2)->u.operand;
226 int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain;
228 ScopeChainIterator iter = scopeChain->begin();
229 ScopeChainIterator end = scopeChain->end();
235 Identifier& ident = codeBlock->identifiers[property];
238 PropertySlot slot(o);
239 if (o->getPropertySlot(exec, ident, slot)) {
240 JSValue* result = slot.getValue(exec, ident);
241 exceptionValue = exec->exception();
244 r[dst].u.jsValue = result;
247 } while (++iter != end);
248 exceptionValue = createUndefinedVariableError(exec, ident);
252 static void NEVER_INLINE resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
254 int dst = (vPC + 1)->u.operand;
255 int property = (vPC + 2)->u.operand;
257 ScopeChainIterator iter = scopeChain->begin();
258 ScopeChainIterator next = iter;
260 ScopeChainIterator end = scopeChain->end();
264 Identifier& ident = codeBlock->identifiers[property];
268 if (next == end || base->getPropertySlot(exec, ident, slot)) {
269 r[dst].u.jsValue = base;
277 static bool NEVER_INLINE resolveBaseAndProperty(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
279 int baseDst = (vPC + 1)->u.operand;
280 int propDst = (vPC + 2)->u.operand;
281 int property = (vPC + 3)->u.operand;
283 ScopeChainIterator iter = scopeChain->begin();
284 ScopeChainIterator end = scopeChain->end();
286 // FIXME: add scopeDepthIsZero optimization
290 Identifier& ident = codeBlock->identifiers[property];
294 PropertySlot slot(base);
295 if (base->getPropertySlot(exec, ident, slot)) {
296 JSValue* result = slot.getValue(exec, ident);
297 exceptionValue = exec->exception();
300 r[propDst].u.jsValue = result;
301 r[baseDst].u.jsValue = base;
305 } while (iter != end);
307 exceptionValue = createUndefinedVariableError(exec, ident);
311 static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
313 int baseDst = (vPC + 1)->u.operand;
314 int funcDst = (vPC + 2)->u.operand;
315 int property = (vPC + 3)->u.operand;
317 ScopeChainIterator iter = scopeChain->begin();
318 ScopeChainIterator end = scopeChain->end();
320 // FIXME: add scopeDepthIsZero optimization
324 Identifier& ident = codeBlock->identifiers[property];
328 PropertySlot slot(base);
329 if (base->getPropertySlot(exec, ident, slot)) {
330 // ECMA 11.2.3 says that if we hit an activation the this value should be null.
331 // However, section 10.2.3 says that in the case where the value provided
332 // by the caller is null, the global object should be used. It also says
333 // that the section does not apply to internal functions, but for simplicity
334 // of implementation we use the global object anyway here. This guarantees
335 // that in host objects you always get a valid object for this.
336 // We also handle wrapper substitution for the global object at the same time.
337 JSObject* thisObj = base->toThisObject(exec);
338 JSValue* result = slot.getValue(exec, ident);
339 exceptionValue = exec->exception();
343 r[baseDst].u.jsValue = thisObj;
344 r[funcDst].u.jsValue = result;
348 } while (iter != end);
350 exceptionValue = createUndefinedVariableError(exec, ident);
354 ALWAYS_INLINE void initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, int registerOffset, int returnValueRegister, int argv, int argc, int calledAsConstructor, JSValue* function)
356 callFrame[Machine::CallerCodeBlock].u.codeBlock = codeBlock;
357 callFrame[Machine::ReturnVPC].u.vPC = vPC + 1;
358 callFrame[Machine::CallerScopeChain].u.scopeChain = scopeChain;
359 callFrame[Machine::CallerRegisterOffset].u.i = registerOffset;
360 callFrame[Machine::ReturnValueRegister].u.i = returnValueRegister;
361 callFrame[Machine::ArgumentStartRegister].u.i = argv; // original argument vector (for the sake of the "arguments" object)
362 callFrame[Machine::ArgumentCount].u.i = argc; // original argument count (for the sake of the "arguments" object)
363 callFrame[Machine::CalledAsConstructor].u.i = calledAsConstructor;
364 callFrame[Machine::Callee].u.jsValue = function;
365 callFrame[Machine::OptionalCalleeActivation].u.jsValue = 0;
368 ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register** registerBase, int registerOffset, int argv, int argc, JSValue*& exceptionValue)
371 int oldOffset = registerOffset;
372 registerOffset += argv + newCodeBlock->numLocals;
373 size_t size = registerOffset + newCodeBlock->numTemporaries;
375 if (argc == newCodeBlock->numParameters) { // correct number of arguments
376 if (!registerFile->grow(size)) {
377 exceptionValue = createStackOverflowError(exec);
378 return *registerBase + oldOffset;
380 r = (*registerBase) + registerOffset;
381 } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks
382 if (!registerFile->grow(size)) {
383 exceptionValue = createStackOverflowError(exec);
384 return *registerBase + oldOffset;
386 r = (*registerBase) + registerOffset;
388 int omittedArgCount = newCodeBlock->numParameters - argc;
389 Register* endOfParams = r - newCodeBlock->numVars;
390 for (Register* it = endOfParams - omittedArgCount; it != endOfParams; ++it)
391 (*it).u.jsValue = jsUndefined();
392 } else { // too many arguments -- copy return info and expected arguments, leaving the extra arguments behind
393 int shift = argc + Machine::CallFrameHeaderSize;
394 registerOffset += shift;
397 if (!registerFile->grow(size)) {
398 exceptionValue = createStackOverflowError(exec);
399 return *registerBase + oldOffset;
401 r = (*registerBase) + registerOffset;
403 Register* it = r - newCodeBlock->numLocals - Machine::CallFrameHeaderSize - shift;
404 Register* end = it + Machine::CallFrameHeaderSize + newCodeBlock->numParameters;
405 for ( ; it != end; ++it)
409 // initialize local variable slots
410 for (Register* it = r - newCodeBlock->numVars; it != r; ++it)
411 (*it).u.jsValue = jsUndefined();
416 ALWAYS_INLINE ScopeChainNode* scopeChainForCall(ExecState* exec, FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register** registerBase, Register* r)
418 if (newCodeBlock->needsFullScopeChain) {
419 JSActivation* activation = new (exec) JSActivation(functionBodyNode, registerBase, r - (*registerBase));
420 r[Machine::OptionalCalleeActivation - Machine::CallFrameHeaderSize - newCodeBlock->numLocals].u.jsValue = activation;
422 return callDataScopeChain->copy()->push(activation);
425 return callDataScopeChain;
428 static NEVER_INLINE bool isNotObject(ExecState* exec, bool forInstanceOf, CodeBlock*, JSValue* value, JSValue*& exceptionData)
430 if (value->isObject())
432 exceptionData = createInvalidParamError(exec, forInstanceOf ? "instanceof" : "in" , value);
436 static NEVER_INLINE JSValue* callEval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
439 return jsUndefined();
441 JSValue* program = r[argv + 1].u.jsValue;
443 if (!program->isString())
446 Profiler** profiler = Profiler::enabledProfilerReference();
448 (*profiler)->willExecute(exec, scopeChain->globalObject()->evalFunction());
453 RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(static_cast<JSString*>(program)->value()), &sourceId, &errLine, &errMsg);
456 exceptionValue = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
458 (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
462 JSValue* result = exec->machine()->execute(evalNode.get(), exec, thisObj, registerFile, r - (*registerFile->basePointer()) + argv + argc, scopeChain, &exceptionValue);
465 (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
473 privateExecute(InitializeAndReturn);
476 void Machine::dumpCallFrame(const CodeBlock* codeBlock, ScopeChainNode* scopeChain, RegisterFile* registerFile, const Register* r)
478 ScopeChain sc(scopeChain);
479 JSGlobalObject* globalObject = sc.globalObject();
480 codeBlock->dump(globalObject->globalExec());
481 dumpRegisters(codeBlock, registerFile, r);
484 void Machine::dumpRegisters(const CodeBlock* codeBlock, RegisterFile* registerFile, const Register* r)
486 printf("Register frame: \n\n");
487 printf("----------------------------------------\n");
488 printf(" use | address | value \n");
489 printf("----------------------------------------\n");
494 if (isGlobalCallFrame(registerFile->basePointer(), r)) {
495 it = r - registerFile->numGlobalSlots();
499 printf("[global var] | %10p | %10p \n", it, (*it).u.jsValue);
502 printf("----------------------------------------\n");
505 it = r - codeBlock->numLocals - CallFrameHeaderSize;
506 end = it + CallFrameHeaderSize;
509 printf("[call frame] | %10p | %10p \n", it, (*it).u.jsValue);
512 printf("----------------------------------------\n");
515 end = it + codeBlock->numParameters;
518 printf("[param] | %10p | %10p \n", it, (*it).u.jsValue);
521 printf("----------------------------------------\n");
524 end = it + codeBlock->numVars;
527 printf("[var] | %10p | %10p \n", it, (*it).u.jsValue);
530 printf("----------------------------------------\n");
534 end = it + codeBlock->numTemporaries;
537 printf("[temp] | %10p | %10p \n", it, (*it).u.jsValue);
543 bool Machine::isOpcode(Opcode opcode)
545 #if HAVE(COMPUTED_GOTO)
546 return opcode != HashTraits<Opcode>::emptyValue()
547 && !HashTraits<Opcode>::isDeletedValue(opcode)
548 && m_opcodeIDTable.contains(opcode);
550 return opcode >= 0 && opcode <= op_end;
554 NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, Register** registerBase, const Instruction*& vPC, CodeBlock*& codeBlock, JSValue**& k, ScopeChainNode*& scopeChain, Register*& r)
556 CodeBlock* oldCodeBlock = codeBlock;
557 Register* callFrame = r - oldCodeBlock->numLocals - CallFrameHeaderSize;
559 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
560 DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, exceptionValue, registerBase, r - *registerBase);
561 if (!isGlobalCallFrame(registerBase, r) && callFrame[Callee].u.jsObject) // Check for global and eval code
562 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
564 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
567 if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
568 if (!isGlobalCallFrame(registerBase, r) && callFrame[Callee].u.jsObject) // Check for global and eval code
569 profiler->didExecute(exec, callFrame[Callee].u.jsObject);
571 profiler->didExecute(exec, codeBlock->ownerNode->sourceURL(), codeBlock->ownerNode->lineNo());
574 if (oldCodeBlock->needsFullScopeChain)
577 if (isGlobalCallFrame(registerBase, r))
580 // If this call frame created an activation, tear it off.
581 if (JSActivation* activation = static_cast<JSActivation*>(callFrame[OptionalCalleeActivation].u.jsValue)) {
582 ASSERT(activation->isActivationObject());
583 activation->copyRegisters();
586 codeBlock = callFrame[CallerCodeBlock].u.codeBlock;
590 k = codeBlock->jsValues.data();
591 scopeChain = callFrame[CallerScopeChain].u.scopeChain;
592 int callerRegisterOffset = callFrame[CallerRegisterOffset].u.i;
593 r = (*registerBase) + callerRegisterOffset;
594 exec->m_callFrameOffset = callerRegisterOffset - codeBlock->numLocals - CallFrameHeaderSize;
595 vPC = callFrame[ReturnVPC].u.vPC;
600 NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue* exceptionValue, Register** registerBase, const Instruction* vPC, CodeBlock*& codeBlock, JSValue**& k, ScopeChainNode*& scopeChain, Register*& r)
602 // Set up the exception object
604 if (exceptionValue->isObject()) {
605 JSObject* exception = static_cast<JSObject*>(exceptionValue);
606 if (!exception->hasProperty(exec, Identifier(exec, "line")) && !exception->hasProperty(exec, Identifier(exec, "sourceURL"))) {
607 exception->put(exec, Identifier(exec, "line"), jsNumber(exec, codeBlock->lineNumberForVPC(vPC)));
608 exception->put(exec, Identifier(exec, "sourceURL"), jsOwnedString(exec, codeBlock->ownerNode->sourceURL()));
612 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
613 DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, exceptionValue, registerBase, r - *registerBase);
614 debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->lineNumberForVPC(vPC));
617 // Calculate an exception handler vPC, unwinding call frames as necessary.
620 Instruction* handlerVPC;
622 while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) {
623 if (!unwindCallFrame(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r))
627 // Now unwind the scope chain within the exception handler's call frame.
629 ScopeChain sc(scopeChain);
630 int scopeDelta = depth(sc) - scopeDepth;
631 ASSERT(scopeDelta >= 0);
634 setScopeChain(exec, scopeChain, sc.node());
639 JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainNode* scopeChain, JSObject* thisObj, RegisterFileStack* registerFileStack, JSValue** exception)
641 if (m_reentryDepth >= MaxReentryDepth) {
642 *exception = createStackOverflowError(exec);
646 RegisterFile* registerFile = registerFileStack->pushGlobalRegisterFile();
647 ASSERT(registerFile->numGlobalSlots());
648 CodeBlock* codeBlock = &programNode->code(scopeChain, !registerFileStack->inImplicitCall());
649 registerFile->addGlobalSlots(codeBlock->numVars);
651 if (!registerFile->grow(codeBlock->numTemporaries)) {
652 registerFileStack->popGlobalRegisterFile();
653 *exception = createStackOverflowError(exec);
656 Register* r = (*registerFile->basePointer());
658 r[ProgramCodeThisRegister].u.jsValue = thisObj;
660 if (codeBlock->needsFullScopeChain)
661 scopeChain = scopeChain->copy();
663 ExecState newExec(exec, registerFile, scopeChain, -1);
665 Profiler** profiler = Profiler::enabledProfilerReference();
667 (*profiler)->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
670 JSValue* result = privateExecute(Normal, &newExec, registerFile, r, scopeChain, codeBlock, exception);
673 registerFileStack->popGlobalRegisterFile();
676 (*profiler)->didExecute(exec, programNode->sourceURL(), programNode->lineNo());
678 (*profiler)->didFinishAllExecution(exec);
684 JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, JSFunction* function, JSObject* thisObj, const ArgList& args, RegisterFileStack* registerFileStack, ScopeChainNode* scopeChain, JSValue** exception)
686 if (m_reentryDepth >= MaxReentryDepth) {
687 *exception = createStackOverflowError(exec);
691 RegisterFile* registerFile = registerFileStack->current();
693 int argv = CallFrameHeaderSize;
694 int argc = args.size() + 1; // implicit "this" parameter
696 size_t oldSize = registerFile->size();
697 if (!registerFile->grow(oldSize + CallFrameHeaderSize + argc)) {
698 *exception = createStackOverflowError(exec);
702 Register** registerBase = registerFile->basePointer();
703 int registerOffset = oldSize;
704 int callFrameOffset = registerOffset;
705 Register* callFrame = (*registerBase) + callFrameOffset;
707 // put args in place, including "this"
708 Register* dst = callFrame + CallFrameHeaderSize;
709 (*dst).u.jsValue = thisObj;
711 ArgList::const_iterator end = args.end();
712 for (ArgList::const_iterator it = args.begin(); it != end; ++it)
713 (*++dst).u.jsValue = *it;
715 // put call frame in place, using a 0 codeBlock to indicate a built-in caller
716 initializeCallFrame(callFrame, 0, 0, 0, registerOffset, 0, argv, argc, 0, function);
718 CodeBlock* newCodeBlock = &functionBodyNode->code(scopeChain);
719 Register* r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, argv, argc, *exception);
721 registerFile->shrink(oldSize);
725 scopeChain = scopeChainForCall(exec, functionBodyNode, newCodeBlock, scopeChain, registerBase, r);
727 ExecState newExec(exec, registerFile, scopeChain, callFrameOffset);
729 Profiler** profiler = Profiler::enabledProfilerReference();
731 (*profiler)->willExecute(exec, function);
734 JSValue* result = privateExecute(Normal, &newExec, registerFile, r, scopeChain, newCodeBlock, exception);
737 if (*profiler && !m_reentryDepth)
738 (*profiler)->didFinishAllExecution(exec);
740 registerFile->shrink(oldSize);
744 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, RegisterFile* registerFile, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
746 if (m_reentryDepth >= MaxReentryDepth) {
747 *exception = createStackOverflowError(exec);
751 EvalCodeBlock* codeBlock = &evalNode->code(scopeChain);
753 JSVariableObject* variableObject;
754 for (ScopeChainNode* node = scopeChain; ; node = node->next) {
756 if (node->object->isVariableObject()) {
757 variableObject = static_cast<JSVariableObject*>(node->object);
762 const Node::VarStack& varStack = codeBlock->ownerNode->varStack();
763 Node::VarStack::const_iterator varStackEnd = varStack.end();
764 for (Node::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
765 const Identifier& ident = (*it).first;
766 if (!variableObject->hasProperty(exec, ident))
767 variableObject->put(exec, ident, jsUndefined());
770 const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack();
771 Node::FunctionStack::const_iterator functionStackEnd = functionStack.end();
772 for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it)
773 variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain));
775 size_t oldSize = registerFile->size();
776 size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numTemporaries + CallFrameHeaderSize;
777 if (!registerFile->grow(newSize)) {
778 *exception = createStackOverflowError(exec);
782 Register* callFrame = *registerFile->basePointer() + registerOffset;
784 // put call frame in place, using a 0 codeBlock to indicate a built-in caller
785 initializeCallFrame(callFrame, 0, 0, 0, registerOffset, 0, 0, 0, 0, 0);
787 Register* r = callFrame + CallFrameHeaderSize + codeBlock->numVars;
788 r[ProgramCodeThisRegister].u.jsValue = thisObj;
790 if (codeBlock->needsFullScopeChain)
791 scopeChain = scopeChain->copy();
793 ExecState newExec(exec, registerFile, scopeChain, -1);
795 Profiler** profiler = Profiler::enabledProfilerReference();
797 (*profiler)->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
800 JSValue* result = privateExecute(Normal, &newExec, registerFile, r, scopeChain, codeBlock, exception);
803 registerFile->shrink(oldSize);
806 (*profiler)->didExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
808 (*profiler)->didFinishAllExecution(exec);
814 JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, RegisterFileStack* registerFileStack, ScopeChainNode* scopeChain, JSValue** exception)
816 RegisterFile* registerFile = registerFileStack->current();
817 if (registerFile->safeForReentry())
818 return Machine::execute(evalNode, exec, thisObj, registerFile, registerFile->size(), scopeChain, exception);
819 registerFile = registerFileStack->pushFunctionRegisterFile();
820 JSValue* result = Machine::execute(evalNode, exec, thisObj, registerFile, registerFile->size(), scopeChain, exception);
821 registerFileStack->popFunctionRegisterFile();
825 ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scopeChain, ScopeChainNode* newScopeChain)
827 scopeChain = newScopeChain;
828 exec->m_scopeChain = newScopeChain;
831 NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register** registerBase, Register* r)
833 int debugHookID = (++vPC)->u.operand;
834 int firstLine = (++vPC)->u.operand;
835 int lastLine = (++vPC)->u.operand;
837 Debugger* debugger = exec->dynamicGlobalObject()->debugger();
841 DebuggerCallFrame debuggerCallFrame(exec->dynamicGlobalObject(), codeBlock, scopeChain, 0, registerBase, r - *registerBase);
843 switch((DebugHookID)debugHookID) {
844 case DidEnterCallFrame: {
845 debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
848 case WillLeaveCallFrame: {
849 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
852 case WillExecuteStatement: {
853 debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
856 case WillExecuteProgram: {
857 debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
860 case DidExecuteProgram: {
861 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
864 case DidReachBreakpoint: {
865 debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
871 JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
873 // One-time initialization of our address tables. We have to put this code
874 // here because our labels are only in scope inside this function.
875 if (flag == InitializeAndReturn) {
876 #if HAVE(COMPUTED_GOTO)
877 #define ADD_OPCODE(id) m_opcodeTable[id] = &&id;
878 FOR_EACH_OPCODE_ID(ADD_OPCODE);
881 #define ADD_OPCODE_ID(id) m_opcodeIDTable.add(&&id, id);
882 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
884 ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
885 op_throw_end_indirect = &&op_throw_end;
886 op_call_indirect = &&op_call;
887 #endif // HAVE(COMPUTED_GOTO)
891 JSValue* exceptionValue = 0;
892 Instruction* handlerVPC = 0;
894 Register** registerBase = registerFile->basePointer();
895 Instruction* vPC = codeBlock->instructions.begin();
896 JSValue** k = codeBlock->jsValues.data();
897 Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
899 registerFile->setSafeForReentry(false);
900 #define VM_CHECK_EXCEPTION() \
902 if (UNLIKELY(exec->hadException())) { \
903 exceptionValue = exec->exception(); \
908 #if DUMP_OPCODE_STATS
909 OpcodeStats::resetLastInstruction();
912 #define CHECK_FOR_TIMEOUT()
914 #if HAVE(COMPUTED_GOTO)
915 #define NEXT_OPCODE goto *vPC->u.opcode
916 #if DUMP_OPCODE_STATS
917 #define BEGIN_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
919 #define BEGIN_OPCODE(opcode) opcode:
923 #define NEXT_OPCODE continue
924 #if DUMP_OPCODE_STATS
925 #define BEGIN_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
927 #define BEGIN_OPCODE(opcode) case opcode:
929 while (1) // iterator loop begins
930 switch (vPC->u.opcode)
933 BEGIN_OPCODE(op_load) {
934 /* load dst(r) src(k)
936 Copies constant src to register dst.
938 int dst = (++vPC)->u.operand;
939 int src = (++vPC)->u.operand;
940 r[dst].u.jsValue = k[src];
945 BEGIN_OPCODE(op_new_object) {
948 Constructs a new empty Object instance using the original
949 constructor, and puts the result in register dst.
951 int dst = (++vPC)->u.operand;
952 r[dst].u.jsValue = constructEmptyObject(exec);
957 BEGIN_OPCODE(op_new_array) {
960 Constructs a new empty Array instance using the original
961 constructor, and puts the result in register dst.
963 int dst = (++vPC)->u.operand;
964 r[dst].u.jsValue = constructEmptyArray(exec);
969 BEGIN_OPCODE(op_new_regexp) {
970 /* new_regexp dst(r) regExp(re)
972 Constructs a new RegExp instance using the original
973 constructor from regexp regExp, and puts the result in
976 int dst = (++vPC)->u.operand;
977 int regExp = (++vPC)->u.operand;
978 r[dst].u.jsValue = new (exec) RegExpObject(scopeChain->globalObject()->regExpPrototype(), codeBlock->regexps[regExp]);
983 BEGIN_OPCODE(op_mov) {
986 Copies register src to register dst.
988 int dst = (++vPC)->u.operand;
989 int src = (++vPC)->u.operand;
995 BEGIN_OPCODE(op_eq) {
996 /* eq dst(r) src1(r) src2(r)
998 Checks whether register src1 and register src2 are equal,
999 as with the ECMAScript '==' operator, and puts the result
1000 as a boolean in register dst.
1002 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1003 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1004 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1006 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1007 result = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1009 result = jsBoolean(equal(exec, src1, src2));
1010 VM_CHECK_EXCEPTION();
1017 BEGIN_OPCODE(op_neq) {
1018 /* neq dst(r) src1(r) src2(r)
1020 Checks whether register src1 and register src2 are not
1021 equal, as with the ECMAScript '!=' operator, and puts the
1022 result as a boolean in register dst.
1024 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1025 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1026 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1028 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1029 result = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1031 result = jsBoolean(!equal(exec, src1, src2));
1032 VM_CHECK_EXCEPTION();
1039 BEGIN_OPCODE(op_stricteq) {
1040 /* stricteq dst(r) src1(r) src2(r)
1042 Checks whether register src1 and register src2 are strictly
1043 equal, as with the ECMAScript '===' operator, and puts the
1044 result as a boolean in register dst.
1046 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1047 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1048 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1049 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1050 dst = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1052 dst = jsBoolean(strictEqual(src1, src2));
1057 BEGIN_OPCODE(op_nstricteq) {
1058 /* nstricteq dst(r) src1(r) src2(r)
1060 Checks whether register src1 and register src2 are not
1061 strictly equal, as with the ECMAScript '!==' operator, and
1062 puts the result as a boolean in register dst.
1064 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1065 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1066 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1067 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1068 dst = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1070 dst = jsBoolean(!strictEqual(src1, src2));
1075 BEGIN_OPCODE(op_less) {
1076 /* less dst(r) src1(r) src2(r)
1078 Checks whether register src1 is less than register src2, as
1079 with the ECMAScript '<' operator, and puts the result as
1080 a boolean in register dst.
1082 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1083 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1084 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1085 JSValue* result = jsBoolean(jsLess(exec, src1, src2));
1086 VM_CHECK_EXCEPTION();
1092 BEGIN_OPCODE(op_lesseq) {
1093 /* lesseq dst(r) src1(r) src2(r)
1095 Checks whether register src1 is less than or equal to
1096 register src2, as with the ECMAScript '<=' operator, and
1097 puts the result as a boolean in register dst.
1099 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1100 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1101 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1102 JSValue* result = jsBoolean(jsLessEq(exec, src1, src2));
1103 VM_CHECK_EXCEPTION();
1109 BEGIN_OPCODE(op_pre_inc) {
1110 /* pre_inc srcDst(r)
1112 Converts register srcDst to number, adds one, and puts the result
1113 back in register srcDst.
1115 int srcDst = (++vPC)->u.operand;
1116 JSValue* v = r[srcDst].u.jsValue;
1118 if (JSImmediate::canDoFastAdditiveOperations(v))
1119 result = JSImmediate::incImmediateNumber(v);
1121 result = jsNumber(exec, v->toNumber(exec) + 1);
1122 VM_CHECK_EXCEPTION();
1123 r[srcDst].u.jsValue = result;
1128 BEGIN_OPCODE(op_pre_dec) {
1129 /* pre_dec srcDst(r)
1131 Converts register srcDst to number, subtracts one, and puts the result
1132 back in register srcDst.
1134 int srcDst = (++vPC)->u.operand;
1135 JSValue* v = r[srcDst].u.jsValue;
1137 if (JSImmediate::canDoFastAdditiveOperations(v))
1138 result = JSImmediate::decImmediateNumber(v);
1140 result = jsNumber(exec, v->toNumber(exec) - 1);
1141 VM_CHECK_EXCEPTION();
1142 r[srcDst].u.jsValue = result;
1147 BEGIN_OPCODE(op_post_inc) {
1148 /* post_inc dst(r) srcDst(r)
1150 Converts register srcDst to number. The number itself is
1151 written to register dst, and the number plus one is written
1152 back to register srcDst.
1154 int dst = (++vPC)->u.operand;
1155 int srcDst = (++vPC)->u.operand;
1156 JSValue* v = r[srcDst].u.jsValue;
1159 if (JSImmediate::canDoFastAdditiveOperations(v)) {
1161 result = JSImmediate::incImmediateNumber(v);
1163 number = r[srcDst].u.jsValue->toJSNumber(exec);
1164 result = jsNumber(exec, number->uncheckedGetNumber() + 1);
1166 VM_CHECK_EXCEPTION();
1168 r[dst].u.jsValue = number;
1169 r[srcDst].u.jsValue = result;
1174 BEGIN_OPCODE(op_post_dec) {
1175 /* post_dec dst(r) srcDst(r)
1177 Converts register srcDst to number. The number itself is
1178 written to register dst, and the number minus one is written
1179 back to register srcDst.
1181 int dst = (++vPC)->u.operand;
1182 int srcDst = (++vPC)->u.operand;
1183 JSValue* v = r[srcDst].u.jsValue;
1186 if (JSImmediate::canDoFastAdditiveOperations(v)) {
1188 result = JSImmediate::decImmediateNumber(v);
1190 number = r[srcDst].u.jsValue->toJSNumber(exec);
1191 result = jsNumber(exec, number->uncheckedGetNumber() - 1);
1193 VM_CHECK_EXCEPTION();
1195 r[dst].u.jsValue = number;
1196 r[srcDst].u.jsValue = result;
1201 BEGIN_OPCODE(op_to_jsnumber) {
1202 /* to_jsnumber dst(r) src(r)
1204 Converts register src to number, and puts the result
1207 int dst = (++vPC)->u.operand;
1208 int src = (++vPC)->u.operand;
1209 JSValue* result = r[src].u.jsValue->toJSNumber(exec);
1210 VM_CHECK_EXCEPTION();
1212 r[dst].u.jsValue = result;
1217 BEGIN_OPCODE(op_negate) {
1218 /* negate dst(r) src(r)
1220 Converts register src to number, negates it, and puts the
1221 result in register dst.
1223 int dst = (++vPC)->u.operand;
1224 int src = (++vPC)->u.operand;
1225 JSValue* result = jsNumber(exec, -r[src].u.jsValue->toNumber(exec));
1226 VM_CHECK_EXCEPTION();
1227 r[dst].u.jsValue = result;
1232 BEGIN_OPCODE(op_add) {
1233 /* add dst(r) src1(r) src2(r)
1235 Adds register src1 and register src2, and puts the result
1236 in register dst. (JS add may be string concatenation or
1237 numeric add, depending on the types of the operands.)
1239 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1240 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1241 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1243 if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1244 result = JSImmediate::addImmediateNumbers(src1, src2);
1246 result = jsAdd(exec, src1, src2);
1247 VM_CHECK_EXCEPTION();
1253 BEGIN_OPCODE(op_mul) {
1254 /* mul dst(r) src1(r) src2(r)
1256 Multiplies register src1 and register src2 (converted to
1257 numbers), and puts the product in register dst.
1259 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1260 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1261 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1262 JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
1263 VM_CHECK_EXCEPTION();
1269 BEGIN_OPCODE(op_div) {
1270 /* div dst(r) dividend(r) divisor(r)
1272 Divides register dividend (converted to number) by the
1273 register divisor (converted to number), and puts the
1274 quotient in register dst.
1276 int dst = (++vPC)->u.operand;
1277 int dividend = (++vPC)->u.operand;
1278 int divisor = (++vPC)->u.operand;
1279 JSValue* result = jsNumber(exec, r[dividend].u.jsValue->toNumber(exec) / r[divisor].u.jsValue->toNumber(exec));
1280 VM_CHECK_EXCEPTION();
1281 r[dst].u.jsValue = result;
1285 BEGIN_OPCODE(op_mod) {
1286 /* mod dst(r) dividend(r) divisor(r)
1288 Divides register dividend (converted to number) by
1289 register divisor (converted to number), and puts the
1290 remainder in register dst.
1292 int dst = (++vPC)->u.operand;
1293 int dividend = (++vPC)->u.operand;
1294 int divisor = (++vPC)->u.operand;
1295 double d = r[dividend].u.jsValue->toNumber(exec);
1296 JSValue* result = jsNumber(exec, fmod(d, r[divisor].u.jsValue->toNumber(exec)));
1297 VM_CHECK_EXCEPTION();
1298 r[dst].u.jsValue = result;
1302 BEGIN_OPCODE(op_sub) {
1303 /* sub dst(r) src1(r) src2(r)
1305 Subtracts register src2 (converted to number) from register
1306 src1 (converted to number), and puts the difference in
1309 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1310 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1311 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1313 if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1314 result = JSImmediate::subImmediateNumbers(src1, src2);
1316 result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
1317 VM_CHECK_EXCEPTION();
1323 BEGIN_OPCODE(op_lshift) {
1324 /* lshift dst(r) val(r) shift(r)
1326 Performs left shift of register val (converted to int32) by
1327 register shift (converted to uint32), and puts the result
1330 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1331 JSValue* val = r[(++vPC)->u.operand].u.jsValue;
1332 JSValue* shift = r[(++vPC)->u.operand].u.jsValue;
1334 if (JSImmediate::areBothImmediateNumbers(val, shift))
1335 result = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::toTruncatedUInt32(shift) & 0x1f));
1337 result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
1338 VM_CHECK_EXCEPTION();
1345 BEGIN_OPCODE(op_rshift) {
1346 /* rshift dst(r) val(r) shift(r)
1348 Performs arithmetic right shift of register val (converted
1349 to int32) by register shift (converted to
1350 uint32), and puts the result in register dst.
1352 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1353 JSValue* val = r[(++vPC)->u.operand].u.jsValue;
1354 JSValue* shift = r[(++vPC)->u.operand].u.jsValue;
1356 if (JSImmediate::areBothImmediateNumbers(val, shift))
1357 result = JSImmediate::rightShiftImmediateNumbers(val, shift);
1359 result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1360 VM_CHECK_EXCEPTION();
1367 BEGIN_OPCODE(op_urshift) {
1368 /* rshift dst(r) val(r) shift(r)
1370 Performs logical right shift of register val (converted
1371 to uint32) by register shift (converted to
1372 uint32), and puts the result in register dst.
1374 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1375 JSValue* val = r[(++vPC)->u.operand].u.jsValue;
1376 JSValue* shift = r[(++vPC)->u.operand].u.jsValue;
1378 if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
1379 result = JSImmediate::rightShiftImmediateNumbers(val, shift);
1381 result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1382 VM_CHECK_EXCEPTION();
1389 BEGIN_OPCODE(op_bitand) {
1390 /* bitand dst(r) src1(r) src2(r)
1392 Computes bitwise AND of register src1 (converted to int32)
1393 and register src2 (converted to int32), and puts the result
1396 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1397 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1398 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1400 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1401 result = JSImmediate::andImmediateNumbers(src1, src2);
1403 result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
1404 VM_CHECK_EXCEPTION();
1411 BEGIN_OPCODE(op_bitxor) {
1412 /* bitxor dst(r) src1(r) src2(r)
1414 Computes bitwise XOR of register src1 (converted to int32)
1415 and register src2 (converted to int32), and puts the result
1418 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1419 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1420 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1422 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1423 result = JSImmediate::xorImmediateNumbers(src1, src2);
1425 result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
1426 VM_CHECK_EXCEPTION();
1433 BEGIN_OPCODE(op_bitor) {
1434 /* bitor dst(r) src1(r) src2(r)
1436 Computes bitwise OR of register src1 (converted to int32)
1437 and register src2 (converted to int32), and puts the
1438 result in register dst.
1440 JSValue*& dst = r[(++vPC)->u.operand].u.jsValue;
1441 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1442 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1444 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1445 result = JSImmediate::orImmediateNumbers(src1, src2);
1447 result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
1448 VM_CHECK_EXCEPTION();
1455 BEGIN_OPCODE(op_bitnot) {
1456 /* bitnot dst(r) src(r)
1458 Computes bitwise NOT of register src1 (converted to int32),
1459 and puts the result in register dst.
1461 int dst = (++vPC)->u.operand;
1462 int src = (++vPC)->u.operand;
1463 JSValue* result = jsNumber(exec, ~r[src].u.jsValue->toInt32(exec));
1464 VM_CHECK_EXCEPTION();
1465 r[dst].u.jsValue = result;
1470 BEGIN_OPCODE(op_not) {
1471 /* not dst(r) src1(r) src2(r)
1473 Computes logical NOT of register src1 (converted to
1474 boolean), and puts the result in register dst.
1476 int dst = (++vPC)->u.operand;
1477 int src = (++vPC)->u.operand;
1478 JSValue* result = jsBoolean(!r[src].u.jsValue->toBoolean(exec));
1479 VM_CHECK_EXCEPTION();
1480 r[dst].u.jsValue = result;
1485 BEGIN_OPCODE(op_instanceof) {
1486 /* instanceof dst(r) value(r) constructor(r)
1488 Tests whether register value is an instance of register
1489 constructor, and puts the boolean result in register dst.
1491 Raises an exception if register constructor is not an
1494 int dst = (++vPC)->u.operand;
1495 int value = (++vPC)->u.operand;
1496 int base = (++vPC)->u.operand;
1498 JSValue* baseVal = r[base].u.jsValue;
1500 if (isNotObject(exec, vPC, codeBlock, baseVal, exceptionValue))
1503 JSObject* baseObj = static_cast<JSObject*>(baseVal);
1504 r[dst].u.jsValue = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].u.jsValue) : false);
1509 BEGIN_OPCODE(op_typeof) {
1510 /* typeof dst(r) src(r)
1512 Determines the type string for src according to ECMAScript
1513 rules, and puts the result in register dst.
1515 int dst = (++vPC)->u.operand;
1516 int src = (++vPC)->u.operand;
1517 r[dst].u.jsValue = jsTypeStringForValue(exec, r[src].u.jsValue);
1522 BEGIN_OPCODE(op_in) {
1523 /* in dst(r) property(r) base(r)
1525 Tests whether register base has a property named register
1526 property, and puts the boolean result in register dst.
1528 Raises an exception if register constructor is not an
1531 int dst = (++vPC)->u.operand;
1532 int property = (++vPC)->u.operand;
1533 int base = (++vPC)->u.operand;
1535 JSValue* baseVal = r[base].u.jsValue;
1536 if (isNotObject(exec, vPC, codeBlock, baseVal, exceptionValue))
1539 JSObject* baseObj = static_cast<JSObject*>(baseVal);
1541 JSValue* propName = r[property].u.jsValue;
1544 if (propName->getUInt32(i))
1545 r[dst].u.jsValue = jsBoolean(baseObj->hasProperty(exec, i));
1547 Identifier property(exec, propName->toString(exec));
1548 VM_CHECK_EXCEPTION();
1549 r[dst].u.jsValue = jsBoolean(baseObj->hasProperty(exec, property));
1555 BEGIN_OPCODE(op_resolve) {
1556 /* resolve dst(r) property(id)
1558 Looks up the property named by identifier property in the
1559 scope chain, and writes the resulting value to register
1560 dst. If the property is not found, raises an exception.
1562 if (UNLIKELY(!resolve(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1568 BEGIN_OPCODE(op_resolve_skip) {
1569 /* resolve_skip dst(r) property(id) skip(n)
1571 Looks up the property named by identifier property in the
1572 scope chain skipping the top 'skip' levels, and writes the resulting
1573 value to register dst. If the property is not found, raises an exception.
1575 if (UNLIKELY(!resolve_skip(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1582 BEGIN_OPCODE(op_get_scoped_var) {
1583 /* get_scoped_var dst(r) index(n) skip(n)
1585 Loads the contents of the index-th local from the scope skip nodes from
1586 the top of the scope chain, and places it in register dst
1588 int dst = (++vPC)->u.operand;
1589 int index = (++vPC)->u.operand;
1590 int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1592 ScopeChainIterator iter = scopeChain->begin();
1593 ScopeChainIterator end = scopeChain->end();
1594 ASSERT(iter != end);
1597 ASSERT(iter != end);
1600 ASSERT((*iter)->isVariableObject());
1601 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1602 r[dst].u.jsValue = scope->valueAt(index);
1606 BEGIN_OPCODE(op_put_scoped_var) {
1607 /* put_scoped_var index(n) skip(n) value(r)
1610 int index = (++vPC)->u.operand;
1611 int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
1612 int value = (++vPC)->u.operand;
1614 ScopeChainIterator iter = scopeChain->begin();
1615 ScopeChainIterator end = scopeChain->end();
1616 ASSERT(iter != end);
1619 ASSERT(iter != end);
1622 ASSERT((*iter)->isVariableObject());
1623 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
1624 scope->valueAt(index) = r[value].u.jsValue;
1628 BEGIN_OPCODE(op_resolve_base) {
1629 /* resolve_base dst(r) property(id)
1631 Searches the scope chain for an object containing
1632 identifier property, and if one is found, writes it to
1633 register dst. If none is found, the outermost scope (which
1634 will be the global object) is stored in register dst.
1636 resolveBase(exec, vPC, r, scopeChain, codeBlock);
1641 BEGIN_OPCODE(op_resolve_with_base) {
1642 /* resolve_with_base baseDst(r) propDst(r) property(id)
1644 Searches the scope chain for an object containing
1645 identifier property, and if one is found, writes it to
1646 register srcDst, and the retrieved property value to register
1647 propDst. If the property is not found, raises an exception.
1649 This is more efficient than doing resolve_base followed by
1650 resolve, or resolve_base followed by get_by_id, as it
1651 avoids duplicate hash lookups.
1653 if (UNLIKELY(!resolveBaseAndProperty(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1659 BEGIN_OPCODE(op_resolve_func) {
1660 /* resolve_func baseDst(r) funcDst(r) property(id)
1662 Searches the scope chain for an object containing
1663 identifier property, and if one is found, writes the
1664 appropriate object to use as "this" when calling its
1665 properties to register baseDst; and the retrieved property
1666 value to register propDst. If the property is not found,
1667 raises an exception.
1669 This differs from resolve_with_base, because the
1670 global this value will be substituted for activations or
1671 the global object, which is the right behavior for function
1672 calls but not for other property lookup.
1674 if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
1680 BEGIN_OPCODE(op_get_by_id) {
1681 /* get_by_id dst(r) base(r) property(id)
1683 Converts register base to Object, gets the property
1684 named by identifier property from the object, and puts the
1685 result in register dst.
1687 int dst = (++vPC)->u.operand;
1688 int base = (++vPC)->u.operand;
1689 int property = (++vPC)->u.operand;
1691 int registerOffset = r - (*registerBase);
1694 Identifier& ident = codeBlock->identifiers[property];
1695 JSValue *result = r[base].u.jsValue->get(exec, ident);
1696 ASSERT(registerOffset == (r - (*registerBase)));
1697 VM_CHECK_EXCEPTION();
1698 r[dst].u.jsValue = result;
1702 BEGIN_OPCODE(op_put_by_id) {
1703 /* put_by_id base(r) property(id) value(r)
1705 Sets register value on register base as the property named
1706 by identifier property. Base is converted to object first.
1708 Unlike many opcodes, this one does not write any output to
1711 int base = (++vPC)->u.operand;
1712 int property = (++vPC)->u.operand;
1713 int value = (++vPC)->u.operand;
1715 int registerOffset = r - (*registerBase);
1718 Identifier& ident = codeBlock->identifiers[property];
1719 r[base].u.jsValue->put(exec, ident, r[value].u.jsValue);
1720 ASSERT(registerOffset == (r - (*registerBase)));
1722 VM_CHECK_EXCEPTION();
1726 BEGIN_OPCODE(op_del_by_id) {
1727 /* del_by_id dst(r) base(r) property(id)
1729 Converts register base to Object, deletes the property
1730 named by identifier property from the object, and writes a
1731 boolean indicating success (if true) or failure (if false)
1734 int dst = (++vPC)->u.operand;
1735 int base = (++vPC)->u.operand;
1736 int property = (++vPC)->u.operand;
1738 JSObject* baseObj = r[base].u.jsValue->toObject(exec);
1740 Identifier& ident = codeBlock->identifiers[property];
1741 JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
1742 VM_CHECK_EXCEPTION();
1743 r[dst].u.jsValue = result;
1747 BEGIN_OPCODE(op_get_by_val) {
1748 /* get_by_val dst(r) base(r) property(r)
1750 Converts register base to Object, gets the property named
1751 by register property from the object, and puts the result
1752 in register dst. property is nominally converted to string
1753 but numbers are treated more efficiently.
1755 int dst = (++vPC)->u.operand;
1756 int base = (++vPC)->u.operand;
1757 int property = (++vPC)->u.operand;
1759 JSValue* baseValue = r[base].u.jsValue;
1761 JSValue* subscript = r[property].u.jsValue;
1764 if (subscript->getUInt32(i))
1765 result = baseValue->get(exec, i);
1767 JSObject* baseObj = baseValue->toObject(exec); // may throw
1769 Identifier property;
1770 if (subscript->isObject()) {
1771 VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
1772 property = Identifier(exec, subscript->toString(exec));
1774 property = Identifier(exec, subscript->toString(exec));
1776 VM_CHECK_EXCEPTION(); // This check is needed to prevent us from incorrectly calling a getter after an exception is thrown
1777 result = baseObj->get(exec, property);
1780 VM_CHECK_EXCEPTION();
1781 r[dst].u.jsValue = result;
1785 BEGIN_OPCODE(op_put_by_val) {
1786 /* put_by_val base(r) property(r) value(r)
1788 Sets register value on register base as the property named
1789 by register property. Base is converted to object
1790 first. register property is nominally converted to string
1791 but numbers are treated more efficiently.
1793 Unlike many opcodes, this one does not write any output to
1796 int base = (++vPC)->u.operand;
1797 int property = (++vPC)->u.operand;
1798 int value = (++vPC)->u.operand;
1800 JSValue* baseValue = r[base].u.jsValue;
1802 JSValue* subscript = r[property].u.jsValue;
1805 if (subscript->getUInt32(i))
1806 baseValue->put(exec, i, r[value].u.jsValue);
1808 JSObject* baseObj = baseValue->toObject(exec);
1810 Identifier property;
1811 if (subscript->isObject()) {
1812 VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
1813 property = Identifier(exec, subscript->toString(exec));
1815 property = Identifier(exec, subscript->toString(exec));
1817 VM_CHECK_EXCEPTION(); // This check is needed to prevent us from incorrectly calling a setter after an exception is thrown
1818 baseObj->put(exec, property, r[value].u.jsValue);
1821 VM_CHECK_EXCEPTION();
1825 BEGIN_OPCODE(op_del_by_val) {
1826 /* del_by_val dst(r) base(r) property(r)
1828 Converts register base to Object, deletes the property
1829 named by register property from the object, and writes a
1830 boolean indicating success (if true) or failure (if false)
1833 int dst = (++vPC)->u.operand;
1834 int base = (++vPC)->u.operand;
1835 int property = (++vPC)->u.operand;
1837 JSObject* baseObj = r[base].u.jsValue->toObject(exec); // may throw
1839 JSValue* subscript = r[property].u.jsValue;
1842 if (subscript->getUInt32(i))
1843 result = jsBoolean(baseObj->deleteProperty(exec, i));
1845 VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
1846 Identifier property(exec, subscript->toString(exec));
1847 VM_CHECK_EXCEPTION();
1848 result = jsBoolean(baseObj->deleteProperty(exec, property));
1851 VM_CHECK_EXCEPTION();
1852 r[dst].u.jsValue = result;
1856 BEGIN_OPCODE(op_put_by_index) {
1857 /* put_by_index base(r) property(n) value(r)
1859 Sets register value on register base as the property named
1860 by the immediate number property. Base is converted to
1861 object first. register property is nominally converted to
1862 string but numbers are treated more efficiently.
1864 Unlike many opcodes, this one does not write any output to
1867 This opcode is mainly used to initialize array literals.
1869 int base = (++vPC)->u.operand;
1870 unsigned property = (++vPC)->u.operand;
1871 int value = (++vPC)->u.operand;
1873 r[base].u.jsObject->put(exec, property, r[value].u.jsValue);
1878 BEGIN_OPCODE(op_jmp) {
1879 /* jmp target(offset)
1881 Jumps unconditionally to offset target from the current
1884 #if DUMP_OPCODE_STATS
1885 OpcodeStats::resetLastInstruction();
1887 int target = (++vPC)->u.operand;
1892 BEGIN_OPCODE(op_loop_if_true) {
1893 /* loop_if_true cond(r) target(offset)
1895 Jumps to offset target from the current instruction, if and
1896 only if register cond converts to boolean as true.
1898 Additionally this loop instruction may terminate JS execution is
1899 the JS timeout is reached.
1901 int cond = (++vPC)->u.operand;
1902 int target = (++vPC)->u.operand;
1903 if (r[cond].u.jsValue->toBoolean(exec)) {
1905 CHECK_FOR_TIMEOUT();
1912 BEGIN_OPCODE(op_jtrue) {
1913 /* jtrue cond(r) target(offset)
1915 Jumps to offset target from the current instruction, if and
1916 only if register cond converts to boolean as true.
1918 int cond = (++vPC)->u.operand;
1919 int target = (++vPC)->u.operand;
1920 if (r[cond].u.jsValue->toBoolean(exec)) {
1928 BEGIN_OPCODE(op_jfalse) {
1929 /* jfalse cond(r) target(offset)
1931 Jumps to offset target from the current instruction, if and
1932 only if register cond converts to boolean as false.
1934 int cond = (++vPC)->u.operand;
1935 int target = (++vPC)->u.operand;
1936 if (!r[cond].u.jsValue->toBoolean(exec)) {
1944 BEGIN_OPCODE(op_loop_if_less) {
1945 /* loop_if_less src1(r) src2(r) target(offset)
1947 Checks whether register src1 is less than register src2, as
1948 with the ECMAScript '<' operator, and then jumps to offset
1949 target from the current instruction, if and only if the
1950 result of the comparison is true.
1952 Additionally this loop instruction may terminate JS execution is
1953 the JS timeout is reached.
1955 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1956 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1957 int target = (++vPC)->u.operand;
1959 bool result = jsLess(exec, src1, src2);
1960 VM_CHECK_EXCEPTION();
1964 CHECK_FOR_TIMEOUT();
1971 BEGIN_OPCODE(op_jless) {
1972 /* jless src1(r) src2(r) target(offset)
1974 Checks whether register src1 is less than register src2, as
1975 with the ECMAScript '<' operator, and then jumps to offset
1976 target from the current instruction, if and only if the
1977 result of the comparison is true.
1979 JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
1980 JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
1981 int target = (++vPC)->u.operand;
1983 bool result = jsLess(exec, src1, src2);
1984 VM_CHECK_EXCEPTION();
1994 BEGIN_OPCODE(op_new_func) {
1995 /* new_func dst(r) func(f)
1997 Constructs a new Function instance from function func and
1998 the current scope chain using the original Function
1999 constructor, using the rules for function declarations, and
2000 puts the result in register dst.
2002 int dst = (++vPC)->u.operand;
2003 int func = (++vPC)->u.operand;
2005 r[dst].u.jsValue = codeBlock->functions[func]->makeFunction(exec, scopeChain);
2010 BEGIN_OPCODE(op_new_func_exp) {
2011 /* new_func_exp dst(r) func(f)
2013 Constructs a new Function instance from function func and
2014 the current scope chain using the original Function
2015 constructor, using the rules for function expressions, and
2016 puts the result in register dst.
2018 int dst = (++vPC)->u.operand;
2019 int func = (++vPC)->u.operand;
2021 r[dst].u.jsValue = codeBlock->functionExpressions[func]->makeFunction(exec, scopeChain);
2026 BEGIN_OPCODE(op_call_eval) {
2027 /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2029 Call a function named "eval" with no explicit "this" value
2030 (which may therefore be the eval operator). If register
2031 thisVal is the global object, and register func contains
2032 that global object's original global eval function, then
2033 perform the eval operator in local scope (interpreting
2034 the argument registers as for the "call"
2035 opcode). Otherwise, act exacty as the "call" opcode.
2038 int dst = (++vPC)->u.operand;
2039 int func = (++vPC)->u.operand;
2040 int thisVal = (++vPC)->u.operand;
2041 int firstArg = (++vPC)->u.operand;
2042 int argCount = (++vPC)->u.operand;
2044 JSValue* funcVal = r[func].u.jsValue;
2045 JSValue* baseVal = r[thisVal].u.jsValue;
2047 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
2048 int registerOffset = r - (*registerBase);
2050 JSObject* thisObject = r[codeBlock->thisRegister].u.jsObject;
2052 registerFile->setSafeForReentry(true);
2054 JSValue* result = callEval(exec, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
2056 registerFile->setSafeForReentry(false);
2057 r = (*registerBase) + registerOffset;
2062 r[dst].u.jsValue = result;
2068 // We didn't find the blessed version of eval, so reset vPC and process
2069 // this instruction as a normal function call, supplying the proper 'this'
2072 r[thisVal].u.jsValue = baseVal->toThisObject(exec);
2074 #if HAVE(COMPUTED_GOTO)
2075 // Hack around gcc performance quirk by performing an indirect goto
2076 // in order to set the vPC -- attempting to do so directly results in a
2077 // significant regression.
2078 goto *op_call_indirect; // indirect goto -> op_call
2080 // fall through to op_call
2082 BEGIN_OPCODE(op_call) {
2083 /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2085 Perform a function call. Specifically, call register func
2086 with a "this" value of register thisVal, and put the result
2089 The arguments start at register firstArg and go up to
2090 argCount, but the "this" value is considered an implicit
2091 first argument, so the argCount should be one greater than
2092 the number of explicit arguments passed, and the register
2093 after firstArg should contain the actual first
2094 argument. This opcode will copy from the thisVal register
2095 to the firstArg register, unless the register index of
2096 thisVal is the special missing this object marker, which is
2097 2^31-1; in that case, the global object will be used as the
2100 If func is a native code function, then this opcode calls
2101 it and returns the value immediately.
2103 But if it is a JS function, then the current scope chain
2104 and code block is set to the function's, and we slide the
2105 register window so that the arguments would form the first
2106 few local registers of the called function's register
2107 window. In addition, a call frame header is written
2108 immediately before the arguments; see the call frame
2109 documentation for an explanation of how many registers a
2110 call frame takes and what they contain. That many registers
2111 before the firstArg register will be overwritten by the
2112 call. In addition, any registers higher than firstArg +
2113 argCount may be overwritten. Once this setup is complete,
2114 execution continues from the called function's first
2115 argument, and does not return until a "ret" opcode is
2119 int dst = (++vPC)->u.operand;
2120 int func = (++vPC)->u.operand;
2121 int thisVal = (++vPC)->u.operand;
2122 int firstArg = (++vPC)->u.operand;
2123 int argCount = (++vPC)->u.operand;
2125 JSValue* v = r[func].u.jsValue;
2128 CallType callType = v->getCallData(callData);
2130 if (callType == CallTypeJS) {
2131 if (*enabledProfilerReference)
2132 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2133 int registerOffset = r - (*registerBase);
2134 Register* callFrame = r + firstArg - CallFrameHeaderSize;
2135 int callFrameOffset = registerOffset + firstArg - CallFrameHeaderSize;
2137 r[firstArg].u.jsValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].u.jsValue;
2138 initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, registerOffset, dst, firstArg, argCount, 0, v);
2140 ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
2141 FunctionBodyNode* functionBodyNode = callData.js.functionBody;
2143 CodeBlock* newCodeBlock = &functionBodyNode->code(callDataScopeChain);
2144 r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, firstArg, argCount, exceptionValue);
2145 if (UNLIKELY(exceptionValue != 0))
2148 codeBlock = newCodeBlock;
2149 exec->m_callFrameOffset = callFrameOffset;
2150 setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, registerBase, r));
2151 k = codeBlock->jsValues.data();
2152 vPC = codeBlock->instructions.begin();
2154 #if DUMP_OPCODE_STATS
2155 OpcodeStats::resetLastInstruction();
2161 if (callType == CallTypeNative) {
2162 if (*enabledProfilerReference)
2163 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2164 int registerOffset = r - (*registerBase);
2166 r[firstArg].u.jsValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : (r[thisVal].u.jsValue)->toObject(exec);
2167 JSValue* thisValue = r[firstArg].u.jsValue;
2169 ArgList args(reinterpret_cast<JSValue***>(registerBase), registerOffset + firstArg + 1, argCount - 1);
2171 registerFile->setSafeForReentry(true);
2172 JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(v), thisValue, args);
2173 registerFile->setSafeForReentry(false);
2175 r = (*registerBase) + registerOffset;
2176 r[dst].u.jsValue = returnValue;
2178 if (*enabledProfilerReference)
2179 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
2180 VM_CHECK_EXCEPTION();
2186 ASSERT(callType == CallTypeNone);
2188 exceptionValue = createNotAFunctionError(exec, v, 0);
2191 BEGIN_OPCODE(op_ret) {
2194 Return register result as the return value of the current
2195 function call, writing it into the caller's expected return
2196 value register. In addition, unwind one call frame and
2197 restore the scope chain, code block instruction pointer and
2198 register base to those of the calling function.
2201 int result = (++vPC)->u.operand;
2203 CodeBlock* oldCodeBlock = codeBlock;
2205 Register* callFrame = r - oldCodeBlock->numLocals - CallFrameHeaderSize;
2206 JSValue* returnValue = r[result].u.jsValue;
2208 if (JSActivation* activation = static_cast<JSActivation*>(callFrame[OptionalCalleeActivation].u.jsValue)) {
2209 ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
2210 ASSERT(activation->isActivationObject());
2211 activation->copyRegisters();
2214 if (*enabledProfilerReference)
2215 (*enabledProfilerReference)->didExecute(exec, callFrame[Callee].u.jsObject);
2217 if (codeBlock->needsFullScopeChain)
2218 scopeChain->deref();
2220 if (callFrame[CalledAsConstructor].u.i && !returnValue->isObject()) {
2221 JSValue* thisObject = callFrame[CallFrameHeaderSize].u.jsValue;
2222 returnValue = thisObject;
2225 codeBlock = callFrame[CallerCodeBlock].u.codeBlock;
2229 k = codeBlock->jsValues.data();
2230 vPC = callFrame[ReturnVPC].u.vPC;
2231 setScopeChain(exec, scopeChain, callFrame[CallerScopeChain].u.scopeChain);
2232 int callerRegisterOffset = callFrame[CallerRegisterOffset].u.i;
2233 r = (*registerBase) + callerRegisterOffset;
2234 exec->m_callFrameOffset = callerRegisterOffset - codeBlock->numLocals - CallFrameHeaderSize;
2235 int dst = callFrame[ReturnValueRegister].u.i;
2236 r[dst].u.jsValue = returnValue;
2240 BEGIN_OPCODE(op_construct) {
2241 /* construct dst(r) constr(r) firstArg(r) argCount(n)
2243 Invoke register "constr" as a constructor. For JS
2244 functions, the calling convention is exactly as for the
2245 "call" opcode, except that the "this" value is a newly
2246 created Object. For native constructors, a null "this"
2247 value is passed. In either case, the firstArg and argCount
2248 registers are interpreted as for the "call" opcode.
2251 int dst = (++vPC)->u.operand;
2252 int constr = (++vPC)->u.operand;
2253 int firstArg = (++vPC)->u.operand;
2254 int argCount = (++vPC)->u.operand;
2256 JSValue* constrVal = r[constr].u.jsValue;
2258 ConstructData constructData;
2259 ConstructType constructType = constrVal->getConstructData(constructData);
2261 // Removing this line of code causes a measurable regression on squirrelfish.
2262 JSObject* constructor = static_cast<JSObject*>(constrVal);
2264 if (constructType == ConstructTypeJS) {
2265 if (*enabledProfilerReference)
2266 (*enabledProfilerReference)->willExecute(exec, constructor);
2268 int registerOffset = r - (*registerBase);
2269 Register* callFrame = r + firstArg - CallFrameHeaderSize;
2270 int callFrameOffset = registerOffset + firstArg - CallFrameHeaderSize;
2272 JSObject* prototype;
2273 JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
2275 prototype = static_cast<JSObject*>(p);
2277 prototype = scopeChain->globalObject()->objectPrototype();
2278 JSObject* newObject = new (exec) JSObject(prototype);
2279 r[firstArg].u.jsValue = newObject; // "this" value
2281 initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, registerOffset, dst, firstArg, argCount, 1, constructor);
2283 ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
2284 FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
2286 CodeBlock* newCodeBlock = &functionBodyNode->code(callDataScopeChain);
2287 r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, registerOffset, firstArg, argCount, exceptionValue);
2291 codeBlock = newCodeBlock;
2292 exec->m_callFrameOffset = callFrameOffset;
2293 setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, registerBase, r));
2294 k = codeBlock->jsValues.data();
2295 vPC = codeBlock->instructions.begin();
2300 if (constructType == ConstructTypeNative) {
2301 if (*enabledProfilerReference)
2302 (*enabledProfilerReference)->willExecute(exec, constructor);
2304 int registerOffset = r - (*registerBase);
2306 ArgList args(reinterpret_cast<JSValue***>(registerBase), registerOffset + firstArg + 1, argCount - 1);
2308 registerFile->setSafeForReentry(true);
2309 JSValue* returnValue = constructData.native.function(exec, constructor, args);
2310 registerFile->setSafeForReentry(false);
2312 r = (*registerBase) + registerOffset;
2313 VM_CHECK_EXCEPTION();
2314 r[dst].u.jsValue = returnValue;
2316 if (*enabledProfilerReference)
2317 (*enabledProfilerReference)->didExecute(exec, constructor);
2323 ASSERT(constructType == ConstructTypeNone);
2325 exceptionValue = createNotAConstructorError(exec, constrVal, 0);
2328 BEGIN_OPCODE(op_push_scope) {
2329 /* push_scope scope(r)
2331 Converts register scope to object, and pushes it onto the top
2332 of the current scope chain.
2334 int scope = (++vPC)->u.operand;
2335 JSValue* v = r[scope].u.jsValue;
2336 JSObject* o = v->toObject(exec);
2337 VM_CHECK_EXCEPTION();
2339 setScopeChain(exec, scopeChain, scopeChain->push(o));
2344 BEGIN_OPCODE(op_pop_scope) {
2347 Removes the top item from the current scope chain.
2349 setScopeChain(exec, scopeChain, scopeChain->pop());
2354 BEGIN_OPCODE(op_get_pnames) {
2355 /* get_pnames dst(r) base(r)
2357 Creates a property name list for register base and puts it
2358 in register dst. This is not a true JavaScript value, just
2359 a synthetic value used to keep the iteration state in a
2362 int dst = (++vPC)->u.operand;
2363 int base = (++vPC)->u.operand;
2365 r[dst].u.jsPropertyNameIterator = JSPropertyNameIterator::create(exec, r[base].u.jsValue);
2369 BEGIN_OPCODE(op_next_pname) {
2370 /* next_pname dst(r) iter(r) target(offset)
2372 Tries to copies the next name from property name list in
2373 register iter. If there are names left, then copies one to
2374 register dst, and jumps to offset target. If there are none
2375 left, invalidates the iterator and continues to the next
2378 int dst = (++vPC)->u.operand;
2379 int iter = (++vPC)->u.operand;
2380 int target = (++vPC)->u.operand;
2382 JSPropertyNameIterator* it = r[iter].u.jsPropertyNameIterator;
2383 if (JSValue* temp = it->next(exec)) {
2384 r[dst].u.jsValue = temp;
2393 BEGIN_OPCODE(op_jmp_scopes) {
2394 /* jmp_scopes count(n) target(offset)
2396 Removes the a number of items from the current scope chain
2397 specified by immediate number count, then jumps to offset
2400 int count = (++vPC)->u.operand;
2401 int target = (++vPC)->u.operand;
2403 ScopeChainNode* tmp = scopeChain;
2406 setScopeChain(exec, scopeChain, tmp);
2411 BEGIN_OPCODE(op_catch) {
2414 Retrieves the VMs current exception and puts it in register
2415 ex. This is only valid after an exception has been raised,
2416 and usually forms the beginning of an exception handler.
2418 ASSERT(exceptionValue);
2419 ASSERT(!exec->hadException());
2420 int ex = (++vPC)->u.operand;
2421 r[ex].u.jsValue = exceptionValue;
2427 BEGIN_OPCODE(op_throw) {
2430 Throws register ex as an exception. This involves three
2431 steps: first, it is set as the current exception in the
2432 VM's internal state, then the stack is unwound until an
2433 exception handler or a native code boundary is found, and
2434 then control resumes at the exception handler if any or
2435 else the script returns control to the nearest native caller.
2438 int ex = (++vPC)->u.operand;
2439 exceptionValue = r[ex].u.jsValue;
2440 handlerVPC = throwException(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r);
2442 *exception = exceptionValue;
2446 #if HAVE(COMPUTED_GOTO)
2447 // Hack around gcc performance quirk by performing an indirect goto
2448 // in order to set the vPC -- attempting to do so directly results in a
2449 // significant regression.
2450 goto *op_throw_end_indirect; // indirect goto -> op_throw_end
2458 BEGIN_OPCODE(op_new_error) {
2459 /* new_error dst(r) type(n) message(k)
2461 Constructs a new Error instance using the original
2462 constructor, using immediate number n as the type and
2463 constant message as the message string. The result is
2464 written to register dst.
2466 int dst = (++vPC)->u.operand;
2467 int type = (++vPC)->u.operand;
2468 int message = (++vPC)->u.operand;
2470 r[dst].u.jsValue = Error::create(exec, (ErrorType)type, k[message]->toString(exec), codeBlock->lineNumberForVPC(vPC), codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
2475 BEGIN_OPCODE(op_end) {
2478 Return register result as the value of a global or eval
2479 program. Return control to the calling native code.
2482 if (codeBlock->needsFullScopeChain) {
2483 ASSERT(scopeChain->refCount > 1);
2484 scopeChain->deref();
2486 int result = (++vPC)->u.operand;
2487 return r[result].u.jsValue;
2489 BEGIN_OPCODE(op_put_getter) {
2490 /* put_getter base(r) property(id) function(r)
2492 Sets register function on register base as the getter named
2493 by identifier property. Base and function are assumed to be
2494 objects as this op should only be used for getters defined
2495 in object literal form.
2497 Unlike many opcodes, this one does not write any output to
2500 int base = (++vPC)->u.operand;
2501 int property = (++vPC)->u.operand;
2502 int function = (++vPC)->u.operand;
2504 ASSERT(r[base].u.jsValue->isObject());
2505 JSObject* baseObj = static_cast<JSObject*>(r[base].u.jsValue);
2506 Identifier& ident = codeBlock->identifiers[property];
2507 ASSERT(r[function].u.jsValue->isObject());
2508 baseObj->defineGetter(exec, ident, static_cast<JSObject* >(r[function].u.jsValue));
2513 BEGIN_OPCODE(op_put_setter) {
2514 /* put_setter base(r) property(id) function(r)
2516 Sets register function on register base as the setter named
2517 by identifier property. Base and function are assumed to be
2518 objects as this op should only be used for setters defined
2519 in object literal form.
2521 Unlike many opcodes, this one does not write any output to
2524 int base = (++vPC)->u.operand;
2525 int property = (++vPC)->u.operand;
2526 int function = (++vPC)->u.operand;
2528 ASSERT(r[base].u.jsValue->isObject());
2529 JSObject* baseObj = static_cast<JSObject*>(r[base].u.jsValue);
2530 Identifier& ident = codeBlock->identifiers[property];
2531 ASSERT(r[function].u.jsValue->isObject());
2532 baseObj->defineSetter(exec, ident, static_cast<JSObject* >(r[function].u.jsValue));
2537 BEGIN_OPCODE(op_jsr) {
2538 /* jsr retAddrDst(r) target(offset)
2540 Places the address of the next instruction into the retAddrDst
2541 register and jumps to offset target from the current instruction.
2543 int retAddrDst = (++vPC)->u.operand;
2544 int target = (++vPC)->u.operand;
2545 r[retAddrDst].u.vPC = vPC + 1;
2550 BEGIN_OPCODE(op_sret) {
2551 /* sret retAddrSrc(r)
2553 Jumps to the address stored in the retAddrSrc register. This
2554 differs from op_jmp because the target address is stored in a
2555 register, not as an immediate.
2557 int retAddrSrc = (++vPC)->u.operand;
2558 vPC = r[retAddrSrc].u.vPC;
2561 BEGIN_OPCODE(op_debug) {
2562 /* debug debugHookID(n) firstLine(n) lastLine(n)
2564 Notifies the debugger of the current state of execution. This opcode
2565 is only generated while the debugger is attached.
2568 int registerOffset = r - (*registerBase);
2569 registerFile->setSafeForReentry(true);
2570 debug(exec, vPC, codeBlock, scopeChain, registerBase, r);
2571 registerFile->setSafeForReentry(false);
2572 r = (*registerBase) + registerOffset;
2578 exec->clearException();
2579 handlerVPC = throwException(exec, exceptionValue, registerBase, vPC, codeBlock, k, scopeChain, r);
2581 *exception = exceptionValue;
2590 #undef VM_CHECK_EXCEPTION
2593 JSValue* Machine::retrieveArguments(ExecState* exec, JSFunction* function) const
2595 Register** registerBase;
2596 int callFrameOffset;
2598 if (!getCallFrame(exec, function, registerBase, callFrameOffset))
2601 Register* callFrame = (*registerBase) + callFrameOffset;
2602 JSActivation* activation = static_cast<JSActivation*>(callFrame[OptionalCalleeActivation].u.jsValue);
2604 CodeBlock* codeBlock = &function->body->generatedCode();
2605 activation = new (exec) JSActivation(function->body, registerBase, callFrameOffset + CallFrameHeaderSize + codeBlock->numLocals);
2606 callFrame[OptionalCalleeActivation].u.jsValue = activation;
2609 return activation->get(exec, exec->propertyNames().arguments);
2612 JSValue* Machine::retrieveCaller(ExecState* exec, JSFunction* function) const
2614 Register** registerBase;
2615 int callFrameOffset;
2617 if (!getCallFrame(exec, function, registerBase, callFrameOffset))
2620 int callerFrameOffset;
2621 if (!getCallerFunctionOffset(registerBase, callFrameOffset, callerFrameOffset))
2624 Register* callerFrame = (*registerBase) + callerFrameOffset;
2625 ASSERT(callerFrame[Callee].u.jsValue);
2626 return callerFrame[Callee].u.jsValue;
2629 bool Machine::getCallFrame(ExecState* exec, JSFunction* function, Register**& registerBase, int& callFrameOffset) const
2631 callFrameOffset = exec->m_callFrameOffset;
2634 while (callFrameOffset < 0) {
2635 exec = exec->m_prev;
2638 callFrameOffset = exec->m_callFrameOffset;
2641 registerBase = exec->m_registerFile->basePointer();
2642 Register* callFrame = (*registerBase) + callFrameOffset;
2643 if (callFrame[Callee].u.jsValue == function)
2646 if (!getCallerFunctionOffset(registerBase, callFrameOffset, callFrameOffset))
2647 callFrameOffset = -1;
2651 void Machine::getFunctionAndArguments(Register** registerBase, Register* callFrame, JSFunction*& function, Register*& argv, int& argc)
2653 function = static_cast<JSFunction*>(callFrame[Callee].u.jsValue);
2654 ASSERT(function->inherits(&JSFunction::info));
2656 argv = (*registerBase) + callFrame[CallerRegisterOffset].u.i + callFrame[ArgumentStartRegister].u.i + 1; // skip "this"
2657 argc = callFrame[ArgumentCount].u.i - 1; // skip "this"