diff --git a/js/js2/icodegenerator.cpp b/js/js2/icodegenerator.cpp index af130549a2ff..1750b2513507 100644 --- a/js/js2/icodegenerator.cpp +++ b/js/js2/icodegenerator.cpp @@ -59,6 +59,7 @@ namespace ICG { { #ifdef DEBUG ASSERT(stitcher.empty()); + ASSERT(statementLabels.empty()); for (LabelList::iterator i = labels.begin(); i != labels.end(); i++) { ASSERT((*i)->mBase == iCode); @@ -207,6 +208,26 @@ namespace ICG { iCode->push_back(instr); } + void ICodeGenerator::branchNotConditional(Label *label, Register condition) + { + ICodeOp branchOp = getBranchOp(); + if (branchOp == NOP) { + // XXXX emit convert to boolean / Test / ... + branchOp = BRANCH_NE; + } + switch (branchOp) { + case BRANCH_EQ : branchOp = BRANCH_NE; break; + case BRANCH_GE : branchOp = BRANCH_LT; break; + case BRANCH_GT : branchOp = BRANCH_LE; break; + case BRANCH_LE : branchOp = BRANCH_GT; break; + case BRANCH_LT : branchOp = BRANCH_GE; break; + case BRANCH_NE : branchOp = BRANCH_EQ; break; + default : NOT_REACHED("Expected a branch op"); break; + } + GenericBranch *instr = new GenericBranch(branchOp, label, condition); + iCode->push_back(instr); + } + /********************************************************************/ Label *ICodeGenerator::getLabel() @@ -262,7 +283,7 @@ namespace ICG { branch(whileConditionTop); // save off the current stream while we gen code for the condition - stitcher.push_back(new WhileCodeState(whileConditionTop, + addStitcher(new WhileCodeState(whileConditionTop, whileBlockStart, this)); iCode = new InstructionStream(); @@ -314,7 +335,7 @@ namespace ICG { branch(forCondition); - stitcher.push_back(ics); + addStitcher(ics); // begin the stream for collecting the condition expression iCode = new InstructionStream(); @@ -383,7 +404,7 @@ namespace ICG { Label *doCondition = getLabel(); setLabel(doBlock); - stitcher.push_back(new DoCodeState(doBlock, doCondition, this)); + addStitcher(new DoCodeState(doBlock, doCondition, this)); iCode = new InstructionStream(); } @@ -430,7 +451,7 @@ namespace ICG { InstructionStream *x = new InstructionStream(); SwitchCodeState *ics = new SwitchCodeState(control, this); ics->swapStream(x); - stitcher.push_back(ics); + addStitcher(ics); } void ICodeGenerator::endCaseCondition(Register expression) @@ -448,7 +469,7 @@ namespace ICG { resetTopRegister(); } - void ICodeGenerator::beginCaseStatement() + void ICodeGenerator::beginCaseStatement(uint32 pos) { SwitchCodeState *ics = static_cast(stitcher.back()); @@ -468,7 +489,7 @@ namespace ICG { resetTopRegister(); } - void ICodeGenerator::beginDefaultStatement() + void ICodeGenerator::beginDefaultStatement(uint32 pos) { SwitchCodeState *ics = static_cast(stitcher.back()); @@ -525,10 +546,9 @@ namespace ICG { { Label *elseLabel = getLabel(); - stitcher.push_back(new IfCodeState(elseLabel, NULL, this)); + addStitcher(new IfCodeState(elseLabel, NULL, this)); - Register notCond = op(NOT, condition); - branchConditional(elseLabel, notCond); + branchNotConditional(elseLabel, condition); resetTopRegister(); } @@ -563,7 +583,7 @@ namespace ICG { /************************************************************************/ - void ICodeGenerator::breakStatement() + void ICodeGenerator::breakStatement(uint32 pos) { for (std::vector::reverse_iterator p = stitcher.rbegin(); p != stitcher.rend(); p++) { @@ -583,7 +603,30 @@ namespace ICG { NOT_REACHED("no break target available"); } - void ICodeGenerator::continueStatement() + void ICodeGenerator::breakStatement(uint32 pos, const StringAtom &label) + { + uint32 statementLabelCeiling = statementLabels.size(); + + for (std::vector::reverse_iterator p = + stitcher.rbegin(); p != stitcher.rend(); p++) { + + for (std::vector::iterator lbl = + statementLabels.begin() + (*p)->statementLabelBase; + lbl != statementLabels.begin() + statementLabelCeiling; + lbl++) { + if ((*lbl) == &label) { + if ((*p)->breakLabel == NULL) + (*p)->breakLabel = getLabel(); + branch((*p)->breakLabel); + return; + } + } + statementLabelCeiling = (*p)->statementLabelBase; + } + NOT_REACHED("no break target available"); + } + + void ICodeGenerator::continueStatement(uint32 pos) { for (std::vector::reverse_iterator p = stitcher.rbegin(); p != stitcher.rend(); p++) { @@ -602,7 +645,32 @@ namespace ICG { NOT_REACHED("no continue target available"); } - Formatter& ICodeGenerator::print(Formatter& f) + void ICodeGenerator::continueStatement(uint32 pos, const StringAtom &label) + { + uint32 statementLabelCeiling = statementLabels.size(); + + for (std::vector::reverse_iterator p = + stitcher.rbegin(); p != stitcher.rend(); p++) { + + for (std::vector::iterator lbl = + statementLabels.begin() + (*p)->statementLabelBase; + lbl != statementLabels.begin() + statementLabelCeiling; + lbl++) { + if ((*lbl) == &label) { + if ((*p)->continueLabel == NULL) + (*p)->continueLabel = getLabel(); + branch((*p)->continueLabel); + return; + } + } + statementLabelCeiling = (*p)->statementLabelBase; + } + NOT_REACHED("no continue target available"); + } + + /************************************************************************/ + + Formatter& ICodeGenerator::print(Formatter& f) { f << "ICG! " << (uint32)iCode->size() << "\n"; for (InstructionIterator i = iCode->begin(); diff --git a/js/js2/icodegenerator.h b/js/js2/icodegenerator.h index c4e977952b3a..f2efec11a59e 100644 --- a/js/js2/icodegenerator.h +++ b/js/js2/icodegenerator.h @@ -72,6 +72,7 @@ namespace ICG { StateKind stateKind; Register registerBase; + uint32 statementLabelBase; Label *breakLabel; Label *continueLabel; }; @@ -97,6 +98,7 @@ namespace ICG { InstructionStream *iCode; LabelList labels; std::vector stitcher; + std::vector statementLabels; void markMaxRegister() \ { if (topRegister > maxRegister) maxRegister = topRegister; } @@ -107,21 +109,26 @@ namespace ICG { { markMaxRegister(); topRegister = stitcher.empty() ? registerBase : \ stitcher.back()->registerBase; } - ICodeOp getBranchOp() \ - { ASSERT(!iCode->empty()); return iCode->back()->getBranchOp(); } + void addStitcher(ICodeState *ics) \ + { stitcher.push_back(ics); statementLabelBase = statementLabels.size(); } + + ICodeOp getBranchOp() \ + { return (iCode->empty()) ? NOP : iCode->back()->getBranchOp(); } Register topRegister; Register registerBase; - uint32 maxRegister; + uint32 maxRegister; + uint32 statementLabelBase;; void setLabel(Label *label); void setLabel(InstructionStream *stream, Label *label); void branch(Label *label); void branchConditional(Label *label, Register condition); + void branchNotConditional(Label *label, Register condition); public: - ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0) + ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0), statementLabelBase(0) { iCode = new InstructionStream(); } virtual ~ICodeGenerator() { if (iCode) delete iCode; } @@ -140,6 +147,7 @@ namespace ICG { Register call(Register target, RegisterList args); void move(Register destination, Register source); + void not(Register destination, Register source); Register compare(ICodeOp op, Register source1, Register source2); @@ -157,8 +165,9 @@ namespace ICG { Register getElement(Register base, Register index); void setElement(Register base, Register index, Register value); - Register getRegisterBase() { return topRegister; } - InstructionStream *get_iCode() { return iCode; } + Register getRegisterBase() { return topRegister; } + InstructionStream *get_iCode() { return iCode; } + uint32 getStatementLabelBase() { return statementLabelBase; } Label *getLabel(); @@ -202,26 +211,28 @@ namespace ICG { void endCaseCondition(Register expression); - void beginCaseStatement(); + void beginCaseStatement(uint32 pos); void endCaseStatement(); // optionally - void beginDefaultStatement(); + void beginDefaultStatement(uint32 pos); 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 beginLabelStatement(uint32 pos, const StringAtom &label) + { statementLabels.push_back(&label); } + void endLabelStatement() { statementLabels.pop_back(); } - void continueStatement(const StringAtom &label); - void breakStatement(const StringAtom &label); + void continueStatement(uint32 pos); + void breakStatement(uint32 pos); - void throwStatement(Register expression); + void continueStatement(uint32 pos, const StringAtom &label); + void breakStatement(uint32 pos, const StringAtom &label); - void beginCatchStatement(); + void throwStatement(uint32 pos, Register expression); + + void beginCatchStatement(uint32 pos); void endCatchExpression(Register expression); void endCatchStatement(); @@ -318,7 +329,8 @@ namespace ICG { inline ICodeState::ICodeState(StateKind kind, ICodeGenerator *icg) : stateKind(kind), registerBase(icg->getRegisterBase()), - breakLabel(NULL), continueLabel(NULL) { } + breakLabel(NULL), continueLabel(NULL), + statementLabelBase(icg->getStatementLabelBase()) { } inline SwitchCodeState::SwitchCodeState(Register control, ICodeGenerator *icg) diff --git a/js/js2/interpreter.cpp b/js/js2/interpreter.cpp index 4f2023450043..549bb2e75197 100644 --- a/js/js2/interpreter.cpp +++ b/js/js2/interpreter.cpp @@ -47,6 +47,9 @@ namespace JavaScript { #define src2(i) op3(i) #define ofs(i) (i->getOffset()) + using namespace ICG; + using namespace JSTypes; + JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) { diff --git a/js/js2/js2.cpp b/js/js2/js2.cpp index 5a99d5d944f4..994167066da6 100644 --- a/js/js2/js2.cpp +++ b/js/js2/js2.cpp @@ -26,6 +26,7 @@ #include "world.h" #include "interpreter.h" +#include "icodegenerator.h" #if defined(XP_MAC) && !defined(XP_MAC_MPW) @@ -57,6 +58,10 @@ static void initConsole(StringPtr consoleName, namespace JavaScript { namespace Shell { + using namespace ICG; + using namespace JSTypes; + // using namespace VMTypes; + // Interactively read a line from the input stream in and put it into // s Return false if reached the end of input before reading anything. static bool promptLine(LineReader &inReader, string &s, @@ -117,9 +122,7 @@ namespace Shell { } stdOut << '\n'; } - -#include "icodegenerator.h" - + static void testICG(World &world) { // @@ -127,7 +130,7 @@ namespace Shell { // uint32 pos = 0; ICodeGenerator icg; - + // var i,j; // i is bound to var #0, j to var #1 Register r_i = icg.allocateVariable(world.identifiers[widenCString("i")]); @@ -136,19 +139,27 @@ namespace Shell { // i = j + 2; icg.beginStatement(pos); Register r1 = icg.loadImmediate(2.0); - icg.move(r_i, icg.op(ADD, r_i, r_j)); - + icg.move(r_i, icg.op(ADD, r1, r_j)); + // j = a.b icg.beginStatement(pos); r1 = icg.loadName(world.identifiers[widenCString("a")]); r1 = icg.getProperty(r1, world.identifiers[widenCString("b")]); icg.move(r_j, r1); - // while (i) i = i + j; + // label1 : while (i) { while (i) { i = i + j; break label1; } } + icg.beginLabelStatement(pos, world.identifiers[widenCString("label1")]); icg.beginWhileStatement(pos); icg.endWhileExpression(r_i); - icg.move(r_i, icg.op(ADD, r_i, r_j)); + + icg.beginWhileStatement(pos); + icg.endWhileExpression(r_i); + icg.move(r_i, icg.op(ADD, r_i, r_j)); + icg.breakStatement(pos, world.identifiers[widenCString("label1")]); + icg.endWhileStatement(); + icg.endWhileStatement(); + icg.endLabelStatement(); // if (i) if (j) i = 3; else j = 4; icg.beginIfStatement(pos, r_i); @@ -159,35 +170,35 @@ namespace Shell { icg.endIfStatement(); icg.beginElseStatement(false); icg.endIfStatement(); - + // switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; } icg.beginSwitchStatement(pos, r_i); // case 3, note empty case statement (?necessary???) icg.endCaseCondition(icg.loadImmediate(3)); - icg.beginCaseStatement(); + icg.beginCaseStatement(pos); icg.endCaseStatement(); // case 4 icg.endCaseCondition(icg.loadImmediate(4)); - icg.beginCaseStatement(); + icg.beginCaseStatement(pos); icg.beginStatement(pos); icg.move(r_j, icg.loadImmediate(4)); - icg.breakStatement(); + icg.breakStatement(pos); icg.endCaseStatement(); // case 5 icg.endCaseCondition(icg.loadImmediate(5)); - icg.beginCaseStatement(); + icg.beginCaseStatement(pos); icg.beginStatement(pos); icg.move(r_j, icg.loadImmediate(5)); - icg.breakStatement(); + icg.breakStatement(pos); icg.endCaseStatement(); // default - icg.beginDefaultStatement(); + icg.beginDefaultStatement(pos); icg.beginStatement(pos); icg.move(r_j, icg.loadImmediate(6)); icg.endDefaultStatement(); icg.endSwitchStatement(); - + // for ( ; i; i = i + 1 ) j = 99; icg.beginForStatement(pos); icg.forCondition(r_i); @@ -389,14 +400,14 @@ int main(int /* argc */, char /* **argv */) #if defined(XP_MAC) && !defined(XP_MAC_MPW) initConsole("\pJavaScript Shell", "Welcome to the js2 shell.\n", argc, argv); #endif - JavaScript::World world; + JavaScript::World world; #if 1 assert(JavaScript::Shell::testFactorial(world, 5) == 120); assert(JavaScript::Shell::testObjects(world, 5) == 5); - // testICG(world); + // JavaScript::Shell::testICG(world); assert(JavaScript::Shell::testFunctionCall(world, 5) == 5); #endif - JavaScript::Shell::readEvalPrint(stdin, world); + JavaScript::Shell::readEvalPrint(stdin, world); return 0; // return ProcessArgs(argv + 1, argc - 1); } diff --git a/js2/src/icodegenerator.cpp b/js2/src/icodegenerator.cpp index af130549a2ff..1750b2513507 100644 --- a/js2/src/icodegenerator.cpp +++ b/js2/src/icodegenerator.cpp @@ -59,6 +59,7 @@ namespace ICG { { #ifdef DEBUG ASSERT(stitcher.empty()); + ASSERT(statementLabels.empty()); for (LabelList::iterator i = labels.begin(); i != labels.end(); i++) { ASSERT((*i)->mBase == iCode); @@ -207,6 +208,26 @@ namespace ICG { iCode->push_back(instr); } + void ICodeGenerator::branchNotConditional(Label *label, Register condition) + { + ICodeOp branchOp = getBranchOp(); + if (branchOp == NOP) { + // XXXX emit convert to boolean / Test / ... + branchOp = BRANCH_NE; + } + switch (branchOp) { + case BRANCH_EQ : branchOp = BRANCH_NE; break; + case BRANCH_GE : branchOp = BRANCH_LT; break; + case BRANCH_GT : branchOp = BRANCH_LE; break; + case BRANCH_LE : branchOp = BRANCH_GT; break; + case BRANCH_LT : branchOp = BRANCH_GE; break; + case BRANCH_NE : branchOp = BRANCH_EQ; break; + default : NOT_REACHED("Expected a branch op"); break; + } + GenericBranch *instr = new GenericBranch(branchOp, label, condition); + iCode->push_back(instr); + } + /********************************************************************/ Label *ICodeGenerator::getLabel() @@ -262,7 +283,7 @@ namespace ICG { branch(whileConditionTop); // save off the current stream while we gen code for the condition - stitcher.push_back(new WhileCodeState(whileConditionTop, + addStitcher(new WhileCodeState(whileConditionTop, whileBlockStart, this)); iCode = new InstructionStream(); @@ -314,7 +335,7 @@ namespace ICG { branch(forCondition); - stitcher.push_back(ics); + addStitcher(ics); // begin the stream for collecting the condition expression iCode = new InstructionStream(); @@ -383,7 +404,7 @@ namespace ICG { Label *doCondition = getLabel(); setLabel(doBlock); - stitcher.push_back(new DoCodeState(doBlock, doCondition, this)); + addStitcher(new DoCodeState(doBlock, doCondition, this)); iCode = new InstructionStream(); } @@ -430,7 +451,7 @@ namespace ICG { InstructionStream *x = new InstructionStream(); SwitchCodeState *ics = new SwitchCodeState(control, this); ics->swapStream(x); - stitcher.push_back(ics); + addStitcher(ics); } void ICodeGenerator::endCaseCondition(Register expression) @@ -448,7 +469,7 @@ namespace ICG { resetTopRegister(); } - void ICodeGenerator::beginCaseStatement() + void ICodeGenerator::beginCaseStatement(uint32 pos) { SwitchCodeState *ics = static_cast(stitcher.back()); @@ -468,7 +489,7 @@ namespace ICG { resetTopRegister(); } - void ICodeGenerator::beginDefaultStatement() + void ICodeGenerator::beginDefaultStatement(uint32 pos) { SwitchCodeState *ics = static_cast(stitcher.back()); @@ -525,10 +546,9 @@ namespace ICG { { Label *elseLabel = getLabel(); - stitcher.push_back(new IfCodeState(elseLabel, NULL, this)); + addStitcher(new IfCodeState(elseLabel, NULL, this)); - Register notCond = op(NOT, condition); - branchConditional(elseLabel, notCond); + branchNotConditional(elseLabel, condition); resetTopRegister(); } @@ -563,7 +583,7 @@ namespace ICG { /************************************************************************/ - void ICodeGenerator::breakStatement() + void ICodeGenerator::breakStatement(uint32 pos) { for (std::vector::reverse_iterator p = stitcher.rbegin(); p != stitcher.rend(); p++) { @@ -583,7 +603,30 @@ namespace ICG { NOT_REACHED("no break target available"); } - void ICodeGenerator::continueStatement() + void ICodeGenerator::breakStatement(uint32 pos, const StringAtom &label) + { + uint32 statementLabelCeiling = statementLabels.size(); + + for (std::vector::reverse_iterator p = + stitcher.rbegin(); p != stitcher.rend(); p++) { + + for (std::vector::iterator lbl = + statementLabels.begin() + (*p)->statementLabelBase; + lbl != statementLabels.begin() + statementLabelCeiling; + lbl++) { + if ((*lbl) == &label) { + if ((*p)->breakLabel == NULL) + (*p)->breakLabel = getLabel(); + branch((*p)->breakLabel); + return; + } + } + statementLabelCeiling = (*p)->statementLabelBase; + } + NOT_REACHED("no break target available"); + } + + void ICodeGenerator::continueStatement(uint32 pos) { for (std::vector::reverse_iterator p = stitcher.rbegin(); p != stitcher.rend(); p++) { @@ -602,7 +645,32 @@ namespace ICG { NOT_REACHED("no continue target available"); } - Formatter& ICodeGenerator::print(Formatter& f) + void ICodeGenerator::continueStatement(uint32 pos, const StringAtom &label) + { + uint32 statementLabelCeiling = statementLabels.size(); + + for (std::vector::reverse_iterator p = + stitcher.rbegin(); p != stitcher.rend(); p++) { + + for (std::vector::iterator lbl = + statementLabels.begin() + (*p)->statementLabelBase; + lbl != statementLabels.begin() + statementLabelCeiling; + lbl++) { + if ((*lbl) == &label) { + if ((*p)->continueLabel == NULL) + (*p)->continueLabel = getLabel(); + branch((*p)->continueLabel); + return; + } + } + statementLabelCeiling = (*p)->statementLabelBase; + } + NOT_REACHED("no continue target available"); + } + + /************************************************************************/ + + Formatter& ICodeGenerator::print(Formatter& f) { f << "ICG! " << (uint32)iCode->size() << "\n"; for (InstructionIterator i = iCode->begin(); diff --git a/js2/src/icodegenerator.h b/js2/src/icodegenerator.h index c4e977952b3a..f2efec11a59e 100644 --- a/js2/src/icodegenerator.h +++ b/js2/src/icodegenerator.h @@ -72,6 +72,7 @@ namespace ICG { StateKind stateKind; Register registerBase; + uint32 statementLabelBase; Label *breakLabel; Label *continueLabel; }; @@ -97,6 +98,7 @@ namespace ICG { InstructionStream *iCode; LabelList labels; std::vector stitcher; + std::vector statementLabels; void markMaxRegister() \ { if (topRegister > maxRegister) maxRegister = topRegister; } @@ -107,21 +109,26 @@ namespace ICG { { markMaxRegister(); topRegister = stitcher.empty() ? registerBase : \ stitcher.back()->registerBase; } - ICodeOp getBranchOp() \ - { ASSERT(!iCode->empty()); return iCode->back()->getBranchOp(); } + void addStitcher(ICodeState *ics) \ + { stitcher.push_back(ics); statementLabelBase = statementLabels.size(); } + + ICodeOp getBranchOp() \ + { return (iCode->empty()) ? NOP : iCode->back()->getBranchOp(); } Register topRegister; Register registerBase; - uint32 maxRegister; + uint32 maxRegister; + uint32 statementLabelBase;; void setLabel(Label *label); void setLabel(InstructionStream *stream, Label *label); void branch(Label *label); void branchConditional(Label *label, Register condition); + void branchNotConditional(Label *label, Register condition); public: - ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0) + ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0), statementLabelBase(0) { iCode = new InstructionStream(); } virtual ~ICodeGenerator() { if (iCode) delete iCode; } @@ -140,6 +147,7 @@ namespace ICG { Register call(Register target, RegisterList args); void move(Register destination, Register source); + void not(Register destination, Register source); Register compare(ICodeOp op, Register source1, Register source2); @@ -157,8 +165,9 @@ namespace ICG { Register getElement(Register base, Register index); void setElement(Register base, Register index, Register value); - Register getRegisterBase() { return topRegister; } - InstructionStream *get_iCode() { return iCode; } + Register getRegisterBase() { return topRegister; } + InstructionStream *get_iCode() { return iCode; } + uint32 getStatementLabelBase() { return statementLabelBase; } Label *getLabel(); @@ -202,26 +211,28 @@ namespace ICG { void endCaseCondition(Register expression); - void beginCaseStatement(); + void beginCaseStatement(uint32 pos); void endCaseStatement(); // optionally - void beginDefaultStatement(); + void beginDefaultStatement(uint32 pos); 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 beginLabelStatement(uint32 pos, const StringAtom &label) + { statementLabels.push_back(&label); } + void endLabelStatement() { statementLabels.pop_back(); } - void continueStatement(const StringAtom &label); - void breakStatement(const StringAtom &label); + void continueStatement(uint32 pos); + void breakStatement(uint32 pos); - void throwStatement(Register expression); + void continueStatement(uint32 pos, const StringAtom &label); + void breakStatement(uint32 pos, const StringAtom &label); - void beginCatchStatement(); + void throwStatement(uint32 pos, Register expression); + + void beginCatchStatement(uint32 pos); void endCatchExpression(Register expression); void endCatchStatement(); @@ -318,7 +329,8 @@ namespace ICG { inline ICodeState::ICodeState(StateKind kind, ICodeGenerator *icg) : stateKind(kind), registerBase(icg->getRegisterBase()), - breakLabel(NULL), continueLabel(NULL) { } + breakLabel(NULL), continueLabel(NULL), + statementLabelBase(icg->getStatementLabelBase()) { } inline SwitchCodeState::SwitchCodeState(Register control, ICodeGenerator *icg) diff --git a/js2/src/interpreter.cpp b/js2/src/interpreter.cpp index 4f2023450043..549bb2e75197 100644 --- a/js2/src/interpreter.cpp +++ b/js2/src/interpreter.cpp @@ -47,6 +47,9 @@ namespace JavaScript { #define src2(i) op3(i) #define ofs(i) (i->getOffset()) + using namespace ICG; + using namespace JSTypes; + JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) { diff --git a/js2/tests/cpp/js2_shell.cpp b/js2/tests/cpp/js2_shell.cpp index 5a99d5d944f4..994167066da6 100644 --- a/js2/tests/cpp/js2_shell.cpp +++ b/js2/tests/cpp/js2_shell.cpp @@ -26,6 +26,7 @@ #include "world.h" #include "interpreter.h" +#include "icodegenerator.h" #if defined(XP_MAC) && !defined(XP_MAC_MPW) @@ -57,6 +58,10 @@ static void initConsole(StringPtr consoleName, namespace JavaScript { namespace Shell { + using namespace ICG; + using namespace JSTypes; + // using namespace VMTypes; + // Interactively read a line from the input stream in and put it into // s Return false if reached the end of input before reading anything. static bool promptLine(LineReader &inReader, string &s, @@ -117,9 +122,7 @@ namespace Shell { } stdOut << '\n'; } - -#include "icodegenerator.h" - + static void testICG(World &world) { // @@ -127,7 +130,7 @@ namespace Shell { // uint32 pos = 0; ICodeGenerator icg; - + // var i,j; // i is bound to var #0, j to var #1 Register r_i = icg.allocateVariable(world.identifiers[widenCString("i")]); @@ -136,19 +139,27 @@ namespace Shell { // i = j + 2; icg.beginStatement(pos); Register r1 = icg.loadImmediate(2.0); - icg.move(r_i, icg.op(ADD, r_i, r_j)); - + icg.move(r_i, icg.op(ADD, r1, r_j)); + // j = a.b icg.beginStatement(pos); r1 = icg.loadName(world.identifiers[widenCString("a")]); r1 = icg.getProperty(r1, world.identifiers[widenCString("b")]); icg.move(r_j, r1); - // while (i) i = i + j; + // label1 : while (i) { while (i) { i = i + j; break label1; } } + icg.beginLabelStatement(pos, world.identifiers[widenCString("label1")]); icg.beginWhileStatement(pos); icg.endWhileExpression(r_i); - icg.move(r_i, icg.op(ADD, r_i, r_j)); + + icg.beginWhileStatement(pos); + icg.endWhileExpression(r_i); + icg.move(r_i, icg.op(ADD, r_i, r_j)); + icg.breakStatement(pos, world.identifiers[widenCString("label1")]); + icg.endWhileStatement(); + icg.endWhileStatement(); + icg.endLabelStatement(); // if (i) if (j) i = 3; else j = 4; icg.beginIfStatement(pos, r_i); @@ -159,35 +170,35 @@ namespace Shell { icg.endIfStatement(); icg.beginElseStatement(false); icg.endIfStatement(); - + // switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; } icg.beginSwitchStatement(pos, r_i); // case 3, note empty case statement (?necessary???) icg.endCaseCondition(icg.loadImmediate(3)); - icg.beginCaseStatement(); + icg.beginCaseStatement(pos); icg.endCaseStatement(); // case 4 icg.endCaseCondition(icg.loadImmediate(4)); - icg.beginCaseStatement(); + icg.beginCaseStatement(pos); icg.beginStatement(pos); icg.move(r_j, icg.loadImmediate(4)); - icg.breakStatement(); + icg.breakStatement(pos); icg.endCaseStatement(); // case 5 icg.endCaseCondition(icg.loadImmediate(5)); - icg.beginCaseStatement(); + icg.beginCaseStatement(pos); icg.beginStatement(pos); icg.move(r_j, icg.loadImmediate(5)); - icg.breakStatement(); + icg.breakStatement(pos); icg.endCaseStatement(); // default - icg.beginDefaultStatement(); + icg.beginDefaultStatement(pos); icg.beginStatement(pos); icg.move(r_j, icg.loadImmediate(6)); icg.endDefaultStatement(); icg.endSwitchStatement(); - + // for ( ; i; i = i + 1 ) j = 99; icg.beginForStatement(pos); icg.forCondition(r_i); @@ -389,14 +400,14 @@ int main(int /* argc */, char /* **argv */) #if defined(XP_MAC) && !defined(XP_MAC_MPW) initConsole("\pJavaScript Shell", "Welcome to the js2 shell.\n", argc, argv); #endif - JavaScript::World world; + JavaScript::World world; #if 1 assert(JavaScript::Shell::testFactorial(world, 5) == 120); assert(JavaScript::Shell::testObjects(world, 5) == 5); - // testICG(world); + // JavaScript::Shell::testICG(world); assert(JavaScript::Shell::testFunctionCall(world, 5) == 5); #endif - JavaScript::Shell::readEvalPrint(stdin, world); + JavaScript::Shell::readEvalPrint(stdin, world); return 0; // return ProcessArgs(argv + 1, argc - 1); }