Changes to CodeState thing, still not happy with this - RTTI would be

better?
This commit is contained in:
rogerl%netscape.com 2000-03-31 01:54:28 +00:00
parent fe663d8006
commit 820c2dd375
4 changed files with 134 additions and 64 deletions

View File

@ -37,6 +37,21 @@ ostream &JS::operator<<(ostream &s, ICodeGenerator &i)
// ICodeGenerator
//
InstructionStream *ICodeGenerator::complete()
{
#ifdef DEBUG
ASSERT(stitcher.empty());
for (LabelIterator i = labels.begin(); i != labels.end(); i++) {
ASSERT((*i)->itsBase == iCode);
ASSERT((*i)->itsOffset >= 0);
ASSERT((*i)->itsOffset < iCode->size());
}
#endif
return iCode;
}
/***********************************************************************************************/
Register ICodeGenerator::loadVariable(int32 frameIndex)
{
@ -129,6 +144,26 @@ void ICodeGenerator::setLabel(int32 label)
l->itsOffset = iCode->size();
}
/***********************************************************************************************/
void MultiPathICodeState::mergeStream(InstructionStream *mainStream, LabelList &labels)
{
if (itsTopLabel < labels.size()) {
// labels (might) have been allocated in this stream
// we need to adjust their position relative to the
// size of the stream we're joining
for (LabelList::iterator i = labels.begin() + itsTopLabel; i != labels.end(); i++) {
if ((*i)->itsBase == its_iCode) {
(*i)->itsBase = mainStream;
(*i)->itsOffset += mainStream->size();
}
}
}
for (InstructionIterator i = its_iCode->begin(); i != its_iCode->end(); i++)
mainStream->push_back(*i);
}
/***********************************************************************************************/
@ -150,13 +185,14 @@ void ICodeGenerator::beginWhileStatement(const SourcePosition &pos)
void ICodeGenerator::endWhileExpression(Register condition)
{
WhileCodeState *ics = (WhileCodeState *)(stitcher.top());
WhileCodeState *ics = static_cast<WhileCodeState *>(stitcher.top());
ASSERT(ics->stateKind == While_State);
branchConditional(ics->whileBodyLabel, condition);
resetTopRegister();
// stash away the condition expression and switch
// back to the main stream
iCode = stitcher.top()->swap_iCode(iCode);
iCode = ics->swapStream(iCode);
setLabel(ics->whileBodyLabel); // mark the start of the while block
}
@ -164,29 +200,14 @@ void ICodeGenerator::endWhileStatement()
{
// recover the while stream
WhileCodeState *ics = static_cast<WhileCodeState *>(stitcher.top());
ASSERT(ics->stateKind == While_State);
stitcher.pop();
// mark the start of the condition code
// and re-attach it to the main stream
setLabel(ics->whileConditionLabel);
if (ics->itsTopLabel < labels.size()) {
// labels (might) have been allocated in this stream
// we need to adjust their position relative to the
// size of the stream we're joining
// XXXX how do I start at 'ics->itsTopLabel' ???
//
for (LabelList::iterator i = labels.begin(); i != labels.end(); i++) {
if ((*i)->itsBase == ics->its_iCode) {
(*i)->itsBase = iCode;
(*i)->itsOffset += iCode->size();
}
}
}
for (InstructionIterator i = ics->its_iCode->begin(); i != ics->its_iCode->end(); i++)
iCode->push_back(*i);
ics->mergeStream(iCode, labels);
delete ics->its_iCode;
delete ics;
@ -201,8 +222,7 @@ void ICodeGenerator::beginIfStatement(const SourcePosition &pos, Register condit
{
int32 elseLabel = getLabel();
// save off the current stream while we gen code for the condition
stitcher.push(new IfCodeState(iCode, labels.size(), elseLabel, -1));
stitcher.push(new IfCodeState(elseLabel, -1));
Register notCond = op(NOT, condition);
branchConditional(elseLabel, notCond);
@ -212,7 +232,8 @@ void ICodeGenerator::beginIfStatement(const SourcePosition &pos, Register condit
void ICodeGenerator::beginElseStatement(bool hasElse)
{
IfCodeState *ics = (IfCodeState *)(stitcher.top());
IfCodeState *ics = static_cast<IfCodeState *>(stitcher.top());
ASSERT(ics->stateKind == If_State);
if (hasElse) {
int32 beyondElse = getLabel();
@ -225,7 +246,8 @@ void ICodeGenerator::beginElseStatement(bool hasElse)
void ICodeGenerator::endIfStatement()
{
IfCodeState *ics = (IfCodeState *)(stitcher.top());
IfCodeState *ics = static_cast<IfCodeState *>(stitcher.top());
ASSERT(ics->stateKind == If_State);
if (ics->beyondElse != -1) { // had an else
setLabel(ics->beyondElse); // the beyond else label

View File

@ -99,36 +99,47 @@ namespace JavaScript {
};
typedef std::vector<Label *> LabelList;
typedef LabelList::iterator LabelIterator;
/****************************************************************/
/****************************************************************/
enum StateKind { While_State, If_state };
class ICodeState {
public:
ICodeState(InstructionStream *iCode, int32 topLabel) : its_iCode(iCode), itsTopLabel(topLabel) {}
virtual ~ICodeState() { }
public :
ICodeState(StateKind kind) : stateKind(kind) { }
StateKind stateKind;
};
InstructionStream *swap_iCode(InstructionStream *iCode) { InstructionStream *t = its_iCode; its_iCode = iCode; return t; }
// an ICodeState that handles switching to a new InstructionStream
// and then re-combining the streams later
class MultiPathICodeState : public ICodeState {
public:
MultiPathICodeState(StateKind kind,InstructionStream *iCode, int32 topLabel)
: ICodeState(kind), its_iCode(iCode), itsTopLabel(topLabel) {}
InstructionStream *swapStream(InstructionStream *iCode) { InstructionStream *t = its_iCode; its_iCode = iCode; return t; }
InstructionStream *its_iCode;
int32 itsTopLabel; // set to the highest label allocated when this stream
// was created. If that value changes, this stream may
// contain labels that will need to be adjusted when
// the streams are merged.
void mergeStream(InstructionStream *mainStream, LabelList &labels);
};
class WhileCodeState : public ICodeState {
class WhileCodeState : public MultiPathICodeState {
public:
WhileCodeState(InstructionStream *iCode, int32 topLabel, int32 a, int32 b)
: ICodeState(iCode, topLabel), whileConditionLabel(a), whileBodyLabel(b) { }
: MultiPathICodeState(While_State, iCode, topLabel), whileConditionLabel(a), whileBodyLabel(b) { }
int32 whileConditionLabel;
int32 whileBodyLabel;
};
class IfCodeState : public ICodeState {
public:
IfCodeState(InstructionStream *iCode, int32 topLabel, int32 a, int32 b)
: ICodeState(iCode, topLabel), elseLabel(a), beyondElse(b) { }
IfCodeState(int32 a, int32 b) : ICodeState(If_state), elseLabel(a), beyondElse(b) { }
int32 elseLabel;
int32 beyondElse;
};
@ -161,6 +172,8 @@ namespace JavaScript {
public:
ICodeGenerator() { iCode = new InstructionStream(); }
InstructionStream *complete();
ostream &print(ostream &s);
Register op(ICodeOp op, Register source);

View File

@ -37,6 +37,21 @@ ostream &JS::operator<<(ostream &s, ICodeGenerator &i)
// ICodeGenerator
//
InstructionStream *ICodeGenerator::complete()
{
#ifdef DEBUG
ASSERT(stitcher.empty());
for (LabelIterator i = labels.begin(); i != labels.end(); i++) {
ASSERT((*i)->itsBase == iCode);
ASSERT((*i)->itsOffset >= 0);
ASSERT((*i)->itsOffset < iCode->size());
}
#endif
return iCode;
}
/***********************************************************************************************/
Register ICodeGenerator::loadVariable(int32 frameIndex)
{
@ -129,6 +144,26 @@ void ICodeGenerator::setLabel(int32 label)
l->itsOffset = iCode->size();
}
/***********************************************************************************************/
void MultiPathICodeState::mergeStream(InstructionStream *mainStream, LabelList &labels)
{
if (itsTopLabel < labels.size()) {
// labels (might) have been allocated in this stream
// we need to adjust their position relative to the
// size of the stream we're joining
for (LabelList::iterator i = labels.begin() + itsTopLabel; i != labels.end(); i++) {
if ((*i)->itsBase == its_iCode) {
(*i)->itsBase = mainStream;
(*i)->itsOffset += mainStream->size();
}
}
}
for (InstructionIterator i = its_iCode->begin(); i != its_iCode->end(); i++)
mainStream->push_back(*i);
}
/***********************************************************************************************/
@ -150,13 +185,14 @@ void ICodeGenerator::beginWhileStatement(const SourcePosition &pos)
void ICodeGenerator::endWhileExpression(Register condition)
{
WhileCodeState *ics = (WhileCodeState *)(stitcher.top());
WhileCodeState *ics = static_cast<WhileCodeState *>(stitcher.top());
ASSERT(ics->stateKind == While_State);
branchConditional(ics->whileBodyLabel, condition);
resetTopRegister();
// stash away the condition expression and switch
// back to the main stream
iCode = stitcher.top()->swap_iCode(iCode);
iCode = ics->swapStream(iCode);
setLabel(ics->whileBodyLabel); // mark the start of the while block
}
@ -164,29 +200,14 @@ void ICodeGenerator::endWhileStatement()
{
// recover the while stream
WhileCodeState *ics = static_cast<WhileCodeState *>(stitcher.top());
ASSERT(ics->stateKind == While_State);
stitcher.pop();
// mark the start of the condition code
// and re-attach it to the main stream
setLabel(ics->whileConditionLabel);
if (ics->itsTopLabel < labels.size()) {
// labels (might) have been allocated in this stream
// we need to adjust their position relative to the
// size of the stream we're joining
// XXXX how do I start at 'ics->itsTopLabel' ???
//
for (LabelList::iterator i = labels.begin(); i != labels.end(); i++) {
if ((*i)->itsBase == ics->its_iCode) {
(*i)->itsBase = iCode;
(*i)->itsOffset += iCode->size();
}
}
}
for (InstructionIterator i = ics->its_iCode->begin(); i != ics->its_iCode->end(); i++)
iCode->push_back(*i);
ics->mergeStream(iCode, labels);
delete ics->its_iCode;
delete ics;
@ -201,8 +222,7 @@ void ICodeGenerator::beginIfStatement(const SourcePosition &pos, Register condit
{
int32 elseLabel = getLabel();
// save off the current stream while we gen code for the condition
stitcher.push(new IfCodeState(iCode, labels.size(), elseLabel, -1));
stitcher.push(new IfCodeState(elseLabel, -1));
Register notCond = op(NOT, condition);
branchConditional(elseLabel, notCond);
@ -212,7 +232,8 @@ void ICodeGenerator::beginIfStatement(const SourcePosition &pos, Register condit
void ICodeGenerator::beginElseStatement(bool hasElse)
{
IfCodeState *ics = (IfCodeState *)(stitcher.top());
IfCodeState *ics = static_cast<IfCodeState *>(stitcher.top());
ASSERT(ics->stateKind == If_State);
if (hasElse) {
int32 beyondElse = getLabel();
@ -225,7 +246,8 @@ void ICodeGenerator::beginElseStatement(bool hasElse)
void ICodeGenerator::endIfStatement()
{
IfCodeState *ics = (IfCodeState *)(stitcher.top());
IfCodeState *ics = static_cast<IfCodeState *>(stitcher.top());
ASSERT(ics->stateKind == If_State);
if (ics->beyondElse != -1) { // had an else
setLabel(ics->beyondElse); // the beyond else label

View File

@ -99,36 +99,47 @@ namespace JavaScript {
};
typedef std::vector<Label *> LabelList;
typedef LabelList::iterator LabelIterator;
/****************************************************************/
/****************************************************************/
enum StateKind { While_State, If_state };
class ICodeState {
public:
ICodeState(InstructionStream *iCode, int32 topLabel) : its_iCode(iCode), itsTopLabel(topLabel) {}
virtual ~ICodeState() { }
public :
ICodeState(StateKind kind) : stateKind(kind) { }
StateKind stateKind;
};
InstructionStream *swap_iCode(InstructionStream *iCode) { InstructionStream *t = its_iCode; its_iCode = iCode; return t; }
// an ICodeState that handles switching to a new InstructionStream
// and then re-combining the streams later
class MultiPathICodeState : public ICodeState {
public:
MultiPathICodeState(StateKind kind,InstructionStream *iCode, int32 topLabel)
: ICodeState(kind), its_iCode(iCode), itsTopLabel(topLabel) {}
InstructionStream *swapStream(InstructionStream *iCode) { InstructionStream *t = its_iCode; its_iCode = iCode; return t; }
InstructionStream *its_iCode;
int32 itsTopLabel; // set to the highest label allocated when this stream
// was created. If that value changes, this stream may
// contain labels that will need to be adjusted when
// the streams are merged.
void mergeStream(InstructionStream *mainStream, LabelList &labels);
};
class WhileCodeState : public ICodeState {
class WhileCodeState : public MultiPathICodeState {
public:
WhileCodeState(InstructionStream *iCode, int32 topLabel, int32 a, int32 b)
: ICodeState(iCode, topLabel), whileConditionLabel(a), whileBodyLabel(b) { }
: MultiPathICodeState(While_State, iCode, topLabel), whileConditionLabel(a), whileBodyLabel(b) { }
int32 whileConditionLabel;
int32 whileBodyLabel;
};
class IfCodeState : public ICodeState {
public:
IfCodeState(InstructionStream *iCode, int32 topLabel, int32 a, int32 b)
: ICodeState(iCode, topLabel), elseLabel(a), beyondElse(b) { }
IfCodeState(int32 a, int32 b) : ICodeState(If_state), elseLabel(a), beyondElse(b) { }
int32 elseLabel;
int32 beyondElse;
};
@ -161,6 +172,8 @@ namespace JavaScript {
public:
ICodeGenerator() { iCode = new InstructionStream(); }
InstructionStream *complete();
ostream &print(ostream &s);
Register op(ICodeOp op, Register source);