Home | History | Annotate | Download | only in interpreter
      1 /*
      2  * Copyright (C) 2008, 2009, 2010 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 "Heap.h"
     39 #include "Debugger.h"
     40 #include "DebuggerCallFrame.h"
     41 #include "ErrorInstance.h"
     42 #include "EvalCodeCache.h"
     43 #include "ExceptionHelpers.h"
     44 #include "GetterSetter.h"
     45 #include "JSActivation.h"
     46 #include "JSArray.h"
     47 #include "JSByteArray.h"
     48 #include "JSFunction.h"
     49 #include "JSNotAnObject.h"
     50 #include "JSPropertyNameIterator.h"
     51 #include "LiteralParser.h"
     52 #include "JSStaticScopeObject.h"
     53 #include "JSString.h"
     54 #include "ObjectPrototype.h"
     55 #include "Operations.h"
     56 #include "Parser.h"
     57 #include "Profiler.h"
     58 #include "RegExpObject.h"
     59 #include "RegExpPrototype.h"
     60 #include "Register.h"
     61 #include "SamplingTool.h"
     62 #include "StrictEvalActivation.h"
     63 #include "UStringConcatenate.h"
     64 #include <limits.h>
     65 #include <stdio.h>
     66 #include <wtf/Threading.h>
     67 
     68 #if ENABLE(JIT)
     69 #include "JIT.h"
     70 #endif
     71 
     72 #define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(COMPUTED_GOTO_INTERPRETER) && !defined(__llvm__))
     73 
     74 using namespace std;
     75 
     76 namespace JSC {
     77 
     78 // Returns the depth of the scope chain within a given call frame.
     79 static int depth(CodeBlock* codeBlock, ScopeChainNode* sc)
     80 {
     81     if (!codeBlock->needsFullScopeChain())
     82         return 0;
     83     return sc->localDepth();
     84 }
     85 
     86 #if ENABLE(INTERPRETER)
     87 static NEVER_INLINE JSValue concatenateStrings(ExecState* exec, Register* strings, unsigned count)
     88 {
     89     return jsString(exec, strings, count);
     90 }
     91 
     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->get();
    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->uncheckedR(dst) = JSValue(result);
    113             return true;
    114         }
    115     } while (++iter != end);
    116     exceptionValue = createUndefinedVariableError(callFrame, ident);
    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;
    127 
    128     ScopeChainNode* scopeChain = callFrame->scopeChain();
    129     ScopeChainIterator iter = scopeChain->begin();
    130     ScopeChainIterator end = scopeChain->end();
    131     ASSERT(iter != end);
    132     bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
    133     ASSERT(skip || !checkTopLevel);
    134     if (checkTopLevel && skip--) {
    135         if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
    136             ++iter;
    137     }
    138     while (skip--) {
    139         ++iter;
    140         ASSERT(iter != end);
    141     }
    142     Identifier& ident = codeBlock->identifier(property);
    143     do {
    144         JSObject* o = iter->get();
    145         PropertySlot slot(o);
    146         if (o->getPropertySlot(callFrame, ident, slot)) {
    147             JSValue result = slot.getValue(callFrame, ident);
    148             exceptionValue = callFrame->globalData().exception;
    149             if (exceptionValue)
    150                 return false;
    151             ASSERT(result);
    152             callFrame->uncheckedR(dst) = JSValue(result);
    153             return true;
    154         }
    155     } while (++iter != end);
    156     exceptionValue = createUndefinedVariableError(callFrame, ident);
    157     return false;
    158 }
    159 
    160 NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
    161 {
    162     int dst = vPC[1].u.operand;
    163     CodeBlock* codeBlock = callFrame->codeBlock();
    164     JSGlobalObject* globalObject = codeBlock->globalObject();
    165     ASSERT(globalObject->isGlobalObject());
    166     int property = vPC[2].u.operand;
    167     Structure* structure = vPC[3].u.structure.get();
    168     int offset = vPC[4].u.operand;
    169 
    170     if (structure == globalObject->structure()) {
    171         callFrame->uncheckedR(dst) = JSValue(globalObject->getDirectOffset(offset));
    172         return true;
    173     }
    174 
    175     Identifier& ident = codeBlock->identifier(property);
    176     PropertySlot slot(globalObject);
    177     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
    178         JSValue result = slot.getValue(callFrame, ident);
    179         if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
    180             vPC[3].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
    181             vPC[4] = slot.cachedOffset();
    182             callFrame->uncheckedR(dst) = JSValue(result);
    183             return true;
    184         }
    185 
    186         exceptionValue = callFrame->globalData().exception;
    187         if (exceptionValue)
    188             return false;
    189         callFrame->uncheckedR(dst) = JSValue(result);
    190         return true;
    191     }
    192 
    193     exceptionValue = createUndefinedVariableError(callFrame, ident);
    194     return false;
    195 }
    196 
    197 NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
    198 {
    199     int dst = vPC[1].u.operand;
    200     CodeBlock* codeBlock = callFrame->codeBlock();
    201     JSGlobalObject* globalObject = codeBlock->globalObject();
    202     ASSERT(globalObject->isGlobalObject());
    203     int property = vPC[2].u.operand;
    204     Structure* structure = vPC[3].u.structure.get();
    205     int offset = vPC[4].u.operand;
    206     int skip = vPC[5].u.operand;
    207 
    208     ScopeChainNode* scopeChain = callFrame->scopeChain();
    209     ScopeChainIterator iter = scopeChain->begin();
    210     ScopeChainIterator end = scopeChain->end();
    211     ASSERT(iter != end);
    212     bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
    213     ASSERT(skip || !checkTopLevel);
    214     if (checkTopLevel && skip--) {
    215         if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
    216             ++iter;
    217     }
    218     while (skip--) {
    219         JSObject* o = iter->get();
    220         if (o->hasCustomProperties()) {
    221             Identifier& ident = codeBlock->identifier(property);
    222             do {
    223                 PropertySlot slot(o);
    224                 if (o->getPropertySlot(callFrame, ident, slot)) {
    225                     JSValue result = slot.getValue(callFrame, ident);
    226                     exceptionValue = callFrame->globalData().exception;
    227                     if (exceptionValue)
    228                         return false;
    229                     ASSERT(result);
    230                     callFrame->uncheckedR(dst) = JSValue(result);
    231                     return true;
    232                 }
    233                 if (iter == end)
    234                     break;
    235                 o = iter->get();
    236                 ++iter;
    237             } while (true);
    238             exceptionValue = createUndefinedVariableError(callFrame, ident);
    239             return false;
    240         }
    241         ++iter;
    242     }
    243 
    244     if (structure == globalObject->structure()) {
    245         callFrame->uncheckedR(dst) = JSValue(globalObject->getDirectOffset(offset));
    246         ASSERT(callFrame->uncheckedR(dst).jsValue());
    247         return true;
    248     }
    249 
    250     Identifier& ident = codeBlock->identifier(property);
    251     PropertySlot slot(globalObject);
    252     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
    253         JSValue result = slot.getValue(callFrame, ident);
    254         if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
    255             vPC[3].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
    256             vPC[4] = slot.cachedOffset();
    257             ASSERT(result);
    258             callFrame->uncheckedR(dst) = JSValue(result);
    259             return true;
    260         }
    261 
    262         exceptionValue = callFrame->globalData().exception;
    263         if (exceptionValue)
    264             return false;
    265         ASSERT(result);
    266         callFrame->uncheckedR(dst) = JSValue(result);
    267         return true;
    268     }
    269 
    270     exceptionValue = createUndefinedVariableError(callFrame, ident);
    271     return false;
    272 }
    273 
    274 NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC)
    275 {
    276     int dst = vPC[1].u.operand;
    277     int property = vPC[2].u.operand;
    278     bool isStrictPut = vPC[3].u.operand;
    279     Identifier ident = callFrame->codeBlock()->identifier(property);
    280     JSValue result = JSC::resolveBase(callFrame, ident, callFrame->scopeChain(), isStrictPut);
    281     if (result) {
    282         callFrame->uncheckedR(dst) = result;
    283         ASSERT(callFrame->uncheckedR(dst).jsValue());
    284     } else
    285         callFrame->globalData().exception = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring());
    286 }
    287 
    288 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
    289 {
    290     int baseDst = vPC[1].u.operand;
    291     int propDst = vPC[2].u.operand;
    292     int property = vPC[3].u.operand;
    293 
    294     ScopeChainNode* scopeChain = callFrame->scopeChain();
    295     ScopeChainIterator iter = scopeChain->begin();
    296     ScopeChainIterator end = scopeChain->end();
    297 
    298     // FIXME: add scopeDepthIsZero optimization
    299 
    300     ASSERT(iter != end);
    301 
    302     CodeBlock* codeBlock = callFrame->codeBlock();
    303     Identifier& ident = codeBlock->identifier(property);
    304     JSObject* base;
    305     do {
    306         base = iter->get();
    307         PropertySlot slot(base);
    308         if (base->getPropertySlot(callFrame, ident, slot)) {
    309             JSValue result = slot.getValue(callFrame, ident);
    310             exceptionValue = callFrame->globalData().exception;
    311             if (exceptionValue)
    312                 return false;
    313             callFrame->uncheckedR(propDst) = JSValue(result);
    314             callFrame->uncheckedR(baseDst) = JSValue(base);
    315             return true;
    316         }
    317         ++iter;
    318     } while (iter != end);
    319 
    320     exceptionValue = createUndefinedVariableError(callFrame, ident);
    321     return false;
    322 }
    323 
    324 #endif // ENABLE(INTERPRETER)
    325 
    326 ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
    327 {
    328     Register* r = callFrame->registers();
    329     Register* newEnd = r + registerOffset + newCodeBlock->m_numCalleeRegisters;
    330 
    331     if (LIKELY(argc == newCodeBlock->m_numParameters)) { // correct number of arguments
    332         if (UNLIKELY(!registerFile->grow(newEnd)))
    333             return 0;
    334         r += registerOffset;
    335     } else if (argc < newCodeBlock->m_numParameters) { // too few arguments -- fill in the blanks
    336         size_t omittedArgCount = newCodeBlock->m_numParameters - argc;
    337         registerOffset += omittedArgCount;
    338         newEnd += omittedArgCount;
    339         if (!registerFile->grow(newEnd))
    340             return 0;
    341         r += registerOffset;
    342 
    343         Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
    344         for (size_t i = 0; i < omittedArgCount; ++i)
    345             argv[i] = jsUndefined();
    346     } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind
    347         size_t numParameters = newCodeBlock->m_numParameters;
    348         registerOffset += numParameters;
    349         newEnd += numParameters;
    350 
    351         if (!registerFile->grow(newEnd))
    352             return 0;
    353         r += registerOffset;
    354 
    355         Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argc;
    356         for (size_t i = 0; i < numParameters; ++i)
    357             argv[i + argc] = argv[i];
    358     }
    359 
    360     return CallFrame::create(r);
    361 }
    362 
    363 #if ENABLE(INTERPRETER)
    364 static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, JSValue value, JSValue& exceptionData)
    365 {
    366     if (value.isObject())
    367         return false;
    368     exceptionData = createInvalidParamError(callFrame, "in" , value);
    369     return true;
    370 }
    371 
    372 static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, JSValue value, JSValue& exceptionData)
    373 {
    374     if (value.isObject() && asObject(value)->structure()->typeInfo().implementsHasInstance())
    375         return false;
    376     exceptionData = createInvalidParamError(callFrame, "instanceof" , value);
    377     return true;
    378 }
    379 #endif
    380 
    381 NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset)
    382 {
    383     if (argc < 2)
    384         return jsUndefined();
    385 
    386     JSValue program = argv[1].jsValue();
    387 
    388     if (!program.isString())
    389         return program;
    390 
    391     UString programSource = asString(program)->value(callFrame);
    392     if (callFrame->hadException())
    393         return JSValue();
    394 
    395     CodeBlock* codeBlock = callFrame->codeBlock();
    396     if (!codeBlock->isStrictMode()) {
    397         // FIXME: We can use the preparser in strict mode, we just need additional logic
    398         // to prevent duplicates.
    399         LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
    400         if (JSValue parsedObject = preparser.tryLiteralParse())
    401             return parsedObject;
    402     }
    403 
    404     ScopeChainNode* scopeChain = callFrame->scopeChain();
    405     JSValue exceptionValue;
    406     EvalExecutable* eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->ownerExecutable(), codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue);
    407 
    408     ASSERT(!eval == exceptionValue);
    409     if (UNLIKELY(!eval))
    410         return throwError(callFrame, exceptionValue);
    411 
    412     return callFrame->globalData().interpreter->execute(eval, callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain);
    413 }
    414 
    415 Interpreter::Interpreter(JSGlobalData& globalData)
    416     : m_sampleEntryDepth(0)
    417     , m_reentryDepth(0)
    418     , m_registerFile(globalData)
    419 {
    420 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
    421     privateExecute(InitializeAndReturn, 0, 0);
    422 
    423     for (int i = 0; i < numOpcodeIDs; ++i)
    424         m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
    425 #endif // ENABLE(COMPUTED_GOTO_INTERPRETER)
    426 
    427 #if ENABLE(OPCODE_SAMPLING)
    428     enableSampler();
    429 #endif
    430 }
    431 
    432 #ifndef NDEBUG
    433 
    434 void Interpreter::dumpCallFrame(CallFrame* callFrame)
    435 {
    436     callFrame->codeBlock()->dump(callFrame);
    437     dumpRegisters(callFrame);
    438 }
    439 
    440 void Interpreter::dumpRegisters(CallFrame* callFrame)
    441 {
    442     printf("Register frame: \n\n");
    443     printf("-----------------------------------------------------------------------------\n");
    444     printf("            use            |   address  |                value               \n");
    445     printf("-----------------------------------------------------------------------------\n");
    446 
    447     CodeBlock* codeBlock = callFrame->codeBlock();
    448     RegisterFile* registerFile = &callFrame->scopeChain()->globalObject->globalData().interpreter->registerFile();
    449     const Register* it;
    450     const Register* end;
    451     JSValue v;
    452 
    453     if (codeBlock->codeType() == GlobalCode) {
    454         it = registerFile->lastGlobal();
    455         end = it + registerFile->numGlobals();
    456         while (it != end) {
    457             v = (*it).jsValue();
    458 #if USE(JSVALUE32_64)
    459             printf("[global var]               | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
    460 #else
    461             printf("[global var]               | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
    462 #endif
    463             ++it;
    464         }
    465         printf("-----------------------------------------------------------------------------\n");
    466     }
    467 
    468     it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;
    469     v = (*it).jsValue();
    470 #if USE(JSVALUE32_64)
    471     printf("[this]                     | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it;
    472 #else
    473     printf("[this]                     | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it;
    474 #endif
    475     end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this"
    476     if (it != end) {
    477         do {
    478             v = (*it).jsValue();
    479 #if USE(JSVALUE32_64)
    480             printf("[param]                    | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
    481 #else
    482             printf("[param]                    | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
    483 #endif
    484             ++it;
    485         } while (it != end);
    486     }
    487     printf("-----------------------------------------------------------------------------\n");
    488     printf("[CodeBlock]                | %10p | %p \n", it, (*it).codeBlock()); ++it;
    489     printf("[ScopeChain]               | %10p | %p \n", it, (*it).scopeChain()); ++it;
    490     printf("[CallerRegisters]          | %10p | %d \n", it, (*it).i()); ++it;
    491     printf("[ReturnPC]                 | %10p | %p \n", it, (*it).vPC()); ++it;
    492     printf("[ArgumentCount]            | %10p | %d \n", it, (*it).i()); ++it;
    493     printf("[Callee]                   | %10p | %p \n", it, (*it).function()); ++it;
    494     printf("-----------------------------------------------------------------------------\n");
    495 
    496     int registerCount = 0;
    497 
    498     end = it + codeBlock->m_numVars;
    499     if (it != end) {
    500         do {
    501             v = (*it).jsValue();
    502 #if USE(JSVALUE32_64)
    503             printf("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
    504 #else
    505             printf("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
    506 #endif
    507             ++it;
    508             ++registerCount;
    509         } while (it != end);
    510     }
    511     printf("-----------------------------------------------------------------------------\n");
    512 
    513     end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
    514     if (it != end) {
    515         do {
    516             v = (*it).jsValue();
    517 #if USE(JSVALUE32_64)
    518             printf("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
    519 #else
    520             printf("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
    521 #endif
    522             ++it;
    523             ++registerCount;
    524         } while (it != end);
    525     }
    526     printf("-----------------------------------------------------------------------------\n");
    527 }
    528 
    529 #endif
    530 
    531 bool Interpreter::isOpcode(Opcode opcode)
    532 {
    533 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
    534     return opcode != HashTraits<Opcode>::emptyValue()
    535         && !HashTraits<Opcode>::isDeletedValue(opcode)
    536         && m_opcodeIDTable.contains(opcode);
    537 #else
    538     return opcode >= 0 && opcode <= op_end;
    539 #endif
    540 }
    541 
    542 NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue exceptionValue, unsigned& bytecodeOffset, CodeBlock*& codeBlock)
    543 {
    544     CodeBlock* oldCodeBlock = codeBlock;
    545     ScopeChainNode* scopeChain = callFrame->scopeChain();
    546 
    547     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
    548         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
    549         if (callFrame->callee())
    550             debugger->returnEvent(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
    551         else
    552             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
    553     }
    554 
    555     // If this call frame created an activation or an 'arguments' object, tear it off.
    556     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
    557         if (!callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue()) {
    558             oldCodeBlock->createActivation(callFrame);
    559             scopeChain = callFrame->scopeChain();
    560         }
    561         while (!scopeChain->object->inherits(&JSActivation::s_info))
    562             scopeChain = scopeChain->pop();
    563 
    564         callFrame->setScopeChain(scopeChain);
    565         JSActivation* activation = asActivation(scopeChain->object.get());
    566         activation->copyRegisters(*scopeChain->globalData);
    567         if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) {
    568             if (!oldCodeBlock->isStrictMode())
    569                 asArguments(arguments)->setActivation(callFrame->globalData(), activation);
    570         }
    571     } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) {
    572         if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
    573             asArguments(arguments)->copyRegisters(callFrame->globalData());
    574     }
    575 
    576     CallFrame* callerFrame = callFrame->callerFrame();
    577     if (callerFrame->hasHostCallFrameFlag())
    578         return false;
    579 
    580     codeBlock = callerFrame->codeBlock();
    581 #if ENABLE(JIT) && ENABLE(INTERPRETER)
    582     if (callerFrame->globalData().canUseJIT())
    583         bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
    584     else
    585         bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC());
    586 #elif ENABLE(JIT)
    587     bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
    588 #else
    589     bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC());
    590 #endif
    591 
    592     callFrame = callerFrame;
    593     return true;
    594 }
    595 
    596 static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, unsigned bytecodeOffset)
    597 {
    598     exception->clearAppendSourceToMessage();
    599 
    600     if (!callFrame->codeBlock()->hasExpressionInfo())
    601         return;
    602 
    603     int startOffset = 0;
    604     int endOffset = 0;
    605     int divotPoint = 0;
    606 
    607     CodeBlock* codeBlock = callFrame->codeBlock();
    608     codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divotPoint, startOffset, endOffset);
    609 
    610     int expressionStart = divotPoint - startOffset;
    611     int expressionStop = divotPoint + endOffset;
    612 
    613     if (!expressionStop || expressionStart > codeBlock->source()->length())
    614         return;
    615 
    616     JSGlobalData* globalData = &callFrame->globalData();
    617     JSValue jsMessage = exception->getDirect(*globalData, globalData->propertyNames->message);
    618     if (!jsMessage || !jsMessage.isString())
    619         return;
    620 
    621     UString message = asString(jsMessage)->value(callFrame);
    622 
    623     if (expressionStart < expressionStop)
    624         message =  makeUString(message, " (evaluating '", codeBlock->source()->getRange(expressionStart, expressionStop), "')");
    625     else {
    626         // No range information, so give a few characters of context
    627         const UChar* data = codeBlock->source()->data();
    628         int dataLength = codeBlock->source()->length();
    629         int start = expressionStart;
    630         int stop = expressionStart;
    631         // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
    632         // then strip whitespace.
    633         while (start > 0 && (expressionStart - start < 20) && data[start - 1] != '\n')
    634             start--;
    635         while (start < (expressionStart - 1) && isStrWhiteSpace(data[start]))
    636             start++;
    637         while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n')
    638             stop++;
    639         while (stop > expressionStart && isStrWhiteSpace(data[stop - 1]))
    640             stop--;
    641         message = makeUString(message, " (near '...", codeBlock->source()->getRange(start, stop), "...')");
    642     }
    643 
    644     exception->putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
    645 }
    646 
    647 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
    648 {
    649     CodeBlock* codeBlock = callFrame->codeBlock();
    650     bool isInterrupt = false;
    651 
    652     // Set up the exception object
    653     if (exceptionValue.isObject()) {
    654         JSObject* exception = asObject(exceptionValue);
    655 
    656         if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
    657             appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset);
    658 
    659         // Using hasExpressionInfo to imply we are interested in rich exception info.
    660         if (codeBlock->hasExpressionInfo() && !hasErrorInfo(callFrame, exception)) {
    661             ASSERT(codeBlock->hasLineInfo());
    662 
    663             // FIXME: should only really be adding these properties to VM generated exceptions,
    664             // but the inspector currently requires these for all thrown objects.
    665             addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
    666         }
    667 
    668         ComplType exceptionType = exception->exceptionType();
    669         isInterrupt = exceptionType == Interrupted || exceptionType == Terminated;
    670     }
    671 
    672     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
    673         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
    674         bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
    675         debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), hasHandler);
    676     }
    677 
    678     // Calculate an exception handler vPC, unwinding call frames as necessary.
    679     HandlerInfo* handler = 0;
    680     while (isInterrupt || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
    681         if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
    682             if (Profiler* profiler = *Profiler::enabledProfilerReference())
    683                 profiler->exceptionUnwind(callFrame);
    684             return 0;
    685         }
    686     }
    687 
    688     if (Profiler* profiler = *Profiler::enabledProfilerReference())
    689         profiler->exceptionUnwind(callFrame);
    690 
    691     // Shrink the JS stack, in case stack overflow made it huge.
    692     Register* highWaterMark = 0;
    693     for (CallFrame* callerFrame = callFrame; callerFrame; callerFrame = callerFrame->callerFrame()->removeHostCallFrameFlag()) {
    694         CodeBlock* codeBlock = callerFrame->codeBlock();
    695         if (!codeBlock)
    696             continue;
    697         Register* callerHighWaterMark = callerFrame->registers() + codeBlock->m_numCalleeRegisters;
    698         highWaterMark = max(highWaterMark, callerHighWaterMark);
    699     }
    700     m_registerFile.shrink(highWaterMark);
    701 
    702     // Unwind the scope chain within the exception handler's call frame.
    703     ScopeChainNode* scopeChain = callFrame->scopeChain();
    704     int scopeDelta = 0;
    705     if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode
    706         || callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
    707         scopeDelta = depth(codeBlock, scopeChain) - handler->scopeDepth;
    708     ASSERT(scopeDelta >= 0);
    709     while (scopeDelta--)
    710         scopeChain = scopeChain->pop();
    711     callFrame->setScopeChain(scopeChain);
    712 
    713     return handler;
    714 }
    715 
    716 static inline JSValue checkedReturn(JSValue returnValue)
    717 {
    718     ASSERT(returnValue);
    719     return returnValue;
    720 }
    721 
    722 static inline JSObject* checkedReturn(JSObject* returnValue)
    723 {
    724     ASSERT(returnValue);
    725     return returnValue;
    726 }
    727 
    728 JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj)
    729 {
    730     ASSERT(!scopeChain->globalData->exception);
    731 
    732     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
    733         return checkedReturn(throwStackOverflowError(callFrame));
    734 
    735     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
    736 
    737     JSObject* error = program->compile(callFrame, scopeChain);
    738     if (error)
    739         return checkedReturn(throwError(callFrame, error));
    740     CodeBlock* codeBlock = &program->generatedBytecode();
    741 
    742     Register* oldEnd = m_registerFile.end();
    743     Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
    744     if (!m_registerFile.grow(newEnd))
    745         return checkedReturn(throwStackOverflowError(callFrame));
    746 
    747     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
    748     JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
    749     globalObject->copyGlobalsTo(m_registerFile);
    750 
    751     CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
    752     ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
    753     newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), codeBlock->m_numParameters, 0);
    754     newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj);
    755 
    756     Profiler** profiler = Profiler::enabledProfilerReference();
    757     if (*profiler)
    758         (*profiler)->willExecute(callFrame, program->sourceURL(), program->lineNo());
    759 
    760     JSValue result;
    761     {
    762         SamplingTool::CallRecord callRecord(m_sampler.get());
    763 
    764         m_reentryDepth++;
    765 #if ENABLE(JIT)
    766         if (callFrame->globalData().canUseJIT())
    767             result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
    768         else
    769 #endif
    770             result = privateExecute(Normal, &m_registerFile, newCallFrame);
    771 
    772         m_reentryDepth--;
    773     }
    774 
    775     if (*profiler)
    776         (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
    777 
    778     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
    779         lastGlobalObject->copyGlobalsTo(m_registerFile);
    780 
    781     m_registerFile.shrink(oldEnd);
    782 
    783     return checkedReturn(result);
    784 }
    785 
    786 JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
    787 {
    788     ASSERT(!callFrame->hadException());
    789 
    790     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
    791         return checkedReturn(throwStackOverflowError(callFrame));
    792 
    793     Register* oldEnd = m_registerFile.end();
    794     int argCount = 1 + args.size(); // implicit "this" parameter
    795     size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
    796 
    797     if (!m_registerFile.grow(oldEnd + registerOffset))
    798         return checkedReturn(throwStackOverflowError(callFrame));
    799 
    800     CallFrame* newCallFrame = CallFrame::create(oldEnd);
    801     size_t dst = 0;
    802     newCallFrame->uncheckedR(0) = thisValue;
    803     ArgList::const_iterator end = args.end();
    804     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
    805         newCallFrame->uncheckedR(++dst) = *it;
    806 
    807     if (callType == CallTypeJS) {
    808         ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
    809 
    810         DynamicGlobalObjectScope globalObjectScope(*callDataScopeChain->globalData, callDataScopeChain->globalObject.get());
    811 
    812         JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
    813         if (UNLIKELY(!!compileError)) {
    814             m_registerFile.shrink(oldEnd);
    815             return checkedReturn(throwError(callFrame, compileError));
    816         }
    817 
    818         CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
    819         newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
    820         if (UNLIKELY(!newCallFrame)) {
    821             m_registerFile.shrink(oldEnd);
    822             return checkedReturn(throwStackOverflowError(callFrame));
    823         }
    824 
    825         newCallFrame->init(newCodeBlock, 0, callDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
    826 
    827         Profiler** profiler = Profiler::enabledProfilerReference();
    828         if (*profiler)
    829             (*profiler)->willExecute(callFrame, function);
    830 
    831         JSValue result;
    832         {
    833             SamplingTool::CallRecord callRecord(m_sampler.get());
    834 
    835             m_reentryDepth++;
    836 #if ENABLE(JIT)
    837             if (callFrame->globalData().canUseJIT())
    838                 result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData);
    839             else
    840 #endif
    841                 result = privateExecute(Normal, &m_registerFile, newCallFrame);
    842             m_reentryDepth--;
    843         }
    844 
    845         if (*profiler)
    846             (*profiler)->didExecute(callFrame, function);
    847 
    848         m_registerFile.shrink(oldEnd);
    849         return checkedReturn(result);
    850     }
    851 
    852     ASSERT(callType == CallTypeHost);
    853     ScopeChainNode* scopeChain = callFrame->scopeChain();
    854     newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
    855     newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
    856 
    857     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
    858 
    859     Profiler** profiler = Profiler::enabledProfilerReference();
    860     if (*profiler)
    861         (*profiler)->willExecute(callFrame, function);
    862 
    863     JSValue result;
    864     {
    865         SamplingTool::HostCallRecord callRecord(m_sampler.get());
    866         result = JSValue::decode(callData.native.function(newCallFrame));
    867     }
    868 
    869     if (*profiler)
    870         (*profiler)->didExecute(callFrame, function);
    871 
    872     m_registerFile.shrink(oldEnd);
    873     return checkedReturn(result);
    874 }
    875 
    876 JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
    877 {
    878     ASSERT(!callFrame->hadException());
    879 
    880     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
    881         return checkedReturn(throwStackOverflowError(callFrame));
    882 
    883     Register* oldEnd = m_registerFile.end();
    884     int argCount = 1 + args.size(); // implicit "this" parameter
    885     size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
    886 
    887     if (!m_registerFile.grow(oldEnd + registerOffset))
    888         return checkedReturn(throwStackOverflowError(callFrame));
    889 
    890     CallFrame* newCallFrame = CallFrame::create(oldEnd);
    891     size_t dst = 0;
    892     ArgList::const_iterator end = args.end();
    893     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
    894         newCallFrame->uncheckedR(++dst) = *it;
    895 
    896     if (constructType == ConstructTypeJS) {
    897         ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain;
    898 
    899         DynamicGlobalObjectScope globalObjectScope(*constructDataScopeChain->globalData, constructDataScopeChain->globalObject.get());
    900 
    901         JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, constructDataScopeChain);
    902         if (UNLIKELY(!!compileError)) {
    903             m_registerFile.shrink(oldEnd);
    904             return checkedReturn(throwError(callFrame, compileError));
    905         }
    906 
    907         CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
    908         newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
    909         if (UNLIKELY(!newCallFrame)) {
    910             m_registerFile.shrink(oldEnd);
    911             return checkedReturn(throwStackOverflowError(callFrame));
    912         }
    913 
    914         newCallFrame->init(newCodeBlock, 0, constructDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
    915 
    916         Profiler** profiler = Profiler::enabledProfilerReference();
    917         if (*profiler)
    918             (*profiler)->willExecute(callFrame, constructor);
    919 
    920         JSValue result;
    921         {
    922             SamplingTool::CallRecord callRecord(m_sampler.get());
    923 
    924             m_reentryDepth++;
    925 #if ENABLE(JIT)
    926             if (callFrame->globalData().canUseJIT())
    927                 result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData);
    928             else
    929 #endif
    930                 result = privateExecute(Normal, &m_registerFile, newCallFrame);
    931             m_reentryDepth--;
    932         }
    933 
    934         if (*profiler)
    935             (*profiler)->didExecute(callFrame, constructor);
    936 
    937         m_registerFile.shrink(oldEnd);
    938         if (callFrame->hadException())
    939             return 0;
    940         ASSERT(result.isObject());
    941         return checkedReturn(asObject(result));
    942     }
    943 
    944     ASSERT(constructType == ConstructTypeHost);
    945     ScopeChainNode* scopeChain = callFrame->scopeChain();
    946     newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
    947     newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
    948 
    949     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
    950 
    951     Profiler** profiler = Profiler::enabledProfilerReference();
    952     if (*profiler)
    953         (*profiler)->willExecute(callFrame, constructor);
    954 
    955     JSValue result;
    956     {
    957         SamplingTool::HostCallRecord callRecord(m_sampler.get());
    958         result = JSValue::decode(constructData.native.function(newCallFrame));
    959     }
    960 
    961     if (*profiler)
    962         (*profiler)->didExecute(callFrame, constructor);
    963 
    964     m_registerFile.shrink(oldEnd);
    965     if (callFrame->hadException())
    966         return 0;
    967     ASSERT(result.isObject());
    968     return checkedReturn(asObject(result));
    969 }
    970 
    971 CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain)
    972 {
    973     ASSERT(!scopeChain->globalData->exception);
    974 
    975     if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
    976         if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
    977             throwStackOverflowError(callFrame);
    978             return CallFrameClosure();
    979         }
    980     }
    981 
    982     Register* oldEnd = m_registerFile.end();
    983     int argc = 1 + argCount; // implicit "this" parameter
    984 
    985     if (!m_registerFile.grow(oldEnd + argc)) {
    986         throwStackOverflowError(callFrame);
    987         return CallFrameClosure();
    988     }
    989 
    990     CallFrame* newCallFrame = CallFrame::create(oldEnd);
    991     // We initialise |this| unnecessarily here for the sake of code clarity
    992     size_t dst = 0;
    993     for (int i = 0; i < argc; ++i)
    994         newCallFrame->uncheckedR(dst++) = jsUndefined();
    995 
    996     JSObject* error = FunctionExecutable->compileForCall(callFrame, scopeChain);
    997     if (error) {
    998         throwError(callFrame, error);
    999         m_registerFile.shrink(oldEnd);
   1000         return CallFrameClosure();
   1001     }
   1002     CodeBlock* codeBlock = &FunctionExecutable->generatedBytecodeForCall();
   1003 
   1004     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
   1005     if (UNLIKELY(!newCallFrame)) {
   1006         throwStackOverflowError(callFrame);
   1007         m_registerFile.shrink(oldEnd);
   1008         return CallFrameClosure();
   1009     }
   1010     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function);
   1011     CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
   1012     return result;
   1013 }
   1014 
   1015 JSValue Interpreter::execute(CallFrameClosure& closure)
   1016 {
   1017     closure.resetCallFrame();
   1018     Profiler** profiler = Profiler::enabledProfilerReference();
   1019     if (*profiler)
   1020         (*profiler)->willExecute(closure.oldCallFrame, closure.function);
   1021 
   1022     JSValue result;
   1023     {
   1024         SamplingTool::CallRecord callRecord(m_sampler.get());
   1025 
   1026         m_reentryDepth++;
   1027 #if ENABLE(JIT)
   1028 #if ENABLE(INTERPRETER)
   1029         if (closure.newCallFrame->globalData().canUseJIT())
   1030 #endif
   1031             result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData);
   1032 #if ENABLE(INTERPRETER)
   1033         else
   1034 #endif
   1035 #endif
   1036 #if ENABLE(INTERPRETER)
   1037             result = privateExecute(Normal, &m_registerFile, closure.newCallFrame);
   1038 #endif
   1039         m_reentryDepth--;
   1040     }
   1041 
   1042     if (*profiler)
   1043         (*profiler)->didExecute(closure.oldCallFrame, closure.function);
   1044     return checkedReturn(result);
   1045 }
   1046 
   1047 void Interpreter::endRepeatCall(CallFrameClosure& closure)
   1048 {
   1049     m_registerFile.shrink(closure.oldEnd);
   1050 }
   1051 
   1052 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain)
   1053 {
   1054     JSObject* compileError = eval->compile(callFrame, scopeChain);
   1055     if (UNLIKELY(!!compileError))
   1056         return checkedReturn(throwError(callFrame, compileError));
   1057     return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->generatedBytecode().m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain);
   1058 }
   1059 
   1060 JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain)
   1061 {
   1062     ASSERT(!scopeChain->globalData->exception);
   1063 
   1064     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
   1065 
   1066     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
   1067         return checkedReturn(throwStackOverflowError(callFrame));
   1068 
   1069     JSObject* compileError = eval->compile(callFrame, scopeChain);
   1070     if (UNLIKELY(!!compileError))
   1071         return checkedReturn(throwError(callFrame, compileError));
   1072     EvalCodeBlock* codeBlock = &eval->generatedBytecode();
   1073 
   1074     JSObject* variableObject;
   1075     for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) {
   1076         ASSERT(node);
   1077         if (node->object->isVariableObject()) {
   1078             variableObject = static_cast<JSVariableObject*>(node->object.get());
   1079             break;
   1080         }
   1081     }
   1082 
   1083     unsigned numVariables = codeBlock->numVariables();
   1084     int numFunctions = codeBlock->numberOfFunctionDecls();
   1085     bool pushedScope = false;
   1086     if (numVariables || numFunctions) {
   1087         if (codeBlock->isStrictMode()) {
   1088             variableObject = new (callFrame) StrictEvalActivation(callFrame);
   1089             scopeChain = scopeChain->push(variableObject);
   1090             pushedScope = true;
   1091         }
   1092         // Scope for BatchedTransitionOptimizer
   1093         BatchedTransitionOptimizer optimizer(callFrame->globalData(), variableObject);
   1094 
   1095         for (unsigned i = 0; i < numVariables; ++i) {
   1096             const Identifier& ident = codeBlock->variable(i);
   1097             if (!variableObject->hasProperty(callFrame, ident)) {
   1098                 PutPropertySlot slot;
   1099                 variableObject->put(callFrame, ident, jsUndefined(), slot);
   1100             }
   1101         }
   1102 
   1103         for (int i = 0; i < numFunctions; ++i) {
   1104             FunctionExecutable* function = codeBlock->functionDecl(i);
   1105             PutPropertySlot slot;
   1106             variableObject->put(callFrame, function->name(), function->make(callFrame, scopeChain), slot);
   1107         }
   1108     }
   1109 
   1110     Register* oldEnd = m_registerFile.end();
   1111     Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
   1112     if (!m_registerFile.grow(newEnd)) {
   1113         if (pushedScope)
   1114             scopeChain->pop();
   1115         return checkedReturn(throwStackOverflowError(callFrame));
   1116     }
   1117 
   1118     CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
   1119 
   1120     ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
   1121     newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), codeBlock->m_numParameters, 0);
   1122     newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj);
   1123 
   1124     Profiler** profiler = Profiler::enabledProfilerReference();
   1125     if (*profiler)
   1126         (*profiler)->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
   1127 
   1128     JSValue result;
   1129     {
   1130         SamplingTool::CallRecord callRecord(m_sampler.get());
   1131 
   1132         m_reentryDepth++;
   1133 
   1134 #if ENABLE(JIT)
   1135 #if ENABLE(INTERPRETER)
   1136         if (callFrame->globalData().canUseJIT())
   1137 #endif
   1138             result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
   1139 #if ENABLE(INTERPRETER)
   1140         else
   1141 #endif
   1142 #endif
   1143 #if ENABLE(INTERPRETER)
   1144             result = privateExecute(Normal, &m_registerFile, newCallFrame);
   1145 #endif
   1146         m_reentryDepth--;
   1147     }
   1148 
   1149     if (*profiler)
   1150         (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
   1151 
   1152     m_registerFile.shrink(oldEnd);
   1153     if (pushedScope)
   1154         scopeChain->pop();
   1155     return checkedReturn(result);
   1156 }
   1157 
   1158 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine)
   1159 {
   1160     Debugger* debugger = callFrame->dynamicGlobalObject()->debugger();
   1161     if (!debugger)
   1162         return;
   1163 
   1164     switch (debugHookID) {
   1165         case DidEnterCallFrame:
   1166             debugger->callEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
   1167             return;
   1168         case WillLeaveCallFrame:
   1169             debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
   1170             return;
   1171         case WillExecuteStatement:
   1172             debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
   1173             return;
   1174         case WillExecuteProgram:
   1175             debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine);
   1176             return;
   1177         case DidExecuteProgram:
   1178             debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
   1179             return;
   1180         case DidReachBreakpoint:
   1181             debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine);
   1182             return;
   1183     }
   1184 }
   1185 
   1186 #if ENABLE(INTERPRETER)
   1187 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
   1188 {
   1189     int dst = vPC[1].u.operand;
   1190     CodeBlock* codeBlock = callFrame->codeBlock();
   1191     Identifier& property = codeBlock->identifier(vPC[2].u.operand);
   1192     JSValue value = callFrame->r(vPC[3].u.operand).jsValue();
   1193     JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
   1194     callFrame->uncheckedR(dst) = JSValue(scope);
   1195 
   1196     return callFrame->scopeChain()->push(scope);
   1197 }
   1198 
   1199 NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const PutPropertySlot& slot)
   1200 {
   1201     // Recursive invocation may already have specialized this instruction.
   1202     if (vPC[0].u.opcode != getOpcode(op_put_by_id))
   1203         return;
   1204 
   1205     if (!baseValue.isCell())
   1206         return;
   1207 
   1208     // Uncacheable: give up.
   1209     if (!slot.isCacheable()) {
   1210         vPC[0] = getOpcode(op_put_by_id_generic);
   1211         return;
   1212     }
   1213 
   1214     JSCell* baseCell = baseValue.asCell();
   1215     Structure* structure = baseCell->structure();
   1216 
   1217     if (structure->isUncacheableDictionary()) {
   1218         vPC[0] = getOpcode(op_put_by_id_generic);
   1219         return;
   1220     }
   1221 
   1222     // Cache miss: record Structure to compare against next time.
   1223     Structure* lastStructure = vPC[4].u.structure.get();
   1224     if (structure != lastStructure) {
   1225         // First miss: record Structure to compare against next time.
   1226         if (!lastStructure) {
   1227             vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
   1228             return;
   1229         }
   1230 
   1231         // Second miss: give up.
   1232         vPC[0] = getOpcode(op_put_by_id_generic);
   1233         return;
   1234     }
   1235 
   1236     // Cache hit: Specialize instruction and ref Structures.
   1237 
   1238     // If baseCell != slot.base(), then baseCell must be a proxy for another object.
   1239     if (baseCell != slot.base()) {
   1240         vPC[0] = getOpcode(op_put_by_id_generic);
   1241         return;
   1242     }
   1243 
   1244     // Structure transition, cache transition info
   1245     if (slot.type() == PutPropertySlot::NewProperty) {
   1246         if (structure->isDictionary()) {
   1247             vPC[0] = getOpcode(op_put_by_id_generic);
   1248             return;
   1249         }
   1250 
   1251         // put_by_id_transition checks the prototype chain for setters.
   1252         normalizePrototypeChain(callFrame, baseCell);
   1253         JSCell* owner = codeBlock->ownerExecutable();
   1254         JSGlobalData& globalData = callFrame->globalData();
   1255         vPC[0] = getOpcode(op_put_by_id_transition);
   1256         vPC[4].u.structure.set(globalData, owner, structure->previousID());
   1257         vPC[5].u.structure.set(globalData, owner, structure);
   1258         vPC[6].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure->prototypeChain(callFrame));
   1259         ASSERT(vPC[6].u.structureChain);
   1260         vPC[7] = slot.cachedOffset();
   1261         return;
   1262     }
   1263 
   1264     vPC[0] = getOpcode(op_put_by_id_replace);
   1265     vPC[5] = slot.cachedOffset();
   1266 }
   1267 
   1268 NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock*, Instruction* vPC)
   1269 {
   1270     vPC[0] = getOpcode(op_put_by_id);
   1271     vPC[4] = 0;
   1272 }
   1273 
   1274 NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* vPC, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot)
   1275 {
   1276     // Recursive invocation may already have specialized this instruction.
   1277     if (vPC[0].u.opcode != getOpcode(op_get_by_id))
   1278         return;
   1279 
   1280     // FIXME: Cache property access for immediates.
   1281     if (!baseValue.isCell()) {
   1282         vPC[0] = getOpcode(op_get_by_id_generic);
   1283         return;
   1284     }
   1285 
   1286     JSGlobalData* globalData = &callFrame->globalData();
   1287     if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
   1288         vPC[0] = getOpcode(op_get_array_length);
   1289         return;
   1290     }
   1291 
   1292     if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
   1293         vPC[0] = getOpcode(op_get_string_length);
   1294         return;
   1295     }
   1296 
   1297     // Uncacheable: give up.
   1298     if (!slot.isCacheable()) {
   1299         vPC[0] = getOpcode(op_get_by_id_generic);
   1300         return;
   1301     }
   1302 
   1303     Structure* structure = baseValue.asCell()->structure();
   1304 
   1305     if (structure->isUncacheableDictionary()) {
   1306         vPC[0] = getOpcode(op_get_by_id_generic);
   1307         return;
   1308     }
   1309 
   1310     // Cache miss
   1311     Structure* lastStructure = vPC[4].u.structure.get();
   1312     if (structure != lastStructure) {
   1313         // First miss: record Structure to compare against next time.
   1314         if (!lastStructure) {
   1315             vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
   1316             return;
   1317         }
   1318 
   1319         // Second miss: give up.
   1320         vPC[0] = getOpcode(op_get_by_id_generic);
   1321         return;
   1322     }
   1323 
   1324     // Cache hit: Specialize instruction and ref Structures.
   1325 
   1326     if (slot.slotBase() == baseValue) {
   1327         switch (slot.cachedPropertyType()) {
   1328         case PropertySlot::Getter:
   1329             vPC[0] = getOpcode(op_get_by_id_getter_self);
   1330             vPC[5] = slot.cachedOffset();
   1331             break;
   1332         case PropertySlot::Custom:
   1333             vPC[0] = getOpcode(op_get_by_id_custom_self);
   1334             vPC[5] = slot.customGetter();
   1335             break;
   1336         default:
   1337             vPC[0] = getOpcode(op_get_by_id_self);
   1338             vPC[5] = slot.cachedOffset();
   1339             break;
   1340         }
   1341         return;
   1342     }
   1343 
   1344     if (structure->isDictionary()) {
   1345         vPC[0] = getOpcode(op_get_by_id_generic);
   1346         return;
   1347     }
   1348 
   1349     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
   1350         ASSERT(slot.slotBase().isObject());
   1351 
   1352         JSObject* baseObject = asObject(slot.slotBase());
   1353         size_t offset = slot.cachedOffset();
   1354 
   1355         // Since we're accessing a prototype in a loop, it's a good bet that it
   1356         // should not be treated as a dictionary.
   1357         if (baseObject->structure()->isDictionary()) {
   1358             baseObject->flattenDictionaryObject(callFrame->globalData());
   1359             offset = baseObject->structure()->get(callFrame->globalData(), propertyName);
   1360         }
   1361 
   1362         ASSERT(!baseObject->structure()->isUncacheableDictionary());
   1363 
   1364         switch (slot.cachedPropertyType()) {
   1365         case PropertySlot::Getter:
   1366             vPC[0] = getOpcode(op_get_by_id_getter_proto);
   1367             vPC[6] = offset;
   1368             break;
   1369         case PropertySlot::Custom:
   1370             vPC[0] = getOpcode(op_get_by_id_custom_proto);
   1371             vPC[6] = slot.customGetter();
   1372             break;
   1373         default:
   1374             vPC[0] = getOpcode(op_get_by_id_proto);
   1375             vPC[6] = offset;
   1376             break;
   1377         }
   1378         vPC[5].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), baseObject->structure());
   1379         return;
   1380     }
   1381 
   1382     size_t offset = slot.cachedOffset();
   1383     size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
   1384     if (!count) {
   1385         vPC[0] = getOpcode(op_get_by_id_generic);
   1386         return;
   1387     }
   1388 
   1389 
   1390     switch (slot.cachedPropertyType()) {
   1391     case PropertySlot::Getter:
   1392         vPC[0] = getOpcode(op_get_by_id_getter_chain);
   1393         vPC[7] = offset;
   1394         break;
   1395     case PropertySlot::Custom:
   1396         vPC[0] = getOpcode(op_get_by_id_custom_chain);
   1397         vPC[7] = slot.customGetter();
   1398         break;
   1399     default:
   1400         vPC[0] = getOpcode(op_get_by_id_chain);
   1401         vPC[7] = offset;
   1402         break;
   1403     }
   1404     vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
   1405     vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure->prototypeChain(callFrame));
   1406     vPC[6] = count;
   1407 }
   1408 
   1409 NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock*, Instruction* vPC)
   1410 {
   1411     vPC[0] = getOpcode(op_get_by_id);
   1412     vPC[4] = 0;
   1413 }
   1414 
   1415 #endif // ENABLE(INTERPRETER)
   1416 
   1417 JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame)
   1418 {
   1419     // One-time initialization of our address tables. We have to put this code
   1420     // here because our labels are only in scope inside this function.
   1421     if (UNLIKELY(flag == InitializeAndReturn)) {
   1422         #if ENABLE(COMPUTED_GOTO_INTERPRETER)
   1423             #define LIST_OPCODE_LABEL(id, length) &&id,
   1424                 static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) };
   1425                 for (size_t i = 0; i < WTF_ARRAY_LENGTH(labels); ++i)
   1426                     m_opcodeTable[i] = labels[i];
   1427             #undef LIST_OPCODE_LABEL
   1428         #endif // ENABLE(COMPUTED_GOTO_INTERPRETER)
   1429         return JSValue();
   1430     }
   1431 
   1432 #if ENABLE(JIT)
   1433 #if ENABLE(INTERPRETER)
   1434     // Mixing Interpreter + JIT is not supported.
   1435     if (callFrame->globalData().canUseJIT())
   1436 #endif
   1437         ASSERT_NOT_REACHED();
   1438 #endif
   1439 
   1440 #if !ENABLE(INTERPRETER)
   1441     UNUSED_PARAM(registerFile);
   1442     UNUSED_PARAM(callFrame);
   1443     return JSValue();
   1444 #else
   1445 
   1446     JSGlobalData* globalData = &callFrame->globalData();
   1447     JSValue exceptionValue;
   1448     HandlerInfo* handler = 0;
   1449 
   1450     CodeBlock* codeBlock = callFrame->codeBlock();
   1451     Instruction* vPC = codeBlock->instructions().begin();
   1452     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
   1453     unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck();
   1454     JSValue functionReturnValue;
   1455 
   1456 #define CHECK_FOR_EXCEPTION() \
   1457     do { \
   1458         if (UNLIKELY(globalData->exception != JSValue())) { \
   1459             exceptionValue = globalData->exception; \
   1460             goto vm_throw; \
   1461         } \
   1462     } while (0)
   1463 
   1464 #if ENABLE(OPCODE_STATS)
   1465     OpcodeStats::resetLastInstruction();
   1466 #endif
   1467 
   1468 #define CHECK_FOR_TIMEOUT() \
   1469     if (!--tickCount) { \
   1470         if (globalData->terminator.shouldTerminate() || globalData->timeoutChecker.didTimeOut(callFrame)) { \
   1471             exceptionValue = jsNull(); \
   1472             goto vm_throw; \
   1473         } \
   1474         tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); \
   1475     }
   1476 
   1477 #if ENABLE(OPCODE_SAMPLING)
   1478     #define SAMPLE(codeBlock, vPC) m_sampler->sample(codeBlock, vPC)
   1479 #else
   1480     #define SAMPLE(codeBlock, vPC)
   1481 #endif
   1482 
   1483 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
   1484     #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto *vPC->u.opcode
   1485 #if ENABLE(OPCODE_STATS)
   1486     #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
   1487 #else
   1488     #define DEFINE_OPCODE(opcode) opcode:
   1489 #endif
   1490     NEXT_INSTRUCTION();
   1491 #else
   1492     #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto interpreterLoopStart
   1493 #if ENABLE(OPCODE_STATS)
   1494     #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
   1495 #else
   1496     #define DEFINE_OPCODE(opcode) case opcode:
   1497 #endif
   1498     while (1) { // iterator loop begins
   1499     interpreterLoopStart:;
   1500     switch (vPC->u.opcode)
   1501 #endif
   1502     {
   1503     DEFINE_OPCODE(op_new_object) {
   1504         /* new_object dst(r)
   1505 
   1506            Constructs a new empty Object instance using the original
   1507            constructor, and puts the result in register dst.
   1508         */
   1509         int dst = vPC[1].u.operand;
   1510         callFrame->uncheckedR(dst) = JSValue(constructEmptyObject(callFrame));
   1511 
   1512         vPC += OPCODE_LENGTH(op_new_object);
   1513         NEXT_INSTRUCTION();
   1514     }
   1515     DEFINE_OPCODE(op_new_array) {
   1516         /* new_array dst(r) firstArg(r) argCount(n)
   1517 
   1518            Constructs a new Array instance using the original
   1519            constructor, and puts the result in register dst.
   1520            The array will contain argCount elements with values
   1521            taken from registers starting at register firstArg.
   1522         */
   1523         int dst = vPC[1].u.operand;
   1524         int firstArg = vPC[2].u.operand;
   1525         int argCount = vPC[3].u.operand;
   1526         ArgList args(callFrame->registers() + firstArg, argCount);
   1527         callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, args));
   1528 
   1529         vPC += OPCODE_LENGTH(op_new_array);
   1530         NEXT_INSTRUCTION();
   1531     }
   1532     DEFINE_OPCODE(op_new_regexp) {
   1533         /* new_regexp dst(r) regExp(re)
   1534 
   1535            Constructs a new RegExp instance using the original
   1536            constructor from regexp regExp, and puts the result in
   1537            register dst.
   1538         */
   1539         int dst = vPC[1].u.operand;
   1540         RegExp* regExp = codeBlock->regexp(vPC[2].u.operand);
   1541         if (!regExp->isValid()) {
   1542             exceptionValue = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor.");
   1543             goto vm_throw;
   1544         }
   1545         callFrame->uncheckedR(dst) = JSValue(new (globalData) RegExpObject(callFrame->lexicalGlobalObject(), callFrame->scopeChain()->globalObject->regExpStructure(), regExp));
   1546 
   1547         vPC += OPCODE_LENGTH(op_new_regexp);
   1548         NEXT_INSTRUCTION();
   1549     }
   1550     DEFINE_OPCODE(op_mov) {
   1551         /* mov dst(r) src(r)
   1552 
   1553            Copies register src to register dst.
   1554         */
   1555         int dst = vPC[1].u.operand;
   1556         int src = vPC[2].u.operand;
   1557 
   1558         callFrame->uncheckedR(dst) = callFrame->r(src);
   1559 
   1560         vPC += OPCODE_LENGTH(op_mov);
   1561         NEXT_INSTRUCTION();
   1562     }
   1563     DEFINE_OPCODE(op_eq) {
   1564         /* eq dst(r) src1(r) src2(r)
   1565 
   1566            Checks whether register src1 and register src2 are equal,
   1567            as with the ECMAScript '==' operator, and puts the result
   1568            as a boolean in register dst.
   1569         */
   1570         int dst = vPC[1].u.operand;
   1571         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1572         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1573         if (src1.isInt32() && src2.isInt32())
   1574             callFrame->uncheckedR(dst) = jsBoolean(src1.asInt32() == src2.asInt32());
   1575         else {
   1576             JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2));
   1577             CHECK_FOR_EXCEPTION();
   1578             callFrame->uncheckedR(dst) = result;
   1579         }
   1580 
   1581         vPC += OPCODE_LENGTH(op_eq);
   1582         NEXT_INSTRUCTION();
   1583     }
   1584     DEFINE_OPCODE(op_eq_null) {
   1585         /* eq_null dst(r) src(r)
   1586 
   1587            Checks whether register src is null, as with the ECMAScript '!='
   1588            operator, and puts the result as a boolean in register dst.
   1589         */
   1590         int dst = vPC[1].u.operand;
   1591         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
   1592 
   1593         if (src.isUndefinedOrNull()) {
   1594             callFrame->uncheckedR(dst) = jsBoolean(true);
   1595             vPC += OPCODE_LENGTH(op_eq_null);
   1596             NEXT_INSTRUCTION();
   1597         }
   1598 
   1599         callFrame->uncheckedR(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
   1600         vPC += OPCODE_LENGTH(op_eq_null);
   1601         NEXT_INSTRUCTION();
   1602     }
   1603     DEFINE_OPCODE(op_neq) {
   1604         /* neq dst(r) src1(r) src2(r)
   1605 
   1606            Checks whether register src1 and register src2 are not
   1607            equal, as with the ECMAScript '!=' operator, and puts the
   1608            result as a boolean in register dst.
   1609         */
   1610         int dst = vPC[1].u.operand;
   1611         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1612         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1613         if (src1.isInt32() && src2.isInt32())
   1614             callFrame->uncheckedR(dst) = jsBoolean(src1.asInt32() != src2.asInt32());
   1615         else {
   1616             JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2));
   1617             CHECK_FOR_EXCEPTION();
   1618             callFrame->uncheckedR(dst) = result;
   1619         }
   1620 
   1621         vPC += OPCODE_LENGTH(op_neq);
   1622         NEXT_INSTRUCTION();
   1623     }
   1624     DEFINE_OPCODE(op_neq_null) {
   1625         /* neq_null dst(r) src(r)
   1626 
   1627            Checks whether register src is not null, as with the ECMAScript '!='
   1628            operator, and puts the result as a boolean in register dst.
   1629         */
   1630         int dst = vPC[1].u.operand;
   1631         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
   1632 
   1633         if (src.isUndefinedOrNull()) {
   1634             callFrame->uncheckedR(dst) = jsBoolean(false);
   1635             vPC += OPCODE_LENGTH(op_neq_null);
   1636             NEXT_INSTRUCTION();
   1637         }
   1638 
   1639         callFrame->uncheckedR(dst) = jsBoolean(!src.isCell() || !src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
   1640         vPC += OPCODE_LENGTH(op_neq_null);
   1641         NEXT_INSTRUCTION();
   1642     }
   1643     DEFINE_OPCODE(op_stricteq) {
   1644         /* stricteq dst(r) src1(r) src2(r)
   1645 
   1646            Checks whether register src1 and register src2 are strictly
   1647            equal, as with the ECMAScript '===' operator, and puts the
   1648            result as a boolean in register dst.
   1649         */
   1650         int dst = vPC[1].u.operand;
   1651         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1652         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1653         bool result = JSValue::strictEqual(callFrame, src1, src2);
   1654         CHECK_FOR_EXCEPTION();
   1655         callFrame->uncheckedR(dst) = jsBoolean(result);
   1656 
   1657         vPC += OPCODE_LENGTH(op_stricteq);
   1658         NEXT_INSTRUCTION();
   1659     }
   1660     DEFINE_OPCODE(op_nstricteq) {
   1661         /* nstricteq dst(r) src1(r) src2(r)
   1662 
   1663            Checks whether register src1 and register src2 are not
   1664            strictly equal, as with the ECMAScript '!==' operator, and
   1665            puts the result as a boolean in register dst.
   1666         */
   1667         int dst = vPC[1].u.operand;
   1668         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1669         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1670         bool result = !JSValue::strictEqual(callFrame, src1, src2);
   1671         CHECK_FOR_EXCEPTION();
   1672         callFrame->uncheckedR(dst) = jsBoolean(result);
   1673 
   1674         vPC += OPCODE_LENGTH(op_nstricteq);
   1675         NEXT_INSTRUCTION();
   1676     }
   1677     DEFINE_OPCODE(op_less) {
   1678         /* less dst(r) src1(r) src2(r)
   1679 
   1680            Checks whether register src1 is less than register src2, as
   1681            with the ECMAScript '<' operator, and puts the result as
   1682            a boolean in register dst.
   1683         */
   1684         int dst = vPC[1].u.operand;
   1685         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1686         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1687         JSValue result = jsBoolean(jsLess(callFrame, src1, src2));
   1688         CHECK_FOR_EXCEPTION();
   1689         callFrame->uncheckedR(dst) = result;
   1690 
   1691         vPC += OPCODE_LENGTH(op_less);
   1692         NEXT_INSTRUCTION();
   1693     }
   1694     DEFINE_OPCODE(op_lesseq) {
   1695         /* lesseq dst(r) src1(r) src2(r)
   1696 
   1697            Checks whether register src1 is less than or equal to
   1698            register src2, as with the ECMAScript '<=' operator, and
   1699            puts the result as a boolean in register dst.
   1700         */
   1701         int dst = vPC[1].u.operand;
   1702         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1703         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1704         JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2));
   1705         CHECK_FOR_EXCEPTION();
   1706         callFrame->uncheckedR(dst) = result;
   1707 
   1708         vPC += OPCODE_LENGTH(op_lesseq);
   1709         NEXT_INSTRUCTION();
   1710     }
   1711     DEFINE_OPCODE(op_pre_inc) {
   1712         /* pre_inc srcDst(r)
   1713 
   1714            Converts register srcDst to number, adds one, and puts the result
   1715            back in register srcDst.
   1716         */
   1717         int srcDst = vPC[1].u.operand;
   1718         JSValue v = callFrame->r(srcDst).jsValue();
   1719         if (v.isInt32() && v.asInt32() < INT_MAX)
   1720             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1);
   1721         else {
   1722             JSValue result = jsNumber(v.toNumber(callFrame) + 1);
   1723             CHECK_FOR_EXCEPTION();
   1724             callFrame->uncheckedR(srcDst) = result;
   1725         }
   1726 
   1727         vPC += OPCODE_LENGTH(op_pre_inc);
   1728         NEXT_INSTRUCTION();
   1729     }
   1730     DEFINE_OPCODE(op_pre_dec) {
   1731         /* pre_dec srcDst(r)
   1732 
   1733            Converts register srcDst to number, subtracts one, and puts the result
   1734            back in register srcDst.
   1735         */
   1736         int srcDst = vPC[1].u.operand;
   1737         JSValue v = callFrame->r(srcDst).jsValue();
   1738         if (v.isInt32() && v.asInt32() > INT_MIN)
   1739             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1);
   1740         else {
   1741             JSValue result = jsNumber(v.toNumber(callFrame) - 1);
   1742             CHECK_FOR_EXCEPTION();
   1743             callFrame->uncheckedR(srcDst) = result;
   1744         }
   1745 
   1746         vPC += OPCODE_LENGTH(op_pre_dec);
   1747         NEXT_INSTRUCTION();
   1748     }
   1749     DEFINE_OPCODE(op_post_inc) {
   1750         /* post_inc dst(r) srcDst(r)
   1751 
   1752            Converts register srcDst to number. The number itself is
   1753            written to register dst, and the number plus one is written
   1754            back to register srcDst.
   1755         */
   1756         int dst = vPC[1].u.operand;
   1757         int srcDst = vPC[2].u.operand;
   1758         JSValue v = callFrame->r(srcDst).jsValue();
   1759         if (v.isInt32() && v.asInt32() < INT_MAX) {
   1760             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1);
   1761             callFrame->uncheckedR(dst) = v;
   1762         } else {
   1763             JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
   1764             CHECK_FOR_EXCEPTION();
   1765             callFrame->uncheckedR(srcDst) = jsNumber(number.uncheckedGetNumber() + 1);
   1766             callFrame->uncheckedR(dst) = number;
   1767         }
   1768 
   1769         vPC += OPCODE_LENGTH(op_post_inc);
   1770         NEXT_INSTRUCTION();
   1771     }
   1772     DEFINE_OPCODE(op_post_dec) {
   1773         /* post_dec dst(r) srcDst(r)
   1774 
   1775            Converts register srcDst to number. The number itself is
   1776            written to register dst, and the number minus one is written
   1777            back to register srcDst.
   1778         */
   1779         int dst = vPC[1].u.operand;
   1780         int srcDst = vPC[2].u.operand;
   1781         JSValue v = callFrame->r(srcDst).jsValue();
   1782         if (v.isInt32() && v.asInt32() > INT_MIN) {
   1783             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1);
   1784             callFrame->uncheckedR(dst) = v;
   1785         } else {
   1786             JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
   1787             CHECK_FOR_EXCEPTION();
   1788             callFrame->uncheckedR(srcDst) = jsNumber(number.uncheckedGetNumber() - 1);
   1789             callFrame->uncheckedR(dst) = number;
   1790         }
   1791 
   1792         vPC += OPCODE_LENGTH(op_post_dec);
   1793         NEXT_INSTRUCTION();
   1794     }
   1795     DEFINE_OPCODE(op_to_jsnumber) {
   1796         /* to_jsnumber dst(r) src(r)
   1797 
   1798            Converts register src to number, and puts the result
   1799            in register dst.
   1800         */
   1801         int dst = vPC[1].u.operand;
   1802         int src = vPC[2].u.operand;
   1803 
   1804         JSValue srcVal = callFrame->r(src).jsValue();
   1805 
   1806         if (LIKELY(srcVal.isNumber()))
   1807             callFrame->uncheckedR(dst) = callFrame->r(src);
   1808         else {
   1809             JSValue result = srcVal.toJSNumber(callFrame);
   1810             CHECK_FOR_EXCEPTION();
   1811             callFrame->uncheckedR(dst) = result;
   1812         }
   1813 
   1814         vPC += OPCODE_LENGTH(op_to_jsnumber);
   1815         NEXT_INSTRUCTION();
   1816     }
   1817     DEFINE_OPCODE(op_negate) {
   1818         /* negate dst(r) src(r)
   1819 
   1820            Converts register src to number, negates it, and puts the
   1821            result in register dst.
   1822         */
   1823         int dst = vPC[1].u.operand;
   1824         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
   1825         if (src.isInt32() && (src.asInt32() & 0x7fffffff)) // non-zero and no overflow
   1826             callFrame->uncheckedR(dst) = jsNumber(-src.asInt32());
   1827         else {
   1828             JSValue result = jsNumber(-src.toNumber(callFrame));
   1829             CHECK_FOR_EXCEPTION();
   1830             callFrame->uncheckedR(dst) = result;
   1831         }
   1832 
   1833         vPC += OPCODE_LENGTH(op_negate);
   1834         NEXT_INSTRUCTION();
   1835     }
   1836     DEFINE_OPCODE(op_add) {
   1837         /* add dst(r) src1(r) src2(r)
   1838 
   1839            Adds register src1 and register src2, and puts the result
   1840            in register dst. (JS add may be string concatenation or
   1841            numeric add, depending on the types of the operands.)
   1842         */
   1843         int dst = vPC[1].u.operand;
   1844         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1845         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1846         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
   1847             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() + src2.asInt32());
   1848         else {
   1849             JSValue result = jsAdd(callFrame, src1, src2);
   1850             CHECK_FOR_EXCEPTION();
   1851             callFrame->uncheckedR(dst) = result;
   1852         }
   1853         vPC += OPCODE_LENGTH(op_add);
   1854         NEXT_INSTRUCTION();
   1855     }
   1856     DEFINE_OPCODE(op_mul) {
   1857         /* mul dst(r) src1(r) src2(r)
   1858 
   1859            Multiplies register src1 and register src2 (converted to
   1860            numbers), and puts the product in register dst.
   1861         */
   1862         int dst = vPC[1].u.operand;
   1863         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1864         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1865         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow
   1866                 callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() * src2.asInt32());
   1867         else {
   1868             JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
   1869             CHECK_FOR_EXCEPTION();
   1870             callFrame->uncheckedR(dst) = result;
   1871         }
   1872 
   1873         vPC += OPCODE_LENGTH(op_mul);
   1874         NEXT_INSTRUCTION();
   1875     }
   1876     DEFINE_OPCODE(op_div) {
   1877         /* div dst(r) dividend(r) divisor(r)
   1878 
   1879            Divides register dividend (converted to number) by the
   1880            register divisor (converted to number), and puts the
   1881            quotient in register dst.
   1882         */
   1883         int dst = vPC[1].u.operand;
   1884         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
   1885         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
   1886 
   1887         JSValue result = jsNumber(dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
   1888         CHECK_FOR_EXCEPTION();
   1889         callFrame->uncheckedR(dst) = result;
   1890 
   1891         vPC += OPCODE_LENGTH(op_div);
   1892         NEXT_INSTRUCTION();
   1893     }
   1894     DEFINE_OPCODE(op_mod) {
   1895         /* mod dst(r) dividend(r) divisor(r)
   1896 
   1897            Divides register dividend (converted to number) by
   1898            register divisor (converted to number), and puts the
   1899            remainder in register dst.
   1900         */
   1901         int dst = vPC[1].u.operand;
   1902         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
   1903         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
   1904 
   1905         if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) {
   1906             JSValue result = jsNumber(dividend.asInt32() % divisor.asInt32());
   1907             ASSERT(result);
   1908             callFrame->uncheckedR(dst) = result;
   1909             vPC += OPCODE_LENGTH(op_mod);
   1910             NEXT_INSTRUCTION();
   1911         }
   1912 
   1913         // Conversion to double must happen outside the call to fmod since the
   1914         // order of argument evaluation is not guaranteed.
   1915         double d1 = dividend.toNumber(callFrame);
   1916         double d2 = divisor.toNumber(callFrame);
   1917         JSValue result = jsNumber(fmod(d1, d2));
   1918         CHECK_FOR_EXCEPTION();
   1919         callFrame->uncheckedR(dst) = result;
   1920         vPC += OPCODE_LENGTH(op_mod);
   1921         NEXT_INSTRUCTION();
   1922     }
   1923     DEFINE_OPCODE(op_sub) {
   1924         /* sub dst(r) src1(r) src2(r)
   1925 
   1926            Subtracts register src2 (converted to number) from register
   1927            src1 (converted to number), and puts the difference in
   1928            register dst.
   1929         */
   1930         int dst = vPC[1].u.operand;
   1931         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   1932         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   1933         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
   1934             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() - src2.asInt32());
   1935         else {
   1936             JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
   1937             CHECK_FOR_EXCEPTION();
   1938             callFrame->uncheckedR(dst) = result;
   1939         }
   1940         vPC += OPCODE_LENGTH(op_sub);
   1941         NEXT_INSTRUCTION();
   1942     }
   1943     DEFINE_OPCODE(op_lshift) {
   1944         /* lshift dst(r) val(r) shift(r)
   1945 
   1946            Performs left shift of register val (converted to int32) by
   1947            register shift (converted to uint32), and puts the result
   1948            in register dst.
   1949         */
   1950         int dst = vPC[1].u.operand;
   1951         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
   1952         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
   1953 
   1954         if (val.isInt32() && shift.isInt32())
   1955             callFrame->uncheckedR(dst) = jsNumber(val.asInt32() << (shift.asInt32() & 0x1f));
   1956         else {
   1957             JSValue result = jsNumber((val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
   1958             CHECK_FOR_EXCEPTION();
   1959             callFrame->uncheckedR(dst) = result;
   1960         }
   1961 
   1962         vPC += OPCODE_LENGTH(op_lshift);
   1963         NEXT_INSTRUCTION();
   1964     }
   1965     DEFINE_OPCODE(op_rshift) {
   1966         /* rshift dst(r) val(r) shift(r)
   1967 
   1968            Performs arithmetic right shift of register val (converted
   1969            to int32) by register shift (converted to
   1970            uint32), and puts the result in register dst.
   1971         */
   1972         int dst = vPC[1].u.operand;
   1973         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
   1974         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
   1975 
   1976         if (val.isInt32() && shift.isInt32())
   1977             callFrame->uncheckedR(dst) = jsNumber(val.asInt32() >> (shift.asInt32() & 0x1f));
   1978         else {
   1979             JSValue result = jsNumber((val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
   1980             CHECK_FOR_EXCEPTION();
   1981             callFrame->uncheckedR(dst) = result;
   1982         }
   1983 
   1984         vPC += OPCODE_LENGTH(op_rshift);
   1985         NEXT_INSTRUCTION();
   1986     }
   1987     DEFINE_OPCODE(op_urshift) {
   1988         /* rshift dst(r) val(r) shift(r)
   1989 
   1990            Performs logical right shift of register val (converted
   1991            to uint32) by register shift (converted to
   1992            uint32), and puts the result in register dst.
   1993         */
   1994         int dst = vPC[1].u.operand;
   1995         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
   1996         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
   1997         if (val.isUInt32() && shift.isInt32())
   1998             callFrame->uncheckedR(dst) = jsNumber(val.asInt32() >> (shift.asInt32() & 0x1f));
   1999         else {
   2000             JSValue result = jsNumber((val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
   2001             CHECK_FOR_EXCEPTION();
   2002             callFrame->uncheckedR(dst) = result;
   2003         }
   2004 
   2005         vPC += OPCODE_LENGTH(op_urshift);
   2006         NEXT_INSTRUCTION();
   2007     }
   2008     DEFINE_OPCODE(op_bitand) {
   2009         /* bitand dst(r) src1(r) src2(r)
   2010 
   2011            Computes bitwise AND of register src1 (converted to int32)
   2012            and register src2 (converted to int32), and puts the result
   2013            in register dst.
   2014         */
   2015         int dst = vPC[1].u.operand;
   2016         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   2017         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   2018         if (src1.isInt32() && src2.isInt32())
   2019             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() & src2.asInt32());
   2020         else {
   2021             JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame));
   2022             CHECK_FOR_EXCEPTION();
   2023             callFrame->uncheckedR(dst) = result;
   2024         }
   2025 
   2026         vPC += OPCODE_LENGTH(op_bitand);
   2027         NEXT_INSTRUCTION();
   2028     }
   2029     DEFINE_OPCODE(op_bitxor) {
   2030         /* bitxor dst(r) src1(r) src2(r)
   2031 
   2032            Computes bitwise XOR of register src1 (converted to int32)
   2033            and register src2 (converted to int32), and puts the result
   2034            in register dst.
   2035         */
   2036         int dst = vPC[1].u.operand;
   2037         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   2038         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   2039         if (src1.isInt32() && src2.isInt32())
   2040             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() ^ src2.asInt32());
   2041         else {
   2042             JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
   2043             CHECK_FOR_EXCEPTION();
   2044             callFrame->uncheckedR(dst) = result;
   2045         }
   2046 
   2047         vPC += OPCODE_LENGTH(op_bitxor);
   2048         NEXT_INSTRUCTION();
   2049     }
   2050     DEFINE_OPCODE(op_bitor) {
   2051         /* bitor dst(r) src1(r) src2(r)
   2052 
   2053            Computes bitwise OR of register src1 (converted to int32)
   2054            and register src2 (converted to int32), and puts the
   2055            result in register dst.
   2056         */
   2057         int dst = vPC[1].u.operand;
   2058         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
   2059         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
   2060         if (src1.isInt32() && src2.isInt32())
   2061             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() | src2.asInt32());
   2062         else {
   2063             JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame));
   2064             CHECK_FOR_EXCEPTION();
   2065             callFrame->uncheckedR(dst) = result;
   2066         }
   2067 
   2068         vPC += OPCODE_LENGTH(op_bitor);
   2069         NEXT_INSTRUCTION();
   2070     }
   2071     DEFINE_OPCODE(op_bitnot) {
   2072         /* bitnot dst(r) src(r)
   2073 
   2074            Computes bitwise NOT of register src1 (converted to int32),
   2075            and puts the result in register dst.
   2076         */
   2077         int dst = vPC[1].u.operand;
   2078         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
   2079         if (src.isInt32())
   2080             callFrame->uncheckedR(dst) = jsNumber(~src.asInt32());
   2081         else {
   2082             JSValue result = jsNumber(~src.toInt32(callFrame));
   2083             CHECK_FOR_EXCEPTION();
   2084             callFrame->uncheckedR(dst) = result;
   2085         }
   2086         vPC += OPCODE_LENGTH(op_bitnot);
   2087         NEXT_INSTRUCTION();
   2088     }
   2089     DEFINE_OPCODE(op_not) {
   2090         /* not dst(r) src(r)
   2091 
   2092            Computes logical NOT of register src (converted to
   2093            boolean), and puts the result in register dst.
   2094         */
   2095         int dst = vPC[1].u.operand;
   2096         int src = vPC[2].u.operand;
   2097         JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame));
   2098         CHECK_FOR_EXCEPTION();
   2099         callFrame->uncheckedR(dst) = result;
   2100 
   2101         vPC += OPCODE_LENGTH(op_not);
   2102         NEXT_INSTRUCTION();
   2103     }
   2104     DEFINE_OPCODE(op_check_has_instance) {
   2105         /* check_has_instance constructor(r)
   2106 
   2107            Check 'constructor' is an object with the internal property
   2108            [HasInstance] (i.e. is a function ... *shakes head sadly at
   2109            JSC API*). Raises an exception if register constructor is not
   2110            an valid parameter for instanceof.
   2111         */
   2112         int base = vPC[1].u.operand;
   2113         JSValue baseVal = callFrame->r(base).jsValue();
   2114 
   2115         if (isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue))
   2116             goto vm_throw;
   2117 
   2118         vPC += OPCODE_LENGTH(op_check_has_instance);
   2119         NEXT_INSTRUCTION();
   2120     }
   2121     DEFINE_OPCODE(op_instanceof) {
   2122         /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
   2123 
   2124            Tests whether register value is an instance of register
   2125            constructor, and puts the boolean result in register
   2126            dst. Register constructorProto must contain the "prototype"
   2127            property (not the actual prototype) of the object in
   2128            register constructor. This lookup is separated so that
   2129            polymorphic inline caching can apply.
   2130 
   2131            Raises an exception if register constructor is not an
   2132            object.
   2133         */
   2134         int dst = vPC[1].u.operand;
   2135         int value = vPC[2].u.operand;
   2136         int base = vPC[3].u.operand;
   2137         int baseProto = vPC[4].u.operand;
   2138 
   2139         JSValue baseVal = callFrame->r(base).jsValue();
   2140 
   2141         ASSERT(!isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue));
   2142 
   2143         bool result = asObject(baseVal)->hasInstance(callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
   2144         CHECK_FOR_EXCEPTION();
   2145         callFrame->uncheckedR(dst) = jsBoolean(result);
   2146 
   2147         vPC += OPCODE_LENGTH(op_instanceof);
   2148         NEXT_INSTRUCTION();
   2149     }
   2150     DEFINE_OPCODE(op_typeof) {
   2151         /* typeof dst(r) src(r)
   2152 
   2153            Determines the type string for src according to ECMAScript
   2154            rules, and puts the result in register dst.
   2155         */
   2156         int dst = vPC[1].u.operand;
   2157         int src = vPC[2].u.operand;
   2158         callFrame->uncheckedR(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue()));
   2159 
   2160         vPC += OPCODE_LENGTH(op_typeof);
   2161         NEXT_INSTRUCTION();
   2162     }
   2163     DEFINE_OPCODE(op_is_undefined) {
   2164         /* is_undefined dst(r) src(r)
   2165 
   2166            Determines whether the type string for src according to
   2167            the ECMAScript rules is "undefined", and puts the result
   2168            in register dst.
   2169         */
   2170         int dst = vPC[1].u.operand;
   2171         int src = vPC[2].u.operand;
   2172         JSValue v = callFrame->r(src).jsValue();
   2173         callFrame->uncheckedR(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
   2174 
   2175         vPC += OPCODE_LENGTH(op_is_undefined);
   2176         NEXT_INSTRUCTION();
   2177     }
   2178     DEFINE_OPCODE(op_is_boolean) {
   2179         /* is_boolean dst(r) src(r)
   2180 
   2181            Determines whether the type string for src according to
   2182            the ECMAScript rules is "boolean", and puts the result
   2183            in register dst.
   2184         */
   2185         int dst = vPC[1].u.operand;
   2186         int src = vPC[2].u.operand;
   2187         callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean());
   2188 
   2189         vPC += OPCODE_LENGTH(op_is_boolean);
   2190         NEXT_INSTRUCTION();
   2191     }
   2192     DEFINE_OPCODE(op_is_number) {
   2193         /* is_number dst(r) src(r)
   2194 
   2195            Determines whether the type string for src according to
   2196            the ECMAScript rules is "number", and puts the result
   2197            in register dst.
   2198         */
   2199         int dst = vPC[1].u.operand;
   2200         int src = vPC[2].u.operand;
   2201         callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber());
   2202 
   2203         vPC += OPCODE_LENGTH(op_is_number);
   2204         NEXT_INSTRUCTION();
   2205     }
   2206     DEFINE_OPCODE(op_is_string) {
   2207         /* is_string dst(r) src(r)
   2208 
   2209            Determines whether the type string for src according to
   2210            the ECMAScript rules is "string", and puts the result
   2211            in register dst.
   2212         */
   2213         int dst = vPC[1].u.operand;
   2214         int src = vPC[2].u.operand;
   2215         callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isString());
   2216 
   2217         vPC += OPCODE_LENGTH(op_is_string);
   2218         NEXT_INSTRUCTION();
   2219     }
   2220     DEFINE_OPCODE(op_is_object) {
   2221         /* is_object dst(r) src(r)
   2222 
   2223            Determines whether the type string for src according to
   2224            the ECMAScript rules is "object", and puts the result
   2225            in register dst.
   2226         */
   2227         int dst = vPC[1].u.operand;
   2228         int src = vPC[2].u.operand;
   2229         callFrame->uncheckedR(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue()));
   2230 
   2231         vPC += OPCODE_LENGTH(op_is_object);
   2232         NEXT_INSTRUCTION();
   2233     }
   2234     DEFINE_OPCODE(op_is_function) {
   2235         /* is_function dst(r) src(r)
   2236 
   2237            Determines whether the type string for src according to
   2238            the ECMAScript rules is "function", and puts the result
   2239            in register dst.
   2240         */
   2241         int dst = vPC[1].u.operand;
   2242         int src = vPC[2].u.operand;
   2243         callFrame->uncheckedR(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue()));
   2244 
   2245         vPC += OPCODE_LENGTH(op_is_function);
   2246         NEXT_INSTRUCTION();
   2247     }
   2248     DEFINE_OPCODE(op_in) {
   2249         /* in dst(r) property(r) base(r)
   2250 
   2251            Tests whether register base has a property named register
   2252            property, and puts the boolean result in register dst.
   2253 
   2254            Raises an exception if register constructor is not an
   2255            object.
   2256         */
   2257         int dst = vPC[1].u.operand;
   2258         int property = vPC[2].u.operand;
   2259         int base = vPC[3].u.operand;
   2260 
   2261         JSValue baseVal = callFrame->r(base).jsValue();
   2262         if (isInvalidParamForIn(callFrame, baseVal, exceptionValue))
   2263             goto vm_throw;
   2264 
   2265         JSObject* baseObj = asObject(baseVal);
   2266 
   2267         JSValue propName = callFrame->r(property).jsValue();
   2268 
   2269         uint32_t i;
   2270         if (propName.getUInt32(i))
   2271             callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
   2272         else {
   2273             Identifier property(callFrame, propName.toString(callFrame));
   2274             CHECK_FOR_EXCEPTION();
   2275             callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
   2276         }
   2277 
   2278         vPC += OPCODE_LENGTH(op_in);
   2279         NEXT_INSTRUCTION();
   2280     }
   2281     DEFINE_OPCODE(op_resolve) {
   2282         /* resolve dst(r) property(id)
   2283 
   2284            Looks up the property named by identifier property in the
   2285            scope chain, and writes the resulting value to register
   2286            dst. If the property is not found, raises an exception.
   2287         */
   2288         if (UNLIKELY(!resolve(callFrame, vPC, exceptionValue)))
   2289             goto vm_throw;
   2290 
   2291         vPC += OPCODE_LENGTH(op_resolve);
   2292         NEXT_INSTRUCTION();
   2293     }
   2294     DEFINE_OPCODE(op_resolve_skip) {
   2295         /* resolve_skip dst(r) property(id) skip(n)
   2296 
   2297          Looks up the property named by identifier property in the
   2298          scope chain skipping the top 'skip' levels, and writes the resulting
   2299          value to register dst. If the property is not found, raises an exception.
   2300          */
   2301         if (UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue)))
   2302             goto vm_throw;
   2303 
   2304         vPC += OPCODE_LENGTH(op_resolve_skip);
   2305 
   2306         NEXT_INSTRUCTION();
   2307     }
   2308     DEFINE_OPCODE(op_resolve_global) {
   2309         /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n)
   2310 
   2311            Performs a dynamic property lookup for the given property, on the provided
   2312            global object.  If structure matches the Structure of the global then perform
   2313            a fast lookup using the case offset, otherwise fall back to a full resolve and
   2314            cache the new structure and offset
   2315          */
   2316         if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue)))
   2317             goto vm_throw;
   2318 
   2319         vPC += OPCODE_LENGTH(op_resolve_global);
   2320 
   2321         NEXT_INSTRUCTION();
   2322     }
   2323     DEFINE_OPCODE(op_resolve_global_dynamic) {
   2324         /* resolve_skip dst(r) globalObject(c) property(id) structure(sID) offset(n), depth(n)
   2325 
   2326          Performs a dynamic property lookup for the given property, on the provided
   2327          global object.  If structure matches the Structure of the global then perform
   2328          a fast lookup using the case offset, otherwise fall back to a full resolve and
   2329          cache the new structure and offset.
   2330 
   2331          This walks through n levels of the scope chain to verify that none of those levels
   2332          in the scope chain include dynamically added properties.
   2333          */
   2334         if (UNLIKELY(!resolveGlobalDynamic(callFrame, vPC, exceptionValue)))
   2335             goto vm_throw;
   2336 
   2337         vPC += OPCODE_LENGTH(op_resolve_global_dynamic);
   2338 
   2339         NEXT_INSTRUCTION();
   2340     }
   2341     DEFINE_OPCODE(op_get_global_var) {
   2342         /* get_global_var dst(r) globalObject(c) index(n)
   2343 
   2344            Gets the global var at global slot index and places it in register dst.
   2345          */
   2346         int dst = vPC[1].u.operand;
   2347         JSGlobalObject* scope = codeBlock->globalObject();
   2348         ASSERT(scope->isGlobalObject());
   2349         int index = vPC[2].u.operand;
   2350 
   2351         callFrame->uncheckedR(dst) = scope->registerAt(index).get();
   2352         vPC += OPCODE_LENGTH(op_get_global_var);
   2353         NEXT_INSTRUCTION();
   2354     }
   2355     DEFINE_OPCODE(op_put_global_var) {
   2356         /* put_global_var globalObject(c) index(n) value(r)
   2357 
   2358            Puts value into global slot index.
   2359          */
   2360         JSGlobalObject* scope = codeBlock->globalObject();
   2361         ASSERT(scope->isGlobalObject());
   2362         int index = vPC[1].u.operand;
   2363         int value = vPC[2].u.operand;
   2364 
   2365         scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
   2366         vPC += OPCODE_LENGTH(op_put_global_var);
   2367         NEXT_INSTRUCTION();
   2368     }
   2369     DEFINE_OPCODE(op_get_scoped_var) {
   2370         /* get_scoped_var dst(r) index(n) skip(n)
   2371 
   2372          Loads the contents of the index-th local from the scope skip nodes from
   2373          the top of the scope chain, and places it in register dst.
   2374          */
   2375         int dst = vPC[1].u.operand;
   2376         int index = vPC[2].u.operand;
   2377         int skip = vPC[3].u.operand;
   2378 
   2379         ScopeChainNode* scopeChain = callFrame->scopeChain();
   2380         ScopeChainIterator iter = scopeChain->begin();
   2381         ScopeChainIterator end = scopeChain->end();
   2382         ASSERT(iter != end);
   2383         ASSERT(codeBlock == callFrame->codeBlock());
   2384         bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
   2385         ASSERT(skip || !checkTopLevel);
   2386     if (checkTopLevel && skip--) {
   2387             if (callFrame->r(codeBlock->activationRegister()).jsValue())
   2388                 ++iter;
   2389         }
   2390         while (skip--) {
   2391             ++iter;
   2392             ASSERT(iter != end);
   2393         }
   2394         ASSERT((*iter)->isVariableObject());
   2395         JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get());
   2396         callFrame->uncheckedR(dst) = scope->registerAt(index).get();
   2397         ASSERT(callFrame->r(dst).jsValue());
   2398         vPC += OPCODE_LENGTH(op_get_scoped_var);
   2399         NEXT_INSTRUCTION();
   2400     }
   2401     DEFINE_OPCODE(op_put_scoped_var) {
   2402         /* put_scoped_var index(n) skip(n) value(r)
   2403 
   2404          */
   2405         int index = vPC[1].u.operand;
   2406         int skip = vPC[2].u.operand;
   2407         int value = vPC[3].u.operand;
   2408 
   2409         ScopeChainNode* scopeChain = callFrame->scopeChain();
   2410         ScopeChainIterator iter = scopeChain->begin();
   2411         ScopeChainIterator end = scopeChain->end();
   2412         ASSERT(codeBlock == callFrame->codeBlock());
   2413         ASSERT(iter != end);
   2414         bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
   2415         ASSERT(skip || !checkTopLevel);
   2416     if (checkTopLevel && skip--) {
   2417             if (callFrame->r(codeBlock->activationRegister()).jsValue())
   2418                 ++iter;
   2419         }
   2420         while (skip--) {
   2421             ++iter;
   2422             ASSERT(iter != end);
   2423         }
   2424 
   2425         ASSERT((*iter)->isVariableObject());
   2426         JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get());
   2427         ASSERT(callFrame->r(value).jsValue());
   2428         scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
   2429         vPC += OPCODE_LENGTH(op_put_scoped_var);
   2430         NEXT_INSTRUCTION();
   2431     }
   2432     DEFINE_OPCODE(op_resolve_base) {
   2433         /* resolve_base dst(r) property(id) isStrict(bool)
   2434 
   2435            Searches the scope chain for an object containing
   2436            identifier property, and if one is found, writes it to
   2437            register dst. If none is found and isStrict is false, the
   2438            outermost scope (which will be the global object) is
   2439            stored in register dst.
   2440         */
   2441         resolveBase(callFrame, vPC);
   2442         CHECK_FOR_EXCEPTION();
   2443 
   2444         vPC += OPCODE_LENGTH(op_resolve_base);
   2445         NEXT_INSTRUCTION();
   2446     }
   2447     DEFINE_OPCODE(op_ensure_property_exists) {
   2448         /* ensure_property_exists base(r) property(id)
   2449 
   2450            Throws an exception if property does not exist on base
   2451          */
   2452         int base = vPC[1].u.operand;
   2453         int property = vPC[2].u.operand;
   2454         Identifier& ident = codeBlock->identifier(property);
   2455 
   2456         JSValue baseVal = callFrame->r(base).jsValue();
   2457         JSObject* baseObject = asObject(baseVal);
   2458         PropertySlot slot(baseVal);
   2459         if (!baseObject->getPropertySlot(callFrame, ident, slot)) {
   2460             exceptionValue = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring());
   2461             goto vm_throw;
   2462         }
   2463 
   2464         vPC += OPCODE_LENGTH(op_ensure_property_exists);
   2465         NEXT_INSTRUCTION();
   2466     }
   2467     DEFINE_OPCODE(op_resolve_with_base) {
   2468         /* resolve_with_base baseDst(r) propDst(r) property(id)
   2469 
   2470            Searches the scope chain for an object containing
   2471            identifier property, and if one is found, writes it to
   2472            register srcDst, and the retrieved property value to register
   2473            propDst. If the property is not found, raises an exception.
   2474 
   2475            This is more efficient than doing resolve_base followed by
   2476            resolve, or resolve_base followed by get_by_id, as it
   2477            avoids duplicate hash lookups.
   2478         */
   2479         if (UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue)))
   2480             goto vm_throw;
   2481 
   2482         vPC += OPCODE_LENGTH(op_resolve_with_base);
   2483         NEXT_INSTRUCTION();
   2484     }
   2485     DEFINE_OPCODE(op_get_by_id) {
   2486         /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n)
   2487 
   2488            Generic property access: Gets the property named by identifier
   2489            property from the value base, and puts the result in register dst.
   2490         */
   2491         int dst = vPC[1].u.operand;
   2492         int base = vPC[2].u.operand;
   2493         int property = vPC[3].u.operand;
   2494 
   2495         Identifier& ident = codeBlock->identifier(property);
   2496         JSValue baseValue = callFrame->r(base).jsValue();
   2497         PropertySlot slot(baseValue);
   2498         JSValue result = baseValue.get(callFrame, ident, slot);
   2499         CHECK_FOR_EXCEPTION();
   2500 
   2501         tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
   2502 
   2503         callFrame->uncheckedR(dst) = result;
   2504         vPC += OPCODE_LENGTH(op_get_by_id);
   2505         NEXT_INSTRUCTION();
   2506     }
   2507     DEFINE_OPCODE(op_get_by_id_self) {
   2508         /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
   2509 
   2510            Cached property access: Attempts to get a cached property from the
   2511            value base. If the cache misses, op_get_by_id_self reverts to
   2512            op_get_by_id.
   2513         */
   2514         int base = vPC[2].u.operand;
   2515         JSValue baseValue = callFrame->r(base).jsValue();
   2516 
   2517         if (LIKELY(baseValue.isCell())) {
   2518             JSCell* baseCell = baseValue.asCell();
   2519             Structure* structure = vPC[4].u.structure.get();
   2520 
   2521             if (LIKELY(baseCell->structure() == structure)) {
   2522                 ASSERT(baseCell->isObject());
   2523                 JSObject* baseObject = asObject(baseCell);
   2524                 int dst = vPC[1].u.operand;
   2525                 int offset = vPC[5].u.operand;
   2526 
   2527                 ASSERT(baseObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
   2528                 callFrame->uncheckedR(dst) = JSValue(baseObject->getDirectOffset(offset));
   2529 
   2530                 vPC += OPCODE_LENGTH(op_get_by_id_self);
   2531                 NEXT_INSTRUCTION();
   2532             }
   2533         }
   2534 
   2535         uncacheGetByID(codeBlock, vPC);
   2536         NEXT_INSTRUCTION();
   2537     }
   2538     DEFINE_OPCODE(op_get_by_id_proto) {
   2539         /* op_get_by_id_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
   2540 
   2541            Cached property access: Attempts to get a cached property from the
   2542            value base's prototype. If the cache misses, op_get_by_id_proto
   2543            reverts to op_get_by_id.
   2544         */
   2545         int base = vPC[2].u.operand;
   2546         JSValue baseValue = callFrame->r(base).jsValue();
   2547 
   2548         if (LIKELY(baseValue.isCell())) {
   2549             JSCell* baseCell = baseValue.asCell();
   2550             Structure* structure = vPC[4].u.structure.get();
   2551 
   2552             if (LIKELY(baseCell->structure() == structure)) {
   2553                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
   2554                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
   2555                 Structure* prototypeStructure = vPC[5].u.structure.get();
   2556 
   2557                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
   2558                     int dst = vPC[1].u.operand;
   2559                     int offset = vPC[6].u.operand;
   2560 
   2561                     ASSERT(protoObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
   2562                     ASSERT(baseValue.get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
   2563                     callFrame->uncheckedR(dst) = JSValue(protoObject->getDirectOffset(offset));
   2564 
   2565                     vPC += OPCODE_LENGTH(op_get_by_id_proto);
   2566                     NEXT_INSTRUCTION();
   2567                 }
   2568             }
   2569         }
   2570 
   2571         uncacheGetByID(codeBlock, vPC);
   2572         NEXT_INSTRUCTION();
   2573     }
   2574 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2575     goto *(&&skip_id_getter_proto);
   2576 #endif
   2577     DEFINE_OPCODE(op_get_by_id_getter_proto) {
   2578         /* op_get_by_id_getter_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
   2579 
   2580          Cached property access: Attempts to get a cached getter property from the
   2581          value base's prototype. If the cache misses, op_get_by_id_getter_proto
   2582          reverts to op_get_by_id.
   2583          */
   2584         int base = vPC[2].u.operand;
   2585         JSValue baseValue = callFrame->r(base).jsValue();
   2586 
   2587         if (LIKELY(baseValue.isCell())) {
   2588             JSCell* baseCell = baseValue.asCell();
   2589             Structure* structure = vPC[4].u.structure.get();
   2590 
   2591             if (LIKELY(baseCell->structure() == structure)) {
   2592                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
   2593                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
   2594                 Structure* prototypeStructure = vPC[5].u.structure.get();
   2595 
   2596                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
   2597                     int dst = vPC[1].u.operand;
   2598                     int offset = vPC[6].u.operand;
   2599                     if (GetterSetter* getterSetter = asGetterSetter(protoObject->getDirectOffset(offset).asCell())) {
   2600                         JSObject* getter = getterSetter->getter();
   2601                         CallData callData;
   2602                         CallType callType = getter->getCallData(callData);
   2603                         JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList());
   2604                         CHECK_FOR_EXCEPTION();
   2605                         callFrame->uncheckedR(dst) = result;
   2606                     } else
   2607                         callFrame->uncheckedR(dst) = jsUndefined();
   2608                     vPC += OPCODE_LENGTH(op_get_by_id_getter_proto);
   2609                     NEXT_INSTRUCTION();
   2610                 }
   2611             }
   2612         }
   2613         uncacheGetByID(codeBlock, vPC);
   2614         NEXT_INSTRUCTION();
   2615     }
   2616 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2617     skip_id_getter_proto:
   2618 #endif
   2619 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2620     goto *(&&skip_id_custom_proto);
   2621 #endif
   2622     DEFINE_OPCODE(op_get_by_id_custom_proto) {
   2623         /* op_get_by_id_custom_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
   2624 
   2625          Cached property access: Attempts to use a cached named property getter
   2626          from the value base's prototype. If the cache misses, op_get_by_id_custom_proto
   2627          reverts to op_get_by_id.
   2628          */
   2629         int base = vPC[2].u.operand;
   2630         JSValue baseValue = callFrame->r(base).jsValue();
   2631 
   2632         if (LIKELY(baseValue.isCell())) {
   2633             JSCell* baseCell = baseValue.asCell();
   2634             Structure* structure = vPC[4].u.structure.get();
   2635 
   2636             if (LIKELY(baseCell->structure() == structure)) {
   2637                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
   2638                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
   2639                 Structure* prototypeStructure = vPC[5].u.structure.get();
   2640 
   2641                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
   2642                     int dst = vPC[1].u.operand;
   2643                     int property = vPC[3].u.operand;
   2644                     Identifier& ident = codeBlock->identifier(property);
   2645 
   2646                     PropertySlot::GetValueFunc getter = vPC[6].u.getterFunc;
   2647                     JSValue result = getter(callFrame, protoObject, ident);
   2648                     CHECK_FOR_EXCEPTION();
   2649                     callFrame->uncheckedR(dst) = result;
   2650                     vPC += OPCODE_LENGTH(op_get_by_id_custom_proto);
   2651                     NEXT_INSTRUCTION();
   2652                 }
   2653             }
   2654         }
   2655         uncacheGetByID(codeBlock, vPC);
   2656         NEXT_INSTRUCTION();
   2657     }
   2658 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2659     skip_id_custom_proto:
   2660 #endif
   2661     DEFINE_OPCODE(op_get_by_id_self_list) {
   2662         // Polymorphic self access caching currently only supported when JITting.
   2663         ASSERT_NOT_REACHED();
   2664         // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
   2665         vPC += OPCODE_LENGTH(op_get_by_id_self_list);
   2666         NEXT_INSTRUCTION();
   2667     }
   2668     DEFINE_OPCODE(op_get_by_id_proto_list) {
   2669         // Polymorphic prototype access caching currently only supported when JITting.
   2670         ASSERT_NOT_REACHED();
   2671         // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
   2672         vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
   2673         NEXT_INSTRUCTION();
   2674     }
   2675     DEFINE_OPCODE(op_get_by_id_getter_self_list) {
   2676         // Polymorphic self access caching currently only supported when JITting.
   2677         ASSERT_NOT_REACHED();
   2678         // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
   2679         vPC += OPCODE_LENGTH(op_get_by_id_self_list);
   2680         NEXT_INSTRUCTION();
   2681     }
   2682     DEFINE_OPCODE(op_get_by_id_getter_proto_list) {
   2683         // Polymorphic prototype access caching currently only supported when JITting.
   2684         ASSERT_NOT_REACHED();
   2685         // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
   2686         vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
   2687         NEXT_INSTRUCTION();
   2688     }
   2689     DEFINE_OPCODE(op_get_by_id_custom_self_list) {
   2690         // Polymorphic self access caching currently only supported when JITting.
   2691         ASSERT_NOT_REACHED();
   2692         // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
   2693         vPC += OPCODE_LENGTH(op_get_by_id_custom_self_list);
   2694         NEXT_INSTRUCTION();
   2695     }
   2696     DEFINE_OPCODE(op_get_by_id_custom_proto_list) {
   2697         // Polymorphic prototype access caching currently only supported when JITting.
   2698         ASSERT_NOT_REACHED();
   2699         // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
   2700         vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
   2701         NEXT_INSTRUCTION();
   2702     }
   2703 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2704     goto *(&&skip_get_by_id_chain);
   2705 #endif
   2706     DEFINE_OPCODE(op_get_by_id_chain) {
   2707         /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
   2708 
   2709            Cached property access: Attempts to get a cached property from the
   2710            value base's prototype chain. If the cache misses, op_get_by_id_chain
   2711            reverts to op_get_by_id.
   2712         */
   2713         int base = vPC[2].u.operand;
   2714         JSValue baseValue = callFrame->r(base).jsValue();
   2715 
   2716         if (LIKELY(baseValue.isCell())) {
   2717             JSCell* baseCell = baseValue.asCell();
   2718             Structure* structure = vPC[4].u.structure.get();
   2719 
   2720             if (LIKELY(baseCell->structure() == structure)) {
   2721                 WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
   2722                 size_t count = vPC[6].u.operand;
   2723                 WriteBarrier<Structure>* end = it + count;
   2724 
   2725                 while (true) {
   2726                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
   2727 
   2728                     if (UNLIKELY(baseObject->structure() != (*it).get()))
   2729                         break;
   2730 
   2731                     if (++it == end) {
   2732                         int dst = vPC[1].u.operand;
   2733                         int offset = vPC[7].u.operand;
   2734 
   2735                         ASSERT(baseObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
   2736                         ASSERT(baseValue.get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
   2737                         callFrame->uncheckedR(dst) = JSValue(baseObject->getDirectOffset(offset));
   2738 
   2739                         vPC += OPCODE_LENGTH(op_get_by_id_chain);
   2740                         NEXT_INSTRUCTION();
   2741                     }
   2742 
   2743                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
   2744                     baseCell = baseObject;
   2745                 }
   2746             }
   2747         }
   2748 
   2749         uncacheGetByID(codeBlock, vPC);
   2750         NEXT_INSTRUCTION();
   2751     }
   2752 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2753     skip_get_by_id_chain:
   2754     goto *(&&skip_id_getter_self);
   2755 #endif
   2756     DEFINE_OPCODE(op_get_by_id_getter_self) {
   2757         /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
   2758 
   2759          Cached property access: Attempts to get a cached property from the
   2760          value base. If the cache misses, op_get_by_id_getter_self reverts to
   2761          op_get_by_id.
   2762          */
   2763         int base = vPC[2].u.operand;
   2764         JSValue baseValue = callFrame->r(base).jsValue();
   2765 
   2766         if (LIKELY(baseValue.isCell())) {
   2767             JSCell* baseCell = baseValue.asCell();
   2768             Structure* structure = vPC[4].u.structure.get();
   2769 
   2770             if (LIKELY(baseCell->structure() == structure)) {
   2771                 ASSERT(baseCell->isObject());
   2772                 JSObject* baseObject = asObject(baseCell);
   2773                 int dst = vPC[1].u.operand;
   2774                 int offset = vPC[5].u.operand;
   2775 
   2776                 if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
   2777                     JSObject* getter = getterSetter->getter();
   2778                     CallData callData;
   2779                     CallType callType = getter->getCallData(callData);
   2780                     JSValue result = call(callFrame, getter, callType, callData, baseObject, ArgList());
   2781                     CHECK_FOR_EXCEPTION();
   2782                     callFrame->uncheckedR(dst) = result;
   2783                 } else
   2784                     callFrame->uncheckedR(dst) = jsUndefined();
   2785 
   2786                 vPC += OPCODE_LENGTH(op_get_by_id_getter_self);
   2787                 NEXT_INSTRUCTION();
   2788             }
   2789         }
   2790         uncacheGetByID(codeBlock, vPC);
   2791         NEXT_INSTRUCTION();
   2792     }
   2793 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2794     skip_id_getter_self:
   2795 #endif
   2796 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2797     goto *(&&skip_id_custom_self);
   2798 #endif
   2799     DEFINE_OPCODE(op_get_by_id_custom_self) {
   2800         /* op_get_by_id_custom_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
   2801 
   2802          Cached property access: Attempts to use a cached named property getter
   2803          from the value base. If the cache misses, op_get_by_id_custom_self reverts to
   2804          op_get_by_id.
   2805          */
   2806         int base = vPC[2].u.operand;
   2807         JSValue baseValue = callFrame->r(base).jsValue();
   2808 
   2809         if (LIKELY(baseValue.isCell())) {
   2810             JSCell* baseCell = baseValue.asCell();
   2811             Structure* structure = vPC[4].u.structure.get();
   2812 
   2813             if (LIKELY(baseCell->structure() == structure)) {
   2814                 ASSERT(baseCell->isObject());
   2815                 int dst = vPC[1].u.operand;
   2816                 int property = vPC[3].u.operand;
   2817                 Identifier& ident = codeBlock->identifier(property);
   2818 
   2819                 PropertySlot::GetValueFunc getter = vPC[5].u.getterFunc;
   2820                 JSValue result = getter(callFrame, baseValue, ident);
   2821                 CHECK_FOR_EXCEPTION();
   2822                 callFrame->uncheckedR(dst) = result;
   2823                 vPC += OPCODE_LENGTH(op_get_by_id_custom_self);
   2824                 NEXT_INSTRUCTION();
   2825             }
   2826         }
   2827         uncacheGetByID(codeBlock, vPC);
   2828         NEXT_INSTRUCTION();
   2829     }
   2830 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2831 skip_id_custom_self:
   2832 #endif
   2833     DEFINE_OPCODE(op_get_by_id_generic) {
   2834         /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
   2835 
   2836            Generic property access: Gets the property named by identifier
   2837            property from the value base, and puts the result in register dst.
   2838         */
   2839         int dst = vPC[1].u.operand;
   2840         int base = vPC[2].u.operand;
   2841         int property = vPC[3].u.operand;
   2842 
   2843         Identifier& ident = codeBlock->identifier(property);
   2844         JSValue baseValue = callFrame->r(base).jsValue();
   2845         PropertySlot slot(baseValue);
   2846         JSValue result = baseValue.get(callFrame, ident, slot);
   2847         CHECK_FOR_EXCEPTION();
   2848 
   2849         callFrame->uncheckedR(dst) = result;
   2850         vPC += OPCODE_LENGTH(op_get_by_id_generic);
   2851         NEXT_INSTRUCTION();
   2852     }
   2853 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2854     goto *(&&skip_id_getter_chain);
   2855 #endif
   2856     DEFINE_OPCODE(op_get_by_id_getter_chain) {
   2857         /* op_get_by_id_getter_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
   2858 
   2859          Cached property access: Attempts to get a cached property from the
   2860          value base's prototype chain. If the cache misses, op_get_by_id_getter_chain
   2861          reverts to op_get_by_id.
   2862          */
   2863         int base = vPC[2].u.operand;
   2864         JSValue baseValue = callFrame->r(base).jsValue();
   2865 
   2866         if (LIKELY(baseValue.isCell())) {
   2867             JSCell* baseCell = baseValue.asCell();
   2868             Structure* structure = vPC[4].u.structure.get();
   2869 
   2870             if (LIKELY(baseCell->structure() == structure)) {
   2871                 WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
   2872                 size_t count = vPC[6].u.operand;
   2873                 WriteBarrier<Structure>* end = it + count;
   2874 
   2875                 while (true) {
   2876                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
   2877 
   2878                     if (UNLIKELY(baseObject->structure() != (*it).get()))
   2879                         break;
   2880 
   2881                     if (++it == end) {
   2882                         int dst = vPC[1].u.operand;
   2883                         int offset = vPC[7].u.operand;
   2884                         if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
   2885                             JSObject* getter = getterSetter->getter();
   2886                             CallData callData;
   2887                             CallType callType = getter->getCallData(callData);
   2888                             JSValue result = call(callFrame, getter, callType, callData, baseValue, ArgList());
   2889                             CHECK_FOR_EXCEPTION();
   2890                             callFrame->uncheckedR(dst) = result;
   2891                         } else
   2892                             callFrame->uncheckedR(dst) = jsUndefined();
   2893                         vPC += OPCODE_LENGTH(op_get_by_id_getter_chain);
   2894                         NEXT_INSTRUCTION();
   2895                     }
   2896 
   2897                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
   2898                     baseCell = baseObject;
   2899                 }
   2900             }
   2901         }
   2902         uncacheGetByID(codeBlock, vPC);
   2903         NEXT_INSTRUCTION();
   2904     }
   2905 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2906     skip_id_getter_chain:
   2907 #endif
   2908 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2909     goto *(&&skip_id_custom_chain);
   2910 #endif
   2911     DEFINE_OPCODE(op_get_by_id_custom_chain) {
   2912         /* op_get_by_id_custom_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
   2913 
   2914          Cached property access: Attempts to use a cached named property getter on the
   2915          value base's prototype chain. If the cache misses, op_get_by_id_custom_chain
   2916          reverts to op_get_by_id.
   2917          */
   2918         int base = vPC[2].u.operand;
   2919         JSValue baseValue = callFrame->r(base).jsValue();
   2920 
   2921         if (LIKELY(baseValue.isCell())) {
   2922             JSCell* baseCell = baseValue.asCell();
   2923             Structure* structure = vPC[4].u.structure.get();
   2924 
   2925             if (LIKELY(baseCell->structure() == structure)) {
   2926                 WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
   2927                 size_t count = vPC[6].u.operand;
   2928                 WriteBarrier<Structure>* end = it + count;
   2929 
   2930                 while (true) {
   2931                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
   2932 
   2933                     if (UNLIKELY(baseObject->structure() != (*it).get()))
   2934                         break;
   2935 
   2936                     if (++it == end) {
   2937                         int dst = vPC[1].u.operand;
   2938                         int property = vPC[3].u.operand;
   2939                         Identifier& ident = codeBlock->identifier(property);
   2940 
   2941                         PropertySlot::GetValueFunc getter = vPC[7].u.getterFunc;
   2942                         JSValue result = getter(callFrame, baseObject, ident);
   2943                         CHECK_FOR_EXCEPTION();
   2944                         callFrame->uncheckedR(dst) = result;
   2945                         vPC += OPCODE_LENGTH(op_get_by_id_custom_chain);
   2946                         NEXT_INSTRUCTION();
   2947                     }
   2948 
   2949                     // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
   2950                     baseCell = baseObject;
   2951                 }
   2952             }
   2953         }
   2954         uncacheGetByID(codeBlock, vPC);
   2955         NEXT_INSTRUCTION();
   2956     }
   2957 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2958     skip_id_custom_chain:
   2959     goto *(&&skip_get_array_length);
   2960 #endif
   2961     DEFINE_OPCODE(op_get_array_length) {
   2962         /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
   2963 
   2964            Cached property access: Gets the length of the array in register base,
   2965            and puts the result in register dst. If register base does not hold
   2966            an array, op_get_array_length reverts to op_get_by_id.
   2967         */
   2968 
   2969         int base = vPC[2].u.operand;
   2970         JSValue baseValue = callFrame->r(base).jsValue();
   2971         if (LIKELY(isJSArray(globalData, baseValue))) {
   2972             int dst = vPC[1].u.operand;
   2973             callFrame->uncheckedR(dst) = jsNumber(asArray(baseValue)->length());
   2974             vPC += OPCODE_LENGTH(op_get_array_length);
   2975             NEXT_INSTRUCTION();
   2976         }
   2977 
   2978         uncacheGetByID(codeBlock, vPC);
   2979         NEXT_INSTRUCTION();
   2980     }
   2981 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   2982     skip_get_array_length:
   2983     goto *(&&skip_get_string_length);
   2984 #endif
   2985     DEFINE_OPCODE(op_get_string_length) {
   2986         /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
   2987 
   2988            Cached property access: Gets the length of the string in register base,
   2989            and puts the result in register dst. If register base does not hold
   2990            a string, op_get_string_length reverts to op_get_by_id.
   2991         */
   2992 
   2993         int base = vPC[2].u.operand;
   2994         JSValue baseValue = callFrame->r(base).jsValue();
   2995         if (LIKELY(isJSString(globalData, baseValue))) {
   2996             int dst = vPC[1].u.operand;
   2997             callFrame->uncheckedR(dst) = jsNumber(asString(baseValue)->length());
   2998             vPC += OPCODE_LENGTH(op_get_string_length);
   2999             NEXT_INSTRUCTION();
   3000         }
   3001 
   3002         uncacheGetByID(codeBlock, vPC);
   3003         NEXT_INSTRUCTION();
   3004     }
   3005 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   3006     skip_get_string_length:
   3007     goto *(&&skip_put_by_id);
   3008 #endif
   3009     DEFINE_OPCODE(op_put_by_id) {
   3010         /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
   3011 
   3012            Generic property access: Sets the property named by identifier
   3013            property, belonging to register base, to register value.
   3014 
   3015            Unlike many opcodes, this one does not write any output to
   3016            the register file.
   3017 
   3018            The "direct" flag should only be set this put_by_id is to initialize
   3019            an object literal.
   3020         */
   3021 
   3022         int base = vPC[1].u.operand;
   3023         int property = vPC[2].u.operand;
   3024         int value = vPC[3].u.operand;
   3025         int direct = vPC[8].u.operand;
   3026 
   3027         JSValue baseValue = callFrame->r(base).jsValue();
   3028         Identifier& ident = codeBlock->identifier(property);
   3029         PutPropertySlot slot(codeBlock->isStrictMode());
   3030         if (direct) {
   3031             baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
   3032             ASSERT(slot.base() == baseValue);
   3033         } else
   3034             baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
   3035         CHECK_FOR_EXCEPTION();
   3036 
   3037         tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
   3038 
   3039         vPC += OPCODE_LENGTH(op_put_by_id);
   3040         NEXT_INSTRUCTION();
   3041     }
   3042 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
   3043       skip_put_by_id:
   3044 #endif
   3045     DEFINE_OPCODE(op_put_by_id_transition) {
   3046         /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b)
   3047 
   3048            Cached property access: Attempts to set a new property with a cached transition
   3049            property named by identifier property, belonging to register base,
   3050            to register value. If the cache misses, op_put_by_id_transition
   3051            reverts to op_put_by_id_generic.
   3052 
   3053            Unlike many opcodes, this one does not write any output to
   3054            the register file.
   3055          */
   3056         int base = vPC[1].u.operand;
   3057         JSValue baseValue = callFrame->r(base).jsValue();
   3058 
   3059         if (LIKELY(baseValue.isCell())) {
   3060             JSCell* baseCell = baseValue.asCell();
   3061             Structure* oldStructure = vPC[4].u.structure.get();
   3062             Structure* newStructure = vPC[5].u.structure.get();
   3063 
   3064             if (LIKELY(baseCell->structure() == oldStructure)) {
   3065                 ASSERT(baseCell->isObject());
   3066                 JSObject* baseObject = asObject(baseCell);
   3067                 int direct = vPC[8].u.operand;
   3068 
   3069                 if (!direct) {
   3070                     WriteBarrier<Structure>* it = vPC[6].u.structureChain->head();
   3071 
   3072                     JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
   3073                     while (!proto.isNull()) {
   3074                         if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
   3075                             uncachePutByID(codeBlock, vPC);
   3076                             NEXT_INSTRUCTION();
   3077                         }
   3078                         ++it;
   3079                         proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
   3080                     }
   3081                 }
   3082                 baseObject->transitionTo(*globalData, newStructure);
   3083 
   3084                 int value = vPC[3].u.operand;
   3085                 unsigned offset = vPC[7].u.operand;
   3086                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset);
   3087                 baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue());
   3088 
   3089                 vPC += OPCODE_LENGTH(op_put_by_id_transition);
   3090                 NEXT_INSTRUCTION();
   3091             }
   3092         }
   3093 
   3094         uncachePutByID(codeBlock, vPC);
   3095         NEXT_INSTRUCTION();
   3096     }
   3097     DEFINE_OPCODE(op_put_by_id_replace) {
   3098         /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n) direct(b)
   3099 
   3100            Cached property access: Attempts to set a pre-existing, cached
   3101            property named by identifier property, belonging to register base,
   3102            to register value. If the cache misses, op_put_by_id_replace
   3103            reverts to op_put_by_id.
   3104 
   3105            Unlike many opcodes, this one does not write any output to
   3106            the register file.
   3107         */
   3108         int base = vPC[1].u.operand;
   3109         JSValue baseValue = callFrame->r(base).jsValue();
   3110 
   3111         if (LIKELY(baseValue.isCell())) {
   3112             JSCell* baseCell = baseValue.asCell();
   3113             Structure* structure = vPC[4].u.structure.get();
   3114 
   3115             if (LIKELY(baseCell->structure() == structure)) {
   3116                 ASSERT(baseCell->isObject());
   3117                 JSObject* baseObject = asObject(baseCell);
   3118                 int value = vPC[3].u.operand;
   3119                 unsigned offset = vPC[5].u.operand;
   3120 
   3121                 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset);
   3122                 baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue());
   3123 
   3124                 vPC += OPCODE_LENGTH(op_put_by_id_replace);
   3125                 NEXT_INSTRUCTION();
   3126             }
   3127         }
   3128 
   3129         uncachePutByID(codeBlock, vPC);
   3130         NEXT_INSTRUCTION();
   3131     }
   3132     DEFINE_OPCODE(op_put_by_id_generic) {
   3133         /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
   3134 
   3135            Generic property access: Sets the property named by identifier
   3136            property, belonging to register base, to register value.
   3137 
   3138            Unlike many opcodes, this one does not write any output to
   3139            the register file.
   3140         */
   3141         int base = vPC[1].u.operand;
   3142         int property = vPC[2].u.operand;
   3143         int value = vPC[3].u.operand;
   3144         int direct = vPC[8].u.operand;
   3145 
   3146         JSValue baseValue = callFrame->r(base).jsValue();
   3147         Identifier& ident = codeBlock->identifier(property);
   3148         PutPropertySlot slot(codeBlock->isStrictMode());
   3149         if (direct) {
   3150             baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
   3151             ASSERT(slot.base() == baseValue);
   3152         } else
   3153             baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
   3154         CHECK_FOR_EXCEPTION();
   3155 
   3156         vPC += OPCODE_LENGTH(op_put_by_id_generic);
   3157         NEXT_INSTRUCTION();
   3158     }
   3159     DEFINE_OPCODE(op_del_by_id) {
   3160         /* del_by_id dst(r) base(r) property(id)
   3161 
   3162            Converts register base to Object, deletes the property
   3163            named by identifier property from the object, and writes a
   3164            boolean indicating success (if true) or failure (if false)
   3165            to register dst.
   3166         */
   3167         int dst = vPC[1].u.operand;
   3168         int base = vPC[2].u.operand;
   3169         int property = vPC[3].u.operand;
   3170 
   3171         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
   3172         Identifier& ident = codeBlock->identifier(property);
   3173         bool result = baseObj->deleteProperty(callFrame, ident);
   3174         if (!result && codeBlock->isStrictMode()) {
   3175             exceptionValue = createTypeError(callFrame, "Unable to delete property.");
   3176             goto vm_throw;
   3177         }
   3178         CHECK_FOR_EXCEPTION();
   3179         callFrame->uncheckedR(dst) = jsBoolean(result);
   3180         vPC += OPCODE_LENGTH(op_del_by_id);
   3181         NEXT_INSTRUCTION();
   3182     }
   3183     DEFINE_OPCODE(op_get_by_pname) {
   3184         int dst = vPC[1].u.operand;
   3185         int base = vPC[2].u.operand;
   3186         int property = vPC[3].u.operand;
   3187         int expected = vPC[4].u.operand;
   3188         int iter = vPC[5].u.operand;
   3189         int i = vPC[6].u.operand;
   3190 
   3191         JSValue baseValue = callFrame->r(base).jsValue();
   3192         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
   3193         JSValue subscript = callFrame->r(property).jsValue();
   3194         JSValue expectedSubscript = callFrame->r(expected).jsValue();
   3195         int index = callFrame->r(i).i() - 1;
   3196         JSValue result;
   3197         int offset = 0;
   3198         if (subscript == expectedSubscript && baseValue.isCell() && (baseValue.asCell()->structure() == it->cachedStructure()) && it->getOffset(index, offset)) {
   3199             callFrame->uncheckedR(dst) = JSValue(asObject(baseValue)->getDirectOffset(offset));
   3200             vPC += OPCODE_LENGTH(op_get_by_pname);
   3201             NEXT_INSTRUCTION();
   3202         }
   3203         {
   3204             Identifier propertyName(callFrame, subscript.toString(callFrame));
   3205             result = baseValue.get(callFrame, propertyName);
   3206         }
   3207         CHECK_FOR_EXCEPTION();
   3208         callFrame->uncheckedR(dst) = result;
   3209         vPC += OPCODE_LENGTH(op_get_by_pname);
   3210         NEXT_INSTRUCTION();
   3211     }
   3212     DEFINE_OPCODE(op_get_arguments_length) {
   3213         int dst = vPC[1].u.operand;
   3214         int argumentsRegister = vPC[2].u.operand;
   3215         int property = vPC[3].u.operand;
   3216         JSValue arguments = callFrame->r(argumentsRegister).jsValue();
   3217         if (arguments) {
   3218             Identifier& ident = codeBlock->identifier(property);
   3219             PropertySlot slot(arguments);
   3220             JSValue result = arguments.get(callFrame, ident, slot);
   3221             CHECK_FOR_EXCEPTION();
   3222             callFrame->uncheckedR(dst) = result;
   3223         } else
   3224             callFrame->uncheckedR(dst) = jsNumber(callFrame->argumentCount());
   3225 
   3226         vPC += OPCODE_LENGTH(op_get_arguments_length);
   3227         NEXT_INSTRUCTION();
   3228     }
   3229     DEFINE_OPCODE(op_get_argument_by_val) {
   3230         int dst = vPC[1].u.operand;
   3231         int argumentsRegister = vPC[2].u.operand;
   3232         int property = vPC[3].u.operand;
   3233         JSValue arguments = callFrame->r(argumentsRegister).jsValue();
   3234         JSValue subscript = callFrame->r(property).jsValue();
   3235         if (!arguments && subscript.isUInt32() && subscript.asUInt32() < callFrame->argumentCount()) {
   3236             unsigned arg = subscript.asUInt32() + 1;
   3237             unsigned numParameters = callFrame->codeBlock()->m_numParameters;
   3238             if (arg < numParameters)
   3239                 callFrame->uncheckedR(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters);
   3240             else
   3241                 callFrame->uncheckedR(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters - callFrame->argumentCount() - 1);
   3242             vPC += OPCODE_LENGTH(op_get_argument_by_val);
   3243             NEXT_INSTRUCTION();
   3244         }
   3245         if (!arguments) {
   3246             Arguments* arguments = new (globalData) Arguments(callFrame);
   3247             callFrame->uncheckedR(argumentsRegister) = JSValue(arguments);
   3248             callFrame->uncheckedR(unmodifiedArgumentsRegister(argumentsRegister)) = JSValue(arguments);
   3249         }
   3250         // fallthrough
   3251     }
   3252     DEFINE_OPCODE(op_get_by_val) {
   3253         /* get_by_val dst(r) base(r) property(r)
   3254 
   3255            Converts register base to Object, gets the property named
   3256            by register property from the object, and puts the result
   3257            in register dst. property is nominally converted to string
   3258            but numbers are treated more efficiently.
   3259         */
   3260         int dst = vPC[1].u.operand;
   3261         int base = vPC[2].u.operand;
   3262         int property = vPC[3].u.operand;
   3263 
   3264         JSValue baseValue = callFrame->r(base).jsValue();
   3265         JSValue subscript = callFrame->r(property).jsValue();
   3266 
   3267         JSValue result;
   3268 
   3269         if (LIKELY(subscript.isUInt32())) {
   3270             uint32_t i = subscript.asUInt32();
   3271             if (isJSArray(globalData, baseValue)) {
   3272                 JSArray* jsArray = asArray(baseValue);
   3273                 if (jsArray->canGetIndex(i))
   3274                     result = jsArray->getIndex(i);
   3275                 else
   3276                     result = jsArray->JSArray::get(callFrame, i);
   3277             } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
   3278                 result = asString(baseValue)->getIndex(callFrame, i);
   3279             else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i))
   3280                 result = asByteArray(baseValue)->getIndex(callFrame, i);
   3281             else
   3282                 result = baseValue.get(callFrame, i);
   3283         } else {
   3284             Identifier property(callFrame, subscript.toString(callFrame));
   3285             result = baseValue.get(callFrame, property);
   3286         }
   3287 
   3288         CHECK_FOR_EXCEPTION();
   3289         callFrame->uncheckedR(dst) = result;
   3290         vPC += OPCODE_LENGTH(op_get_by_val);
   3291         NEXT_INSTRUCTION();
   3292     }
   3293     DEFINE_OPCODE(op_put_by_val) {
   3294         /* put_by_val base(r) property(r) value(r)
   3295 
   3296            Sets register value on register base as the property named
   3297            by register property. Base is converted to object
   3298            first. register property is nominally converted to string
   3299            but numbers are treated more efficiently.
   3300 
   3301            Unlike many opcodes, this one does not write any output to
   3302            the register file.
   3303         */
   3304         int base = vPC[1].u.operand;
   3305         int property = vPC[2].u.operand;
   3306         int value = vPC[3].u.operand;
   3307 
   3308         JSValue baseValue = callFrame->r(base).jsValue();
   3309         JSValue subscript = callFrame->r(property).jsValue();
   3310 
   3311         if (LIKELY(subscript.isUInt32())) {
   3312             uint32_t i = subscript.asUInt32();
   3313             if (isJSArray(globalData, baseValue)) {
   3314                 JSArray* jsArray = asArray(baseValue);
   3315                 if (jsArray->canSetIndex(i))
   3316                     jsArray->setIndex(*globalData, i, callFrame->r(value).jsValue());
   3317                 else
   3318                     jsArray->JSArray::put(callFrame, i, callFrame->r(value).jsValue());
   3319             } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
   3320                 JSByteArray* jsByteArray = asByteArray(baseValue);
   3321                 double dValue = 0;
   3322                 JSValue jsValue = callFrame->r(value).jsValue();
   3323                 if (jsValue.isInt32())
   3324                     jsByteArray->setIndex(i, jsValue.asInt32());
   3325                 else if (jsValue.getNumber(dValue))
   3326                     jsByteArray->setIndex(i, dValue);
   3327                 else
   3328                     baseValue.put(callFrame, i, jsValue);
   3329             } else
   3330                 baseValue.put(callFrame, i, callFrame->r(value).jsValue());
   3331         } else {
   3332             Identifier property(callFrame, subscript.toString(callFrame));
   3333             if (!globalData->exception) { // Don't put to an object if toString threw an exception.
   3334                 PutPropertySlot slot(codeBlock->isStrictMode());
   3335                 baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot);
   3336             }
   3337         }
   3338 
   3339         CHECK_FOR_EXCEPTION();
   3340         vPC += OPCODE_LENGTH(op_put_by_val);
   3341         NEXT_INSTRUCTION();
   3342     }
   3343     DEFINE_OPCODE(op_del_by_val) {
   3344         /* del_by_val dst(r) base(r) property(r)
   3345 
   3346            Converts register base to Object, deletes the property
   3347            named by register property from the object, and writes a
   3348            boolean indicating success (if true) or failure (if false)
   3349            to register dst.
   3350         */
   3351         int dst = vPC[1].u.operand;
   3352         int base = vPC[2].u.operand;
   3353         int property = vPC[3].u.operand;
   3354 
   3355         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw
   3356 
   3357         JSValue subscript = callFrame->r(property).jsValue();
   3358         bool result;
   3359         uint32_t i;
   3360         if (subscript.getUInt32(i))
   3361             result = baseObj->deleteProperty(callFrame, i);
   3362         else {
   3363             CHECK_FOR_EXCEPTION();
   3364             Identifier property(callFrame, subscript.toString(callFrame));
   3365             CHECK_FOR_EXCEPTION();
   3366             result = baseObj->deleteProperty(callFrame, property);
   3367         }
   3368         if (!result && codeBlock->isStrictMode()) {
   3369             exceptionValue = createTypeError(callFrame, "Unable to delete property.");
   3370             goto vm_throw;
   3371         }
   3372         CHECK_FOR_EXCEPTION();
   3373         callFrame->uncheckedR(dst) = jsBoolean(result);
   3374         vPC += OPCODE_LENGTH(op_del_by_val);
   3375         NEXT_INSTRUCTION();
   3376     }
   3377     DEFINE_OPCODE(op_put_by_index) {
   3378         /* put_by_index base(r) property(n) value(r)
   3379 
   3380            Sets register value on register base as the property named
   3381            by the immediate number property. Base is converted to
   3382            object first.
   3383 
   3384            Unlike many opcodes, this one does not write any output to
   3385            the register file.
   3386 
   3387            This opcode is mainly used to initialize array literals.
   3388         */
   3389         int base = vPC[1].u.operand;
   3390         unsigned property = vPC[2].u.operand;
   3391         int value = vPC[3].u.operand;
   3392 
   3393         callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue());
   3394 
   3395         vPC += OPCODE_LENGTH(op_put_by_index);
   3396         NEXT_INSTRUCTION();
   3397     }
   3398     DEFINE_OPCODE(op_loop) {
   3399         /* loop target(offset)
   3400 
   3401            Jumps unconditionally to offset target from the current
   3402            instruction.
   3403 
   3404            Additionally this loop instruction may terminate JS execution is
   3405            the JS timeout is reached.
   3406          */
   3407 #if ENABLE(OPCODE_STATS)
   3408         OpcodeStats::resetLastInstruction();
   3409 #endif
   3410         int target = vPC[1].u.operand;
   3411         CHECK_FOR_TIMEOUT();
   3412         vPC += target;
   3413         NEXT_INSTRUCTION();
   3414     }
   3415     DEFINE_OPCODE(op_jmp) {
   3416         /* jmp target(offset)
   3417 
   3418            Jumps unconditionally to offset target from the current
   3419            instruction.
   3420         */
   3421 #if ENABLE(OPCODE_STATS)
   3422         OpcodeStats::resetLastInstruction();
   3423 #endif
   3424         int target = vPC[1].u.operand;
   3425 
   3426         vPC += target;
   3427         NEXT_INSTRUCTION();
   3428     }
   3429     DEFINE_OPCODE(op_loop_if_true) {
   3430         /* loop_if_true cond(r) target(offset)
   3431 
   3432            Jumps to offset target from the current instruction, if and
   3433            only if register cond converts to boolean as true.
   3434 
   3435            Additionally this loop instruction may terminate JS execution is
   3436            the JS timeout is reached.
   3437          */
   3438         int cond = vPC[1].u.operand;
   3439         int target = vPC[2].u.operand;
   3440         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
   3441             vPC += target;
   3442             CHECK_FOR_TIMEOUT();
   3443             NEXT_INSTRUCTION();
   3444         }
   3445 
   3446         vPC += OPCODE_LENGTH(op_loop_if_true);
   3447         NEXT_INSTRUCTION();
   3448     }
   3449     DEFINE_OPCODE(op_loop_if_false) {
   3450         /* loop_if_true cond(r) target(offset)
   3451 
   3452            Jumps to offset target from the current instruction, if and
   3453            only if register cond converts to boolean as false.
   3454 
   3455            Additionally this loop instruction may terminate JS execution is
   3456            the JS timeout is reached.
   3457          */
   3458         int cond = vPC[1].u.operand;
   3459         int target = vPC[2].u.operand;
   3460         if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
   3461             vPC += target;
   3462             CHECK_FOR_TIMEOUT();
   3463             NEXT_INSTRUCTION();
   3464         }
   3465 
   3466         vPC += OPCODE_LENGTH(op_loop_if_true);
   3467         NEXT_INSTRUCTION();
   3468     }
   3469     DEFINE_OPCODE(op_jtrue) {
   3470         /* jtrue cond(r) target(offset)
   3471 
   3472            Jumps to offset target from the current instruction, if and
   3473            only if register cond converts to boolean as true.
   3474         */
   3475         int cond = vPC[1].u.operand;
   3476         int target = vPC[2].u.operand;
   3477         if (callFrame->r(cond).jsValue().toBoolean(callFrame)) {
   3478             vPC += target;
   3479             NEXT_INSTRUCTION();
   3480         }
   3481 
   3482         vPC += OPCODE_LENGTH(op_jtrue);
   3483         NEXT_INSTRUCTION();
   3484     }
   3485     DEFINE_OPCODE(op_jfalse) {
   3486         /* jfalse cond(r) target(offset)
   3487 
   3488            Jumps to offset target from the current instruction, if and
   3489            only if register cond converts to boolean as false.
   3490         */
   3491         int cond = vPC[1].u.operand;
   3492         int target = vPC[2].u.operand;
   3493         if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
   3494             vPC += target;
   3495             NEXT_INSTRUCTION();
   3496         }
   3497 
   3498         vPC += OPCODE_LENGTH(op_jfalse);
   3499         NEXT_INSTRUCTION();
   3500     }
   3501     DEFINE_OPCODE(op_jeq_null) {
   3502         /* jeq_null src(r) target(offset)
   3503 
   3504            Jumps to offset target from the current instruction, if and
   3505            only if register src is null.
   3506         */
   3507         int src = vPC[1].u.operand;
   3508         int target = vPC[2].u.operand;
   3509         JSValue srcValue = callFrame->r(src).jsValue();
   3510 
   3511         if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
   3512             vPC += target;
   3513             NEXT_INSTRUCTION();
   3514         }
   3515 
   3516         vPC += OPCODE_LENGTH(op_jeq_null);
   3517         NEXT_INSTRUCTION();
   3518     }
   3519     DEFINE_OPCODE(op_jneq_null) {
   3520         /* jneq_null src(r) target(offset)
   3521 
   3522            Jumps to offset target from the current instruction, if and
   3523            only if register src is not null.
   3524         */
   3525         int src = vPC[1].u.operand;
   3526         int target = vPC[2].u.operand;
   3527         JSValue srcValue = callFrame->r(src).jsValue();
   3528 
   3529         if (!srcValue.isUndefinedOrNull() && (!srcValue.isCell() || !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) {
   3530             vPC += target;
   3531             NEXT_INSTRUCTION();
   3532         }
   3533 
   3534         vPC += OPCODE_LENGTH(op_jneq_null);
   3535         NEXT_INSTRUCTION();
   3536     }
   3537     DEFINE_OPCODE(op_jneq_ptr) {
   3538         /* jneq_ptr src(r) ptr(jsCell) target(offset)
   3539 
   3540            Jumps to offset target from the current instruction, if the value r is equal
   3541            to ptr, using pointer equality.
   3542          */
   3543         int src = vPC[1].u.operand;
   3544         int target = vPC[3].u.operand;
   3545         JSValue srcValue = callFrame->r(src).jsValue();
   3546         if (srcValue != vPC[2].u.jsCell.get()) {
   3547             vPC += target;
   3548             NEXT_INSTRUCTION();
   3549         }
   3550 
   3551         vPC += OPCODE_LENGTH(op_jneq_ptr);
   3552         NEXT_INSTRUCTION();
   3553     }
   3554     DEFINE_OPCODE(op_loop_if_less) {
   3555         /* loop_if_less src1(r) src2(r) target(offset)
   3556 
   3557            Checks whether register src1 is less than register src2, as
   3558            with the ECMAScript '<' operator, and then jumps to offset
   3559            target from the current instruction, if and only if the
   3560            result of the comparison is true.
   3561 
   3562            Additionally this loop instruction may terminate JS execution is
   3563            the JS timeout is reached.
   3564          */
   3565         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   3566         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   3567         int target = vPC[3].u.operand;
   3568 
   3569         bool result = jsLess(callFrame, src1, src2);
   3570         CHECK_FOR_EXCEPTION();
   3571 
   3572         if (result) {
   3573             vPC += target;
   3574             CHECK_FOR_TIMEOUT();
   3575             NEXT_INSTRUCTION();
   3576         }
   3577 
   3578         vPC += OPCODE_LENGTH(op_loop_if_less);
   3579         NEXT_INSTRUCTION();
   3580     }
   3581     DEFINE_OPCODE(op_loop_if_lesseq) {
   3582         /* loop_if_lesseq src1(r) src2(r) target(offset)
   3583 
   3584            Checks whether register src1 is less than or equal to register
   3585            src2, as with the ECMAScript '<=' operator, and then jumps to
   3586            offset target from the current instruction, if and only if the
   3587            result of the comparison is true.
   3588 
   3589            Additionally this loop instruction may terminate JS execution is
   3590            the JS timeout is reached.
   3591         */
   3592         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   3593         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   3594         int target = vPC[3].u.operand;
   3595 
   3596         bool result = jsLessEq(callFrame, src1, src2);
   3597         CHECK_FOR_EXCEPTION();
   3598 
   3599         if (result) {
   3600             vPC += target;
   3601             CHECK_FOR_TIMEOUT();
   3602             NEXT_INSTRUCTION();
   3603         }
   3604 
   3605         vPC += OPCODE_LENGTH(op_loop_if_lesseq);
   3606         NEXT_INSTRUCTION();
   3607     }
   3608     DEFINE_OPCODE(op_jnless) {
   3609         /* jnless src1(r) src2(r) target(offset)
   3610 
   3611            Checks whether register src1 is less than register src2, as
   3612            with the ECMAScript '<' operator, and then jumps to offset
   3613            target from the current instruction, if and only if the
   3614            result of the comparison is false.
   3615         */
   3616         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   3617         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   3618         int target = vPC[3].u.operand;
   3619 
   3620         bool result = jsLess(callFrame, src1, src2);
   3621         CHECK_FOR_EXCEPTION();
   3622 
   3623         if (!result) {
   3624             vPC += target;
   3625             NEXT_INSTRUCTION();
   3626         }
   3627 
   3628         vPC += OPCODE_LENGTH(op_jnless);
   3629         NEXT_INSTRUCTION();
   3630     }
   3631     DEFINE_OPCODE(op_jless) {
   3632         /* jless src1(r) src2(r) target(offset)
   3633 
   3634            Checks whether register src1 is less than register src2, as
   3635            with the ECMAScript '<' operator, and then jumps to offset
   3636            target from the current instruction, if and only if the
   3637            result of the comparison is true.
   3638         */
   3639         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   3640         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   3641         int target = vPC[3].u.operand;
   3642 
   3643         bool result = jsLess(callFrame, src1, src2);
   3644         CHECK_FOR_EXCEPTION();
   3645 
   3646         if (result) {
   3647             vPC += target;
   3648             NEXT_INSTRUCTION();
   3649         }
   3650 
   3651         vPC += OPCODE_LENGTH(op_jless);
   3652         NEXT_INSTRUCTION();
   3653     }
   3654     DEFINE_OPCODE(op_jnlesseq) {
   3655         /* jnlesseq src1(r) src2(r) target(offset)
   3656 
   3657            Checks whether register src1 is less than or equal to
   3658            register src2, as with the ECMAScript '<=' operator,
   3659            and then jumps to offset target from the current instruction,
   3660            if and only if theresult of the comparison is false.
   3661         */
   3662         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   3663         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   3664         int target = vPC[3].u.operand;
   3665 
   3666         bool result = jsLessEq(callFrame, src1, src2);
   3667         CHECK_FOR_EXCEPTION();
   3668 
   3669         if (!result) {
   3670             vPC += target;
   3671             NEXT_INSTRUCTION();
   3672         }
   3673 
   3674         vPC += OPCODE_LENGTH(op_jnlesseq);
   3675         NEXT_INSTRUCTION();
   3676     }
   3677     DEFINE_OPCODE(op_jlesseq) {
   3678         /* jlesseq src1(r) src2(r) target(offset)
   3679 
   3680          Checks whether register src1 is less than or equal to
   3681          register src2, as with the ECMAScript '<=' operator,
   3682          and then jumps to offset target from the current instruction,
   3683          if and only if the result of the comparison is true.
   3684          */
   3685         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
   3686         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
   3687         int target = vPC[3].u.operand;
   3688 
   3689         bool result = jsLessEq(callFrame, src1, src2);
   3690         CHECK_FOR_EXCEPTION();
   3691 
   3692         if (result) {
   3693             vPC += target;
   3694             NEXT_INSTRUCTION();
   3695         }
   3696 
   3697         vPC += OPCODE_LENGTH(op_jlesseq);
   3698         NEXT_INSTRUCTION();
   3699     }
   3700     DEFINE_OPCODE(op_switch_imm) {
   3701         /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
   3702 
   3703            Performs a range checked switch on the scrutinee value, using
   3704            the tableIndex-th immediate switch jump table.  If the scrutinee value
   3705            is an immediate number in the range covered by the referenced jump
   3706            table, and the value at jumpTable[scrutinee value] is non-zero, then
   3707            that value is used as the jump offset, otherwise defaultOffset is used.
   3708          */
   3709         int tableIndex = vPC[1].u.operand;
   3710         int defaultOffset = vPC[2].u.operand;
   3711         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
   3712         if (scrutinee.isInt32())
   3713             vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
   3714         else {
   3715             double value;
   3716             int32_t intValue;
   3717             if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
   3718                 vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(intValue, defaultOffset);
   3719             else
   3720                 vPC += defaultOffset;
   3721         }
   3722         NEXT_INSTRUCTION();
   3723     }
   3724     DEFINE_OPCODE(op_switch_char) {
   3725         /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
   3726 
   3727            Performs a range checked switch on the scrutinee value, using
   3728            the tableIndex-th character switch jump table.  If the scrutinee value
   3729            is a single character string in the range covered by the referenced jump
   3730            table, and the value at jumpTable[scrutinee value] is non-zero, then
   3731            that value is used as the jump offset, otherwise defaultOffset is used.
   3732          */
   3733         int tableIndex = vPC[1].u.operand;
   3734         int defaultOffset = vPC[2].u.operand;
   3735         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
   3736         if (!scrutinee.isString())
   3737             vPC += defaultOffset;
   3738         else {
   3739             StringImpl* value = asString(scrutinee)->value(callFrame).impl();
   3740             if (value->length() != 1)
   3741                 vPC += defaultOffset;
   3742             else
   3743                 vPC += codeBlock->characterSwitchJumpTable(tableIndex).offsetForValue(value->characters()[0], defaultOffset);
   3744         }
   3745         NEXT_INSTRUCTION();
   3746     }
   3747     DEFINE_OPCODE(op_switch_string) {
   3748         /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
   3749 
   3750            Performs a sparse hashmap based switch on the value in the scrutinee
   3751            register, using the tableIndex-th string switch jump table.  If the
   3752            scrutinee value is a string that exists as a key in the referenced
   3753            jump table, then the value associated with the string is used as the
   3754            jump offset, otherwise defaultOffset is used.
   3755          */
   3756         int tableIndex = vPC[1].u.operand;
   3757         int defaultOffset = vPC[2].u.operand;
   3758         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
   3759         if (!scrutinee.isString())
   3760             vPC += defaultOffset;
   3761         else
   3762             vPC += codeBlock->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value(callFrame).impl(), defaultOffset);
   3763         NEXT_INSTRUCTION();
   3764     }
   3765     DEFINE_OPCODE(op_new_func) {
   3766         /* new_func dst(r) func(f)
   3767 
   3768            Constructs a new Function instance from function func and
   3769            the current scope chain using the original Function
   3770            constructor, using the rules for function declarations, and
   3771            puts the result in register dst.
   3772         */
   3773         int dst = vPC[1].u.operand;
   3774         int func = vPC[2].u.operand;
   3775         int shouldCheck = vPC[3].u.operand;
   3776         ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
   3777         if (!shouldCheck || !callFrame->r(dst).jsValue())
   3778             callFrame->uncheckedR(dst) = JSValue(codeBlock->functionDecl(func)->make(callFrame, callFrame->scopeChain()));
   3779 
   3780         vPC += OPCODE_LENGTH(op_new_func);
   3781         NEXT_INSTRUCTION();
   3782     }
   3783     DEFINE_OPCODE(op_new_func_exp) {
   3784         /* new_func_exp dst(r) func(f)
   3785 
   3786            Constructs a new Function instance from function func and
   3787            the current scope chain using the original Function
   3788            constructor, using the rules for function expressions, and
   3789            puts the result in register dst.
   3790         */
   3791         int dst = vPC[1].u.operand;
   3792         int funcIndex = vPC[2].u.operand;
   3793 
   3794         ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
   3795         FunctionExecutable* function = codeBlock->functionExpr(funcIndex);
   3796         JSFunction* func = function->make(callFrame, callFrame->scopeChain());
   3797 
   3798         /*
   3799             The Identifier in a FunctionExpression can be referenced from inside
   3800             the FunctionExpression's FunctionBody to allow the function to call
   3801             itself recursively. However, unlike in a FunctionDeclaration, the
   3802             Identifier in a FunctionExpression cannot be referenced from and
   3803             does not affect the scope enclosing the FunctionExpression.
   3804          */
   3805         if (!function->name().isNull()) {
   3806             JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
   3807             func->setScope(*globalData, func->scope()->push(functionScopeObject));
   3808         }
   3809 
   3810         callFrame->uncheckedR(dst) = JSValue(func);
   3811 
   3812         vPC += OPCODE_LENGTH(op_new_func_exp);
   3813         NEXT_INSTRUCTION();
   3814     }
   3815     DEFINE_OPCODE(op_call_eval) {
   3816         /* call_eval func(r) argCount(n) registerOffset(n)
   3817 
   3818            Call a function named "eval" with no explicit "this" value
   3819            (which may therefore be the eval operator). If register
   3820            thisVal is the global object, and register func contains
   3821            that global object's original global eval function, then
   3822            perform the eval operator in local scope (interpreting
   3823            the argument registers as for the "call"
   3824            opcode). Otherwise, act exactly as the "call" opcode would.
   3825          */
   3826 
   3827         int func = vPC[1].u.operand;
   3828         int argCount = vPC[2].u.operand;
   3829         int registerOffset = vPC[3].u.operand;
   3830 
   3831         ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
   3832         JSValue funcVal = callFrame->r(func).jsValue();
   3833 
   3834         Register* newCallFrame = callFrame->registers() + registerOffset;
   3835         Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
   3836         JSValue thisValue = argv[0].jsValue();
   3837         JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject.get();
   3838 
   3839         if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
   3840             JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset);
   3841             if ((exceptionValue = globalData->exception))
   3842                 goto vm_throw;
   3843             functionReturnValue = result;
   3844 
   3845             vPC += OPCODE_LENGTH(op_call_eval);
   3846             NEXT_INSTRUCTION();
   3847         }
   3848 
   3849         // We didn't find the blessed version of eval, so process this
   3850         // instruction as a normal function call.
   3851         // fall through to op_call
   3852     }
   3853     DEFINE_OPCODE(op_call) {
   3854         /* call func(r) argCount(n) registerOffset(n)
   3855 
   3856            Perform a function call.
   3857 
   3858            registerOffset is the distance the callFrame pointer should move
   3859            before the VM initializes the new call frame's header.
   3860 
   3861            dst is where op_ret should store its result.
   3862          */
   3863 
   3864         int func = vPC[1].u.operand;
   3865         int argCount = vPC[2].u.operand;
   3866         int registerOffset = vPC[3].u.operand;
   3867 
   3868         JSValue v = callFrame->r(func).jsValue();
   3869 
   3870         CallData callData;
   3871         CallType callType = getCallData(v, callData);
   3872 
   3873         if (callType == CallTypeJS) {
   3874             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
   3875 
   3876             JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
   3877             if (UNLIKELY(!!error)) {
   3878                 exceptionValue = error;
   3879                 goto vm_throw;
   3880             }
   3881 
   3882             CallFrame* previousCallFrame = callFrame;
   3883             CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
   3884             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
   3885             if (UNLIKELY(!callFrame)) {
   3886                 callFrame = previousCallFrame;
   3887                 exceptionValue = createStackOverflowError(callFrame);
   3888                 goto vm_throw;
   3889             }
   3890 
   3891             callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
   3892             codeBlock = newCodeBlock;
   3893             ASSERT(codeBlock == callFrame->codeBlock());
   3894             vPC = newCodeBlock->instructions().begin();
   3895 
   3896 #if ENABLE(OPCODE_STATS)
   3897             OpcodeStats::resetLastInstruction();
   3898 #endif
   3899 
   3900             NEXT_INSTRUCTION();
   3901         }
   3902 
   3903         if (callType == CallTypeHost) {
   3904             ScopeChainNode* scopeChain = callFrame->scopeChain();
   3905             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
   3906             if (!registerFile->grow(newCallFrame->registers())) {
   3907                 exceptionValue = createStackOverflowError(callFrame);
   3908                 goto vm_throw;
   3909             }
   3910 
   3911             newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call), scopeChain, callFrame, argCount, asObject(v));
   3912 
   3913             JSValue returnValue;
   3914             {
   3915                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
   3916                 returnValue = JSValue::decode(callData.native.function(newCallFrame));
   3917             }
   3918             CHECK_FOR_EXCEPTION();
   3919 
   3920             functionReturnValue = returnValue;
   3921 
   3922             vPC += OPCODE_LENGTH(op_call);
   3923             NEXT_INSTRUCTION();
   3924         }
   3925 
   3926         ASSERT(callType == CallTypeNone);
   3927 
   3928         exceptionValue = createNotAFunctionError(callFrame, v);
   3929         goto vm_throw;
   3930     }
   3931     DEFINE_OPCODE(op_load_varargs) {
   3932         int argCountDst = vPC[1].u.operand;
   3933         int argsOffset = vPC[2].u.operand;
   3934 
   3935         JSValue arguments = callFrame->r(argsOffset).jsValue();
   3936         uint32_t argCount = 0;
   3937         if (!arguments) {
   3938             argCount = (uint32_t)(callFrame->argumentCount());
   3939             argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
   3940             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   3941             Register* newEnd = callFrame->registers() + sizeDelta;
   3942             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   3943                 exceptionValue = createStackOverflowError(callFrame);
   3944                 goto vm_throw;
   3945             }
   3946             ASSERT(!asFunction(callFrame->callee())->isHostFunction());
   3947             int32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
   3948             int32_t inplaceArgs = min(static_cast<int32_t>(argCount), expectedParams);
   3949             int32_t i = 0;
   3950             Register* argStore = callFrame->registers() + argsOffset;
   3951 
   3952             // First step is to copy the "expected" parameters from their normal location relative to the callframe
   3953             for (; i < inplaceArgs; i++)
   3954                 argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams];
   3955             // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
   3956             for (; i < static_cast<int32_t>(argCount); i++)
   3957                 argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - static_cast<int32_t>(argCount) - 1];
   3958         } else if (!arguments.isUndefinedOrNull()) {
   3959             if (!arguments.isObject()) {
   3960                 exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
   3961                 goto vm_throw;
   3962             }
   3963             if (asObject(arguments)->classInfo() == &Arguments::s_info) {
   3964                 Arguments* args = asArguments(arguments);
   3965                 argCount = args->numProvidedArguments(callFrame);
   3966                 argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
   3967                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   3968                 Register* newEnd = callFrame->registers() + sizeDelta;
   3969                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   3970                     exceptionValue = createStackOverflowError(callFrame);
   3971                     goto vm_throw;
   3972                 }
   3973                 args->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
   3974             } else if (isJSArray(&callFrame->globalData(), arguments)) {
   3975                 JSArray* array = asArray(arguments);
   3976                 argCount = array->length();
   3977                 argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
   3978                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   3979                 Register* newEnd = callFrame->registers() + sizeDelta;
   3980                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   3981                     exceptionValue = createStackOverflowError(callFrame);
   3982                     goto vm_throw;
   3983                 }
   3984                 array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
   3985             } else if (asObject(arguments)->inherits(&JSArray::s_info)) {
   3986                 JSObject* argObject = asObject(arguments);
   3987                 argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
   3988                 argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
   3989                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
   3990                 Register* newEnd = callFrame->registers() + sizeDelta;
   3991                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
   3992                     exceptionValue = createStackOverflowError(callFrame);
   3993                     goto vm_throw;
   3994                 }
   3995                 Register* argsBuffer = callFrame->registers() + argsOffset;
   3996                 for (uint32_t i = 0; i < argCount; ++i) {
   3997                     argsBuffer[i] = asObject(arguments)->get(callFrame, i);
   3998                     CHECK_FOR_EXCEPTION();
   3999                 }
   4000             } else {
   4001                 exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
   4002                 goto vm_throw;
   4003             }
   4004         }
   4005         CHECK_FOR_EXCEPTION();
   4006         callFrame->uncheckedR(argCountDst) = Register::withInt(argCount + 1);
   4007         vPC += OPCODE_LENGTH(op_load_varargs);
   4008         NEXT_INSTRUCTION();
   4009     }
   4010     DEFINE_OPCODE(op_call_varargs) {
   4011         /* call_varargs func(r) argCountReg(r) baseRegisterOffset(n)
   4012 
   4013          Perform a function call with a dynamic set of arguments.
   4014 
   4015          registerOffset is the distance the callFrame pointer should move
   4016          before the VM initializes the new call frame's header, excluding
   4017          space for arguments.
   4018 
   4019          dst is where op_ret should store its result.
   4020          */
   4021 
   4022         int func = vPC[1].u.operand;
   4023         int argCountReg = vPC[2].u.operand;
   4024         int registerOffset = vPC[3].u.operand;
   4025 
   4026         JSValue v = callFrame->r(func).jsValue();
   4027         int argCount = callFrame->r(argCountReg).i();
   4028         registerOffset += argCount;
   4029         CallData callData;
   4030         CallType callType = getCallData(v, callData);
   4031 
   4032         if (callType == CallTypeJS) {
   4033             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
   4034 
   4035             JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
   4036             if (UNLIKELY(!!error)) {
   4037                 exceptionValue = error;
   4038                 goto vm_throw;
   4039             }
   4040 
   4041             CallFrame* previousCallFrame = callFrame;
   4042             CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
   4043             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
   4044             if (UNLIKELY(!callFrame)) {
   4045                 callFrame = previousCallFrame;
   4046                 exceptionValue = createStackOverflowError(callFrame);
   4047                 goto vm_throw;
   4048             }
   4049 
   4050             callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
   4051             codeBlock = newCodeBlock;
   4052             ASSERT(codeBlock == callFrame->codeBlock());
   4053             vPC = newCodeBlock->instructions().begin();
   4054 
   4055 #if ENABLE(OPCODE_STATS)
   4056             OpcodeStats::resetLastInstruction();
   4057 #endif
   4058 
   4059             NEXT_INSTRUCTION();
   4060         }
   4061 
   4062         if (callType == CallTypeHost) {
   4063             ScopeChainNode* scopeChain = callFrame->scopeChain();
   4064             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
   4065             if (!registerFile->grow(newCallFrame->registers())) {
   4066                 exceptionValue = createStackOverflowError(callFrame);
   4067                 goto vm_throw;
   4068             }
   4069             newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_varargs), scopeChain, callFrame, argCount, asObject(v));
   4070 
   4071             JSValue returnValue;
   4072             {
   4073                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
   4074                 returnValue = JSValue::decode(callData.native.function(newCallFrame));
   4075             }
   4076             CHECK_FOR_EXCEPTION();
   4077 
   4078             functionReturnValue = returnValue;
   4079 
   4080             vPC += OPCODE_LENGTH(op_call_varargs);
   4081             NEXT_INSTRUCTION();
   4082         }
   4083 
   4084         ASSERT(callType == CallTypeNone);
   4085 
   4086         exceptionValue = createNotAFunctionError(callFrame, v);
   4087         goto vm_throw;
   4088     }
   4089     DEFINE_OPCODE(op_tear_off_activation) {
   4090         /* tear_off_activation activation(r) arguments(r)
   4091 
   4092            Copy locals and named parameters from the register file to the heap.
   4093            Point the bindings in 'activation' and 'arguments' to this new backing
   4094            store. (Note that 'arguments' may not have been created. If created,
   4095            'arguments' already holds a copy of any extra / unnamed parameters.)
   4096 
   4097            This opcode appears before op_ret in functions that require full scope chains.
   4098         */
   4099 
   4100         int activation = vPC[1].u.operand;
   4101         int arguments = vPC[2].u.operand;
   4102         ASSERT(codeBlock->needsFullScopeChain());
   4103         JSValue activationValue = callFrame->r(activation).jsValue();
   4104         if (activationValue) {
   4105             asActivation(activationValue)->copyRegisters(*globalData);
   4106 
   4107             if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
   4108                 if (!codeBlock->isStrictMode())
   4109                     asArguments(argumentsValue)->setActivation(*globalData, asActivation(activationValue));
   4110             }
   4111         } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
   4112             if (!codeBlock->isStrictMode())
   4113                 asArguments(argumentsValue)->copyRegisters(*globalData);
   4114         }
   4115 
   4116         vPC += OPCODE_LENGTH(op_tear_off_activation);
   4117         NEXT_INSTRUCTION();
   4118     }
   4119     DEFINE_OPCODE(op_tear_off_arguments) {
   4120         /* tear_off_arguments arguments(r)
   4121 
   4122            Copy named parameters from the register file to the heap. Point the
   4123            bindings in 'arguments' to this new backing store. (Note that
   4124            'arguments' may not have been created. If created, 'arguments' already
   4125            holds a copy of any extra / unnamed parameters.)
   4126 
   4127            This opcode appears before op_ret in functions that don't require full
   4128            scope chains, but do use 'arguments'.
   4129         */
   4130 
   4131         int src1 = vPC[1].u.operand;
   4132         ASSERT(!codeBlock->needsFullScopeChain() && codeBlock->ownerExecutable()->usesArguments());
   4133 
   4134         if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src1)).jsValue())
   4135             asArguments(arguments)->copyRegisters(*globalData);
   4136 
   4137         vPC += OPCODE_LENGTH(op_tear_off_arguments);
   4138         NEXT_INSTRUCTION();
   4139     }
   4140     DEFINE_OPCODE(op_ret) {
   4141         /* ret result(r)
   4142 
   4143            Return register result as the return value of the current
   4144            function call, writing it into functionReturnValue.
   4145            In addition, unwind one call frame and restore the scope
   4146            chain, code block instruction pointer and register base
   4147            to those of the calling function.
   4148         */
   4149 
   4150         int result = vPC[1].u.operand;
   4151 
   4152         JSValue returnValue = callFrame->r(result).jsValue();
   4153 
   4154         vPC = callFrame->returnVPC();
   4155         callFrame = callFrame->callerFrame();
   4156 
   4157         if (callFrame->hasHostCallFrameFlag())
   4158             return returnValue;
   4159 
   4160         functionReturnValue = returnValue;
   4161         codeBlock = callFrame->codeBlock();
   4162         ASSERT(codeBlock == callFrame->codeBlock());
   4163 
   4164         NEXT_INSTRUCTION();
   4165     }
   4166     DEFINE_OPCODE(op_call_put_result) {
   4167         /* op_call_put_result result(r)
   4168 
   4169            Move call result from functionReturnValue to caller's
   4170            expected return value register.
   4171         */
   4172 
   4173         callFrame->uncheckedR(vPC[1].u.operand) = functionReturnValue;
   4174 
   4175         vPC += OPCODE_LENGTH(op_call_put_result);
   4176         NEXT_INSTRUCTION();
   4177     }
   4178     DEFINE_OPCODE(op_ret_object_or_this) {
   4179         /* ret result(r)
   4180 
   4181            Return register result as the return value of the current
   4182            function call, writing it into the caller's expected return
   4183            value register. In addition, unwind one call frame and
   4184            restore the scope chain, code block instruction pointer and
   4185            register base to those of the calling function.
   4186         */
   4187 
   4188         int result = vPC[1].u.operand;
   4189 
   4190         JSValue returnValue = callFrame->r(result).jsValue();
   4191 
   4192         if (UNLIKELY(!returnValue.isObject()))
   4193             returnValue = callFrame->r(vPC[2].u.operand).jsValue();
   4194 
   4195         vPC = callFrame->returnVPC();
   4196         callFrame = callFrame->callerFrame();
   4197 
   4198         if (callFrame->hasHostCallFrameFlag())
   4199             return returnValue;
   4200 
   4201         functionReturnValue = returnValue;
   4202         codeBlock = callFrame->codeBlock();
   4203         ASSERT(codeBlock == callFrame->codeBlock());
   4204 
   4205         NEXT_INSTRUCTION();
   4206     }
   4207     DEFINE_OPCODE(op_enter) {
   4208         /* enter
   4209 
   4210            Initializes local variables to undefined. If the code block requires
   4211            an activation, enter_with_activation is used instead.
   4212 
   4213            This opcode appears only at the beginning of a code block.
   4214         */
   4215 
   4216         size_t i = 0;
   4217         for (size_t count = codeBlock->m_numVars; i < count; ++i)
   4218             callFrame->uncheckedR(i) = jsUndefined();
   4219 
   4220         vPC += OPCODE_LENGTH(op_enter);
   4221         NEXT_INSTRUCTION();
   4222     }
   4223     DEFINE_OPCODE(op_create_activation) {
   4224         /* create_activation dst(r)
   4225 
   4226            If the activation object for this callframe has not yet been created,
   4227            this creates it and writes it back to dst.
   4228         */
   4229 
   4230         int activationReg = vPC[1].u.operand;
   4231         if (!callFrame->r(activationReg).jsValue()) {
   4232             JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
   4233             callFrame->r(activationReg) = JSValue(activation);
   4234             callFrame->setScopeChain(callFrame->scopeChain()->push(activation));
   4235         }
   4236         vPC += OPCODE_LENGTH(op_create_activation);
   4237         NEXT_INSTRUCTION();
   4238     }
   4239     DEFINE_OPCODE(op_get_callee) {
   4240         /* op_get_callee callee(r)
   4241 
   4242            Move callee into a register.
   4243         */
   4244 
   4245         callFrame->uncheckedR(vPC[1].u.operand) = JSValue(callFrame->callee());
   4246 
   4247         vPC += OPCODE_LENGTH(op_get_callee);
   4248         NEXT_INSTRUCTION();
   4249     }
   4250     DEFINE_OPCODE(op_create_this) {
   4251         /* op_create_this this(r) proto(r)
   4252 
   4253            Allocate an object as 'this', fr use in construction.
   4254 
   4255            This opcode should only be used at the beginning of a code
   4256            block.
   4257         */
   4258 
   4259         int thisRegister = vPC[1].u.operand;
   4260         int protoRegister = vPC[2].u.operand;
   4261 
   4262         JSFunction* constructor = asFunction(callFrame->callee());
   4263 #if !ASSERT_DISABLED
   4264         ConstructData constructData;
   4265         ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
   4266 #endif
   4267 
   4268         Structure* structure;
   4269         JSValue proto = callFrame->r(protoRegister).jsValue();
   4270         if (proto.isObject())
   4271             structure = asObject(proto)->inheritorID(callFrame->globalData());
   4272         else
   4273             structure = constructor->scope()->globalObject->emptyObjectStructure();
   4274         callFrame->uncheckedR(thisRegister) = constructEmptyObject(callFrame, structure);
   4275 
   4276         vPC += OPCODE_LENGTH(op_create_this);
   4277         NEXT_INSTRUCTION();
   4278     }
   4279     DEFINE_OPCODE(op_convert_this) {
   4280         /* convert_this this(r)
   4281 
   4282            Takes the value in the 'this' register, converts it to a
   4283            value that is suitable for use as the 'this' value, and
   4284            stores it in the 'this' register. This opcode is emitted
   4285            to avoid doing the conversion in the caller unnecessarily.
   4286 
   4287            This opcode should only be used at the beginning of a code
   4288            block.
   4289         */
   4290 
   4291         int thisRegister = vPC[1].u.operand;
   4292         JSValue thisVal = callFrame->r(thisRegister).jsValue();
   4293         if (thisVal.needsThisConversion())
   4294             callFrame->uncheckedR(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
   4295 
   4296         vPC += OPCODE_LENGTH(op_convert_this);
   4297         NEXT_INSTRUCTION();
   4298     }
   4299     DEFINE_OPCODE(op_convert_this_strict) {
   4300         /* convert_this_strict this(r)
   4301 
   4302          Takes the value in the 'this' register, and converts it to
   4303          its "this" form if (and only if) "this" is an object with a
   4304          custom this conversion
   4305 
   4306          This opcode should only be used at the beginning of a code
   4307          block.
   4308          */
   4309 
   4310         int thisRegister = vPC[1].u.operand;
   4311         JSValue thisVal = callFrame->r(thisRegister).jsValue();
   4312         if (thisVal.isObject() && thisVal.needsThisConversion())
   4313             callFrame->uncheckedR(thisRegister) = JSValue(thisVal.toStrictThisObject(callFrame));
   4314 
   4315         vPC += OPCODE_LENGTH(op_convert_this_strict);
   4316         NEXT_INSTRUCTION();
   4317     }
   4318     DEFINE_OPCODE(op_init_lazy_reg) {
   4319         /* init_lazy_reg dst(r)
   4320 
   4321            Initialises dst(r) to JSValue().
   4322 
   4323            This opcode appears only at the beginning of a code block.
   4324          */
   4325         int dst = vPC[1].u.operand;
   4326 
   4327         callFrame->uncheckedR(dst) = JSValue();
   4328         vPC += OPCODE_LENGTH(op_init_lazy_reg);
   4329         NEXT_INSTRUCTION();
   4330     }
   4331     DEFINE_OPCODE(op_create_arguments) {
   4332         /* create_arguments dst(r)
   4333 
   4334            Creates the 'arguments' object and places it in both the
   4335            'arguments' call frame slot and the local 'arguments'
   4336            register, if it has not already been initialised.
   4337          */
   4338 
   4339         int dst = vPC[1].u.operand;
   4340 
   4341         if (!callFrame->r(dst).jsValue()) {
   4342             Arguments* arguments = new (globalData) Arguments(callFrame);
   4343             callFrame->uncheckedR(dst) = JSValue(arguments);
   4344             callFrame->uncheckedR(unmodifiedArgumentsRegister(dst)) = JSValue(arguments);
   4345         }
   4346         vPC += OPCODE_LENGTH(op_create_arguments);
   4347         NEXT_INSTRUCTION();
   4348     }
   4349     DEFINE_OPCODE(op_construct) {
   4350         /* construct func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
   4351 
   4352            Invoke register "func" as a constructor. For JS
   4353            functions, the calling convention is exactly as for the
   4354            "call" opcode, except that the "this" value is a newly
   4355            created Object. For native constructors, no "this"
   4356            value is passed. In either case, the argCount and registerOffset
   4357            registers are interpreted as for the "call" opcode.
   4358 
   4359            Register proto must contain the prototype property of
   4360            register func. This is to enable polymorphic inline
   4361            caching of this lookup.
   4362         */
   4363 
   4364         int func = vPC[1].u.operand;
   4365         int argCount = vPC[2].u.operand;
   4366         int registerOffset = vPC[3].u.operand;
   4367 
   4368         JSValue v = callFrame->r(func).jsValue();
   4369 
   4370         ConstructData constructData;
   4371         ConstructType constructType = getConstructData(v, constructData);
   4372 
   4373         if (constructType == ConstructTypeJS) {
   4374             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
   4375 
   4376             JSObject* error = constructData.js.functionExecutable->compileForConstruct(callFrame, callDataScopeChain);
   4377             if (UNLIKELY(!!error)) {
   4378                 exceptionValue = error;
   4379                 goto vm_throw;
   4380             }
   4381 
   4382             CallFrame* previousCallFrame = callFrame;
   4383             CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
   4384             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
   4385             if (UNLIKELY(!callFrame)) {
   4386                 callFrame = previousCallFrame;
   4387                 exceptionValue = createStackOverflowError(callFrame);
   4388                 goto vm_throw;
   4389             }
   4390 
   4391             callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
   4392             codeBlock = newCodeBlock;
   4393             vPC = newCodeBlock->instructions().begin();
   4394 #if ENABLE(OPCODE_STATS)
   4395             OpcodeStats::resetLastInstruction();
   4396 #endif
   4397 
   4398             NEXT_INSTRUCTION();
   4399         }
   4400 
   4401         if (constructType == ConstructTypeHost) {
   4402             ScopeChainNode* scopeChain = callFrame->scopeChain();
   4403             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
   4404             if (!registerFile->grow(newCallFrame->registers())) {
   4405                 exceptionValue = createStackOverflowError(callFrame);
   4406                 goto vm_throw;
   4407             }
   4408             newCallFrame->init(0, vPC + OPCODE_LENGTH(op_construct), scopeChain, callFrame, argCount, asObject(v));
   4409 
   4410             JSValue returnValue;
   4411             {
   4412                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
   4413                 returnValue = JSValue::decode(constructData.native.function(newCallFrame));
   4414             }
   4415             CHECK_FOR_EXCEPTION();
   4416             functionReturnValue = returnValue;
   4417 
   4418             vPC += OPCODE_LENGTH(op_construct);
   4419             NEXT_INSTRUCTION();
   4420         }
   4421 
   4422         ASSERT(constructType == ConstructTypeNone);
   4423 
   4424         exceptionValue = createNotAConstructorError(callFrame, v);
   4425         goto vm_throw;
   4426     }
   4427     DEFINE_OPCODE(op_strcat) {
   4428         /* strcat dst(r) src(r) count(n)
   4429 
   4430            Construct a new String instance using the original
   4431            constructor, and puts the result in register dst.
   4432            The string will be the result of concatenating count
   4433            strings with values taken from registers starting at
   4434            register src.
   4435         */
   4436         int dst = vPC[1].u.operand;
   4437         int src = vPC[2].u.operand;
   4438         int count = vPC[3].u.operand;
   4439 
   4440         callFrame->uncheckedR(dst) = concatenateStrings(callFrame, &callFrame->registers()[src], count);
   4441         CHECK_FOR_EXCEPTION();
   4442         vPC += OPCODE_LENGTH(op_strcat);
   4443 
   4444         NEXT_INSTRUCTION();
   4445     }
   4446     DEFINE_OPCODE(op_to_primitive) {
   4447         int dst = vPC[1].u.operand;
   4448         int src = vPC[2].u.operand;
   4449 
   4450         callFrame->uncheckedR(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame);
   4451         vPC += OPCODE_LENGTH(op_to_primitive);
   4452 
   4453         NEXT_INSTRUCTION();
   4454     }
   4455     DEFINE_OPCODE(op_push_scope) {
   4456         /* push_scope scope(r)
   4457 
   4458            Converts register scope to object, and pushes it onto the top
   4459            of the current scope chain.  The contents of the register scope
   4460            are replaced by the result of toObject conversion of the scope.
   4461         */
   4462         int scope = vPC[1].u.operand;
   4463         JSValue v = callFrame->r(scope).jsValue();
   4464         JSObject* o = v.toObject(callFrame);
   4465         CHECK_FOR_EXCEPTION();
   4466 
   4467         callFrame->uncheckedR(scope) = JSValue(o);
   4468         callFrame->setScopeChain(callFrame->scopeChain()->push(o));
   4469 
   4470         vPC += OPCODE_LENGTH(op_push_scope);
   4471         NEXT_INSTRUCTION();
   4472     }
   4473     DEFINE_OPCODE(op_pop_scope) {
   4474         /* pop_scope
   4475 
   4476            Removes the top item from the current scope chain.
   4477         */
   4478         callFrame->setScopeChain(callFrame->scopeChain()->pop());
   4479 
   4480         vPC += OPCODE_LENGTH(op_pop_scope);
   4481         NEXT_INSTRUCTION();
   4482     }
   4483     DEFINE_OPCODE(op_get_pnames) {
   4484         /* get_pnames dst(r) base(r) i(n) size(n) breakTarget(offset)
   4485 
   4486            Creates a property name list for register base and puts it
   4487            in register dst, initializing i and size for iteration. If
   4488            base is undefined or null, jumps to breakTarget.
   4489         */
   4490         int dst = vPC[1].u.operand;
   4491         int base = vPC[2].u.operand;
   4492         int i = vPC[3].u.operand;
   4493         int size = vPC[4].u.operand;
   4494         int breakTarget = vPC[5].u.operand;
   4495 
   4496         JSValue v = callFrame->r(base).jsValue();
   4497         if (v.isUndefinedOrNull()) {
   4498             vPC += breakTarget;
   4499             NEXT_INSTRUCTION();
   4500         }
   4501 
   4502         JSObject* o = v.toObject(callFrame);
   4503         Structure* structure = o->structure();
   4504         JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
   4505         if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
   4506             jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
   4507 
   4508         callFrame->uncheckedR(dst) = jsPropertyNameIterator;
   4509         callFrame->uncheckedR(base) = JSValue(o);
   4510         callFrame->uncheckedR(i) = Register::withInt(0);
   4511         callFrame->uncheckedR(size) = Register::withInt(jsPropertyNameIterator->size());
   4512         vPC += OPCODE_LENGTH(op_get_pnames);
   4513         NEXT_INSTRUCTION();
   4514     }
   4515     DEFINE_OPCODE(op_next_pname) {
   4516         /* next_pname dst(r) base(r) i(n) size(n) iter(r) target(offset)
   4517 
   4518            Copies the next name from the property name list in
   4519            register iter to dst, then jumps to offset target. If there are no
   4520            names left, invalidates the iterator and continues to the next
   4521            instruction.
   4522         */
   4523         int dst = vPC[1].u.operand;
   4524         int base = vPC[2].u.operand;
   4525         int i = vPC[3].u.operand;
   4526         int size = vPC[4].u.operand;
   4527         int iter = vPC[5].u.operand;
   4528         int target = vPC[6].u.operand;
   4529 
   4530         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
   4531         while (callFrame->r(i).i() != callFrame->r(size).i()) {
   4532             JSValue key = it->get(callFrame, asObject(callFrame->r(base).jsValue()), callFrame->r(i).i());
   4533             CHECK_FOR_EXCEPTION();
   4534             callFrame->uncheckedR(i) = Register::withInt(callFrame->r(i).i() + 1);
   4535             if (key) {
   4536                 CHECK_FOR_TIMEOUT();
   4537                 callFrame->uncheckedR(dst) = key;
   4538                 vPC += target;
   4539                 NEXT_INSTRUCTION();
   4540             }
   4541         }
   4542 
   4543         vPC += OPCODE_LENGTH(op_next_pname);
   4544         NEXT_INSTRUCTION();
   4545     }
   4546     DEFINE_OPCODE(op_jmp_scopes) {
   4547         /* jmp_scopes count(n) target(offset)
   4548 
   4549            Removes the a number of items from the current scope chain
   4550            specified by immediate number count, then jumps to offset
   4551            target.
   4552         */
   4553         int count = vPC[1].u.operand;
   4554         int target = vPC[2].u.operand;
   4555 
   4556         ScopeChainNode* tmp = callFrame->scopeChain();
   4557         while (count--)
   4558             tmp = tmp->pop();
   4559         callFrame->setScopeChain(tmp);
   4560 
   4561         vPC += target;
   4562         NEXT_INSTRUCTION();
   4563     }
   4564 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
   4565     // Appease GCC
   4566     goto *(&&skip_new_scope);
   4567 #endif
   4568     DEFINE_OPCODE(op_push_new_scope) {
   4569         /* new_scope dst(r) property(id) value(r)
   4570 
   4571            Constructs a new StaticScopeObject with property set to value.  That scope
   4572            object is then pushed onto the ScopeChain.  The scope object is then stored
   4573            in dst for GC.
   4574          */
   4575         callFrame->setScopeChain(createExceptionScope(callFrame, vPC));
   4576 
   4577         vPC += OPCODE_LENGTH(op_push_new_scope);
   4578         NEXT_INSTRUCTION();
   4579     }
   4580 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
   4581     skip_new_scope:
   4582 #endif
   4583     DEFINE_OPCODE(op_catch) {
   4584         /* catch ex(r)
   4585 
   4586            Retrieves the VM's current exception and puts it in register
   4587            ex. This is only valid after an exception has been raised,
   4588            and usually forms the beginning of an exception handler.
   4589         */
   4590         ASSERT(exceptionValue);
   4591         ASSERT(!globalData->exception);
   4592         int ex = vPC[1].u.operand;
   4593         callFrame->uncheckedR(ex) = exceptionValue;
   4594         exceptionValue = JSValue();
   4595 
   4596         vPC += OPCODE_LENGTH(op_catch);
   4597         NEXT_INSTRUCTION();
   4598     }
   4599     DEFINE_OPCODE(op_throw) {
   4600         /* throw ex(r)
   4601 
   4602            Throws register ex as an exception. This involves three
   4603            steps: first, it is set as the current exception in the
   4604            VM's internal state, then the stack is unwound until an
   4605            exception handler or a native code boundary is found, and
   4606            then control resumes at the exception handler if any or
   4607            else the script returns control to the nearest native caller.
   4608         */
   4609 
   4610         int ex = vPC[1].u.operand;
   4611         exceptionValue = callFrame->r(ex).jsValue();
   4612 
   4613         handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin());
   4614         if (!handler)
   4615             return throwError(callFrame, exceptionValue);
   4616 
   4617         codeBlock = callFrame->codeBlock();
   4618         vPC = codeBlock->instructions().begin() + handler->target;
   4619         NEXT_INSTRUCTION();
   4620     }
   4621     DEFINE_OPCODE(op_throw_reference_error) {
   4622         /* op_throw_reference_error message(k)
   4623 
   4624            Constructs a new reference Error instance using the
   4625            original constructor, using constant message as the
   4626            message string. The result is thrown.
   4627         */
   4628         UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame);
   4629         exceptionValue = JSValue(createReferenceError(callFrame, message));
   4630         goto vm_throw;
   4631     }
   4632     DEFINE_OPCODE(op_end) {
   4633         /* end result(r)
   4634 
   4635            Return register result as the value of a global or eval
   4636            program. Return control to the calling native code.
   4637         */
   4638 
   4639         int result = vPC[1].u.operand;
   4640         return callFrame->r(result).jsValue();
   4641     }
   4642     DEFINE_OPCODE(op_put_getter) {
   4643         /* put_getter base(r) property(id) function(r)
   4644 
   4645            Sets register function on register base as the getter named
   4646            by identifier property. Base and function are assumed to be
   4647            objects as this op should only be used for getters defined
   4648            in object literal form.
   4649 
   4650            Unlike many opcodes, this one does not write any output to
   4651            the register file.
   4652         */
   4653         int base = vPC[1].u.operand;
   4654         int property = vPC[2].u.operand;
   4655         int function = vPC[3].u.operand;
   4656 
   4657         ASSERT(callFrame->r(base).jsValue().isObject());
   4658         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
   4659         Identifier& ident = codeBlock->identifier(property);
   4660         ASSERT(callFrame->r(function).jsValue().isObject());
   4661         baseObj->defineGetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
   4662 
   4663         vPC += OPCODE_LENGTH(op_put_getter);
   4664         NEXT_INSTRUCTION();
   4665     }
   4666     DEFINE_OPCODE(op_put_setter) {
   4667         /* put_setter base(r) property(id) function(r)
   4668 
   4669            Sets register function on register base as the setter named
   4670            by identifier property. Base and function are assumed to be
   4671            objects as this op should only be used for setters defined
   4672            in object literal form.
   4673 
   4674            Unlike many opcodes, this one does not write any output to
   4675            the register file.
   4676         */
   4677         int base = vPC[1].u.operand;
   4678         int property = vPC[2].u.operand;
   4679         int function = vPC[3].u.operand;
   4680 
   4681         ASSERT(callFrame->r(base).jsValue().isObject());
   4682         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
   4683         Identifier& ident = codeBlock->identifier(property);
   4684         ASSERT(callFrame->r(function).jsValue().isObject());
   4685         baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()), 0);
   4686 
   4687         vPC += OPCODE_LENGTH(op_put_setter);
   4688         NEXT_INSTRUCTION();
   4689     }
   4690     DEFINE_OPCODE(op_method_check) {
   4691         vPC++;
   4692         NEXT_INSTRUCTION();
   4693     }
   4694     DEFINE_OPCODE(op_jsr) {
   4695         /* jsr retAddrDst(r) target(offset)
   4696 
   4697            Places the address of the next instruction into the retAddrDst
   4698            register and jumps to offset target from the current instruction.
   4699         */
   4700         int retAddrDst = vPC[1].u.operand;
   4701         int target = vPC[2].u.operand;
   4702         callFrame->r(retAddrDst) = vPC + OPCODE_LENGTH(op_jsr);
   4703 
   4704         vPC += target;
   4705         NEXT_INSTRUCTION();
   4706     }
   4707     DEFINE_OPCODE(op_sret) {
   4708         /* sret retAddrSrc(r)
   4709 
   4710          Jumps to the address stored in the retAddrSrc register. This
   4711          differs from op_jmp because the target address is stored in a
   4712          register, not as an immediate.
   4713         */
   4714         int retAddrSrc = vPC[1].u.operand;
   4715         vPC = callFrame->r(retAddrSrc).vPC();
   4716         NEXT_INSTRUCTION();
   4717     }
   4718     DEFINE_OPCODE(op_debug) {
   4719         /* debug debugHookID(n) firstLine(n) lastLine(n)
   4720 
   4721          Notifies the debugger of the current state of execution. This opcode
   4722          is only generated while the debugger is attached.
   4723         */
   4724         int debugHookID = vPC[1].u.operand;
   4725         int firstLine = vPC[2].u.operand;
   4726         int lastLine = vPC[3].u.operand;
   4727 
   4728         debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
   4729 
   4730         vPC += OPCODE_LENGTH(op_debug);
   4731         NEXT_INSTRUCTION();
   4732     }
   4733     DEFINE_OPCODE(op_profile_will_call) {
   4734         /* op_profile_will_call function(r)
   4735 
   4736          Notifies the profiler of the beginning of a function call. This opcode
   4737          is only generated if developer tools are enabled.
   4738         */
   4739         int function = vPC[1].u.operand;
   4740 
   4741         if (*enabledProfilerReference)
   4742             (*enabledProfilerReference)->willExecute(callFrame, callFrame->r(function).jsValue());
   4743 
   4744         vPC += OPCODE_LENGTH(op_profile_will_call);
   4745         NEXT_INSTRUCTION();
   4746     }
   4747     DEFINE_OPCODE(op_profile_did_call) {
   4748         /* op_profile_did_call function(r)
   4749 
   4750          Notifies the profiler of the end of a function call. This opcode
   4751          is only generated if developer tools are enabled.
   4752         */
   4753         int function = vPC[1].u.operand;
   4754 
   4755         if (*enabledProfilerReference)
   4756             (*enabledProfilerReference)->didExecute(callFrame, callFrame->r(function).jsValue());
   4757 
   4758         vPC += OPCODE_LENGTH(op_profile_did_call);
   4759         NEXT_INSTRUCTION();
   4760     }
   4761     vm_throw: {
   4762         globalData->exception = JSValue();
   4763         if (!tickCount) {
   4764             // The exceptionValue is a lie! (GCC produces bad code for reasons I
   4765             // cannot fathom if we don't assign to the exceptionValue before branching)
   4766             exceptionValue = createInterruptedExecutionException(globalData);
   4767         }
   4768         JSGlobalObject* globalObject = callFrame->lexicalGlobalObject();
   4769         handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin());
   4770         if (!handler) {
   4771             // Can't use the callframe at this point as the scopechain, etc have
   4772             // been released.
   4773             return throwError(globalObject->globalExec(), exceptionValue);
   4774         }
   4775 
   4776         codeBlock = callFrame->codeBlock();
   4777         vPC = codeBlock->instructions().begin() + handler->target;
   4778         NEXT_INSTRUCTION();
   4779     }
   4780     }
   4781 #if !ENABLE(COMPUTED_GOTO_INTERPRETER)
   4782     } // iterator loop ends
   4783 #endif
   4784     #undef NEXT_INSTRUCTION
   4785     #undef DEFINE_OPCODE
   4786     #undef CHECK_FOR_EXCEPTION
   4787     #undef CHECK_FOR_TIMEOUT
   4788 #endif // ENABLE(INTERPRETER)
   4789 }
   4790 
   4791 JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
   4792 {
   4793     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
   4794     if (!functionCallFrame)
   4795         return jsNull();
   4796 
   4797     CodeBlock* codeBlock = functionCallFrame->codeBlock();
   4798     if (codeBlock->usesArguments()) {
   4799         ASSERT(codeBlock->codeType() == FunctionCode);
   4800         int argumentsRegister = codeBlock->argumentsRegister();
   4801         int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
   4802         if (JSValue arguments = functionCallFrame->uncheckedR(argumentsRegister).jsValue())
   4803             return arguments;
   4804         JSValue arguments = JSValue(new (callFrame) Arguments(functionCallFrame));
   4805         functionCallFrame->r(argumentsRegister) = arguments;
   4806         functionCallFrame->r(realArgumentsRegister) = arguments;
   4807         return arguments;
   4808     }
   4809 
   4810     Arguments* arguments = new (functionCallFrame) Arguments(functionCallFrame);
   4811     arguments->copyRegisters(functionCallFrame->globalData());
   4812     return arguments;
   4813 }
   4814 
   4815 JSValue Interpreter::retrieveCaller(CallFrame* callFrame, JSFunction* function) const
   4816 {
   4817     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
   4818     if (!functionCallFrame)
   4819         return jsNull();
   4820 
   4821     CallFrame* callerFrame = functionCallFrame->callerFrame();
   4822     if (callerFrame->hasHostCallFrameFlag())
   4823         return jsNull();
   4824 
   4825     JSValue caller = callerFrame->callee();
   4826     if (!caller)
   4827         return jsNull();
   4828 
   4829     return caller;
   4830 }
   4831 
   4832 void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const
   4833 {
   4834     function = JSValue();
   4835     lineNumber = -1;
   4836     sourceURL = UString();
   4837 
   4838     CallFrame* callerFrame = callFrame->callerFrame();
   4839     if (callerFrame->hasHostCallFrameFlag())
   4840         return;
   4841 
   4842     CodeBlock* callerCodeBlock = callerFrame->codeBlock();
   4843     if (!callerCodeBlock)
   4844         return;
   4845     unsigned bytecodeOffset = 0;
   4846 #if ENABLE(INTERPRETER)
   4847     if (!callerFrame->globalData().canUseJIT())
   4848         bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
   4849 #if ENABLE(JIT)
   4850     else
   4851         bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
   4852 #endif
   4853 #else
   4854     bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
   4855 #endif
   4856     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
   4857     sourceID = callerCodeBlock->ownerExecutable()->sourceID();
   4858     sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
   4859     function = callerFrame->callee();
   4860 }
   4861 
   4862 CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, JSFunction* function)
   4863 {
   4864     for (CallFrame* candidate = callFrame; candidate; candidate = candidate->callerFrame()->removeHostCallFrameFlag()) {
   4865         if (candidate->callee() == function)
   4866             return candidate;
   4867     }
   4868     return 0;
   4869 }
   4870 
   4871 void Interpreter::enableSampler()
   4872 {
   4873 #if ENABLE(OPCODE_SAMPLING)
   4874     if (!m_sampler) {
   4875         m_sampler.set(new SamplingTool(this));
   4876         m_sampler->setup();
   4877     }
   4878 #endif
   4879 }
   4880 void Interpreter::dumpSampleData(ExecState* exec)
   4881 {
   4882 #if ENABLE(OPCODE_SAMPLING)
   4883     if (m_sampler)
   4884         m_sampler->dump(exec);
   4885 #else
   4886     UNUSED_PARAM(exec);
   4887 #endif
   4888 }
   4889 void Interpreter::startSampling()
   4890 {
   4891 #if ENABLE(SAMPLING_THREAD)
   4892     if (!m_sampleEntryDepth)
   4893         SamplingThread::start();
   4894 
   4895     m_sampleEntryDepth++;
   4896 #endif
   4897 }
   4898 void Interpreter::stopSampling()
   4899 {
   4900 #if ENABLE(SAMPLING_THREAD)
   4901     m_sampleEntryDepth--;
   4902     if (!m_sampleEntryDepth)
   4903         SamplingThread::stop();
   4904 #endif
   4905 }
   4906 
   4907 } // namespace JSC
   4908