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