Changeset 36244 in webkit for trunk/JavaScriptCore/VM/Machine.cpp


Ignore:
Timestamp:
Sep 6, 2008, 10:44:58 PM (17 years ago)
Author:
[email protected]
Message:

Merge squirrelfish-extreme to trunk.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/VM/Machine.cpp

    r36081 r36244  
    7676namespace KJS {
    7777
    78 // Default number of ticks before a timeout check should be done.
    79 static const int initialTickCountThreshold = 255;
    80 
    8178// Preferred number of milliseconds between each timeout check
    8279static const int preferredScriptCheckTimeInterval = 1000;
     
    307304}
    308305
    309 static void NEVER_INLINE resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
    310 {
    311     int dst = (vPC + 1)->u.operand;
    312     int property = (vPC + 2)->u.operand;
    313 
     306ALWAYS_INLINE static JSValue* inlineResolveBase(ExecState* exec, Identifier& property, ScopeChainNode* scopeChain)
     307{
    314308    ScopeChainIterator iter = scopeChain->begin();
    315309    ScopeChainIterator next = iter;
     
    319313
    320314    PropertySlot slot;
    321     Identifier& ident = codeBlock->identifiers[property];
    322315    JSObject* base;
    323316    while (true) {
    324317        base = *iter;
    325         if (next == end || base->getPropertySlot(exec, ident, slot)) {
    326             r[dst] = base;
    327             return;
    328         }
     318        if (next == end || base->getPropertySlot(exec, property, slot))
     319            return base;
     320
    329321        iter = next;
    330322        ++next;
    331323    }
     324
     325    ASSERT_NOT_REACHED();
     326    return 0;
     327}
     328
     329NEVER_INLINE static void resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
     330{
     331    int dst = (vPC + 1)->u.operand;
     332    int property = (vPC + 2)->u.operand;
     333    r[dst] = inlineResolveBase(exec, codeBlock->identifiers[property], scopeChain);
    332334}
    333335
     
    466468        (*it) = jsUndefined();
    467469
    468 
    469470    for (size_t i = 0; i < newCodeBlock->constantRegisters.size(); ++i)
    470471        r[i] = newCodeBlock->constantRegisters[i];
     
    529530Machine::Machine()
    530531    : m_sampler(0)
     532#if ENABLE(CTI)
     533    , m_ctiArrayLengthTrampoline(0)
     534    , m_ctiStringLengthTrampoline(0)
     535    , m_jitCodeBuffer(new JITCodeBuffer(1024 * 1024))
     536#endif
    531537    , m_reentryDepth(0)
    532538    , m_timeoutTime(0)
     
    548554    m_jsStringVptr = jsString->vptr();
    549555    static_cast<JSCell*>(jsString)->~JSCell();
     556
     557    JSFunction* jsFunction = new (storage) JSFunction(StructureID::create(jsNull()));
     558    m_jsFunctionVptr = jsFunction->vptr();
     559    static_cast<JSCell*>(jsFunction)->~JSCell();
    550560   
    551561    fastFree(storage);
     562}
     563
     564Machine::~Machine()
     565{
     566#if ENABLE(CTI)
     567    if (m_ctiArrayLengthTrampoline)
     568        fastFree(m_ctiArrayLengthTrampoline);
     569    if (m_ctiStringLengthTrampoline)
     570        fastFree(m_ctiStringLengthTrampoline);
     571#endif
    552572}
    553573
     
    627647#endif
    628648
    629 #if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
     649//#if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
    630650
    631651bool Machine::isOpcode(Opcode opcode)
     
    640660}
    641661
    642 #endif
     662//#endif
    643663
    644664NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r)
     
    686706{
    687707    // Set up the exception object
    688 
     708   
    689709    if (exceptionValue->isObject()) {
    690710        JSObject* exception = static_cast<JSObject*>(exceptionValue);
     
    793813
    794814    m_reentryDepth++;
     815#if ENABLE(CTI)
     816    if (!codeBlock->ctiCode)
     817        CTI::compile(this, exec, codeBlock);
     818    JSValue* result = CTI::execute(codeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
     819#else
    795820    JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
     821#endif
    796822    m_reentryDepth--;
    797823
     
    853879
    854880    m_reentryDepth++;
     881#if ENABLE(CTI)
     882    if (!newCodeBlock->ctiCode)
     883        CTI::compile(this, exec, newCodeBlock);
     884    JSValue* result = CTI::execute(newCodeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
     885#else
    855886    JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
     887#endif
    856888    m_reentryDepth--;
    857889
     
    931963
    932964    m_reentryDepth++;
     965#if ENABLE(CTI)
     966    if (!codeBlock->ctiCode)
     967        CTI::compile(this, exec, codeBlock);
     968    JSValue* result = CTI::execute(codeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
     969#else
    933970    JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
     971#endif
    934972    m_reentryDepth--;
    935973
     
    949987}
    950988
    951 NEVER_INLINE void Machine::debug(ExecState* exec, const Instruction* vPC, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r)
    952 {
    953     int debugHookID = (++vPC)->u.operand;
    954     int firstLine = (++vPC)->u.operand;
    955     int lastLine = (++vPC)->u.operand;
    956 
     989NEVER_INLINE void Machine::debug(ExecState* exec, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r, DebugHookID debugHookID, int firstLine, int lastLine)
     990{
    957991    Debugger* debugger = exec->dynamicGlobalObject()->debugger();
    958992    if (!debugger)
     
    961995    DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, 0);
    962996
    963     switch((DebugHookID)debugHookID) {
    964     case DidEnterCallFrame: {
    965         debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
    966         return;
    967     }
    968     case WillLeaveCallFrame: {
    969         debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
    970         return;
    971     }
    972     case WillExecuteStatement: {
    973         debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
    974         return;
    975     }
    976     case WillExecuteProgram: {
    977         debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
    978         return;
    979     }
    980     case DidExecuteProgram: {
    981         debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
    982         return;
    983     }
    984     case DidReachBreakpoint: {
    985         debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
    986         return;
    987     }
     997    switch (debugHookID) {
     998        case DidEnterCallFrame:
     999            debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
     1000            return;
     1001        case WillLeaveCallFrame:
     1002            debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
     1003            return;
     1004        case WillExecuteStatement:
     1005            debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
     1006            return;
     1007        case WillExecuteProgram:
     1008            debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
     1009            return;
     1010        case DidExecuteProgram:
     1011            debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
     1012            return;
     1013        case DidReachBreakpoint:
     1014            debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
     1015            return;
    9881016    }
    9891017}
     
    10741102}
    10751103
    1076 static int32_t offsetForStringSwitch(StringJumpTable& jumpTable, JSValue* scrutinee, int32_t defaultOffset) {
    1077     StringJumpTable::const_iterator end = jumpTable.end();
    1078     UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
    1079     StringJumpTable::const_iterator loc = jumpTable.find(value);
    1080     if (loc == end)
    1081         return defaultOffset;
    1082     return loc->second;
    1083 }
    1084 
    10851104static NEVER_INLINE ScopeChainNode* createExceptionScope(ExecState* exec, CodeBlock* codeBlock, const Instruction* vPC, Register* r, ScopeChainNode* scopeChain)
    10861105{
     
    12361255        ASSERT(slot.slotBase()->isObject());
    12371256
    1238         JSObject* slotBaseObject = static_cast<JSObject*>(slot.slotBase());
     1257        JSObject* baseObject = static_cast<JSObject*>(slot.slotBase());
    12391258
    12401259        // Heavy access to a prototype is a good indication that it's not being
    12411260        // used as a dictionary.
    1242         if (slotBaseObject->structureID()->isDictionary()) {
    1243             RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(slotBaseObject->structureID());
    1244             slotBaseObject->setStructureID(transition.release());
     1261        if (baseObject->structureID()->isDictionary()) {
     1262            RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(baseObject->structureID());
     1263            baseObject->setStructureID(transition.release());
    12451264            static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
    12461265        }
    12471266
    12481267        vPC[0] = getOpcode(op_get_by_id_proto);
    1249         vPC[5] = slotBaseObject->structureID();
     1268        vPC[5] = baseObject->structureID();
    12501269        vPC[6] = slot.cachedOffset();
    12511270
     
    12591278        JSValue* v = o->structureID()->prototype();
    12601279
    1261         // If we didn't find slotBase in baseValue's prototype chain, then baseValue
     1280        // If we didn't find base in baseValue's prototype chain, then baseValue
    12621281        // must be a proxy for another object.
    12631282        if (v->isNull()) {
     
    13181337    }
    13191338
     1339#if ENABLE(CTI)
     1340    // Currently with CTI enabled we never interpret functions
     1341    ASSERT_NOT_REACHED();
     1342#endif
     1343
    13201344    JSValue* exceptionValue = 0;
    13211345    Instruction* handlerVPC = 0;
     
    13271351
    13281352#define VM_CHECK_EXCEPTION() \
    1329      do { \
     1353    do { \
    13301354        if (UNLIKELY(exec->hadException())) { \
    13311355            exceptionValue = exec->exception(); \
     
    13441368        tickCount = m_ticksUntilNextTimeoutCheck; \
    13451369    }
    1346    
     1370
    13471371#if HAVE(COMPUTED_GOTO)
    13481372    #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); goto *vPC->u.opcode
     
    24852509        int base = (++vPC)->u.operand;
    24862510        int property = (++vPC)->u.operand;
    2487 
     2511       
    24882512        JSValue* baseValue = r[base].jsValue(exec);
    24892513        JSValue* subscript = r[property].jsValue(exec);
     
    27992823            vPC += defaultOffset;
    28002824        else
    2801             vPC += offsetForStringSwitch(codeBlock->stringSwitchJumpTables[tableIndex], scrutinee, defaultOffset);
     2825            vPC += codeBlock->stringSwitchJumpTables[tableIndex].offsetForValue(static_cast<JSString*>(scrutinee)->value().rep(), defaultOffset);
    28022826        NEXT_OPCODE;
    28032827    }
     
    33813405         is only generated while the debugger is attached.
    33823406        */
    3383 
    3384         debug(exec, vPC, codeBlock, scopeChain, r);
    3385 
    3386         vPC += 4;
     3407        int debugHookID = (++vPC)->u.operand;
     3408        int firstLine = (++vPC)->u.operand;
     3409        int lastLine = (++vPC)->u.operand;
     3410
     3411        debug(exec, codeBlock, scopeChain, r, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
     3412
     3413        ++vPC;
    33873414        NEXT_OPCODE;
    33883415    }
     
    34063433    #undef BEGIN_OPCODE
    34073434    #undef VM_CHECK_EXCEPTION
     3435    #undef CHECK_FOR_TIMEOUT
    34083436}
    34093437
     
    34993527}
    35003528
     3529#if ENABLE(CTI)
     3530
     3531NEVER_INLINE static void doSetReturnAddressVMThrowTrampoline(void** returnAddress)
     3532{
     3533    ctiSetReturnAddress(returnAddress, (void*)ctiVMThrowTrampoline);
     3534}
     3535
     3536NEVER_INLINE void Machine::tryCTICachePutByID(ExecState* exec, CodeBlock* codeBlock, void* returnAddress, JSValue* baseValue, const PutPropertySlot& slot)
     3537{
     3538    // The interpreter checks for recursion here; I do not believe this can occur in CTI.
     3539
     3540    if (JSImmediate::isImmediate(baseValue))
     3541        return;
     3542
     3543    // Uncacheable: give up.
     3544    if (!slot.isCacheable()) {
     3545        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
     3546        return;
     3547    }
     3548
     3549    // FIXME: Cache new property transitions, too.
     3550    if (slot.type() == PutPropertySlot::NewProperty) {
     3551        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
     3552        return;
     3553    }
     3554   
     3555    JSCell* baseCell = static_cast<JSCell*>(baseValue);
     3556    StructureID* structureID = baseCell->structureID();
     3557
     3558    // FIXME: Remove this !structureID check once all objects have StructureIDs.
     3559    if (!structureID) {
     3560        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
     3561        return;
     3562    }
     3563
     3564    if (structureID->isDictionary()) {
     3565        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
     3566        return;
     3567    }
     3568
     3569    // In the interpreter the last structure is trapped here; in CTI we use the
     3570    // *_second method to achieve a similar (but not quite the same) effect.
     3571
     3572    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(returnAddress);
     3573    Instruction* vPC = codeBlock->instructions.begin() + vPCIndex;
     3574
     3575    // Cache hit: Specialize instruction and ref StructureIDs.
     3576
     3577    // If baseCell != base, then baseCell must be a proxy for another object.
     3578    if (baseCell != slot.base()) {
     3579        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
     3580        return;
     3581    }
     3582    vPC[0] = getOpcode(op_put_by_id_replace);
     3583    vPC[4] = structureID;
     3584    vPC[5] = slot.cachedOffset();
     3585    codeBlock->refStructureIDs(vPC);
     3586
     3587    ctiRepatchCallByReturnAddress(returnAddress, CTI::compilePutByIdReplace(this, exec, codeBlock, structureID, slot.cachedOffset()));
     3588}
     3589
     3590void* Machine::getCTIArrayLengthTrampoline(ExecState* exec, CodeBlock* codeBlock)
     3591{
     3592    if (!m_ctiArrayLengthTrampoline)
     3593        m_ctiArrayLengthTrampoline = CTI::compileArrayLengthTrampoline(this, exec, codeBlock);
     3594       
     3595    return m_ctiArrayLengthTrampoline;
     3596}
     3597
     3598void* Machine::getCTIStringLengthTrampoline(ExecState* exec, CodeBlock* codeBlock)
     3599{
     3600    if (!m_ctiStringLengthTrampoline)
     3601        m_ctiStringLengthTrampoline = CTI::compileStringLengthTrampoline(this, exec, codeBlock);
     3602       
     3603    return m_ctiStringLengthTrampoline;
     3604}
     3605
     3606NEVER_INLINE void Machine::tryCTICacheGetByID(ExecState* exec, CodeBlock* codeBlock, void* returnAddress, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot)
     3607{
     3608    // The interpreter checks for recursion here; I do not believe this can occur in CTI.
     3609
     3610    if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) {
     3611        ctiRepatchCallByReturnAddress(returnAddress, getCTIArrayLengthTrampoline(exec, codeBlock));
     3612        return;
     3613    }
     3614    if (isJSString(baseValue) && propertyName == exec->propertyNames().length) {
     3615        ctiRepatchCallByReturnAddress(returnAddress, getCTIStringLengthTrampoline(exec, codeBlock));
     3616        return;
     3617    }
     3618
     3619    // Uncacheable: give up.
     3620    if (!slot.isCacheable()) {
     3621        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
     3622        return;
     3623    }
     3624
     3625    // FIXME: Cache property access for immediates.
     3626    if (JSImmediate::isImmediate(baseValue)) {
     3627        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
     3628        return;
     3629    }
     3630
     3631    JSCell* baseCell = static_cast<JSCell*>(baseValue);
     3632    StructureID* structureID = baseCell->structureID();
     3633
     3634    // FIXME: Remove this !structureID check once all JSCells have StructureIDs.
     3635    if (!structureID) {
     3636        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
     3637        return;
     3638    }
     3639
     3640    if (structureID->isDictionary()) {
     3641        ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
     3642        return;
     3643    }
     3644
     3645    // In the interpreter the last structure is trapped here; in CTI we use the
     3646    // *_second method to achieve a similar (but not quite the same) effect.
     3647
     3648    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(returnAddress);
     3649    Instruction* vPC = codeBlock->instructions.begin() + vPCIndex;
     3650
     3651    // Cache hit: Specialize instruction and ref StructureIDs.
     3652
     3653    if (slot.slotBase() == baseValue) {
     3654        // set this up, so derefStructureIDs can do it's job.
     3655        vPC[0] = getOpcode(op_get_by_id_self);
     3656        vPC[4] = structureID;
     3657        vPC[5] = slot.cachedOffset();
     3658        codeBlock->refStructureIDs(vPC);
     3659       
     3660        ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdSelf(this, exec, codeBlock, structureID, slot.cachedOffset()));
     3661        return;
     3662    }
     3663
     3664    if (slot.slotBase() == structureID->prototype()) {
     3665        ASSERT(slot.slotBase()->isObject());
     3666
     3667        JSObject* slotBaseObject = static_cast<JSObject*>(slot.slotBase());
     3668
     3669        // Heavy access to a prototype is a good indication that it's not being
     3670        // used as a dictionary.
     3671        if (slotBaseObject->structureID()->isDictionary()) {
     3672            RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(slotBaseObject->structureID());
     3673            slotBaseObject->setStructureID(transition.release());
     3674            static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
     3675        }
     3676
     3677        vPC[0] = getOpcode(op_get_by_id_proto);
     3678        vPC[4] = structureID;
     3679        vPC[5] = slotBaseObject->structureID();
     3680        vPC[6] = slot.cachedOffset();
     3681        codeBlock->refStructureIDs(vPC);
     3682
     3683        ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdProto(this, exec, codeBlock, structureID, slotBaseObject->structureID(), slot.cachedOffset()));
     3684        return;
     3685    }
     3686
     3687    size_t count = 0;
     3688    JSObject* o = static_cast<JSObject*>(baseValue);
     3689    while (slot.slotBase() != o) {
     3690        JSValue* v = o->structureID()->prototype();
     3691
     3692        // If we didn't find slotBase in baseValue's prototype chain, then baseValue
     3693        // must be a proxy for another object.
     3694
     3695        if (v->isNull()) {
     3696            vPC[0] = getOpcode(op_get_by_id_generic);
     3697            return;
     3698        }
     3699
     3700        o = static_cast<JSObject*>(v);
     3701
     3702        // Heavy access to a prototype is a good indication that it's not being
     3703        // used as a dictionary.
     3704        if (o->structureID()->isDictionary()) {
     3705            RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(o->structureID());
     3706            o->setStructureID(transition.release());
     3707            static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
     3708        }
     3709
     3710        ++count;
     3711    }
     3712
     3713    StructureIDChain* chain = structureID->cachedPrototypeChain();
     3714    if (!chain)
     3715        chain = cachePrototypeChain(structureID);
     3716
     3717    vPC[0] = getOpcode(op_get_by_id_chain);
     3718    vPC[4] = structureID;
     3719    vPC[5] = chain;
     3720    vPC[6] = count;
     3721    vPC[7] = slot.cachedOffset();
     3722    codeBlock->refStructureIDs(vPC);
     3723
     3724    ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdChain(this, exec, codeBlock, structureID, chain, count, slot.cachedOffset()));
     3725}
     3726
     3727
     3728#define JSVALUE_VM_CHECK_EXCEPTION_ARG(exception) \
     3729    do { \
     3730        if (UNLIKELY(exception != 0)) { \
     3731            exec->setException(exception); \
     3732            exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
     3733            doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
     3734            return 0; \
     3735        } \
     3736    } while (0)
     3737#define VM_CHECK_EXCEPTION_v() \
     3738    do { \
     3739        if (UNLIKELY(exec->hadException())) { \
     3740            exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
     3741            doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
     3742            return; \
     3743        } \
     3744    } while (0)
     3745#define VM_CHECK_EXCEPTION(type) \
     3746    do { \
     3747        if (UNLIKELY(exec->hadException())) { \
     3748            exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
     3749            doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
     3750            return (type)0; \
     3751        } \
     3752    } while (0)
     3753#define VM_CHECK_EXCEPTION_AT_END() \
     3754    do { \
     3755        if (UNLIKELY(exec->hadException())) { \
     3756            /*printf("VM_CHECK_EXCEPTION_AT_END()\n");*/ \
     3757            exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
     3758            doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
     3759        } \
     3760    } while (0)
     3761
     3762void Machine::cti_op_end(CTI_ARGS)
     3763{
     3764    ASSERT(ARG_scopeChain->refCount > 1);
     3765    ARG_scopeChain->deref();
     3766}
     3767
     3768JSValue* Machine::cti_op_add(CTI_ARGS)
     3769{
     3770    JSValue* src1 = ARG_src1;
     3771    JSValue* src2 = ARG_src2;
     3772
     3773    ExecState* exec = ARG_exec;
     3774    JSValue* result = jsAdd(exec, src1, src2);
     3775    VM_CHECK_EXCEPTION_AT_END();
     3776    return result;
     3777}
     3778
     3779JSValue* Machine::cti_op_pre_inc(CTI_ARGS)
     3780{
     3781    JSValue* v = ARG_src1;
     3782
     3783    ExecState* exec = ARG_exec;
     3784    JSValue* result = jsNumber(exec, v->toNumber(exec) + 1);
     3785    VM_CHECK_EXCEPTION_AT_END();
     3786    return result;
     3787}
     3788
     3789void Machine::cti_timeout_check(CTI_ARGS)
     3790{
     3791    ExecState* exec = ARG_exec;
     3792
     3793    if (exec->machine()->checkTimeout(exec->dynamicGlobalObject()))
     3794        exec->setException(createInterruptedExecutionException(exec));
     3795
     3796    VM_CHECK_EXCEPTION_AT_END();
     3797}
     3798
     3799
     3800int Machine::cti_op_loop_if_less(CTI_ARGS)
     3801{
     3802    JSValue* src1 = ARG_src1;
     3803    JSValue* src2 = ARG_src2;
     3804    ExecState* exec = ARG_exec;
     3805
     3806    bool result = jsLess(exec, src1, src2);
     3807    VM_CHECK_EXCEPTION_AT_END();
     3808    return result;
     3809}
     3810
     3811JSValue* Machine::cti_op_new_object(CTI_ARGS)
     3812{
     3813    return constructEmptyObject(ARG_exec);;
     3814}
     3815
     3816void Machine::cti_op_put_by_id(CTI_ARGS)
     3817{
     3818    ExecState* exec = ARG_exec;
     3819    Identifier& ident = *ARG_id2;
     3820
     3821    PutPropertySlot slot;
     3822    ARG_src1->put(exec, ident, ARG_src3, slot);
     3823
     3824    ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_put_by_id_second);
     3825
     3826    VM_CHECK_EXCEPTION_AT_END();
     3827}
     3828
     3829void Machine::cti_op_put_by_id_second(CTI_ARGS)
     3830{
     3831    ExecState* exec = ARG_exec;
     3832    Identifier& ident = *ARG_id2;
     3833
     3834    JSValue* baseValue = ARG_src1;
     3835    PutPropertySlot slot;
     3836    baseValue->put(exec, ident, ARG_src3, slot);
     3837
     3838    exec->machine()->tryCTICachePutByID(exec, ARG_codeBlock, CTI_RETURN_ADDRESS, baseValue, slot);
     3839
     3840    VM_CHECK_EXCEPTION_AT_END();
     3841}
     3842
     3843void Machine::cti_op_put_by_id_generic(CTI_ARGS)
     3844{
     3845    ExecState* exec = ARG_exec;
     3846    Identifier& ident = *ARG_id2;
     3847
     3848    PutPropertySlot slot;
     3849    ARG_src1->put(exec, ident, ARG_src3, slot);
     3850
     3851    VM_CHECK_EXCEPTION_AT_END();
     3852}
     3853
     3854void Machine::cti_op_put_by_id_fail(CTI_ARGS)
     3855{
     3856    ExecState* exec = ARG_exec;
     3857    Identifier& ident = *ARG_id2;
     3858
     3859    PutPropertySlot slot;
     3860    ARG_src1->put(exec, ident, ARG_src3, slot);
     3861
     3862    // should probably uncachePutByID() ... this would mean doing a vPC lookup - might be worth just bleeding this until the end.
     3863    ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_put_by_id_generic);
     3864
     3865    VM_CHECK_EXCEPTION_AT_END();
     3866}
     3867
     3868JSValue* Machine::cti_op_get_by_id(CTI_ARGS)
     3869{
     3870    ExecState* exec = ARG_exec;
     3871    Identifier& ident = *ARG_id2;
     3872
     3873    JSValue* baseValue = ARG_src1;
     3874    PropertySlot slot(baseValue);
     3875    JSValue* result = baseValue->get(exec, ident, slot);
     3876
     3877    ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_get_by_id_second);
     3878
     3879    VM_CHECK_EXCEPTION_AT_END();
     3880    return result;
     3881}
     3882
     3883JSValue* Machine::cti_op_get_by_id_second(CTI_ARGS)
     3884{
     3885    ExecState* exec = ARG_exec;
     3886    Identifier& ident = *ARG_id2;
     3887
     3888    JSValue* baseValue = ARG_src1;
     3889    PropertySlot slot(baseValue);
     3890    JSValue* result = baseValue->get(exec, ident, slot);
     3891
     3892    exec->machine()->tryCTICacheGetByID(exec, ARG_codeBlock, CTI_RETURN_ADDRESS, baseValue, ident, slot);
     3893
     3894    VM_CHECK_EXCEPTION_AT_END();
     3895    return result;
     3896}
     3897
     3898JSValue* Machine::cti_op_get_by_id_generic(CTI_ARGS)
     3899{
     3900    ExecState* exec = ARG_exec;
     3901    Identifier& ident = *ARG_id2;
     3902
     3903    JSValue* baseValue = ARG_src1;
     3904    PropertySlot slot(baseValue);
     3905    JSValue* result = baseValue->get(exec, ident, slot);
     3906
     3907    VM_CHECK_EXCEPTION_AT_END();
     3908    return result;
     3909}
     3910
     3911JSValue* Machine::cti_op_get_by_id_fail(CTI_ARGS)
     3912{
     3913    ExecState* exec = ARG_exec;
     3914    Identifier& ident = *ARG_id2;
     3915
     3916    JSValue* baseValue = ARG_src1;
     3917    PropertySlot slot(baseValue);
     3918    JSValue* result = baseValue->get(exec, ident, slot);
     3919
     3920    // should probably uncacheGetByID() ... this would mean doing a vPC lookup - might be worth just bleeding this until the end.
     3921    ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_get_by_id_generic);
     3922
     3923    VM_CHECK_EXCEPTION_AT_END();
     3924    return result;
     3925}
     3926
     3927JSValue* Machine::cti_op_instanceof(CTI_ARGS)
     3928{
     3929    ExecState* exec = ARG_exec;
     3930    JSValue* baseVal = ARG_src2;
     3931
     3932    if (!baseVal->isObject()) {
     3933        CodeBlock* codeBlock = ARG_codeBlock;
     3934        ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
     3935        unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
     3936        exec->setException(createInvalidParamError(exec, "instanceof", baseVal, codeBlock->instructions.begin() + vPCIndex, codeBlock));
     3937        VM_CHECK_EXCEPTION(JSValue*);
     3938    }
     3939
     3940    JSObject* baseObj = static_cast<JSObject*>(baseVal);
     3941    JSValue* result = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec,  ARG_src1) : false);
     3942    VM_CHECK_EXCEPTION_AT_END();
     3943    return result;
     3944}
     3945
     3946JSValue* Machine::cti_op_del_by_id(CTI_ARGS)
     3947{
     3948    ExecState* exec = ARG_exec;
     3949    Identifier& ident = *ARG_id2;
     3950   
     3951    JSObject* baseObj = ARG_src1->toObject(exec);
     3952
     3953    JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
     3954    VM_CHECK_EXCEPTION_AT_END();
     3955    return result;
     3956}
     3957
     3958JSValue* Machine::cti_op_mul(CTI_ARGS)
     3959{
     3960    ExecState* exec = ARG_exec;
     3961    JSValue* src1 = ARG_src1;
     3962    JSValue* src2 = ARG_src2;
     3963
     3964    double left;
     3965    double right;
     3966    if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
     3967        return jsNumber(exec, left * right);
     3968    else {
     3969        JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
     3970        VM_CHECK_EXCEPTION_AT_END();
     3971        return result;
     3972    }
     3973}
     3974
     3975JSValue* Machine::cti_op_new_func(CTI_ARGS)
     3976{
     3977    return ARG_func1->makeFunction(ARG_exec, ARG_scopeChain);
     3978}
     3979
     3980void* Machine::cti_op_call_JSFunction(CTI_ARGS)
     3981{
     3982    ExecState* exec = ARG_exec;
     3983    RegisterFile* registerFile = ARG_registerFile;
     3984    Register* r = ARG_r;
     3985    CodeBlock* codeBlock = ARG_codeBlock;
     3986    ScopeChainNode* scopeChain = ARG_scopeChain;
     3987
     3988    Machine* machine = exec->machine();
     3989    JSValue* exceptionValue = 0;
     3990    Register* registerBase = registerFile->base();
     3991   
     3992    JSValue* funcVal = ARG_src1;
     3993    JSValue* thisValue = ARG_src2;
     3994    int firstArg = ARG_int3;
     3995    int argCount = ARG_int4;
     3996
     3997    CallData callData;
     3998#ifndef NDEBUG
     3999    CallType callType =
     4000#endif
     4001        funcVal->getCallData(callData);
     4002
     4003    ASSERT(callType == CallTypeJS);
     4004
     4005    if (*ARG_profilerReference)
     4006        (*ARG_profilerReference)->willExecute(exec, static_cast<JSObject*>(funcVal));
     4007
     4008    ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
     4009    FunctionBodyNode* functionBodyNode = callData.js.functionBody;
     4010    CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
     4011
     4012    r[firstArg] = thisValue;
     4013
     4014    Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
     4015    machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 0, funcVal);
     4016    exec->m_callFrame = callFrame;
     4017
     4018    r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
     4019    JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
     4020   
     4021    codeBlock = newCodeBlock;
     4022    machine->setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
     4023
     4024    if (!codeBlock->ctiCode)
     4025        CTI::compile(machine, exec, codeBlock);
     4026
     4027    ARG_setScopeChain(scopeChain);
     4028    ARG_setCodeBlock(codeBlock);
     4029    ARG_setR(r);
     4030    return codeBlock->ctiCode;
     4031}
     4032
     4033JSValue* Machine::cti_op_call_NotJSFunction(CTI_ARGS)
     4034{
     4035    ExecState* exec = ARG_exec;
     4036    Register* r = ARG_r;
     4037
     4038    JSValue* funcVal = ARG_src1;
     4039    JSValue* thisValue = ARG_src2;
     4040    int firstArg = ARG_int3;
     4041    int argCount = ARG_int4;
     4042
     4043    CallData callData;
     4044    CallType callType = funcVal->getCallData(callData);
     4045
     4046    ASSERT(callType != CallTypeJS);
     4047
     4048    if (callType == CallTypeHost) {
     4049        CodeBlock* codeBlock = ARG_codeBlock;
     4050        ScopeChainNode* scopeChain = ARG_scopeChain;
     4051        Machine* machine = exec->machine();
     4052
     4053        Register* oldCallFrame = exec->m_callFrame;
     4054        Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
     4055        machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 0, funcVal);
     4056        exec->m_callFrame = callFrame;
     4057
     4058        if (*ARG_profilerReference)
     4059            (*ARG_profilerReference)->willExecute(exec, static_cast<JSObject*>(funcVal));
     4060
     4061        ArgList argList(r + firstArg + 1, argCount - 1);
     4062
     4063        CTI_MACHINE_SAMPLING_callingHostFunction();
     4064
     4065        JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(funcVal), thisValue, argList);
     4066        exec->m_callFrame = oldCallFrame;
     4067        VM_CHECK_EXCEPTION(JSValue*);
     4068
     4069        if (*ARG_profilerReference)
     4070            (*ARG_profilerReference)->didExecute(exec, static_cast<JSObject*>(funcVal));
     4071
     4072        return returnValue;
     4073
     4074    }
     4075
     4076    ASSERT(callType == CallTypeNone);
     4077
     4078    exec->setException(createNotAFunctionError(exec, funcVal, ARG_instr5, ARG_codeBlock));
     4079    VM_CHECK_EXCEPTION_AT_END();
     4080    return 0;
     4081}
     4082
     4083JSValue* Machine::cti_op_ret(CTI_ARGS)
     4084{
     4085    ExecState* exec = ARG_exec;
     4086    Register* r = ARG_r;
     4087    CodeBlock* codeBlock = ARG_codeBlock;
     4088    ScopeChainNode* scopeChain = ARG_scopeChain;
     4089
     4090    Machine* machine = exec->machine();
     4091
     4092    Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
     4093    if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
     4094        ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
     4095        ASSERT(activation->isActivationObject());
     4096        activation->copyRegisters();
     4097    }
     4098
     4099    if (*ARG_profilerReference)
     4100        (*ARG_profilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
     4101
     4102    if (codeBlock->needsFullScopeChain)
     4103        scopeChain->deref();
     4104
     4105    JSValue* returnValue = ARG_src1;
     4106    if (callFrame[RegisterFile::CalledAsConstructor].i() && !returnValue->isObject()) {
     4107        JSValue* thisObject = callFrame[RegisterFile::CallFrameHeaderSize].jsValue(exec);
     4108        returnValue = thisObject;
     4109    }
     4110
     4111    codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
     4112    if (codeBlock) {
     4113        machine->setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].scopeChain());
     4114        r = callFrame[RegisterFile::CallerRegisters].r();
     4115        exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
     4116    }
     4117
     4118    ARG_setScopeChain(scopeChain);
     4119    ARG_setCodeBlock(codeBlock);
     4120    ARG_setR(r);
     4121
     4122    return returnValue;
     4123}
     4124
     4125JSValue* Machine::cti_op_new_array(CTI_ARGS)
     4126{
     4127    ArgList argsList(ARG_registers1, ARG_int2);
     4128    return constructArray(ARG_exec, argsList);
     4129}
     4130
     4131JSValue* Machine::cti_op_resolve(CTI_ARGS)
     4132{
     4133    ExecState* exec = ARG_exec;
     4134    ScopeChainNode* scopeChain = ARG_scopeChain;
     4135
     4136    ScopeChainIterator iter = scopeChain->begin();
     4137    ScopeChainIterator end = scopeChain->end();
     4138    ASSERT(iter != end);
     4139
     4140    Identifier& ident = *ARG_id1;
     4141    do {
     4142        JSObject* o = *iter;
     4143        PropertySlot slot(o);
     4144        if (o->getPropertySlot(exec, ident, slot)) {
     4145            JSValue* result = slot.getValue(exec, ident);
     4146            VM_CHECK_EXCEPTION_AT_END();
     4147            return result;
     4148        }
     4149    } while (++iter != end);
     4150
     4151    CodeBlock* codeBlock = ARG_codeBlock;
     4152    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
     4153    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
     4154    exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
     4155
     4156    VM_CHECK_EXCEPTION_AT_END();
     4157    return 0;
     4158}
     4159
     4160void* Machine::cti_op_construct_JSConstruct(CTI_ARGS)
     4161{
     4162    ExecState* exec = ARG_exec;
     4163    RegisterFile* registerFile = ARG_registerFile;
     4164    Register* r = ARG_r;
     4165    CodeBlock* codeBlock = ARG_codeBlock;
     4166    ScopeChainNode* scopeChain = ARG_scopeChain;
     4167
     4168    Machine* machine = exec->machine();
     4169    JSValue* exceptionValue = 0;
     4170    Register* registerBase = registerFile->base();
     4171   
     4172    JSValue* constrVal = ARG_src1;
     4173    int firstArg = ARG_int2;
     4174    int argCount = ARG_int3;
     4175
     4176    ConstructData constructData;
     4177#ifndef NDEBUG
     4178    ConstructType constructType =
     4179#endif
     4180        constrVal->getConstructData(constructData);
     4181
     4182    // Removing this line of code causes a measurable regression on squirrelfish.
     4183    JSObject* constructor = static_cast<JSObject*>(constrVal);
     4184
     4185    ASSERT(constructType == ConstructTypeJS);
     4186
     4187    if (*ARG_profilerReference)
     4188        (*ARG_profilerReference)->willExecute(exec, constructor);
     4189
     4190    JSObject* prototype;
     4191    JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
     4192    if (p->isObject())
     4193        prototype = static_cast<JSObject*>(p);
     4194    else
     4195        prototype = scopeChain->globalObject()->objectPrototype();
     4196    JSObject* newObject = new (exec) JSObject(prototype);
     4197
     4198    ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
     4199    FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
     4200    CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
     4201
     4202    r[firstArg] = newObject; // "this" value
     4203
     4204    Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
     4205    machine->initializeCallFrame(callFrame, codeBlock, ARG_instr4, scopeChain, r, 0/*dst*/, firstArg, argCount, 1, constructor);
     4206    exec->m_callFrame = callFrame;
     4207
     4208    r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
     4209    JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
     4210
     4211    codeBlock = newCodeBlock;
     4212    machine->setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
     4213
     4214    if (!codeBlock->ctiCode)
     4215        CTI::compile(machine, exec, codeBlock);
     4216
     4217    ARG_setScopeChain(scopeChain);
     4218    ARG_setCodeBlock(codeBlock);
     4219    ARG_setR(r);
     4220    return codeBlock->ctiCode;
     4221}
     4222
     4223JSValue* Machine::cti_op_construct_NotJSConstruct(CTI_ARGS)
     4224{
     4225    ExecState* exec = ARG_exec;
     4226    Register* r = ARG_r;
     4227
     4228    JSValue* constrVal = ARG_src1;
     4229    int firstArg = ARG_int2;
     4230    int argCount = ARG_int3;
     4231
     4232    ConstructData constructData;
     4233    ConstructType constructType = constrVal->getConstructData(constructData);
     4234
     4235    // Removing this line of code causes a measurable regression on squirrelfish.
     4236    JSObject* constructor = static_cast<JSObject*>(constrVal);
     4237
     4238    ASSERT(constructType != ConstructTypeJS);
     4239
     4240    if (constructType == ConstructTypeHost) {
     4241        CodeBlock* codeBlock = ARG_codeBlock;
     4242        ScopeChainNode* scopeChain = ARG_scopeChain;
     4243        Machine* machine = exec->machine();
     4244
     4245        Register* oldCallFrame = exec->m_callFrame;
     4246        Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
     4247        machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 1, constrVal);
     4248        exec->m_callFrame = callFrame;
     4249
     4250        if (*ARG_profilerReference)
     4251            (*ARG_profilerReference)->willExecute(exec, constructor);
     4252
     4253        ArgList argList(r + firstArg + 1, argCount - 1);
     4254
     4255        CTI_MACHINE_SAMPLING_callingHostFunction();
     4256
     4257        JSValue* returnValue = constructData.native.function(exec, constructor, argList);
     4258        exec->m_callFrame = oldCallFrame;
     4259        VM_CHECK_EXCEPTION(JSValue*);
     4260
     4261        if (*ARG_profilerReference)
     4262            (*ARG_profilerReference)->didExecute(exec, constructor);
     4263
     4264        return returnValue;
     4265    }
     4266
     4267    ASSERT(constructType == ConstructTypeNone);
     4268
     4269    exec->setException(createNotAConstructorError(exec, constrVal, ARG_instr4, ARG_codeBlock));
     4270    VM_CHECK_EXCEPTION_AT_END();
     4271    return 0;
     4272}
     4273
     4274JSValue* Machine::cti_op_get_by_val(CTI_ARGS)
     4275{
     4276    ExecState* exec = ARG_exec;
     4277    Machine* machine = exec->machine();
     4278
     4279    JSValue* baseValue = ARG_src1;
     4280    JSValue* subscript = ARG_src2;
     4281
     4282    JSValue* result;
     4283    unsigned i;
     4284
     4285    bool isUInt32 = JSImmediate::getUInt32(subscript, i);
     4286    if (LIKELY(isUInt32)) {
     4287        if (machine->isJSArray(baseValue)) {
     4288            JSArray* jsArray = static_cast<JSArray*>(baseValue);
     4289            if (jsArray->canGetIndex(i))
     4290                result = jsArray->getIndex(i);
     4291            else
     4292                result = jsArray->JSArray::get(exec, i);
     4293        } else if (machine->isJSString(baseValue) && static_cast<JSString*>(baseValue)->canGetIndex(i))
     4294            result = static_cast<JSString*>(baseValue)->getIndex(exec, i);
     4295        else
     4296            result = baseValue->get(exec, i);
     4297    } else {
     4298        Identifier property(exec, subscript->toString(exec));
     4299        result = baseValue->get(exec, property);
     4300    }
     4301
     4302    VM_CHECK_EXCEPTION_AT_END();
     4303    return result;
     4304}
     4305
     4306JSValue* Machine::cti_op_resolve_func(CTI_ARGS)
     4307{
     4308    ExecState* exec = ARG_exec;
     4309    ScopeChainNode* scopeChain = ARG_scopeChain;
     4310
     4311    ScopeChainIterator iter = scopeChain->begin();
     4312    ScopeChainIterator end = scopeChain->end();
     4313
     4314    // FIXME: add scopeDepthIsZero optimization
     4315
     4316    ASSERT(iter != end);
     4317
     4318    Identifier& ident = *ARG_id1;
     4319    JSObject* base;
     4320    do {
     4321        base = *iter;
     4322        PropertySlot slot(base);
     4323        if (base->getPropertySlot(exec, ident, slot)) {           
     4324            // ECMA 11.2.3 says that if we hit an activation the this value should be null.
     4325            // However, section 10.2.3 says that in the case where the value provided
     4326            // by the caller is null, the global object should be used. It also says
     4327            // that the section does not apply to internal functions, but for simplicity
     4328            // of implementation we use the global object anyway here. This guarantees
     4329            // that in host objects you always get a valid object for this.
     4330            // We also handle wrapper substitution for the global object at the same time.
     4331            JSObject* thisObj = base->toThisObject(exec);
     4332            JSValue* result = slot.getValue(exec, ident);
     4333            VM_CHECK_EXCEPTION_AT_END();
     4334
     4335            ARG_set2ndResult(result);
     4336            return thisObj;
     4337        }
     4338        ++iter;
     4339    } while (iter != end);
     4340
     4341    CodeBlock* codeBlock = ARG_codeBlock;
     4342    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
     4343    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
     4344    exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
     4345
     4346    VM_CHECK_EXCEPTION_AT_END();
     4347    return 0;
     4348}
     4349
     4350JSValue* Machine::cti_op_sub(CTI_ARGS)
     4351{
     4352    JSValue* src1 = ARG_src1;
     4353    JSValue* src2 = ARG_src2;
     4354
     4355    double left;
     4356    double right;
     4357    if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
     4358        return jsNumber(ARG_exec, left - right);
     4359    else {
     4360        ExecState* exec = ARG_exec;
     4361        JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
     4362        VM_CHECK_EXCEPTION_AT_END();
     4363        return result;
     4364    }
     4365}
     4366
     4367void Machine::cti_op_put_by_val(CTI_ARGS)
     4368{
     4369    ExecState* exec = ARG_exec;
     4370    Machine* machine = exec->machine();
     4371
     4372    JSValue* baseValue = ARG_src1;
     4373    JSValue* subscript = ARG_src2;
     4374    JSValue* value = ARG_src3;
     4375
     4376    unsigned i;
     4377
     4378    bool isUInt32 = JSImmediate::getUInt32(subscript, i);
     4379    if (LIKELY(isUInt32)) {
     4380        if (machine->isJSArray(baseValue)) {
     4381            JSArray* jsArray = static_cast<JSArray*>(baseValue);
     4382            if (jsArray->canSetIndex(i))
     4383                jsArray->setIndex(i, value);
     4384            else
     4385                jsArray->JSArray::put(exec, i, value);
     4386        } else
     4387            baseValue->put(exec, i, value);
     4388    } else {
     4389        Identifier property(exec, subscript->toString(exec));
     4390        if (!exec->hadException()) { // Don't put to an object if toString threw an exception.
     4391            PutPropertySlot slot;
     4392            baseValue->put(exec, property, value, slot);
     4393        }
     4394    }
     4395
     4396    VM_CHECK_EXCEPTION_AT_END();
     4397}
     4398
     4399JSValue* Machine::cti_op_lesseq(CTI_ARGS)
     4400{
     4401    ExecState* exec = ARG_exec;
     4402    JSValue* result = jsBoolean(jsLessEq(exec, ARG_src1, ARG_src2));
     4403    VM_CHECK_EXCEPTION_AT_END();
     4404    return result;
     4405}
     4406
     4407int Machine::cti_op_loop_if_true(CTI_ARGS)
     4408{
     4409    JSValue* src1 = ARG_src1;
     4410
     4411    ExecState* exec = ARG_exec;
     4412
     4413    bool result = src1->toBoolean(exec);
     4414    VM_CHECK_EXCEPTION_AT_END();
     4415    return result;
     4416}
     4417
     4418JSValue* Machine::cti_op_negate(CTI_ARGS)
     4419{
     4420    JSValue* src = ARG_src1;
     4421
     4422    ExecState* exec = ARG_exec;
     4423
     4424    double v;
     4425    if (fastIsNumber(src, v))
     4426        return jsNumber(exec, -v);
     4427    else {
     4428        JSValue* result = jsNumber(exec, -src->toNumber(exec));
     4429        VM_CHECK_EXCEPTION_AT_END();
     4430        return result;
     4431    }
     4432}
     4433
     4434JSValue* Machine::cti_op_resolve_base(CTI_ARGS)
     4435{
     4436    return inlineResolveBase(ARG_exec, *ARG_id1, ARG_scopeChain);
     4437}
     4438
     4439JSValue* Machine::cti_op_resolve_skip(CTI_ARGS)
     4440{
     4441    ExecState* exec = ARG_exec;
     4442    ScopeChainNode* scopeChain = ARG_scopeChain;
     4443
     4444    int skip = ARG_int2;
     4445
     4446    ScopeChainIterator iter = scopeChain->begin();
     4447    ScopeChainIterator end = scopeChain->end();
     4448    ASSERT(iter != end);
     4449    while (skip--) {
     4450        ++iter;
     4451        ASSERT(iter != end);
     4452    }
     4453    Identifier& ident = *ARG_id1;
     4454    do {
     4455        JSObject* o = *iter;
     4456        PropertySlot slot(o);
     4457        if (o->getPropertySlot(exec, ident, slot)) {
     4458            JSValue* result = slot.getValue(exec, ident);
     4459            VM_CHECK_EXCEPTION_AT_END();
     4460            return result;
     4461        }
     4462    } while (++iter != end);
     4463
     4464    CodeBlock* codeBlock = ARG_codeBlock;
     4465    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
     4466    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
     4467    exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
     4468
     4469    VM_CHECK_EXCEPTION_AT_END();
     4470    return 0;
     4471}
     4472
     4473JSValue* Machine::cti_op_div(CTI_ARGS)
     4474{
     4475    ExecState* exec = ARG_exec;
     4476    JSValue* src1 = ARG_src1;
     4477    JSValue* src2 = ARG_src2;
     4478
     4479    double left;
     4480    double right;
     4481    if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
     4482        return jsNumber(exec, left / right);
     4483    else {
     4484        JSValue* result = jsNumber(exec, src1->toNumber(exec) / src2->toNumber(exec));
     4485        VM_CHECK_EXCEPTION_AT_END();
     4486        return result;
     4487    }
     4488}
     4489
     4490JSValue* Machine::cti_op_pre_dec(CTI_ARGS)
     4491{
     4492    JSValue* v = ARG_src1;
     4493
     4494    ExecState* exec = ARG_exec;
     4495    JSValue* result = jsNumber(exec, v->toNumber(exec) - 1);
     4496    VM_CHECK_EXCEPTION_AT_END();
     4497    return result;
     4498}
     4499
     4500int Machine::cti_op_jless(CTI_ARGS)
     4501{
     4502    JSValue* src1 = ARG_src1;
     4503    JSValue* src2 = ARG_src2;
     4504    ExecState* exec = ARG_exec;
     4505
     4506    bool result = jsLess(exec, src1, src2);
     4507    VM_CHECK_EXCEPTION_AT_END();
     4508    return result;
     4509}
     4510
     4511JSValue* Machine::cti_op_not(CTI_ARGS)
     4512{
     4513    JSValue* src = ARG_src1;
     4514
     4515    ExecState* exec = ARG_exec;
     4516
     4517    JSValue* result = jsBoolean(!src->toBoolean(exec));
     4518    VM_CHECK_EXCEPTION_AT_END();
     4519    return result;
     4520}
     4521
     4522int SFX_CALL Machine::cti_op_jtrue(CTI_ARGS)
     4523{
     4524    JSValue* src1 = ARG_src1;
     4525
     4526    ExecState* exec = ARG_exec;
     4527
     4528    bool result = src1->toBoolean(exec);
     4529    VM_CHECK_EXCEPTION_AT_END();
     4530    return result;
     4531}
     4532
     4533JSValue* Machine::cti_op_post_inc(CTI_ARGS)
     4534{
     4535    JSValue* v = ARG_src1;
     4536
     4537    ExecState* exec = ARG_exec;
     4538
     4539    JSValue* number = v->toJSNumber(exec);
     4540    VM_CHECK_EXCEPTION(JSValue*);
     4541    ARG_set2ndResult(jsNumber(exec, number->uncheckedGetNumber() + 1));
     4542    return number;
     4543}
     4544
     4545JSValue* Machine::cti_op_eq(CTI_ARGS)
     4546{
     4547    JSValue* src1 = ARG_src1;
     4548    JSValue* src2 = ARG_src2;
     4549
     4550    if (JSImmediate::areBothImmediateNumbers(src1, src2))
     4551        return jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
     4552    else {
     4553        ExecState* exec = ARG_exec;
     4554        JSValue* result = jsBoolean(equal(exec, src1, src2));
     4555        VM_CHECK_EXCEPTION_AT_END();
     4556        return result;
     4557    }
     4558}
     4559
     4560JSValue* Machine::cti_op_lshift(CTI_ARGS)
     4561{
     4562    JSValue* val = ARG_src1;
     4563    JSValue* shift = ARG_src2;
     4564
     4565    ExecState* exec = ARG_exec;
     4566
     4567    int32_t left;
     4568    uint32_t right;
     4569    if (JSImmediate::areBothImmediateNumbers(val, shift))
     4570        return jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f));
     4571    else if (fastToInt32(val, left) && fastToUInt32(shift, right))
     4572        return jsNumber(exec, left << (right & 0x1f));
     4573    else {
     4574        JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
     4575        VM_CHECK_EXCEPTION_AT_END();
     4576        return result;
     4577    }
     4578}
     4579
     4580JSValue* Machine::cti_op_bitand(CTI_ARGS)
     4581{
     4582    JSValue* src1 = ARG_src1;
     4583    JSValue* src2 = ARG_src2;
     4584
     4585    ExecState* exec = ARG_exec;
     4586
     4587    int32_t left;
     4588    int32_t right;
     4589    if (fastToInt32(src1, left) && fastToInt32(src2, right))
     4590        return jsNumber(exec, left & right);
     4591    else {
     4592        JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
     4593        VM_CHECK_EXCEPTION_AT_END();
     4594        return result;
     4595    }
     4596}
     4597
     4598JSValue* Machine::cti_op_rshift(CTI_ARGS)
     4599{
     4600    JSValue* val = ARG_src1;
     4601    JSValue* shift = ARG_src2;
     4602
     4603    ExecState* exec = ARG_exec;
     4604
     4605    int32_t left;
     4606    uint32_t right;
     4607    if (JSImmediate::areBothImmediateNumbers(val, shift))
     4608        return JSImmediate::rightShiftImmediateNumbers(val, shift);
     4609    else if (fastToInt32(val, left) && fastToUInt32(shift, right))
     4610        return jsNumber(exec, left >> (right & 0x1f));
     4611    else {
     4612        JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
     4613        VM_CHECK_EXCEPTION_AT_END();
     4614        return result;
     4615    }
     4616}
     4617
     4618JSValue* Machine::cti_op_bitnot(CTI_ARGS)
     4619{
     4620    JSValue* src = ARG_src1;
     4621
     4622    ExecState* exec = ARG_exec;
     4623
     4624    int value;
     4625    if (fastToInt32(src, value))
     4626        return jsNumber(exec, ~value);
     4627           
     4628    JSValue* result = jsNumber(exec, ~src->toInt32(exec));
     4629    VM_CHECK_EXCEPTION_AT_END();
     4630    return result;
     4631}
     4632
     4633JSValue* Machine::cti_op_resolve_with_base(CTI_ARGS)
     4634{
     4635    ExecState* exec = ARG_exec;
     4636    ScopeChainNode* scopeChain = ARG_scopeChain;
     4637
     4638    ScopeChainIterator iter = scopeChain->begin();
     4639    ScopeChainIterator end = scopeChain->end();
     4640
     4641    // FIXME: add scopeDepthIsZero optimization
     4642
     4643    ASSERT(iter != end);
     4644
     4645    Identifier& ident = *ARG_id1;
     4646    JSObject* base;
     4647    do {
     4648        base = *iter;
     4649        PropertySlot slot(base);
     4650        if (base->getPropertySlot(exec, ident, slot)) {
     4651            JSValue* result = slot.getValue(exec, ident);
     4652            VM_CHECK_EXCEPTION_AT_END();
     4653            ARG_set2ndResult(result);
     4654            return base;
     4655        }
     4656        ++iter;
     4657    } while (iter != end);
     4658
     4659    CodeBlock* codeBlock = ARG_codeBlock;
     4660    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
     4661    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
     4662    exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
     4663
     4664    VM_CHECK_EXCEPTION_AT_END();
     4665    return 0;
     4666}
     4667
     4668JSValue* Machine::cti_op_new_func_exp(CTI_ARGS)
     4669{
     4670    return ARG_funcexp1->makeFunction(ARG_exec, ARG_scopeChain);
     4671}
     4672
     4673JSValue* Machine::cti_op_mod(CTI_ARGS)
     4674{
     4675    JSValue* dividendValue = ARG_src1;
     4676    JSValue* divisorValue = ARG_src2;
     4677
     4678    ExecState* exec = ARG_exec;
     4679    double d = dividendValue->toNumber(exec);
     4680    JSValue* result = jsNumber(exec, fmod(d, divisorValue->toNumber(exec)));
     4681    VM_CHECK_EXCEPTION_AT_END();
     4682    return result;
     4683}
     4684
     4685JSValue* Machine::cti_op_less(CTI_ARGS)
     4686{
     4687    ExecState* exec = ARG_exec;
     4688    JSValue* result = jsBoolean(jsLess(exec, ARG_src1, ARG_src2));
     4689    VM_CHECK_EXCEPTION_AT_END();
     4690    return result;
     4691}
     4692
     4693JSValue* Machine::cti_op_neq(CTI_ARGS)
     4694{
     4695    JSValue* src1 = ARG_src1;
     4696    JSValue* src2 = ARG_src2;
     4697
     4698    if (JSImmediate::areBothImmediateNumbers(src1, src2))
     4699        return jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
     4700    else {
     4701        ExecState* exec = ARG_exec;
     4702        JSValue* result = jsBoolean(!equal(exec, src1, src2));
     4703        VM_CHECK_EXCEPTION_AT_END();
     4704        return result;
     4705    }
     4706}
     4707
     4708JSValue* Machine::cti_op_post_dec(CTI_ARGS)
     4709{
     4710    JSValue* v = ARG_src1;
     4711
     4712    ExecState* exec = ARG_exec;
     4713
     4714    JSValue* number = v->toJSNumber(exec);
     4715    VM_CHECK_EXCEPTION(JSValue*);
     4716
     4717    ARG_set2ndResult(jsNumber(exec, number->uncheckedGetNumber() - 1));
     4718    return number;
     4719}
     4720
     4721JSValue* Machine::cti_op_urshift(CTI_ARGS)
     4722{
     4723    JSValue* val = ARG_src1;
     4724    JSValue* shift = ARG_src2;
     4725
     4726    ExecState* exec = ARG_exec;
     4727
     4728    if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
     4729        return JSImmediate::rightShiftImmediateNumbers(val, shift);
     4730    else {
     4731        JSValue* result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
     4732        VM_CHECK_EXCEPTION_AT_END();
     4733        return result;
     4734    }
     4735}
     4736
     4737JSValue* Machine::cti_op_bitxor(CTI_ARGS)
     4738{
     4739    JSValue* src1 = ARG_src1;
     4740    JSValue* src2 = ARG_src2;
     4741
     4742    ExecState* exec = ARG_exec;
     4743
     4744    JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
     4745    VM_CHECK_EXCEPTION_AT_END();
     4746    return result;
     4747}
     4748
     4749JSValue* Machine::cti_op_new_regexp(CTI_ARGS)
     4750{
     4751    return new (ARG_exec) RegExpObject(ARG_scopeChain->globalObject()->regExpPrototype(), ARG_regexp1);
     4752}
     4753
     4754JSValue* Machine::cti_op_bitor(CTI_ARGS)
     4755{
     4756    JSValue* src1 = ARG_src1;
     4757    JSValue* src2 = ARG_src2;
     4758
     4759    ExecState* exec = ARG_exec;
     4760
     4761    JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
     4762    VM_CHECK_EXCEPTION_AT_END();
     4763    return result;
     4764}
     4765
     4766JSValue* Machine::cti_op_call_eval(CTI_ARGS)
     4767{
     4768    ExecState* exec = ARG_exec;
     4769    RegisterFile* registerFile = ARG_registerFile;
     4770    Register* r = ARG_r;
     4771    CodeBlock* codeBlock = ARG_codeBlock;
     4772    ScopeChainNode* scopeChain = ARG_scopeChain;
     4773
     4774    Machine* machine = exec->machine();
     4775    JSValue* exceptionValue = 0;
     4776   
     4777    JSValue* funcVal = ARG_src1;
     4778    JSValue* baseVal = ARG_src2;
     4779    int firstArg = ARG_int3;
     4780    int argCount = ARG_int4;
     4781
     4782    if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
     4783        JSObject* thisObject = static_cast<JSObject*>(r[codeBlock->thisRegister].jsValue(exec));
     4784        JSValue* result = machine->callEval(exec, thisObject, scopeChain, registerFile,  r, firstArg, argCount, exceptionValue);
     4785        JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
     4786        return result;
     4787    }
     4788
     4789    return JSImmediate::impossibleValue();
     4790}
     4791
     4792void* Machine::cti_op_throw(CTI_ARGS)
     4793{
     4794    ExecState* exec = ARG_exec;
     4795    CodeBlock* codeBlock = ARG_codeBlock;
     4796    ScopeChainNode* scopeChain = ARG_scopeChain;
     4797    Register* r = ARG_r;
     4798
     4799    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
     4800    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
     4801
     4802    JSValue* exceptionValue = ARG_src1;
     4803    Instruction* handlerVPC = ARG_exec->machine()->throwException(exec, exceptionValue, codeBlock->instructions.begin() + vPCIndex, codeBlock, scopeChain, r, true);
     4804
     4805    if (handlerVPC) {
     4806        exec->setException(exceptionValue);
     4807        ARG_setScopeChain(scopeChain);
     4808        ARG_setCodeBlock(codeBlock);
     4809        ARG_setR(r);
     4810
     4811        void* catchRoutine = codeBlock->nativeExceptionCodeForHandlerVPC(handlerVPC);
     4812        ASSERT(catchRoutine);
     4813        ctiSetReturnAddress(&CTI_RETURN_ADDRESS, catchRoutine);
     4814        return catchRoutine;
     4815    } else {
     4816        exec->clearException();
     4817        *ARG_exception = exceptionValue;
     4818        return JSImmediate::nullImmediate();
     4819    }
     4820}
     4821
     4822JSPropertyNameIterator* Machine::cti_op_get_pnames(CTI_ARGS)
     4823{
     4824    return JSPropertyNameIterator::create(ARG_exec, ARG_src1);
     4825}
     4826
     4827JSValue* Machine::cti_op_next_pname(CTI_ARGS)
     4828{
     4829    JSPropertyNameIterator* it = ARG_pni1;
     4830    JSValue* temp = it->next(ARG_exec);
     4831    if (!temp)
     4832        it->invalidate();
     4833    return temp;
     4834}
     4835
     4836void Machine::cti_op_push_scope(CTI_ARGS)
     4837{
     4838    ExecState* exec = ARG_exec;
     4839
     4840    JSValue* v = ARG_src1;
     4841    JSObject* o = v->toObject(exec);
     4842    VM_CHECK_EXCEPTION_v();
     4843
     4844    ScopeChainNode* newScopeChain = ARG_scopeChain->push(o);
     4845    ARG_setScopeChain(newScopeChain);
     4846    exec->m_scopeChain = newScopeChain;
     4847}
     4848
     4849void Machine::cti_op_pop_scope(CTI_ARGS)
     4850{
     4851    ExecState* exec = ARG_exec;
     4852
     4853    ScopeChainNode* newScopeChain = ARG_scopeChain->pop();
     4854    ARG_setScopeChain(newScopeChain);
     4855    exec->m_scopeChain = newScopeChain;
     4856}
     4857
     4858JSValue* Machine::cti_op_typeof(CTI_ARGS)
     4859{
     4860    return jsTypeStringForValue(ARG_exec, ARG_src1);
     4861}
     4862
     4863JSValue* Machine::cti_op_stricteq(CTI_ARGS)
     4864{
     4865    JSValue* src1 = ARG_src1;
     4866    JSValue* src2 = ARG_src2;
     4867
     4868    if (JSImmediate::areBothImmediateNumbers(src1, src2))
     4869        return jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
     4870    else {
     4871        ExecState* exec = ARG_exec;
     4872        JSValue* result = jsBoolean(strictEqual(src1, src2));
     4873        VM_CHECK_EXCEPTION_AT_END();
     4874        return result;
     4875    }
     4876}
     4877
     4878JSValue* Machine::cti_op_nstricteq(CTI_ARGS)
     4879{
     4880    JSValue* src1 = ARG_src1;
     4881    JSValue* src2 = ARG_src2;
     4882
     4883    if (JSImmediate::areBothImmediateNumbers(src1, src2))
     4884        return jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
     4885    else {
     4886        ExecState* exec = ARG_exec;
     4887        JSValue* result = jsBoolean(!strictEqual(src1, src2));
     4888        VM_CHECK_EXCEPTION_AT_END();
     4889        return result;
     4890    }
     4891}
     4892
     4893JSValue* Machine::cti_op_to_jsnumber(CTI_ARGS)
     4894{
     4895    JSValue* src = ARG_src1;
     4896    ExecState* exec = ARG_exec;
     4897
     4898    JSValue* result = src->toJSNumber(exec);
     4899    VM_CHECK_EXCEPTION_AT_END();
     4900    return result;
     4901}
     4902
     4903JSValue* Machine::cti_op_in(CTI_ARGS)
     4904{
     4905    ExecState* exec = ARG_exec;
     4906    JSValue* baseVal = ARG_src2;
     4907
     4908    if (!baseVal->isObject()) {
     4909        CodeBlock* codeBlock = ARG_codeBlock;
     4910        ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
     4911        unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
     4912        exec->setException(createInvalidParamError(exec, "in", baseVal, codeBlock->instructions.begin() + vPCIndex, codeBlock));
     4913        VM_CHECK_EXCEPTION(JSValue*);
     4914    }
     4915
     4916    JSValue* propName = ARG_src1;
     4917    JSObject* baseObj = static_cast<JSObject*>(baseVal);
     4918
     4919    uint32_t i;
     4920    if (propName->getUInt32(i))
     4921        return jsBoolean(baseObj->hasProperty(exec, i));
     4922
     4923    Identifier property(exec, propName->toString(exec));
     4924    VM_CHECK_EXCEPTION(JSValue*);
     4925    return jsBoolean(baseObj->hasProperty(exec, property));
     4926}
     4927
     4928JSValue* Machine::cti_op_push_new_scope(CTI_ARGS)
     4929{
     4930    ExecState* exec = ARG_exec;
     4931    JSObject* scope = new (exec) JSStaticScopeObject(exec, *ARG_id1, ARG_src2, DontDelete);
     4932
     4933    ScopeChainNode* newScopeChain = ARG_scopeChain->push(scope);
     4934    ARG_setScopeChain(newScopeChain);
     4935    exec->m_scopeChain = newScopeChain;
     4936
     4937    return scope;
     4938}
     4939
     4940void Machine::cti_op_jmp_scopes(CTI_ARGS)
     4941{
     4942    ExecState* exec = ARG_exec;
     4943    unsigned count = ARG_int1;
     4944
     4945    ScopeChainNode* tmp = ARG_scopeChain;
     4946    while (count--)
     4947        tmp = tmp->pop();
     4948
     4949    ARG_setScopeChain(tmp);
     4950    exec->m_scopeChain = tmp;
     4951}
     4952
     4953void Machine::cti_op_put_by_index(CTI_ARGS)
     4954{
     4955    ExecState* exec = ARG_exec;
     4956    unsigned property = ARG_int2;
     4957
     4958    ARG_src1->put(exec, property, ARG_src3);
     4959}
     4960
     4961void* Machine::cti_op_switch_imm(CTI_ARGS)
     4962{
     4963    JSValue* scrutinee = ARG_src1;
     4964    unsigned tableIndex = ARG_int2;
     4965
     4966    CodeBlock* codeBlock = ARG_codeBlock;
     4967
     4968    if (JSImmediate::isNumber(scrutinee)) {
     4969        int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
     4970        return codeBlock->immediateSwitchJumpTables[tableIndex].ctiForValue(value);
     4971    }
     4972
     4973    return codeBlock->immediateSwitchJumpTables[tableIndex].ctiDefault;
     4974}
     4975
     4976void* Machine::cti_op_switch_char(CTI_ARGS)
     4977{
     4978    JSValue* scrutinee = ARG_src1;
     4979    unsigned tableIndex = ARG_int2;
     4980
     4981    CodeBlock* codeBlock = ARG_codeBlock;
     4982
     4983    void* result = codeBlock->characterSwitchJumpTables[tableIndex].ctiDefault;
     4984
     4985    if (scrutinee->isString()) {
     4986        UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
     4987        if (value->size() == 1)
     4988            result = codeBlock->characterSwitchJumpTables[tableIndex].ctiForValue(value->data()[0]);
     4989    }
     4990
     4991    return result;
     4992}
     4993
     4994void* Machine::cti_op_switch_string(CTI_ARGS)
     4995{
     4996    JSValue* scrutinee = ARG_src1;
     4997    unsigned tableIndex = ARG_int2;
     4998
     4999    CodeBlock* codeBlock = ARG_codeBlock;
     5000
     5001    void* result = codeBlock->stringSwitchJumpTables[tableIndex].ctiDefault;
     5002
     5003    if (scrutinee->isString()) {
     5004        UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
     5005        result = codeBlock->stringSwitchJumpTables[tableIndex].ctiForValue(value);
     5006    }
     5007
     5008    return result;
     5009}
     5010
     5011JSValue* Machine::cti_op_del_by_val(CTI_ARGS)
     5012{
     5013    ExecState* exec = ARG_exec;
     5014
     5015    JSValue* baseValue = ARG_src1;
     5016    JSObject* baseObj = baseValue->toObject(exec); // may throw
     5017
     5018    JSValue* subscript = ARG_src2;
     5019    JSValue* result;
     5020    uint32_t i;
     5021    if (subscript->getUInt32(i))
     5022        result = jsBoolean(baseObj->deleteProperty(exec, i));
     5023    else {
     5024        VM_CHECK_EXCEPTION(JSValue*);
     5025        Identifier property(exec, subscript->toString(exec));
     5026        VM_CHECK_EXCEPTION(JSValue*);
     5027        result = jsBoolean(baseObj->deleteProperty(exec, property));
     5028    }
     5029
     5030    VM_CHECK_EXCEPTION_AT_END();
     5031    return result;
     5032}
     5033
     5034void Machine::cti_op_put_getter(CTI_ARGS)
     5035{
     5036    ExecState* exec = ARG_exec;
     5037
     5038    ASSERT(ARG_src1->isObject());
     5039    JSObject* baseObj = static_cast<JSObject*>(ARG_src1);
     5040    Identifier& ident = *ARG_id2;
     5041    ASSERT(ARG_src3->isObject());
     5042    baseObj->defineGetter(exec, ident, static_cast<JSObject*>(ARG_src3));
     5043}
     5044
     5045void Machine::cti_op_put_setter(CTI_ARGS)
     5046{
     5047    ExecState* exec = ARG_exec;
     5048
     5049    ASSERT(ARG_src1->isObject());
     5050    JSObject* baseObj = static_cast<JSObject*>(ARG_src1);
     5051    Identifier& ident = *ARG_id2;
     5052    ASSERT(ARG_src3->isObject());
     5053    baseObj->defineSetter(exec, ident, static_cast<JSObject*>(ARG_src3));
     5054}
     5055
     5056JSValue* Machine::cti_op_new_error(CTI_ARGS)
     5057{
     5058    ExecState* exec = ARG_exec;
     5059    CodeBlock* codeBlock = ARG_codeBlock;
     5060    unsigned type = ARG_int1;
     5061    JSValue* message = ARG_src2;
     5062    unsigned lineNumber = ARG_int3;
     5063
     5064    return Error::create(exec, static_cast<ErrorType>(type), message->toString(exec), lineNumber, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
     5065}
     5066
     5067void Machine::cti_op_debug(CTI_ARGS)
     5068{
     5069    ExecState* exec = ARG_exec;
     5070    CodeBlock* codeBlock = ARG_codeBlock;
     5071    ScopeChainNode* scopeChain = ARG_scopeChain;
     5072    Register* r = ARG_r;
     5073
     5074    int debugHookID = ARG_int1;
     5075    int firstLine = ARG_int2;
     5076    int lastLine = ARG_int3;
     5077
     5078    exec->machine()->debug(exec, codeBlock, scopeChain, r, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
     5079}
     5080
     5081JSValue* Machine::cti_op_eq_null(CTI_ARGS)
     5082{
     5083    JSValue* src = ARG_src1;
     5084    if (src->isUndefinedOrNull())
     5085        return jsBoolean(true);
     5086
     5087    return jsBoolean(!JSImmediate::isImmediate(src) && static_cast<JSCell*>(src)->masqueradeAsUndefined());
     5088}
     5089
     5090JSValue* Machine::cti_op_neq_null(CTI_ARGS)
     5091{
     5092    JSValue* src = ARG_src1;
     5093    if (src->isUndefinedOrNull())
     5094        return jsBoolean(false);
     5095
     5096    return jsBoolean(JSImmediate::isImmediate(src) || !static_cast<JSCell*>(src)->masqueradeAsUndefined());
     5097}
     5098
     5099void* Machine::cti_vm_throw(CTI_ARGS)
     5100{
     5101    ExecState* exec = ARG_exec;
     5102    CodeBlock* codeBlock = ARG_codeBlock;
     5103    ScopeChainNode* scopeChain = ARG_scopeChain;
     5104    Register* r = ARG_r;
     5105
     5106    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(exec->ctiReturnAddress()));
     5107    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(exec->ctiReturnAddress());
     5108
     5109    ASSERT(exec->hadException());
     5110
     5111    JSValue* exceptionValue = exec->exception();
     5112
     5113    Instruction* handlerVPC = ARG_exec->machine()->throwException(exec, exceptionValue, codeBlock->instructions.begin() + vPCIndex, codeBlock, scopeChain, r, false);
     5114
     5115    if (handlerVPC) {
     5116        exec->setException(exceptionValue);
     5117        ARG_setScopeChain(scopeChain);
     5118        ARG_setCodeBlock(codeBlock);
     5119        ARG_setR(r);
     5120
     5121        void* catchRoutine = codeBlock->nativeExceptionCodeForHandlerVPC(handlerVPC);
     5122        ASSERT(catchRoutine);
     5123        ctiSetReturnAddress(&CTI_RETURN_ADDRESS, catchRoutine);
     5124        return catchRoutine;
     5125    } else {
     5126        exec->clearException();
     5127        *ARG_exception = exceptionValue;
     5128        return JSImmediate::nullImmediate();
     5129    }
     5130}
     5131
     5132#undef VM_CHECK_EXCEPTION
     5133#undef VM_CHECK_EXCEPTION_v
     5134#undef VM_CHECK_EXCEPTION_AT_END
     5135
     5136#endif // ENABLE(CTI)
     5137
    35015138} // namespace KJS
Note: See TracChangeset for help on using the changeset viewer.