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.
31 #include "Interpreter.h"
33 #include "Arguments.h"
34 #include "BatchedTransitionOptimizer.h"
35 #include "CodeBlock.h"
36 #include "DebuggerCallFrame.h"
37 #include "EvalCodeCache.h"
38 #include "ExceptionHelpers.h"
39 #include "CallFrame.h"
40 #include "GlobalEvalFunction.h"
41 #include "JSActivation.h"
43 #include "JSByteArray.h"
44 #include "JSFunction.h"
45 #include "JSNotAnObject.h"
46 #include "JSPropertyNameIterator.h"
47 #include "JSStaticScopeObject.h"
49 #include "ObjectPrototype.h"
52 #include "RegExpObject.h"
53 #include "RegExpPrototype.h"
55 #include "Collector.h"
57 #include "Operations.h"
58 #include "SamplingTool.h"
66 #include "AssemblerBuffer.h"
70 #include <mach/mach.h>
89 // Preferred number of milliseconds between each timeout check
90 static const int preferredScriptCheckTimeInterval = 1000;
92 static ALWAYS_INLINE unsigned bytecodeOffsetForPC(CodeBlock* codeBlock, void* pc)
95 return codeBlock->getBytecodeIndex(pc);
97 return static_cast<Instruction*>(pc) - codeBlock->instructions().begin();
101 // Returns the depth of the scope chain within a given call frame.
102 static int depth(CodeBlock* codeBlock, ScopeChain& sc)
104 if (!codeBlock->needsFullScopeChain())
106 return sc.localDepth();
109 // FIXME: This operation should be called "getNumber", not "isNumber" (as it is in JSValue.h).
110 // FIXME: There's no need to have a "slow" version of this. All versions should be fast.
111 static ALWAYS_INLINE bool fastIsNumber(JSValue* value, double& arg)
113 if (JSImmediate::isNumber(value))
114 arg = JSImmediate::getTruncatedInt32(value);
115 else if (LIKELY(!JSImmediate::isImmediate(value)) && LIKELY(Heap::isNumber(asCell(value))))
116 arg = asNumberCell(value)->value();
122 // FIXME: Why doesn't JSValue*::toInt32 have the Heap::isNumber optimization?
123 static bool fastToInt32(JSValue* value, int32_t& arg)
125 if (JSImmediate::isNumber(value))
126 arg = JSImmediate::getTruncatedInt32(value);
127 else if (LIKELY(!JSImmediate::isImmediate(value)) && LIKELY(Heap::isNumber(asCell(value))))
128 arg = asNumberCell(value)->toInt32();
134 static ALWAYS_INLINE bool fastToUInt32(JSValue* value, uint32_t& arg)
136 if (JSImmediate::isNumber(value)) {
137 if (JSImmediate::getTruncatedUInt32(value, arg))
140 arg = toUInt32SlowCase(JSImmediate::getTruncatedInt32(value), scratch);
142 } else if (!JSImmediate::isImmediate(value) && Heap::isNumber(asCell(value)))
143 arg = asNumberCell(value)->toUInt32();
149 static inline bool jsLess(CallFrame* callFrame, JSValue* v1, JSValue* v2)
151 if (JSImmediate::areBothImmediateNumbers(v1, v2))
152 return JSImmediate::getTruncatedInt32(v1) < JSImmediate::getTruncatedInt32(v2);
156 if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2))
159 Interpreter* interpreter = callFrame->interpreter();
160 if (interpreter->isJSString(v1) && interpreter->isJSString(v2))
161 return asString(v1)->value() < asString(v2)->value();
165 bool wasNotString1 = v1->getPrimitiveNumber(callFrame, n1, p1);
166 bool wasNotString2 = v2->getPrimitiveNumber(callFrame, n2, p2);
168 if (wasNotString1 | wasNotString2)
171 return asString(p1)->value() < asString(p2)->value();
174 static inline bool jsLessEq(CallFrame* callFrame, JSValue* v1, JSValue* v2)
176 if (JSImmediate::areBothImmediateNumbers(v1, v2))
177 return JSImmediate::getTruncatedInt32(v1) <= JSImmediate::getTruncatedInt32(v2);
181 if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2))
184 Interpreter* interpreter = callFrame->interpreter();
185 if (interpreter->isJSString(v1) && interpreter->isJSString(v2))
186 return !(asString(v2)->value() < asString(v1)->value());
190 bool wasNotString1 = v1->getPrimitiveNumber(callFrame, n1, p1);
191 bool wasNotString2 = v2->getPrimitiveNumber(callFrame, n2, p2);
193 if (wasNotString1 | wasNotString2)
196 return !(asString(p2)->value() < asString(p1)->value());
199 static NEVER_INLINE JSValue* jsAddSlowCase(CallFrame* callFrame, JSValue* v1, JSValue* v2)
201 // exception for the Date exception in defaultValue()
202 JSValue* p1 = v1->toPrimitive(callFrame);
203 JSValue* p2 = v2->toPrimitive(callFrame);
205 if (p1->isString() || p2->isString()) {
206 RefPtr<UString::Rep> value = concatenate(p1->toString(callFrame).rep(), p2->toString(callFrame).rep());
208 return throwOutOfMemoryError(callFrame);
209 return jsString(callFrame, value.release());
212 return jsNumber(callFrame, p1->toNumber(callFrame) + p2->toNumber(callFrame));
215 // Fast-path choices here are based on frequency data from SunSpider:
216 // <times> Add case: <t1> <t2>
217 // ---------------------------
218 // 5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
219 // 247412 Add case: 5 5
220 // 20900 Add case: 5 6
221 // 13962 Add case: 5 3
222 // 4000 Add case: 3 5
224 static ALWAYS_INLINE JSValue* jsAdd(CallFrame* callFrame, JSValue* v1, JSValue* v2)
229 bool rightIsNumber = fastIsNumber(v2, right);
230 if (rightIsNumber && fastIsNumber(v1, left))
231 return jsNumber(callFrame, left + right);
233 bool leftIsString = v1->isString();
234 if (leftIsString && v2->isString()) {
235 RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep());
237 return throwOutOfMemoryError(callFrame);
238 return jsString(callFrame, value.release());
241 if (rightIsNumber & leftIsString) {
242 RefPtr<UString::Rep> value = JSImmediate::isImmediate(v2) ?
243 concatenate(asString(v1)->value().rep(), JSImmediate::getTruncatedInt32(v2)) :
244 concatenate(asString(v1)->value().rep(), right);
247 return throwOutOfMemoryError(callFrame);
248 return jsString(callFrame, value.release());
251 // All other cases are pretty uncommon
252 return jsAddSlowCase(callFrame, v1, v2);
255 static JSValue* jsTypeStringForValue(CallFrame* callFrame, JSValue* v)
257 if (v->isUndefined())
258 return jsNontrivialString(callFrame, "undefined");
260 return jsNontrivialString(callFrame, "boolean");
262 return jsNontrivialString(callFrame, "number");
264 return jsNontrivialString(callFrame, "string");
266 // Return "undefined" for objects that should be treated
267 // as null when doing comparisons.
268 if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
269 return jsNontrivialString(callFrame, "undefined");
271 if (asObject(v)->getCallData(callData) != CallTypeNone)
272 return jsNontrivialString(callFrame, "function");
274 return jsNontrivialString(callFrame, "object");
277 static bool jsIsObjectType(JSValue* v)
279 if (JSImmediate::isImmediate(v))
282 JSType type = asCell(v)->structure()->typeInfo().type();
283 if (type == NumberType || type == StringType)
285 if (type == ObjectType) {
286 if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
289 if (asObject(v)->getCallData(callData) != CallTypeNone)
295 static bool jsIsFunctionType(JSValue* v)
299 if (asObject(v)->getCallData(callData) != CallTypeNone)
305 NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue*& exceptionValue)
307 int dst = (vPC + 1)->u.operand;
308 int property = (vPC + 2)->u.operand;
310 ScopeChainNode* scopeChain = callFrame->scopeChain();
311 ScopeChainIterator iter = scopeChain->begin();
312 ScopeChainIterator end = scopeChain->end();
315 CodeBlock* codeBlock = callFrame->codeBlock();
316 Identifier& ident = codeBlock->identifier(property);
319 PropertySlot slot(o);
320 if (o->getPropertySlot(callFrame, ident, slot)) {
321 JSValue* result = slot.getValue(callFrame, ident);
322 exceptionValue = callFrame->globalData().exception;
325 callFrame[dst] = result;
328 } while (++iter != end);
329 exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
333 NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValue*& exceptionValue)
335 CodeBlock* codeBlock = callFrame->codeBlock();
337 int dst = (vPC + 1)->u.operand;
338 int property = (vPC + 2)->u.operand;
339 int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain();
341 ScopeChainNode* scopeChain = callFrame->scopeChain();
342 ScopeChainIterator iter = scopeChain->begin();
343 ScopeChainIterator end = scopeChain->end();
349 Identifier& ident = codeBlock->identifier(property);
352 PropertySlot slot(o);
353 if (o->getPropertySlot(callFrame, ident, slot)) {
354 JSValue* result = slot.getValue(callFrame, ident);
355 exceptionValue = callFrame->globalData().exception;
358 callFrame[dst] = result;
361 } while (++iter != end);
362 exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
366 NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue*& exceptionValue)
368 int dst = (vPC + 1)->u.operand;
369 JSGlobalObject* globalObject = static_cast<JSGlobalObject*>((vPC + 2)->u.jsCell);
370 ASSERT(globalObject->isGlobalObject());
371 int property = (vPC + 3)->u.operand;
372 Structure* structure = (vPC + 4)->u.structure;
373 int offset = (vPC + 5)->u.operand;
375 if (structure == globalObject->structure()) {
376 callFrame[dst] = globalObject->getDirectOffset(offset);
380 CodeBlock* codeBlock = callFrame->codeBlock();
381 Identifier& ident = codeBlock->identifier(property);
382 PropertySlot slot(globalObject);
383 if (globalObject->getPropertySlot(callFrame, ident, slot)) {
384 JSValue* result = slot.getValue(callFrame, ident);
385 if (slot.isCacheable() && !globalObject->structure()->isDictionary()) {
386 if (vPC[4].u.structure)
387 vPC[4].u.structure->deref();
388 globalObject->structure()->ref();
389 vPC[4] = globalObject->structure();
390 vPC[5] = slot.cachedOffset();
391 callFrame[dst] = result;
395 exceptionValue = callFrame->globalData().exception;
398 callFrame[dst] = result;
402 exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
406 static ALWAYS_INLINE JSValue* inlineResolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain)
408 ScopeChainIterator iter = scopeChain->begin();
409 ScopeChainIterator next = iter;
411 ScopeChainIterator end = scopeChain->end();
418 if (next == end || base->getPropertySlot(callFrame, property, slot))
425 ASSERT_NOT_REACHED();
429 NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC)
431 int dst = (vPC + 1)->u.operand;
432 int property = (vPC + 2)->u.operand;
433 callFrame[dst] = inlineResolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain());
436 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue*& exceptionValue)
438 int baseDst = (vPC + 1)->u.operand;
439 int propDst = (vPC + 2)->u.operand;
440 int property = (vPC + 3)->u.operand;
442 ScopeChainNode* scopeChain = callFrame->scopeChain();
443 ScopeChainIterator iter = scopeChain->begin();
444 ScopeChainIterator end = scopeChain->end();
446 // FIXME: add scopeDepthIsZero optimization
450 CodeBlock* codeBlock = callFrame->codeBlock();
451 Identifier& ident = codeBlock->identifier(property);
455 PropertySlot slot(base);
456 if (base->getPropertySlot(callFrame, ident, slot)) {
457 JSValue* result = slot.getValue(callFrame, ident);
458 exceptionValue = callFrame->globalData().exception;
461 callFrame[propDst] = result;
462 callFrame[baseDst] = base;
466 } while (iter != end);
468 exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
472 NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValue*& exceptionValue)
474 int baseDst = (vPC + 1)->u.operand;
475 int funcDst = (vPC + 2)->u.operand;
476 int property = (vPC + 3)->u.operand;
478 ScopeChainNode* scopeChain = callFrame->scopeChain();
479 ScopeChainIterator iter = scopeChain->begin();
480 ScopeChainIterator end = scopeChain->end();
482 // FIXME: add scopeDepthIsZero optimization
486 CodeBlock* codeBlock = callFrame->codeBlock();
487 Identifier& ident = codeBlock->identifier(property);
491 PropertySlot slot(base);
492 if (base->getPropertySlot(callFrame, ident, slot)) {
493 // ECMA 11.2.3 says that if we hit an activation the this value should be null.
494 // However, section 10.2.3 says that in the case where the value provided
495 // by the caller is null, the global object should be used. It also says
496 // that the section does not apply to internal functions, but for simplicity
497 // of implementation we use the global object anyway here. This guarantees
498 // that in host objects you always get a valid object for this.
499 // We also handle wrapper substitution for the global object at the same time.
500 JSObject* thisObj = base->toThisObject(callFrame);
501 JSValue* result = slot.getValue(callFrame, ident);
502 exceptionValue = callFrame->globalData().exception;
506 callFrame[baseDst] = thisObj;
507 callFrame[funcDst] = result;
511 } while (iter != end);
513 exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
517 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
519 Register* r = callFrame->registers();
520 Register* newEnd = r + registerOffset + newCodeBlock->m_numCalleeRegisters;
522 if (LIKELY(argc == newCodeBlock->m_numParameters)) { // correct number of arguments
523 if (UNLIKELY(!registerFile->grow(newEnd)))
526 } else if (argc < newCodeBlock->m_numParameters) { // too few arguments -- fill in the blanks
527 size_t omittedArgCount = newCodeBlock->m_numParameters - argc;
528 registerOffset += omittedArgCount;
529 newEnd += omittedArgCount;
530 if (!registerFile->grow(newEnd))
534 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
535 for (size_t i = 0; i < omittedArgCount; ++i)
536 argv[i] = jsUndefined();
537 } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind
538 size_t numParameters = newCodeBlock->m_numParameters;
539 registerOffset += numParameters;
540 newEnd += numParameters;
542 if (!registerFile->grow(newEnd))
546 Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argc;
547 for (size_t i = 0; i < numParameters; ++i)
548 argv[i + argc] = argv[i];
551 return CallFrame::create(r);
554 static NEVER_INLINE bool isNotObject(CallFrame* callFrame, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValue* value, JSValue*& exceptionData)
556 if (value->isObject())
558 exceptionData = createInvalidParamError(callFrame, forInstanceOf ? "instanceof" : "in" , value, vPC - codeBlock->instructions().begin(), codeBlock);
562 NEVER_INLINE JSValue* Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue*& exceptionValue)
565 return jsUndefined();
567 JSValue* program = argv[1].jsValue(callFrame);
569 if (!program->isString())
572 UString programSource = asString(program)->value();
574 ScopeChainNode* scopeChain = callFrame->scopeChain();
575 CodeBlock* codeBlock = callFrame->codeBlock();
576 RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
578 JSValue* result = jsUndefined();
580 result = callFrame->globalData().interpreter->execute(evalNode.get(), callFrame, callFrame->thisValue()->toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
585 Interpreter::Interpreter()
588 , m_ctiArrayLengthTrampoline(0)
589 , m_ctiStringLengthTrampoline(0)
590 , m_ctiVirtualCallPreLink(0)
591 , m_ctiVirtualCallLink(0)
592 , m_ctiVirtualCall(0)
596 , m_timeAtLastCheckTimeout(0)
598 , m_timeoutCheckCount(0)
599 , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold)
602 privateExecute(InitializeAndReturn, 0, 0, 0);
604 // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
605 void* storage = fastMalloc(sizeof(CollectorBlock));
607 JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
608 m_jsArrayVptr = jsArray->vptr();
611 JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
612 m_jsByteArrayVptr = jsByteArray->vptr();
613 jsByteArray->~JSCell();
615 JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
616 m_jsStringVptr = jsString->vptr();
619 JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
620 m_jsFunctionVptr = jsFunction->vptr();
621 jsFunction->~JSCell();
626 void Interpreter::initialize(JSGlobalData* globalData)
629 JIT::compileCTIMachineTrampolines(globalData);
631 UNUSED_PARAM(globalData);
635 Interpreter::~Interpreter()
641 void Interpreter::dumpCallFrame(CallFrame* callFrame)
643 callFrame->codeBlock()->dump(callFrame);
644 dumpRegisters(callFrame);
647 void Interpreter::dumpRegisters(CallFrame* callFrame)
649 printf("Register frame: \n\n");
650 printf("----------------------------------------------------\n");
651 printf(" use | address | value \n");
652 printf("----------------------------------------------------\n");
654 CodeBlock* codeBlock = callFrame->codeBlock();
655 RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->interpreter->registerFile();
659 if (codeBlock->codeType() == GlobalCode) {
660 it = registerFile->lastGlobal();
661 end = it + registerFile->numGlobals();
663 printf("[global var] | %10p | %10p \n", it, (*it).v());
666 printf("----------------------------------------------------\n");
669 it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;
670 printf("[this] | %10p | %10p \n", it, (*it).v()); ++it;
671 end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this"
674 printf("[param] | %10p | %10p \n", it, (*it).v());
678 printf("----------------------------------------------------\n");
680 printf("[CodeBlock] | %10p | %10p \n", it, (*it).v()); ++it;
681 printf("[ScopeChain] | %10p | %10p \n", it, (*it).v()); ++it;
682 printf("[CallerRegisters] | %10p | %10p \n", it, (*it).v()); ++it;
683 printf("[ReturnPC] | %10p | %10p \n", it, (*it).v()); ++it;
684 printf("[ReturnValueRegister] | %10p | %10p \n", it, (*it).v()); ++it;
685 printf("[ArgumentCount] | %10p | %10p \n", it, (*it).v()); ++it;
686 printf("[Callee] | %10p | %10p \n", it, (*it).v()); ++it;
687 printf("[OptionalCalleeArguments] | %10p | %10p \n", it, (*it).v()); ++it;
688 printf("----------------------------------------------------\n");
690 int registerCount = 0;
692 end = it + codeBlock->m_numVars;
695 printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v());
700 printf("----------------------------------------------------\n");
702 end = it + codeBlock->m_numConstants;
705 printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v());
710 printf("----------------------------------------------------\n");
712 end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numConstants - codeBlock->m_numVars;
715 printf("[r%2d] | %10p | %10p \n", registerCount, it, (*it).v());
720 printf("----------------------------------------------------\n");
725 bool Interpreter::isOpcode(Opcode opcode)
727 #if HAVE(COMPUTED_GOTO)
728 return opcode != HashTraits<Opcode>::emptyValue()
729 && !HashTraits<Opcode>::isDeletedValue(opcode)
730 && m_opcodeIDTable.contains(opcode);
732 return opcode >= 0 && opcode <= op_end;
736 NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue* exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
738 CodeBlock* oldCodeBlock = codeBlock;
739 ScopeChainNode* scopeChain = callFrame->scopeChain();
741 if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
742 DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
743 if (callFrame->callee())
744 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine());
746 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine());
749 if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
750 if (callFrame->callee())
751 profiler->didExecute(callFrame, callFrame->callee());
753 profiler->didExecute(callFrame, codeBlock->ownerNode()->sourceURL(), codeBlock->ownerNode()->lineNo());
756 // If this call frame created an activation or an 'arguments' object, tear it off.
757 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
758 while (!scopeChain->object->isObject(&JSActivation::info))
759 scopeChain = scopeChain->pop();
760 static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments());
761 } else if (Arguments* arguments = callFrame->optionalCalleeArguments()) {
762 if (!arguments->isTornOff())
763 arguments->copyRegisters();
766 if (oldCodeBlock->needsFullScopeChain())
769 void* returnPC = callFrame->returnPC();
770 callFrame = callFrame->callerFrame();
771 if (callFrame->hasHostCallFrameFlag())
774 codeBlock = callFrame->codeBlock();
775 bytecodeOffset = bytecodeOffsetForPC(codeBlock, returnPC);
779 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue*& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
781 // Set up the exception object
783 CodeBlock* codeBlock = callFrame->codeBlock();
784 if (exceptionValue->isObject()) {
785 JSObject* exception = asObject(exceptionValue);
786 if (exception->isNotAnObjectErrorStub()) {
787 exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock);
788 exceptionValue = exception;
790 if (!exception->hasProperty(callFrame, Identifier(callFrame, "line")) &&
791 !exception->hasProperty(callFrame, Identifier(callFrame, "sourceId")) &&
792 !exception->hasProperty(callFrame, Identifier(callFrame, "sourceURL")) &&
793 !exception->hasProperty(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName)) &&
794 !exception->hasProperty(callFrame, Identifier(callFrame, expressionCaretOffsetPropertyName)) &&
795 !exception->hasProperty(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName))) {
800 int line = codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divotPoint, startOffset, endOffset);
801 exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, line), ReadOnly | DontDelete);
803 // We only hit this path for error messages and throw statements, which don't have a specific failure position
804 // So we just give the full range of the error/throw statement.
805 exception->putWithAttributes(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName), jsNumber(callFrame, divotPoint - startOffset), ReadOnly | DontDelete);
806 exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete);
808 exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset)), ReadOnly | DontDelete);
809 exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerNode()->sourceID()), ReadOnly | DontDelete);
810 exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerNode()->sourceURL()), ReadOnly | DontDelete);
813 if (exception->isWatchdogException()) {
814 while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
815 // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
822 if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
823 DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
824 debugger->exception(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset));
827 // If we throw in the middle of a call instruction, we need to notify
828 // the profiler manually that the call instruction has returned, since
829 // we'll never reach the relevant op_profile_did_call.
830 if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
832 if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
833 profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 2].u.operand].jsValue(callFrame));
834 else if (codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
835 profiler->didExecute(callFrame, callFrame[codeBlock->instructions()[bytecodeOffset + 10].u.operand].jsValue(callFrame));
837 int functionRegisterIndex;
838 if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
839 profiler->didExecute(callFrame, callFrame[functionRegisterIndex].jsValue(callFrame));
843 // Calculate an exception handler vPC, unwinding call frames as necessary.
845 HandlerInfo* handler = 0;
846 while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
847 if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock))
851 // Now unwind the scope chain within the exception handler's call frame.
853 ScopeChainNode* scopeChain = callFrame->scopeChain();
854 ScopeChain sc(scopeChain);
855 int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;
856 ASSERT(scopeDelta >= 0);
858 scopeChain = scopeChain->pop();
859 callFrame->setScopeChain(scopeChain);
864 JSValue* Interpreter::execute(ProgramNode* programNode, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue** exception)
866 ASSERT(!scopeChain->globalData->exception);
868 if (m_reentryDepth >= MaxReentryDepth) {
869 *exception = createStackOverflowError(callFrame);
873 CodeBlock* codeBlock = &programNode->bytecode(scopeChain);
875 Register* oldEnd = m_registerFile.end();
876 Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
877 if (!m_registerFile.grow(newEnd)) {
878 *exception = createStackOverflowError(callFrame);
882 DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject());
884 JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
885 JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
886 globalObject->copyGlobalsTo(m_registerFile);
888 CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
889 newCallFrame[codeBlock->thisRegister()] = thisObj;
890 newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0);
892 if (codeBlock->needsFullScopeChain())
895 Profiler** profiler = Profiler::enabledProfilerReference();
897 (*profiler)->willExecute(newCallFrame, programNode->sourceURL(), programNode->lineNo());
901 SamplingTool::CallRecord callRecord(m_sampler);
905 if (!codeBlock->jitCode())
906 JIT::compile(scopeChain->globalData, codeBlock);
907 result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception);
909 result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
915 (*profiler)->didExecute(callFrame, programNode->sourceURL(), programNode->lineNo());
917 if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
918 lastGlobalObject->copyGlobalsTo(m_registerFile);
920 m_registerFile.shrink(oldEnd);
925 JSValue* Interpreter::execute(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue** exception)
927 ASSERT(!scopeChain->globalData->exception);
929 if (m_reentryDepth >= MaxReentryDepth) {
930 *exception = createStackOverflowError(callFrame);
934 Register* oldEnd = m_registerFile.end();
935 int argc = 1 + args.size(); // implicit "this" parameter
937 if (!m_registerFile.grow(oldEnd + argc)) {
938 *exception = createStackOverflowError(callFrame);
942 DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
944 CallFrame* newCallFrame = CallFrame::create(oldEnd);
946 newCallFrame[0] = thisObj;
947 ArgList::const_iterator end = args.end();
948 for (ArgList::const_iterator it = args.begin(); it != end; ++it)
949 newCallFrame[++dst] = *it;
951 CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain);
952 newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
953 if (UNLIKELY(!newCallFrame)) {
954 *exception = createStackOverflowError(callFrame);
955 m_registerFile.shrink(oldEnd);
958 // a 0 codeBlock indicates a built-in caller
959 newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
961 Profiler** profiler = Profiler::enabledProfilerReference();
963 (*profiler)->willExecute(newCallFrame, function);
967 SamplingTool::CallRecord callRecord(m_sampler);
971 if (!codeBlock->jitCode())
972 JIT::compile(scopeChain->globalData, codeBlock);
973 result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception);
975 result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
981 (*profiler)->didExecute(newCallFrame, function);
983 m_registerFile.shrink(oldEnd);
987 JSValue* Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue** exception)
989 return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNode->bytecode(scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
992 JSValue* Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue** exception)
994 ASSERT(!scopeChain->globalData->exception);
996 if (m_reentryDepth >= MaxReentryDepth) {
997 *exception = createStackOverflowError(callFrame);
1001 DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject());
1003 EvalCodeBlock* codeBlock = &evalNode->bytecode(scopeChain);
1005 JSVariableObject* variableObject;
1006 for (ScopeChainNode* node = scopeChain; ; node = node->next) {
1008 if (node->object->isVariableObject()) {
1009 variableObject = static_cast<JSVariableObject*>(node->object);
1014 { // Scope for BatchedTransitionOptimizer
1016 BatchedTransitionOptimizer optimizer(variableObject);
1018 const DeclarationStacks::VarStack& varStack = codeBlock->ownerNode()->varStack();
1019 DeclarationStacks::VarStack::const_iterator varStackEnd = varStack.end();
1020 for (DeclarationStacks::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
1021 const Identifier& ident = (*it).first;
1022 if (!variableObject->hasProperty(callFrame, ident)) {
1023 PutPropertySlot slot;
1024 variableObject->put(callFrame, ident, jsUndefined(), slot);
1028 const DeclarationStacks::FunctionStack& functionStack = codeBlock->ownerNode()->functionStack();
1029 DeclarationStacks::FunctionStack::const_iterator functionStackEnd = functionStack.end();
1030 for (DeclarationStacks::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) {
1031 PutPropertySlot slot;
1032 variableObject->put(callFrame, (*it)->m_ident, (*it)->makeFunction(callFrame, scopeChain), slot);
1037 Register* oldEnd = m_registerFile.end();
1038 Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
1039 if (!m_registerFile.grow(newEnd)) {
1040 *exception = createStackOverflowError(callFrame);
1044 CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
1046 // a 0 codeBlock indicates a built-in caller
1047 newCallFrame[codeBlock->thisRegister()] = thisObj;
1048 newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0);
1050 if (codeBlock->needsFullScopeChain())
1053 Profiler** profiler = Profiler::enabledProfilerReference();
1055 (*profiler)->willExecute(newCallFrame, evalNode->sourceURL(), evalNode->lineNo());
1059 SamplingTool::CallRecord callRecord(m_sampler);
1063 if (!codeBlock->jitCode())
1064 JIT::compile(scopeChain->globalData, codeBlock);
1065 result = JIT::execute(codeBlock->jitCode(), &m_registerFile, newCallFrame, scopeChain->globalData, exception);
1067 result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
1073 (*profiler)->didExecute(callFrame, evalNode->sourceURL(), evalNode->lineNo());
1075 m_registerFile.shrink(oldEnd);
1079 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine)
1081 Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
1085 switch (debugHookID) {
1086 case DidEnterCallFrame:
1087 debugger->callEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
1089 case WillLeaveCallFrame:
1090 debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
1092 case WillExecuteStatement:
1093 debugger->atStatement(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
1095 case WillExecuteProgram:
1096 debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine);
1098 case DidExecuteProgram:
1099 debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
1101 case DidReachBreakpoint:
1102 debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine);
1107 void Interpreter::resetTimeoutCheck()
1109 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1110 m_timeAtLastCheckTimeout = 0;
1111 m_timeExecuting = 0;
1114 // Returns the time the current thread has spent executing, in milliseconds.
1115 static inline unsigned getCPUTime()
1117 #if PLATFORM(DARWIN)
1118 mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
1119 thread_basic_info_data_t info;
1121 // Get thread information
1122 mach_port_t threadPort = mach_thread_self();
1123 thread_info(threadPort, THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount);
1124 mach_port_deallocate(mach_task_self(), threadPort);
1126 unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000;
1127 time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
1130 #elif HAVE(SYS_TIME_H)
1131 // FIXME: This should probably use getrusage with the RUSAGE_THREAD flag.
1133 gettimeofday(&tv, 0);
1134 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
1136 QDateTime t = QDateTime::currentDateTime();
1137 return t.toTime_t() * 1000 + t.time().msec();
1138 #elif PLATFORM(WIN_OS)
1141 unsigned long long fileTimeAsLong;
1142 } userTime, kernelTime;
1144 // GetThreadTimes won't accept NULL arguments so we pass these even though
1145 // they're not used.
1146 FILETIME creationTime, exitTime;
1148 GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
1150 return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
1152 #error Platform does not have getCurrentTime function
1156 // We have to return a JSValue here, gcc seems to produce worse code if
1157 // we attempt to return a bool
1158 ALWAYS_INLINE JSValue* Interpreter::checkTimeout(JSGlobalObject* globalObject)
1160 unsigned currentTime = getCPUTime();
1162 if (!m_timeAtLastCheckTimeout) {
1163 // Suspicious amount of looping in a script -- start timing it
1164 m_timeAtLastCheckTimeout = currentTime;
1168 unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
1173 m_timeExecuting += timeDiff;
1174 m_timeAtLastCheckTimeout = currentTime;
1176 // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
1177 // preferredScriptCheckTimeInterval
1178 m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck);
1179 // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
1180 // preferred script check time interval.
1181 if (m_ticksUntilNextTimeoutCheck == 0)
1182 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1184 if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
1185 if (globalObject->shouldInterruptScript())
1186 return jsNull(); // Appeasing GCC, all we need is a non-null js value.
1188 resetTimeoutCheck();
1194 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
1196 int dst = (++vPC)->u.operand;
1197 CodeBlock* codeBlock = callFrame->codeBlock();
1198 Identifier& property = codeBlock->identifier((++vPC)->u.operand);
1199 JSValue* value = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1200 JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
1201 callFrame[dst] = scope;
1203 return callFrame->scopeChain()->push(scope);
1206 static StructureChain* cachePrototypeChain(CallFrame* callFrame, Structure* structure)
1208 JSValue* prototype = structure->prototypeForLookup(callFrame);
1209 if (JSImmediate::isImmediate(prototype))
1211 RefPtr<StructureChain> chain = StructureChain::create(asObject(prototype)->structure());
1212 structure->setCachedPrototypeChain(chain.release());
1213 return structure->cachedPrototypeChain();
1216 NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const PutPropertySlot& slot)
1218 // Recursive invocation may already have specialized this instruction.
1219 if (vPC[0].u.opcode != getOpcode(op_put_by_id))
1222 if (JSImmediate::isImmediate(baseValue))
1225 // Uncacheable: give up.
1226 if (!slot.isCacheable()) {
1227 vPC[0] = getOpcode(op_put_by_id_generic);
1231 JSCell* baseCell = asCell(baseValue);
1232 Structure* structure = baseCell->structure();
1234 if (structure->isDictionary()) {
1235 vPC[0] = getOpcode(op_put_by_id_generic);
1239 // Cache miss: record Structure to compare against next time.
1240 Structure* lastStructure = vPC[4].u.structure;
1241 if (structure != lastStructure) {
1242 // First miss: record Structure to compare against next time.
1243 if (!lastStructure) {
1248 // Second miss: give up.
1249 vPC[0] = getOpcode(op_put_by_id_generic);
1253 // Cache hit: Specialize instruction and ref Structures.
1255 // If baseCell != slot.base(), then baseCell must be a proxy for another object.
1256 if (baseCell != slot.base()) {
1257 vPC[0] = getOpcode(op_put_by_id_generic);
1261 // Structure transition, cache transition info
1262 if (slot.type() == PutPropertySlot::NewProperty) {
1263 vPC[0] = getOpcode(op_put_by_id_transition);
1264 vPC[4] = structure->previousID();
1266 StructureChain* chain = structure->cachedPrototypeChain();
1268 chain = cachePrototypeChain(callFrame, structure);
1270 // This happens if someone has manually inserted null into the prototype chain
1271 vPC[0] = getOpcode(op_put_by_id_generic);
1276 vPC[7] = slot.cachedOffset();
1277 codeBlock->refStructures(vPC);
1281 vPC[0] = getOpcode(op_put_by_id_replace);
1282 vPC[5] = slot.cachedOffset();
1283 codeBlock->refStructures(vPC);
1286 NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC)
1288 codeBlock->derefStructures(vPC);
1289 vPC[0] = getOpcode(op_put_by_id);
1293 static size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValue* baseValue, const PropertySlot& slot)
1295 JSCell* cell = asCell(baseValue);
1298 while (slot.slotBase() != cell) {
1299 JSValue* v = cell->structure()->prototypeForLookup(callFrame);
1301 // If we didn't find slotBase in baseValue's prototype chain, then baseValue
1302 // must be a proxy for another object.
1309 // Since we're accessing a prototype in a loop, it's a good bet that it
1310 // should not be treated as a dictionary.
1311 if (cell->structure()->isDictionary()) {
1312 RefPtr<Structure> transition = Structure::fromDictionaryTransition(cell->structure());
1313 asObject(cell)->setStructure(transition.release());
1314 cell->structure()->setCachedPrototypeChain(0);
1324 NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot)
1326 // Recursive invocation may already have specialized this instruction.
1327 if (vPC[0].u.opcode != getOpcode(op_get_by_id))
1330 // FIXME: Cache property access for immediates.
1331 if (JSImmediate::isImmediate(baseValue)) {
1332 vPC[0] = getOpcode(op_get_by_id_generic);
1336 if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
1337 vPC[0] = getOpcode(op_get_array_length);
1341 if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
1342 vPC[0] = getOpcode(op_get_string_length);
1346 // Uncacheable: give up.
1347 if (!slot.isCacheable()) {
1348 vPC[0] = getOpcode(op_get_by_id_generic);
1352 Structure* structure = asCell(baseValue)->structure();
1354 if (structure->isDictionary()) {
1355 vPC[0] = getOpcode(op_get_by_id_generic);
1360 Structure* lastStructure = vPC[4].u.structure;
1361 if (structure != lastStructure) {
1362 // First miss: record Structure to compare against next time.
1363 if (!lastStructure) {
1368 // Second miss: give up.
1369 vPC[0] = getOpcode(op_get_by_id_generic);
1373 // Cache hit: Specialize instruction and ref Structures.
1375 if (slot.slotBase() == baseValue) {
1376 vPC[0] = getOpcode(op_get_by_id_self);
1377 vPC[5] = slot.cachedOffset();
1379 codeBlock->refStructures(vPC);
1383 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
1384 ASSERT(slot.slotBase()->isObject());
1386 JSObject* baseObject = asObject(slot.slotBase());
1388 // Since we're accessing a prototype in a loop, it's a good bet that it
1389 // should not be treated as a dictionary.
1390 if (baseObject->structure()->isDictionary()) {
1391 RefPtr<Structure> transition = Structure::fromDictionaryTransition(baseObject->structure());
1392 baseObject->setStructure(transition.release());
1393 asCell(baseValue)->structure()->setCachedPrototypeChain(0);
1396 vPC[0] = getOpcode(op_get_by_id_proto);
1397 vPC[5] = baseObject->structure();
1398 vPC[6] = slot.cachedOffset();
1400 codeBlock->refStructures(vPC);
1404 size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
1406 vPC[0] = getOpcode(op_get_by_id_generic);
1410 StructureChain* chain = structure->cachedPrototypeChain();
1412 chain = cachePrototypeChain(callFrame, structure);
1415 vPC[0] = getOpcode(op_get_by_id_chain);
1419 vPC[7] = slot.cachedOffset();
1420 codeBlock->refStructures(vPC);
1423 NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC)
1425 codeBlock->derefStructures(vPC);
1426 vPC[0] = getOpcode(op_get_by_id);
1430 JSValue* Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue** exception)
1432 // One-time initialization of our address tables. We have to put this code
1433 // here because our labels are only in scope inside this function.
1434 if (flag == InitializeAndReturn) {
1435 #if HAVE(COMPUTED_GOTO)
1436 #define ADD_BYTECODE(id, length) m_opcodeTable[id] = &&id;
1437 FOR_EACH_OPCODE_ID(ADD_BYTECODE);
1440 #define ADD_OPCODE_ID(id, length) m_opcodeIDTable.add(&&id, id);
1441 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
1442 #undef ADD_OPCODE_ID
1443 ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
1444 #endif // HAVE(COMPUTED_GOTO)
1449 // Currently with CTI enabled we never interpret functions
1450 ASSERT_NOT_REACHED();
1453 JSGlobalData* globalData = &callFrame->globalData();
1454 JSValue* exceptionValue = noValue();
1455 HandlerInfo* handler = 0;
1457 Instruction* vPC = callFrame->codeBlock()->instructions().begin();
1458 Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
1459 unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
1461 #define CHECK_FOR_EXCEPTION() \
1463 if (UNLIKELY(globalData->exception != noValue())) { \
1464 exceptionValue = globalData->exception; \
1469 #if ENABLE(OPCODE_STATS)
1470 OpcodeStats::resetLastInstruction();
1473 #define CHECK_FOR_TIMEOUT() \
1474 if (!--tickCount) { \
1475 if ((exceptionValue = checkTimeout(callFrame->dynamicGlobalObject()))) \
1477 tickCount = m_ticksUntilNextTimeoutCheck; \
1480 #if ENABLE(OPCODE_SAMPLING)
1481 #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC)
1482 #define CTI_SAMPLER ARG_globalData->interpreter->sampler()
1484 #define SAMPLE(codeBlock, vPC)
1485 #define CTI_SAMPLER 0
1488 #if HAVE(COMPUTED_GOTO)
1489 #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto *vPC->u.opcode
1490 #if ENABLE(OPCODE_STATS)
1491 #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
1493 #define DEFINE_OPCODE(opcode) opcode:
1497 #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto interpreterLoopStart
1498 #if ENABLE(OPCODE_STATS)
1499 #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
1501 #define DEFINE_OPCODE(opcode) case opcode:
1503 while (1) { // iterator loop begins
1504 interpreterLoopStart:;
1505 switch (vPC->u.opcode)
1508 DEFINE_OPCODE(op_new_object) {
1509 /* new_object dst(r)
1511 Constructs a new empty Object instance using the original
1512 constructor, and puts the result in register dst.
1514 int dst = (++vPC)->u.operand;
1515 callFrame[dst] = constructEmptyObject(callFrame);
1520 DEFINE_OPCODE(op_new_array) {
1521 /* new_array dst(r) firstArg(r) argCount(n)
1523 Constructs a new Array instance using the original
1524 constructor, and puts the result in register dst.
1525 The array will contain argCount elements with values
1526 taken from registers starting at register firstArg.
1528 int dst = (++vPC)->u.operand;
1529 int firstArg = (++vPC)->u.operand;
1530 int argCount = (++vPC)->u.operand;
1531 ArgList args(callFrame->registers() + firstArg, argCount);
1532 callFrame[dst] = constructArray(callFrame, args);
1537 DEFINE_OPCODE(op_new_regexp) {
1538 /* new_regexp dst(r) regExp(re)
1540 Constructs a new RegExp instance using the original
1541 constructor from regexp regExp, and puts the result in
1544 int dst = (++vPC)->u.operand;
1545 int regExp = (++vPC)->u.operand;
1546 callFrame[dst] = new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp));
1551 DEFINE_OPCODE(op_mov) {
1552 /* mov dst(r) src(r)
1554 Copies register src to register dst.
1556 int dst = (++vPC)->u.operand;
1557 int src = (++vPC)->u.operand;
1558 callFrame[dst] = callFrame[src];
1563 DEFINE_OPCODE(op_eq) {
1564 /* eq dst(r) src1(r) src2(r)
1566 Checks whether register src1 and register src2 are equal,
1567 as with the ECMAScript '==' operator, and puts the result
1568 as a boolean in register dst.
1570 int dst = (++vPC)->u.operand;
1571 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1572 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1573 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1574 callFrame[dst] = jsBoolean(src1 == src2);
1576 JSValue* result = jsBoolean(equalSlowCase(callFrame, src1, src2));
1577 CHECK_FOR_EXCEPTION();
1578 callFrame[dst] = result;
1584 DEFINE_OPCODE(op_eq_null) {
1585 /* eq_null dst(r) src(r)
1587 Checks whether register src is null, as with the ECMAScript '!='
1588 operator, and puts the result as a boolean in register dst.
1590 int dst = (++vPC)->u.operand;
1591 JSValue* src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1593 if (src->isUndefinedOrNull()) {
1594 callFrame[dst] = jsBoolean(true);
1599 callFrame[dst] = jsBoolean(!JSImmediate::isImmediate(src) && src->asCell()->structure()->typeInfo().masqueradesAsUndefined());
1603 DEFINE_OPCODE(op_neq) {
1604 /* neq dst(r) src1(r) src2(r)
1606 Checks whether register src1 and register src2 are not
1607 equal, as with the ECMAScript '!=' operator, and puts the
1608 result as a boolean in register dst.
1610 int dst = (++vPC)->u.operand;
1611 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1612 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1613 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1614 callFrame[dst] = jsBoolean(src1 != src2);
1616 JSValue* result = jsBoolean(!equalSlowCase(callFrame, src1, src2));
1617 CHECK_FOR_EXCEPTION();
1618 callFrame[dst] = result;
1624 DEFINE_OPCODE(op_neq_null) {
1625 /* neq_null dst(r) src(r)
1627 Checks whether register src is not null, as with the ECMAScript '!='
1628 operator, and puts the result as a boolean in register dst.
1630 int dst = (++vPC)->u.operand;
1631 JSValue* src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1633 if (src->isUndefinedOrNull()) {
1634 callFrame[dst] = jsBoolean(false);
1639 callFrame[dst] = jsBoolean(JSImmediate::isImmediate(src) || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined());
1643 DEFINE_OPCODE(op_stricteq) {
1644 /* stricteq dst(r) src1(r) src2(r)
1646 Checks whether register src1 and register src2 are strictly
1647 equal, as with the ECMAScript '===' operator, and puts the
1648 result as a boolean in register dst.
1650 int dst = (++vPC)->u.operand;
1651 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1652 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1653 if (JSImmediate::areBothImmediate(src1, src2))
1654 callFrame[dst] = jsBoolean(src1 == src2);
1655 else if (JSImmediate::isEitherImmediate(src1, src2) & (src1 != JSImmediate::zeroImmediate()) & (src2 != JSImmediate::zeroImmediate()))
1656 callFrame[dst] = jsBoolean(false);
1658 callFrame[dst] = jsBoolean(strictEqualSlowCase(src1, src2));
1663 DEFINE_OPCODE(op_nstricteq) {
1664 /* nstricteq dst(r) src1(r) src2(r)
1666 Checks whether register src1 and register src2 are not
1667 strictly equal, as with the ECMAScript '!==' operator, and
1668 puts the result as a boolean in register dst.
1670 int dst = (++vPC)->u.operand;
1671 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1672 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1674 if (JSImmediate::areBothImmediate(src1, src2))
1675 callFrame[dst] = jsBoolean(src1 != src2);
1676 else if (JSImmediate::isEitherImmediate(src1, src2) & (src1 != JSImmediate::zeroImmediate()) & (src2 != JSImmediate::zeroImmediate()))
1677 callFrame[dst] = jsBoolean(true);
1679 callFrame[dst] = jsBoolean(!strictEqualSlowCase(src1, src2));
1684 DEFINE_OPCODE(op_less) {
1685 /* less dst(r) src1(r) src2(r)
1687 Checks whether register src1 is less than register src2, as
1688 with the ECMAScript '<' operator, and puts the result as
1689 a boolean in register dst.
1691 int dst = (++vPC)->u.operand;
1692 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1693 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1694 JSValue* result = jsBoolean(jsLess(callFrame, src1, src2));
1695 CHECK_FOR_EXCEPTION();
1696 callFrame[dst] = result;
1701 DEFINE_OPCODE(op_lesseq) {
1702 /* lesseq dst(r) src1(r) src2(r)
1704 Checks whether register src1 is less than or equal to
1705 register src2, as with the ECMAScript '<=' operator, and
1706 puts the result as a boolean in register dst.
1708 int dst = (++vPC)->u.operand;
1709 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1710 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1711 JSValue* result = jsBoolean(jsLessEq(callFrame, src1, src2));
1712 CHECK_FOR_EXCEPTION();
1713 callFrame[dst] = result;
1718 DEFINE_OPCODE(op_pre_inc) {
1719 /* pre_inc srcDst(r)
1721 Converts register srcDst to number, adds one, and puts the result
1722 back in register srcDst.
1724 int srcDst = (++vPC)->u.operand;
1725 JSValue* v = callFrame[srcDst].jsValue(callFrame);
1726 if (JSImmediate::canDoFastAdditiveOperations(v))
1727 callFrame[srcDst] = JSImmediate::incImmediateNumber(v);
1729 JSValue* result = jsNumber(callFrame, v->toNumber(callFrame) + 1);
1730 CHECK_FOR_EXCEPTION();
1731 callFrame[srcDst] = result;
1737 DEFINE_OPCODE(op_pre_dec) {
1738 /* pre_dec srcDst(r)
1740 Converts register srcDst to number, subtracts one, and puts the result
1741 back in register srcDst.
1743 int srcDst = (++vPC)->u.operand;
1744 JSValue* v = callFrame[srcDst].jsValue(callFrame);
1745 if (JSImmediate::canDoFastAdditiveOperations(v))
1746 callFrame[srcDst] = JSImmediate::decImmediateNumber(v);
1748 JSValue* result = jsNumber(callFrame, v->toNumber(callFrame) - 1);
1749 CHECK_FOR_EXCEPTION();
1750 callFrame[srcDst] = result;
1756 DEFINE_OPCODE(op_post_inc) {
1757 /* post_inc dst(r) srcDst(r)
1759 Converts register srcDst to number. The number itself is
1760 written to register dst, and the number plus one is written
1761 back to register srcDst.
1763 int dst = (++vPC)->u.operand;
1764 int srcDst = (++vPC)->u.operand;
1765 JSValue* v = callFrame[srcDst].jsValue(callFrame);
1766 if (JSImmediate::canDoFastAdditiveOperations(v)) {
1768 callFrame[srcDst] = JSImmediate::incImmediateNumber(v);
1770 JSValue* number = callFrame[srcDst].jsValue(callFrame)->toJSNumber(callFrame);
1771 CHECK_FOR_EXCEPTION();
1772 callFrame[dst] = number;
1773 callFrame[srcDst] = jsNumber(callFrame, number->uncheckedGetNumber() + 1);
1779 DEFINE_OPCODE(op_post_dec) {
1780 /* post_dec dst(r) srcDst(r)
1782 Converts register srcDst to number. The number itself is
1783 written to register dst, and the number minus one is written
1784 back to register srcDst.
1786 int dst = (++vPC)->u.operand;
1787 int srcDst = (++vPC)->u.operand;
1788 JSValue* v = callFrame[srcDst].jsValue(callFrame);
1789 if (JSImmediate::canDoFastAdditiveOperations(v)) {
1791 callFrame[srcDst] = JSImmediate::decImmediateNumber(v);
1793 JSValue* number = callFrame[srcDst].jsValue(callFrame)->toJSNumber(callFrame);
1794 CHECK_FOR_EXCEPTION();
1795 callFrame[dst] = number;
1796 callFrame[srcDst] = jsNumber(callFrame, number->uncheckedGetNumber() - 1);
1802 DEFINE_OPCODE(op_to_jsnumber) {
1803 /* to_jsnumber dst(r) src(r)
1805 Converts register src to number, and puts the result
1808 int dst = (++vPC)->u.operand;
1809 int src = (++vPC)->u.operand;
1811 JSValue* srcVal = callFrame[src].jsValue(callFrame);
1813 if (LIKELY(srcVal->isNumber()))
1814 callFrame[dst] = callFrame[src];
1816 JSValue* result = srcVal->toJSNumber(callFrame);
1817 CHECK_FOR_EXCEPTION();
1818 callFrame[dst] = result;
1824 DEFINE_OPCODE(op_negate) {
1825 /* negate dst(r) src(r)
1827 Converts register src to number, negates it, and puts the
1828 result in register dst.
1830 int dst = (++vPC)->u.operand;
1831 JSValue* src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1834 if (fastIsNumber(src, v))
1835 callFrame[dst] = jsNumber(callFrame, -v);
1837 JSValue* result = jsNumber(callFrame, -src->toNumber(callFrame));
1838 CHECK_FOR_EXCEPTION();
1839 callFrame[dst] = result;
1844 DEFINE_OPCODE(op_add) {
1845 /* add dst(r) src1(r) src2(r)
1847 Adds register src1 and register src2, and puts the result
1848 in register dst. (JS add may be string concatenation or
1849 numeric add, depending on the types of the operands.)
1851 int dst = (++vPC)->u.operand;
1852 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1853 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1854 if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1855 callFrame[dst] = JSImmediate::addImmediateNumbers(src1, src2);
1857 JSValue* result = jsAdd(callFrame, src1, src2);
1858 CHECK_FOR_EXCEPTION();
1859 callFrame[dst] = result;
1864 DEFINE_OPCODE(op_mul) {
1865 /* mul dst(r) src1(r) src2(r)
1867 Multiplies register src1 and register src2 (converted to
1868 numbers), and puts the product in register dst.
1870 int dst = (++vPC)->u.operand;
1871 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1872 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1875 if (JSImmediate::areBothImmediateNumbers(src1, src2)) {
1876 int32_t left = JSImmediate::getTruncatedInt32(src1);
1877 int32_t right = JSImmediate::getTruncatedInt32(src2);
1878 if ((left | right) >> 15 == 0)
1879 callFrame[dst] = jsNumber(callFrame, left * right);
1881 callFrame[dst] = jsNumber(callFrame, static_cast<double>(left) * static_cast<double>(right));
1882 } else if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1883 callFrame[dst] = jsNumber(callFrame, left * right);
1885 JSValue* result = jsNumber(callFrame, src1->toNumber(callFrame) * src2->toNumber(callFrame));
1886 CHECK_FOR_EXCEPTION();
1887 callFrame[dst] = result;
1893 DEFINE_OPCODE(op_div) {
1894 /* div dst(r) dividend(r) divisor(r)
1896 Divides register dividend (converted to number) by the
1897 register divisor (converted to number), and puts the
1898 quotient in register dst.
1900 int dst = (++vPC)->u.operand;
1901 JSValue* dividend = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1902 JSValue* divisor = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1905 if (fastIsNumber(dividend, left) && fastIsNumber(divisor, right))
1906 callFrame[dst] = jsNumber(callFrame, left / right);
1908 JSValue* result = jsNumber(callFrame, dividend->toNumber(callFrame) / divisor->toNumber(callFrame));
1909 CHECK_FOR_EXCEPTION();
1910 callFrame[dst] = result;
1915 DEFINE_OPCODE(op_mod) {
1916 /* mod dst(r) dividend(r) divisor(r)
1918 Divides register dividend (converted to number) by
1919 register divisor (converted to number), and puts the
1920 remainder in register dst.
1922 int dst = (++vPC)->u.operand;
1923 int dividend = (++vPC)->u.operand;
1924 int divisor = (++vPC)->u.operand;
1926 JSValue* dividendValue = callFrame[dividend].jsValue(callFrame);
1927 JSValue* divisorValue = callFrame[divisor].jsValue(callFrame);
1929 if (JSImmediate::areBothImmediateNumbers(dividendValue, divisorValue) && divisorValue != JSImmediate::from(0)) {
1930 callFrame[dst] = JSImmediate::from(JSImmediate::getTruncatedInt32(dividendValue) % JSImmediate::getTruncatedInt32(divisorValue));
1935 double d = dividendValue->toNumber(callFrame);
1936 JSValue* result = jsNumber(callFrame, fmod(d, divisorValue->toNumber(callFrame)));
1937 CHECK_FOR_EXCEPTION();
1938 callFrame[dst] = result;
1942 DEFINE_OPCODE(op_sub) {
1943 /* sub dst(r) src1(r) src2(r)
1945 Subtracts register src2 (converted to number) from register
1946 src1 (converted to number), and puts the difference in
1949 int dst = (++vPC)->u.operand;
1950 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1951 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1954 if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1955 callFrame[dst] = JSImmediate::subImmediateNumbers(src1, src2);
1956 else if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1957 callFrame[dst] = jsNumber(callFrame, left - right);
1959 JSValue* result = jsNumber(callFrame, src1->toNumber(callFrame) - src2->toNumber(callFrame));
1960 CHECK_FOR_EXCEPTION();
1961 callFrame[dst] = result;
1966 DEFINE_OPCODE(op_lshift) {
1967 /* lshift dst(r) val(r) shift(r)
1969 Performs left shift of register val (converted to int32) by
1970 register shift (converted to uint32), and puts the result
1973 int dst = (++vPC)->u.operand;
1974 JSValue* val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1975 JSValue* shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
1978 if (JSImmediate::areBothImmediateNumbers(val, shift))
1979 callFrame[dst] = jsNumber(callFrame, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f));
1980 else if (fastToInt32(val, left) && fastToUInt32(shift, right))
1981 callFrame[dst] = jsNumber(callFrame, left << (right & 0x1f));
1983 JSValue* result = jsNumber(callFrame, (val->toInt32(callFrame)) << (shift->toUInt32(callFrame) & 0x1f));
1984 CHECK_FOR_EXCEPTION();
1985 callFrame[dst] = result;
1991 DEFINE_OPCODE(op_rshift) {
1992 /* rshift dst(r) val(r) shift(r)
1994 Performs arithmetic right shift of register val (converted
1995 to int32) by register shift (converted to
1996 uint32), and puts the result in register dst.
1998 int dst = (++vPC)->u.operand;
1999 JSValue* val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2000 JSValue* shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2003 if (JSImmediate::areBothImmediateNumbers(val, shift))
2004 callFrame[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
2005 else if (fastToInt32(val, left) && fastToUInt32(shift, right))
2006 callFrame[dst] = jsNumber(callFrame, left >> (right & 0x1f));
2008 JSValue* result = jsNumber(callFrame, (val->toInt32(callFrame)) >> (shift->toUInt32(callFrame) & 0x1f));
2009 CHECK_FOR_EXCEPTION();
2010 callFrame[dst] = result;
2016 DEFINE_OPCODE(op_urshift) {
2017 /* rshift dst(r) val(r) shift(r)
2019 Performs logical right shift of register val (converted
2020 to uint32) by register shift (converted to
2021 uint32), and puts the result in register dst.
2023 int dst = (++vPC)->u.operand;
2024 JSValue* val = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2025 JSValue* shift = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2026 if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
2027 callFrame[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
2029 JSValue* result = jsNumber(callFrame, (val->toUInt32(callFrame)) >> (shift->toUInt32(callFrame) & 0x1f));
2030 CHECK_FOR_EXCEPTION();
2031 callFrame[dst] = result;
2037 DEFINE_OPCODE(op_bitand) {
2038 /* bitand dst(r) src1(r) src2(r)
2040 Computes bitwise AND of register src1 (converted to int32)
2041 and register src2 (converted to int32), and puts the result
2044 int dst = (++vPC)->u.operand;
2045 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2046 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2049 if (JSImmediate::areBothImmediateNumbers(src1, src2))
2050 callFrame[dst] = JSImmediate::andImmediateNumbers(src1, src2);
2051 else if (fastToInt32(src1, left) && fastToInt32(src2, right))
2052 callFrame[dst] = jsNumber(callFrame, left & right);
2054 JSValue* result = jsNumber(callFrame, src1->toInt32(callFrame) & src2->toInt32(callFrame));
2055 CHECK_FOR_EXCEPTION();
2056 callFrame[dst] = result;
2062 DEFINE_OPCODE(op_bitxor) {
2063 /* bitxor dst(r) src1(r) src2(r)
2065 Computes bitwise XOR of register src1 (converted to int32)
2066 and register src2 (converted to int32), and puts the result
2069 int dst = (++vPC)->u.operand;
2070 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2071 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2074 if (JSImmediate::areBothImmediateNumbers(src1, src2))
2075 callFrame[dst] = JSImmediate::xorImmediateNumbers(src1, src2);
2076 else if (fastToInt32(src1, left) && fastToInt32(src2, right))
2077 callFrame[dst] = jsNumber(callFrame, left ^ right);
2079 JSValue* result = jsNumber(callFrame, src1->toInt32(callFrame) ^ src2->toInt32(callFrame));
2080 CHECK_FOR_EXCEPTION();
2081 callFrame[dst] = result;
2087 DEFINE_OPCODE(op_bitor) {
2088 /* bitor dst(r) src1(r) src2(r)
2090 Computes bitwise OR of register src1 (converted to int32)
2091 and register src2 (converted to int32), and puts the
2092 result in register dst.
2094 int dst = (++vPC)->u.operand;
2095 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2096 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2099 if (JSImmediate::areBothImmediateNumbers(src1, src2))
2100 callFrame[dst] = JSImmediate::orImmediateNumbers(src1, src2);
2101 else if (fastToInt32(src1, left) && fastToInt32(src2, right))
2102 callFrame[dst] = jsNumber(callFrame, left | right);
2104 JSValue* result = jsNumber(callFrame, src1->toInt32(callFrame) | src2->toInt32(callFrame));
2105 CHECK_FOR_EXCEPTION();
2106 callFrame[dst] = result;
2112 DEFINE_OPCODE(op_bitnot) {
2113 /* bitnot dst(r) src(r)
2115 Computes bitwise NOT of register src1 (converted to int32),
2116 and puts the result in register dst.
2118 int dst = (++vPC)->u.operand;
2119 JSValue* src = callFrame[(++vPC)->u.operand].jsValue(callFrame);
2121 if (fastToInt32(src, value))
2122 callFrame[dst] = jsNumber(callFrame, ~value);
2124 JSValue* result = jsNumber(callFrame, ~src->toInt32(callFrame));
2125 CHECK_FOR_EXCEPTION();
2126 callFrame[dst] = result;
2131 DEFINE_OPCODE(op_not) {
2132 /* not dst(r) src(r)
2134 Computes logical NOT of register src (converted to
2135 boolean), and puts the result in register dst.
2137 int dst = (++vPC)->u.operand;
2138 int src = (++vPC)->u.operand;
2139 JSValue* result = jsBoolean(!callFrame[src].jsValue(callFrame)->toBoolean(callFrame));
2140 CHECK_FOR_EXCEPTION();
2141 callFrame[dst] = result;
2146 DEFINE_OPCODE(op_instanceof) {
2147 /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
2149 Tests whether register value is an instance of register
2150 constructor, and puts the boolean result in register
2151 dst. Register constructorProto must contain the "prototype"
2152 property (not the actual prototype) of the object in
2153 register constructor. This lookup is separated so that
2154 polymorphic inline caching can apply.
2156 Raises an exception if register constructor is not an
2159 int dst = vPC[1].u.operand;
2160 int value = vPC[2].u.operand;
2161 int base = vPC[3].u.operand;
2162 int baseProto = vPC[4].u.operand;
2164 JSValue* baseVal = callFrame[base].jsValue(callFrame);
2166 if (isNotObject(callFrame, true, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
2169 JSObject* baseObj = asObject(baseVal);
2170 callFrame[dst] = jsBoolean(baseObj->structure()->typeInfo().implementsHasInstance() ? baseObj->hasInstance(callFrame, callFrame[value].jsValue(callFrame), callFrame[baseProto].jsValue(callFrame)) : false);
2175 DEFINE_OPCODE(op_typeof) {
2176 /* typeof dst(r) src(r)
2178 Determines the type string for src according to ECMAScript
2179 rules, and puts the result in register dst.
2181 int dst = (++vPC)->u.operand;
2182 int src = (++vPC)->u.operand;
2183 callFrame[dst] = jsTypeStringForValue(callFrame, callFrame[src].jsValue(callFrame));
2188 DEFINE_OPCODE(op_is_undefined) {
2189 /* is_undefined dst(r) src(r)
2191 Determines whether the type string for src according to
2192 the ECMAScript rules is "undefined", and puts the result
2195 int dst = (++vPC)->u.operand;
2196 int src = (++vPC)->u.operand;
2197 JSValue* v = callFrame[src].jsValue(callFrame);
2198 callFrame[dst] = jsBoolean(JSImmediate::isImmediate(v) ? v->isUndefined() : v->asCell()->structure()->typeInfo().masqueradesAsUndefined());
2203 DEFINE_OPCODE(op_is_boolean) {
2204 /* is_boolean dst(r) src(r)
2206 Determines whether the type string for src according to
2207 the ECMAScript rules is "boolean", and puts the result
2210 int dst = (++vPC)->u.operand;
2211 int src = (++vPC)->u.operand;
2212 callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame)->isBoolean());
2217 DEFINE_OPCODE(op_is_number) {
2218 /* is_number dst(r) src(r)
2220 Determines whether the type string for src according to
2221 the ECMAScript rules is "number", and puts the result
2224 int dst = (++vPC)->u.operand;
2225 int src = (++vPC)->u.operand;
2226 callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame)->isNumber());
2231 DEFINE_OPCODE(op_is_string) {
2232 /* is_string dst(r) src(r)
2234 Determines whether the type string for src according to
2235 the ECMAScript rules is "string", and puts the result
2238 int dst = (++vPC)->u.operand;
2239 int src = (++vPC)->u.operand;
2240 callFrame[dst] = jsBoolean(callFrame[src].jsValue(callFrame)->isString());
2245 DEFINE_OPCODE(op_is_object) {
2246 /* is_object dst(r) src(r)
2248 Determines whether the type string for src according to
2249 the ECMAScript rules is "object", and puts the result
2252 int dst = (++vPC)->u.operand;
2253 int src = (++vPC)->u.operand;
2254 callFrame[dst] = jsBoolean(jsIsObjectType(callFrame[src].jsValue(callFrame)));
2259 DEFINE_OPCODE(op_is_function) {
2260 /* is_function dst(r) src(r)
2262 Determines whether the type string for src according to
2263 the ECMAScript rules is "function", and puts the result
2266 int dst = (++vPC)->u.operand;
2267 int src = (++vPC)->u.operand;
2268 callFrame[dst] = jsBoolean(jsIsFunctionType(callFrame[src].jsValue(callFrame)));
2273 DEFINE_OPCODE(op_in) {
2274 /* in dst(r) property(r) base(r)
2276 Tests whether register base has a property named register
2277 property, and puts the boolean result in register dst.
2279 Raises an exception if register constructor is not an
2282 int dst = (++vPC)->u.operand;
2283 int property = (++vPC)->u.operand;
2284 int base = (++vPC)->u.operand;
2286 JSValue* baseVal = callFrame[base].jsValue(callFrame);
2287 if (isNotObject(callFrame, false, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
2290 JSObject* baseObj = asObject(baseVal);
2292 JSValue* propName = callFrame[property].jsValue(callFrame);
2295 if (propName->getUInt32(i))
2296 callFrame[dst] = jsBoolean(baseObj->hasProperty(callFrame, i));
2298 Identifier property(callFrame, propName->toString(callFrame));
2299 CHECK_FOR_EXCEPTION();
2300 callFrame[dst] = jsBoolean(baseObj->hasProperty(callFrame, property));
2306 DEFINE_OPCODE(op_resolve) {
2307 /* resolve dst(r) property(id)
2309 Looks up the property named by identifier property in the
2310 scope chain, and writes the resulting value to register
2311 dst. If the property is not found, raises an exception.
2313 if (UNLIKELY(!resolve(callFrame, vPC, exceptionValue)))
2319 DEFINE_OPCODE(op_resolve_skip) {
2320 /* resolve_skip dst(r) property(id) skip(n)
2322 Looks up the property named by identifier property in the
2323 scope chain skipping the top 'skip' levels, and writes the resulting
2324 value to register dst. If the property is not found, raises an exception.
2326 if (UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue)))
2333 DEFINE_OPCODE(op_resolve_global) {
2334 /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n)
2336 Performs a dynamic property lookup for the given property, on the provided
2337 global object. If structure matches the Structure of the global then perform
2338 a fast lookup using the case offset, otherwise fall back to a full resolve and
2339 cache the new structure and offset
2341 if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue)))
2348 DEFINE_OPCODE(op_get_global_var) {
2349 /* get_global_var dst(r) globalObject(c) index(n)
2351 Gets the global var at global slot index and places it in register dst.
2353 int dst = (++vPC)->u.operand;
2354 JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
2355 ASSERT(scope->isGlobalObject());
2356 int index = (++vPC)->u.operand;
2358 callFrame[dst] = scope->registerAt(index);
2362 DEFINE_OPCODE(op_put_global_var) {
2363 /* put_global_var globalObject(c) index(n) value(r)
2365 Puts value into global slot index.
2367 JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
2368 ASSERT(scope->isGlobalObject());
2369 int index = (++vPC)->u.operand;
2370 int value = (++vPC)->u.operand;
2372 scope->registerAt(index) = callFrame[value].jsValue(callFrame);
2376 DEFINE_OPCODE(op_get_scoped_var) {
2377 /* get_scoped_var dst(r) index(n) skip(n)
2379 Loads the contents of the index-th local from the scope skip nodes from
2380 the top of the scope chain, and places it in register dst
2382 int dst = (++vPC)->u.operand;
2383 int index = (++vPC)->u.operand;
2384 int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain();
2386 ScopeChainNode* scopeChain = callFrame->scopeChain();
2387 ScopeChainIterator iter = scopeChain->begin();
2388 ScopeChainIterator end = scopeChain->end();
2389 ASSERT(iter != end);
2392 ASSERT(iter != end);
2395 ASSERT((*iter)->isVariableObject());
2396 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2397 callFrame[dst] = scope->registerAt(index);
2401 DEFINE_OPCODE(op_put_scoped_var) {
2402 /* put_scoped_var index(n) skip(n) value(r)
2405 int index = (++vPC)->u.operand;
2406 int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain();
2407 int value = (++vPC)->u.operand;
2409 ScopeChainNode* scopeChain = callFrame->scopeChain();
2410 ScopeChainIterator iter = scopeChain->begin();
2411 ScopeChainIterator end = scopeChain->end();
2412 ASSERT(iter != end);
2415 ASSERT(iter != end);
2418 ASSERT((*iter)->isVariableObject());
2419 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2420 scope->registerAt(index) = callFrame[value].jsValue(callFrame);
2424 DEFINE_OPCODE(op_resolve_base) {
2425 /* resolve_base dst(r) property(id)
2427 Searches the scope chain for an object containing
2428 identifier property, and if one is found, writes it to
2429 register dst. If none is found, the outermost scope (which
2430 will be the global object) is stored in register dst.
2432 resolveBase(callFrame, vPC);
2437 DEFINE_OPCODE(op_resolve_with_base) {
2438 /* resolve_with_base baseDst(r) propDst(r) property(id)
2440 Searches the scope chain for an object containing
2441 identifier property, and if one is found, writes it to
2442 register srcDst, and the retrieved property value to register
2443 propDst. If the property is not found, raises an exception.
2445 This is more efficient than doing resolve_base followed by
2446 resolve, or resolve_base followed by get_by_id, as it
2447 avoids duplicate hash lookups.
2449 if (UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue)))
2455 DEFINE_OPCODE(op_resolve_func) {
2456 /* resolve_func baseDst(r) funcDst(r) property(id)
2458 Searches the scope chain for an object containing
2459 identifier property, and if one is found, writes the
2460 appropriate object to use as "this" when calling its
2461 properties to register baseDst; and the retrieved property
2462 value to register propDst. If the property is not found,
2463 raises an exception.
2465 This differs from resolve_with_base, because the
2466 global this value will be substituted for activations or
2467 the global object, which is the right behavior for function
2468 calls but not for other property lookup.
2470 if (UNLIKELY(!resolveBaseAndFunc(callFrame, vPC, exceptionValue)))
2476 DEFINE_OPCODE(op_get_by_id) {
2477 /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n)
2479 Generic property access: Gets the property named by identifier
2480 property from the value base, and puts the result in register dst.
2482 int dst = vPC[1].u.operand;
2483 int base = vPC[2].u.operand;
2484 int property = vPC[3].u.operand;
2486 CodeBlock* codeBlock = callFrame->codeBlock();
2487 Identifier& ident = codeBlock->identifier(property);
2488 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2489 PropertySlot slot(baseValue);
2490 JSValue* result = baseValue->get(callFrame, ident, slot);
2491 CHECK_FOR_EXCEPTION();
2493 tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
2495 callFrame[dst] = result;
2499 DEFINE_OPCODE(op_get_by_id_self) {
2500 /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
2502 Cached property access: Attempts to get a cached property from the
2503 value base. If the cache misses, op_get_by_id_self reverts to
2506 int base = vPC[2].u.operand;
2507 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2509 if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2510 JSCell* baseCell = asCell(baseValue);
2511 Structure* structure = vPC[4].u.structure;
2513 if (LIKELY(baseCell->structure() == structure)) {
2514 ASSERT(baseCell->isObject());
2515 JSObject* baseObject = asObject(baseCell);
2516 int dst = vPC[1].u.operand;
2517 int offset = vPC[5].u.operand;
2519 ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
2520 callFrame[dst] = baseObject->getDirectOffset(offset);
2527 uncacheGetByID(callFrame->codeBlock(), vPC);
2530 DEFINE_OPCODE(op_get_by_id_proto) {
2531 /* op_get_by_id_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
2533 Cached property access: Attempts to get a cached property from the
2534 value base's prototype. If the cache misses, op_get_by_id_proto
2535 reverts to op_get_by_id.
2537 int base = vPC[2].u.operand;
2538 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2540 if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2541 JSCell* baseCell = asCell(baseValue);
2542 Structure* structure = vPC[4].u.structure;
2544 if (LIKELY(baseCell->structure() == structure)) {
2545 ASSERT(structure->prototypeForLookup(callFrame)->isObject());
2546 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
2547 Structure* prototypeStructure = vPC[5].u.structure;
2549 if (LIKELY(protoObject->structure() == prototypeStructure)) {
2550 int dst = vPC[1].u.operand;
2551 int offset = vPC[6].u.operand;
2553 ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
2554 callFrame[dst] = protoObject->getDirectOffset(offset);
2562 uncacheGetByID(callFrame->codeBlock(), vPC);
2565 DEFINE_OPCODE(op_get_by_id_self_list) {
2566 // Polymorphic self access caching currently only supported when JITting.
2567 ASSERT_NOT_REACHED();
2568 // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
2572 DEFINE_OPCODE(op_get_by_id_proto_list) {
2573 // Polymorphic prototype access caching currently only supported when JITting.
2574 ASSERT_NOT_REACHED();
2575 // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
2579 DEFINE_OPCODE(op_get_by_id_chain) {
2580 /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
2582 Cached property access: Attempts to get a cached property from the
2583 value base's prototype chain. If the cache misses, op_get_by_id_chain
2584 reverts to op_get_by_id.
2586 int base = vPC[2].u.operand;
2587 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2589 if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2590 JSCell* baseCell = asCell(baseValue);
2591 Structure* structure = vPC[4].u.structure;
2593 if (LIKELY(baseCell->structure() == structure)) {
2594 RefPtr<Structure>* it = vPC[5].u.structureChain->head();
2595 size_t count = vPC[6].u.operand;
2596 RefPtr<Structure>* end = it + count;
2598 JSObject* baseObject = asObject(baseCell);
2600 baseObject = asObject(baseObject->structure()->prototypeForLookup(callFrame));
2601 if (UNLIKELY(baseObject->structure() != (*it).get()))
2605 int dst = vPC[1].u.operand;
2606 int offset = vPC[7].u.operand;
2608 ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
2609 callFrame[dst] = baseObject->getDirectOffset(offset);
2618 uncacheGetByID(callFrame->codeBlock(), vPC);
2621 DEFINE_OPCODE(op_get_by_id_generic) {
2622 /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2624 Generic property access: Gets the property named by identifier
2625 property from the value base, and puts the result in register dst.
2627 int dst = vPC[1].u.operand;
2628 int base = vPC[2].u.operand;
2629 int property = vPC[3].u.operand;
2631 Identifier& ident = callFrame->codeBlock()->identifier(property);
2632 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2633 PropertySlot slot(baseValue);
2634 JSValue* result = baseValue->get(callFrame, ident, slot);
2635 CHECK_FOR_EXCEPTION();
2637 callFrame[dst] = result;
2641 DEFINE_OPCODE(op_get_array_length) {
2642 /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2644 Cached property access: Gets the length of the array in register base,
2645 and puts the result in register dst. If register base does not hold
2646 an array, op_get_array_length reverts to op_get_by_id.
2649 int base = vPC[2].u.operand;
2650 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2651 if (LIKELY(isJSArray(baseValue))) {
2652 int dst = vPC[1].u.operand;
2653 callFrame[dst] = jsNumber(callFrame, asArray(baseValue)->length());
2658 uncacheGetByID(callFrame->codeBlock(), vPC);
2661 DEFINE_OPCODE(op_get_string_length) {
2662 /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2664 Cached property access: Gets the length of the string in register base,
2665 and puts the result in register dst. If register base does not hold
2666 a string, op_get_string_length reverts to op_get_by_id.
2669 int base = vPC[2].u.operand;
2670 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2671 if (LIKELY(isJSString(baseValue))) {
2672 int dst = vPC[1].u.operand;
2673 callFrame[dst] = jsNumber(callFrame, asString(baseValue)->value().size());
2678 uncacheGetByID(callFrame->codeBlock(), vPC);
2681 DEFINE_OPCODE(op_put_by_id) {
2682 /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
2684 Generic property access: Sets the property named by identifier
2685 property, belonging to register base, to register value.
2687 Unlike many opcodes, this one does not write any output to
2691 int base = vPC[1].u.operand;
2692 int property = vPC[2].u.operand;
2693 int value = vPC[3].u.operand;
2695 CodeBlock* codeBlock = callFrame->codeBlock();
2696 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2697 Identifier& ident = codeBlock->identifier(property);
2698 PutPropertySlot slot;
2699 baseValue->put(callFrame, ident, callFrame[value].jsValue(callFrame), slot);
2700 CHECK_FOR_EXCEPTION();
2702 tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
2707 DEFINE_OPCODE(op_put_by_id_transition) {
2708 /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n)
2710 Cached property access: Attempts to set a new property with a cached transition
2711 property named by identifier property, belonging to register base,
2712 to register value. If the cache misses, op_put_by_id_transition
2713 reverts to op_put_by_id_generic.
2715 Unlike many opcodes, this one does not write any output to
2718 int base = vPC[1].u.operand;
2719 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2721 if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2722 JSCell* baseCell = asCell(baseValue);
2723 Structure* oldStructure = vPC[4].u.structure;
2724 Structure* newStructure = vPC[5].u.structure;
2726 if (LIKELY(baseCell->structure() == oldStructure)) {
2727 ASSERT(baseCell->isObject());
2728 JSObject* baseObject = asObject(baseCell);
2730 RefPtr<Structure>* it = vPC[6].u.structureChain->head();
2732 JSValue* proto = baseObject->structure()->prototypeForLookup(callFrame);
2733 while (!proto->isNull()) {
2734 if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
2735 uncachePutByID(callFrame->codeBlock(), vPC);
2739 proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
2742 baseObject->transitionTo(newStructure);
2744 int value = vPC[3].u.operand;
2745 unsigned offset = vPC[7].u.operand;
2746 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
2747 baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame));
2754 uncachePutByID(callFrame->codeBlock(), vPC);
2757 DEFINE_OPCODE(op_put_by_id_replace) {
2758 /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n)
2760 Cached property access: Attempts to set a pre-existing, cached
2761 property named by identifier property, belonging to register base,
2762 to register value. If the cache misses, op_put_by_id_replace
2763 reverts to op_put_by_id.
2765 Unlike many opcodes, this one does not write any output to
2768 int base = vPC[1].u.operand;
2769 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2771 if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2772 JSCell* baseCell = asCell(baseValue);
2773 Structure* structure = vPC[4].u.structure;
2775 if (LIKELY(baseCell->structure() == structure)) {
2776 ASSERT(baseCell->isObject());
2777 JSObject* baseObject = asObject(baseCell);
2778 int value = vPC[3].u.operand;
2779 unsigned offset = vPC[5].u.operand;
2781 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
2782 baseObject->putDirectOffset(offset, callFrame[value].jsValue(callFrame));
2789 uncachePutByID(callFrame->codeBlock(), vPC);
2792 DEFINE_OPCODE(op_put_by_id_generic) {
2793 /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
2795 Generic property access: Sets the property named by identifier
2796 property, belonging to register base, to register value.
2798 Unlike many opcodes, this one does not write any output to
2801 int base = vPC[1].u.operand;
2802 int property = vPC[2].u.operand;
2803 int value = vPC[3].u.operand;
2805 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2806 Identifier& ident = callFrame->codeBlock()->identifier(property);
2807 PutPropertySlot slot;
2808 baseValue->put(callFrame, ident, callFrame[value].jsValue(callFrame), slot);
2809 CHECK_FOR_EXCEPTION();
2814 DEFINE_OPCODE(op_del_by_id) {
2815 /* del_by_id dst(r) base(r) property(id)
2817 Converts register base to Object, deletes the property
2818 named by identifier property from the object, and writes a
2819 boolean indicating success (if true) or failure (if false)
2822 int dst = (++vPC)->u.operand;
2823 int base = (++vPC)->u.operand;
2824 int property = (++vPC)->u.operand;
2826 JSObject* baseObj = callFrame[base].jsValue(callFrame)->toObject(callFrame);
2827 Identifier& ident = callFrame->codeBlock()->identifier(property);
2828 JSValue* result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
2829 CHECK_FOR_EXCEPTION();
2830 callFrame[dst] = result;
2834 DEFINE_OPCODE(op_get_by_val) {
2835 /* get_by_val dst(r) base(r) property(r)
2837 Converts register base to Object, gets the property named
2838 by register property from the object, and puts the result
2839 in register dst. property is nominally converted to string
2840 but numbers are treated more efficiently.
2842 int dst = (++vPC)->u.operand;
2843 int base = (++vPC)->u.operand;
2844 int property = (++vPC)->u.operand;
2846 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2847 JSValue* subscript = callFrame[property].jsValue(callFrame);
2852 bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2853 if (LIKELY(isUInt32)) {
2854 if (isJSArray(baseValue)) {
2855 JSArray* jsArray = asArray(baseValue);
2856 if (jsArray->canGetIndex(i))
2857 result = jsArray->getIndex(i);
2859 result = jsArray->JSArray::get(callFrame, i);
2860 } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
2861 result = asString(baseValue)->getIndex(&callFrame->globalData(), i);
2862 else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i))
2863 result = asByteArray(baseValue)->getIndex(i);
2865 result = baseValue->get(callFrame, i);
2867 Identifier property(callFrame, subscript->toString(callFrame));
2868 result = baseValue->get(callFrame, property);
2871 CHECK_FOR_EXCEPTION();
2872 callFrame[dst] = result;
2876 DEFINE_OPCODE(op_put_by_val) {
2877 /* put_by_val base(r) property(r) value(r)
2879 Sets register value on register base as the property named
2880 by register property. Base is converted to object
2881 first. register property is nominally converted to string
2882 but numbers are treated more efficiently.
2884 Unlike many opcodes, this one does not write any output to
2887 int base = (++vPC)->u.operand;
2888 int property = (++vPC)->u.operand;
2889 int value = (++vPC)->u.operand;
2891 JSValue* baseValue = callFrame[base].jsValue(callFrame);
2892 JSValue* subscript = callFrame[property].jsValue(callFrame);
2896 bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2897 if (LIKELY(isUInt32)) {
2898 if (isJSArray(baseValue)) {
2899 JSArray* jsArray = asArray(baseValue);
2900 if (jsArray->canSetIndex(i))
2901 jsArray->setIndex(i, callFrame[value].jsValue(callFrame));
2903 jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue(callFrame));
2904 } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
2905 JSByteArray* jsByteArray = asByteArray(baseValue);
2907 JSValue* jsValue = callFrame[value].jsValue(callFrame);
2908 if (JSImmediate::isNumber(jsValue))
2909 jsByteArray->setIndex(i, JSImmediate::getTruncatedInt32(jsValue));
2910 else if (fastIsNumber(jsValue, dValue))
2911 jsByteArray->setIndex(i, dValue);
2913 baseValue->put(callFrame, i, jsValue);
2915 baseValue->put(callFrame, i, callFrame[value].jsValue(callFrame));
2917 Identifier property(callFrame, subscript->toString(callFrame));
2918 if (!globalData->exception) { // Don't put to an object if toString threw an exception.
2919 PutPropertySlot slot;
2920 baseValue->put(callFrame, property, callFrame[value].jsValue(callFrame), slot);
2924 CHECK_FOR_EXCEPTION();
2928 DEFINE_OPCODE(op_del_by_val) {
2929 /* del_by_val dst(r) base(r) property(r)
2931 Converts register base to Object, deletes the property
2932 named by register property from the object, and writes a
2933 boolean indicating success (if true) or failure (if false)
2936 int dst = (++vPC)->u.operand;
2937 int base = (++vPC)->u.operand;
2938 int property = (++vPC)->u.operand;
2940 JSObject* baseObj = callFrame[base].jsValue(callFrame)->toObject(callFrame); // may throw
2942 JSValue* subscript = callFrame[property].jsValue(callFrame);
2945 if (subscript->getUInt32(i))
2946 result = jsBoolean(baseObj->deleteProperty(callFrame, i));
2948 CHECK_FOR_EXCEPTION();
2949 Identifier property(callFrame, subscript->toString(callFrame));
2950 CHECK_FOR_EXCEPTION();
2951 result = jsBoolean(baseObj->deleteProperty(callFrame, property));
2954 CHECK_FOR_EXCEPTION();
2955 callFrame[dst] = result;
2959 DEFINE_OPCODE(op_put_by_index) {
2960 /* put_by_index base(r) property(n) value(r)
2962 Sets register value on register base as the property named
2963 by the immediate number property. Base is converted to
2966 Unlike many opcodes, this one does not write any output to
2969 This opcode is mainly used to initialize array literals.
2971 int base = (++vPC)->u.operand;
2972 unsigned property = (++vPC)->u.operand;
2973 int value = (++vPC)->u.operand;
2975 callFrame[base].jsValue(callFrame)->put(callFrame, property, callFrame[value].jsValue(callFrame));
2980 DEFINE_OPCODE(op_loop) {
2981 /* loop target(offset)
2983 Jumps unconditionally to offset target from the current
2986 Additionally this loop instruction may terminate JS execution is
2987 the JS timeout is reached.
2989 #if ENABLE(OPCODE_STATS)
2990 OpcodeStats::resetLastInstruction();
2992 int target = (++vPC)->u.operand;
2993 CHECK_FOR_TIMEOUT();
2997 DEFINE_OPCODE(op_jmp) {
2998 /* jmp target(offset)
3000 Jumps unconditionally to offset target from the current
3003 #if ENABLE(OPCODE_STATS)
3004 OpcodeStats::resetLastInstruction();
3006 int target = (++vPC)->u.operand;
3011 DEFINE_OPCODE(op_loop_if_true) {
3012 /* loop_if_true cond(r) target(offset)
3014 Jumps to offset target from the current instruction, if and
3015 only if register cond converts to boolean as true.
3017 Additionally this loop instruction may terminate JS execution is
3018 the JS timeout is reached.
3020 int cond = (++vPC)->u.operand;
3021 int target = (++vPC)->u.operand;
3022 if (callFrame[cond].jsValue(callFrame)->toBoolean(callFrame)) {
3024 CHECK_FOR_TIMEOUT();
3031 DEFINE_OPCODE(op_jtrue) {
3032 /* jtrue cond(r) target(offset)
3034 Jumps to offset target from the current instruction, if and
3035 only if register cond converts to boolean as true.
3037 int cond = (++vPC)->u.operand;
3038 int target = (++vPC)->u.operand;
3039 if (callFrame[cond].jsValue(callFrame)->toBoolean(callFrame)) {
3047 DEFINE_OPCODE(op_jfalse) {
3048 /* jfalse cond(r) target(offset)
3050 Jumps to offset target from the current instruction, if and
3051 only if register cond converts to boolean as false.
3053 int cond = (++vPC)->u.operand;
3054 int target = (++vPC)->u.operand;
3055 if (!callFrame[cond].jsValue(callFrame)->toBoolean(callFrame)) {
3063 DEFINE_OPCODE(op_jeq_null) {
3064 /* jeq_null src(r) target(offset)
3066 Jumps to offset target from the current instruction, if and
3067 only if register src is null.
3069 int src = (++vPC)->u.operand;
3070 int target = (++vPC)->u.operand;
3071 JSValue* srcValue = callFrame[src].jsValue(callFrame);
3073 if (srcValue->isUndefinedOrNull() || (!JSImmediate::isImmediate(srcValue) && srcValue->asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
3081 DEFINE_OPCODE(op_jneq_null) {
3082 /* jneq_null src(r) target(offset)
3084 Jumps to offset target from the current instruction, if and
3085 only if register src is not null.
3087 int src = (++vPC)->u.operand;
3088 int target = (++vPC)->u.operand;
3089 JSValue* srcValue = callFrame[src].jsValue(callFrame);
3091 if (!srcValue->isUndefinedOrNull() || (!JSImmediate::isImmediate(srcValue) && !srcValue->asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
3099 DEFINE_OPCODE(op_loop_if_less) {
3100 /* loop_if_less src1(r) src2(r) target(offset)
3102 Checks whether register src1 is less than register src2, as
3103 with the ECMAScript '<' operator, and then jumps to offset
3104 target from the current instruction, if and only if the
3105 result of the comparison is true.
3107 Additionally this loop instruction may terminate JS execution is
3108 the JS timeout is reached.
3110 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3111 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3112 int target = (++vPC)->u.operand;
3114 bool result = jsLess(callFrame, src1, src2);
3115 CHECK_FOR_EXCEPTION();
3119 CHECK_FOR_TIMEOUT();
3126 DEFINE_OPCODE(op_loop_if_lesseq) {
3127 /* loop_if_lesseq src1(r) src2(r) target(offset)
3129 Checks whether register src1 is less than or equal to register
3130 src2, as with the ECMAScript '<=' operator, and then jumps to
3131 offset target from the current instruction, if and only if the
3132 result of the comparison is true.
3134 Additionally this loop instruction may terminate JS execution is
3135 the JS timeout is reached.
3137 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3138 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3139 int target = (++vPC)->u.operand;
3141 bool result = jsLessEq(callFrame, src1, src2);
3142 CHECK_FOR_EXCEPTION();
3146 CHECK_FOR_TIMEOUT();
3153 DEFINE_OPCODE(op_jnless) {
3154 /* jnless src1(r) src2(r) target(offset)
3156 Checks whether register src1 is less than register src2, as
3157 with the ECMAScript '<' operator, and then jumps to offset
3158 target from the current instruction, if and only if the
3159 result of the comparison is false.
3161 JSValue* src1 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3162 JSValue* src2 = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3163 int target = (++vPC)->u.operand;
3165 bool result = jsLess(callFrame, src1, src2);
3166 CHECK_FOR_EXCEPTION();
3176 DEFINE_OPCODE(op_switch_imm) {
3177 /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
3179 Performs a range checked switch on the scrutinee value, using
3180 the tableIndex-th immediate switch jump table. If the scrutinee value
3181 is an immediate number in the range covered by the referenced jump
3182 table, and the value at jumpTable[scrutinee value] is non-zero, then
3183 that value is used as the jump offset, otherwise defaultOffset is used.
3185 int tableIndex = (++vPC)->u.operand;
3186 int defaultOffset = (++vPC)->u.operand;
3187 JSValue* scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3188 if (!JSImmediate::isNumber(scrutinee))
3189 vPC += defaultOffset;
3191 int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
3192 vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(value, defaultOffset);
3196 DEFINE_OPCODE(op_switch_char) {
3197 /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
3199 Performs a range checked switch on the scrutinee value, using
3200 the tableIndex-th character switch jump table. If the scrutinee value
3201 is a single character string in the range covered by the referenced jump
3202 table, and the value at jumpTable[scrutinee value] is non-zero, then
3203 that value is used as the jump offset, otherwise defaultOffset is used.
3205 int tableIndex = (++vPC)->u.operand;
3206 int defaultOffset = (++vPC)->u.operand;
3207 JSValue* scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3208 if (!scrutinee->isString())
3209 vPC += defaultOffset;
3211 UString::Rep* value = asString(scrutinee)->value().rep();
3212 if (value->size() != 1)
3213 vPC += defaultOffset;
3215 vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->data()[0], defaultOffset);
3219 DEFINE_OPCODE(op_switch_string) {
3220 /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
3222 Performs a sparse hashmap based switch on the value in the scrutinee
3223 register, using the tableIndex-th string switch jump table. If the
3224 scrutinee value is a string that exists as a key in the referenced
3225 jump table, then the value associated with the string is used as the
3226 jump offset, otherwise defaultOffset is used.
3228 int tableIndex = (++vPC)->u.operand;
3229 int defaultOffset = (++vPC)->u.operand;
3230 JSValue* scrutinee = callFrame[(++vPC)->u.operand].jsValue(callFrame);
3231 if (!scrutinee->isString())
3232 vPC += defaultOffset;
3234 vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value().rep(), defaultOffset);
3237 DEFINE_OPCODE(op_new_func) {
3238 /* new_func dst(r) func(f)
3240 Constructs a new Function instance from function func and
3241 the current scope chain using the original Function
3242 constructor, using the rules for function declarations, and
3243 puts the result in register dst.
3245 int dst = (++vPC)->u.operand;
3246 int func = (++vPC)->u.operand;
3248 callFrame[dst] = callFrame->codeBlock()->function(func)->makeFunction(callFrame, callFrame->scopeChain());
3253 DEFINE_OPCODE(op_new_func_exp) {
3254 /* new_func_exp dst(r) func(f)
3256 Constructs a new Function instance from function func and
3257 the current scope chain using the original Function
3258 constructor, using the rules for function expressions, and
3259 puts the result in register dst.
3261 int dst = (++vPC)->u.operand;
3262 int func = (++vPC)->u.operand;
3264 callFrame[dst] = callFrame->codeBlock()->functionExpression(func)->makeFunction(callFrame, callFrame->scopeChain());
3269 DEFINE_OPCODE(op_call_eval) {
3270 /* call_eval dst(r) func(r) argCount(n) registerOffset(n)
3272 Call a function named "eval" with no explicit "this" value
3273 (which may therefore be the eval operator). If register
3274 thisVal is the global object, and register func contains
3275 that global object's original global eval function, then
3276 perform the eval operator in local scope (interpreting
3277 the argument registers as for the "call"
3278 opcode). Otherwise, act exactly as the "call" opcode would.
3281 int dst = vPC[1].u.operand;
3282 int func = vPC[2].u.operand;
3283 int argCount = vPC[3].u.operand;
3284 int registerOffset = vPC[4].u.operand;
3286 JSValue* funcVal = callFrame[func].jsValue(callFrame);
3288 Register* newCallFrame = callFrame->registers() + registerOffset;
3289 Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
3290 JSValue* thisValue = argv[0].jsValue(callFrame);
3291 JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
3293 if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
3294 JSValue* result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
3297 callFrame[dst] = result;
3303 // We didn't find the blessed version of eval, so process this
3304 // instruction as a normal function call.
3305 // fall through to op_call
3307 DEFINE_OPCODE(op_call) {
3308 /* call dst(r) func(r) argCount(n) registerOffset(n)
3310 Perform a function call.
3312 registerOffset is the distance the callFrame pointer should move
3313 before the VM initializes the new call frame's header.
3315 dst is where op_ret should store its result.
3318 int dst = vPC[1].u.operand;
3319 int func = vPC[2].u.operand;
3320 int argCount = vPC[3].u.operand;
3321 int registerOffset = vPC[4].u.operand;
3323 JSValue* v = callFrame[func].jsValue(callFrame);
3326 CallType callType = v->getCallData(callData);
3328 if (callType == CallTypeJS) {
3329 ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
3330 FunctionBodyNode* functionBodyNode = callData.js.functionBody;
3331 CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
3333 CallFrame* previousCallFrame = callFrame;
3335 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
3336 if (UNLIKELY(!callFrame)) {
3337 callFrame = previousCallFrame;
3338 exceptionValue = createStackOverflowError(callFrame);
3342 callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
3343 vPC = newCodeBlock->instructions().begin();
3345 #if ENABLE(OPCODE_STATS)
3346 OpcodeStats::resetLastInstruction();
3352 if (callType == CallTypeHost) {
3353 ScopeChainNode* scopeChain = callFrame->scopeChain();
3354 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
3355 newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0);
3357 Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
3358 ArgList args(thisRegister + 1, argCount - 1);
3360 // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
3361 JSValue* thisValue = thisRegister->jsValue(callFrame);
3362 if (thisValue == jsNull())
3363 thisValue = callFrame->globalThisValue();
3365 JSValue* returnValue;
3367 SamplingTool::HostCallRecord callRecord(m_sampler);
3368 returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
3370 CHECK_FOR_EXCEPTION();
3372 callFrame[dst] = returnValue;
3378 ASSERT(callType == CallTypeNone);
3380 exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
3383 DEFINE_OPCODE(op_tear_off_activation) {
3384 /* tear_off_activation activation(r)
3386 Copy all locals and parameters to new memory allocated on
3387 the heap, and make the passed activation use this memory
3388 in the future when looking up entries in the symbol table.
3389 If there is an 'arguments' object, then it will also use
3390 this memory for storing the named parameters, but not any
3393 This opcode should only be used immediately before op_ret.
3396 int src = (++vPC)->u.operand;
3397 ASSERT(callFrame->codeBlock()->needsFullScopeChain());
3399 asActivation(callFrame[src].getJSValue())->copyRegisters(callFrame->optionalCalleeArguments());
3404 DEFINE_OPCODE(op_tear_off_arguments) {
3405 /* tear_off_arguments
3407 Copy all arguments to new memory allocated on the heap,
3408 and make the 'arguments' object use this memory in the
3409 future when looking up named parameters, but not any
3410 extra arguments. If an activation object exists for the
3411 current function context, then the tear_off_activation
3412 opcode should be used instead.
3414 This opcode should only be used immediately before op_ret.
3417 ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
3419 callFrame->optionalCalleeArguments()->copyRegisters();
3424 DEFINE_OPCODE(op_ret) {
3427 Return register result as the return value of the current
3428 function call, writing it into the caller's expected return
3429 value register. In addition, unwind one call frame and
3430 restore the scope chain, code block instruction pointer and
3431 register base to those of the calling function.
3434 int result = (++vPC)->u.operand;
3436 if (callFrame->codeBlock()->needsFullScopeChain())
3437 callFrame->scopeChain()->deref();
3439 JSValue* returnValue = callFrame[result].jsValue(callFrame);
3441 vPC = callFrame->returnPC();
3442 int dst = callFrame->returnValueRegister();
3443 callFrame = callFrame->callerFrame();
3445 if (callFrame->hasHostCallFrameFlag())
3448 callFrame[dst] = returnValue;
3452 DEFINE_OPCODE(op_enter) {
3455 Initializes local variables to undefined and fills constant
3456 registers with their values. If the code block requires an
3457 activation, enter_with_activation should be used instead.
3459 This opcode should only be used at the beginning of a code
3464 CodeBlock* codeBlock = callFrame->codeBlock();
3466 for (size_t count = codeBlock->m_numVars; i < count; ++i)
3467 callFrame[i] = jsUndefined();
3469 for (size_t count = codeBlock->numberOfConstantRegisters(), j = 0; j < count; ++i, ++j)
3470 callFrame[i] = codeBlock->constantRegister(j);
3475 DEFINE_OPCODE(op_enter_with_activation) {
3476 /* enter_with_activation dst(r)
3478 Initializes local variables to undefined, fills constant
3479 registers with their values, creates an activation object,
3480 and places the new activation both in dst and at the top
3481 of the scope chain. If the code block does not require an
3482 activation, enter should be used instead.
3484 This opcode should only be used at the beginning of a code
3489 CodeBlock* codeBlock = callFrame->codeBlock();
3491 for (size_t count = codeBlock->m_numVars; i < count; ++i)
3492 callFrame[i] = jsUndefined();
3494 for (size_t count = codeBlock->numberOfConstantRegisters(), j = 0; j < count; ++i, ++j)
3495 callFrame[i] = codeBlock->constantRegister(j);
3497 int dst = (++vPC)->u.operand;
3498 JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionBodyNode*>(codeBlock->ownerNode()));
3499 callFrame[dst] = activation;
3500 callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
3505 DEFINE_OPCODE(op_convert_this) {
3506 /* convert_this this(r)
3508 Takes the value in the 'this' register, converts it to a
3509 value that is suitable for use as the 'this' value, and
3510 stores it in the 'this' register. This opcode is emitted
3511 to avoid doing the conversion in the caller unnecessarily.
3513 This opcode should only be used at the beginning of a code
3517 int thisRegister = (++vPC)->u.operand;
3518 JSValue* thisVal = callFrame[thisRegister].getJSValue();
3519 if (thisVal->needsThisConversion())
3520 callFrame[thisRegister] = thisVal->toThisObject(callFrame);
3525 DEFINE_OPCODE(op_create_arguments) {
3528 Creates the 'arguments' object and places it in both the
3529 'arguments' call frame slot and the local 'arguments'
3532 This opcode should only be used at the beginning of a code
3536 Arguments* arguments = new (globalData) Arguments(callFrame);
3537 callFrame->setCalleeArguments(arguments);
3538 callFrame[RegisterFile::ArgumentsRegister] = arguments;
3543 DEFINE_OPCODE(op_construct) {
3544 /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
3546 Invoke register "func" as a constructor. For JS
3547 functions, the calling convention is exactly as for the
3548 "call" opcode, except that the "this" value is a newly
3549 created Object. For native constructors, no "this"
3550 value is passed. In either case, the argCount and registerOffset
3551 registers are interpreted as for the "call" opcode.
3553 Register proto must contain the prototype property of
3554 register func. This is to enable polymorphic inline
3555 caching of this lookup.
3558 int dst = vPC[1].u.operand;
3559 int func = vPC[2].u.operand;
3560 int argCount = vPC[3].u.operand;
3561 int registerOffset = vPC[4].u.operand;
3562 int proto = vPC[5].u.operand;
3563 int thisRegister = vPC[6].u.operand;
3565 JSValue* v = callFrame[func].jsValue(callFrame);
3567 ConstructData constructData;
3568 ConstructType constructType = v->getConstructData(constructData);
3570 if (constructType == ConstructTypeJS) {
3571 ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
3572 FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
3573 CodeBlock* newCodeBlock = &functionBodyNode->bytecode(callDataScopeChain);
3575 Structure* structure;
3576 JSValue* prototype = callFrame[proto].jsValue(callFrame);
3577 if (prototype->isObject())
3578 structure = asObject(prototype)->inheritorID();
3580 structure = callDataScopeChain->globalObject()->emptyObjectStructure();
3581 JSObject* newObject = new (globalData) JSObject(structure);
3583 callFrame[thisRegister] = newObject; // "this" value
3585 CallFrame* previousCallFrame = callFrame;
3587 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
3588 if (UNLIKELY(!callFrame)) {
3589 callFrame = previousCallFrame;
3590 exceptionValue = createStackOverflowError(callFrame);
3594 callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
3595 vPC = newCodeBlock->instructions().begin();
3597 #if ENABLE(OPCODE_STATS)
3598 OpcodeStats::resetLastInstruction();
3604 if (constructType == ConstructTypeHost) {
3605 ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1);
3607 ScopeChainNode* scopeChain = callFrame->scopeChain();
3608 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
3609 newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0);
3611 JSValue* returnValue;
3613 SamplingTool::HostCallRecord callRecord(m_sampler);
3614 returnValue = constructData.native.function(newCallFrame, asObject(v), args);
3616 CHECK_FOR_EXCEPTION();
3617 callFrame[dst] = returnValue;
3623 ASSERT(constructType == ConstructTypeNone);
3625 exceptionValue = createNotAConstructorError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
3628 DEFINE_OPCODE(op_construct_verify) {
3629 /* construct_verify dst(r) override(r)
3631 Verifies that register dst holds an object. If not, moves
3632 the object in register override to register dst.
3635 int dst = vPC[1].u.operand;;
3636 if (LIKELY(callFrame[dst].jsValue(callFrame)->isObject())) {
3641 int override = vPC[2].u.operand;
3642 callFrame[dst] = callFrame[override];
3647 DEFINE_OPCODE(op_push_scope) {
3648 /* push_scope scope(r)
3650 Converts register scope to object, and pushes it onto the top
3651 of the current scope chain. The contents of the register scope
3652 are replaced by the result of toObject conversion of the scope.
3654 int scope = (++vPC)->u.operand;
3655 JSValue* v = callFrame[scope].jsValue(callFrame);
3656 JSObject* o = v->toObject(callFrame);
3657 CHECK_FOR_EXCEPTION();
3659 callFrame[scope] = o;
3660 callFrame->setScopeChain(callFrame->scopeChain()->push(o));
3665 DEFINE_OPCODE(op_pop_scope) {
3668 Removes the top item from the current scope chain.
3670 callFrame->setScopeChain(callFrame->scopeChain()->pop());
3675 DEFINE_OPCODE(op_get_pnames) {
3676 /* get_pnames dst(r) base(r)
3678 Creates a property name list for register base and puts it
3679 in register dst. This is not a true JavaScript value, just
3680 a synthetic value used to keep the iteration state in a
3683 int dst = (++vPC)->u.operand;
3684 int base = (++vPC)->u.operand;
3686 callFrame[dst] = JSPropertyNameIterator::create(callFrame, callFrame[base].jsValue(callFrame));
3690 DEFINE_OPCODE(op_next_pname) {
3691 /* next_pname dst(r) iter(r) target(offset)
3693 Tries to copies the next name from property name list in
3694 register iter. If there are names left, then copies one to
3695 register dst, and jumps to offset target. If there are none
3696 left, invalidates the iterator and continues to the next
3699 int dst = (++vPC)->u.operand;
3700 int iter = (++vPC)->u.operand;
3701 int target = (++vPC)->u.operand;
3703 JSPropertyNameIterator* it = callFrame[iter].propertyNameIterator();
3704 if (JSValue* temp = it->next(callFrame)) {
3705 CHECK_FOR_TIMEOUT();
3706 callFrame[dst] = temp;
3715 DEFINE_OPCODE(op_jmp_scopes) {
3716 /* jmp_scopes count(n) target(offset)
3718 Removes the a number of items from the current scope chain
3719 specified by immediate number count, then jumps to offset
3722 int count = (++vPC)->u.operand;
3723 int target = (++vPC)->u.operand;
3725 ScopeChainNode* tmp = callFrame->scopeChain();
3728 callFrame->setScopeChain(tmp);
3733 #if HAVE(COMPUTED_GOTO)
3735 goto *(&&skip_new_scope);
3737 DEFINE_OPCODE(op_push_new_scope) {
3738 /* new_scope dst(r) property(id) value(r)
3740 Constructs a new StaticScopeObject with property set to value. That scope
3741 object is then pushed onto the ScopeChain. The scope object is then stored
3744 callFrame->setScopeChain(createExceptionScope(callFrame, vPC));
3749 #if HAVE(COMPUTED_GOTO)
3752 DEFINE_OPCODE(op_catch) {
3755 Retrieves the VMs current exception and puts it in register
3756 ex. This is only valid after an exception has been raised,
3757 and usually forms the beginning of an exception handler.
3759 ASSERT(exceptionValue);
3760 ASSERT(!globalData->exception);
3761 int ex = (++vPC)->u.operand;
3762 callFrame[ex] = exceptionValue;
3763 exceptionValue = noValue();
3768 DEFINE_OPCODE(op_throw) {
3771 Throws register ex as an exception. This involves three
3772 steps: first, it is set as the current exception in the
3773 VM's internal state, then the stack is unwound until an
3774 exception handler or a native code boundary is found, and
3775 then control resumes at the exception handler if any or
3776 else the script returns control to the nearest native caller.
3779 int ex = (++vPC)->u.operand;
3780 exceptionValue = callFrame[ex].jsValue(callFrame);
3782 handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true);
3784 *exception = exceptionValue;
3788 vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
3791 DEFINE_OPCODE(op_unexpected_load) {
3792 /* unexpected_load load dst(r) src(k)
3794 Copies constant src to register dst.
3796 int dst = (++vPC)->u.operand;
3797 int src = (++vPC)->u.operand;
3798 callFrame[dst] = callFrame->codeBlock()->unexpectedConstant(src);
3803 DEFINE_OPCODE(op_new_error) {
3804 /* new_error dst(r) type(n) message(k)
3806 Constructs a new Error instance using the original
3807 constructor, using immediate number n as the type and
3808 constant message as the message string. The result is
3809 written to register dst.
3811 int dst = (++vPC)->u.operand;
3812 int type = (++vPC)->u.operand;
3813 int message = (++vPC)->u.operand;
3815 CodeBlock* codeBlock = callFrame->codeBlock();
3816 callFrame[dst] = Error::create(callFrame, (ErrorType)type, codeBlock->unexpectedConstant(message)->toString(callFrame), codeBlock->lineNumberForBytecodeOffset(vPC - codeBlock->instructions().begin()), codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
3821 DEFINE_OPCODE(op_end) {
3824 Return register result as the value of a global or eval
3825 program. Return control to the calling native code.