diff --git a/js/js2/icodegenerator.cpp b/js/js2/icodegenerator.cpp index 96a4b6c72fa..257550a4a3c 100644 --- a/js/js2/icodegenerator.cpp +++ b/js/js2/icodegenerator.cpp @@ -41,601 +41,601 @@ namespace JavaScript { - namespace ICG { +namespace ICG { - using namespace VM; + using namespace VM; - Formatter& operator<<(Formatter &f, ICodeGenerator &i) - { - return i.print(f); - } + Formatter& operator<<(Formatter &f, ICodeGenerator &i) + { + return i.print(f); + } - // - // ICodeGenerator - // + // + // ICodeGenerator + // - ICodeModule *ICodeGenerator:: -complete() - { + ICodeModule *ICodeGenerator::complete() + { #ifdef DEBUG - ASSERT(stitcher.empty()); - for (LabelList::iterator i = labels.begin(); - i != labels.end(); i++) { - ASSERT((*i)->base == iCode); - ASSERT((*i)->offset <= iCode->size()); - } + ASSERT(stitcher.empty()); + for (LabelList::iterator i = labels.begin(); + i != labels.end(); i++) { + ASSERT((*i)->base == iCode); + ASSERT((*i)->offset <= iCode->size()); + } #endif -/* - for (InstructionIterator ii = iCode->begin(); - ii != iCode->end(); ii++) { - if ((*ii)->op() == BRANCH) { + + /* + for (InstructionIterator ii = iCode->begin(); + ii != iCode->end(); ii++) { + if ((*ii)->op() == BRANCH) { + Instruction *t = *ii; + *ii = new ResolvedBranch(static_cast(*ii)->operand1->itsOffset); + delete t; + } + else + if ((*ii)->itsOp >= BRANCH_LT && (*ii)->itsOp <= BRANCH_GT) { Instruction *t = *ii; - *ii = new ResolvedBranch(static_cast(*ii)->operand1->itsOffset); + *ii = new ResolvedBranchCond((*ii)->itsOp, + static_cast(*ii)->itsOperand1->itsOffset, + static_cast(*ii)->itsOperand2); delete t; } - else - if ((*ii)->itsOp >= BRANCH_LT && (*ii)->itsOp <= BRANCH_GT) { - Instruction *t = *ii; - *ii = new ResolvedBranchCond((*ii)->itsOp, - static_cast(*ii)->itsOperand1->itsOffset, - static_cast(*ii)->itsOperand2); - delete t; - } - } -*/ - markMaxRegister(); + } + */ + markMaxRegister(); - return new ICodeModule(iCode, maxRegister, maxVariable); - } + return new ICodeModule(iCode, maxRegister, maxVariable); + } - /********************************************************************/ + /********************************************************************/ - Register ICodeGenerator::loadVariable(uint32 frameIndex) - { - markMaxVariable(frameIndex); - Register dest = getRegister(); - LoadVar *instr = new LoadVar(dest, frameIndex); - iCode->push_back(instr); - return dest; - } + Register ICodeGenerator::loadVariable(uint32 frameIndex) + { + markMaxVariable(frameIndex); + Register dest = getRegister(); + LoadVar *instr = new LoadVar(dest, frameIndex); + iCode->push_back(instr); + return dest; + } - void ICodeGenerator::saveVariable(uint32 frameIndex, Register value) - { - markMaxVariable(frameIndex); - SaveVar *instr = new SaveVar(frameIndex, value); - iCode->push_back(instr); - } + void ICodeGenerator::saveVariable(uint32 frameIndex, Register value) + { + markMaxVariable(frameIndex); + SaveVar *instr = new SaveVar(frameIndex, value); + iCode->push_back(instr); + } - Register ICodeGenerator::loadImmediate(double value) - { - Register dest = getRegister(); - LoadImmediate *instr = new LoadImmediate(dest, value); - iCode->push_back(instr); - return dest; - } + Register ICodeGenerator::loadImmediate(double value) + { + Register dest = getRegister(); + LoadImmediate *instr = new LoadImmediate(dest, value); + iCode->push_back(instr); + return dest; + } - Register ICodeGenerator::newObject() - { - Register dest = getRegister(); - NewObject *instr = new NewObject(dest); - iCode->push_back(instr); - return dest; - } + Register ICodeGenerator::newObject() + { + Register dest = getRegister(); + NewObject *instr = new NewObject(dest); + iCode->push_back(instr); + return dest; + } - Register ICodeGenerator::newArray() - { - Register dest = getRegister(); - NewArray *instr = new NewArray(dest); - iCode->push_back(instr); - return dest; - } + Register ICodeGenerator::newArray() + { + Register dest = getRegister(); + NewArray *instr = new NewArray(dest); + iCode->push_back(instr); + return dest; + } - Register ICodeGenerator::loadName(StringAtom &name) - { - Register dest = getRegister(); - LoadName *instr = new LoadName(dest, &name); - iCode->push_back(instr); - return dest; - } + Register ICodeGenerator::loadName(StringAtom &name) + { + Register dest = getRegister(); + LoadName *instr = new LoadName(dest, &name); + iCode->push_back(instr); + return dest; + } - void ICodeGenerator::saveName(StringAtom &name, Register value) - { - SaveName *instr = new SaveName(&name, value); - iCode->push_back(instr); - } + void ICodeGenerator::saveName(StringAtom &name, Register value) + { + SaveName *instr = new SaveName(&name, value); + iCode->push_back(instr); + } - Register ICodeGenerator::getProperty(Register base, StringAtom &name) - { - Register dest = getRegister(); - GetProp *instr = new GetProp(dest, base, &name); - iCode->push_back(instr); - return dest; - } + Register ICodeGenerator::getProperty(Register base, StringAtom &name) + { + Register dest = getRegister(); + GetProp *instr = new GetProp(dest, base, &name); + iCode->push_back(instr); + return dest; + } - void ICodeGenerator::setProperty(Register base, StringAtom &name, - Register value) - { - SetProp *instr = new SetProp(base, &name, value); - iCode->push_back(instr); - } + void ICodeGenerator::setProperty(Register base, StringAtom &name, + Register value) + { + SetProp *instr = new SetProp(base, &name, value); + iCode->push_back(instr); + } - Register ICodeGenerator::getElement(Register base, Register index) - { - Register dest = getRegister(); - GetElement *instr = new GetElement(dest, base, index); - iCode->push_back(instr); - return dest; - } + Register ICodeGenerator::getElement(Register base, Register index) + { + Register dest = getRegister(); + GetElement *instr = new GetElement(dest, base, index); + iCode->push_back(instr); + return dest; + } - void ICodeGenerator::setElement(Register base, Register index, - Register value) - { - SetElement *instr = new SetElement(base, index, value); - iCode->push_back(instr); - } + void ICodeGenerator::setElement(Register base, Register index, + Register value) + { + SetElement *instr = new SetElement(base, index, value); + iCode->push_back(instr); + } - Register ICodeGenerator::op(ICodeOp op, Register source) - { - Register dest = getRegister(); - Compare *instr = new Compare (op, dest, source); - iCode->push_back(instr); - return dest; - } + Register ICodeGenerator::op(ICodeOp op, Register source) + { + Register dest = getRegister(); + Compare *instr = new Compare (op, dest, source); + iCode->push_back(instr); + return dest; + } - Register ICodeGenerator::op(ICodeOp op, Register source1, - Register source2) - { - Register dest = getRegister(); - Arithmetic *instr = new Arithmetic(op, dest, source1, source2); - iCode->push_back(instr); - return dest; - } + Register ICodeGenerator::op(ICodeOp op, Register source1, + Register source2) + { + Register dest = getRegister(); + Arithmetic *instr = new Arithmetic(op, dest, source1, source2); + iCode->push_back(instr); + return dest; + } - Register ICodeGenerator::call(Register target, RegisterList args) - { - Register dest = getRegister(); - Call *instr = new Call(dest, target, args); - iCode->push_back(instr); - return dest; - } + Register ICodeGenerator::call(Register target, RegisterList args) + { + Register dest = getRegister(); + Call *instr = new Call(dest, target, args); + iCode->push_back(instr); + return dest; + } - void ICodeGenerator::branch(Label *label) - { - Branch *instr = new Branch(label); - iCode->push_back(instr); - } + void ICodeGenerator::branch(Label *label) + { + Branch *instr = new Branch(label); + iCode->push_back(instr); + } - void ICodeGenerator::branchConditional(Label *label, Register condition) - { - ICodeOp branchOp = getBranchOp(); - if (branchOp == NOP) { - // XXXX emit convert to boolean / Test / ... - branchOp = BRANCH_NE; + void ICodeGenerator::branchConditional(Label *label, Register condition) + { + ICodeOp branchOp = getBranchOp(); + if (branchOp == NOP) { + // XXXX emit convert to boolean / Test / ... + branchOp = BRANCH_NE; + } + GenericBranch *instr = new GenericBranch(branchOp, label, condition); + iCode->push_back(instr); + } + + /********************************************************************/ + + Label *ICodeGenerator::getLabel() + { + labels.push_back(new Label(NULL)); + return labels.back(); + } + + void ICodeGenerator::setLabel(Label *l) + { + l->base = iCode; + l->offset = static_cast(iCode->size()); + } + + void ICodeGenerator::setLabel(InstructionStream *stream, Label *l) + { + l->base = stream; + l->offset = static_cast(stream->size()); + } + + /********************************************************************/ + + void ICodeGenerator::mergeStream(InstructionStream *sideStream) + { + // change InstructionStream to be a class that also remembers + // if it contains any labels (maybe even remembers the labels + // themselves?) in order to avoid running this loop unnecessarily. + for (LabelList::iterator i = labels.begin(); + i != labels.end(); i++) { + if ((*i)->base == sideStream) { + (*i)->base = iCode; + (*i)->offset += iCode->size(); } - GenericBranch *instr = new GenericBranch(branchOp, label, condition); - iCode->push_back(instr); } - /********************************************************************/ - - Label *ICodeGenerator::getLabel() - { - labels.push_back(new Label(NULL)); - return labels.back(); + for (InstructionIterator ii = sideStream->begin(); + ii != sideStream->end(); ii++) { + iCode->push_back(*ii); } - void ICodeGenerator::setLabel(Label *l) - { - l->base = iCode; - l->offset = static_cast(iCode->size()); - } + } - void ICodeGenerator::setLabel(InstructionStream *stream, Label *l) - { - l->base = stream; - l->offset = static_cast(stream->size()); - } + /********************************************************************/ - /********************************************************************/ - - void ICodeGenerator::mergeStream(InstructionStream *sideStream) - { - // change InstructionStream to be a class that also remembers - // if it contains any labels (maybe even remembers the labels - // themselves?) in order to avoid running this loop unnecessarily. - for (LabelList::iterator i = labels.begin(); - i != labels.end(); i++) { - if ((*i)->base == sideStream) { - (*i)->base = iCode; - (*i)->offset += iCode->size(); - } - } - - for (InstructionIterator ii = sideStream->begin(); - ii != sideStream->end(); ii++) { - iCode->push_back(*ii); - } - - } - - /********************************************************************/ - - void ICodeGenerator::beginWhileStatement(uint32) - { - resetTopRegister(); + void ICodeGenerator::beginWhileStatement(uint32) + { + resetTopRegister(); - // insert a branch to the while condition, which we're - // moving to follow the while block - Label *whileConditionTop = getLabel(); - Label *whileBlockStart = getLabel(); - branch(whileConditionTop); + // insert a branch to the while condition, which we're + // moving to follow the while block + Label *whileConditionTop = getLabel(); + Label *whileBlockStart = getLabel(); + branch(whileConditionTop); - // save off the current stream while we gen code for the condition - stitcher.push_back(new WhileCodeState(whileConditionTop, - whileBlockStart, this)); + // save off the current stream while we gen code for the condition + stitcher.push_back(new WhileCodeState(whileConditionTop, + whileBlockStart, this)); - iCode = new InstructionStream(); - } + iCode = new InstructionStream(); + } - void ICodeGenerator::endWhileExpression(Register condition) - { - WhileCodeState *ics = static_cast(stitcher.back()); - ASSERT(ics->stateKind == While_state); + void ICodeGenerator::endWhileExpression(Register condition) + { + WhileCodeState *ics = static_cast(stitcher.back()); + ASSERT(ics->stateKind == While_state); - branchConditional(ics->whileBody, condition); - resetTopRegister(); - // stash away the condition expression and switch - // back to the main stream - iCode = ics->swapStream(iCode); - // mark the start of the while block - setLabel(ics->whileBody); - } + branchConditional(ics->whileBody, condition); + resetTopRegister(); + // stash away the condition expression and switch + // back to the main stream + iCode = ics->swapStream(iCode); + // mark the start of the while block + setLabel(ics->whileBody); + } - void ICodeGenerator::endWhileStatement() - { - // recover the while stream - WhileCodeState *ics = static_cast(stitcher.back()); - ASSERT(ics->stateKind == While_state); - stitcher.pop_back(); + void ICodeGenerator::endWhileStatement() + { + // recover the while stream + WhileCodeState *ics = static_cast(stitcher.back()); + ASSERT(ics->stateKind == While_state); + stitcher.pop_back(); // mark the start of the condition code // which is where continues will target - setLabel(ics->whileCondition); + setLabel(ics->whileCondition); - // and re-attach it to the main stream - mergeStream(ics->whileExpressionStream); + // and re-attach it to the main stream + mergeStream(ics->whileExpressionStream); - if (ics->breakLabel != NULL) - setLabel(ics->breakLabel); + if (ics->breakLabel != NULL) + setLabel(ics->breakLabel); - delete ics; + delete ics; - resetTopRegister(); - } + resetTopRegister(); + } - /********************************************************************/ + /********************************************************************/ - void ICodeGenerator::beginForStatement(uint32) - { - Label *forCondition = getLabel(); + void ICodeGenerator::beginForStatement(uint32) + { + Label *forCondition = getLabel(); - ForCodeState *ics = new ForCodeState(forCondition, getLabel(), this); + ForCodeState *ics = new ForCodeState(forCondition, getLabel(), this); - branch(forCondition); + branch(forCondition); - stitcher.push_back(ics); + stitcher.push_back(ics); - // begin the stream for collecting the condition expression - iCode = new InstructionStream(); - setLabel(forCondition); + // begin the stream for collecting the condition expression + iCode = new InstructionStream(); + setLabel(forCondition); - resetTopRegister(); - } + resetTopRegister(); + } - void ICodeGenerator::forCondition(Register condition) - { - ForCodeState *ics = static_cast(stitcher.back()); - ASSERT(ics->stateKind == For_state); + void ICodeGenerator::forCondition(Register condition) + { + ForCodeState *ics = static_cast(stitcher.back()); + ASSERT(ics->stateKind == For_state); - // finsh off the test expression by adding the branch to the body - branchConditional(ics->forBody, condition); + // finsh off the test expression by adding the branch to the body + branchConditional(ics->forBody, condition); - // switch back to main stream - iCode = ics->swapStream(iCode); - // begin the stream for collecting the increment expression - iCode = new InstructionStream(); + // switch back to main stream + iCode = ics->swapStream(iCode); + // begin the stream for collecting the increment expression + iCode = new InstructionStream(); - ics->continueLabel = getLabel(); - // can't lazily insert this since we haven't seen the body yet - // ??? could just remember the offset - setLabel(ics->continueLabel); + ics->continueLabel = getLabel(); + // can't lazily insert this since we haven't seen the body yet + // ??? could just remember the offset + setLabel(ics->continueLabel); - resetTopRegister(); - } + resetTopRegister(); + } - void ICodeGenerator::forIncrement() - { - ForCodeState *ics = static_cast(stitcher.back()); - ASSERT(ics->stateKind == For_state); + void ICodeGenerator::forIncrement() + { + ForCodeState *ics = static_cast(stitcher.back()); + ASSERT(ics->stateKind == For_state); - // now switch back to the main stream - iCode = ics->swapStream2(iCode); - setLabel(ics->forBody); + // now switch back to the main stream + iCode = ics->swapStream2(iCode); + setLabel(ics->forBody); - resetTopRegister(); - } + resetTopRegister(); + } - void ICodeGenerator::endForStatement() - { - ForCodeState *ics = static_cast(stitcher.back()); - ASSERT(ics->stateKind == For_state); - stitcher.pop_back(); + void ICodeGenerator::endForStatement() + { + ForCodeState *ics = static_cast(stitcher.back()); + ASSERT(ics->stateKind == For_state); + stitcher.pop_back(); - mergeStream(ics->forIncrementStream); - mergeStream(ics->forConditionStream); + mergeStream(ics->forIncrementStream); + mergeStream(ics->forConditionStream); - if (ics->breakLabel != NULL) - setLabel(ics->breakLabel); + if (ics->breakLabel != NULL) + setLabel(ics->breakLabel); - delete ics; - } + delete ics; + } - /********************************************************************/ + /********************************************************************/ - void ICodeGenerator::beginDoStatement(uint32) - { - resetTopRegister(); + void ICodeGenerator::beginDoStatement(uint32) + { + resetTopRegister(); - // mark the top of the loop body - // and reserve a label for the condition - Label *doBlock = getLabel(); - Label *doCondition = getLabel(); - setLabel(doBlock); + // mark the top of the loop body + // and reserve a label for the condition + Label *doBlock = getLabel(); + Label *doCondition = getLabel(); + setLabel(doBlock); - stitcher.push_back(new DoCodeState(doBlock, doCondition, this)); + stitcher.push_back(new DoCodeState(doBlock, doCondition, this)); - iCode = new InstructionStream(); - } + iCode = new InstructionStream(); + } - void ICodeGenerator::endDoStatement() - { - DoCodeState *ics = static_cast(stitcher.back()); - ASSERT(ics->stateKind == Do_state); + void ICodeGenerator::endDoStatement() + { + DoCodeState *ics = static_cast(stitcher.back()); + ASSERT(ics->stateKind == Do_state); - // mark the start of the do conditional - setLabel(ics->doCondition); - if (ics->continueLabel != NULL) - setLabel(ics->continueLabel); + // mark the start of the do conditional + setLabel(ics->doCondition); + if (ics->continueLabel != NULL) + setLabel(ics->continueLabel); - resetTopRegister(); - } + resetTopRegister(); + } - void ICodeGenerator::endDoExpression(Register condition) - { - DoCodeState *ics = static_cast(stitcher.back()); - ASSERT(ics->stateKind == Do_state); - stitcher.pop_back(); + void ICodeGenerator::endDoExpression(Register condition) + { + DoCodeState *ics = static_cast(stitcher.back()); + ASSERT(ics->stateKind == Do_state); + stitcher.pop_back(); - // add branch to top of do block - branchConditional(ics->doBody, condition); - if (ics->breakLabel != NULL) - setLabel(ics->breakLabel); + // add branch to top of do block + branchConditional(ics->doBody, condition); + if (ics->breakLabel != NULL) + setLabel(ics->breakLabel); - delete ics; + delete ics; - resetTopRegister(); + resetTopRegister(); + } + + /********************************************************************/ + + void ICodeGenerator::beginSwitchStatement(uint32, Register expression) + { + // stash the control expression value + resetTopRegister(); + Register control = op(MOVE, expression); + // build an instruction stream for the case statements, the case + // expressions are generated into the main stream directly, the + // case statements are then added back in afterwards. + InstructionStream *x = new InstructionStream(); + SwitchCodeState *ics = new SwitchCodeState(control, this); + ics->swapStream(x); + stitcher.push_back(ics); + } + + void ICodeGenerator::endCaseCondition(Register expression) + { + SwitchCodeState *ics = + static_cast(stitcher.back()); + ASSERT(ics->stateKind == Switch_state); + + Label *caseLabel = getLabel(); + Register r = op(COMPARE_EQ, expression, ics->controlExpression); + branchConditional(caseLabel, r); + + // mark the case in the Case Statement stream + setLabel(ics->caseStatementsStream, caseLabel); + resetTopRegister(); + } + + void ICodeGenerator::beginCaseStatement() + { + SwitchCodeState *ics = + static_cast(stitcher.back()); + ASSERT(ics->stateKind == Switch_state); + // switch to Case Statement stream + iCode = ics->swapStream(iCode); + } + + void ICodeGenerator::endCaseStatement() + { + SwitchCodeState *ics = + static_cast(stitcher.back()); + // do more to guarantee correct blocking? + ASSERT(ics->stateKind == Switch_state); + // switch back to Case Conditional stream + iCode = ics->swapStream(iCode); + resetTopRegister(); + } + + void ICodeGenerator::beginDefaultStatement() + { + SwitchCodeState *ics = + static_cast(stitcher.back()); + ASSERT(ics->stateKind == Switch_state); + ASSERT(ics->defaultLabel == NULL); + ics->defaultLabel = getLabel(); + setLabel(ics->caseStatementsStream, ics->defaultLabel); + // switch to Case Statement stream + iCode = ics->swapStream(iCode); + } + + void ICodeGenerator::endDefaultStatement() + { + SwitchCodeState *ics = + static_cast(stitcher.back()); + ASSERT(ics->stateKind == Switch_state); + // do more to guarantee correct blocking? + ASSERT(ics->defaultLabel != NULL); + // switch to Case Statement stream + iCode = ics->swapStream(iCode); + resetTopRegister(); + } + + void ICodeGenerator::endSwitchStatement() + { + SwitchCodeState *ics = + static_cast(stitcher.back()); + ASSERT(ics->stateKind == Switch_state); + stitcher.pop_back(); + + // ground out the case chain at the default block or fall thru + // to the break label + if (ics->defaultLabel != NULL) + branch(ics->defaultLabel); + else { + if (ics->breakLabel == NULL) + ics->breakLabel = getLabel(); + branch(ics->breakLabel); } - - /********************************************************************/ - - void ICodeGenerator::beginSwitchStatement(uint32, Register expression) - { - // stash the control expression value - resetTopRegister(); - Register control = op(MOVE, expression); - // build an instruction stream for the case statements, the case - // expressions are generated into the main stream directly, the - // case statements are then added back in afterwards. - InstructionStream *x = new InstructionStream(); - SwitchCodeState *ics = new SwitchCodeState(control, this); - ics->swapStream(x); - stitcher.push_back(ics); - } - - void ICodeGenerator::endCaseCondition(Register expression) - { - SwitchCodeState *ics = - static_cast(stitcher.back()); - ASSERT(ics->stateKind == Switch_state); - - Label *caseLabel = getLabel(); - Register r = op(COMPARE_EQ, expression, ics->controlExpression); - branchConditional(caseLabel, r); - - // mark the case in the Case Statement stream - setLabel(ics->caseStatementsStream, caseLabel); - resetTopRegister(); - } - - void ICodeGenerator::beginCaseStatement() - { - SwitchCodeState *ics = - static_cast(stitcher.back()); - ASSERT(ics->stateKind == Switch_state); - // switch to Case Statement stream - iCode = ics->swapStream(iCode); - } - - void ICodeGenerator::endCaseStatement() - { - SwitchCodeState *ics = - static_cast(stitcher.back()); - // do more to guarantee correct blocking? - ASSERT(ics->stateKind == Switch_state); - // switch back to Case Conditional stream - iCode = ics->swapStream(iCode); - resetTopRegister(); - } - - void ICodeGenerator::beginDefaultStatement() - { - SwitchCodeState *ics = - static_cast(stitcher.back()); - ASSERT(ics->stateKind == Switch_state); - ASSERT(ics->defaultLabel == NULL); - ics->defaultLabel = getLabel(); - setLabel(ics->caseStatementsStream, ics->defaultLabel); - // switch to Case Statement stream - iCode = ics->swapStream(iCode); - } - - void ICodeGenerator::endDefaultStatement() - { - SwitchCodeState *ics = - static_cast(stitcher.back()); - ASSERT(ics->stateKind == Switch_state); - // do more to guarantee correct blocking? - ASSERT(ics->defaultLabel != NULL); - // switch to Case Statement stream - iCode = ics->swapStream(iCode); - resetTopRegister(); - } - - void ICodeGenerator::endSwitchStatement() - { - SwitchCodeState *ics = - static_cast(stitcher.back()); - ASSERT(ics->stateKind == Switch_state); - stitcher.pop_back(); - - // ground out the case chain at the default block or fall thru - // to the break label - if (ics->defaultLabel != NULL) - branch(ics->defaultLabel); - else { - if (ics->breakLabel == NULL) - ics->breakLabel = getLabel(); - branch(ics->breakLabel); - } - // dump all the case statements into the main stream - mergeStream(ics->caseStatementsStream); + // dump all the case statements into the main stream + mergeStream(ics->caseStatementsStream); - if (ics->breakLabel != NULL) - setLabel(ics->breakLabel); + if (ics->breakLabel != NULL) + setLabel(ics->breakLabel); - delete ics; - } + delete ics; + } - /********************************************************************/ + /********************************************************************/ - void ICodeGenerator::beginIfStatement(uint32, Register condition) - { - Label *elseLabel = getLabel(); + void ICodeGenerator::beginIfStatement(uint32, Register condition) + { + Label *elseLabel = getLabel(); - stitcher.push_back(new IfCodeState(elseLabel, NULL, this)); + stitcher.push_back(new IfCodeState(elseLabel, NULL, this)); - Register notCond = op(NOT, condition); - branchConditional(elseLabel, notCond); + Register notCond = op(NOT, condition); + branchConditional(elseLabel, notCond); - resetTopRegister(); + resetTopRegister(); + } + + void ICodeGenerator::beginElseStatement(bool hasElse) + { + IfCodeState *ics = static_cast(stitcher.back()); + ASSERT(ics->stateKind == If_state); + + if (hasElse) { + Label *beyondElse = getLabel(); + ics->beyondElse = beyondElse; + branch(beyondElse); } + setLabel(ics->elseLabel); + resetTopRegister(); + } - void ICodeGenerator::beginElseStatement(bool hasElse) - { - IfCodeState *ics = static_cast(stitcher.back()); - ASSERT(ics->stateKind == If_state); + void ICodeGenerator::endIfStatement() + { + IfCodeState *ics = static_cast(stitcher.back()); + ASSERT(ics->stateKind == If_state); + stitcher.pop_back(); - if (hasElse) { - Label *beyondElse = getLabel(); - ics->beyondElse = beyondElse; - branch(beyondElse); - } - setLabel(ics->elseLabel); - resetTopRegister(); + if (ics->beyondElse != NULL) { // had an else + setLabel(ics->beyondElse); // the beyond else label } - - void ICodeGenerator::endIfStatement() - { - IfCodeState *ics = static_cast(stitcher.back()); - ASSERT(ics->stateKind == If_state); - stitcher.pop_back(); - - if (ics->beyondElse != NULL) { // had an else - setLabel(ics->beyondElse); // the beyond else label - } - delete ics; - resetTopRegister(); - } + delete ics; + resetTopRegister(); + } - /************************************************************************/ + /************************************************************************/ - void ICodeGenerator::breakStatement() - { - for (std::vector::reverse_iterator p = - stitcher.rbegin(); p != stitcher.rend(); p++) { - if ((*p)->breakLabel != NULL) { - branch((*p)->breakLabel); - return; - } - if (((*p)->stateKind == While_state) - || ((*p)->stateKind == Do_state) - || ((*p)->stateKind == For_state) - || ((*p)->stateKind == Switch_state)) { - (*p)->breakLabel = getLabel(); - branch((*p)->breakLabel); - return; - } + void ICodeGenerator::breakStatement() + { + for (std::vector::reverse_iterator p = + stitcher.rbegin(); p != stitcher.rend(); p++) { + if ((*p)->breakLabel != NULL) { + branch((*p)->breakLabel); + return; } - NOT_REACHED("no break target available"); - } - - void ICodeGenerator::continueStatement() - { - for (std::vector::reverse_iterator p = - stitcher.rbegin(); p != stitcher.rend(); p++) { - if ((*p)->continueLabel != NULL) { - branch((*p)->continueLabel); - return; - } - if (((*p)->stateKind == While_state) - || ((*p)->stateKind == Do_state) - || ((*p)->stateKind == For_state)) { - (*p)->continueLabel = getLabel(); - branch((*p)->continueLabel); - return; - } + if (((*p)->stateKind == While_state) + || ((*p)->stateKind == Do_state) + || ((*p)->stateKind == For_state) + || ((*p)->stateKind == Switch_state)) { + (*p)->breakLabel = getLabel(); + branch((*p)->breakLabel); + return; } - NOT_REACHED("no continue target available"); - } + } + NOT_REACHED("no break target available"); + } - Formatter& ICodeGenerator::print(Formatter& f) - { - f << "ICG! " << (uint32)iCode->size() << "\n"; - for (InstructionIterator i = iCode->begin(); - i != iCode->end(); i++) { - bool isLabel = false; + void ICodeGenerator::continueStatement() + { + for (std::vector::reverse_iterator p = + stitcher.rbegin(); p != stitcher.rend(); p++) { + if ((*p)->continueLabel != NULL) { + branch((*p)->continueLabel); + return; + } + if (((*p)->stateKind == While_state) + || ((*p)->stateKind == Do_state) + || ((*p)->stateKind == For_state)) { + (*p)->continueLabel = getLabel(); + branch((*p)->continueLabel); + return; + } + } + NOT_REACHED("no continue target available"); + } - for (LabelList::iterator k = labels.begin(); - k != labels.end(); k++) - if ((ptrdiff_t)(*k)->offset == (i - iCode->begin())) { - f << "#" << (uint32)(i - iCode->begin()) << "\t"; - isLabel = true; - break; - } + Formatter& ICodeGenerator::print(Formatter& f) + { + f << "ICG! " << (uint32)iCode->size() << "\n"; + for (InstructionIterator i = iCode->begin(); + i != iCode->end(); i++) { + bool isLabel = false; - if (!isLabel) - f << "\t"; + for (LabelList::iterator k = labels.begin(); + k != labels.end(); k++) + if ((ptrdiff_t)(*k)->offset == (i - iCode->begin())) { + f << "#" << (uint32)(i - iCode->begin()) << "\t"; + isLabel = true; + break; + } + + if (!isLabel) + f << "\t"; - f << **i << "\n"; - } - - return f; + f << **i << "\n"; } + + return f; + } - } // namespace ICG +} // namespace ICG } // namespace JavaScript diff --git a/js/js2/icodegenerator.h b/js/js2/icodegenerator.h index 21b7f9d8e76..521c1e5c950 100644 --- a/js/js2/icodegenerator.h +++ b/js/js2/icodegenerator.h @@ -42,304 +42,306 @@ #include "parser.h" #include "vmtypes.h" + +#define NS_JSICG JavaScript::IGC + namespace JavaScript { - namespace ICG { - - using namespace VM; - - class ICodeGenerator; // forward declaration +namespace ICG { - enum StateKind { - While_state, - If_state, - Do_state, - Switch_state, - For_state - }; - - class ICodeState { - public : - ICodeState(StateKind kind, ICodeGenerator *icg); // inline below - virtual ~ICodeState() { } - - virtual Label *getBreakLabel(ICodeGenerator *) \ - { ASSERT(false); return NULL; } - virtual Label *getContinueLabel(ICodeGenerator *) \ - { ASSERT(false); return NULL;} - - StateKind stateKind; - Register registerBase; - Label *breakLabel; - Label *continueLabel; - }; - - class ICodeModule { - public: - ICodeModule(InstructionStream *iCode, uint32 maxRegister, - uint32 maxVariable) : - its_iCode(iCode), itsMaxRegister(maxRegister), - itsMaxVariable(maxVariable) { } - - InstructionStream *its_iCode; - uint32 itsMaxRegister; - uint32 itsMaxVariable; - }; - - /****************************************************************/ - - // An ICodeGenerator provides the interface between the parser and the - // interpreter. The parser constructs one of these for each - // function/script, adds statements and expressions to it and then - // converts it into an ICodeModule, ready for execution. - - class ICodeGenerator { - private: - InstructionStream *iCode; - LabelList labels; - std::vector stitcher; - - void markMaxRegister() \ - { if (topRegister > maxRegister) maxRegister = topRegister; } - void markMaxVariable(uint32 variableIndex) \ - { if (variableIndex > maxVariable) maxVariable = variableIndex; } - - Register topRegister; - Register getRegister() \ - { return topRegister++; } - void resetTopRegister() \ - { markMaxRegister(); topRegister = stitcher.empty() ? 0 : \ - stitcher.back()->registerBase; } - - ICodeOp getBranchOp() \ - { ASSERT(!iCode->empty()); return iCode->back()->getBranchOp(); } - - uint32 maxRegister; - uint32 maxVariable; - - void setLabel(Label *label); - void setLabel(InstructionStream *stream, Label *label); - - void branch(Label *label); - void branchConditional(Label *label, Register condition); + using namespace VM; - public: - ICodeGenerator() : topRegister(0), maxRegister(0), - maxVariable(0) \ - { iCode = new InstructionStream(); } - - virtual ~ICodeGenerator() { if (iCode) delete iCode; } - - void mergeStream(InstructionStream *sideStream); - - ICodeModule *complete(); - - Formatter& print(Formatter& f); - - Register op(ICodeOp op, Register source); - Register op(ICodeOp op, Register source1, Register source2); - Register call(Register target, RegisterList args); - - Register compare(ICodeOp op, Register source1, Register source2); - - Register loadVariable(uint32 frameIndex); - Register loadImmediate(double value); - - void saveVariable(uint32 frameIndex, Register value); - - Register newObject(); - Register newArray(); - - Register loadName(StringAtom &name); - void saveName(StringAtom &name, Register value); - - Register getProperty(Register base, StringAtom &name); - void setProperty(Register base, StringAtom &name, Register value); - - Register getElement(Register base, Register index); - void setElement(Register base, Register index, Register value); - - Register getRegisterBase() { return topRegister; } - InstructionStream *get_iCode() { return iCode; } - - Label *getLabel(); - - - // Rather than have the ICG client maniplate labels and branches, it - // uses the following calls to describe the high level looping - // constructs being generated. The functions listed below are - // expected to be called in the order listed for each construct, - // (internal error otherwise). - // The ICG will enforce correct nesting and closing. - - // expression statements - void beginStatement(uint32 /*pos*/) { resetTopRegister(); } + class ICodeGenerator; // forward declaration - void returnStatement() { iCode->push_back(new Return()); } - void returnStatement(Register result) \ - { iCode->push_back(new Return(result)); } - - void beginWhileStatement(uint32 pos); - void endWhileExpression(Register condition); - void endWhileStatement(); - - void beginDoStatement(uint32 pos); - void endDoStatement(); - void endDoExpression(Register condition); - - void beginIfStatement(uint32 pos, Register condition); - void beginElseStatement(bool hasElse); // required, regardless of - // existence of else clause - void endIfStatement(); - - // for ( ... in ...) statements get turned into generic for - // statements by the parser (ok?) - void beginForStatement(uint32 pos); // for initialization is - // emitted prior to this call - void forCondition(Register condition); // required - void forIncrement(); // required - void endForStatement(); - - void beginSwitchStatement(uint32 pos, Register expression); - - void endCaseCondition(Register expression); + enum StateKind { + While_state, + If_state, + Do_state, + Switch_state, + For_state + }; - void beginCaseStatement(); - void endCaseStatement(); + class ICodeState { + public : + ICodeState(StateKind kind, ICodeGenerator *icg); // inline below + virtual ~ICodeState() { } - // optionally - void beginDefaultStatement(); - void endDefaultStatement(); - - void endSwitchStatement(); - - void labelStatement(const StringAtom &label); // adds to label set - // for next statement, removed when that statement is finished - void continueStatement(); - void breakStatement(); - - void continueStatement(const StringAtom &label); - void breakStatement(const StringAtom &label); - - void throwStatement(Register expression); - - void beginCatchStatement(); - void endCatchExpression(Register expression); - void endCatchStatement(); - - }; - - Formatter& operator<<(Formatter &f, ICodeGenerator &i); - /* - std::ostream &operator<<(std::ostream &s, ICodeGenerator &i); - std::ostream &operator<<(std::ostream &s, StringAtom &str); - */ - - class WhileCodeState : public ICodeState { - public: - WhileCodeState(Label *conditionLabel, Label *bodyLabel, - ICodeGenerator *icg); // inline below - InstructionStream *swapStream(InstructionStream *iCode) \ - { InstructionStream *t = whileExpressionStream; \ - whileExpressionStream = iCode; return t; } - - virtual Label *getBreakLabel(ICodeGenerator *icg) \ - { if (breakLabel == NULL) breakLabel = icg->getLabel(); \ - return breakLabel; } - virtual Label *getContinueLabel(ICodeGenerator *) \ - { return whileCondition; } - - Label *whileCondition; - Label *whileBody; - InstructionStream *whileExpressionStream; - }; - - class ForCodeState : public ICodeState { - public: - ForCodeState(Label *conditionLabel, Label *bodyLabel, - ICodeGenerator *icg); // inline below - InstructionStream *swapStream(InstructionStream *iCode) \ - { InstructionStream *t = forConditionStream; \ - forConditionStream = iCode; return t; } - InstructionStream *swapStream2(InstructionStream *iCode) \ - { InstructionStream *t = forIncrementStream; \ - forIncrementStream = iCode; return t; } + virtual Label *getBreakLabel(ICodeGenerator *) \ + { ASSERT(false); return NULL; } + virtual Label *getContinueLabel(ICodeGenerator *) \ + { ASSERT(false); return NULL;} - virtual Label *getBreakLabel(ICodeGenerator *icg) \ - { if (breakLabel == NULL) breakLabel = icg->getLabel(); \ - return breakLabel; } - virtual Label *getContinueLabel(ICodeGenerator *) \ - { ASSERT(continueLabel); return continueLabel; } - - Label *forCondition; - Label *forBody; - InstructionStream *forConditionStream; - InstructionStream *forIncrementStream; - }; - - class IfCodeState : public ICodeState { - public: - IfCodeState(Label *a, Label *b, ICodeGenerator *icg) - : ICodeState(If_state, icg), elseLabel(a), beyondElse(b) { } - Label *elseLabel; - Label *beyondElse; - }; - - class DoCodeState : public ICodeState { - public: - DoCodeState(Label *bodyLabel, Label *conditionLabel, - ICodeGenerator *icg) - : ICodeState(Do_state, icg), doBody(bodyLabel), - doCondition(conditionLabel) { } - - virtual Label *getBreakLabel(ICodeGenerator *icg) \ - { if (breakLabel == NULL) breakLabel = icg->getLabel(); - return breakLabel; } - virtual Label *getContinueLabel(ICodeGenerator *) \ - { return doCondition; } - - Label *doBody; - Label *doCondition; - }; - - class SwitchCodeState : public ICodeState { - public: - SwitchCodeState(Register control, ICodeGenerator *icg); // inline below - InstructionStream *swapStream(InstructionStream *iCode) \ - { InstructionStream *t = caseStatementsStream; \ - caseStatementsStream = iCode; return t; } - - virtual Label *getBreakLabel(ICodeGenerator *icg) \ - { if (breakLabel == NULL) breakLabel = icg->getLabel(); - return breakLabel; } - - Register controlExpression; - Label *defaultLabel; - InstructionStream *caseStatementsStream; - }; - - inline ICodeState::ICodeState(StateKind kind, ICodeGenerator *icg) - : stateKind(kind), registerBase(icg->getRegisterBase()), - breakLabel(NULL), continueLabel(NULL) { } - - inline SwitchCodeState::SwitchCodeState(Register control, - ICodeGenerator *icg) - : ICodeState(Switch_state, icg), controlExpression(control), - defaultLabel(NULL), caseStatementsStream(icg->get_iCode()) {} - - inline WhileCodeState::WhileCodeState(Label *conditionLabel, - Label *bodyLabel, - ICodeGenerator *icg) - : ICodeState(While_state, icg), whileCondition(conditionLabel), - whileBody(bodyLabel), whileExpressionStream(icg->get_iCode()) {} - - inline ForCodeState::ForCodeState(Label *conditionLabel, - Label *bodyLabel, ICodeGenerator *icg) - : ICodeState(For_state, icg), forCondition(conditionLabel), - forBody(bodyLabel), forConditionStream(icg->get_iCode()), - forIncrementStream(icg->get_iCode()) {} - - } /* namespace IGC */ + StateKind stateKind; + Register registerBase; + Label *breakLabel; + Label *continueLabel; + }; + class ICodeModule { + public: + ICodeModule(InstructionStream *iCode, uint32 maxRegister, + uint32 maxVariable) : + its_iCode(iCode), itsMaxRegister(maxRegister), + itsMaxVariable(maxVariable) { } + + InstructionStream *its_iCode; + uint32 itsMaxRegister; + uint32 itsMaxVariable; + }; + + /****************************************************************/ + + // An ICodeGenerator provides the interface between the parser and the + // interpreter. The parser constructs one of these for each + // function/script, adds statements and expressions to it and then + // converts it into an ICodeModule, ready for execution. + + class ICodeGenerator { + private: + InstructionStream *iCode; + LabelList labels; + std::vector stitcher; + + void markMaxRegister() \ + { if (topRegister > maxRegister) maxRegister = topRegister; } + void markMaxVariable(uint32 variableIndex) \ + { if (variableIndex > maxVariable) maxVariable = variableIndex; } + + Register topRegister; + Register getRegister() \ + { return topRegister++; } + void resetTopRegister() \ + { markMaxRegister(); topRegister = stitcher.empty() ? 0 : \ + stitcher.back()->registerBase; } + + ICodeOp getBranchOp() \ + { ASSERT(!iCode->empty()); return iCode->back()->getBranchOp(); } + + uint32 maxRegister; + uint32 maxVariable; + + void setLabel(Label *label); + void setLabel(InstructionStream *stream, Label *label); + + void branch(Label *label); + void branchConditional(Label *label, Register condition); + + public: + ICodeGenerator() : topRegister(0), maxRegister(0), + maxVariable(0) \ + { iCode = new InstructionStream(); } + + virtual ~ICodeGenerator() { if (iCode) delete iCode; } + + void mergeStream(InstructionStream *sideStream); + + ICodeModule *complete(); + + Formatter& print(Formatter& f); + + Register op(ICodeOp op, Register source); + Register op(ICodeOp op, Register source1, Register source2); + Register call(Register target, RegisterList args); + + Register compare(ICodeOp op, Register source1, Register source2); + + Register loadVariable(uint32 frameIndex); + Register loadImmediate(double value); + + void saveVariable(uint32 frameIndex, Register value); + + Register newObject(); + Register newArray(); + + Register loadName(StringAtom &name); + void saveName(StringAtom &name, Register value); + + Register getProperty(Register base, StringAtom &name); + void setProperty(Register base, StringAtom &name, Register value); + + Register getElement(Register base, Register index); + void setElement(Register base, Register index, Register value); + + Register getRegisterBase() { return topRegister; } + InstructionStream *get_iCode() { return iCode; } + + Label *getLabel(); + + + // Rather than have the ICG client maniplate labels and branches, it + // uses the following calls to describe the high level looping + // constructs being generated. The functions listed below are + // expected to be called in the order listed for each construct, + // (internal error otherwise). + // The ICG will enforce correct nesting and closing. + + // expression statements + void beginStatement(uint32 /*pos*/) { resetTopRegister(); } + + void returnStatement() { iCode->push_back(new Return()); } + void returnStatement(Register result) \ + { iCode->push_back(new Return(result)); } + + void beginWhileStatement(uint32 pos); + void endWhileExpression(Register condition); + void endWhileStatement(); + + void beginDoStatement(uint32 pos); + void endDoStatement(); + void endDoExpression(Register condition); + + void beginIfStatement(uint32 pos, Register condition); + void beginElseStatement(bool hasElse); // required, regardless of + // existence of else clause + void endIfStatement(); + + // for ( ... in ...) statements get turned into generic for + // statements by the parser (ok?) + void beginForStatement(uint32 pos); // for initialization is + // emitted prior to this call + void forCondition(Register condition); // required + void forIncrement(); // required + void endForStatement(); + + void beginSwitchStatement(uint32 pos, Register expression); + + void endCaseCondition(Register expression); + + void beginCaseStatement(); + void endCaseStatement(); + + // optionally + void beginDefaultStatement(); + void endDefaultStatement(); + + void endSwitchStatement(); + + void labelStatement(const StringAtom &label); // adds to label set + // for next statement, removed when that statement is finished + void continueStatement(); + void breakStatement(); + + void continueStatement(const StringAtom &label); + void breakStatement(const StringAtom &label); + + void throwStatement(Register expression); + + void beginCatchStatement(); + void endCatchExpression(Register expression); + void endCatchStatement(); + + }; + + Formatter& operator<<(Formatter &f, ICodeGenerator &i); + /* + std::ostream &operator<<(std::ostream &s, ICodeGenerator &i); + std::ostream &operator<<(std::ostream &s, StringAtom &str); + */ + + class WhileCodeState : public ICodeState { + public: + WhileCodeState(Label *conditionLabel, Label *bodyLabel, + ICodeGenerator *icg); // inline below + InstructionStream *swapStream(InstructionStream *iCode) \ + { InstructionStream *t = whileExpressionStream; \ + whileExpressionStream = iCode; return t; } + + virtual Label *getBreakLabel(ICodeGenerator *icg) \ + { if (breakLabel == NULL) breakLabel = icg->getLabel(); \ + return breakLabel; } + virtual Label *getContinueLabel(ICodeGenerator *) \ + { return whileCondition; } + + Label *whileCondition; + Label *whileBody; + InstructionStream *whileExpressionStream; + }; + + class ForCodeState : public ICodeState { + public: + ForCodeState(Label *conditionLabel, Label *bodyLabel, + ICodeGenerator *icg); // inline below + InstructionStream *swapStream(InstructionStream *iCode) \ + { InstructionStream *t = forConditionStream; \ + forConditionStream = iCode; return t; } + InstructionStream *swapStream2(InstructionStream *iCode) \ + { InstructionStream *t = forIncrementStream; \ + forIncrementStream = iCode; return t; } + + virtual Label *getBreakLabel(ICodeGenerator *icg) \ + { if (breakLabel == NULL) breakLabel = icg->getLabel(); \ + return breakLabel; } + virtual Label *getContinueLabel(ICodeGenerator *) \ + { ASSERT(continueLabel); return continueLabel; } + + Label *forCondition; + Label *forBody; + InstructionStream *forConditionStream; + InstructionStream *forIncrementStream; + }; + + class IfCodeState : public ICodeState { + public: + IfCodeState(Label *a, Label *b, ICodeGenerator *icg) + : ICodeState(If_state, icg), elseLabel(a), beyondElse(b) { } + Label *elseLabel; + Label *beyondElse; + }; + + class DoCodeState : public ICodeState { + public: + DoCodeState(Label *bodyLabel, Label *conditionLabel, + ICodeGenerator *icg) + : ICodeState(Do_state, icg), doBody(bodyLabel), + doCondition(conditionLabel) { } + + virtual Label *getBreakLabel(ICodeGenerator *icg) \ + { if (breakLabel == NULL) breakLabel = icg->getLabel(); + return breakLabel; } + virtual Label *getContinueLabel(ICodeGenerator *) \ + { return doCondition; } + + Label *doBody; + Label *doCondition; + }; + + class SwitchCodeState : public ICodeState { + public: + SwitchCodeState(Register control, ICodeGenerator *icg); // inline below + InstructionStream *swapStream(InstructionStream *iCode) \ + { InstructionStream *t = caseStatementsStream; \ + caseStatementsStream = iCode; return t; } + + virtual Label *getBreakLabel(ICodeGenerator *icg) \ + { if (breakLabel == NULL) breakLabel = icg->getLabel(); + return breakLabel; } + + Register controlExpression; + Label *defaultLabel; + InstructionStream *caseStatementsStream; + }; + + inline ICodeState::ICodeState(StateKind kind, ICodeGenerator *icg) + : stateKind(kind), registerBase(icg->getRegisterBase()), + breakLabel(NULL), continueLabel(NULL) { } + + inline SwitchCodeState::SwitchCodeState(Register control, + ICodeGenerator *icg) + : ICodeState(Switch_state, icg), controlExpression(control), + defaultLabel(NULL), caseStatementsStream(icg->get_iCode()) {} + + inline WhileCodeState::WhileCodeState(Label *conditionLabel, + Label *bodyLabel, + ICodeGenerator *icg) + : ICodeState(While_state, icg), whileCondition(conditionLabel), + whileBody(bodyLabel), whileExpressionStream(icg->get_iCode()) {} + + inline ForCodeState::ForCodeState(Label *conditionLabel, + Label *bodyLabel, ICodeGenerator *icg) + : ICodeState(For_state, icg), forCondition(conditionLabel), + forBody(bodyLabel), forConditionStream(icg->get_iCode()), + forIncrementStream(icg->get_iCode()) {} + +} /* namespace IGC */ } /* namespace JavaScript */ #endif /* icodegenerator_h */ diff --git a/js/js2/interpreter.cpp b/js/js2/interpreter.cpp index 6ea4f40a761..c6685210ac4 100644 --- a/js/js2/interpreter.cpp +++ b/js/js2/interpreter.cpp @@ -22,280 +22,293 @@ #include "vmtypes.h" namespace JavaScript { - namespace Interpreter { +namespace Interpreter { - using namespace JSTypes; - // operand access macros. + using namespace JSTypes; + + // operand access macros. #define op1(i) (i->o1()) #define op2(i) (i->o2()) #define op3(i) (i->o3()) - // mnemonic names for operands. + // mnemonic names for operands. #define dst(i) op1(i) #define src1(i) op2(i) #define src2(i) op3(i) #define ofs(i) (i->getOffset()) - static JSObject globals; + static JSObject globals; - JSValue& defineGlobalProperty(const String& name, const JSValue& value) - { - return (globals[name] = value); - } + JSValue& defineGlobalProperty(const String& name, const JSValue& value) + { + return (globals[name] = value); + } - // FIXME: need to copy the ICodeModule's instruction stream. + // FIXME: need to copy the ICodeModule's instruction stream. + + JSValue& defineFunction(const String& name, ICodeModule* iCode) + { + JSValue value; + value.function = new JSFunction(iCode); + return defineGlobalProperty(name, value); + } - JSValue& defineFunction(const String& name, ICodeModule* iCode) - { - JSValue value; - value.function = new JSFunction(iCode); - return defineGlobalProperty(name, value); - } + JSValue interpret(ICodeModule* iCode, const JSValues& args) + { + // stack of JSFrames. + // XXX is a linked list of activation's sufficient? + JSFrameStack frames; - JSValue interpret(ICodeModule* iCode, const JSValues& args) - { - // stack of JSFrames. - // XXX is a linked list of activation's sufficient? - JSFrameStack frames; + // initial activation. + JSActivation* activation = new JSActivation(iCode, args); + JSValues* locals = &activation->mLocals; + JSValues* registers = &activation->mRegisters; - // initial activation. - JSActivation* activation = new JSActivation(iCode, args); - JSValues* locals = &activation->mLocals; - JSValues* registers = &activation->mRegisters; + InstructionIterator begin_pc = iCode->its_iCode->begin(); + InstructionIterator pc = begin_pc; - InstructionIterator begin_pc = iCode->its_iCode->begin(); - InstructionIterator pc = begin_pc; - - while (true) { - 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)); - locals = &activation->mLocals; - registers = &activation->mRegisters; - begin_pc = pc = target->its_iCode->begin(); - } + while (true) { + 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)); + locals = &activation->mLocals; + registers = &activation->mRegisters; + begin_pc = pc = target->its_iCode->begin(); + } + continue; + case RETURN: + { + Return* ret = static_cast(instruction); + JSValue result; + 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; + locals = &activation->mLocals; + (*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)] = globals[*src1(ln)]; + } + break; + case SAVE_NAME: + { + SaveName* sn = static_cast(instruction); + globals[*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 LOAD_VAR: + { + LoadVar* lv = static_cast(instruction); + (*registers)[dst(lv)] = (*locals)[src1(lv)]; + } + break; + case SAVE_VAR: + { + SaveVar* sv = static_cast(instruction); + (*locals)[dst(sv)] = (*registers)[src1(sv)]; + } + break; + case BRANCH: + { + GenericBranch* bra = + static_cast(instruction); + pc = begin_pc + ofs(bra); continue; - case RETURN: - { - Return* ret = static_cast(instruction); - JSValue result; - 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; - locals = &activation->mLocals; - (*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)] = globals[*src1(ln)]; - } - break; - case SAVE_NAME: - { - SaveName* sn = static_cast(instruction); - globals[*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 LOAD_VAR: - { - LoadVar* lv = static_cast(instruction); - (*registers)[dst(lv)] = (*locals)[src1(lv)]; - } - break; - case SAVE_VAR: - { - SaveVar* sv = static_cast(instruction); - (*locals)[dst(sv)] = (*registers)[src1(sv)]; - } - 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: - { - Move* nt = static_cast(instruction); - (*registers)[dst(nt)].i32 = !(*registers)[src1(nt)].i32; - } - break; - default: - NOT_REACHED("bad opcode"); - break; } - - // increment the program counter. - ++pc; + 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: + { + Move* nt = static_cast(instruction); + (*registers)[dst(nt)].i32 = !(*registers)[src1(nt)].i32; + } + break; + default: + NOT_REACHED("bad opcode"); + break; } + + // increment the program counter. + ++pc; + } - } /* interpret */ + } /* interpret */ - } /* namespace Interpreter */ - +} /* namespace Interpreter */ } /* namespace JavaScript */ diff --git a/js/js2/interpreter.h b/js/js2/interpreter.h index 27ecc802110..deb3c95e6e5 100644 --- a/js/js2/interpreter.h +++ b/js/js2/interpreter.h @@ -25,18 +25,18 @@ #include "icodegenerator.h" namespace JavaScript { - namespace Interpreter { - using namespace ICG; - using namespace JSTypes; - - JSValue interpret(ICodeModule* iCode, const JSValues& args); +namespace Interpreter { - JSValue& defineGlobalProperty(const String& name, - const JSValue& value); - JSValue& defineFunction(const String& name, ICodeModule* iCode); - }; + using namespace ICG; + using namespace JSTypes; -}; + JSValue interpret(ICodeModule* iCode, const JSValues& args); + + JSValue& defineGlobalProperty(const String& name, + const JSValue& value); + JSValue& defineFunction(const String& name, ICodeModule* iCode); +} /* namespace Interpreter */ +} /* namespace JavaScript */ #endif /* interpreter_h */ diff --git a/js/js2/jstypes.h b/js/js2/jstypes.h index db56972d7d3..c423d4984f7 100644 --- a/js/js2/jstypes.h +++ b/js/js2/jstypes.h @@ -44,183 +44,188 @@ #include "icodegenerator.h" namespace JavaScript { - namespace JSTypes { - using namespace VM; - using namespace ICG; +namespace JSTypes { + using namespace VM; + using namespace ICG; + + class JSObject; + class JSArray; + class JSFunction; + + /** + * All JavaScript data types. + */ + union JSValue { + int8 i8; + uint8 u8; + int16 i16; + uint16 u16; + int32 i32; + uint32 u32; + int64 i64; + uint64 u64; + float32 f32; + float64 f64; + JSObject* object; + JSArray* array; + JSFunction *function; - class JSObject; - class JSArray; - class JSFunction; - - /** - * All JavaScript data types. - */ - union JSValue { - int8 i8; - uint8 u8; - int16 i16; - uint16 u16; - int32 i32; - uint32 u32; - int64 i64; - uint64 u64; - float32 f32; - float64 f64; - JSObject* object; - JSArray* array; - JSFunction *function; + JSValue() : f64(0.0) {} - JSValue() : f64(0.0) {} - - explicit JSValue(float64 f64) : f64(f64) {} - }; + explicit JSValue(float64 f64) : f64(f64) {} + }; #if defined(XP_MAC) - // copied from default template parameters in map. - typedef gc_allocator > gc_map_allocator; + // copied from default template parameters in map. + typedef gc_allocator > gc_map_allocator; #elif defined(XP_UNIX) - // FIXME: in libg++, they assume the map's allocator is a byte allocator, - // which is wrapped in a simple_allocator. this is crap. - typedef char _Char[1]; - typedef gc_allocator<_Char> gc_map_allocator; + // FIXME: in libg++, they assume the map's allocator is a byte allocator, + // which is wrapped in a simple_allocator. this is crap. + typedef char _Char[1]; + typedef gc_allocator<_Char> gc_map_allocator; #elif defined(_WIN32) - // FIXME: MSVC++'s notion. this is why we had to add _Charalloc(). - typedef gc_allocator gc_map_allocator; + // FIXME: MSVC++'s notion. this is why we had to add _Charalloc(). + typedef gc_allocator gc_map_allocator; #endif - /** + /** * GC-scannable array of values. */ - typedef std::vector > JSValues; + typedef std::vector > JSValues; - /** + /** * Basic behavior of all JS objects, mapping a name to a value. * This is provided mainly to avoid having an awkward implementation * of JSObject & JSArray, which must each define its own * gc_allocator. This is all in flux. */ - class JSMap : public gc_base { - std::map, gc_map_allocator> properties; - public: - JSValue& operator[](const String& name) - { - return properties[name]; - } - }; + class JSMap : public gc_base { + std::map, + gc_map_allocator> properties; + public: + JSValue& operator[](const String& name) + { + return properties[name]; + } + }; - /** + /** * Private representation of a JavaScript object. * This will change over time, so it is treated as an opaque * type everywhere else but here. */ - class JSObject : public JSMap {}; + class JSObject : public JSMap {}; - /** + /** * Private representation of a JavaScript array. */ - class JSArray : public JSMap { - JSValues elements; - public: - JSArray() : elements(1) {} - JSArray(uint32 size) : elements(size) {} - JSArray(const JSValues &v) : elements(v) {} + class JSArray : public JSMap { + JSValues elements; + public: + JSArray() : elements(1) {} + JSArray(uint32 size) : elements(size) {} + JSArray(const JSValues &v) : elements(v) {} - uint32 length() - { - return elements.size(); - } + uint32 length() + { + return elements.size(); + } - JSValue& operator[](const JSValue& index) - { - // for now, we can only handle f64 index values. - uint32 n = (uint32)index.f64; - // obviously, a sparse representation might be better. - uint32 size = elements.size(); - if (n >= size) expand(n, size); - return elements[n]; - } + JSValue& operator[](const JSValue& index) + { + // for now, we can only handle f64 index values. + uint32 n = (uint32)index.f64; + // obviously, a sparse representation might be better. + uint32 size = elements.size(); + if (n >= size) expand(n, size); + return elements[n]; + } - JSValue& operator[](uint32 n) - { - // obviously, a sparse representation might be better. - uint32 size = elements.size(); - if (n >= size) expand(n, size); - return elements[n]; - } + JSValue& operator[](uint32 n) + { + // obviously, a sparse representation might be better. + uint32 size = elements.size(); + if (n >= size) expand(n, size); + return elements[n]; + } - void resize(uint32 size) - { - elements.resize(size); - } + void resize(uint32 size) + { + elements.resize(size); + } - private: - void expand(uint32 n, uint32 size) - { - do { - size *= 2; - } while (n >= size); - elements.resize(size); - } - }; + private: + void expand(uint32 n, uint32 size) + { + do { + size *= 2; + } while (n >= size); + elements.resize(size); + } + }; - class JSFunction : public JSMap { - ICodeModule* mICode; - public: - JSFunction(ICodeModule* iCode) : mICode(iCode) {} - ICodeModule* getICode() { return mICode; } - }; + class JSFunction : public JSMap { + ICodeModule* mICode; + public: + JSFunction(ICodeModule* iCode) : mICode(iCode) {} + ICodeModule* getICode() { return mICode; } + }; - /** + /** * Represents the current function's invocation state. */ - struct JSActivation : public gc_base { - JSValues mRegisters; - JSValues mLocals; + struct JSActivation : public gc_base { + JSValues mRegisters; + JSValues mLocals; - JSActivation(ICodeModule* iCode, const JSValues& args) - : mRegisters(iCode->itsMaxRegister + 1), mLocals(args) - { - // ensure that locals array is large enough. - uint32 localsSize = iCode->itsMaxVariable + 1; - if (localsSize > mLocals.size()) - mLocals.resize(localsSize); - } + JSActivation(ICodeModule* iCode, const JSValues& args) + : mRegisters(iCode->itsMaxRegister + 1), mLocals(args) + { + // ensure that locals array is large enough. + uint32 localsSize = iCode->itsMaxVariable + 1; + if (localsSize > mLocals.size()) + mLocals.resize(localsSize); + } - JSActivation(ICodeModule* iCode, JSActivation* caller, const RegisterList& list) - : mRegisters(iCode->itsMaxRegister + 1), mLocals(iCode->itsMaxVariable + 1) - { - // copy caller's parameter list in to locals. - JSValues::iterator dest = mLocals.begin(); - const JSValues& params = caller->mRegisters; - for (RegisterList::const_iterator src = list.begin(), end = list.end(); src != end; ++src, ++dest) { - *dest = params[*src]; - } + JSActivation(ICodeModule* iCode, JSActivation* caller, + const RegisterList& list) + : mRegisters(iCode->itsMaxRegister + 1), + mLocals(iCode->itsMaxVariable + 1) + { + // copy caller's parameter list in to locals. + JSValues::iterator dest = mLocals.begin(); + const JSValues& params = caller->mRegisters; + for (RegisterList::const_iterator src = list.begin(), + end = list.end(); src != end; ++src, ++dest) { + *dest = params[*src]; } - }; + } + }; - /** - * Stores saved state from the *previous* activation, the current activation is alive - * and well in locals of the interpreter loop. +/** + * Stores saved state from the *previous* activation, the current activation is + * alive and well in locals of the interpreter loop. */ - struct JSFrame : public gc_base { - JSFrame(InstructionIterator returnPC, InstructionIterator basePC, - JSActivation* activation, Register result) - : itsReturnPC(returnPC), itsBasePC(basePC), - itsActivation(activation), - itsResult(result) - { - } + struct JSFrame : public gc_base { + JSFrame(InstructionIterator returnPC, InstructionIterator basePC, + JSActivation* activation, Register result) + : itsReturnPC(returnPC), itsBasePC(basePC), + itsActivation(activation), + itsResult(result) + { + } - InstructionIterator itsReturnPC; - InstructionIterator itsBasePC; - JSActivation* itsActivation; // caller's activation. - Register itsResult; // the desired target register for the return value - }; + InstructionIterator itsReturnPC; + InstructionIterator itsBasePC; + JSActivation* itsActivation; // caller's activation. + // the desired target register for the return value + Register itsResult; + }; - // a stack of JSFrames. - typedef std::stack > > JSFrameStack; + // a stack of JSFrames. + typedef std::stack > > JSFrameStack; - } /* namespace JSTypes */ +} /* namespace JSTypes */ } /* namespace JavaScript */ diff --git a/js/js2/tools/gencode.pl b/js/js2/tools/gencode.pl index d87eab8a6dc..8b8eb4cf510 100644 --- a/js/js2/tools/gencode.pl +++ b/js/js2/tools/gencode.pl @@ -1,7 +1,7 @@ use strict; my $tab = " "; -my $tab2 = " "; +my $init_tab = $tab; my $enum_decs = ""; my $class_decs = ""; my @name_array; @@ -186,20 +186,21 @@ sub collect { } push (@name_array, $opname); - $enum_decs .= "$tab2$tab$opname, /* $rem */\n"; - $class_decs .= ($tab2 . "class $cname : public $super {\n" . - $tab2 . "public:\n" . - $tab2 . $tab . "/* $rem */\n" . - $tab2 . $tab . "$cname ($dec_list) :\n" . - $tab2 . $tab . $tab . "$super\n$tab2$tab$tab($params) " . + $enum_decs .= "$init_tab$tab$opname, /* $rem */\n"; + $class_decs .= ($init_tab . "class $cname : public $super {\n" . + $init_tab . "public:\n" . + $init_tab . $tab . "/* $rem */\n" . + $init_tab . $tab . "$cname ($dec_list) :\n" . + $init_tab . $tab . $tab . "$super\n" . + "$init_tab$tab$tab($params) " . "{};\n" . - $tab2 . $tab . + $init_tab . $tab . "virtual Formatter& print (Formatter& f) {\n" . - $tab2 . $tab . $tab . "f << opcodeNames[$opname];\n" . + $init_tab . $tab . $tab . "f << opcodeNames[$opname];\n" . $printbody . - $tab2 . $tab . $tab . "return f;\n" . - $tab2 . $tab . "}\n" . - $tab2 . "};\n\n"); + $init_tab . $tab . $tab . "return f;\n" . + $init_tab . $tab . "}\n" . + $init_tab . "};\n\n"); } sub spew { @@ -274,7 +275,7 @@ sub get_printbody { my $type; my @oplist; my $op = 1; - my $in = $tab2 . $tab . $tab; + my $in = $init_tab . $tab . $tab; for $type (@types) { print "type $type\n"; diff --git a/js/js2/vmtypes.cpp b/js/js2/vmtypes.cpp index d0d89df4681..10a1d375c55 100644 --- a/js/js2/vmtypes.cpp +++ b/js/js2/vmtypes.cpp @@ -35,29 +35,28 @@ #include "vmtypes.h" namespace JavaScript { - - namespace VM { +namespace VM { - Formatter& operator<< (Formatter& f, Instruction& i) - { - return i.print(f); + Formatter& operator<< (Formatter& f, Instruction& i) + { + return i.print(f); + } + + Formatter& operator<< (Formatter& f, RegisterList& rl) + { + Register* e = rl.end(); + + f << "("; + for (RegisterList::iterator r = rl.begin(); r != e; r++) { + f << "R" << (*r); + if ((r + 1) != e) + f << ", "; } - - Formatter& operator<< (Formatter& f, RegisterList& rl) - { - Register* e = rl.end(); - - f << "("; - for (RegisterList::iterator r = rl.begin(); r != e; r++) { - f << "R" << (*r); - if ((r + 1) != e) - f << ", "; - } - f << ")"; - - return f; - } - }; -}; + f << ")"; + + return f; + } +} /* namespace VM */ +} /* namespace JavaScript */ diff --git a/js/js2/vmtypes.h b/js/js2/vmtypes.h index 2c9009e0751..2ddec054a26 100644 --- a/js/js2/vmtypes.h +++ b/js/js2/vmtypes.h @@ -39,978 +39,1009 @@ #include "numerics.h" /* needed for formatter << double */ namespace JavaScript { - - namespace VM { +namespace VM { - enum ICodeOp { - ADD, /* dest, source1, source2 */ - BRANCH, /* target label */ - BRANCH_EQ, /* target label, condition */ - BRANCH_GE, /* target label, condition */ - BRANCH_GT, /* target label, condition */ - BRANCH_LE, /* target label, condition */ - BRANCH_LT, /* target label, condition */ - BRANCH_NE, /* target label, condition */ - CALL, /* result, target, args */ - COMPARE_EQ, /* dest, source */ - COMPARE_GE, /* dest, source */ - COMPARE_GT, /* dest, source */ - COMPARE_LE, /* dest, source */ - COMPARE_LT, /* dest, source */ - COMPARE_NE, /* dest, source */ - DIVIDE, /* dest, source1, source2 */ - GET_ELEMENT, /* dest, array, index */ - GET_PROP, /* dest, object, prop name */ - LOAD_IMMEDIATE, /* dest, immediate value (double) */ - LOAD_NAME, /* dest, name */ - LOAD_VAR, /* dest, index of frame slot */ - MOVE, /* dest, source */ - MULTIPLY, /* dest, source1, source2 */ - NEW_ARRAY, /* dest */ - NEW_OBJECT, /* dest */ - NOP, /* do nothing and like it */ - NOT, /* dest, source */ - RETURN, /* return value or NotARegister */ - SAVE_NAME, /* name, source */ - SAVE_VAR, /* index of frame slot, source */ - SET_ELEMENT, /* base, source1, source2 */ - SET_PROP, /* object, name, source */ - SUBTRACT /* dest, source1, source2 */ - }; - - /********************************************************************/ - - - static char *opcodeNames[] = { - "ADD ", - "BRANCH ", - "BRANCH_EQ ", - "BRANCH_GE ", - "BRANCH_GT ", - "BRANCH_LE ", - "BRANCH_LT ", - "BRANCH_NE ", - "CALL ", - "COMPARE_EQ ", - "COMPARE_GE ", - "COMPARE_GT ", - "COMPARE_LE ", - "COMPARE_LT ", - "COMPARE_NE ", - "DIVIDE ", - "GET_ELEMENT ", - "GET_PROP ", - "LOAD_IMMEDIATE", - "LOAD_NAME ", - "LOAD_VAR ", - "MOVE ", - "MULTIPLY ", - "NEW_ARRAY ", - "NEW_OBJECT ", - "NOP ", - "NOT ", - "RETURN ", - "SAVE_NAME ", - "SAVE_VAR ", - "SET_ELEMENT ", - "SET_PROP ", - "SUBTRACT " - }; - - /********************************************************************/ - - /* super-class for all instructions */ - class Instruction - { - public: - Instruction(ICodeOp opcodeA) : opcode(opcodeA) { } - virtual Formatter& print (Formatter& f) { - f << opcodeNames[opcode] << "\t"; - return f; - } - - ICodeOp getBranchOp() \ - { return ((opcode >= COMPARE_LT) && (opcode <= COMPARE_GT)) ? \ - (ICodeOp)(BRANCH_LT + (opcode - COMPARE_LT)) : NOP; } - - ICodeOp op() { return opcode; } - - protected: - ICodeOp opcode; - - }; - - /********************************************************************/ - - enum { NotARegister = 0xFFFFFFFF }; - enum { NotALabel = 0xFFFFFFFF }; - enum { NotAnOffset = 0xFFFFFFFF }; + enum ICodeOp { + ADD, /* dest, source1, source2 */ + BRANCH, /* target label */ + BRANCH_EQ, /* target label, condition */ + BRANCH_GE, /* target label, condition */ + BRANCH_GT, /* target label, condition */ + BRANCH_LE, /* target label, condition */ + BRANCH_LT, /* target label, condition */ + BRANCH_NE, /* target label, condition */ + CALL, /* result, target, args */ + COMPARE_EQ, /* dest, source */ + COMPARE_GE, /* dest, source */ + COMPARE_GT, /* dest, source */ + COMPARE_LE, /* dest, source */ + COMPARE_LT, /* dest, source */ + COMPARE_NE, /* dest, source */ + DIVIDE, /* dest, source1, source2 */ + GET_ELEMENT, /* dest, array, index */ + GET_PROP, /* dest, object, prop name */ + LOAD_IMMEDIATE, /* dest, immediate value (double) */ + LOAD_NAME, /* dest, name */ + LOAD_VAR, /* dest, index of frame slot */ + MOVE, /* dest, source */ + MULTIPLY, /* dest, source1, source2 */ + NEW_ARRAY, /* dest */ + NEW_OBJECT, /* dest */ + NOP, /* do nothing and like it */ + NOT, /* dest, source */ + RETURN, /* return value or NotARegister */ + SAVE_NAME, /* name, source */ + SAVE_VAR, /* index of frame slot, source */ + SET_ELEMENT, /* base, source1, source2 */ + SET_PROP, /* object, name, source */ + SUBTRACT /* dest, source1, source2 */ + }; - /********************************************************************/ - - typedef uint32 Register; - typedef std::vector RegisterList; - typedef std::vector InstructionStream; - typedef InstructionStream::iterator InstructionIterator; - - /********************************************************************/ - - Formatter& operator<< (Formatter& f, Instruction& i); - Formatter& operator<< (Formatter& f, RegisterList& rl); - - /********************************************************************/ + /********************************************************************/ - class Label { - public: - Label(InstructionStream* baseA) : - base(baseA), offset(NotALabel) {} - - InstructionStream *base; - uint32 offset; - }; + + static char *opcodeNames[] = { + "ADD ", + "BRANCH ", + "BRANCH_EQ ", + "BRANCH_GE ", + "BRANCH_GT ", + "BRANCH_LE ", + "BRANCH_LT ", + "BRANCH_NE ", + "CALL ", + "COMPARE_EQ ", + "COMPARE_GE ", + "COMPARE_GT ", + "COMPARE_LE ", + "COMPARE_LT ", + "COMPARE_NE ", + "DIVIDE ", + "GET_ELEMENT ", + "GET_PROP ", + "LOAD_IMMEDIATE", + "LOAD_NAME ", + "LOAD_VAR ", + "MOVE ", + "MULTIPLY ", + "NEW_ARRAY ", + "NEW_OBJECT ", + "NOP ", + "NOT ", + "RETURN ", + "SAVE_NAME ", + "SAVE_VAR ", + "SET_ELEMENT ", + "SET_PROP ", + "SUBTRACT " + }; + + /********************************************************************/ + + /* super-class for all instructions */ + class Instruction + { + public: + Instruction(ICodeOp opcodeA) : opcode(opcodeA) { } + virtual Formatter& print (Formatter& f) { + f << opcodeNames[opcode] << "\t"; + return f; + } - typedef std::vector