mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
Added labelled statements, fixed some VC++'isms
This commit is contained in:
parent
0aa794713c
commit
8c81be5a55
@ -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<SwitchCodeState *>(stitcher.back());
|
||||
@ -468,7 +489,7 @@ namespace ICG {
|
||||
resetTopRegister();
|
||||
}
|
||||
|
||||
void ICodeGenerator::beginDefaultStatement()
|
||||
void ICodeGenerator::beginDefaultStatement(uint32 pos)
|
||||
{
|
||||
SwitchCodeState *ics =
|
||||
static_cast<SwitchCodeState *>(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<ICodeState *>::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<ICodeState *>::reverse_iterator p =
|
||||
stitcher.rbegin(); p != stitcher.rend(); p++) {
|
||||
|
||||
for (std::vector<const StringAtom *>::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<ICodeState *>::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<ICodeState *>::reverse_iterator p =
|
||||
stitcher.rbegin(); p != stitcher.rend(); p++) {
|
||||
|
||||
for (std::vector<const StringAtom *>::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();
|
||||
|
@ -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<ICodeState *> stitcher;
|
||||
std::vector<const StringAtom *> 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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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<SwitchCodeState *>(stitcher.back());
|
||||
@ -468,7 +489,7 @@ namespace ICG {
|
||||
resetTopRegister();
|
||||
}
|
||||
|
||||
void ICodeGenerator::beginDefaultStatement()
|
||||
void ICodeGenerator::beginDefaultStatement(uint32 pos)
|
||||
{
|
||||
SwitchCodeState *ics =
|
||||
static_cast<SwitchCodeState *>(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<ICodeState *>::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<ICodeState *>::reverse_iterator p =
|
||||
stitcher.rbegin(); p != stitcher.rend(); p++) {
|
||||
|
||||
for (std::vector<const StringAtom *>::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<ICodeState *>::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<ICodeState *>::reverse_iterator p =
|
||||
stitcher.rbegin(); p != stitcher.rend(); p++) {
|
||||
|
||||
for (std::vector<const StringAtom *>::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();
|
||||
|
@ -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<ICodeState *> stitcher;
|
||||
std::vector<const StringAtom *> 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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user