Ignore:
Timestamp:
Feb 22, 2009, 3:26:07 PM (16 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

2009-02-22 Geoffrey Garen <[email protected]>

Reviewed by Sam Weinig.

Next step in splitting JIT functionality out of the Interpreter class:
Created a JITStubs class and renamed Interpreter::cti_* to JITStubs::cti_*.


Also, moved timeout checking into its own class, located in JSGlobalData,
so both the Interpreter and the JIT could have access to it.

  • JavaScriptCore.exp:
  • JavaScriptCore.pri:
  • JavaScriptCore.scons:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • JavaScriptCoreSources.bkl:
  • interpreter/CallFrame.h:
  • interpreter/Interpreter.cpp: (JSC::Interpreter::Interpreter): (JSC::Interpreter::privateExecute):
  • interpreter/Interpreter.h:
  • interpreter/Register.h:
  • jit/JIT.cpp: (JSC::): (JSC::JIT::emitTimeoutCheck): (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases): (JSC::JIT::privateCompile): (JSC::JIT::privateCompileCTIMachineTrampolines):
  • jit/JIT.h:
  • jit/JITArithmetic.cpp: (JSC::JIT::compileFastArithSlow_op_lshift): (JSC::JIT::compileFastArithSlow_op_rshift): (JSC::JIT::compileFastArithSlow_op_bitand): (JSC::JIT::compileFastArithSlow_op_mod): (JSC::JIT::compileFastArith_op_mod): (JSC::JIT::compileFastArithSlow_op_post_inc): (JSC::JIT::compileFastArithSlow_op_post_dec): (JSC::JIT::compileFastArithSlow_op_pre_inc): (JSC::JIT::compileFastArithSlow_op_pre_dec): (JSC::JIT::compileFastArith_op_add): (JSC::JIT::compileFastArith_op_mul): (JSC::JIT::compileFastArith_op_sub): (JSC::JIT::compileBinaryArithOpSlowCase): (JSC::JIT::compileFastArithSlow_op_add): (JSC::JIT::compileFastArithSlow_op_mul):
  • jit/JITCall.cpp: (JSC::JIT::compileOpCall): (JSC::JIT::compileOpCallSlowCase):
  • jit/JITPropertyAccess.cpp: (JSC::JIT::compileGetByIdHotPath): (JSC::JIT::compilePutByIdHotPath): (JSC::JIT::compileGetByIdSlowCase): (JSC::JIT::compilePutByIdSlowCase): (JSC::JIT::privateCompilePutByIdTransition): (JSC::JIT::patchGetByIdSelf): (JSC::JIT::patchPutByIdReplace): (JSC::JIT::privateCompilePatchGetArrayLength): (JSC::JIT::privateCompileGetByIdSelf): (JSC::JIT::privateCompileGetByIdProto): (JSC::JIT::privateCompileGetByIdChain): (JSC::JIT::privateCompilePutByIdReplace):
  • jit/JITStubs.cpp: (JSC::JITStubs::tryCachePutByID): (JSC::JITStubs::tryCacheGetByID): (JSC::JITStubs::cti_op_convert_this): (JSC::JITStubs::cti_op_end): (JSC::JITStubs::cti_op_add): (JSC::JITStubs::cti_op_pre_inc): (JSC::JITStubs::cti_timeout_check): (JSC::JITStubs::cti_register_file_check): (JSC::JITStubs::cti_op_loop_if_less): (JSC::JITStubs::cti_op_loop_if_lesseq): (JSC::JITStubs::cti_op_new_object): (JSC::JITStubs::cti_op_put_by_id_generic): (JSC::JITStubs::cti_op_get_by_id_generic): (JSC::JITStubs::cti_op_put_by_id): (JSC::JITStubs::cti_op_put_by_id_second): (JSC::JITStubs::cti_op_put_by_id_fail): (JSC::JITStubs::cti_op_get_by_id): (JSC::JITStubs::cti_op_get_by_id_second): (JSC::JITStubs::cti_op_get_by_id_self_fail): (JSC::JITStubs::cti_op_get_by_id_proto_list): (JSC::JITStubs::cti_op_get_by_id_proto_list_full): (JSC::JITStubs::cti_op_get_by_id_proto_fail): (JSC::JITStubs::cti_op_get_by_id_array_fail): (JSC::JITStubs::cti_op_get_by_id_string_fail): (JSC::JITStubs::cti_op_instanceof): (JSC::JITStubs::cti_op_del_by_id): (JSC::JITStubs::cti_op_mul): (JSC::JITStubs::cti_op_new_func): (JSC::JITStubs::cti_op_call_JSFunction): (JSC::JITStubs::cti_op_call_arityCheck): (JSC::JITStubs::cti_vm_dontLazyLinkCall): (JSC::JITStubs::cti_vm_lazyLinkCall): (JSC::JITStubs::cti_op_push_activation): (JSC::JITStubs::cti_op_call_NotJSFunction): (JSC::JITStubs::cti_op_create_arguments): (JSC::JITStubs::cti_op_create_arguments_no_params): (JSC::JITStubs::cti_op_tear_off_activation): (JSC::JITStubs::cti_op_tear_off_arguments): (JSC::JITStubs::cti_op_profile_will_call): (JSC::JITStubs::cti_op_profile_did_call): (JSC::JITStubs::cti_op_ret_scopeChain): (JSC::JITStubs::cti_op_new_array): (JSC::JITStubs::cti_op_resolve): (JSC::JITStubs::cti_op_construct_JSConstruct): (JSC::JITStubs::cti_op_construct_NotJSConstruct): (JSC::JITStubs::cti_op_get_by_val): (JSC::JITStubs::cti_op_get_by_val_byte_array): (JSC::JITStubs::cti_op_resolve_func): (JSC::JITStubs::cti_op_sub): (JSC::JITStubs::cti_op_put_by_val): (JSC::JITStubs::cti_op_put_by_val_array): (JSC::JITStubs::cti_op_put_by_val_byte_array): (JSC::JITStubs::cti_op_lesseq): (JSC::JITStubs::cti_op_loop_if_true): (JSC::JITStubs::cti_op_negate): (JSC::JITStubs::cti_op_resolve_base): (JSC::JITStubs::cti_op_resolve_skip): (JSC::JITStubs::cti_op_resolve_global): (JSC::JITStubs::cti_op_div): (JSC::JITStubs::cti_op_pre_dec): (JSC::JITStubs::cti_op_jless): (JSC::JITStubs::cti_op_not): (JSC::JITStubs::cti_op_jtrue): (JSC::JITStubs::cti_op_post_inc): (JSC::JITStubs::cti_op_eq): (JSC::JITStubs::cti_op_lshift): (JSC::JITStubs::cti_op_bitand): (JSC::JITStubs::cti_op_rshift): (JSC::JITStubs::cti_op_bitnot): (JSC::JITStubs::cti_op_resolve_with_base): (JSC::JITStubs::cti_op_new_func_exp): (JSC::JITStubs::cti_op_mod): (JSC::JITStubs::cti_op_less): (JSC::JITStubs::cti_op_neq): (JSC::JITStubs::cti_op_post_dec): (JSC::JITStubs::cti_op_urshift): (JSC::JITStubs::cti_op_bitxor): (JSC::JITStubs::cti_op_new_regexp): (JSC::JITStubs::cti_op_bitor): (JSC::JITStubs::cti_op_call_eval): (JSC::JITStubs::cti_op_throw): (JSC::JITStubs::cti_op_get_pnames): (JSC::JITStubs::cti_op_next_pname): (JSC::JITStubs::cti_op_push_scope): (JSC::JITStubs::cti_op_pop_scope): (JSC::JITStubs::cti_op_typeof): (JSC::JITStubs::cti_op_is_undefined): (JSC::JITStubs::cti_op_is_boolean): (JSC::JITStubs::cti_op_is_number): (JSC::JITStubs::cti_op_is_string): (JSC::JITStubs::cti_op_is_object): (JSC::JITStubs::cti_op_is_function): (JSC::JITStubs::cti_op_stricteq): (JSC::JITStubs::cti_op_nstricteq): (JSC::JITStubs::cti_op_to_jsnumber): (JSC::JITStubs::cti_op_in): (JSC::JITStubs::cti_op_push_new_scope): (JSC::JITStubs::cti_op_jmp_scopes): (JSC::JITStubs::cti_op_put_by_index): (JSC::JITStubs::cti_op_switch_imm): (JSC::JITStubs::cti_op_switch_char): (JSC::JITStubs::cti_op_switch_string): (JSC::JITStubs::cti_op_del_by_val): (JSC::JITStubs::cti_op_put_getter): (JSC::JITStubs::cti_op_put_setter): (JSC::JITStubs::cti_op_new_error): (JSC::JITStubs::cti_op_debug): (JSC::JITStubs::cti_vm_throw):
  • jit/JITStubs.h: (JSC::):
  • runtime/JSFunction.h:
  • runtime/JSGlobalData.cpp: (JSC::JSGlobalData::JSGlobalData):
  • runtime/JSGlobalData.h:
  • runtime/JSGlobalObject.cpp:
  • runtime/JSGlobalObject.h:
  • runtime/TimeoutChecker.cpp: Copied from interpreter/Interpreter.cpp. (JSC::TimeoutChecker::TimeoutChecker): (JSC::TimeoutChecker::reset): (JSC::TimeoutChecker::didTimeOut):
  • runtime/TimeoutChecker.h: Copied from interpreter/Interpreter.h. (JSC::TimeoutChecker::setTimeoutInterval): (JSC::TimeoutChecker::ticksUntilNextCheck): (JSC::TimeoutChecker::start): (JSC::TimeoutChecker::stop):

WebCore:

2009-02-20 Geoffrey Garen <[email protected]>

Reviewed by Sam Weinig.

Updated for JavaScriptCore changes to timeout checking.

  • bindings/js/JSCustomPositionCallback.cpp: (WebCore::JSCustomPositionCallback::handleEvent):
  • bindings/js/JSCustomPositionErrorCallback.cpp: (WebCore::JSCustomPositionErrorCallback::handleEvent):
  • bindings/js/JSCustomSQLStatementCallback.cpp: (WebCore::JSCustomSQLStatementCallback::handleEvent):
  • bindings/js/JSCustomSQLStatementErrorCallback.cpp: (WebCore::JSCustomSQLStatementErrorCallback::handleEvent):
  • bindings/js/JSCustomSQLTransactionCallback.cpp: (WebCore::JSCustomSQLTransactionCallback::handleEvent):
  • bindings/js/JSCustomSQLTransactionErrorCallback.cpp: (WebCore::JSCustomSQLTransactionErrorCallback::handleEvent):
  • bindings/js/JSCustomVoidCallback.cpp: (WebCore::JSCustomVoidCallback::handleEvent):
  • bindings/js/JSCustomXPathNSResolver.cpp: (WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):
  • bindings/js/JSDOMWindowBase.cpp: (WebCore::JSDOMWindowBase::JSDOMWindowBase): (WebCore::JSDOMWindowBase::commonJSGlobalData):
  • bindings/js/JSEventListener.cpp: (WebCore::JSAbstractEventListener::handleEvent):
  • bindings/js/ScheduledAction.cpp: (WebCore::ScheduledAction::executeFunctionInContext):
  • bindings/js/ScriptController.cpp: (WebCore::ScriptController::evaluate):
  • bindings/js/WorkerScriptController.cpp: (WebCore::WorkerScriptController::evaluate): (WebCore::WorkerScriptController::forbidExecution):
  • bindings/objc/WebScriptObject.mm: (-[WebScriptObject callWebScriptMethod:withArguments:]): (-[WebScriptObject evaluateWebScript:]):
  • bridge/NP_jsobject.cpp: (_NPN_InvokeDefault): (_NPN_Invoke): (_NPN_Evaluate): (_NPN_Construct):
  • bridge/jni/jni_jsobject.mm: (JavaJSObject::call): (JavaJSObject::eval):
File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/TimeoutChecker.cpp

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