Home | History | Annotate | Download | only in interpreter
      1 /*
      2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich (at) uwaterloo.ca>
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * 1.  Redistributions of source code must retain the above copyright
     10  *     notice, this list of conditions and the following disclaimer.
     11  * 2.  Redistributions in binary form must reproduce the above copyright
     12  *     notice, this list of conditions and the following disclaimer in the
     13  *     documentation and/or other materials provided with the distribution.
     14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     15  *     its contributors may be used to endorse or promote products derived
     16  *     from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include "config.h"
     31 #include "Interpreter.h"
     32 
     33 #include "Arguments.h"
     34 #include "BatchedTransitionOptimizer.h"
     35 #include "CallFrame.h"
     36 #include "CallFrameClosure.h"
     37 #include "CodeBlock.h"
     38 #include "Collector.h"
     39 #include "Debugger.h"
     40 #include "DebuggerCallFrame.h"
     41 #include "EvalCodeCache.h"
     42 #include "ExceptionHelpers.h"
     43 #include "GlobalEvalFunction.h"
     44 #include "JSActivation.h"
     45 #include "JSArray.h"
     46 #include "JSByteArray.h"
     47 #include "JSFunction.h"
     48 #include "JSNotAnObject.h"
     49 #include "JSPropertyNameIterator.h"
     50 #include "LiteralParser.h"
     51 #include "JSStaticScopeObject.h"
     52 #include "JSString.h"
     53 #include "ObjectPrototype.h"
     54 #include "Operations.h"
     55 #include "Parser.h"
     56 #include "Profiler.h"
     57 #include "RegExpObject.h"
     58 #include "RegExpPrototype.h"
     59 #include "Register.h"
     60 #include "SamplingTool.h"
     61 #include <limits.h>
     62 #include <stdio.h>
     63 #include <wtf/Threading.h>
     64 
     65 #if ENABLE(JIT)
     66 #include "JIT.h"
     67 #endif
     68 
     69 using namespace std;
     70 
     71 namespace JSC {
     72 
     73 static ALWAYS_INLINE unsigned bytecodeOffsetForPC(CallFrame* callFrame, CodeBlock* codeBlock, void* pc)
     74 {
     75 #if ENABLE(JIT)
     76     return codeBlock->getBytecodeIndex(callFrame, ReturnAddressPtr(pc));
     77 #else
     78     UNUSED_PARAM(callFrame);
     79     return static_cast<Instruction*>(pc) - codeBlock->instructions().begin();
     80 #endif
     81 }
     82 
     83 // Returns the depth of the scope chain within a given call frame.
     84 static int depth(CodeBlock* codeBlock, ScopeChain& sc)
     85 {
     86     if (!codeBlock->needsFullScopeChain())
     87         return 0;
     88     return sc.localDepth();
     89 }
     90 
     91 #if USE(INTERPRETER)
     92 NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
     93 {
     94     int dst = vPC[1].u.operand;
     95     int property = vPC[2].u.operand;
     96 
     97     ScopeChainNode* scopeChain = callFrame->scopeChain();
     98     ScopeChainIterator iter = scopeChain->begin();
     99     ScopeChainIterator end = scopeChain->end();
    100     ASSERT(iter != end);
    101 
    102     CodeBlock* codeBlock = callFrame->codeBlock();
    103     Identifier& ident = codeBlock->identifier(property);
    104     do {
    105         JSObject* o = *iter;
    106         PropertySlot slot(o);
    107         if (o->getPropertySlot(callFrame, ident, slot)) {
    108             JSValue result = slot.getValue(callFrame, ident);
    109             exceptionValue = callFrame->globalData().exception;
    110             if (exceptionValue)
    111                 return false;
    112             callFrame->r(dst) = JSValue(result);
    113             return true;
    114         }
    115     } while (++iter != end);
    116     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
    117     return false;
    118 }
    119 
    120 NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
    121 {
    122     CodeBlock* codeBlock = callFrame->codeBlock();
    123 
    124     int dst = vPC[1].u.operand;
    125     int property = vPC[2].u.operand;
    126     int skip = vPC[3].u.operand + codeBlock->needsFullScopeChain();
    127 
    128     ScopeChainNode* scopeChain = callFrame->scopeChain();
    129     ScopeChainIterator iter = scopeChain->begin();
    130     ScopeChainIterator end = scopeChain->end();
    131     ASSERT(iter != end);
    132     while (skip--) {
    133         ++iter;
    134         ASSERT(iter != end);
    135     }
    136     Identifier& ident = codeBlock->identifier(property);
    137     do {
    138         JSObject* o = *iter;
    139         PropertySlot slot(o);
    140         if (o->getPropertySlot(callFrame, ident, slot)) {
    141             JSValue result = slot.getValue(callFrame, ident);
    142             exceptionValue = callFrame->globalData().exception;
    143             if (exceptionValue)
    144                 return false;
    145             callFrame->r(dst) = JSValue(result);
    146             return true;
    147         }
    148     } while (++iter != end);
    149     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
    150     return false;
    151 }
    152 
    153 NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
    154 {
    155     int dst = vPC[1].u.operand;
    156     JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(vPC[2].u.jsCell);
    157     ASSERT(globalObject->isGlobalObject());
    158     int property = vPC[3].u.operand;
    159     Structure* structure = vPC[4].u.structure;
    160     int offset = vPC[5].u.operand;
    161 
    162     if (structure == globalObject->structure()) {
    163         callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset));
    164         return true;
    165     }
    166 
    167     CodeBlock* codeBlock = callFrame->codeBlock();
    168     Identifier& ident = codeBlock->identifier(property);
    169     PropertySlot slot(globalObject);
    170     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
    171         JSValue result = slot.getValue(callFrame, ident);
    172         if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
    173             if (vPC[4].u.structure)
    174                 vPC[4].u.structure->deref();
    175             globalObject->structure()->ref();
    176             vPC[4] = globalObject->structure();
    177             vPC[5] = slot.cachedOffset();
    178             callFrame->r(dst) = JSValue(result);
    179             return true;
    180         }
    181 
    182         exceptionValue = callFrame->globalData().exception;
    183         if (exceptionValue)
    184             return false;
    185         callFrame->r(dst) = JSValue(result);
    186         return true;
    187     }
    188 
    189     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
    190     return false;
    191 }
    192 
    193 NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC)
    194 {
    195     int dst = vPC[1].u.operand;
    196     int property = vPC[2].u.operand;
    197     callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
    198 }
    199 
    200 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
    201 {
    202     int baseDst = vPC[1].u.operand;
    203     int propDst = vPC[2].u.operand;
    204     int property = vPC[3].u.operand;
    205 
    206     ScopeChainNode* scopeChain = callFrame->scopeChain();
    207     ScopeChainIterator iter = scopeChain->begin();
    208     ScopeChainIterator end = scopeChain->end();
    209 
    210     // FIXME: add scopeDepthIsZero optimization
    211 
    212     ASSERT(iter != end);
    213 
    214     CodeBlock* codeBlock = callFrame->codeBlock();
    215     Identifier& ident = codeBlock->identifier(property);
    216     JSObject* base;
    217     do {
    218         base = *iter;
    219         PropertySlot slot(base);
    220         if (base->getPropertySlot(callFrame, ident, slot)) {
    221             JSValue result = slot.getValue(callFrame, ident);
    222             exceptionValue = callFrame->globalData().exception;
    223             if (exceptionValue)
    224                 return false;
    225             callFrame->r(propDst) = JSValue(result);
    226             callFrame->r(baseDst) = JSValue(base);
    227             return true;
    228         }
    229         ++iter;
    230     } while (iter != end);
    231 
    232     exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
    233     return false;
    234 }
    235 
    236 #endif // USE(INTERPRETER)
    237 
    238 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
    239 {
    240     Register* r = callFrame->registers();
    241     Register* newEnd = r + registerOffset + newCodeBlock->m_numCalleeRegisters;
    242 
    243     if (LIKELY(argc == newCodeBlock->m_numParameters)) { // correct number of arguments
    244         if (UNLIKELY(!registerFile->grow(newEnd)))
    245             return 0;
    246         r += registerOffset;
    247     } else if (argc < newCodeBlock->m_numParameters) { // too few arguments -- fill in the blanks
    248         size_t omittedArgCount = newCodeBlock->m_numParameters - argc;
    249         registerOffset += omittedArgCount;
    250         newEnd += omittedArgCount;
    251         if (!registerFile->grow(newEnd))
    252             return 0;
    253         r += registerOffset;
    254 
    255         Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
    256         for (size_t i = 0; i < omittedArgCount; ++i)
    257             argv[i] = jsUndefined();
    258     } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind
    259         size_t numParameters = newCodeBlock->m_numParameters;
    260         registerOffset += numParameters;
    261         newEnd += numParameters;
    262 
    263         if (!registerFile->grow(newEnd))
    264             return 0;
    265         r += registerOffset;
    266 
    267         Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argc;
    268         for (size_t i = 0; i < numParameters; ++i)
    269             argv[i + argc] = argv[i];
    270     }
    271 
    272     return CallFrame::create(r);
    273 }
    274 
    275 #if USE(INTERPRETER)
    276 static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
    277 {
    278     if (value.isObject())
    279         return false;
    280     exceptionData = createInvalidParamError(callFrame, "in" , value, vPC - codeBlock->instructions().begin(), codeBlock);
    281     return true;
    282 }
    283 
    284 static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
    285 {
    286     if (value.isObject() && asObject(value)->structure()->typeInfo().implementsHasInstance())
    287         return false;
    288     exceptionData = createInvalidParamError(callFrame, "instanceof" , value, vPC - codeBlock->instructions().begin(), codeBlock);
    289     return true;
    290 }
    291 #endif
    292 
    293 NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue& exceptionValue)
    294 {
    295     if (argc < 2)
    296         return jsUndefined();
    297 
    298     JSValue program = argv[1].jsValue();
    299 
    300     if (!program.isString())
    301         return program;
    302 
    303     UString programSource = asString(program)->value(callFrame);
    304 
    305     LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
    306     if (JSValue parsedObject = preparser.tryLiteralParse())
    307         return parsedObject;
    308 
    309     ScopeChainNode* scopeChain = callFrame->scopeChain();
    310     CodeBlock* codeBlock = callFrame->codeBlock();
    311     RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
    312 
    313     JSValue result = jsUndefined();
    314     if (eval)
    315         result = callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
    316 
    317     return result;
    318 }
    319 
    320 Interpreter::Interpreter()
    321     : m_sampleEntryDepth(0)
    322     , m_reentryDepth(0)
    323 {
    324 #if HAVE(COMPUTED_GOTO)
    325     privateExecute(InitializeAndReturn, 0, 0, 0);
    326 
    327     for (int i = 0; i < numOpcodeIDs; ++i)
    328         m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
    329 #endif // HAVE(COMPUTED_GOTO)
    330 
    331 #if ENABLE(OPCODE_SAMPLING)
    332     enableSampler();
    333 #endif
    334 }
    335 
    336 #ifndef NDEBUG
    337 
    338 void Interpreter::dumpCallFrame(CallFrame* callFrame)
    339 {
    340     callFrame->codeBlock()->dump(callFrame);
    341     dumpRegisters(callFrame);
    342 }
    343 
    344 void Interpreter::dumpRegisters(CallFrame* callFrame)
    345 {
    346     printf("Register frame: \n\n");
    347     printf("-----------------------------------------------------------------------------\n");
    348     printf("            use            |   address  |                value               \n");
    349     printf("-----------------------------------------------------------------------------\n");
    350 
    351     CodeBlock* codeBlock = callFrame->codeBlock();
    352     RegisterFile* registerFile = &callFrame->scopeChain()->globalObject->globalData()->interpreter->registerFile();
    353     const Register* it;
    354     const Register* end;
    355     JSValue v;
    356 
    357     if (codeBlock->codeType() == GlobalCode) {
    358         it = registerFile->lastGlobal();
    359         end = it + registerFile->numGlobals();
    360         while (it != end) {
    361             v = (*it).jsValue();
    362 #if USE(JSVALUE32_64)
    363             printf("[global var]               | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
    364 #else
    365             printf("[global var]               | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
    366 #endif
    367             ++it;
    368         }
    369         printf("-----------------------------------------------------------------------------\n");
    370     }
    371 
    372     it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;
    373     v = (*it).jsValue();
    374 #if USE(JSVALUE32_64)
    375     printf("[this]                     | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it;
    376 #else
    377     printf("[this]                     | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it;
    378 #endif
    379     end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this"
    380     if (it != end) {
    381         do {
    382             v = (*it).jsValue();
    383 #if USE(JSVALUE32_64)
    384             printf("[param]                    | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
    385 #else
    386             printf("[param]                    | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
    387 #endif
    388             ++it;
    389         } while (it != end);
    390     }
    391     printf("-----------------------------------------------------------------------------\n");
    392     printf("[CodeBlock]                | %10p | %p \n", it, (*it).codeBlock()); ++it;
    393     printf("[ScopeChain]               | %10p | %p \n", it, (*it).scopeChain()); ++it;
    394     printf("[CallerRegisters]          | %10p | %d \n", it, (*it).i()); ++it;
    395     printf("[ReturnPC]                 | %10p | %p \n", it, (*it).vPC()); ++it;
    396     printf("[ReturnValueRegister]      | %10p | %d \n", it, (*it).i()); ++it;
    397     printf("[ArgumentCount]            | %10p | %d \n", it, (*it).i()); ++it;
    398     printf("[Callee]                   | %10p | %p \n", it, (*it).function()); ++it;
    399     printf("[OptionalCalleeArguments]  | %10p | %p \n", it, (*it).arguments()); ++it;
    400     printf("-----------------------------------------------------------------------------\n");
    401 
    402     int registerCount = 0;
    403 
    404     end = it + codeBlock->m_numVars;
    405     if (it != end) {
    406         do {
    407             v = (*it).jsValue();
    408 #if USE(JSVALUE32_64)
    409             printf("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
    410 #else
    411             printf("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
    412 #endif
    413             ++it;
    414             ++registerCount;
    415         } while (it != end);
    416     }
    417     printf("-----------------------------------------------------------------------------\n");
    418 
    419     end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
    420     if (it != end) {
    421         do {
    422             v = (*it).jsValue();
    423 #if USE(JSVALUE32_64)
    424             printf("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
    425 #else
    426             printf("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
    427 #endif
    428             ++it;
    429             ++registerCount;
    430         } while (it != end);
    431     }
    432     printf("-----------------------------------------------------------------------------\n");
    433 }
    434 
    435 #endif
    436 
    437 bool Interpreter::isOpcode(Opcode opcode)
    438 {
    439 #if HAVE(COMPUTED_GOTO)
    440     return opcode != HashTraits<Opcode>::emptyValue()
    441         && !HashTraits<Opcode>::isDeletedValue(opcode)
    442         && m_opcodeIDTable.contains(opcode);
    443 #else
    444     return opcode >= 0 && opcode <= op_end;
    445 #endif
    446 }
    447 
    448 NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
    449 {
    450     CodeBlock* oldCodeBlock = codeBlock;
    451     ScopeChainNode* scopeChain = callFrame->scopeChain();
    452 
    453     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
    454         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
    455         if (callFrame->callee())
    456             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
    457         else
    458             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
    459     }
    460 
    461     if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
    462         if (callFrame->callee())
    463             profiler->didExecute(callFrame, callFrame->callee());
    464         else
    465             profiler->didExecute(callFrame, codeBlock->ownerExecutable()->sourceURL(), codeBlock->ownerExecutable()->lineNo());
    466     }
    467 
    468     // If this call frame created an activation or an 'arguments' object, tear it off.
    469     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
    470         while (!scopeChain->object->inherits(&JSActivation::info))
    471             scopeChain = scopeChain->pop();
    472         static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments());
    473     } else if (Arguments* arguments = callFrame->optionalCalleeArguments()) {
    474         if (!arguments->isTornOff())
    475             arguments->copyRegisters();
    476     }
    477 
    478     if (oldCodeBlock->needsFullScopeChain())
    479         scopeChain->deref();
    480 
    481     void* returnPC = callFrame->returnPC();
    482     callFrame = callFrame->callerFrame();
    483     if (callFrame->hasHostCallFrameFlag())
    484         return false;
    485 
    486     codeBlock = callFrame->codeBlock();
    487     bytecodeOffset = bytecodeOffsetForPC(callFrame, codeBlock, returnPC);
    488     return true;
    489 }
    490 
    491 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
    492 {
    493     // Set up the exception object
    494 
    495     CodeBlock* codeBlock = callFrame->codeBlock();
    496     if (exceptionValue.isObject()) {
    497         JSObject* exception = asObject(exceptionValue);
    498         if (exception->isNotAnObjectErrorStub()) {
    499             exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock);
    500             exceptionValue = exception;
    501         } else {
    502             if (!exception->hasProperty(callFrame, Identifier(callFrame, "line")) &&
    503                 !exception->hasProperty(callFrame, Identifier(callFrame, "sourceId")) &&
    504                 !exception->hasProperty(callFrame, Identifier(callFrame, "sourceURL")) &&
    505                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName)) &&
    506                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionCaretOffsetPropertyName)) &&
    507                 !exception->hasProperty(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName))) {
    508                 if (explicitThrow) {
    509                     int startOffset = 0;
    510                     int endOffset = 0;
    511                     int divotPoint = 0;
    512                     int line = codeBlock->expressionRangeForBytecodeOffset(callFrame, bytecodeOffset, divotPoint, startOffset, endOffset);
    513                     exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, line), ReadOnly | DontDelete);
    514 
    515                     // We only hit this path for error messages and throw statements, which don't have a specific failure position
    516                     // So we just give the full range of the error/throw statement.
    517                     exception->putWithAttributes(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName), jsNumber(callFrame, divotPoint - startOffset), ReadOnly | DontDelete);
    518                     exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete);
    519                 } else
    520                     exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete);
    521                 exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerExecutable()->sourceID()), ReadOnly | DontDelete);
    522                 exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerExecutable()->sourceURL()), ReadOnly | DontDelete);
    523             }
    524 
    525             if (exception->isWatchdogException()) {
    526                 while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
    527                     // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
    528                 }
    529                 return 0;
    530             }
    531         }
    532     }
    533 
    534     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
    535         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
    536         bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
    537         debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset), hasHandler);
    538     }
    539 
    540     // If we throw in the middle of a call instruction, we need to notify
    541     // the profiler manually that the call instruction has returned, since
    542     // we'll never reach the relevant op_profile_did_call.
    543     if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
    544 #if !ENABLE(JIT)
    545         if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
    546             profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 2].u.operand).jsValue());
    547         else if (codeBlock->instructions().size() > (bytecodeOffset + 8) && codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
    548             profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 10].u.operand).jsValue());
    549 #else
    550         int functionRegisterIndex;
    551         if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
    552             profiler->didExecute(callFrame, callFrame->r(functionRegisterIndex).jsValue());
    553 #endif
    554     }
    555 
    556     // Calculate an exception handler vPC, unwinding call frames as necessary.
    557 
    558     HandlerInfo* handler = 0;
    559     while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
    560         if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock))
    561             return 0;
    562     }
    563 
    564     // Now unwind the scope chain within the exception handler's call frame.
    565 
    566     ScopeChainNode* scopeChain = callFrame->scopeChain();
    567     ScopeChain sc(scopeChain);
    568     int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;
    569     ASSERT(scopeDelta >= 0);
    570     while (scopeDelta--)
    571         scopeChain = scopeChain->pop();
    572     callFrame->setScopeChain(scopeChain);
    573 
    574     return handler;
    575 }
    576 
    577 JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception)
    578 {
    579     ASSERT(!scopeChain->globalData->exception);
    580 
    581     if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
    582         if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
    583             *exception = createStackOverflowError(callFrame);
    584             return jsNull();
    585         }
    586     }
    587 
    588     CodeBlock* codeBlock = &program->bytecode(callFrame, scopeChain);
    589 
    590     Register* oldEnd = m_registerFile.end();
    591     Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
    592     if (!m_registerFile.grow(newEnd)) {
    593         *exception = createStackOverflowError(callFrame);
    594         return jsNull();
    595     }
    596 
    597     DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
    598 
    599     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
    600     JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
    601     globalObject->copyGlobalsTo(m_registerFile);
    602 
    603     CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
    604     newCallFrame->r(codeBlock->thisRegister()) = JSValue(thisObj);
    605     newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0);
    606 
    607     if (codeBlock->needsFullScopeChain())
    608         scopeChain->ref();
    609 
    610     Profiler** profiler = Profiler::enabledProfilerReference();
    611     if (*profiler)
    612         (*profiler)->willExecute(newCallFrame, program->sourceURL(), program->lineNo());
    613 
    614     JSValue result;
    615     {
    616         SamplingTool::CallRecord callRecord(m_sampler.get());
    617 
    618         m_reentryDepth++;
    619 #if ENABLE(JIT)
    620         result = program->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
    621 #else
    622         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
    623 #endif
    624         m_reentryDepth--;
    625     }
    626 
    627     if (*profiler)
    628         (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
    629 
    630     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
    631         lastGlobalObject->copyGlobalsTo(m_registerFile);
    632 
    633     m_registerFile.shrink(oldEnd);
    634 
    635     return result;
    636 }
    637 
    638 JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception)
    639 {
    640     ASSERT(!scopeChain->globalData->exception);
    641 
    642     if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
    643         if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
    644             *exception = createStackOverflowError(callFrame);
    645             return jsNull();
    646         }
    647     }
    648 
    649     Register* oldEnd = m_registerFile.end();
    650     int argc = 1 + args.size(); // implicit "this" parameter
    651 
    652     if (!m_registerFile.grow(oldEnd + argc)) {
    653         *exception = createStackOverflowError(callFrame);
    654         return jsNull();
    655     }
    656 
    657     DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
    658 
    659     CallFrame* newCallFrame = CallFrame::create(oldEnd);
    660     size_t dst = 0;
    661     newCallFrame->r(0) = JSValue(thisObj);
    662     ArgList::const_iterator end = args.end();
    663     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
    664         newCallFrame->r(++dst) = *it;
    665 
    666     CodeBlock* codeBlock = &functionExecutable->bytecode(callFrame, scopeChain);
    667     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
    668     if (UNLIKELY(!newCallFrame)) {
    669         *exception = createStackOverflowError(callFrame);
    670         m_registerFile.shrink(oldEnd);
    671         return jsNull();
    672     }
    673     // a 0 codeBlock indicates a built-in caller
    674     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
    675 
    676     Profiler** profiler = Profiler::enabledProfilerReference();
    677     if (*profiler)
    678         (*profiler)->willExecute(callFrame, function);
    679 
    680     JSValue result;
    681     {
    682         SamplingTool::CallRecord callRecord(m_sampler.get());
    683 
    684         m_reentryDepth++;
    685 #if ENABLE(JIT)
    686         result = functionExecutable->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
    687 #else
    688         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
    689 #endif
    690         m_reentryDepth--;
    691     }
    692 
    693     if (*profiler)
    694         (*profiler)->didExecute(callFrame, function);
    695 
    696     m_registerFile.shrink(oldEnd);
    697     return result;
    698 }
    699 
    700 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception)
    701 {
    702     ASSERT(!scopeChain->globalData->exception);
    703 
    704     if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
    705         if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
    706             *exception = createStackOverflowError(callFrame);
    707             return CallFrameClosure();
    708         }
    709     }
    710 
    711     Register* oldEnd = m_registerFile.end();
    712     int argc = 1 + argCount; // implicit "this" parameter
    713 
    714     if (!m_registerFile.grow(oldEnd + argc)) {
    715         *exception = createStackOverflowError(callFrame);
    716         return CallFrameClosure();
    717     }
    718 
    719     CallFrame* newCallFrame = CallFrame::create(oldEnd);
    720     size_t dst = 0;
    721     for (int i = 0; i < argc; ++i)
    722         newCallFrame->r(++dst) = jsUndefined();
    723 
    724     CodeBlock* codeBlock = &FunctionExecutable->bytecode(callFrame, scopeChain);
    725     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
    726     if (UNLIKELY(!newCallFrame)) {
    727         *exception = createStackOverflowError(callFrame);
    728         m_registerFile.shrink(oldEnd);
    729         return CallFrameClosure();
    730     }
    731     // a 0 codeBlock indicates a built-in caller
    732     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
    733 #if ENABLE(JIT)
    734     FunctionExecutable->jitCode(newCallFrame, scopeChain);
    735 #endif
    736 
    737     CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
    738     return result;
    739 }
    740 
    741 JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception)
    742 {
    743     closure.resetCallFrame();
    744     Profiler** profiler = Profiler::enabledProfilerReference();
    745     if (*profiler)
    746         (*profiler)->willExecute(closure.oldCallFrame, closure.function);
    747 
    748     JSValue result;
    749     {
    750         SamplingTool::CallRecord callRecord(m_sampler.get());
    751 
    752         m_reentryDepth++;
    753 #if ENABLE(JIT)
    754         result = closure.functionExecutable->generatedJITCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
    755 #else
    756         result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
    757 #endif
    758         m_reentryDepth--;
    759     }
    760 
    761     if (*profiler)
    762         (*profiler)->didExecute(closure.oldCallFrame, closure.function);
    763     return result;
    764 }
    765 
    766 void Interpreter::endRepeatCall(CallFrameClosure& closure)
    767 {
    768     m_registerFile.shrink(closure.oldEnd);
    769 }
    770 
    771 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception)
    772 {
    773     return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->bytecode(callFrame, scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
    774 }
    775 
    776 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
    777 {
    778     ASSERT(!scopeChain->globalData->exception);
    779 
    780     if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) {
    781         if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) {
    782             *exception = createStackOverflowError(callFrame);
    783             return jsNull();
    784         }
    785     }
    786 
    787     DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
    788 
    789     EvalCodeBlock* codeBlock = &eval->bytecode(callFrame, scopeChain);
    790 
    791     JSVariableObject* variableObject;
    792     for (ScopeChainNode* node = scopeChain; ; node = node->next) {
    793         ASSERT(node);
    794         if (node->object->isVariableObject()) {
    795             variableObject = static_cast<JSVariableObject*>(node->object);
    796             break;
    797         }
    798     }
    799 
    800     { // Scope for BatchedTransitionOptimizer
    801 
    802         BatchedTransitionOptimizer optimizer(variableObject);
    803 
    804         unsigned numVariables = codeBlock->numVariables();
    805         for (unsigned i = 0; i < numVariables; ++i) {
    806             const Identifier& ident = codeBlock->variable(i);
    807             if (!variableObject->hasProperty(callFrame, ident)) {
    808                 PutPropertySlot slot;
    809                 variableObject->put(callFrame, ident, jsUndefined(), slot);
    810             }
    811         }
    812 
    813         int numFunctions = codeBlock->numberOfFunctionDecls();
    814         for (int i = 0; i < numFunctions; ++i) {
    815             FunctionExecutable* function = codeBlock->functionDecl(i);
    816             PutPropertySlot slot;
    817             variableObject->put(callFrame, function->name(), function->make(callFrame, scopeChain), slot);
    818         }
    819 
    820     }
    821 
    822     Register* oldEnd = m_registerFile.end();
    823     Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
    824     if (!m_registerFile.grow(newEnd)) {
    825         *exception = createStackOverflowError(callFrame);
    826         return jsNull();
    827     }
    828 
    829     CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
    830 
    831     // a 0 codeBlock indicates a built-in caller
    832     newCallFrame->r(codeBlock->thisRegister()) = JSValue(thisObj);
    833     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0);
    834 
    835     if (codeBlock->needsFullScopeChain())
    836         scopeChain->ref();
    837 
    838     Profiler** profiler = Profiler::enabledProfilerReference();
    839     if (*profiler)
    840         (*profiler)->willExecute(newCallFrame, eval->sourceURL(), eval->lineNo());
    841 
    842     JSValue result;
    843     {
    844         SamplingTool::CallRecord callRecord(m_sampler.get());
    845 
    846         m_reentryDepth++;
    847 #if ENABLE(JIT)
    848         result = eval->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
    849 #else
    850         result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
    851 #endif
    852         m_reentryDepth--;
    853     }
    854 
    855     if (*profiler)
    856         (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
    857 
    858     m_registerFile.shrink(oldEnd);
    859     return result;
    860 }
    861 
    862 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine)
    863 {
    864     Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
    865     if (!debugger)
    866         return;
    867 
    868     switch (debugHookID) {
    869         case DidEnterCallFrame:
    870             debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
    871             return;
    872         case WillLeaveCallFrame:
    873             debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
    874             return;
    875         case WillExecuteStatement:
    876             debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
    877             return;
    878         case WillExecuteProgram:
    879             debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
    880             return;
    881         case DidExecuteProgram:
    882             debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
    883             return;
    884         case DidReachBreakpoint:
    885             debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
    886             return;
    887     }
    888 }
    889 
    890 #if USE(INTERPRETER)
    891 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
    892 {
    893     int dst = vPC[1].u.operand;
    894     CodeBlock* codeBlock = callFrame->codeBlock();
    895     Identifier& property = codeBlock->identifier(vPC[2].u.operand);
    896     JSValue value = callFrame->r(vPC[3].u.operand).jsValue();
    897     JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
    898     callFrame->r(dst) = JSValue(scope);
    899 
    900     return callFrame->scopeChain()->push(scope);
    901 }
    902 
    903 NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const PutPropertySlot& slot)
    904 {
    905     // Recursive invocation may already have specialized this instruction.
    906     if (vPC[0].u.opcode != getOpcode(op_put_by_id))
    907         return;
    908 
    909     if (!baseValue.isCell())
    910         return;
    911 
    912     // Uncacheable: give up.
    913     if (!slot.isCacheable()) {
    914         vPC[0] = getOpcode(op_put_by_id_generic);
    915         return;
    916     }
    917 
    918     JSCell* baseCell = asCell(baseValue);
    919     Structure* structure = baseCell->structure();
    920 
    921     if (structure->isUncacheableDictionary()) {
    922         vPC[0] = getOpcode(op_put_by_id_generic);
    923         return;
    924     }
    925 
    926     // Cache miss: record Structure to compare against next time.
    927     Structure* lastStructure = vPC[4].u.structure;
    928     if (structure != lastStructure) {
    929         // First miss: record Structure to compare against next time.
    930         if (!lastStructure) {
    931             vPC[4] = structure;
    932             return;
    933         }
    934 
    935         // Second miss: give up.
    936         vPC[0] = getOpcode(op_put_by_id_generic);
    937         return;
    938     }
    939 
    940     // Cache hit: Specialize instruction and ref Structures.
    941 
    942     // If baseCell != slot.base(), then baseCell must be a proxy for another object.
    943     if (baseCell != slot.base()) {
    944         vPC[0] = getOpcode(op_put_by_id_generic);
    945         return;
    946     }
    947 
    948     // Structure transition, cache transition info
    949     if (slot.type() == PutPropertySlot::NewProperty) {
    950         if (structure->isDictionary()) {
    951             vPC[0] = getOpcode(op_put_by_id_generic);
    952             return;
    953         }
    954 
    955         // put_by_id_transition checks the prototype chain for setters.
    956         normalizePrototypeChain(callFrame, baseCell);
    957 
    958         vPC[0] = getOpcode(op_put_by_id_transition);
    959         vPC[4] = structure->previousID();
    960         vPC[5] = structure;
    961         vPC[6] = structure->prototypeChain(callFrame);
    962         vPC[7] = slot.cachedOffset();
    963         codeBlock->refStructures(vPC);
    964         return;
    965     }
    966 
    967     vPC[0] = getOpcode(op_put_by_id_replace);
    968     vPC[5] = slot.cachedOffset();
    969     codeBlock->refStructures(vPC);
    970 }
    971 
    972 NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC)
    973 {
    974     codeBlock->derefStructures(vPC);
    975     vPC[0] = getOpcode(op_put_by_id);
    976     vPC[4] = 0;
    977 }
    978 
    979 NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot)
    980 {
    981     // Recursive invocation may already have specialized this instruction.
    982     if (vPC[0].u.opcode != getOpcode(op_get_by_id))
    983         return;
    984 
    985     // FIXME: Cache property access for immediates.
    986     if (!baseValue.isCell()) {
    987         vPC[0] = getOpcode(op_get_by_id_generic);
    988         return;
    989     }
    990 
    991     JSGlobalData* globalData = &callFrame->globalData();
    992     if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
    993         vPC[0] = getOpcode(op_get_array_length);
    994         return;
    995     }
    996 
    997     if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
    998         vPC[0] = getOpcode(op_get_string_length);
    999         return;
   1000     }
   1001 
   1002     // Uncacheable: give up.
   1003     if (!slot.isCacheable()) {
   1004         vPC[0] = getOpcode(op_get_by_id_generic);
   1005         return;
   1006     }
   1007 
   1008     Structure* structure = asCell(baseValue)->structure();
   1009 
   1010     if (structure->isUncacheableDictionary()) {
   1011         vPC[0] = getOpcode(op_get_by_id_generic);
   1012         return;
   1013     }
   1014 
   1015     // Cache miss
   1016     Structure* lastStructure = vPC[4].u.structure;
   1017     if (structure != lastStructure) {
   1018         // First miss: record Structure to compare against next time.
   1019         if (!lastStructure) {
   1020             vPC[4] = structure;
   1021             return;
   1022         }
   1023 
   1024         // Second miss: give up.
   1025         vPC[0] = getOpcode(op_get_by_id_generic);
   1026         return;
   1027     }
   1028 
   1029     // Cache hit: Specialize instruction and ref Structures.
   1030 
   1031     if (slot.slotBase() == baseValue) {
   1032         vPC[0] = getOpcode(op_get_by_id_self);
   1033         vPC[5] = slot.cachedOffset();
   1034 
   1035         codeBlock->refStructures(vPC);
   1036         return;
   1037     }
   1038 
   1039     if (structure->isDictionary()) {
   1040         vPC[0] = getOpcode(op_get_by_id_generic);
   1041         return;
   1042     }
   1043 
   1044     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
   1045         ASSERT(slot.slotBase().isObject());
   1046 
   1047         JSObject* baseObject = asObject(slot.slotBase());
   1048         size_t offset = slot.cachedOffset();
   1049 
   1050         // Since we're accessing a prototype in a loop, it's a good bet that it
   1051         // should not be treated as a dictionary.
   1052         if (baseObject->structure()->isDictionary()) {
   1053             baseObject->flattenDictionaryObject();
   1054             offset = baseObject->structure()->get(propertyName);
   1055         }
   1056 
   1057         ASSERT(!baseObject->structure()->isUncacheableDictionary());
   1058 
   1059         vPC[0] = getOpcode(op_get_by_id_proto);
   1060         vPC[5] = baseObject->structure();
   1061         vPC[6] = offset;
   1062 
   1063         codeBlock->refStructures(vPC);
   1064         return;
   1065     }
   1066 
   1067     size_t offset = slot.cachedOffset();
   1068     size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
   1069     if (!count) {
   1070         vPC[0] = getOpcode(op_get_by_id_generic);
   1071         return;
   1072     }
   1073 
   1074     vPC[0] = getOpcode(op_get_by_id_chain);
   1075     vPC[4] = structure;
   1076     vPC[5] = structure->prototypeChain(callFrame);
   1077     vPC[6] = count;
   1078     vPC[7] = offset;
   1079     codeBlock->refStructures(vPC);
   1080 }
   1081 
   1082 NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC)
   1083 {
   1084     codeBlock->derefStructures(vPC);
   1085     vPC[0] = getOpcode(op_get_by_id);
   1086     vPC[4] = 0;
   1087 }
   1088 
   1089 #endif // USE(INTERPRETER)
   1090 
   1091 JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue* exception)
   1092 {
   1093     // One-time initialization of our address tables. We have to put this code
   1094     // here because our labels are only in scope inside this function.
   1095     if (UNLIKELY(flag == InitializeAndReturn)) {
   1096         #if HAVE(COMPUTED_GOTO)
   1097             #define LIST_OPCODE_LABEL(id, length) &&id,
   1098                 static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) };
   1099                 for (size_t i = 0; i < sizeof(labels) / sizeof(Opcode); ++i)
   1100                     m_opcodeTable[i] = labels[i];
   1101             #undef LIST_OPCODE_LABEL
   1102         #endif // HAVE(COMPUTED_GOTO)
   1103         return JSValue();
   1104     }
   1105 
   1106 #if ENABLE(JIT)
   1107     // Mixing Interpreter + JIT is not supported.
   1108     ASSERT_NOT_REACHED();
   1109 #endif
   1110 #if !USE(INTERPRETER)
   1111     UNUSED_PARAM(registerFile);
   1112     UNUSED_PARAM(callFrame);
   1113     UNUSED_PARAM(exception);
   1114     return JSValue();
   1115 #else
   1116 
   1117     JSGlobalData* globalData = &callFrame->globalData();
   1118     JSValue exceptionValue;
   1119     HandlerInfo* handler = 0;
   1120 
   1121     Instruction* vPC = callFrame->codeBlock()->instructions().begin();
   1122     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
   1123     unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck();
   1124 
   1125 #define CHECK_FOR_EXCEPTION() \
   1126     do { \
   1127         if (UNLIKELY(globalData->exception != JSValue())) { \
   1128             exceptionValue = globalData->exception; \
   1129             goto vm_throw; \
   1130         } \
   1131     } while (0)
   1132 
   1133 #if ENABLE(OPCODE_STATS)
   1134     OpcodeStats::resetLastInstruction();
   1135 #endif
   1136 
   1137 #define CHECK_FOR_TIMEOUT() \
   1138     if (!--tickCount) { \
   1139         if (globalData->timeoutChecker.didTimeOut(callFrame)) { \
   1140             exceptionValue = jsNull(); \
   1141             goto vm_throw; \
   1142         } \
   1143         tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); \
   1144     }
   1145 
   1146 #if ENABLE(OPCODE_SAMPLING)
   1147     #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC)
   1148 #else
   1149     #define SAMPLE(codeBlock, vPC)
   1150 #endif
   1151 
   1152 #if HAVE(COMPUTED_GOTO)
   1153     #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto *vPC->u.opcode
   1154 #if ENABLE(OPCODE_STATS)
   1155     #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
   1156 #else
   1157     #define DEFINE_OPCODE(opcode) opcode:
   1158 #endif
   1159     NEXT_INSTRUCTION();
   1160 #else
   1161     #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto interpreterLoopStart
   1162 #if ENABLE(OPCODE_STATS)
   1163     #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
   1164 #else
   1165     #define DEFINE_OPCODE(opcode) case opcode:
   1166 #endif
   1167     while (1) { // iterator loop begins
   1168     interpreterLoopStart:;
   1169     switch (vPC->u.opcode)
   1170 #endif
   1171     {
   1172     DEFINE_OPCODE(op_new_object) {
   1173         /* new_object dst(r)
   1174 
   1175            Constructs a new empty Object instance using the original
   1176            constructor, and puts the result in register dst.
   1177         */
   1178         int dst = vPC[1].u.operand;
   1179         callFrame->r(dst) = JSValue(constructEmptyObject(callFrame));
   1180 
   1181         vPC += OPCODE_LENGTH(op_new_object);
   1182         NEXT_INSTRUCTION();
   1183     }
   1184     DEFINE_OPCODE(op_new_array) {
   1185         /* new_array dst(r) firstArg(r) argCount(n)
   1186 
   1187            Constructs a new Array instance using the original
   1188            constructor, and puts the result in register dst.
   1189            The array will contain argCount elements with values
   1190            taken from registers starting at register firstArg.
   1191         */
   1192         int dst = vPC[1].u.operand;
   1193         int firstArg = vPC[2].u.operand;
   1194         int argCount = vPC[3].u.operand;
   1195         ArgList args(callFrame->registers() + firstArg, argCount);
   1196         callFrame->r(dst) = JSValue(constructArray(callFrame, args));
   1197 
   1198         vPC += OPCODE_LENGTH(op_new_array);
   1199         NEXT_INSTRUCTION();
   1200     }
   1201     DEFINE_OPCODE(op_new_regexp) {
   1202         /* new_regexp dst(r) regExp(re)
   1203 
   1204            Constructs a new RegExp instance using the original
   1205            constructor from regexp regExp, and puts the result in
   1206            register dst.
   1207         */
   1208         int dst = vPC[1].u.operand;
   1209         int regExp = vPC[2].u.operand;
   1210         callFrame->r(dst) = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
   1211 
   1212         vPC += OPCODE_LENGTH(op_new_regexp);
   1213         NEXT_INSTRUCTION();
   1214     }
   1215     DEFINE_OPCODE(op_mov) {
   1216         /* mov dst(r) src(r)
   1217 
   1218            Copies register src to register dst.
   1219         */
   1220         int dst = vPC[1].u.operand;
   1221         int src = vPC[2].u.operand;
   1222         callFrame->r(dst) = callFrame->r(src);
   1223 
   1224         vPC += OPCODE_LENGTH(op_mov);
   1225         NEXT_INSTRUCTION();
   1226     }
   1227     DEFINE_OPCODE(op_eq) {
   1228         /* eq dst(r) src1(r) src2(r)
   1229 
   1230            Checks whether register src1 and register src2 are equal,
   1231            as with the ECMAScript '==' operator, and puts the result
   1232            as a boolean in register dst.
   1233         */
   1234         int dst = vPC[1].u.operand;
   1235         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1236         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1237         if (src1.isInt32() && src2.isInt32())
   1238             callFrame->r(dst) = jsBoolean(src1.asInt32() == src2.asInt32());
   1239         else {
   1240             JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2));
   1241             CHECK_FOR_EXCEPTION();
   1242             callFrame->r(dst) = result;
   1243         }
   1244 
   1245         vPC += OPCODE_LENGTH(op_eq);
   1246         NEXT_INSTRUCTION();
   1247     }
   1248     DEFINE_OPCODE(op_eq_null) {
   1249         /* eq_null dst(r) src(r)
   1250 
   1251            Checks whether register src is null, as with the ECMAScript '!='
   1252            operator, and puts the result as a boolean in register dst.
   1253         */
   1254         int dst = vPC[1].u.operand;
   1255         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
   1256 
   1257         if (src.isUndefinedOrNull()) {
   1258             callFrame->r(dst) = jsBoolean(true);
   1259             vPC += OPCODE_LENGTH(op_eq_null);
   1260             NEXT_INSTRUCTION();
   1261         }
   1262 
   1263         callFrame->r(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
   1264         vPC += OPCODE_LENGTH(op_eq_null);
   1265         NEXT_INSTRUCTION();
   1266     }
   1267     DEFINE_OPCODE(op_neq) {
   1268         /* neq dst(r) src1(r) src2(r)
   1269 
   1270            Checks whether register src1 and register src2 are not
   1271            equal, as with the ECMAScript '!=' operator, and puts the
   1272            result as a boolean in register dst.
   1273         */
   1274         int dst = vPC[1].u.operand;
   1275         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1276         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1277         if (src1.isInt32() && src2.isInt32())
   1278             callFrame->r(dst) = jsBoolean(src1.asInt32() != src2.asInt32());
   1279         else {
   1280             JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2));
   1281             CHECK_FOR_EXCEPTION();
   1282             callFrame->r(dst) = result;
   1283         }
   1284 
   1285         vPC += OPCODE_LENGTH(op_neq);
   1286         NEXT_INSTRUCTION();
   1287     }
   1288     DEFINE_OPCODE(op_neq_null) {
   1289         /* neq_null dst(r) src(r)
   1290 
   1291            Checks whether register src is not null, as with the ECMAScript '!='
   1292            operator, and puts the result as a boolean in register dst.
   1293         */
   1294         int dst = vPC[1].u.operand;
   1295         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
   1296 
   1297         if (src.isUndefinedOrNull()) {
   1298             callFrame->r(dst) = jsBoolean(false);
   1299             vPC += OPCODE_LENGTH(op_neq_null);
   1300             NEXT_INSTRUCTION();
   1301         }
   1302 
   1303         callFrame->r(dst) = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined());
   1304         vPC += OPCODE_LENGTH(op_neq_null);
   1305         NEXT_INSTRUCTION();
   1306     }
   1307     DEFINE_OPCODE(op_stricteq) {
   1308         /* stricteq dst(r) src1(r) src2(r)
   1309 
   1310            Checks whether register src1 and register src2 are strictly
   1311            equal, as with the ECMAScript '===' operator, and puts the
   1312            result as a boolean in register dst.
   1313         */
   1314         int dst = vPC[1].u.operand;
   1315         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1316         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1317         callFrame->r(dst) = jsBoolean(JSValue::strictEqual(callFrame, src1, src2));
   1318 
   1319         vPC += OPCODE_LENGTH(op_stricteq);
   1320         NEXT_INSTRUCTION();
   1321     }
   1322     DEFINE_OPCODE(op_nstricteq) {
   1323         /* nstricteq dst(r) src1(r) src2(r)
   1324 
   1325            Checks whether register src1 and register src2 are not
   1326            strictly equal, as with the ECMAScript '!==' operator, and
   1327            puts the result as a boolean in register dst.
   1328         */
   1329         int dst = vPC[1].u.operand;
   1330         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1331         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1332         callFrame->r(dst) = jsBoolean(!JSValue::strictEqual(callFrame, src1, src2));
   1333 
   1334         vPC += OPCODE_LENGTH(op_nstricteq);
   1335         NEXT_INSTRUCTION();
   1336     }
   1337     DEFINE_OPCODE(op_less) {
   1338         /* less dst(r) src1(r) src2(r)
   1339 
   1340            Checks whether register src1 is less than register src2, as
   1341            with the ECMAScript '<' operator, and puts the result as
   1342            a boolean in register dst.
   1343         */
   1344         int dst = vPC[1].u.operand;
   1345         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1346         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1347         JSValue result = jsBoolean(jsLess(callFrame, src1, src2));
   1348         CHECK_FOR_EXCEPTION();
   1349         callFrame->r(dst) = result;
   1350 
   1351         vPC += OPCODE_LENGTH(op_less);
   1352         NEXT_INSTRUCTION();
   1353     }
   1354     DEFINE_OPCODE(op_lesseq) {
   1355         /* lesseq dst(r) src1(r) src2(r)
   1356 
   1357            Checks whether register src1 is less than or equal to
   1358            register src2, as with the ECMAScript '<=' operator, and
   1359            puts the result as a boolean in register dst.
   1360         */
   1361         int dst = vPC[1].u.operand;
   1362         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1363         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1364         JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2));
   1365         CHECK_FOR_EXCEPTION();
   1366         callFrame->r(dst) = result;
   1367 
   1368         vPC += OPCODE_LENGTH(op_lesseq);
   1369         NEXT_INSTRUCTION();
   1370     }
   1371     DEFINE_OPCODE(op_pre_inc) {
   1372         /* pre_inc srcDst(r)
   1373 
   1374            Converts register srcDst to number, adds one, and puts the result
   1375            back in register srcDst.
   1376         */
   1377         int srcDst = vPC[1].u.operand;
   1378         JSValue v = callFrame->r(srcDst).jsValue();
   1379         if (v.isInt32() && v.asInt32() < INT_MAX)
   1380             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
   1381         else {
   1382             JSValue result = jsNumber(callFrame, v.toNumber(callFrame) + 1);
   1383             CHECK_FOR_EXCEPTION();
   1384             callFrame->r(srcDst) = result;
   1385         }
   1386 
   1387         vPC += OPCODE_LENGTH(op_pre_inc);
   1388         NEXT_INSTRUCTION();
   1389     }
   1390     DEFINE_OPCODE(op_pre_dec) {
   1391         /* pre_dec srcDst(r)
   1392 
   1393            Converts register srcDst to number, subtracts one, and puts the result
   1394            back in register srcDst.
   1395         */
   1396         int srcDst = vPC[1].u.operand;
   1397         JSValue v = callFrame->r(srcDst).jsValue();
   1398         if (v.isInt32() && v.asInt32() > INT_MIN)
   1399             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
   1400         else {
   1401             JSValue result = jsNumber(callFrame, v.toNumber(callFrame) - 1);
   1402             CHECK_FOR_EXCEPTION();
   1403             callFrame->r(srcDst) = result;
   1404         }
   1405 
   1406         vPC += OPCODE_LENGTH(op_pre_dec);
   1407         NEXT_INSTRUCTION();
   1408     }
   1409     DEFINE_OPCODE(op_post_inc) {
   1410         /* post_inc dst(r) srcDst(r)
   1411 
   1412            Converts register srcDst to number. The number itself is
   1413            written to register dst, and the number plus one is written
   1414            back to register srcDst.
   1415         */
   1416         int dst = vPC[1].u.operand;
   1417         int srcDst = vPC[2].u.operand;
   1418         JSValue v = callFrame->r(srcDst).jsValue();
   1419         if (v.isInt32() && v.asInt32() < INT_MAX) {
   1420             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
   1421             callFrame->r(dst) = v;
   1422         } else {
   1423             JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
   1424             CHECK_FOR_EXCEPTION();
   1425             callFrame->r(srcDst) = jsNumber(callFrame, number.uncheckedGetNumber() + 1);
   1426             callFrame->r(dst) = number;
   1427         }
   1428 
   1429         vPC += OPCODE_LENGTH(op_post_inc);
   1430         NEXT_INSTRUCTION();
   1431     }
   1432     DEFINE_OPCODE(op_post_dec) {
   1433         /* post_dec dst(r) srcDst(r)
   1434 
   1435            Converts register srcDst to number. The number itself is
   1436            written to register dst, and the number minus one is written
   1437            back to register srcDst.
   1438         */
   1439         int dst = vPC[1].u.operand;
   1440         int srcDst = vPC[2].u.operand;
   1441         JSValue v = callFrame->r(srcDst).jsValue();
   1442         if (v.isInt32() && v.asInt32() > INT_MIN) {
   1443             callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
   1444             callFrame->r(dst) = v;
   1445         } else {
   1446             JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
   1447             CHECK_FOR_EXCEPTION();
   1448             callFrame->r(srcDst) = jsNumber(callFrame, number.uncheckedGetNumber() - 1);
   1449             callFrame->r(dst) = number;
   1450         }
   1451 
   1452         vPC += OPCODE_LENGTH(op_post_dec);
   1453         NEXT_INSTRUCTION();
   1454     }
   1455     DEFINE_OPCODE(op_to_jsnumber) {
   1456         /* to_jsnumber dst(r) src(r)
   1457 
   1458            Converts register src to number, and puts the result
   1459            in register dst.
   1460         */
   1461         int dst = vPC[1].u.operand;
   1462         int src = vPC[2].u.operand;
   1463 
   1464         JSValue srcVal = callFrame->r(src).jsValue();
   1465 
   1466         if (LIKELY(srcVal.isNumber()))
   1467             callFrame->r(dst) = callFrame->r(src);
   1468         else {
   1469             JSValue result = srcVal.toJSNumber(callFrame);
   1470             CHECK_FOR_EXCEPTION();
   1471             callFrame->r(dst) = result;
   1472         }
   1473 
   1474         vPC += OPCODE_LENGTH(op_to_jsnumber);
   1475         NEXT_INSTRUCTION();
   1476     }
   1477     DEFINE_OPCODE(op_negate) {
   1478         /* negate dst(r) src(r)
   1479 
   1480            Converts register src to number, negates it, and puts the
   1481            result in register dst.
   1482         */
   1483         int dst = vPC[1].u.operand;
   1484         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
   1485         if (src.isInt32() && src.asInt32())
   1486             callFrame->r(dst) = jsNumber(callFrame, -src.asInt32());
   1487         else {
   1488             JSValue result = jsNumber(callFrame, -src.toNumber(callFrame));
   1489             CHECK_FOR_EXCEPTION();
   1490             callFrame->r(dst) = result;
   1491         }
   1492 
   1493         vPC += OPCODE_LENGTH(op_negate);
   1494         NEXT_INSTRUCTION();
   1495     }
   1496     DEFINE_OPCODE(op_add) {
   1497         /* add dst(r) src1(r) src2(r)
   1498 
   1499            Adds register src1 and register src2, and puts the result
   1500            in register dst. (JS add may be string concatenation or
   1501            numeric add, depending on the types of the operands.)
   1502         */
   1503         int dst = vPC[1].u.operand;
   1504         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1505         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1506         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
   1507             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() + src2.asInt32());
   1508         else {
   1509             JSValue result = jsAdd(callFrame, src1, src2);
   1510             CHECK_FOR_EXCEPTION();
   1511             callFrame->r(dst) = result;
   1512         }
   1513         vPC += OPCODE_LENGTH(op_add);
   1514         NEXT_INSTRUCTION();
   1515     }
   1516     DEFINE_OPCODE(op_mul) {
   1517         /* mul dst(r) src1(r) src2(r)
   1518 
   1519            Multiplies register src1 and register src2 (converted to
   1520            numbers), and puts the product in register dst.
   1521         */
   1522         int dst = vPC[1].u.operand;
   1523         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1524         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1525         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow
   1526                 callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() * src2.asInt32());
   1527         else {
   1528             JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame));
   1529             CHECK_FOR_EXCEPTION();
   1530             callFrame->r(dst) = result;
   1531         }
   1532 
   1533         vPC += OPCODE_LENGTH(op_mul);
   1534         NEXT_INSTRUCTION();
   1535     }
   1536     DEFINE_OPCODE(op_div) {
   1537         /* div dst(r) dividend(r) divisor(r)
   1538 
   1539            Divides register dividend (converted to number) by the
   1540            register divisor (converted to number), and puts the
   1541            quotient in register dst.
   1542         */
   1543         int dst = vPC[1].u.operand;
   1544         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
   1545         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
   1546 
   1547         JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
   1548         CHECK_FOR_EXCEPTION();
   1549         callFrame->r(dst) = result;
   1550 
   1551         vPC += OPCODE_LENGTH(op_div);
   1552         NEXT_INSTRUCTION();
   1553     }
   1554     DEFINE_OPCODE(op_mod) {
   1555         /* mod dst(r) dividend(r) divisor(r)
   1556 
   1557            Divides register dividend (converted to number) by
   1558            register divisor (converted to number), and puts the
   1559            remainder in register dst.
   1560         */
   1561         int dst = vPC[1].u.operand;
   1562         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
   1563         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
   1564 
   1565         if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) {
   1566             JSValue result = jsNumber(callFrame, dividend.asInt32() % divisor.asInt32());
   1567             ASSERT(result);
   1568             callFrame->r(dst) = result;
   1569             vPC += OPCODE_LENGTH(op_mod);
   1570             NEXT_INSTRUCTION();
   1571         }
   1572 
   1573         // Conversion to double must happen outside the call to fmod since the
   1574         // order of argument evaluation is not guaranteed.
   1575         double d1 = dividend.toNumber(callFrame);
   1576         double d2 = divisor.toNumber(callFrame);
   1577         JSValue result = jsNumber(callFrame, fmod(d1, d2));
   1578         CHECK_FOR_EXCEPTION();
   1579         callFrame->r(dst) = result;
   1580         vPC += OPCODE_LENGTH(op_mod);
   1581         NEXT_INSTRUCTION();
   1582     }
   1583     DEFINE_OPCODE(op_sub) {
   1584         /* sub dst(r) src1(r) src2(r)
   1585 
   1586            Subtracts register src2 (converted to number) from register
   1587            src1 (converted to number), and puts the difference in
   1588            register dst.
   1589         */
   1590         int dst = vPC[1].u.operand;
   1591         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1592         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1593         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
   1594             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() - src2.asInt32());
   1595         else {
   1596             JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
   1597             CHECK_FOR_EXCEPTION();
   1598             callFrame->r(dst) = result;
   1599         }
   1600         vPC += OPCODE_LENGTH(op_sub);
   1601         NEXT_INSTRUCTION();
   1602     }
   1603     DEFINE_OPCODE(op_lshift) {
   1604         /* lshift dst(r) val(r) shift(r)
   1605 
   1606            Performs left shift of register val (converted to int32) by
   1607            register shift (converted to uint32), and puts the result
   1608            in register dst.
   1609         */
   1610         int dst = vPC[1].u.operand;
   1611         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
   1612         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
   1613 
   1614         if (val.isInt32() && shift.isInt32())
   1615             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() << (shift.asInt32() & 0x1f));
   1616         else {
   1617             JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
   1618             CHECK_FOR_EXCEPTION();
   1619             callFrame->r(dst) = result;
   1620         }
   1621 
   1622         vPC += OPCODE_LENGTH(op_lshift);
   1623         NEXT_INSTRUCTION();
   1624     }
   1625     DEFINE_OPCODE(op_rshift) {
   1626         /* rshift dst(r) val(r) shift(r)
   1627 
   1628            Performs arithmetic right shift of register val (converted
   1629            to int32) by register shift (converted to
   1630            uint32), and puts the result in register dst.
   1631         */
   1632         int dst = vPC[1].u.operand;
   1633         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
   1634         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
   1635 
   1636         if (val.isInt32() && shift.isInt32())
   1637             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
   1638         else {
   1639             JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
   1640             CHECK_FOR_EXCEPTION();
   1641             callFrame->r(dst) = result;
   1642         }
   1643 
   1644         vPC += OPCODE_LENGTH(op_rshift);
   1645         NEXT_INSTRUCTION();
   1646     }
   1647     DEFINE_OPCODE(op_urshift) {
   1648         /* rshift dst(r) val(r) shift(r)
   1649 
   1650            Performs logical right shift of register val (converted
   1651            to uint32) by register shift (converted to
   1652            uint32), and puts the result in register dst.
   1653         */
   1654         int dst = vPC[1].u.operand;
   1655         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
   1656         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
   1657         if (val.isUInt32() && shift.isInt32())
   1658             callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
   1659         else {
   1660             JSValue result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
   1661             CHECK_FOR_EXCEPTION();
   1662             callFrame->r(dst) = result;
   1663         }
   1664 
   1665         vPC += OPCODE_LENGTH(op_urshift);
   1666         NEXT_INSTRUCTION();
   1667     }
   1668     DEFINE_OPCODE(op_bitand) {
   1669         /* bitand dst(r) src1(r) src2(r)
   1670 
   1671            Computes bitwise AND of register src1 (converted to int32)
   1672            and register src2 (converted to int32), and puts the result
   1673            in register dst.
   1674         */
   1675         int dst = vPC[1].u.operand;
   1676         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1677         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1678         if (src1.isInt32() && src2.isInt32())
   1679             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() & src2.asInt32());
   1680         else {
   1681             JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame));
   1682             CHECK_FOR_EXCEPTION();
   1683             callFrame->r(dst) = result;
   1684         }
   1685 
   1686         vPC += OPCODE_LENGTH(op_bitand);
   1687         NEXT_INSTRUCTION();
   1688     }
   1689     DEFINE_OPCODE(op_bitxor) {
   1690         /* bitxor dst(r) src1(r) src2(r)
   1691 
   1692            Computes bitwise XOR of register src1 (converted to int32)
   1693            and register src2 (converted to int32), and puts the result
   1694            in register dst.
   1695         */
   1696         int dst = vPC[1].u.operand;
   1697         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1698         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1699         if (src1.isInt32() && src2.isInt32())
   1700             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() ^ src2.asInt32());
   1701         else {
   1702             JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
   1703             CHECK_FOR_EXCEPTION();
   1704             callFrame->r(dst) = result;
   1705         }
   1706 
   1707         vPC += OPCODE_LENGTH(op_bitxor);
   1708         NEXT_INSTRUCTION();
   1709     }
   1710     DEFINE_OPCODE(op_bitor) {
   1711         /* bitor dst(r) src1(r) src2(r)
   1712 
   1713            Computes bitwise OR of register src1 (converted to int32)
   1714            and register src2 (converted to int32), and puts the
   1715            result in register dst.
   1716         */
   1717         int dst = vPC[1].u.operand;
   1718         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1719         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1720         if (src1.isInt32() && src2.isInt32())
   1721             callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() | src2.asInt32());
   1722         else {
   1723             JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame));
   1724             CHECK_FOR_EXCEPTION();
   1725             callFrame->r(dst) = result;
   1726         }
   1727 
   1728         vPC += OPCODE_LENGTH(op_bitor);
   1729         NEXT_INSTRUCTION();
   1730     }
   1731     DEFINE_OPCODE(op_bitnot) {
   1732         /* bitnot dst(r) src(r)
   1733 
   1734            Computes bitwise NOT of register src1 (converted to int32),
   1735            and puts the result in register dst.
   1736         */
   1737         int dst = vPC[1].u.operand;
   1738         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
   1739         if (src.isInt32())
   1740             callFrame->r(dst) = jsNumber(callFrame, ~src.asInt32());
   1741         else {
   1742             JSValue result = jsNumber(callFrame, ~src.toInt32(callFrame));
   1743             CHECK_FOR_EXCEPTION();
   1744             callFrame->r(dst) = result;
   1745         }
   1746         vPC += OPCODE_LENGTH(op_bitnot);
   1747         NEXT_INSTRUCTION();
   1748     }
   1749     DEFINE_OPCODE(op_not) {
   1750         /* not dst(r) src(r)
   1751 
   1752            Computes logical NOT of register src (converted to
   1753            boolean), and puts the result in register dst.
   1754         */
   1755         int dst = vPC[1].u.operand;
   1756         int src = vPC[2].u.operand;
   1757         JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame));
   1758         CHECK_FOR_EXCEPTION();
   1759         callFrame->r(dst) = result;
   1760 
   1761         vPC += OPCODE_LENGTH(op_not);
   1762         NEXT_INSTRUCTION();
   1763     }
   1764     DEFINE_OPCODE(op_instanceof) {
   1765         /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
   1766 
   1767            Tests whether register value is an instance of register
   1768            constructor, and puts the boolean result in register
   1769            dst. Register constructorProto must contain the "prototype"
   1770            property (not the actual prototype) of the object in
   1771            register constructor. This lookup is separated so that
   1772            polymorphic inline caching can apply.
   1773 
   1774            Raises an exception if register constructor is not an
   1775            object.
   1776         */
   1777         int dst = vPC[1].u.operand;
   1778         int value = vPC[2].u.operand;
   1779         int base = vPC[3].u.operand;
   1780         int baseProto = vPC[4].u.operand;
   1781 
   1782         JSValue baseVal = callFrame->r(base).jsValue();
   1783 
   1784         if (isInvalidParamForInstanceOf(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
   1785             goto vm_throw;
   1786 
   1787         bool result = asObject(baseVal)->hasInstance(callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
   1788         CHECK_FOR_EXCEPTION();
   1789         callFrame->r(dst) = jsBoolean(result);
   1790 
   1791         vPC += OPCODE_LENGTH(op_instanceof);
   1792         NEXT_INSTRUCTION();
   1793     }
   1794     DEFINE_OPCODE(op_typeof) {
   1795         /* typeof dst(r) src(r)
   1796 
   1797            Determines the type string for src according to ECMAScript
   1798            rules, and puts the result in register dst.
   1799         */
   1800         int dst = vPC[1].u.operand;
   1801         int src = vPC[2].u.operand;
   1802         callFrame->r(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue()));
   1803 
   1804         vPC += OPCODE_LENGTH(op_typeof);
   1805         NEXT_INSTRUCTION();
   1806     }
   1807     DEFINE_OPCODE(op_is_undefined) {
   1808         /* is_undefined dst(r) src(r)
   1809 
   1810            Determines whether the type string for src according to
   1811            the ECMAScript rules is "undefined", and puts the result
   1812            in register dst.
   1813         */
   1814         int dst = vPC[1].u.operand;
   1815         int src = vPC[2].u.operand;
   1816         JSValue v = callFrame->r(src).jsValue();
   1817         callFrame->r(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
   1818 
   1819         vPC += OPCODE_LENGTH(op_is_undefined);
   1820         NEXT_INSTRUCTION();
   1821     }
   1822     DEFINE_OPCODE(op_is_boolean) {
   1823         /* is_boolean dst(r) src(r)
   1824 
   1825            Determines whether the type string for src according to
   1826            the ECMAScript rules is "boolean", and puts the result
   1827            in register dst.
   1828         */
   1829         int dst = vPC[1].u.operand;
   1830         int src = vPC[2].u.operand;
   1831         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean());
   1832 
   1833         vPC += OPCODE_LENGTH(op_is_boolean);
   1834         NEXT_INSTRUCTION();
   1835     }
   1836     DEFINE_OPCODE(op_is_number) {
   1837         /* is_number dst(r) src(r)
   1838 
   1839            Determines whether the type string for src according to
   1840            the ECMAScript rules is "number", and puts the result
   1841            in register dst.
   1842         */
   1843         int dst = vPC[1].u.operand;
   1844         int src = vPC[2].u.operand;
   1845         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber());
   1846 
   1847         vPC += OPCODE_LENGTH(op_is_number);
   1848         NEXT_INSTRUCTION();
   1849     }
   1850     DEFINE_OPCODE(op_is_string) {
   1851         /* is_string dst(r) src(r)
   1852 
   1853            Determines whether the type string for src according to
   1854            the ECMAScript rules is "string", and puts the result
   1855            in register dst.
   1856         */
   1857         int dst = vPC[1].u.operand;
   1858         int src = vPC[2].u.operand;
   1859         callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isString());
   1860 
   1861         vPC += OPCODE_LENGTH(op_is_string);
   1862         NEXT_INSTRUCTION();
   1863     }
   1864     DEFINE_OPCODE(op_is_object) {
   1865         /* is_object dst(r) src(r)
   1866 
   1867            Determines whether the type string for src according to
   1868            the ECMAScript rules is "object", and puts the result
   1869            in register dst.
   1870         */
   1871         int dst = vPC[1].u.operand;
   1872         int src = vPC[2].u.operand;
   1873         callFrame->r(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue()));
   1874 
   1875         vPC += OPCODE_LENGTH(op_is_object);
   1876         NEXT_INSTRUCTION();
   1877     }
   1878     DEFINE_OPCODE(op_is_function) {
   1879         /* is_function dst(r) src(r)
   1880 
   1881            Determines whether the type string for src according to
   1882            the ECMAScript rules is "function", and puts the result
   1883            in register dst.
   1884         */
   1885         int dst = vPC[1].u.operand;
   1886         int src = vPC[2].u.operand;
   1887         callFrame->r(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue()));
   1888 
   1889         vPC += OPCODE_LENGTH(op_is_function);
   1890         NEXT_INSTRUCTION();
   1891     }
   1892     DEFINE_OPCODE(op_in) {
   1893         /* in dst(r) property(r) base(r)
   1894 
   1895            Tests whether register base has a property named register
   1896            property, and puts the boolean result in register dst.
   1897 
   1898            Raises an exception if register constructor is not an
   1899            object.
   1900         */
   1901         int dst = vPC[1].u.operand;
   1902         int property = vPC[2].u.operand;
   1903         int base = vPC[3].u.operand;
   1904 
   1905         JSValue baseVal = callFrame->r(base).jsValue();
   1906         if (isInvalidParamForIn(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
   1907             goto vm_throw;
   1908 
   1909         JSObject* baseObj = asObject(baseVal);
   1910 
   1911         JSValue propName = callFrame->r(property).jsValue();
   1912 
   1913         uint32_t i;
   1914         if (propName.getUInt32(i))
   1915             callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
   1916         else {
   1917             Identifier property(callFrame, propName.toString(callFrame));
   1918             CHECK_FOR_EXCEPTION();
   1919             callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
   1920         }
   1921 
   1922         vPC += OPCODE_LENGTH(op_in);
   1923         NEXT_INSTRUCTION();
   1924     }
   1925     DEFINE_OPCODE(op_resolve) {
   1926         /* resolve dst(r) property(id)
   1927 
   1928            Looks up the property named by identifier property in the
   1929            scope chain, and writes the resulting value to register
   1930            dst. If the property is not found, raises an exception.
   1931         */
   1932         if (UNLIKELY(!resolve(callFrame, vPC, exceptionValue)))
   1933             goto vm_throw;
   1934 
   1935         vPC += OPCODE_LENGTH(op_resolve);
   1936         NEXT_INSTRUCTION();
   1937     }
   1938     DEFINE_OPCODE(op_resolve_skip) {
   1939         /* resolve_skip dst(r) property(id) skip(n)
   1940 
   1941          Looks up the property named by identifier property in the
   1942          scope chain skipping the top 'skip' levels, and writes the resulting
   1943          value to register dst. If the property is not found, raises an exception.
   1944          */
   1945         if (UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue)))
   1946             goto vm_throw;
   1947 
   1948         vPC += OPCODE_LENGTH(op_resolve_skip);
   1949 
   1950         NEXT_INSTRUCTION();
   1951     }
   1952     DEFINE_OPCODE(op_resolve_global) {
   1953         /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n)
   1954 
   1955            Performs a dynamic property lookup for the given property, on the provided
   1956            global object.  If structure matches the Structure of the global then perform
   1957            a fast lookup using the case offset, otherwise fall back to a full resolve and
   1958            cache the new structure and offset
   1959          */
   1960         if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue)))
   1961             goto vm_throw;
   1962 
   1963         vPC += OPCODE_LENGTH(op_resolve_global);
   1964 
   1965         NEXT_INSTRUCTION();
   1966     }
   1967     DEFINE_OPCODE(op_get_global_var) {
   1968         /* get_global_var dst(r) globalObject(c) index(n)
   1969 
   1970            Gets the global var at global slot index and places it in register dst.
   1971          */
   1972         int dst = vPC[1].u.operand;
   1973         JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[2].u.jsCell);
   1974         ASSERT(scope->isGlobalObject());
   1975         int index = vPC[3].u.operand;
   1976 
   1977         callFrame->r(dst) = scope->registerAt(index);
   1978         vPC += OPCODE_LENGTH(op_get_global_var);
   1979         NEXT_INSTRUCTION();
   1980     }
   1981     DEFINE_OPCODE(op_put_global_var) {
   1982         /* put_global_var globalObject(c) index(n) value(r)
   1983 
   1984            Puts value into global slot index.
   1985          */
   1986         JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[1].u.jsCell);
   1987         ASSERT(scope->isGlobalObject());
   1988         int index = vPC[2].u.operand;
   1989         int value = vPC[3].u.operand;
   1990 
   1991         scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
   1992         vPC += OPCODE_LENGTH(op_put_global_var);
   1993         NEXT_INSTRUCTION();
   1994     }
   1995     DEFINE_OPCODE(op_get_scoped_var) {
   1996         /* get_scoped_var dst(r) index(n) skip(n)
   1997 
   1998          Loads the contents of the index-th local from the scope skip nodes from
   1999          the top of the scope chain, and places it in register dst
   2000          */
   2001         int dst = vPC[1].u.operand;
   2002         int index = vPC[2].u.operand;
   2003         int skip = vPC[3].u.operand + callFrame->codeBlock()->needsFullScopeChain();
   2004 
   2005         ScopeChainNode* scopeChain = callFrame->scopeChain();
   2006         ScopeChainIterator iter = scopeChain->begin();
   2007         ScopeChainIterator end = scopeChain->end();
   2008         ASSERT(iter != end);
   2009         while (skip--) {
   2010             ++iter;
   2011             ASSERT(iter != end);
   2012         }
   2013 
   2014         ASSERT((*iter)->isVariableObject());
   2015         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
   2016         callFrame->r(dst) = scope->registerAt(index);
   2017         vPC += OPCODE_LENGTH(op_get_scoped_var);
   2018         NEXT_INSTRUCTION();
   2019     }
   2020     DEFINE_OPCODE(op_put_scoped_var) {
   2021         /* put_scoped_var index(n) skip(n) value(r)
   2022 
   2023          */
   2024         int index = vPC[1].u.operand;
   2025         int skip = vPC[2].u.operand + callFrame->codeBlock()->needsFullScopeChain();
   2026         int value = vPC[3].u.operand;
   2027 
   2028         ScopeChainNode* scopeChain = callFrame->scopeChain();
   2029         ScopeChainIterator iter = scopeChain->begin();
   2030         ScopeChainIterator end = scopeChain->end();
   2031         ASSERT(iter != end);
   2032         while (skip--) {
   2033             ++iter;
   2034             ASSERT(iter != end);
   2035         }
   2036 
   2037         ASSERT((*iter)->isVariableObject());
   2038         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
   2039         scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
   2040         vPC += OPCODE_LENGTH(op_put_scoped_var);
   2041         NEXT_INSTRUCTION();
   2042     }
   2043     DEFINE_OPCODE(op_resolve_base) {
   2044         /* resolve_base dst(r) property(id)
   2045 
   2046            Searches the scope chain for an object containing
   2047            identifier property, and if one is found, writes it to
   2048            register dst. If none is found, the outermost scope (which
   2049            will be the global object) is stored in register dst.
   2050         */
   2051         resolveBase(callFrame, vPC);
   2052 
   2053         vPC += OPCODE_LENGTH(op_resolve_base);
   2054         NEXT_INSTRUCTION();
   2055     }
   2056     DEFINE_OPCODE(op_resolve_with_base) {
   2057         /* resolve_with_base baseDst(r) propDst(r) property(id)
   2058 
   2059            Searches the scope chain for an object containing
   2060            identifier property, and if one is found, writes it to
   2061            register srcDst, and the retrieved property value to register
   2062            propDst. If the property is not found, raises an exception.
   2063 
   2064            This is more efficient than doing resolve_base followed by
   2065            resolve, or resolve_base followed by get_by_id, as it
   2066            avoids duplicate hash lookups.
   2067         */
   2068         if (UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue)))
   2069             goto vm_throw;
   2070 
   2071         vPC += OPCODE_LENGTH(op_resolve_with_base);
   2072         NEXT_INSTRUCTION();
   2073     }
   2074     DEFINE_OPCODE(op_get_by_id) {
   2075         /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n)
   2076 
   2077            Generic property access: Gets the property named by identifier
   2078            property from the value base, and puts the result in register dst.
   2079         */
   2080         int dst = vPC[1].u.operand;
   2081         int base = vPC[2].u.operand;
   2082         int property = vPC[3].u.operand;
   2083 
   2084         CodeBlock* codeBlock = callFrame->codeBlock();
   2085         Identifier& ident = codeBlock->identifier(property);
   2086         JSValue baseValue = callFrame->r(base).jsValue();
   2087         PropertySlot slot(baseValue);
   2088         JSValue result = baseValue.get(callFrame, ident, slot);
   2089         CHECK_FOR_EXCEPTION();
   2090 
   2091         tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
   2092 
   2093         callFrame->r(dst) = result;
   2094         vPC += OPCODE_LENGTH(op_get_by_id);
   2095         NEXT_INSTRUCTION();
   2096     }
   2097     DEFINE_OPCODE(op_get_by_id_self) {
   2098         /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
   2099 
   2100            Cached property access: Attempts to get a cached property from the
   2101            value base. If the cache misses, op_get_by_id_self reverts to
   2102            op_get_by_id.
   2103         */
   2104         int base = vPC[2].u.operand;
   2105         JSValue baseValue = callFrame->r(base).jsValue();
   2106 
   2107         if (LIKELY(baseValue.isCell())) {
   2108             JSCell* baseCell = asCell(baseValue);
   2109             Structure* structure = vPC[4].u.structure;
   2110 
   2111             if (LIKELY(baseCell->structure() == structure)) {
   2112                 ASSERT(baseCell->isObject());
   2113                 JSObject* baseObject = asObject(baseCell);
   2114                 int dst = vPC[1].u.operand;
   2115                 int offset = vPC[5].u.operand;
   2116 
   2117                 ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
   2118                 callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
   2119 
   2120                 vPC += OPCODE_LENGTH(op_get_by_id_self);
   2121                 NEXT_INSTRUCTION();
   2122             }
   2123         }
   2124 
   2125         uncacheGetByID(callFrame->codeBlock(), vPC);
   2126         NEXT_INSTRUCTION();
   2127     }
   2128     DEFINE_OPCODE(op_get_by_id_proto) {
   2129         /* op_get_by_id_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
   2130 
   2131            Cached property access: Attempts to get a cached property from the
   2132            value base's prototype. If the cache misses, op_get_by_id_proto
   2133            reverts to op_get_by_id.
   2134         */
   2135         int base = vPC[2].u.operand;
   2136         JSValue baseValue = callFrame->r(base).jsValue();
   2137 
   2138         if (LIKELY(baseValue.isCell())) {
   2139             JSCell* baseCell = asCell(baseValue);
   2140             Structure* structure = vPC[4].u.structure;
   2141 
   2142             if (LIKELY(baseCell->structure() == structure)) {
   2143                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
   2144                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
   2145                 Structure* prototypeStructure = vPC[5].u.structure;
   2146 
   2147                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
   2148                     int dst = vPC[1].u.operand;
   2149                     int offset = vPC[6].u.operand;
   2150 
   2151                     ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
   2152                     ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
   2153                     callFrame->r(dst) = JSValue(protoObject->getDirectOffset(offset));
   2154 
   2155                     vPC += OPCODE_LENGTH(op_get_by_id_proto);
   2156                     NEXT_INSTRUCTION();
   2157                 }
   2158             }
   2159         }
   2160 
   2161         uncacheGetByID(callFrame->codeBlock(), vPC);
   2162         NEXT_INSTRUCTION();
   2163     }
   2164     DEFINE_OPCODE(op_get_by_id_self_list) {
   2165         // Polymorphic self access caching currently only supported when JITting.
   2166         ASSERT_NOT_REACHED();
   2167         // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
   2168         vPC += OPCODE_LENGTH(op_get_by_id_self_list);
   2169         NEXT_INSTRUCTION();
   2170     }
   2171     DEFINE_OPCODE(op_get_by_id_proto_list) {
   2172         // Polymorphic prototype access caching currently only supported when JITting.
   2173         ASSERT_NOT_REACHED();
   2174         // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
   2175         vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
   2176         NEXT_INSTRUCTION();
   2177     }
   2178     DEFINE_OPCODE(op_get_by_id_chain) {
   2179         /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
   2180 
   2181            Cached property access: Attempts to get a cached property from the
   2182            value base's prototype chain. If the cache misses, op_get_by_id_chain
   2183            reverts to op_get_by_id.
   2184         */
   2185         int base = vPC[2].u.operand;
   2186         JSValue baseValue = callFrame->r(base).jsValue();
   2187 
   2188         if (LIKELY(baseValue.isCell())) {
   2189             JSCell* baseCell = asCell(baseValue);
   2190             Structure* structure = vPC[4].u.structure;
   2191 
   2192             if (LIKELY(baseCell->structure() == structure)) {
   2193                 RefPtr<Structure>* it = vPC[5].u.structureChain->head();
   2194                 size_t count = vPC[6].u.operand;
   2195                 RefPtr<Structure>* end = it + count;
   2196 
   2197                 while (true) {
   2198                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
   2199 
   2200                     if (UNLIKELY(baseObject->structure() != (*it).get()))
   2201                         break;
   2202 
   2203                     if (++it == end) {
   2204                         int dst = vPC[1].u.operand;
   2205                         int offset = vPC[7].u.operand;
   2206 
   2207                         ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
   2208                         ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
   2209                         callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
   2210 
   2211                         vPC += OPCODE_LENGTH(op_get_by_id_chain);
   2212                         NEXT_INSTRUCTION();
   2213                     }
   2214 
   2215                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
   2216                     baseCell = baseObject;
   2217                 }
   2218             }
   2219         }
   2220 
   2221         uncacheGetByID(callFrame->codeBlock(), vPC);
   2222         NEXT_INSTRUCTION();
   2223     }
   2224     DEFINE_OPCODE(op_get_by_id_generic) {
   2225         /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
   2226 
   2227            Generic property access: Gets the property named by identifier
   2228            property from the value base, and puts the result in register dst.
   2229         */
   2230         int dst = vPC[1].u.operand;
   2231         int base = vPC[2].u.operand;
   2232         int property = vPC[3].u.operand;
   2233 
   2234         Identifier& ident = callFrame->codeBlock()->identifier(property);
   2235         JSValue baseValue = callFrame->r(base).jsValue();
   2236         PropertySlot slot(baseValue);
   2237         JSValue result = baseValue.get(callFrame, ident, slot);
   2238         CHECK_FOR_EXCEPTION();
   2239 
   2240         callFrame->r(dst) = result;
   2241         vPC += OPCODE_LENGTH(op_get_by_id_generic);
   2242         NEXT_INSTRUCTION();
   2243     }
   2244     DEFINE_OPCODE(op_get_array_length) {
   2245         /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
   2246 
   2247            Cached property access: Gets the length of the array in register base,
   2248            and puts the result in register dst. If register base does not hold
   2249            an array, op_get_array_length reverts to op_get_by_id.
   2250         */
   2251 
   2252         int base = vPC[2].u.operand;
   2253         JSValue baseValue = callFrame->r(base).jsValue();
   2254         if (LIKELY(isJSArray(globalData, baseValue))) {
   2255             int dst = vPC[1].u.operand;
   2256             callFrame->r(dst) = jsNumber(callFrame, asArray(baseValue)->length());
   2257             vPC += OPCODE_LENGTH(op_get_array_length);
   2258             NEXT_INSTRUCTION();
   2259         }
   2260 
   2261         uncacheGetByID(callFrame->codeBlock(), vPC);
   2262         NEXT_INSTRUCTION();
   2263     }
   2264     DEFINE_OPCODE(op_get_string_length) {
   2265         /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
   2266 
   2267            Cached property access: Gets the length of the string in register base,
   2268            and puts the result in register dst. If register base does not hold
   2269            a string, op_get_string_length reverts to op_get_by_id.
   2270         */
   2271 
   2272         int base = vPC[2].u.operand;
   2273         JSValue baseValue = callFrame->r(base).jsValue();
   2274         if (LIKELY(isJSString(globalData, baseValue))) {
   2275             int dst = vPC[1].u.operand;
   2276             callFrame->r(dst) = jsNumber(callFrame, asString(baseValue)->length());
   2277             vPC += OPCODE_LENGTH(op_get_string_length);
   2278             NEXT_INSTRUCTION();
   2279         }
   2280 
   2281         uncacheGetByID(callFrame->codeBlock(), vPC);
   2282         NEXT_INSTRUCTION();
   2283     }
   2284     DEFINE_OPCODE(op_put_by_id) {
   2285         /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
   2286 
   2287            Generic property access: Sets the property named by identifier
   2288            property, belonging to register base, to register value.
   2289 
   2290            Unlike many opcodes, this one does not write any output to
   2291            the register file.
   2292         */
   2293 
   2294         int base = vPC[1].u.operand;
   2295         int property = vPC[2].u.operand;
   2296         int value = vPC[3].u.operand;
   2297 
   2298         CodeBlock* codeBlock = callFrame->codeBlock();
   2299         JSValue baseValue = callFrame->r(base).jsValue();
   2300         Identifier& ident = codeBlock->identifier(property);
   2301         PutPropertySlot slot;
   2302         baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
   2303         CHECK_FOR_EXCEPTION();
   2304 
   2305         tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
   2306 
   2307         vPC += OPCODE_LENGTH(op_put_by_id);
   2308         NEXT_INSTRUCTION();
   2309     }
   2310     DEFINE_OPCODE(op_put_by_id_transition) {
   2311         /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n)
   2312 
   2313            Cached property access: Attempts to set a new property with a cached transition
   2314            property named by identifier property, belonging to register base,
   2315            to register value. If the cache misses, op_put_by_id_transition
   2316            reverts to op_put_by_id_generic.
   2317 
   2318            Unlike many opcodes, this one does not write any output to
   2319            the register file.
   2320          */
   2321         int base = vPC[1].u.operand;
   2322         JSValue baseValue = callFrame->r(base).jsValue();
   2323 
   2324         if (LIKELY(baseValue.isCell())) {
   2325             JSCell* baseCell = asCell(baseValue);
   2326             Structure* oldStructure = vPC[4].u.structure;
   2327             Structure* newStructure = vPC[5].u.structure;
   2328 
   2329             if (LIKELY(baseCell->structure() == oldStructure)) {
   2330                 ASSERT(baseCell->isObject());
   2331                 JSObject* baseObject = asObject(baseCell);
   2332 
   2333                 RefPtr<Structure>* it = vPC[6].u.structureChain->head();
   2334 
   2335                 JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
   2336                 while (!proto.isNull()) {
   2337                     if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
   2338                         uncachePutByID(callFrame->codeBlock(), vPC);
   2339                         NEXT_INSTRUCTION();
   2340                     }
   2341                     ++it;
   2342                     proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
   2343                 }
   2344 
   2345                 baseObject->transitionTo(newStructure);
   2346 
   2347                 int value = vPC[3].u.operand;
   2348                 unsigned offset = vPC[7].u.operand;
   2349                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
   2350                 baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
   2351 
   2352                 vPC += OPCODE_LENGTH(op_put_by_id_transition);
   2353                 NEXT_INSTRUCTION();
   2354             }
   2355         }
   2356 
   2357         uncachePutByID(callFrame->codeBlock(), vPC);
   2358         NEXT_INSTRUCTION();
   2359     }
   2360     DEFINE_OPCODE(op_put_by_id_replace) {
   2361         /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n)
   2362 
   2363            Cached property access: Attempts to set a pre-existing, cached
   2364            property named by identifier property, belonging to register base,
   2365            to register value. If the cache misses, op_put_by_id_replace
   2366            reverts to op_put_by_id.
   2367 
   2368            Unlike many opcodes, this one does not write any output to
   2369            the register file.
   2370         */
   2371         int base = vPC[1].u.operand;
   2372         JSValue baseValue = callFrame->r(base).jsValue();
   2373 
   2374         if (LIKELY(baseValue.isCell())) {
   2375             JSCell* baseCell = asCell(baseValue);
   2376             Structure* structure = vPC[4].u.structure;
   2377 
   2378             if (LIKELY(baseCell->structure() == structure)) {
   2379                 ASSERT(baseCell->isObject());
   2380                 JSObject* baseObject = asObject(baseCell);
   2381                 int value = vPC[3].u.operand;
   2382                 unsigned offset = vPC[5].u.operand;
   2383 
   2384                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
   2385                 baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
   2386 
   2387                 vPC += OPCODE_LENGTH(op_put_by_id_replace);
   2388                 NEXT_INSTRUCTION();
   2389             }
   2390         }
   2391 
   2392         uncachePutByID(callFrame->codeBlock(), vPC);
   2393         NEXT_INSTRUCTION();
   2394     }
   2395     DEFINE_OPCODE(op_put_by_id_generic) {
   2396         /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
   2397 
   2398            Generic property access: Sets the property named by identifier
   2399            property, belonging to register base, to register value.
   2400 
   2401            Unlike many opcodes, this one does not write any output to
   2402            the register file.
   2403         */
   2404         int base = vPC[1].u.operand;
   2405         int property = vPC[2].u.operand;
   2406         int value = vPC[3].u.operand;
   2407 
   2408         JSValue baseValue = callFrame->r(base).jsValue();
   2409         Identifier& ident = callFrame->codeBlock()->identifier(property);
   2410         PutPropertySlot slot;
   2411         baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
   2412         CHECK_FOR_EXCEPTION();
   2413 
   2414         vPC += OPCODE_LENGTH(op_put_by_id_generic);
   2415         NEXT_INSTRUCTION();
   2416     }
   2417     DEFINE_OPCODE(op_del_by_id) {
   2418         /* del_by_id dst(r) base(r) property(id)
   2419 
   2420            Converts register base to Object, deletes the property
   2421            named by identifier property from the object, and writes a
   2422            boolean indicating success (if true) or failure (if false)
   2423            to register dst.
   2424         */
   2425         int dst = vPC[1].u.operand;
   2426         int base = vPC[2].u.operand;
   2427         int property = vPC[3].u.operand;
   2428 
   2429         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
   2430         Identifier& ident = callFrame->codeBlock()->identifier(property);
   2431         JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
   2432         CHECK_FOR_EXCEPTION();
   2433         callFrame->r(dst) = result;
   2434         vPC += OPCODE_LENGTH(op_del_by_id);
   2435         NEXT_INSTRUCTION();
   2436     }
   2437     DEFINE_OPCODE(op_get_by_pname) {
   2438         int dst = vPC[1].u.operand;
   2439         int base = vPC[2].u.operand;
   2440         int property = vPC[3].u.operand;
   2441         int expected = vPC[4].u.operand;
   2442         int iter = vPC[5].u.operand;
   2443         int i = vPC[6].u.operand;
   2444 
   2445         JSValue baseValue = callFrame->r(base).jsValue();
   2446         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
   2447         JSValue subscript = callFrame->r(property).jsValue();
   2448         JSValue expectedSubscript = callFrame->r(expected).jsValue();
   2449         int index = callFrame->r(i).i() - 1;
   2450         JSValue result;
   2451         int offset = 0;
   2452         if (subscript == expectedSubscript && baseValue.isCell() && (baseValue.asCell()->structure() == it->cachedStructure()) && it->getOffset(index, offset)) {
   2453             callFrame->r(dst) = asObject(baseValue)->getDirectOffset(offset);
   2454             vPC += OPCODE_LENGTH(op_get_by_pname);
   2455             NEXT_INSTRUCTION();
   2456         }
   2457         Identifier propertyName(callFrame, subscript.toString(callFrame));
   2458         result = baseValue.get(callFrame, propertyName);
   2459         CHECK_FOR_EXCEPTION();
   2460         callFrame->r(dst) = result;
   2461         vPC += OPCODE_LENGTH(op_get_by_pname);
   2462         NEXT_INSTRUCTION();
   2463     }
   2464     DEFINE_OPCODE(op_get_by_val) {
   2465         /* get_by_val dst(r) base(r) property(r)
   2466 
   2467            Converts register base to Object, gets the property named
   2468            by register property from the object, and puts the result
   2469            in register dst. property is nominally converted to string
   2470            but numbers are treated more efficiently.
   2471         */
   2472         int dst = vPC[1].u.operand;
   2473         int base = vPC[2].u.operand;
   2474         int property = vPC[3].u.operand;
   2475 
   2476         JSValue baseValue = callFrame->r(base).jsValue();
   2477         JSValue subscript = callFrame->r(property).jsValue();
   2478 
   2479         JSValue result;
   2480 
   2481         if (LIKELY(subscript.isUInt32())) {
   2482             uint32_t i = subscript.asUInt32();
   2483             if (isJSArray(globalData, baseValue)) {
   2484                 JSArray* jsArray = asArray(baseValue);
   2485                 if (jsArray->canGetIndex(i))
   2486                     result = jsArray->getIndex(i);
   2487                 else
   2488                     result = jsArray->JSArray::get(callFrame, i);
   2489             } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
   2490                 result = asString(baseValue)->getIndex(callFrame, i);
   2491             else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i))
   2492                 result = asByteArray(baseValue)->getIndex(callFrame, i);
   2493             else
   2494                 result = baseValue.get(callFrame, i);
   2495         } else {
   2496             Identifier property(callFrame, subscript.toString(callFrame));
   2497             result = baseValue.get(callFrame, property);
   2498         }
   2499 
   2500         CHECK_FOR_EXCEPTION();
   2501         callFrame->r(dst) = result;
   2502         vPC += OPCODE_LENGTH(op_get_by_val);
   2503         NEXT_INSTRUCTION();
   2504     }
   2505     DEFINE_OPCODE(op_put_by_val) {
   2506         /* put_by_val base(r) property(r) value(r)
   2507 
   2508            Sets register value on register base as the property named
   2509            by register property. Base is converted to object
   2510            first. register property is nominally converted to string
   2511            but numbers are treated more efficiently.
   2512 
   2513            Unlike many opcodes, this one does not write any output to
   2514            the register file.
   2515         */
   2516         int base = vPC[1].u.operand;
   2517         int property = vPC[2].u.operand;
   2518         int value = vPC[3].u.operand;
   2519 
   2520         JSValue baseValue = callFrame->r(base).jsValue();
   2521         JSValue subscript = callFrame->r(property).jsValue();
   2522 
   2523         if (LIKELY(subscript.isUInt32())) {
   2524             uint32_t i = subscript.asUInt32();
   2525             if (isJSArray(globalData, baseValue)) {
   2526                 JSArray* jsArray = asArray(baseValue);
   2527                 if (jsArray->canSetIndex(i))
   2528                     jsArray->setIndex(i, callFrame->r(value).jsValue());
   2529                 else
   2530                     jsArray->JSArray::put(callFrame, i, callFrame->r(value).jsValue());
   2531             } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
   2532                 JSByteArray* jsByteArray = asByteArray(baseValue);
   2533                 double dValue = 0;
   2534                 JSValue jsValue = callFrame->r(value).jsValue();
   2535                 if (jsValue.isInt32())
   2536                     jsByteArray->setIndex(i, jsValue.asInt32());
   2537                 else if (jsValue.getNumber(dValue))
   2538                     jsByteArray->setIndex(i, dValue);
   2539                 else
   2540                     baseValue.put(callFrame, i, jsValue);
   2541             } else
   2542                 baseValue.put(callFrame, i, callFrame->r(value).jsValue());
   2543         } else {
   2544             Identifier property(callFrame, subscript.toString(callFrame));
   2545             if (!globalData->exception) { // Don't put to an object if toString threw an exception.
   2546                 PutPropertySlot slot;
   2547                 baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot);
   2548             }
   2549         }
   2550 
   2551         CHECK_FOR_EXCEPTION();
   2552         vPC += OPCODE_LENGTH(op_put_by_val);
   2553         NEXT_INSTRUCTION();
   2554     }
   2555     DEFINE_OPCODE(op_del_by_val) {
   2556         /* del_by_val dst(r) base(r) property(r)
   2557 
   2558            Converts register base to Object, deletes the property
   2559            named by register property from the object, and writes a
   2560            boolean indicating success (if true) or failure (if false)
   2561            to register dst.
   2562         */
   2563         int dst = vPC[1].u.operand;
   2564         int base = vPC[2].u.operand;
   2565         int property = vPC[3].u.operand;
   2566 
   2567         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw
   2568 
   2569         JSValue subscript = callFrame->r(property).jsValue();
   2570         JSValue result;
   2571         uint32_t i;
   2572         if (subscript.getUInt32(i))
   2573             result = jsBoolean(baseObj->deleteProperty(callFrame, i));
   2574         else {
   2575             CHECK_FOR_EXCEPTION();
   2576             Identifier property(callFrame, subscript.toString(callFrame));
   2577             CHECK_FOR_EXCEPTION();
   2578             result = jsBoolean(baseObj->deleteProperty(callFrame, property));
   2579         }
   2580 
   2581         CHECK_FOR_EXCEPTION();
   2582         callFrame->r(dst) = result;
   2583         vPC += OPCODE_LENGTH(op_del_by_val);
   2584         NEXT_INSTRUCTION();
   2585     }
   2586     DEFINE_OPCODE(op_put_by_index) {
   2587         /* put_by_index base(r) property(n) value(r)
   2588 
   2589            Sets register value on register base as the property named
   2590            by the immediate number property. Base is converted to
   2591            object first.
   2592 
   2593            Unlike many opcodes, this one does not write any output to
   2594            the register file.
   2595 
   2596            This opcode is mainly used to initialize array literals.
   2597         */
   2598         int base = vPC[1].u.operand;
   2599         unsigned property = vPC[2].u.operand;
   2600         int value = vPC[3].u.operand;
   2601 
   2602         callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue());
   2603 
   2604         vPC += OPCODE_LENGTH(op_put_by_index);
   2605         NEXT_INSTRUCTION();
   2606     }
   2607     DEFINE_OPCODE(op_loop) {
   2608         /* loop target(offset)
   2609 
   2610            Jumps unconditionally to offset target from the current
   2611            instruction.
   2612 
   2613            Additionally this loop instruction may terminate JS execution is
   2614            the JS timeout is reached.
   2615          */
   2616 #if ENABLE(OPCODE_STATS)
   2617         OpcodeStats::resetLastInstruction();
   2618 #endif
   2619         int target = vPC[1].u.operand;
   2620         CHECK_FOR_TIMEOUT();
   2621         vPC += target;
   2622         NEXT_INSTRUCTION();
   2623     }
   2624     DEFINE_OPCODE(op_jmp) {
   2625         /* jmp target(offset)
   2626 
   2627            Jumps unconditionally to offset target from the current
   2628            instruction.
   2629         */
   2630 #if ENABLE(OPCODE_STATS)
   2631         OpcodeStats::resetLastInstruction();
   2632 #endif
   2633         int target = vPC[1].u.operand;
   2634 
   2635         vPC += target;
   2636         NEXT_INSTRUCTION();
   2637     }
   2638     DEFINE_OPCODE(op_loop_if_true) {
   2639         /* loop_if_true cond(r) target(offset)
   2640 
   2641            Jumps to offset target from the current instruction, if and
   2642            only if register cond converts to boolean as true.
   2643 
   2644            Additionally this loop instruction may terminate JS execution is
   2645            the JS timeout is reached.
   2646          */
   2647         int cond = vPC[1].u.operand;
   2648         int target = vPC[2].u.operand;
   2649         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
   2650             vPC += target;
   2651             CHECK_FOR_TIMEOUT();
   2652             NEXT_INSTRUCTION();
   2653         }
   2654 
   2655         vPC += OPCODE_LENGTH(op_loop_if_true);
   2656         NEXT_INSTRUCTION();
   2657     }
   2658     DEFINE_OPCODE(op_loop_if_false) {
   2659         /* loop_if_true cond(r) target(offset)
   2660 
   2661            Jumps to offset target from the current instruction, if and
   2662            only if register cond converts to boolean as false.
   2663 
   2664            Additionally this loop instruction may terminate JS execution is
   2665            the JS timeout is reached.
   2666          */
   2667         int cond = vPC[1].u.operand;
   2668         int target = vPC[2].u.operand;
   2669         if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
   2670             vPC += target;
   2671             CHECK_FOR_TIMEOUT();
   2672             NEXT_INSTRUCTION();
   2673         }
   2674 
   2675         vPC += OPCODE_LENGTH(op_loop_if_true);
   2676         NEXT_INSTRUCTION();
   2677     }
   2678     DEFINE_OPCODE(op_jtrue) {
   2679         /* jtrue cond(r) target(offset)
   2680 
   2681            Jumps to offset target from the current instruction, if and
   2682            only if register cond converts to boolean as true.
   2683         */
   2684         int cond = vPC[1].u.operand;
   2685         int target = vPC[2].u.operand;
   2686         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
   2687             vPC += target;
   2688             NEXT_INSTRUCTION();
   2689         }
   2690 
   2691         vPC += OPCODE_LENGTH(op_jtrue);
   2692         NEXT_INSTRUCTION();
   2693     }
   2694     DEFINE_OPCODE(op_jfalse) {
   2695         /* jfalse cond(r) target(offset)
   2696 
   2697            Jumps to offset target from the current instruction, if and
   2698            only if register cond converts to boolean as false.
   2699         */
   2700         int cond = vPC[1].u.operand;
   2701         int target = vPC[2].u.operand;
   2702         if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
   2703             vPC += target;
   2704             NEXT_INSTRUCTION();
   2705         }
   2706 
   2707         vPC += OPCODE_LENGTH(op_jfalse);
   2708         NEXT_INSTRUCTION();
   2709     }
   2710     DEFINE_OPCODE(op_jeq_null) {
   2711         /* jeq_null src(r) target(offset)
   2712 
   2713            Jumps to offset target from the current instruction, if and
   2714            only if register src is null.
   2715         */
   2716         int src = vPC[1].u.operand;
   2717         int target = vPC[2].u.operand;
   2718         JSValue srcValue = callFrame->r(src).jsValue();
   2719 
   2720         if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
   2721             vPC += target;
   2722             NEXT_INSTRUCTION();
   2723         }
   2724 
   2725         vPC += OPCODE_LENGTH(op_jeq_null);
   2726         NEXT_INSTRUCTION();
   2727     }
   2728     DEFINE_OPCODE(op_jneq_null) {
   2729         /* jneq_null src(r) target(offset)
   2730 
   2731            Jumps to offset target from the current instruction, if and
   2732            only if register src is not null.
   2733         */
   2734         int src = vPC[1].u.operand;
   2735         int target = vPC[2].u.operand;
   2736         JSValue srcValue = callFrame->r(src).jsValue();
   2737 
   2738         if (!srcValue.isUndefinedOrNull() && (!srcValue.isCell() || !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
   2739             vPC += target;
   2740             NEXT_INSTRUCTION();
   2741         }
   2742 
   2743         vPC += OPCODE_LENGTH(op_jneq_null);
   2744         NEXT_INSTRUCTION();
   2745     }
   2746     DEFINE_OPCODE(op_jneq_ptr) {
   2747         /* jneq_ptr src(r) ptr(jsCell) target(offset)
   2748 
   2749            Jumps to offset target from the current instruction, if the value r is equal
   2750            to ptr, using pointer equality.
   2751          */
   2752         int src = vPC[1].u.operand;
   2753         JSValue ptr = JSValue(vPC[2].u.jsCell);
   2754         int target = vPC[3].u.operand;
   2755         JSValue srcValue = callFrame->r(src).jsValue();
   2756         if (srcValue != ptr) {
   2757             vPC += target;
   2758             NEXT_INSTRUCTION();
   2759         }
   2760 
   2761         vPC += OPCODE_LENGTH(op_jneq_ptr);
   2762         NEXT_INSTRUCTION();
   2763     }
   2764     DEFINE_OPCODE(op_loop_if_less) {
   2765         /* loop_if_less src1(r) src2(r) target(offset)
   2766 
   2767            Checks whether register src1 is less than register src2, as
   2768            with the ECMAScript '<' operator, and then jumps to offset
   2769            target from the current instruction, if and only if the
   2770            result of the comparison is true.
   2771 
   2772            Additionally this loop instruction may terminate JS execution is
   2773            the JS timeout is reached.
   2774          */
   2775         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   2776         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   2777         int target = vPC[3].u.operand;
   2778 
   2779         bool result = jsLess(callFrame, src1, src2);
   2780         CHECK_FOR_EXCEPTION();
   2781 
   2782         if (result) {
   2783             vPC += target;
   2784             CHECK_FOR_TIMEOUT();
   2785             NEXT_INSTRUCTION();
   2786         }
   2787 
   2788         vPC += OPCODE_LENGTH(op_loop_if_less);
   2789         NEXT_INSTRUCTION();
   2790     }
   2791     DEFINE_OPCODE(op_loop_if_lesseq) {
   2792         /* loop_if_lesseq src1(r) src2(r) target(offset)
   2793 
   2794            Checks whether register src1 is less than or equal to register
   2795            src2, as with the ECMAScript '<=' operator, and then jumps to
   2796            offset target from the current instruction, if and only if the
   2797            result of the comparison is true.
   2798 
   2799            Additionally this loop instruction may terminate JS execution is
   2800            the JS timeout is reached.
   2801         */
   2802         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   2803         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   2804         int target = vPC[3].u.operand;
   2805 
   2806         bool result = jsLessEq(callFrame, src1, src2);
   2807         CHECK_FOR_EXCEPTION();
   2808 
   2809         if (result) {
   2810             vPC += target;
   2811             CHECK_FOR_TIMEOUT();
   2812             NEXT_INSTRUCTION();
   2813         }
   2814 
   2815         vPC += OPCODE_LENGTH(op_loop_if_lesseq);
   2816         NEXT_INSTRUCTION();
   2817     }
   2818     DEFINE_OPCODE(op_jnless) {
   2819         /* jnless src1(r) src2(r) target(offset)
   2820 
   2821            Checks whether register src1 is less than register src2, as
   2822            with the ECMAScript '<' operator, and then jumps to offset
   2823            target from the current instruction, if and only if the
   2824            result of the comparison is false.
   2825         */
   2826         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   2827         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   2828         int target = vPC[3].u.operand;
   2829 
   2830         bool result = jsLess(callFrame, src1, src2);
   2831         CHECK_FOR_EXCEPTION();
   2832 
   2833         if (!result) {
   2834             vPC += target;
   2835             NEXT_INSTRUCTION();
   2836         }
   2837 
   2838         vPC += OPCODE_LENGTH(op_jnless);
   2839         NEXT_INSTRUCTION();
   2840     }
   2841     DEFINE_OPCODE(op_jless) {
   2842         /* jless src1(r) src2(r) target(offset)
   2843 
   2844            Checks whether register src1 is less than register src2, as
   2845            with the ECMAScript '<' operator, and then jumps to offset
   2846            target from the current instruction, if and only if the
   2847            result of the comparison is true.
   2848         */
   2849         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   2850         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   2851         int target = vPC[3].u.operand;
   2852 
   2853         bool result = jsLess(callFrame, src1, src2);
   2854         CHECK_FOR_EXCEPTION();
   2855 
   2856         if (result) {
   2857             vPC += target;
   2858             NEXT_INSTRUCTION();
   2859         }
   2860 
   2861         vPC += OPCODE_LENGTH(op_jless);
   2862         NEXT_INSTRUCTION();
   2863     }
   2864     DEFINE_OPCODE(op_jnlesseq) {
   2865         /* jnlesseq src1(r) src2(r) target(offset)
   2866 
   2867            Checks whether register src1 is less than or equal to
   2868            register src2, as with the ECMAScript '<=' operator,
   2869            and then jumps to offset target from the current instruction,
   2870            if and only if theresult of the comparison is false.
   2871         */
   2872         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   2873         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   2874         int target = vPC[3].u.operand;
   2875 
   2876         bool result = jsLessEq(callFrame, src1, src2);
   2877         CHECK_FOR_EXCEPTION();
   2878 
   2879         if (!result) {
   2880             vPC += target;
   2881             NEXT_INSTRUCTION();
   2882         }
   2883 
   2884         vPC += OPCODE_LENGTH(op_jnlesseq);
   2885         NEXT_INSTRUCTION();
   2886     }
   2887     DEFINE_OPCODE(op_switch_imm) {
   2888         /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
   2889 
   2890            Performs a range checked switch on the scrutinee value, using
   2891            the tableIndex-th immediate switch jump table.  If the scrutinee value
   2892            is an immediate number in the range covered by the referenced jump
   2893            table, and the value at jumpTable[scrutinee value] is non-zero, then
   2894            that value is used as the jump offset, otherwise defaultOffset is used.
   2895          */
   2896         int tableIndex = vPC[1].u.operand;
   2897         int defaultOffset = vPC[2].u.operand;
   2898         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
   2899         if (scrutinee.isInt32())
   2900             vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
   2901         else {
   2902             double value;
   2903             int32_t intValue;
   2904             if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
   2905                 vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(intValue, defaultOffset);
   2906             else
   2907                 vPC += defaultOffset;
   2908         }
   2909         NEXT_INSTRUCTION();
   2910     }
   2911     DEFINE_OPCODE(op_switch_char) {
   2912         /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
   2913 
   2914            Performs a range checked switch on the scrutinee value, using
   2915            the tableIndex-th character switch jump table.  If the scrutinee value
   2916            is a single character string in the range covered by the referenced jump
   2917            table, and the value at jumpTable[scrutinee value] is non-zero, then
   2918            that value is used as the jump offset, otherwise defaultOffset is used.
   2919          */
   2920         int tableIndex = vPC[1].u.operand;
   2921         int defaultOffset = vPC[2].u.operand;
   2922         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
   2923         if (!scrutinee.isString())
   2924             vPC += defaultOffset;
   2925         else {
   2926             UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
   2927             if (value->size() != 1)
   2928                 vPC += defaultOffset;
   2929             else
   2930                 vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->data()[0], defaultOffset);
   2931         }
   2932         NEXT_INSTRUCTION();
   2933     }
   2934     DEFINE_OPCODE(op_switch_string) {
   2935         /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
   2936 
   2937            Performs a sparse hashmap based switch on the value in the scrutinee
   2938            register, using the tableIndex-th string switch jump table.  If the
   2939            scrutinee value is a string that exists as a key in the referenced
   2940            jump table, then the value associated with the string is used as the
   2941            jump offset, otherwise defaultOffset is used.
   2942          */
   2943         int tableIndex = vPC[1].u.operand;
   2944         int defaultOffset = vPC[2].u.operand;
   2945         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
   2946         if (!scrutinee.isString())
   2947             vPC += defaultOffset;
   2948         else
   2949             vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value(callFrame).rep(), defaultOffset);
   2950         NEXT_INSTRUCTION();
   2951     }
   2952     DEFINE_OPCODE(op_new_func) {
   2953         /* new_func dst(r) func(f)
   2954 
   2955            Constructs a new Function instance from function func and
   2956            the current scope chain using the original Function
   2957            constructor, using the rules for function declarations, and
   2958            puts the result in register dst.
   2959         */
   2960         int dst = vPC[1].u.operand;
   2961         int func = vPC[2].u.operand;
   2962 
   2963         callFrame->r(dst) = JSValue(callFrame->codeBlock()->functionDecl(func)->make(callFrame, callFrame->scopeChain()));
   2964 
   2965         vPC += OPCODE_LENGTH(op_new_func);
   2966         NEXT_INSTRUCTION();
   2967     }
   2968     DEFINE_OPCODE(op_new_func_exp) {
   2969         /* new_func_exp dst(r) func(f)
   2970 
   2971            Constructs a new Function instance from function func and
   2972            the current scope chain using the original Function
   2973            constructor, using the rules for function expressions, and
   2974            puts the result in register dst.
   2975         */
   2976         int dst = vPC[1].u.operand;
   2977         int funcIndex = vPC[2].u.operand;
   2978 
   2979         FunctionExecutable* function = callFrame->codeBlock()->functionExpr(funcIndex);
   2980         JSFunction* func = function->make(callFrame, callFrame->scopeChain());
   2981 
   2982         /*
   2983             The Identifier in a FunctionExpression can be referenced from inside
   2984             the FunctionExpression's FunctionBody to allow the function to call
   2985             itself recursively. However, unlike in a FunctionDeclaration, the
   2986             Identifier in a FunctionExpression cannot be referenced from and
   2987             does not affect the scope enclosing the FunctionExpression.
   2988          */
   2989         if (!function->name().isNull()) {
   2990             JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
   2991             func->scope().push(functionScopeObject);
   2992         }
   2993 
   2994         callFrame->r(dst) = JSValue(func);
   2995 
   2996         vPC += OPCODE_LENGTH(op_new_func_exp);
   2997         NEXT_INSTRUCTION();
   2998     }
   2999     DEFINE_OPCODE(op_call_eval) {
   3000         /* call_eval dst(r) func(r) argCount(n) registerOffset(n)
   3001 
   3002            Call a function named "eval" with no explicit "this" value
   3003            (which may therefore be the eval operator). If register
   3004            thisVal is the global object, and register func contains
   3005            that global object's original global eval function, then
   3006            perform the eval operator in local scope (interpreting
   3007            the argument registers as for the "call"
   3008            opcode). Otherwise, act exactly as the "call" opcode would.
   3009          */
   3010 
   3011         int dst = vPC[1].u.operand;
   3012         int func = vPC[2].u.operand;
   3013         int argCount = vPC[3].u.operand;
   3014         int registerOffset = vPC[4].u.operand;
   3015 
   3016         JSValue funcVal = callFrame->r(func).jsValue();
   3017 
   3018         Register* newCallFrame = callFrame->registers() + registerOffset;
   3019         Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
   3020         JSValue thisValue = argv[0].jsValue();
   3021         JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
   3022 
   3023         if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
   3024             JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
   3025             if (exceptionValue)
   3026                 goto vm_throw;
   3027             callFrame->r(dst) = result;
   3028 
   3029             vPC += OPCODE_LENGTH(op_call_eval);
   3030             NEXT_INSTRUCTION();
   3031         }
   3032 
   3033         // We didn't find the blessed version of eval, so process this
   3034         // instruction as a normal function call.
   3035         // fall through to op_call
   3036     }
   3037     DEFINE_OPCODE(op_call) {
   3038         /* call dst(r) func(r) argCount(n) registerOffset(n)
   3039 
   3040            Perform a function call.
   3041 
   3042            registerOffset is the distance the callFrame pointer should move
   3043            before the VM initializes the new call frame's header.
   3044 
   3045            dst is where op_ret should store its result.
   3046          */
   3047 
   3048         int dst = vPC[1].u.operand;
   3049         int func = vPC[2].u.operand;
   3050         int argCount = vPC[3].u.operand;
   3051         int registerOffset = vPC[4].u.operand;
   3052 
   3053         JSValue v = callFrame->r(func).jsValue();
   3054 
   3055         CallData callData;
   3056         CallType callType = v.getCallData(callData);
   3057 
   3058         if (callType == CallTypeJS) {
   3059             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
   3060             CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
   3061 
   3062             CallFrame* previousCallFrame = callFrame;
   3063 
   3064             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
   3065             if (UNLIKELY(!callFrame)) {
   3066                 callFrame = previousCallFrame;
   3067                 exceptionValue = createStackOverflowError(callFrame);
   3068                 goto vm_throw;
   3069             }
   3070 
   3071             callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
   3072             vPC = newCodeBlock->instructions().begin();
   3073 
   3074 #if ENABLE(OPCODE_STATS)
   3075             OpcodeStats::resetLastInstruction();
   3076 #endif
   3077 
   3078             NEXT_INSTRUCTION();
   3079         }
   3080 
   3081         if (callType == CallTypeHost) {
   3082             ScopeChainNode* scopeChain = callFrame->scopeChain();
   3083             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
   3084             newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0);
   3085 
   3086             Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
   3087             ArgList args(thisRegister + 1, argCount - 1);
   3088 
   3089             // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
   3090             JSValue thisValue = thisRegister->jsValue();
   3091             if (thisValue == jsNull())
   3092                 thisValue = callFrame->globalThisValue();
   3093 
   3094             JSValue returnValue;
   3095             {
   3096                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
   3097                 returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
   3098             }
   3099             CHECK_FOR_EXCEPTION();
   3100 
   3101             callFrame->r(dst) = returnValue;
   3102 
   3103             vPC += OPCODE_LENGTH(op_call);
   3104             NEXT_INSTRUCTION();
   3105         }
   3106 
   3107         ASSERT(callType == CallTypeNone);
   3108 
   3109         exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
   3110         goto vm_throw;
   3111     }
   3112     DEFINE_OPCODE(op_load_varargs) {
   3113         int argCountDst = vPC[1].u.operand;
   3114         int argsOffset = vPC[2].u.operand;
   3115 
   3116         JSValue arguments = callFrame->r(argsOffset).jsValue();
   3117         int32_t argCount = 0;
   3118         if (!arguments) {
   3119             argCount = (uint32_t)(callFrame->argumentCount()) - 1;
   3120             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   3121             Register* newEnd = callFrame->registers() + sizeDelta;
   3122             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   3123                 exceptionValue = createStackOverflowError(callFrame);
   3124                 goto vm_throw;
   3125             }
   3126             ASSERT(!callFrame->callee()->isHostFunction());
   3127             int32_t expectedParams = callFrame->callee()->jsExecutable()->parameterCount();
   3128             int32_t inplaceArgs = min(argCount, expectedParams);
   3129             int32_t i = 0;
   3130             Register* argStore = callFrame->registers() + argsOffset;
   3131 
   3132             // First step is to copy the "expected" parameters from their normal location relative to the callframe
   3133             for (; i < inplaceArgs; i++)
   3134                 argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams];
   3135             // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
   3136             for (; i < argCount; i++)
   3137                 argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - argCount - 1];
   3138         } else if (!arguments.isUndefinedOrNull()) {
   3139             if (!arguments.isObject()) {
   3140                 exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
   3141                 goto vm_throw;
   3142             }
   3143             if (asObject(arguments)->classInfo() == &Arguments::info) {
   3144                 Arguments* args = asArguments(arguments);
   3145                 argCount = args->numProvidedArguments(callFrame);
   3146                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   3147                 Register* newEnd = callFrame->registers() + sizeDelta;
   3148                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   3149                     exceptionValue = createStackOverflowError(callFrame);
   3150                     goto vm_throw;
   3151                 }
   3152                 args->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
   3153             } else if (isJSArray(&callFrame->globalData(), arguments)) {
   3154                 JSArray* array = asArray(arguments);
   3155                 argCount = array->length();
   3156                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   3157                 Register* newEnd = callFrame->registers() + sizeDelta;
   3158                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   3159                     exceptionValue = createStackOverflowError(callFrame);
   3160                     goto vm_throw;
   3161                 }
   3162                 array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
   3163             } else if (asObject(arguments)->inherits(&JSArray::info)) {
   3164                 JSObject* argObject = asObject(arguments);
   3165                 argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
   3166                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   3167                 Register* newEnd = callFrame->registers() + sizeDelta;
   3168                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   3169                     exceptionValue = createStackOverflowError(callFrame);
   3170                     goto vm_throw;
   3171                 }
   3172                 Register* argsBuffer = callFrame->registers() + argsOffset;
   3173                 for (int32_t i = 0; i < argCount; ++i) {
   3174                     argsBuffer[i] = asObject(arguments)->get(callFrame, i);
   3175                     CHECK_FOR_EXCEPTION();
   3176                 }
   3177             } else {
   3178                 if (!arguments.isObject()) {
   3179                     exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
   3180                     goto vm_throw;
   3181                 }
   3182             }
   3183         }
   3184         CHECK_FOR_EXCEPTION();
   3185         callFrame->r(argCountDst) = Register::withInt(argCount + 1);
   3186         vPC += OPCODE_LENGTH(op_load_varargs);
   3187         NEXT_INSTRUCTION();
   3188     }
   3189     DEFINE_OPCODE(op_call_varargs) {
   3190         /* call_varargs dst(r) func(r) argCountReg(r) baseRegisterOffset(n)
   3191 
   3192          Perform a function call with a dynamic set of arguments.
   3193 
   3194          registerOffset is the distance the callFrame pointer should move
   3195          before the VM initializes the new call frame's header, excluding
   3196          space for arguments.
   3197 
   3198          dst is where op_ret should store its result.
   3199          */
   3200 
   3201         int dst = vPC[1].u.operand;
   3202         int func = vPC[2].u.operand;
   3203         int argCountReg = vPC[3].u.operand;
   3204         int registerOffset = vPC[4].u.operand;
   3205 
   3206         JSValue v = callFrame->r(func).jsValue();
   3207         int argCount = callFrame->r(argCountReg).i();
   3208         registerOffset += argCount;
   3209         CallData callData;
   3210         CallType callType = v.getCallData(callData);
   3211 
   3212         if (callType == CallTypeJS) {
   3213             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
   3214             CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
   3215 
   3216             CallFrame* previousCallFrame = callFrame;
   3217 
   3218             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
   3219             if (UNLIKELY(!callFrame)) {
   3220                 callFrame = previousCallFrame;
   3221                 exceptionValue = createStackOverflowError(callFrame);
   3222                 goto vm_throw;
   3223             }
   3224 
   3225             callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
   3226             vPC = newCodeBlock->instructions().begin();
   3227 
   3228 #if ENABLE(OPCODE_STATS)
   3229             OpcodeStats::resetLastInstruction();
   3230 #endif
   3231 
   3232             NEXT_INSTRUCTION();
   3233         }
   3234 
   3235         if (callType == CallTypeHost) {
   3236             ScopeChainNode* scopeChain = callFrame->scopeChain();
   3237             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
   3238             newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0);
   3239 
   3240             Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
   3241             ArgList args(thisRegister + 1, argCount - 1);
   3242 
   3243             // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
   3244             JSValue thisValue = thisRegister->jsValue();
   3245             if (thisValue == jsNull())
   3246                 thisValue = callFrame->globalThisValue();
   3247 
   3248             JSValue returnValue;
   3249             {
   3250                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
   3251                 returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
   3252             }
   3253             CHECK_FOR_EXCEPTION();
   3254 
   3255             callFrame->r(dst) = returnValue;
   3256 
   3257             vPC += OPCODE_LENGTH(op_call_varargs);
   3258             NEXT_INSTRUCTION();
   3259         }
   3260 
   3261         ASSERT(callType == CallTypeNone);
   3262 
   3263         exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
   3264         goto vm_throw;
   3265     }
   3266     DEFINE_OPCODE(op_tear_off_activation) {
   3267         /* tear_off_activation activation(r)
   3268 
   3269            Copy all locals and parameters to new memory allocated on
   3270            the heap, and make the passed activation use this memory
   3271            in the future when looking up entries in the symbol table.
   3272            If there is an 'arguments' object, then it will also use
   3273            this memory for storing the named parameters, but not any
   3274            extra arguments.
   3275 
   3276            This opcode should only be used immediately before op_ret.
   3277         */
   3278 
   3279         int src = vPC[1].u.operand;
   3280         ASSERT(callFrame->codeBlock()->needsFullScopeChain());
   3281 
   3282         asActivation(callFrame->r(src).jsValue())->copyRegisters(callFrame->optionalCalleeArguments());
   3283 
   3284         vPC += OPCODE_LENGTH(op_tear_off_activation);
   3285         NEXT_INSTRUCTION();
   3286     }
   3287     DEFINE_OPCODE(op_tear_off_arguments) {
   3288         /* tear_off_arguments
   3289 
   3290            Copy all arguments to new memory allocated on the heap,
   3291            and make the 'arguments' object use this memory in the
   3292            future when looking up named parameters, but not any
   3293            extra arguments. If an activation object exists for the
   3294            current function context, then the tear_off_activation
   3295            opcode should be used instead.
   3296 
   3297            This opcode should only be used immediately before op_ret.
   3298         */
   3299 
   3300         ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
   3301 
   3302         if (callFrame->optionalCalleeArguments())
   3303             callFrame->optionalCalleeArguments()->copyRegisters();
   3304 
   3305         vPC += OPCODE_LENGTH(op_tear_off_arguments);
   3306         NEXT_INSTRUCTION();
   3307     }
   3308     DEFINE_OPCODE(op_ret) {
   3309         /* ret result(r)
   3310 
   3311            Return register result as the return value of the current
   3312            function call, writing it into the caller's expected return
   3313            value register. In addition, unwind one call frame and
   3314            restore the scope chain, code block instruction pointer and
   3315            register base to those of the calling function.
   3316         */
   3317 
   3318         int result = vPC[1].u.operand;
   3319 
   3320         if (callFrame->codeBlock()->needsFullScopeChain())
   3321             callFrame->scopeChain()->deref();
   3322 
   3323         JSValue returnValue = callFrame->r(result).jsValue();
   3324 
   3325         vPC = callFrame->returnPC();
   3326         int dst = callFrame->returnValueRegister();
   3327         callFrame = callFrame->callerFrame();
   3328 
   3329         if (callFrame->hasHostCallFrameFlag())
   3330             return returnValue;
   3331 
   3332         callFrame->r(dst) = returnValue;
   3333 
   3334         NEXT_INSTRUCTION();
   3335     }
   3336     DEFINE_OPCODE(op_enter) {
   3337         /* enter
   3338 
   3339            Initializes local variables to undefined and fills constant
   3340            registers with their values. If the code block requires an
   3341            activation, enter_with_activation should be used instead.
   3342 
   3343            This opcode should only be used at the beginning of a code
   3344            block.
   3345         */
   3346 
   3347         size_t i = 0;
   3348         CodeBlock* codeBlock = callFrame->codeBlock();
   3349 
   3350         for (size_t count = codeBlock->m_numVars; i < count; ++i)
   3351             callFrame->r(i) = jsUndefined();
   3352 
   3353         vPC += OPCODE_LENGTH(op_enter);
   3354         NEXT_INSTRUCTION();
   3355     }
   3356     DEFINE_OPCODE(op_enter_with_activation) {
   3357         /* enter_with_activation dst(r)
   3358 
   3359            Initializes local variables to undefined, fills constant
   3360            registers with their values, creates an activation object,
   3361            and places the new activation both in dst and at the top
   3362            of the scope chain. If the code block does not require an
   3363            activation, enter should be used instead.
   3364 
   3365            This opcode should only be used at the beginning of a code
   3366            block.
   3367         */
   3368 
   3369         size_t i = 0;
   3370         CodeBlock* codeBlock = callFrame->codeBlock();
   3371 
   3372         for (size_t count = codeBlock->m_numVars; i < count; ++i)
   3373             callFrame->r(i) = jsUndefined();
   3374 
   3375         int dst = vPC[1].u.operand;
   3376         JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
   3377         callFrame->r(dst) = JSValue(activation);
   3378         callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
   3379 
   3380         vPC += OPCODE_LENGTH(op_enter_with_activation);
   3381         NEXT_INSTRUCTION();
   3382     }
   3383     DEFINE_OPCODE(op_convert_this) {
   3384         /* convert_this this(r)
   3385 
   3386            Takes the value in the 'this' register, converts it to a
   3387            value that is suitable for use as the 'this' value, and
   3388            stores it in the 'this' register. This opcode is emitted
   3389            to avoid doing the conversion in the caller unnecessarily.
   3390 
   3391            This opcode should only be used at the beginning of a code
   3392            block.
   3393         */
   3394 
   3395         int thisRegister = vPC[1].u.operand;
   3396         JSValue thisVal = callFrame->r(thisRegister).jsValue();
   3397         if (thisVal.needsThisConversion())
   3398             callFrame->r(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
   3399 
   3400         vPC += OPCODE_LENGTH(op_convert_this);
   3401         NEXT_INSTRUCTION();
   3402     }
   3403     DEFINE_OPCODE(op_init_arguments) {
   3404         /* create_arguments
   3405 
   3406            Initialises the arguments object reference to null to ensure
   3407            we can correctly detect that we need to create it later (or
   3408            avoid creating it altogether).
   3409 
   3410            This opcode should only be used at the beginning of a code
   3411            block.
   3412          */
   3413         callFrame->r(RegisterFile::ArgumentsRegister) = JSValue();
   3414         vPC += OPCODE_LENGTH(op_init_arguments);
   3415         NEXT_INSTRUCTION();
   3416     }
   3417     DEFINE_OPCODE(op_create_arguments) {
   3418         /* create_arguments
   3419 
   3420            Creates the 'arguments' object and places it in both the
   3421            'arguments' call frame slot and the local 'arguments'
   3422            register, if it has not already been initialised.
   3423          */
   3424 
   3425          if (!callFrame->r(RegisterFile::ArgumentsRegister).jsValue()) {
   3426              Arguments* arguments = new (globalData) Arguments(callFrame);
   3427              callFrame->setCalleeArguments(arguments);
   3428              callFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments);
   3429          }
   3430         vPC += OPCODE_LENGTH(op_create_arguments);
   3431         NEXT_INSTRUCTION();
   3432     }
   3433     DEFINE_OPCODE(op_construct) {
   3434         /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
   3435 
   3436            Invoke register "func" as a constructor. For JS
   3437            functions, the calling convention is exactly as for the
   3438            "call" opcode, except that the "this" value is a newly
   3439            created Object. For native constructors, no "this"
   3440            value is passed. In either case, the argCount and registerOffset
   3441            registers are interpreted as for the "call" opcode.
   3442 
   3443            Register proto must contain the prototype property of
   3444            register func. This is to enable polymorphic inline
   3445            caching of this lookup.
   3446         */
   3447 
   3448         int dst = vPC[1].u.operand;
   3449         int func = vPC[2].u.operand;
   3450         int argCount = vPC[3].u.operand;
   3451         int registerOffset = vPC[4].u.operand;
   3452         int proto = vPC[5].u.operand;
   3453         int thisRegister = vPC[6].u.operand;
   3454 
   3455         JSValue v = callFrame->r(func).jsValue();
   3456 
   3457         ConstructData constructData;
   3458         ConstructType constructType = v.getConstructData(constructData);
   3459 
   3460         if (constructType == ConstructTypeJS) {
   3461             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
   3462             CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
   3463 
   3464             Structure* structure;
   3465             JSValue prototype = callFrame->r(proto).jsValue();
   3466             if (prototype.isObject())
   3467                 structure = asObject(prototype)->inheritorID();
   3468             else
   3469                 structure = callDataScopeChain->globalObject->emptyObjectStructure();
   3470             JSObject* newObject = new (globalData) JSObject(structure);
   3471 
   3472             callFrame->r(thisRegister) = JSValue(newObject); // "this" value
   3473 
   3474             CallFrame* previousCallFrame = callFrame;
   3475 
   3476             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
   3477             if (UNLIKELY(!callFrame)) {
   3478                 callFrame = previousCallFrame;
   3479                 exceptionValue = createStackOverflowError(callFrame);
   3480                 goto vm_throw;
   3481             }
   3482 
   3483             callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
   3484             vPC = newCodeBlock->instructions().begin();
   3485 
   3486 #if ENABLE(OPCODE_STATS)
   3487             OpcodeStats::resetLastInstruction();
   3488 #endif
   3489 
   3490             NEXT_INSTRUCTION();
   3491         }
   3492 
   3493         if (constructType == ConstructTypeHost) {
   3494             ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1);
   3495 
   3496             ScopeChainNode* scopeChain = callFrame->scopeChain();
   3497             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
   3498             newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0);
   3499 
   3500             JSValue returnValue;
   3501             {
   3502                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
   3503                 returnValue = constructData.native.function(newCallFrame, asObject(v), args);
   3504             }
   3505             CHECK_FOR_EXCEPTION();
   3506             callFrame->r(dst) = JSValue(returnValue);
   3507 
   3508             vPC += OPCODE_LENGTH(op_construct);
   3509             NEXT_INSTRUCTION();
   3510         }
   3511 
   3512         ASSERT(constructType == ConstructTypeNone);
   3513 
   3514         exceptionValue = createNotAConstructorError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
   3515         goto vm_throw;
   3516     }
   3517     DEFINE_OPCODE(op_construct_verify) {
   3518         /* construct_verify dst(r) override(r)
   3519 
   3520            Verifies that register dst holds an object. If not, moves
   3521            the object in register override to register dst.
   3522         */
   3523 
   3524         int dst = vPC[1].u.operand;
   3525         if (LIKELY(callFrame->r(dst).jsValue().isObject())) {
   3526             vPC += OPCODE_LENGTH(op_construct_verify);
   3527             NEXT_INSTRUCTION();
   3528         }
   3529 
   3530         int override = vPC[2].u.operand;
   3531         callFrame->r(dst) = callFrame->r(override);
   3532 
   3533         vPC += OPCODE_LENGTH(op_construct_verify);
   3534         NEXT_INSTRUCTION();
   3535     }
   3536     DEFINE_OPCODE(op_strcat) {
   3537         int dst = vPC[1].u.operand;
   3538         int src = vPC[2].u.operand;
   3539         int count = vPC[3].u.operand;
   3540 
   3541         callFrame->r(dst) = jsString(callFrame, &callFrame->registers()[src], count);
   3542         CHECK_FOR_EXCEPTION();
   3543         vPC += OPCODE_LENGTH(op_strcat);
   3544 
   3545         NEXT_INSTRUCTION();
   3546     }
   3547     DEFINE_OPCODE(op_to_primitive) {
   3548         int dst = vPC[1].u.operand;
   3549         int src = vPC[2].u.operand;
   3550 
   3551         callFrame->r(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame);
   3552         vPC += OPCODE_LENGTH(op_to_primitive);
   3553 
   3554         NEXT_INSTRUCTION();
   3555     }
   3556     DEFINE_OPCODE(op_push_scope) {
   3557         /* push_scope scope(r)
   3558 
   3559            Converts register scope to object, and pushes it onto the top
   3560            of the current scope chain.  The contents of the register scope
   3561            are replaced by the result of toObject conversion of the scope.
   3562         */
   3563         int scope = vPC[1].u.operand;
   3564         JSValue v = callFrame->r(scope).jsValue();
   3565         JSObject* o = v.toObject(callFrame);
   3566         CHECK_FOR_EXCEPTION();
   3567 
   3568         callFrame->r(scope) = JSValue(o);
   3569         callFrame->setScopeChain(callFrame->scopeChain()->push(o));
   3570 
   3571         vPC += OPCODE_LENGTH(op_push_scope);
   3572         NEXT_INSTRUCTION();
   3573     }
   3574     DEFINE_OPCODE(op_pop_scope) {
   3575         /* pop_scope
   3576 
   3577            Removes the top item from the current scope chain.
   3578         */
   3579         callFrame->setScopeChain(callFrame->scopeChain()->pop());
   3580 
   3581         vPC += OPCODE_LENGTH(op_pop_scope);
   3582         NEXT_INSTRUCTION();
   3583     }
   3584     DEFINE_OPCODE(op_get_pnames) {
   3585         /* get_pnames dst(r) base(r) i(n) size(n) breakTarget(offset)
   3586 
   3587            Creates a property name list for register base and puts it
   3588            in register dst, initializing i and size for iteration. If
   3589            base is undefined or null, jumps to breakTarget.
   3590         */
   3591         int dst = vPC[1].u.operand;
   3592         int base = vPC[2].u.operand;
   3593         int i = vPC[3].u.operand;
   3594         int size = vPC[4].u.operand;
   3595         int breakTarget = vPC[5].u.operand;
   3596 
   3597         JSValue v = callFrame->r(base).jsValue();
   3598         if (v.isUndefinedOrNull()) {
   3599             vPC += breakTarget;
   3600             NEXT_INSTRUCTION();
   3601         }
   3602 
   3603         JSObject* o = v.toObject(callFrame);
   3604         Structure* structure = o->structure();
   3605         JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
   3606         if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
   3607             jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
   3608 
   3609         callFrame->r(dst) = jsPropertyNameIterator;
   3610         callFrame->r(base) = JSValue(o);
   3611         callFrame->r(i) = Register::withInt(0);
   3612         callFrame->r(size) = Register::withInt(jsPropertyNameIterator->size());
   3613         vPC += OPCODE_LENGTH(op_get_pnames);
   3614         NEXT_INSTRUCTION();
   3615     }
   3616     DEFINE_OPCODE(op_next_pname) {
   3617         /* next_pname dst(r) base(r) i(n) size(n) iter(r) target(offset)
   3618 
   3619            Copies the next name from the property name list in
   3620            register iter to dst, then jumps to offset target. If there are no
   3621            names left, invalidates the iterator and continues to the next
   3622            instruction.
   3623         */
   3624         int dst = vPC[1].u.operand;
   3625         int base = vPC[2].u.operand;
   3626         int i = vPC[3].u.operand;
   3627         int size = vPC[4].u.operand;
   3628         int iter = vPC[5].u.operand;
   3629         int target = vPC[6].u.operand;
   3630 
   3631         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
   3632         while (callFrame->r(i).i() != callFrame->r(size).i()) {
   3633             JSValue key = it->get(callFrame, asObject(callFrame->r(base).jsValue()), callFrame->r(i).i());
   3634             callFrame->r(i) = Register::withInt(callFrame->r(i).i() + 1);
   3635             if (key) {
   3636                 CHECK_FOR_TIMEOUT();
   3637                 callFrame->r(dst) = key;
   3638                 vPC += target;
   3639                 NEXT_INSTRUCTION();
   3640             }
   3641         }
   3642 
   3643         vPC += OPCODE_LENGTH(op_next_pname);
   3644         NEXT_INSTRUCTION();
   3645     }
   3646     DEFINE_OPCODE(op_jmp_scopes) {
   3647         /* jmp_scopes count(n) target(offset)
   3648 
   3649            Removes the a number of items from the current scope chain
   3650            specified by immediate number count, then jumps to offset
   3651            target.
   3652         */
   3653         int count = vPC[1].u.operand;
   3654         int target = vPC[2].u.operand;
   3655 
   3656         ScopeChainNode* tmp = callFrame->scopeChain();
   3657         while (count--)
   3658             tmp = tmp->pop();
   3659         callFrame->setScopeChain(tmp);
   3660 
   3661         vPC += target;
   3662         NEXT_INSTRUCTION();
   3663     }
   3664 #if HAVE(COMPUTED_GOTO)
   3665     // Appease GCC
   3666     goto *(&&skip_new_scope);
   3667 #endif
   3668     DEFINE_OPCODE(op_push_new_scope) {
   3669         /* new_scope dst(r) property(id) value(r)
   3670 
   3671            Constructs a new StaticScopeObject with property set to value.  That scope
   3672            object is then pushed onto the ScopeChain.  The scope object is then stored
   3673            in dst for GC.
   3674          */
   3675         callFrame->setScopeChain(createExceptionScope(callFrame, vPC));
   3676 
   3677         vPC += OPCODE_LENGTH(op_push_new_scope);
   3678         NEXT_INSTRUCTION();
   3679     }
   3680 #if HAVE(COMPUTED_GOTO)
   3681     skip_new_scope:
   3682 #endif
   3683     DEFINE_OPCODE(op_catch) {
   3684         /* catch ex(r)
   3685 
   3686            Retrieves the VM's current exception and puts it in register
   3687            ex. This is only valid after an exception has been raised,
   3688            and usually forms the beginning of an exception handler.
   3689         */
   3690         ASSERT(exceptionValue);
   3691         ASSERT(!globalData->exception);
   3692         int ex = vPC[1].u.operand;
   3693         callFrame->r(ex) = exceptionValue;
   3694         exceptionValue = JSValue();
   3695 
   3696         vPC += OPCODE_LENGTH(op_catch);
   3697         NEXT_INSTRUCTION();
   3698     }
   3699     DEFINE_OPCODE(op_throw) {
   3700         /* throw ex(r)
   3701 
   3702            Throws register ex as an exception. This involves three
   3703            steps: first, it is set as the current exception in the
   3704            VM's internal state, then the stack is unwound until an
   3705            exception handler or a native code boundary is found, and
   3706            then control resumes at the exception handler if any or
   3707            else the script returns control to the nearest native caller.
   3708         */
   3709 
   3710         int ex = vPC[1].u.operand;
   3711         exceptionValue = callFrame->r(ex).jsValue();
   3712 
   3713         handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true);
   3714         if (!handler) {
   3715             *exception = exceptionValue;
   3716             return jsNull();
   3717         }
   3718 
   3719         vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
   3720         NEXT_INSTRUCTION();
   3721     }
   3722     DEFINE_OPCODE(op_new_error) {
   3723         /* new_error dst(r) type(n) message(k)
   3724 
   3725            Constructs a new Error instance using the original
   3726            constructor, using immediate number n as the type and
   3727            constant message as the message string. The result is
   3728            written to register dst.
   3729         */
   3730         int dst = vPC[1].u.operand;
   3731         int type = vPC[2].u.operand;
   3732         int message = vPC[3].u.operand;
   3733 
   3734         CodeBlock* codeBlock = callFrame->codeBlock();
   3735         callFrame->r(dst) = JSValue(Error::create(callFrame, (ErrorType)type, callFrame->r(message).jsValue().toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()));
   3736 
   3737         vPC += OPCODE_LENGTH(op_new_error);
   3738         NEXT_INSTRUCTION();
   3739     }
   3740     DEFINE_OPCODE(op_end) {
   3741         /* end result(r)
   3742 
   3743            Return register result as the value of a global or eval
   3744            program. Return control to the calling native code.
   3745         */
   3746 
   3747         if (callFrame->codeBlock()->needsFullScopeChain()) {
   3748             ScopeChainNode* scopeChain = callFrame->scopeChain();
   3749             ASSERT(scopeChain->refCount > 1);
   3750             scopeChain->deref();
   3751         }
   3752         int result = vPC[1].u.operand;
   3753         return callFrame->r(result).jsValue();
   3754     }
   3755     DEFINE_OPCODE(op_put_getter) {
   3756         /* put_getter base(r) property(id) function(r)
   3757 
   3758            Sets register function on register base as the getter named
   3759            by identifier property. Base and function are assumed to be
   3760            objects as this op should only be used for getters defined
   3761            in object literal form.
   3762 
   3763            Unlike many opcodes, this one does not write any output to
   3764            the register file.
   3765         */
   3766         int base = vPC[1].u.operand;
   3767         int property = vPC[2].u.operand;
   3768         int function = vPC[3].u.operand;
   3769 
   3770         ASSERT(callFrame->r(base).jsValue().isObject());
   3771         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
   3772         Identifier& ident = callFrame->codeBlock()->identifier(property);
   3773         ASSERT(callFrame->r(function).jsValue().isObject());
   3774         baseObj->defineGetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
   3775 
   3776         vPC += OPCODE_LENGTH(op_put_getter);
   3777         NEXT_INSTRUCTION();
   3778     }
   3779     DEFINE_OPCODE(op_put_setter) {
   3780         /* put_setter base(r) property(id) function(r)
   3781 
   3782            Sets register function on register base as the setter named
   3783            by identifier property. Base and function are assumed to be
   3784            objects as this op should only be used for setters defined
   3785            in object literal form.
   3786 
   3787            Unlike many opcodes, this one does not write any output to
   3788            the register file.
   3789         */
   3790         int base = vPC[1].u.operand;
   3791         int property = vPC[2].u.operand;
   3792         int function = vPC[3].u.operand;
   3793 
   3794         ASSERT(callFrame->r(base).jsValue().isObject());
   3795         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
   3796         Identifier& ident = callFrame->codeBlock()->identifier(property);
   3797         ASSERT(callFrame->r(function).jsValue().isObject());
   3798         baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()), 0);
   3799 
   3800         vPC += OPCODE_LENGTH(op_put_setter);
   3801         NEXT_INSTRUCTION();
   3802     }
   3803     DEFINE_OPCODE(op_method_check) {
   3804         vPC++;
   3805         NEXT_INSTRUCTION();
   3806     }
   3807     DEFINE_OPCODE(op_jsr) {
   3808         /* jsr retAddrDst(r) target(offset)
   3809 
   3810            Places the address of the next instruction into the retAddrDst
   3811            register and jumps to offset target from the current instruction.
   3812         */
   3813         int retAddrDst = vPC[1].u.operand;
   3814         int target = vPC[2].u.operand;
   3815         callFrame->r(retAddrDst) = vPC + OPCODE_LENGTH(op_jsr);
   3816 
   3817         vPC += target;
   3818         NEXT_INSTRUCTION();
   3819     }
   3820     DEFINE_OPCODE(op_sret) {
   3821         /* sret retAddrSrc(r)
   3822 
   3823          Jumps to the address stored in the retAddrSrc register. This
   3824          differs from op_jmp because the target address is stored in a
   3825          register, not as an immediate.
   3826         */
   3827         int retAddrSrc = vPC[1].u.operand;
   3828         vPC = callFrame->r(retAddrSrc).vPC();
   3829         NEXT_INSTRUCTION();
   3830     }
   3831     DEFINE_OPCODE(op_debug) {
   3832         /* debug debugHookID(n) firstLine(n) lastLine(n)
   3833 
   3834          Notifies the debugger of the current state of execution. This opcode
   3835          is only generated while the debugger is attached.
   3836         */
   3837         int debugHookID = vPC[1].u.operand;
   3838         int firstLine = vPC[2].u.operand;
   3839         int lastLine = vPC[3].u.operand;
   3840 
   3841         debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
   3842 
   3843         vPC += OPCODE_LENGTH(op_debug);
   3844         NEXT_INSTRUCTION();
   3845     }
   3846     DEFINE_OPCODE(op_profile_will_call) {
   3847         /* op_profile_will_call function(r)
   3848 
   3849          Notifies the profiler of the beginning of a function call. This opcode
   3850          is only generated if developer tools are enabled.
   3851         */
   3852         int function = vPC[1].u.operand;
   3853 
   3854         if (*enabledProfilerReference)
   3855             (*enabledProfilerReference)->willExecute(callFrame, callFrame->r(function).jsValue());
   3856 
   3857         vPC += OPCODE_LENGTH(op_profile_will_call);
   3858         NEXT_INSTRUCTION();
   3859     }
   3860     DEFINE_OPCODE(op_profile_did_call) {
   3861         /* op_profile_did_call function(r)
   3862 
   3863          Notifies the profiler of the end of a function call. This opcode
   3864          is only generated if developer tools are enabled.
   3865         */
   3866         int function = vPC[1].u.operand;
   3867 
   3868         if (*enabledProfilerReference)
   3869             (*enabledProfilerReference)->didExecute(callFrame, callFrame->r(function).jsValue());
   3870 
   3871         vPC += OPCODE_LENGTH(op_profile_did_call);
   3872         NEXT_INSTRUCTION();
   3873     }
   3874     vm_throw: {
   3875         globalData->exception = JSValue();
   3876         if (!tickCount) {
   3877             // The exceptionValue is a lie! (GCC produces bad code for reasons I
   3878             // cannot fathom if we don't assign to the exceptionValue before branching)
   3879             exceptionValue = createInterruptedExecutionException(globalData);
   3880         }
   3881         handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), false);
   3882         if (!handler) {
   3883             *exception = exceptionValue;
   3884             return jsNull();
   3885         }
   3886 
   3887         vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
   3888         NEXT_INSTRUCTION();
   3889     }
   3890     }
   3891 #if !HAVE(COMPUTED_GOTO)
   3892     } // iterator loop ends
   3893 #endif
   3894 #endif // USE(INTERPRETER)
   3895     #undef NEXT_INSTRUCTION
   3896     #undef DEFINE_OPCODE
   3897     #undef CHECK_FOR_EXCEPTION
   3898     #undef CHECK_FOR_TIMEOUT
   3899 }
   3900 
   3901 JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
   3902 {
   3903     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
   3904     if (!functionCallFrame)
   3905         return jsNull();
   3906 
   3907     CodeBlock* codeBlock = functionCallFrame->codeBlock();
   3908     if (codeBlock->usesArguments()) {
   3909         ASSERT(codeBlock->codeType() == FunctionCode);
   3910         SymbolTable& symbolTable = *codeBlock->symbolTable();
   3911         int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex();
   3912         if (!functionCallFrame->r(argumentsIndex).jsValue()) {
   3913             Arguments* arguments = new (callFrame) Arguments(functionCallFrame);
   3914             functionCallFrame->setCalleeArguments(arguments);
   3915             functionCallFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments);
   3916         }
   3917         return functionCallFrame->r(argumentsIndex).jsValue();
   3918     }
   3919 
   3920     Arguments* arguments = functionCallFrame->optionalCalleeArguments();
   3921     if (!arguments) {
   3922         arguments = new (functionCallFrame) Arguments(functionCallFrame);
   3923         arguments->copyRegisters();
   3924         callFrame->setCalleeArguments(arguments);
   3925     }
   3926 
   3927     return arguments;
   3928 }
   3929 
   3930 JSValue Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const
   3931 {
   3932     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
   3933     if (!functionCallFrame)
   3934         return jsNull();
   3935 
   3936     CallFrame* callerFrame = functionCallFrame->callerFrame();
   3937     if (callerFrame->hasHostCallFrameFlag())
   3938         return jsNull();
   3939 
   3940     JSValue caller = callerFrame->callee();
   3941     if (!caller)
   3942         return jsNull();
   3943 
   3944     return caller;
   3945 }
   3946 
   3947 void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const
   3948 {
   3949     function = JSValue();
   3950     lineNumber = -1;
   3951     sourceURL = UString();
   3952 
   3953     CallFrame* callerFrame = callFrame->callerFrame();
   3954     if (callerFrame->hasHostCallFrameFlag())
   3955         return;
   3956 
   3957     CodeBlock* callerCodeBlock = callerFrame->codeBlock();
   3958     if (!callerCodeBlock)
   3959         return;
   3960 
   3961     unsigned bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC());
   3962     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1);
   3963     sourceID = callerCodeBlock->ownerExecutable()->sourceID();
   3964     sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
   3965     function = callerFrame->callee();
   3966 }
   3967 
   3968 CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunction* function)
   3969 {
   3970     for (CallFrame* candidate = callFrame; candidate; candidate = candidate->callerFrame()->removeHostCallFrameFlag()) {
   3971         if (candidate->callee() == function)
   3972             return candidate;
   3973     }
   3974     return 0;
   3975 }
   3976 
   3977 void Interpreter::enableSampler()
   3978 {
   3979 #if ENABLE(OPCODE_SAMPLING)
   3980     if (!m_sampler) {
   3981         m_sampler.set(new SamplingTool(this));
   3982         m_sampler->setup();
   3983     }
   3984 #endif
   3985 }
   3986 void Interpreter::dumpSampleData(ExecState* exec)
   3987 {
   3988 #if ENABLE(OPCODE_SAMPLING)
   3989     if (m_sampler)
   3990         m_sampler->dump(exec);
   3991 #else
   3992     UNUSED_PARAM(exec);
   3993 #endif
   3994 }
   3995 void Interpreter::startSampling()
   3996 {
   3997 #if ENABLE(SAMPLING_THREAD)
   3998     if (!m_sampleEntryDepth)
   3999         SamplingThread::start();
   4000 
   4001     m_sampleEntryDepth++;
   4002 #endif
   4003 }
   4004 void Interpreter::stopSampling()
   4005 {
   4006 #if ENABLE(SAMPLING_THREAD)
   4007     m_sampleEntryDepth--;
   4008     if (!m_sampleEntryDepth)
   4009         SamplingThread::stop();
   4010 #endif
   4011 }
   4012 
   4013 } // namespace JSC
   4014