Changed compare/branch handling to determine last compare opcode.

Made returnStatement a member in ICG.
This commit is contained in:
rogerl%netscape.com 2000-04-06 22:40:17 +00:00
Родитель 6c7e2e4df4
Коммит 7741726bd9
8 изменённых файлов: 140 добавлений и 74 удалений

Просмотреть файл

@ -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<WhileCodeState *>(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<Branch * >(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<BranchCond * >(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<Arithmetic * >(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;
}

Просмотреть файл

@ -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 <typename Operand1>
@ -119,6 +128,7 @@ namespace JavaScript {
typedef Instruction_1<int32> Branch;
typedef Instruction_2<int32, Register> BranchCond;
typedef Instruction_3<Register, Register, Register> Arithmetic;
typedef Instruction_3<Register, Register, Register> Compare;
typedef Instruction_2<Register, Register> Move;
typedef Instruction_1<Register> Return;
@ -167,9 +177,8 @@ namespace JavaScript {
class ICodeGenerator {
private:
InstructionStream *iCode;
LabelList labels;
std::vector<ICodeState *> 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 <operand>
void beginCatchStatement();
void endCatchExpression(Register expression);
void endCatchStatement();

Просмотреть файл

@ -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<LoadName*>(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<Arithmetic*>(instruction);
float64 diff = (registers[op1(i)].f64 - registers[op2(i)].f64);

Просмотреть файл

@ -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.

Просмотреть файл

@ -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<WhileCodeState *>(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<Branch * >(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<BranchCond * >(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<Arithmetic * >(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;
}

Просмотреть файл

@ -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 <typename Operand1>
@ -119,6 +128,7 @@ namespace JavaScript {
typedef Instruction_1<int32> Branch;
typedef Instruction_2<int32, Register> BranchCond;
typedef Instruction_3<Register, Register, Register> Arithmetic;
typedef Instruction_3<Register, Register, Register> Compare;
typedef Instruction_2<Register, Register> Move;
typedef Instruction_1<Register> Return;
@ -167,9 +177,8 @@ namespace JavaScript {
class ICodeGenerator {
private:
InstructionStream *iCode;
LabelList labels;
std::vector<ICodeState *> 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 <operand>
void beginCatchStatement();
void endCatchExpression(Register expression);
void endCatchStatement();

Просмотреть файл

@ -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<LoadName*>(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<Arithmetic*>(instruction);
float64 diff = (registers[op1(i)].f64 - registers[op2(i)].f64);

Просмотреть файл

@ -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.