From 8a6abe2247c623ea1e24666f0b2ecbb1288d719b Mon Sep 17 00:00:00 2001 From: "beard%netscape.com" Date: Wed, 26 Apr 2000 01:42:00 +0000 Subject: [PATCH] JSFrame -> JSLinkage, using explicit linked list rather than a stack. git-svn-id: svn://10.0.0.236/trunk@67165 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js/js2/interpreter.cpp | 595 +++++++++++++++++--------------- mozilla/js/js2/interpreter.h | 19 +- mozilla/js2/src/interpreter.cpp | 595 +++++++++++++++++--------------- mozilla/js2/src/interpreter.h | 19 +- 4 files changed, 662 insertions(+), 566 deletions(-) diff --git a/mozilla/js/js2/interpreter.cpp b/mozilla/js/js2/interpreter.cpp index 243205d6043..8d2989eda7a 100644 --- a/mozilla/js/js2/interpreter.cpp +++ b/mozilla/js/js2/interpreter.cpp @@ -50,289 +50,336 @@ namespace JavaScript { using namespace ICG; using namespace JSTypes; - JSValue - Context::interpret(ICodeModule* iCode, const JSValues& args) +// These classes are private to the JS interpreter. + +/** + * Represents the current function's invocation state. + */ +struct JSActivation : public gc_base { + JSValues mRegisters; + + JSActivation(ICodeModule* iCode, const JSValues& args) + : mRegisters(iCode->itsMaxRegister + 1) { - // stack of JSFrames. - // XXX is a linked list of activation's sufficient? - JSFrameStack frames; + // copy arg list to initial registers. + JSValues::iterator dest = mRegisters.begin(); + for (JSValues::const_iterator src = args.begin(), + end = args.end(); src != end; ++src, ++dest) { + *dest = *src; + } + } - // initial activation. - JSActivation* activation = new JSActivation(iCode, args); - JSValues* registers = &activation->mRegisters; + JSActivation(ICodeModule* iCode, JSActivation* caller, + const RegisterList& list) + : mRegisters(iCode->itsMaxRegister + 1) + { + // copy caller's parameter list to initial registers. + JSValues::iterator dest = mRegisters.begin(); + const JSValues& params = caller->mRegisters; + for (RegisterList::const_iterator src = list.begin(), + end = list.end(); src != end; ++src, ++dest) { + *dest = params[*src]; + } + } +}; - InstructionIterator begin_pc = iCode->its_iCode->begin(); - InstructionIterator pc = begin_pc; +/** + * Stores saved state from the *previous* activation, the current + * activation is alive and well in locals of the interpreter loop. + */ +struct JSLinkage : public gc_base { + JSLinkage* mPrevious; // previous linkage in linkage stack. + InstructionIterator mReturnPC; + InstructionIterator mBasePC; + JSActivation* mActivation; // caller's activation. + Register mResult; // the desired target register for the return value - std::vector catchStack; // <-- later will need to restore scope, other 'global' values - while (true) { - try { - Instruction* instruction = *pc; - switch (instruction->op()) { - case CALL: - { - Call* call = static_cast(instruction); - frames.push(new JSFrame(++pc, begin_pc, activation, - op1(call))); - ICodeModule* target = - (*registers)[op2(call)].function->getICode(); - activation = new JSActivation(target, activation, op3(call)); - registers = &activation->mRegisters; - begin_pc = pc = target->its_iCode->begin(); - } + JSLinkage(JSLinkage* previous, InstructionIterator returnPC, InstructionIterator basePC, + JSActivation* activation, Register result) + : mPrevious(previous), mReturnPC(returnPC), mBasePC(basePC), + mActivation(activation), mResult(result) + { + } +}; + +JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) +{ + // initial activation. + JSActivation* activation = new JSActivation(iCode, args); + JSValues* registers = &activation->mRegisters; + + InstructionIterator begin_pc = iCode->its_iCode->begin(); + InstructionIterator pc = begin_pc; + + std::vector catchStack; // <-- later will need to restore scope, other 'global' values + while (true) { + try { + Instruction* instruction = *pc; + switch (instruction->op()) { + case CALL: + { + Call* call = static_cast(instruction); + mLinkage = new JSLinkage(mLinkage, ++pc, begin_pc, activation, + op1(call)); + ICodeModule* target = + (*registers)[op2(call)].function->getICode(); + activation = new JSActivation(target, activation, op3(call)); + registers = &activation->mRegisters; + begin_pc = pc = target->its_iCode->begin(); + } + continue; + + case RETURN_VOID: + { + JSValue result(NotARegister); + JSLinkage *linkage = mLinkage; + if (!linkage) + return result; + mLinkage = linkage->mPrevious; + activation = linkage->mActivation; + registers = &activation->mRegisters; + (*registers)[linkage->mResult] = result; + pc = linkage->mReturnPC; + begin_pc = linkage->mBasePC; + } + continue; + + case RETURN: + { + Return* ret = static_cast(instruction); + JSValue result(NotARegister); + if (op1(ret) != NotARegister) + result = (*registers)[op1(ret)]; + JSLinkage* linkage = mLinkage; + if (!linkage) + return result; + mLinkage = linkage->mPrevious; + activation = linkage->mActivation; + registers = &activation->mRegisters; + (*registers)[linkage->mResult] = result; + pc = linkage->mReturnPC; + begin_pc = linkage->mBasePC; + } + continue; + case MOVE: + { + Move* mov = static_cast(instruction); + (*registers)[dst(mov)] = (*registers)[src1(mov)]; + } + break; + case LOAD_NAME: + { + LoadName* ln = static_cast(instruction); + (*registers)[dst(ln)] = (*mGlobal)[*src1(ln)]; + } + break; + case SAVE_NAME: + { + SaveName* sn = static_cast(instruction); + (*mGlobal)[*dst(sn)] = (*registers)[src1(sn)]; + } + break; + case NEW_OBJECT: + { + NewObject* no = static_cast(instruction); + (*registers)[dst(no)].object = new JSObject(); + } + break; + case NEW_ARRAY: + { + NewArray* na = static_cast(instruction); + (*registers)[dst(na)].array = new JSArray(); + } + break; + case GET_PROP: + { + GetProp* gp = static_cast(instruction); + JSObject* object = (*registers)[src1(gp)].object; + (*registers)[dst(gp)] = (*object)[*src2(gp)]; + } + break; + case SET_PROP: + { + SetProp* sp = static_cast(instruction); + JSObject* object = (*registers)[dst(sp)].object; + (*object)[*src1(sp)] = (*registers)[src2(sp)]; + } + break; + case GET_ELEMENT: + { + GetElement* ge = static_cast(instruction); + JSArray* array = (*registers)[src1(ge)].array; + (*registers)[dst(ge)] = (*array)[(*registers)[src2(ge)]]; + } + break; + case SET_ELEMENT: + { + SetElement* se = static_cast(instruction); + JSArray* array = (*registers)[dst(se)].array; + (*array)[(*registers)[src1(se)]] = (*registers)[src2(se)]; + } + break; + case LOAD_IMMEDIATE: + { + LoadImmediate* li = static_cast(instruction); + (*registers)[dst(li)] = JSValue(src1(li)); + } + break; + case BRANCH: + { + GenericBranch* bra = + static_cast(instruction); + pc = begin_pc + ofs(bra); continue; - - case RETURN_VOID: - { - JSValue result(NotARegister); - if (frames.empty()) - return result; - JSFrame *frame = frames.top(); - frames.pop(); - activation = frame->itsActivation; - registers = &activation->mRegisters; - (*registers)[frame->itsResult] = result; - pc = frame->itsReturnPC; - begin_pc = frame->itsBasePC; - } - continue; - - case RETURN: - { - Return* ret = static_cast(instruction); - JSValue result(NotARegister); - if (op1(ret) != NotARegister) - result = (*registers)[op1(ret)]; - if (frames.empty()) - return result; - JSFrame *frame = frames.top(); - frames.pop(); - activation = frame->itsActivation; - registers = &activation->mRegisters; - (*registers)[frame->itsResult] = result; - pc = frame->itsReturnPC; - begin_pc = frame->itsBasePC; - } - continue; - case MOVE: - { - Move* mov = static_cast(instruction); - (*registers)[dst(mov)] = (*registers)[src1(mov)]; - } - break; - case LOAD_NAME: - { - LoadName* ln = static_cast(instruction); - (*registers)[dst(ln)] = (*mGlobal)[*src1(ln)]; - } - break; - case SAVE_NAME: - { - SaveName* sn = static_cast(instruction); - (*mGlobal)[*dst(sn)] = (*registers)[src1(sn)]; - } - break; - case NEW_OBJECT: - { - NewObject* no = static_cast(instruction); - (*registers)[dst(no)].object = new JSObject(); - } - break; - case NEW_ARRAY: - { - NewArray* na = static_cast(instruction); - (*registers)[dst(na)].array = new JSArray(); - } - break; - case GET_PROP: - { - GetProp* gp = static_cast(instruction); - JSObject* object = (*registers)[src1(gp)].object; - (*registers)[dst(gp)] = (*object)[*src2(gp)]; - } - break; - case SET_PROP: - { - SetProp* sp = static_cast(instruction); - JSObject* object = (*registers)[dst(sp)].object; - (*object)[*src1(sp)] = (*registers)[src2(sp)]; - } - break; - case GET_ELEMENT: - { - GetElement* ge = static_cast(instruction); - JSArray* array = (*registers)[src1(ge)].array; - (*registers)[dst(ge)] = (*array)[(*registers)[src2(ge)]]; - } - break; - case SET_ELEMENT: - { - SetElement* se = static_cast(instruction); - JSArray* array = (*registers)[dst(se)].array; - (*array)[(*registers)[src1(se)]] = (*registers)[src2(se)]; - } - break; - case LOAD_IMMEDIATE: - { - LoadImmediate* li = static_cast(instruction); - (*registers)[dst(li)] = JSValue(src1(li)); - } - break; - case BRANCH: - { - GenericBranch* bra = - static_cast(instruction); - pc = begin_pc + ofs(bra); + } + break; + case BRANCH_LT: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 < 0) { + pc = begin_pc + ofs(bc); continue; } - break; - case BRANCH_LT: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 < 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case BRANCH_LE: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 <= 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case BRANCH_EQ: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 == 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case BRANCH_NE: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 != 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case BRANCH_GE: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 >= 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case BRANCH_GT: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 > 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case ADD: - { - // could get clever here with Functional forms. - Arithmetic* add = static_cast(instruction); - (*registers)[dst(add)] = - JSValue((*registers)[src1(add)].f64 + - (*registers)[src2(add)].f64); - } - break; - case SUBTRACT: - { - Arithmetic* sub = static_cast(instruction); - (*registers)[dst(sub)] = - JSValue((*registers)[src1(sub)].f64 - - (*registers)[src2(sub)].f64); - } - break; - case MULTIPLY: - { - Arithmetic* mul = static_cast(instruction); - (*registers)[dst(mul)] = - JSValue((*registers)[src1(mul)].f64 * - (*registers)[src2(mul)].f64); - } - break; - case DIVIDE: - { - Arithmetic* div = static_cast(instruction); - (*registers)[dst(div)] = - JSValue((*registers)[src1(div)].f64 / - (*registers)[src2(div)].f64); - } - break; - case COMPARE_LT: - case COMPARE_LE: - case COMPARE_EQ: - case COMPARE_NE: - case COMPARE_GT: - case COMPARE_GE: - { - Arithmetic* cmp = static_cast(instruction); - float64 diff = - ((*registers)[src1(cmp)].f64 - - (*registers)[src2(cmp)].f64); - (*registers)[dst(cmp)].i32 = - (diff == 0.0 ? 0 : (diff > 0.0 ? 1 : -1)); - } - break; - case NOT: - { - Not* nt = static_cast(instruction); - (*registers)[dst(nt)].i32 = !(*registers)[src1(nt)].i32; - } - break; - - case THROW : - { - throw new JS_Exception(); - } - - case TRY: - { // push the catch handler address onto the try stack - // why did Rhino interpreter also have a finally stack? - Try* tri = static_cast(instruction); - catchStack.push_back(begin_pc + ofs(tri)); - } - break; - case ENDTRY : - { - catchStack.pop_back(); - } - break; - - default: - NOT_REACHED("bad opcode"); - break; } - - // increment the program counter. - ++pc; - } - catch (JS_Exception ) { - ASSERT(!catchStack.empty()); - pc = catchStack.back(); - catchStack.pop_back(); + break; + case BRANCH_LE: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 <= 0) { + pc = begin_pc + ofs(bc); + continue; + } + } + break; + case BRANCH_EQ: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 == 0) { + pc = begin_pc + ofs(bc); + continue; + } + } + break; + case BRANCH_NE: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 != 0) { + pc = begin_pc + ofs(bc); + continue; + } + } + break; + case BRANCH_GE: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 >= 0) { + pc = begin_pc + ofs(bc); + continue; + } + } + break; + case BRANCH_GT: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 > 0) { + pc = begin_pc + ofs(bc); + continue; + } + } + break; + case ADD: + { + // could get clever here with Functional forms. + Arithmetic* add = static_cast(instruction); + (*registers)[dst(add)] = + JSValue((*registers)[src1(add)].f64 + + (*registers)[src2(add)].f64); + } + break; + case SUBTRACT: + { + Arithmetic* sub = static_cast(instruction); + (*registers)[dst(sub)] = + JSValue((*registers)[src1(sub)].f64 - + (*registers)[src2(sub)].f64); + } + break; + case MULTIPLY: + { + Arithmetic* mul = static_cast(instruction); + (*registers)[dst(mul)] = + JSValue((*registers)[src1(mul)].f64 * + (*registers)[src2(mul)].f64); + } + break; + case DIVIDE: + { + Arithmetic* div = static_cast(instruction); + (*registers)[dst(div)] = + JSValue((*registers)[src1(div)].f64 / + (*registers)[src2(div)].f64); + } + break; + case COMPARE_LT: + case COMPARE_LE: + case COMPARE_EQ: + case COMPARE_NE: + case COMPARE_GT: + case COMPARE_GE: + { + Arithmetic* cmp = static_cast(instruction); + float64 diff = + ((*registers)[src1(cmp)].f64 - + (*registers)[src2(cmp)].f64); + (*registers)[dst(cmp)].i32 = + (diff == 0.0 ? 0 : (diff > 0.0 ? 1 : -1)); + } + break; + case NOT: + { + Not* nt = static_cast(instruction); + (*registers)[dst(nt)].i32 = !(*registers)[src1(nt)].i32; + } + break; + + case THROW : + { + throw new JS_Exception(); + } + + case TRY: + { // push the catch handler address onto the try stack + // why did Rhino interpreter also have a finally stack? + Try* tri = static_cast(instruction); + catchStack.push_back(begin_pc + ofs(tri)); + } + break; + case ENDTRY : + { + catchStack.pop_back(); + } + break; + + default: + NOT_REACHED("bad opcode"); + break; } + + // increment the program counter. + ++pc; } - } /* interpret */ + catch (JS_Exception ) { + ASSERT(!catchStack.empty()); + pc = catchStack.back(); + catchStack.pop_back(); + } + } +} /* interpret */ } /* namespace JavaScript */ diff --git a/mozilla/js/js2/interpreter.h b/mozilla/js/js2/interpreter.h index 2e44da313c5..3a30bba94be 100644 --- a/mozilla/js/js2/interpreter.h +++ b/mozilla/js/js2/interpreter.h @@ -29,12 +29,16 @@ namespace JavaScript { using namespace ICG; using namespace JSTypes; + struct JSLinkage; + class Context : public gc_base { public: - explicit Context(World& /*world */, JSObject* aGlobal) : - mGlobal(aGlobal) {} + explicit Context(World& world, JSObject* aGlobal) + : mWorld(world), mGlobal(aGlobal), mLinkage(0) + { + } - JSValue interpret(ICodeModule* iCode, const JSValues& args); + JSObject* getGlobalObject() { return mGlobal; } JSObject* setGlobalObject(JSObject* aGlobal) { @@ -43,15 +47,12 @@ namespace JavaScript { return t; } - JSObject* getGlobalObject() - { - return mGlobal; - } + JSValue interpret(ICodeModule* iCode, const JSValues& args); private: - /* World mWorld; */ + World& mWorld; JSObject* mGlobal; - + JSLinkage* mLinkage; }; /* class Interpreter */ } /* namespace JavaScript */ diff --git a/mozilla/js2/src/interpreter.cpp b/mozilla/js2/src/interpreter.cpp index 243205d6043..8d2989eda7a 100644 --- a/mozilla/js2/src/interpreter.cpp +++ b/mozilla/js2/src/interpreter.cpp @@ -50,289 +50,336 @@ namespace JavaScript { using namespace ICG; using namespace JSTypes; - JSValue - Context::interpret(ICodeModule* iCode, const JSValues& args) +// These classes are private to the JS interpreter. + +/** + * Represents the current function's invocation state. + */ +struct JSActivation : public gc_base { + JSValues mRegisters; + + JSActivation(ICodeModule* iCode, const JSValues& args) + : mRegisters(iCode->itsMaxRegister + 1) { - // stack of JSFrames. - // XXX is a linked list of activation's sufficient? - JSFrameStack frames; + // copy arg list to initial registers. + JSValues::iterator dest = mRegisters.begin(); + for (JSValues::const_iterator src = args.begin(), + end = args.end(); src != end; ++src, ++dest) { + *dest = *src; + } + } - // initial activation. - JSActivation* activation = new JSActivation(iCode, args); - JSValues* registers = &activation->mRegisters; + JSActivation(ICodeModule* iCode, JSActivation* caller, + const RegisterList& list) + : mRegisters(iCode->itsMaxRegister + 1) + { + // copy caller's parameter list to initial registers. + JSValues::iterator dest = mRegisters.begin(); + const JSValues& params = caller->mRegisters; + for (RegisterList::const_iterator src = list.begin(), + end = list.end(); src != end; ++src, ++dest) { + *dest = params[*src]; + } + } +}; - InstructionIterator begin_pc = iCode->its_iCode->begin(); - InstructionIterator pc = begin_pc; +/** + * Stores saved state from the *previous* activation, the current + * activation is alive and well in locals of the interpreter loop. + */ +struct JSLinkage : public gc_base { + JSLinkage* mPrevious; // previous linkage in linkage stack. + InstructionIterator mReturnPC; + InstructionIterator mBasePC; + JSActivation* mActivation; // caller's activation. + Register mResult; // the desired target register for the return value - std::vector catchStack; // <-- later will need to restore scope, other 'global' values - while (true) { - try { - Instruction* instruction = *pc; - switch (instruction->op()) { - case CALL: - { - Call* call = static_cast(instruction); - frames.push(new JSFrame(++pc, begin_pc, activation, - op1(call))); - ICodeModule* target = - (*registers)[op2(call)].function->getICode(); - activation = new JSActivation(target, activation, op3(call)); - registers = &activation->mRegisters; - begin_pc = pc = target->its_iCode->begin(); - } + JSLinkage(JSLinkage* previous, InstructionIterator returnPC, InstructionIterator basePC, + JSActivation* activation, Register result) + : mPrevious(previous), mReturnPC(returnPC), mBasePC(basePC), + mActivation(activation), mResult(result) + { + } +}; + +JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) +{ + // initial activation. + JSActivation* activation = new JSActivation(iCode, args); + JSValues* registers = &activation->mRegisters; + + InstructionIterator begin_pc = iCode->its_iCode->begin(); + InstructionIterator pc = begin_pc; + + std::vector catchStack; // <-- later will need to restore scope, other 'global' values + while (true) { + try { + Instruction* instruction = *pc; + switch (instruction->op()) { + case CALL: + { + Call* call = static_cast(instruction); + mLinkage = new JSLinkage(mLinkage, ++pc, begin_pc, activation, + op1(call)); + ICodeModule* target = + (*registers)[op2(call)].function->getICode(); + activation = new JSActivation(target, activation, op3(call)); + registers = &activation->mRegisters; + begin_pc = pc = target->its_iCode->begin(); + } + continue; + + case RETURN_VOID: + { + JSValue result(NotARegister); + JSLinkage *linkage = mLinkage; + if (!linkage) + return result; + mLinkage = linkage->mPrevious; + activation = linkage->mActivation; + registers = &activation->mRegisters; + (*registers)[linkage->mResult] = result; + pc = linkage->mReturnPC; + begin_pc = linkage->mBasePC; + } + continue; + + case RETURN: + { + Return* ret = static_cast(instruction); + JSValue result(NotARegister); + if (op1(ret) != NotARegister) + result = (*registers)[op1(ret)]; + JSLinkage* linkage = mLinkage; + if (!linkage) + return result; + mLinkage = linkage->mPrevious; + activation = linkage->mActivation; + registers = &activation->mRegisters; + (*registers)[linkage->mResult] = result; + pc = linkage->mReturnPC; + begin_pc = linkage->mBasePC; + } + continue; + case MOVE: + { + Move* mov = static_cast(instruction); + (*registers)[dst(mov)] = (*registers)[src1(mov)]; + } + break; + case LOAD_NAME: + { + LoadName* ln = static_cast(instruction); + (*registers)[dst(ln)] = (*mGlobal)[*src1(ln)]; + } + break; + case SAVE_NAME: + { + SaveName* sn = static_cast(instruction); + (*mGlobal)[*dst(sn)] = (*registers)[src1(sn)]; + } + break; + case NEW_OBJECT: + { + NewObject* no = static_cast(instruction); + (*registers)[dst(no)].object = new JSObject(); + } + break; + case NEW_ARRAY: + { + NewArray* na = static_cast(instruction); + (*registers)[dst(na)].array = new JSArray(); + } + break; + case GET_PROP: + { + GetProp* gp = static_cast(instruction); + JSObject* object = (*registers)[src1(gp)].object; + (*registers)[dst(gp)] = (*object)[*src2(gp)]; + } + break; + case SET_PROP: + { + SetProp* sp = static_cast(instruction); + JSObject* object = (*registers)[dst(sp)].object; + (*object)[*src1(sp)] = (*registers)[src2(sp)]; + } + break; + case GET_ELEMENT: + { + GetElement* ge = static_cast(instruction); + JSArray* array = (*registers)[src1(ge)].array; + (*registers)[dst(ge)] = (*array)[(*registers)[src2(ge)]]; + } + break; + case SET_ELEMENT: + { + SetElement* se = static_cast(instruction); + JSArray* array = (*registers)[dst(se)].array; + (*array)[(*registers)[src1(se)]] = (*registers)[src2(se)]; + } + break; + case LOAD_IMMEDIATE: + { + LoadImmediate* li = static_cast(instruction); + (*registers)[dst(li)] = JSValue(src1(li)); + } + break; + case BRANCH: + { + GenericBranch* bra = + static_cast(instruction); + pc = begin_pc + ofs(bra); continue; - - case RETURN_VOID: - { - JSValue result(NotARegister); - if (frames.empty()) - return result; - JSFrame *frame = frames.top(); - frames.pop(); - activation = frame->itsActivation; - registers = &activation->mRegisters; - (*registers)[frame->itsResult] = result; - pc = frame->itsReturnPC; - begin_pc = frame->itsBasePC; - } - continue; - - case RETURN: - { - Return* ret = static_cast(instruction); - JSValue result(NotARegister); - if (op1(ret) != NotARegister) - result = (*registers)[op1(ret)]; - if (frames.empty()) - return result; - JSFrame *frame = frames.top(); - frames.pop(); - activation = frame->itsActivation; - registers = &activation->mRegisters; - (*registers)[frame->itsResult] = result; - pc = frame->itsReturnPC; - begin_pc = frame->itsBasePC; - } - continue; - case MOVE: - { - Move* mov = static_cast(instruction); - (*registers)[dst(mov)] = (*registers)[src1(mov)]; - } - break; - case LOAD_NAME: - { - LoadName* ln = static_cast(instruction); - (*registers)[dst(ln)] = (*mGlobal)[*src1(ln)]; - } - break; - case SAVE_NAME: - { - SaveName* sn = static_cast(instruction); - (*mGlobal)[*dst(sn)] = (*registers)[src1(sn)]; - } - break; - case NEW_OBJECT: - { - NewObject* no = static_cast(instruction); - (*registers)[dst(no)].object = new JSObject(); - } - break; - case NEW_ARRAY: - { - NewArray* na = static_cast(instruction); - (*registers)[dst(na)].array = new JSArray(); - } - break; - case GET_PROP: - { - GetProp* gp = static_cast(instruction); - JSObject* object = (*registers)[src1(gp)].object; - (*registers)[dst(gp)] = (*object)[*src2(gp)]; - } - break; - case SET_PROP: - { - SetProp* sp = static_cast(instruction); - JSObject* object = (*registers)[dst(sp)].object; - (*object)[*src1(sp)] = (*registers)[src2(sp)]; - } - break; - case GET_ELEMENT: - { - GetElement* ge = static_cast(instruction); - JSArray* array = (*registers)[src1(ge)].array; - (*registers)[dst(ge)] = (*array)[(*registers)[src2(ge)]]; - } - break; - case SET_ELEMENT: - { - SetElement* se = static_cast(instruction); - JSArray* array = (*registers)[dst(se)].array; - (*array)[(*registers)[src1(se)]] = (*registers)[src2(se)]; - } - break; - case LOAD_IMMEDIATE: - { - LoadImmediate* li = static_cast(instruction); - (*registers)[dst(li)] = JSValue(src1(li)); - } - break; - case BRANCH: - { - GenericBranch* bra = - static_cast(instruction); - pc = begin_pc + ofs(bra); + } + break; + case BRANCH_LT: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 < 0) { + pc = begin_pc + ofs(bc); continue; } - break; - case BRANCH_LT: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 < 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case BRANCH_LE: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 <= 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case BRANCH_EQ: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 == 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case BRANCH_NE: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 != 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case BRANCH_GE: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 >= 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case BRANCH_GT: - { - GenericBranch* bc = - static_cast(instruction); - if ((*registers)[src1(bc)].i32 > 0) { - pc = begin_pc + ofs(bc); - continue; - } - } - break; - case ADD: - { - // could get clever here with Functional forms. - Arithmetic* add = static_cast(instruction); - (*registers)[dst(add)] = - JSValue((*registers)[src1(add)].f64 + - (*registers)[src2(add)].f64); - } - break; - case SUBTRACT: - { - Arithmetic* sub = static_cast(instruction); - (*registers)[dst(sub)] = - JSValue((*registers)[src1(sub)].f64 - - (*registers)[src2(sub)].f64); - } - break; - case MULTIPLY: - { - Arithmetic* mul = static_cast(instruction); - (*registers)[dst(mul)] = - JSValue((*registers)[src1(mul)].f64 * - (*registers)[src2(mul)].f64); - } - break; - case DIVIDE: - { - Arithmetic* div = static_cast(instruction); - (*registers)[dst(div)] = - JSValue((*registers)[src1(div)].f64 / - (*registers)[src2(div)].f64); - } - break; - case COMPARE_LT: - case COMPARE_LE: - case COMPARE_EQ: - case COMPARE_NE: - case COMPARE_GT: - case COMPARE_GE: - { - Arithmetic* cmp = static_cast(instruction); - float64 diff = - ((*registers)[src1(cmp)].f64 - - (*registers)[src2(cmp)].f64); - (*registers)[dst(cmp)].i32 = - (diff == 0.0 ? 0 : (diff > 0.0 ? 1 : -1)); - } - break; - case NOT: - { - Not* nt = static_cast(instruction); - (*registers)[dst(nt)].i32 = !(*registers)[src1(nt)].i32; - } - break; - - case THROW : - { - throw new JS_Exception(); - } - - case TRY: - { // push the catch handler address onto the try stack - // why did Rhino interpreter also have a finally stack? - Try* tri = static_cast(instruction); - catchStack.push_back(begin_pc + ofs(tri)); - } - break; - case ENDTRY : - { - catchStack.pop_back(); - } - break; - - default: - NOT_REACHED("bad opcode"); - break; } - - // increment the program counter. - ++pc; - } - catch (JS_Exception ) { - ASSERT(!catchStack.empty()); - pc = catchStack.back(); - catchStack.pop_back(); + break; + case BRANCH_LE: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 <= 0) { + pc = begin_pc + ofs(bc); + continue; + } + } + break; + case BRANCH_EQ: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 == 0) { + pc = begin_pc + ofs(bc); + continue; + } + } + break; + case BRANCH_NE: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 != 0) { + pc = begin_pc + ofs(bc); + continue; + } + } + break; + case BRANCH_GE: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 >= 0) { + pc = begin_pc + ofs(bc); + continue; + } + } + break; + case BRANCH_GT: + { + GenericBranch* bc = + static_cast(instruction); + if ((*registers)[src1(bc)].i32 > 0) { + pc = begin_pc + ofs(bc); + continue; + } + } + break; + case ADD: + { + // could get clever here with Functional forms. + Arithmetic* add = static_cast(instruction); + (*registers)[dst(add)] = + JSValue((*registers)[src1(add)].f64 + + (*registers)[src2(add)].f64); + } + break; + case SUBTRACT: + { + Arithmetic* sub = static_cast(instruction); + (*registers)[dst(sub)] = + JSValue((*registers)[src1(sub)].f64 - + (*registers)[src2(sub)].f64); + } + break; + case MULTIPLY: + { + Arithmetic* mul = static_cast(instruction); + (*registers)[dst(mul)] = + JSValue((*registers)[src1(mul)].f64 * + (*registers)[src2(mul)].f64); + } + break; + case DIVIDE: + { + Arithmetic* div = static_cast(instruction); + (*registers)[dst(div)] = + JSValue((*registers)[src1(div)].f64 / + (*registers)[src2(div)].f64); + } + break; + case COMPARE_LT: + case COMPARE_LE: + case COMPARE_EQ: + case COMPARE_NE: + case COMPARE_GT: + case COMPARE_GE: + { + Arithmetic* cmp = static_cast(instruction); + float64 diff = + ((*registers)[src1(cmp)].f64 - + (*registers)[src2(cmp)].f64); + (*registers)[dst(cmp)].i32 = + (diff == 0.0 ? 0 : (diff > 0.0 ? 1 : -1)); + } + break; + case NOT: + { + Not* nt = static_cast(instruction); + (*registers)[dst(nt)].i32 = !(*registers)[src1(nt)].i32; + } + break; + + case THROW : + { + throw new JS_Exception(); + } + + case TRY: + { // push the catch handler address onto the try stack + // why did Rhino interpreter also have a finally stack? + Try* tri = static_cast(instruction); + catchStack.push_back(begin_pc + ofs(tri)); + } + break; + case ENDTRY : + { + catchStack.pop_back(); + } + break; + + default: + NOT_REACHED("bad opcode"); + break; } + + // increment the program counter. + ++pc; } - } /* interpret */ + catch (JS_Exception ) { + ASSERT(!catchStack.empty()); + pc = catchStack.back(); + catchStack.pop_back(); + } + } +} /* interpret */ } /* namespace JavaScript */ diff --git a/mozilla/js2/src/interpreter.h b/mozilla/js2/src/interpreter.h index 2e44da313c5..3a30bba94be 100644 --- a/mozilla/js2/src/interpreter.h +++ b/mozilla/js2/src/interpreter.h @@ -29,12 +29,16 @@ namespace JavaScript { using namespace ICG; using namespace JSTypes; + struct JSLinkage; + class Context : public gc_base { public: - explicit Context(World& /*world */, JSObject* aGlobal) : - mGlobal(aGlobal) {} + explicit Context(World& world, JSObject* aGlobal) + : mWorld(world), mGlobal(aGlobal), mLinkage(0) + { + } - JSValue interpret(ICodeModule* iCode, const JSValues& args); + JSObject* getGlobalObject() { return mGlobal; } JSObject* setGlobalObject(JSObject* aGlobal) { @@ -43,15 +47,12 @@ namespace JavaScript { return t; } - JSObject* getGlobalObject() - { - return mGlobal; - } + JSValue interpret(ICodeModule* iCode, const JSValues& args); private: - /* World mWorld; */ + World& mWorld; JSObject* mGlobal; - + JSLinkage* mLinkage; }; /* class Interpreter */ } /* namespace JavaScript */