From 7741726bd970b56be3112594398032784d4cfb20 Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Thu, 6 Apr 2000 22:40:17 +0000 Subject: [PATCH] Changed compare/branch handling to determine last compare opcode. Made returnStatement a member in ICG. --- js/js2/icodegenerator.cpp | 57 ++++++++++++++++++++++++------------- js/js2/icodegenerator.h | 33 +++++++++++++-------- js/js2/interpreter.cpp | 9 ++++-- js/js2/js2.cpp | 8 +++--- js2/src/icodegenerator.cpp | 57 ++++++++++++++++++++++++------------- js2/src/icodegenerator.h | 33 +++++++++++++-------- js2/src/interpreter.cpp | 9 ++++-- js2/tests/cpp/js2_shell.cpp | 8 +++--- 8 files changed, 140 insertions(+), 74 deletions(-) diff --git a/js/js2/icodegenerator.cpp b/js/js2/icodegenerator.cpp index ef4a6be46204..fdee26eda193 100644 --- a/js/js2/icodegenerator.cpp +++ b/js/js2/icodegenerator.cpp @@ -58,14 +58,6 @@ namespace JavaScript { return iCode; } - InstructionStream *ICodeGenerator::complete(Register result) - { - Return *instr = new Return(RETURN, result); - iCode->push_back(instr); - return complete(); - } - - /***********************************************************************************************/ Register ICodeGenerator::loadVariable(uint32 frameIndex) @@ -128,8 +120,13 @@ namespace JavaScript { iCode->push_back(instr); } - void ICodeGenerator::branchConditional(int32 label, Register condition, ICodeOp branchOp) + void ICodeGenerator::branchConditional(int32 label, Register condition) { + ICodeOp branchOp = getBranchOp(); + if (branchOp == NOP) { + // XXXX emit convert to boolean / Test / ... + branchOp = BRANCH_NE; + } BranchCond *instr = new BranchCond(branchOp, label, condition); iCode->push_back(instr); } @@ -188,8 +185,9 @@ namespace JavaScript { } } - for (InstructionIterator ii = sideStream->begin(); ii != sideStream->end(); ii++) + for (InstructionIterator ii = sideStream->begin(); ii != sideStream->end(); ii++) { iCode->push_back(*ii); + } } @@ -211,12 +209,12 @@ namespace JavaScript { iCode = new InstructionStream(); } - void ICodeGenerator::endWhileExpression(Register condition, ICodeOp branchOp) + void ICodeGenerator::endWhileExpression(Register condition) { WhileCodeState *ics = static_cast(stitcher.back()); ASSERT(ics->stateKind == While_state); - branchConditional(ics->whileBody, condition, branchOp); + branchConditional(ics->whileBody, condition); resetTopRegister(); // stash away the condition expression and switch // back to the main stream @@ -376,7 +374,7 @@ namespace JavaScript { ASSERT(ics->stateKind == Switch_state); int32 caseLabel = getLabel(); - Register r = op(COMPARE, expression, ics->controlExpression); + Register r = op(COMPARE_EQ, expression, ics->controlExpression); branchConditional(caseLabel, r); setLabel(ics->caseStatementsStream, caseLabel); // mark the case in the Case Statement stream @@ -524,10 +522,17 @@ namespace JavaScript { NOT_REACHED("no continue target available"); } + void ICodeGenerator::returnStatement(Register result) + { + Return *instr = new Return(RETURN, result); + iCode->push_back(instr); + } + /***********************************************************************************************/ char *opcodeName[] = { + "nop", "move_to", "load_var", "save_var", @@ -541,6 +546,11 @@ namespace JavaScript { "multiply", "divide", "compare", + "compare", + "compare", + "compare", + "compare", + "compare", "not", "branch", "branch_lt", @@ -563,13 +573,16 @@ namespace JavaScript { { s << "ICG! " << iCode->size() << "\n"; for (InstructionIterator i = iCode->begin(); i != iCode->end(); i++) { + for (LabelList::iterator k = labels.begin(); k != labels.end(); k++) if ((*k)->itsOffset == (i - iCode->begin())) { - s << "label #" << (k - labels.begin()) << ":\n"; + //s << "label #" << (k - labels.begin()) << ":\n"; + s << "#" << (i - iCode->begin()); + break; } Instruction *instr = *i; - s << "\t"<< std::setiosflags( std::ostream::left ) << std::setw(16) << opcodeName[instr->itsOp]; + s << "\t" << std::setiosflags( std::ostream::left ) << std::setw(16) << opcodeName[instr->itsOp]; switch (instr->itsOp) { case LOAD_NAME : { @@ -593,7 +606,7 @@ namespace JavaScript { case BRANCH : { Branch *t = static_cast(instr); - s << "target #" << t->itsOperand1; + s << "instr #" << t->itsOperand1; } break; case BRANCH_LT : @@ -604,14 +617,19 @@ namespace JavaScript { case BRANCH_GT : { BranchCond *t = static_cast(instr); - s << "target #" << t->itsOperand1 << ", R" << t->itsOperand2; + s << "instr #" << t->itsOperand1 << ", R" << t->itsOperand2; } break; case ADD : case SUBTRACT : case MULTIPLY : case DIVIDE : - case COMPARE : + case COMPARE_LT : + case COMPARE_LE : + case COMPARE_EQ : + case COMPARE_NE : + case COMPARE_GT : + case COMPARE_GE : { Arithmetic *t = static_cast(instr); s << "R" << t->itsOperand1 << ", R" << t->itsOperand2 << ", R" << t->itsOperand3; @@ -635,7 +653,8 @@ namespace JavaScript { } for (LabelList::iterator k = labels.begin(); k != labels.end(); k++) if ((*k)->itsOffset == (iCode->end() - iCode->begin())) { - s << "label #" << (k - labels.begin()) << ":\n"; +// s << "label #" << (k - labels.begin()) << ":\n"; + s << "#" << (i - iCode->begin()); } return s; } diff --git a/js/js2/icodegenerator.h b/js/js2/icodegenerator.h index 1977bca2f93b..bdd0f4264813 100644 --- a/js/js2/icodegenerator.h +++ b/js/js2/icodegenerator.h @@ -33,6 +33,7 @@ namespace JavaScript { enum ICodeOp { // Operand1 Operand2 Operand3 + NOP, MOVE_TO, // Source Register Destination Register @@ -52,7 +53,14 @@ namespace JavaScript { MULTIPLY, DIVIDE, - COMPARE, // Source Register 1 Source Register 2 Destination Register + // maintain contiguity + COMPARE_LT, // Source Register 1 Source Register 2 Destination Register + COMPARE_LE, + COMPARE_EQ, + COMPARE_NE, + COMPARE_GE, + COMPARE_GT, + NOT, // Source Register Destination Register BRANCH, // Target label @@ -72,7 +80,8 @@ namespace JavaScript { Instruction(ICodeOp op) : itsOp(op) { } ICodeOp itsOp; - ICodeOp opcode() { return itsOp; } + ICodeOp getBranchOp() { return ((itsOp >= COMPARE_LT) && (itsOp <= COMPARE_GT)) ? (ICodeOp)(BRANCH_LT + (itsOp - COMPARE_LT)) : NOP; } + ICodeOp opcode() { return itsOp; } }; template @@ -119,6 +128,7 @@ namespace JavaScript { typedef Instruction_1 Branch; typedef Instruction_2 BranchCond; typedef Instruction_3 Arithmetic; + typedef Instruction_3 Compare; typedef Instruction_2 Move; typedef Instruction_1 Return; @@ -167,9 +177,8 @@ namespace JavaScript { class ICodeGenerator { private: - InstructionStream *iCode; - + LabelList labels; std::vector stitcher; @@ -178,6 +187,8 @@ namespace JavaScript { Register getRegister() { return topRegister++; } void resetTopRegister() { topRegister = stitcher.empty() ? 0 : stitcher.back()->registerBase; } + ICodeOp getBranchOp() { ASSERT(!iCode->empty()); return iCode->back()->getBranchOp(); } + public: int32 getLabel(); private: @@ -185,7 +196,7 @@ namespace JavaScript { void setLabel(InstructionStream *stream, int32 label); void branch(int32 label); - void branchConditional(int32 label, Register condition, ICodeOp branchOp = BRANCH_NE); + void branchConditional(int32 label, Register condition); public: ICodeGenerator() : topRegister(0) { iCode = new InstructionStream(); } @@ -193,13 +204,14 @@ namespace JavaScript { void mergeStream(InstructionStream *sideStream); InstructionStream *complete(); - InstructionStream *complete(Register result); ostream &print(ostream &s); Register op(ICodeOp op, Register source); Register op(ICodeOp op, Register source1, Register source2); + Register compare(ICodeOp op, Register source1, Register source2); + Register loadVariable(uint32 frameIndex); Register loadImmediate(double value); @@ -222,9 +234,10 @@ namespace JavaScript { // expression statements void beginStatement(uint32 /*pos*/) { resetTopRegister(); } - + void returnStatement(Register result); + void beginWhileStatement(uint32 pos); - void endWhileExpression(Register condition, ICodeOp branchOp = BRANCH_NE); + void endWhileExpression(Register condition); void endWhileStatement(); @@ -270,10 +283,6 @@ namespace JavaScript { void throwStatement(Register expression); - - void returnStatement(Register expression); // optional - - void beginCatchStatement(); void endCatchExpression(Register expression); void endCatchStatement(); diff --git a/js/js2/interpreter.cpp b/js/js2/interpreter.cpp index ca485d2ad5aa..94bc325ea477 100644 --- a/js/js2/interpreter.cpp +++ b/js/js2/interpreter.cpp @@ -45,7 +45,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args) registers[op2(i)] = registers[op1(i)]; } break; - case LOAD_NAME: + case LOAD_NAME: { LoadName* i = static_cast(instruction); registers[op2(i)] = globals[*op1(i)]; @@ -164,7 +164,12 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args) registers[op3(i)] = JSValue(registers[op1(i)].f64 / registers[op2(i)].f64); } break; - case COMPARE: + case COMPARE_LT: + case COMPARE_LE: + case COMPARE_EQ: + case COMPARE_NE: + case COMPARE_GT: + case COMPARE_GE: { Arithmetic* i = static_cast(instruction); float64 diff = (registers[op1(i)].f64 - registers[op2(i)].f64); diff --git a/js/js2/js2.cpp b/js/js2/js2.cpp index d6cda4022cc7..afa2f48a1fd0 100644 --- a/js/js2/js2.cpp +++ b/js/js2/js2.cpp @@ -438,8 +438,8 @@ static void testInterpreter(float64 n) icg.beginWhileStatement(position); Register r0 = icg.loadVariable(0); Register r1 = icg.loadImmediate(1.0); - Register r2 = icg.op(COMPARE, r0, r1); - icg.endWhileExpression(r2, BRANCH_GT); + Register r2 = icg.op(COMPARE_GT, r0, r1); + icg.endWhileExpression(r2); r0 = icg.loadVariable(0); r1 = icg.loadVariable(1); r2 = icg.op(MULTIPLY, r1, r0); @@ -453,8 +453,8 @@ static void testInterpreter(float64 n) } // return result; - icg.beginStatement(position); - InstructionStream *iCode = icg.complete(icg.loadVariable(1)); + icg.returnStatement(icg.loadVariable(1)); + InstructionStream *iCode = icg.complete(); // std::cout << icg; // test the iCode interpreter. diff --git a/js2/src/icodegenerator.cpp b/js2/src/icodegenerator.cpp index ef4a6be46204..fdee26eda193 100644 --- a/js2/src/icodegenerator.cpp +++ b/js2/src/icodegenerator.cpp @@ -58,14 +58,6 @@ namespace JavaScript { return iCode; } - InstructionStream *ICodeGenerator::complete(Register result) - { - Return *instr = new Return(RETURN, result); - iCode->push_back(instr); - return complete(); - } - - /***********************************************************************************************/ Register ICodeGenerator::loadVariable(uint32 frameIndex) @@ -128,8 +120,13 @@ namespace JavaScript { iCode->push_back(instr); } - void ICodeGenerator::branchConditional(int32 label, Register condition, ICodeOp branchOp) + void ICodeGenerator::branchConditional(int32 label, Register condition) { + ICodeOp branchOp = getBranchOp(); + if (branchOp == NOP) { + // XXXX emit convert to boolean / Test / ... + branchOp = BRANCH_NE; + } BranchCond *instr = new BranchCond(branchOp, label, condition); iCode->push_back(instr); } @@ -188,8 +185,9 @@ namespace JavaScript { } } - for (InstructionIterator ii = sideStream->begin(); ii != sideStream->end(); ii++) + for (InstructionIterator ii = sideStream->begin(); ii != sideStream->end(); ii++) { iCode->push_back(*ii); + } } @@ -211,12 +209,12 @@ namespace JavaScript { iCode = new InstructionStream(); } - void ICodeGenerator::endWhileExpression(Register condition, ICodeOp branchOp) + void ICodeGenerator::endWhileExpression(Register condition) { WhileCodeState *ics = static_cast(stitcher.back()); ASSERT(ics->stateKind == While_state); - branchConditional(ics->whileBody, condition, branchOp); + branchConditional(ics->whileBody, condition); resetTopRegister(); // stash away the condition expression and switch // back to the main stream @@ -376,7 +374,7 @@ namespace JavaScript { ASSERT(ics->stateKind == Switch_state); int32 caseLabel = getLabel(); - Register r = op(COMPARE, expression, ics->controlExpression); + Register r = op(COMPARE_EQ, expression, ics->controlExpression); branchConditional(caseLabel, r); setLabel(ics->caseStatementsStream, caseLabel); // mark the case in the Case Statement stream @@ -524,10 +522,17 @@ namespace JavaScript { NOT_REACHED("no continue target available"); } + void ICodeGenerator::returnStatement(Register result) + { + Return *instr = new Return(RETURN, result); + iCode->push_back(instr); + } + /***********************************************************************************************/ char *opcodeName[] = { + "nop", "move_to", "load_var", "save_var", @@ -541,6 +546,11 @@ namespace JavaScript { "multiply", "divide", "compare", + "compare", + "compare", + "compare", + "compare", + "compare", "not", "branch", "branch_lt", @@ -563,13 +573,16 @@ namespace JavaScript { { s << "ICG! " << iCode->size() << "\n"; for (InstructionIterator i = iCode->begin(); i != iCode->end(); i++) { + for (LabelList::iterator k = labels.begin(); k != labels.end(); k++) if ((*k)->itsOffset == (i - iCode->begin())) { - s << "label #" << (k - labels.begin()) << ":\n"; + //s << "label #" << (k - labels.begin()) << ":\n"; + s << "#" << (i - iCode->begin()); + break; } Instruction *instr = *i; - s << "\t"<< std::setiosflags( std::ostream::left ) << std::setw(16) << opcodeName[instr->itsOp]; + s << "\t" << std::setiosflags( std::ostream::left ) << std::setw(16) << opcodeName[instr->itsOp]; switch (instr->itsOp) { case LOAD_NAME : { @@ -593,7 +606,7 @@ namespace JavaScript { case BRANCH : { Branch *t = static_cast(instr); - s << "target #" << t->itsOperand1; + s << "instr #" << t->itsOperand1; } break; case BRANCH_LT : @@ -604,14 +617,19 @@ namespace JavaScript { case BRANCH_GT : { BranchCond *t = static_cast(instr); - s << "target #" << t->itsOperand1 << ", R" << t->itsOperand2; + s << "instr #" << t->itsOperand1 << ", R" << t->itsOperand2; } break; case ADD : case SUBTRACT : case MULTIPLY : case DIVIDE : - case COMPARE : + case COMPARE_LT : + case COMPARE_LE : + case COMPARE_EQ : + case COMPARE_NE : + case COMPARE_GT : + case COMPARE_GE : { Arithmetic *t = static_cast(instr); s << "R" << t->itsOperand1 << ", R" << t->itsOperand2 << ", R" << t->itsOperand3; @@ -635,7 +653,8 @@ namespace JavaScript { } for (LabelList::iterator k = labels.begin(); k != labels.end(); k++) if ((*k)->itsOffset == (iCode->end() - iCode->begin())) { - s << "label #" << (k - labels.begin()) << ":\n"; +// s << "label #" << (k - labels.begin()) << ":\n"; + s << "#" << (i - iCode->begin()); } return s; } diff --git a/js2/src/icodegenerator.h b/js2/src/icodegenerator.h index 1977bca2f93b..bdd0f4264813 100644 --- a/js2/src/icodegenerator.h +++ b/js2/src/icodegenerator.h @@ -33,6 +33,7 @@ namespace JavaScript { enum ICodeOp { // Operand1 Operand2 Operand3 + NOP, MOVE_TO, // Source Register Destination Register @@ -52,7 +53,14 @@ namespace JavaScript { MULTIPLY, DIVIDE, - COMPARE, // Source Register 1 Source Register 2 Destination Register + // maintain contiguity + COMPARE_LT, // Source Register 1 Source Register 2 Destination Register + COMPARE_LE, + COMPARE_EQ, + COMPARE_NE, + COMPARE_GE, + COMPARE_GT, + NOT, // Source Register Destination Register BRANCH, // Target label @@ -72,7 +80,8 @@ namespace JavaScript { Instruction(ICodeOp op) : itsOp(op) { } ICodeOp itsOp; - ICodeOp opcode() { return itsOp; } + ICodeOp getBranchOp() { return ((itsOp >= COMPARE_LT) && (itsOp <= COMPARE_GT)) ? (ICodeOp)(BRANCH_LT + (itsOp - COMPARE_LT)) : NOP; } + ICodeOp opcode() { return itsOp; } }; template @@ -119,6 +128,7 @@ namespace JavaScript { typedef Instruction_1 Branch; typedef Instruction_2 BranchCond; typedef Instruction_3 Arithmetic; + typedef Instruction_3 Compare; typedef Instruction_2 Move; typedef Instruction_1 Return; @@ -167,9 +177,8 @@ namespace JavaScript { class ICodeGenerator { private: - InstructionStream *iCode; - + LabelList labels; std::vector stitcher; @@ -178,6 +187,8 @@ namespace JavaScript { Register getRegister() { return topRegister++; } void resetTopRegister() { topRegister = stitcher.empty() ? 0 : stitcher.back()->registerBase; } + ICodeOp getBranchOp() { ASSERT(!iCode->empty()); return iCode->back()->getBranchOp(); } + public: int32 getLabel(); private: @@ -185,7 +196,7 @@ namespace JavaScript { void setLabel(InstructionStream *stream, int32 label); void branch(int32 label); - void branchConditional(int32 label, Register condition, ICodeOp branchOp = BRANCH_NE); + void branchConditional(int32 label, Register condition); public: ICodeGenerator() : topRegister(0) { iCode = new InstructionStream(); } @@ -193,13 +204,14 @@ namespace JavaScript { void mergeStream(InstructionStream *sideStream); InstructionStream *complete(); - InstructionStream *complete(Register result); ostream &print(ostream &s); Register op(ICodeOp op, Register source); Register op(ICodeOp op, Register source1, Register source2); + Register compare(ICodeOp op, Register source1, Register source2); + Register loadVariable(uint32 frameIndex); Register loadImmediate(double value); @@ -222,9 +234,10 @@ namespace JavaScript { // expression statements void beginStatement(uint32 /*pos*/) { resetTopRegister(); } - + void returnStatement(Register result); + void beginWhileStatement(uint32 pos); - void endWhileExpression(Register condition, ICodeOp branchOp = BRANCH_NE); + void endWhileExpression(Register condition); void endWhileStatement(); @@ -270,10 +283,6 @@ namespace JavaScript { void throwStatement(Register expression); - - void returnStatement(Register expression); // optional - - void beginCatchStatement(); void endCatchExpression(Register expression); void endCatchStatement(); diff --git a/js2/src/interpreter.cpp b/js2/src/interpreter.cpp index ca485d2ad5aa..94bc325ea477 100644 --- a/js2/src/interpreter.cpp +++ b/js2/src/interpreter.cpp @@ -45,7 +45,7 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args) registers[op2(i)] = registers[op1(i)]; } break; - case LOAD_NAME: + case LOAD_NAME: { LoadName* i = static_cast(instruction); registers[op2(i)] = globals[*op1(i)]; @@ -164,7 +164,12 @@ JSValue interpret(InstructionStream& iCode, const JSValues& args) registers[op3(i)] = JSValue(registers[op1(i)].f64 / registers[op2(i)].f64); } break; - case COMPARE: + case COMPARE_LT: + case COMPARE_LE: + case COMPARE_EQ: + case COMPARE_NE: + case COMPARE_GT: + case COMPARE_GE: { Arithmetic* i = static_cast(instruction); float64 diff = (registers[op1(i)].f64 - registers[op2(i)].f64); diff --git a/js2/tests/cpp/js2_shell.cpp b/js2/tests/cpp/js2_shell.cpp index d6cda4022cc7..afa2f48a1fd0 100644 --- a/js2/tests/cpp/js2_shell.cpp +++ b/js2/tests/cpp/js2_shell.cpp @@ -438,8 +438,8 @@ static void testInterpreter(float64 n) icg.beginWhileStatement(position); Register r0 = icg.loadVariable(0); Register r1 = icg.loadImmediate(1.0); - Register r2 = icg.op(COMPARE, r0, r1); - icg.endWhileExpression(r2, BRANCH_GT); + Register r2 = icg.op(COMPARE_GT, r0, r1); + icg.endWhileExpression(r2); r0 = icg.loadVariable(0); r1 = icg.loadVariable(1); r2 = icg.op(MULTIPLY, r1, r0); @@ -453,8 +453,8 @@ static void testInterpreter(float64 n) } // return result; - icg.beginStatement(position); - InstructionStream *iCode = icg.complete(icg.loadVariable(1)); + icg.returnStatement(icg.loadVariable(1)); + InstructionStream *iCode = icg.complete(); // std::cout << icg; // test the iCode interpreter.