зеркало из https://github.com/mozilla/pjs.git
Began moving away from variables, fixed compare/branch ordering.
Testcases working.
This commit is contained in:
Родитель
d982d960b5
Коммит
7b7fc3829f
|
@ -91,22 +91,6 @@ namespace ICG {
|
||||||
|
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
|
|
||||||
Register ICodeGenerator::loadVariable(uint32 frameIndex)
|
|
||||||
{
|
|
||||||
markMaxVariable(frameIndex);
|
|
||||||
Register dest = getRegister();
|
|
||||||
LoadVar *instr = new LoadVar(dest, frameIndex);
|
|
||||||
iCode->push_back(instr);
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ICodeGenerator::saveVariable(uint32 frameIndex, Register value)
|
|
||||||
{
|
|
||||||
markMaxVariable(frameIndex);
|
|
||||||
SaveVar *instr = new SaveVar(frameIndex, value);
|
|
||||||
iCode->push_back(instr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Register ICodeGenerator::loadImmediate(double value)
|
Register ICodeGenerator::loadImmediate(double value)
|
||||||
{
|
{
|
||||||
Register dest = getRegister();
|
Register dest = getRegister();
|
||||||
|
@ -183,6 +167,12 @@ namespace ICG {
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ICodeGenerator::move(Register destination, Register source)
|
||||||
|
{
|
||||||
|
Move *instr = new Move(destination, source);
|
||||||
|
iCode->push_back(instr);
|
||||||
|
}
|
||||||
|
|
||||||
Register ICodeGenerator::op(ICodeOp op, Register source1,
|
Register ICodeGenerator::op(ICodeOp op, Register source1,
|
||||||
Register source2)
|
Register source2)
|
||||||
{
|
{
|
||||||
|
@ -638,4 +628,4 @@ namespace ICG {
|
||||||
|
|
||||||
} // namespace ICG
|
} // namespace ICG
|
||||||
|
|
||||||
} // namespace JavaScript
|
}; // namespace JavaScript
|
||||||
|
|
|
@ -107,10 +107,11 @@ namespace ICG {
|
||||||
{ if (variableIndex > maxVariable) maxVariable = variableIndex; }
|
{ if (variableIndex > maxVariable) maxVariable = variableIndex; }
|
||||||
|
|
||||||
Register topRegister;
|
Register topRegister;
|
||||||
|
Register registerBase;
|
||||||
Register getRegister() \
|
Register getRegister() \
|
||||||
{ return topRegister++; }
|
{ return topRegister++; }
|
||||||
void resetTopRegister() \
|
void resetTopRegister() \
|
||||||
{ markMaxRegister(); topRegister = stitcher.empty() ? 0 : \
|
{ markMaxRegister(); topRegister = stitcher.empty() ? registerBase : \
|
||||||
stitcher.back()->registerBase; }
|
stitcher.back()->registerBase; }
|
||||||
|
|
||||||
ICodeOp getBranchOp() \
|
ICodeOp getBranchOp() \
|
||||||
|
@ -126,7 +127,7 @@ namespace ICG {
|
||||||
void branchConditional(Label *label, Register condition);
|
void branchConditional(Label *label, Register condition);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ICodeGenerator() : topRegister(0), maxRegister(0),
|
ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0),
|
||||||
maxVariable(0) \
|
maxVariable(0) \
|
||||||
{ iCode = new InstructionStream(); }
|
{ iCode = new InstructionStream(); }
|
||||||
|
|
||||||
|
@ -135,12 +136,17 @@ namespace ICG {
|
||||||
void mergeStream(InstructionStream *sideStream);
|
void mergeStream(InstructionStream *sideStream);
|
||||||
|
|
||||||
ICodeModule *complete();
|
ICodeModule *complete();
|
||||||
|
|
||||||
|
Register allocateVariable(StringAtom &name)
|
||||||
|
{ Register result = getRegister(); registerBase = topRegister; return result; }
|
||||||
|
|
||||||
Formatter& print(Formatter& f);
|
Formatter& print(Formatter& f);
|
||||||
|
|
||||||
Register op(ICodeOp op, Register source);
|
Register op(ICodeOp op, Register source);
|
||||||
Register op(ICodeOp op, Register source1, Register source2);
|
Register op(ICodeOp op, Register source1, Register source2);
|
||||||
Register call(Register target, RegisterList args);
|
Register call(Register target, RegisterList args);
|
||||||
|
|
||||||
|
void move(Register destination, Register source);
|
||||||
|
|
||||||
Register compare(ICodeOp op, Register source1, Register source2);
|
Register compare(ICodeOp op, Register source1, Register source2);
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ static void initConsole(StringPtr consoleName,
|
||||||
argc = 1;
|
argc = 1;
|
||||||
argv = mac_argv;
|
argv = mac_argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace JavaScript {
|
namespace JavaScript {
|
||||||
|
@ -287,43 +288,41 @@ namespace JavaScript {
|
||||||
uint32 pos = 0;
|
uint32 pos = 0;
|
||||||
ICodeGenerator icg;
|
ICodeGenerator icg;
|
||||||
|
|
||||||
// var i,j; i = j + 2;
|
// var i,j;
|
||||||
// i is bound to var #0, j to var #1
|
// i is bound to var #0, j to var #1
|
||||||
|
Register r_i = icg.allocateVariable(world.identifiers[widenCString("i")]);
|
||||||
|
Register r_j = icg.allocateVariable(world.identifiers[widenCString("j")]);
|
||||||
|
|
||||||
|
// i = j + 2;
|
||||||
icg.beginStatement(pos);
|
icg.beginStatement(pos);
|
||||||
Register r1 = icg.loadVariable(1);
|
Register r1 = icg.loadImmediate(2.0);
|
||||||
Register r2 = icg.loadImmediate(2.0);
|
icg.move(r_i, icg.op(ADD, r_i, r_j));
|
||||||
icg.saveVariable(0, icg.op(ADD, r1, r2));
|
|
||||||
|
|
||||||
// j = a.b
|
// j = a.b
|
||||||
icg.beginStatement(pos);
|
icg.beginStatement(pos);
|
||||||
Register r4 = icg.loadName(world.identifiers[widenCString("a")]);
|
r1 = icg.loadName(world.identifiers[widenCString("a")]);
|
||||||
Register r5 = icg.getProperty(r4, world.identifiers[widenCString("b")]);
|
r1 = icg.getProperty(r1, world.identifiers[widenCString("b")]);
|
||||||
icg.saveVariable(1, r5);
|
icg.move(r_j, r1);
|
||||||
|
|
||||||
// while (i) i = i + j;
|
// while (i) i = i + j;
|
||||||
icg.beginWhileStatement(pos);
|
icg.beginWhileStatement(pos);
|
||||||
r1 = icg.loadVariable(0);
|
icg.endWhileExpression(r_i);
|
||||||
icg.endWhileExpression(r1);
|
icg.move(r_i, icg.op(ADD, r_i, r_j));
|
||||||
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadVariable(1)));
|
|
||||||
icg.endWhileStatement();
|
icg.endWhileStatement();
|
||||||
|
|
||||||
// if (i) if (j) i = 3; else j = 4;
|
// if (i) if (j) i = 3; else j = 4;
|
||||||
r1 = icg.loadVariable(0);
|
icg.beginIfStatement(pos, r_i);
|
||||||
icg.beginIfStatement(pos, r1);
|
icg.beginIfStatement(pos, r_j);
|
||||||
r2 = icg.loadVariable(1);
|
icg.move(r_i, icg.loadImmediate(3));
|
||||||
icg.beginIfStatement(pos, r2);
|
|
||||||
icg.saveVariable(0, icg.loadImmediate(3));
|
|
||||||
icg.beginElseStatement(true);
|
icg.beginElseStatement(true);
|
||||||
icg.saveVariable(1, icg.loadImmediate(4));
|
icg.move(r_j, icg.loadImmediate(4));
|
||||||
icg.endIfStatement();
|
icg.endIfStatement();
|
||||||
icg.beginElseStatement(false);
|
icg.beginElseStatement(false);
|
||||||
icg.endIfStatement();
|
icg.endIfStatement();
|
||||||
|
|
||||||
|
|
||||||
// switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; }
|
// switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; }
|
||||||
r1 = icg.loadVariable(0);
|
icg.beginSwitchStatement(pos, r_i);
|
||||||
icg.beginSwitchStatement(pos, r1);
|
|
||||||
// case 3, note empty case statement (?necessary???)
|
// case 3, note empty case statement (?necessary???)
|
||||||
icg.endCaseCondition(icg.loadImmediate(3));
|
icg.endCaseCondition(icg.loadImmediate(3));
|
||||||
icg.beginCaseStatement();
|
icg.beginCaseStatement();
|
||||||
|
@ -332,30 +331,29 @@ namespace JavaScript {
|
||||||
icg.endCaseCondition(icg.loadImmediate(4));
|
icg.endCaseCondition(icg.loadImmediate(4));
|
||||||
icg.beginCaseStatement();
|
icg.beginCaseStatement();
|
||||||
icg.beginStatement(pos);
|
icg.beginStatement(pos);
|
||||||
icg.saveVariable(1, icg.loadImmediate(4));
|
icg.move(r_j, icg.loadImmediate(4));
|
||||||
icg.breakStatement();
|
icg.breakStatement();
|
||||||
icg.endCaseStatement();
|
icg.endCaseStatement();
|
||||||
// case 5
|
// case 5
|
||||||
icg.endCaseCondition(icg.loadImmediate(5));
|
icg.endCaseCondition(icg.loadImmediate(5));
|
||||||
icg.beginCaseStatement();
|
icg.beginCaseStatement();
|
||||||
icg.beginStatement(pos);
|
icg.beginStatement(pos);
|
||||||
icg.saveVariable(1, icg.loadImmediate(5));
|
icg.move(r_j, icg.loadImmediate(5));
|
||||||
icg.breakStatement();
|
icg.breakStatement();
|
||||||
icg.endCaseStatement();
|
icg.endCaseStatement();
|
||||||
// default
|
// default
|
||||||
icg.beginDefaultStatement();
|
icg.beginDefaultStatement();
|
||||||
icg.beginStatement(pos);
|
icg.beginStatement(pos);
|
||||||
icg.saveVariable(1, icg.loadImmediate(6));
|
icg.move(r_j, icg.loadImmediate(6));
|
||||||
icg.endDefaultStatement();
|
icg.endDefaultStatement();
|
||||||
icg.endSwitchStatement();
|
icg.endSwitchStatement();
|
||||||
|
|
||||||
// for ( ; i; i + 1 ) j = 99;
|
// for ( ; i; i = i + 1 ) j = 99;
|
||||||
icg.beginForStatement(pos);
|
icg.beginForStatement(pos);
|
||||||
r1 = icg.loadVariable(0);
|
icg.forCondition(r_i);
|
||||||
icg.forCondition(r1);
|
icg.move(r_i, icg.op(ADD, r_i, icg.loadImmediate(1)));
|
||||||
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadImmediate(1)));
|
|
||||||
icg.forIncrement();
|
icg.forIncrement();
|
||||||
icg.saveVariable(0, icg.loadImmediate(99));
|
icg.move(r_j, icg.loadImmediate(99));
|
||||||
icg.endForStatement();
|
icg.endForStatement();
|
||||||
|
|
||||||
ICodeModule *icm = icg.complete();
|
ICodeModule *icm = icg.complete();
|
||||||
|
@ -374,11 +372,12 @@ namespace JavaScript {
|
||||||
ICodeGenerator fun;
|
ICodeGenerator fun;
|
||||||
// function sum(n) { if (n > 1) return 1 + sum(n - 1); else return 1; }
|
// function sum(n) { if (n > 1) return 1 + sum(n - 1); else return 1; }
|
||||||
// n is bound to var #0.
|
// n is bound to var #0.
|
||||||
|
Register r_n = fun.allocateVariable(world.identifiers[widenCString("n")]);
|
||||||
fun.beginStatement(position);
|
fun.beginStatement(position);
|
||||||
Register r1 = fun.op(COMPARE_GT, fun.loadVariable(0), fun.loadImmediate(1.0));
|
Register r1 = fun.op(COMPARE_GT, r_n, fun.loadImmediate(1.0));
|
||||||
fun.beginIfStatement(position, r1);
|
fun.beginIfStatement(position, r1);
|
||||||
fun.beginStatement(position);
|
fun.beginStatement(position);
|
||||||
r1 = fun.op(SUBTRACT, fun.loadVariable(0), fun.loadImmediate(1.0));
|
r1 = fun.op(SUBTRACT, r_n, fun.loadImmediate(1.0));
|
||||||
RegisterList args(1);
|
RegisterList args(1);
|
||||||
args[0] = r1;
|
args[0] = r1;
|
||||||
r1 = fun.call(fun.loadName(sum), args);
|
r1 = fun.call(fun.loadName(sum), args);
|
||||||
|
@ -419,11 +418,12 @@ namespace JavaScript {
|
||||||
ICodeGenerator icg;
|
ICodeGenerator icg;
|
||||||
|
|
||||||
// fact(n) {
|
// fact(n) {
|
||||||
// n is bound to var #0.
|
|
||||||
// var result = 1;
|
// var result = 1;
|
||||||
// result is bound to var #1.
|
Register r_n = icg.allocateVariable(world.identifiers[widenCString("n")]);
|
||||||
|
Register r_result = icg.allocateVariable(world.identifiers[widenCString("result")]);
|
||||||
|
|
||||||
icg.beginStatement(position);
|
icg.beginStatement(position);
|
||||||
icg.saveVariable(1, icg.loadImmediate(1.0));
|
icg.move(r_result, icg.loadImmediate(1.0));
|
||||||
|
|
||||||
// while (n > 1) {
|
// while (n > 1) {
|
||||||
// result = result * n;
|
// result = result * n;
|
||||||
|
@ -431,24 +431,20 @@ namespace JavaScript {
|
||||||
// }
|
// }
|
||||||
{
|
{
|
||||||
icg.beginWhileStatement(position);
|
icg.beginWhileStatement(position);
|
||||||
Register r0 = icg.loadVariable(0);
|
|
||||||
Register r1 = icg.loadImmediate(1.0);
|
Register r1 = icg.loadImmediate(1.0);
|
||||||
Register r2 = icg.op(COMPARE_GT, r0, r1);
|
Register r2 = icg.op(COMPARE_GT, r_n, r1);
|
||||||
icg.endWhileExpression(r2);
|
icg.endWhileExpression(r2);
|
||||||
r0 = icg.loadVariable(0);
|
r2 = icg.op(MULTIPLY, r_result, r_n);
|
||||||
r1 = icg.loadVariable(1);
|
icg.move(r_result, r2);
|
||||||
r2 = icg.op(MULTIPLY, r1, r0);
|
|
||||||
icg.saveVariable(1, r2);
|
|
||||||
icg.beginStatement(position);
|
icg.beginStatement(position);
|
||||||
r0 = icg.loadVariable(0);
|
|
||||||
r1 = icg.loadImmediate(1.0);
|
r1 = icg.loadImmediate(1.0);
|
||||||
r2 = icg.op(SUBTRACT, r0, r1);
|
r2 = icg.op(SUBTRACT, r_n, r1);
|
||||||
icg.saveVariable(0, r2);
|
icg.move(r_n, r2);
|
||||||
icg.endWhileStatement();
|
icg.endWhileStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
// return result;
|
// return result;
|
||||||
icg.returnStatement(icg.loadVariable(1));
|
icg.returnStatement(r_result);
|
||||||
ICodeModule *icm = icg.complete();
|
ICodeModule *icm = icg.complete();
|
||||||
stdOut << icg;
|
stdOut << icg;
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ namespace JSTypes {
|
||||||
mLocals(iCode->itsMaxVariable + 1)
|
mLocals(iCode->itsMaxVariable + 1)
|
||||||
{
|
{
|
||||||
// copy caller's parameter list in to locals.
|
// copy caller's parameter list in to locals.
|
||||||
JSValues::iterator dest = mLocals.begin();
|
JSValues::iterator dest = mRegisters.begin();
|
||||||
const JSValues& params = caller->mRegisters;
|
const JSValues& params = caller->mRegisters;
|
||||||
for (RegisterList::const_iterator src = list.begin(),
|
for (RegisterList::const_iterator src = list.begin(),
|
||||||
end = list.end(); src != end; ++src, ++dest) {
|
end = list.end(); src != end; ++src, ++dest) {
|
||||||
|
@ -225,9 +225,8 @@ namespace JSTypes {
|
||||||
// a stack of JSFrames.
|
// a stack of JSFrames.
|
||||||
typedef std::stack<JSFrame*, std::vector<JSFrame*, gc_allocator<JSFrame*> > > JSFrameStack;
|
typedef std::stack<JSFrame*, std::vector<JSFrame*, gc_allocator<JSFrame*> > > JSFrameStack;
|
||||||
|
|
||||||
} /* namespace JSTypes */
|
} /* namespace JSTypes */
|
||||||
|
}; /* namespace JavaScript */
|
||||||
} /* namespace JavaScript */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* jstypes_h */
|
#endif /* jstypes_h */
|
||||||
|
|
|
@ -129,8 +129,8 @@ namespace VM {
|
||||||
}
|
}
|
||||||
|
|
||||||
ICodeOp getBranchOp() \
|
ICodeOp getBranchOp() \
|
||||||
{ return ((opcode >= COMPARE_LT) && (opcode <= COMPARE_GT)) ? \
|
{ return ((opcode >= COMPARE_EQ) && (opcode <= COMPARE_NE)) ? \
|
||||||
(ICodeOp)(BRANCH_LT + (opcode - COMPARE_LT)) : NOP; }
|
(ICodeOp)(BRANCH_EQ + (opcode - COMPARE_EQ)) : NOP; }
|
||||||
|
|
||||||
ICodeOp op() { return opcode; }
|
ICodeOp op() { return opcode; }
|
||||||
|
|
||||||
|
|
|
@ -91,22 +91,6 @@ namespace ICG {
|
||||||
|
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
|
|
||||||
Register ICodeGenerator::loadVariable(uint32 frameIndex)
|
|
||||||
{
|
|
||||||
markMaxVariable(frameIndex);
|
|
||||||
Register dest = getRegister();
|
|
||||||
LoadVar *instr = new LoadVar(dest, frameIndex);
|
|
||||||
iCode->push_back(instr);
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ICodeGenerator::saveVariable(uint32 frameIndex, Register value)
|
|
||||||
{
|
|
||||||
markMaxVariable(frameIndex);
|
|
||||||
SaveVar *instr = new SaveVar(frameIndex, value);
|
|
||||||
iCode->push_back(instr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Register ICodeGenerator::loadImmediate(double value)
|
Register ICodeGenerator::loadImmediate(double value)
|
||||||
{
|
{
|
||||||
Register dest = getRegister();
|
Register dest = getRegister();
|
||||||
|
@ -183,6 +167,12 @@ namespace ICG {
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ICodeGenerator::move(Register destination, Register source)
|
||||||
|
{
|
||||||
|
Move *instr = new Move(destination, source);
|
||||||
|
iCode->push_back(instr);
|
||||||
|
}
|
||||||
|
|
||||||
Register ICodeGenerator::op(ICodeOp op, Register source1,
|
Register ICodeGenerator::op(ICodeOp op, Register source1,
|
||||||
Register source2)
|
Register source2)
|
||||||
{
|
{
|
||||||
|
@ -638,4 +628,4 @@ namespace ICG {
|
||||||
|
|
||||||
} // namespace ICG
|
} // namespace ICG
|
||||||
|
|
||||||
} // namespace JavaScript
|
}; // namespace JavaScript
|
||||||
|
|
|
@ -107,10 +107,11 @@ namespace ICG {
|
||||||
{ if (variableIndex > maxVariable) maxVariable = variableIndex; }
|
{ if (variableIndex > maxVariable) maxVariable = variableIndex; }
|
||||||
|
|
||||||
Register topRegister;
|
Register topRegister;
|
||||||
|
Register registerBase;
|
||||||
Register getRegister() \
|
Register getRegister() \
|
||||||
{ return topRegister++; }
|
{ return topRegister++; }
|
||||||
void resetTopRegister() \
|
void resetTopRegister() \
|
||||||
{ markMaxRegister(); topRegister = stitcher.empty() ? 0 : \
|
{ markMaxRegister(); topRegister = stitcher.empty() ? registerBase : \
|
||||||
stitcher.back()->registerBase; }
|
stitcher.back()->registerBase; }
|
||||||
|
|
||||||
ICodeOp getBranchOp() \
|
ICodeOp getBranchOp() \
|
||||||
|
@ -126,7 +127,7 @@ namespace ICG {
|
||||||
void branchConditional(Label *label, Register condition);
|
void branchConditional(Label *label, Register condition);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ICodeGenerator() : topRegister(0), maxRegister(0),
|
ICodeGenerator() : topRegister(0), registerBase(0), maxRegister(0),
|
||||||
maxVariable(0) \
|
maxVariable(0) \
|
||||||
{ iCode = new InstructionStream(); }
|
{ iCode = new InstructionStream(); }
|
||||||
|
|
||||||
|
@ -135,12 +136,17 @@ namespace ICG {
|
||||||
void mergeStream(InstructionStream *sideStream);
|
void mergeStream(InstructionStream *sideStream);
|
||||||
|
|
||||||
ICodeModule *complete();
|
ICodeModule *complete();
|
||||||
|
|
||||||
|
Register allocateVariable(StringAtom &name)
|
||||||
|
{ Register result = getRegister(); registerBase = topRegister; return result; }
|
||||||
|
|
||||||
Formatter& print(Formatter& f);
|
Formatter& print(Formatter& f);
|
||||||
|
|
||||||
Register op(ICodeOp op, Register source);
|
Register op(ICodeOp op, Register source);
|
||||||
Register op(ICodeOp op, Register source1, Register source2);
|
Register op(ICodeOp op, Register source1, Register source2);
|
||||||
Register call(Register target, RegisterList args);
|
Register call(Register target, RegisterList args);
|
||||||
|
|
||||||
|
void move(Register destination, Register source);
|
||||||
|
|
||||||
Register compare(ICodeOp op, Register source1, Register source2);
|
Register compare(ICodeOp op, Register source1, Register source2);
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ namespace JSTypes {
|
||||||
mLocals(iCode->itsMaxVariable + 1)
|
mLocals(iCode->itsMaxVariable + 1)
|
||||||
{
|
{
|
||||||
// copy caller's parameter list in to locals.
|
// copy caller's parameter list in to locals.
|
||||||
JSValues::iterator dest = mLocals.begin();
|
JSValues::iterator dest = mRegisters.begin();
|
||||||
const JSValues& params = caller->mRegisters;
|
const JSValues& params = caller->mRegisters;
|
||||||
for (RegisterList::const_iterator src = list.begin(),
|
for (RegisterList::const_iterator src = list.begin(),
|
||||||
end = list.end(); src != end; ++src, ++dest) {
|
end = list.end(); src != end; ++src, ++dest) {
|
||||||
|
@ -225,9 +225,8 @@ namespace JSTypes {
|
||||||
// a stack of JSFrames.
|
// a stack of JSFrames.
|
||||||
typedef std::stack<JSFrame*, std::vector<JSFrame*, gc_allocator<JSFrame*> > > JSFrameStack;
|
typedef std::stack<JSFrame*, std::vector<JSFrame*, gc_allocator<JSFrame*> > > JSFrameStack;
|
||||||
|
|
||||||
} /* namespace JSTypes */
|
} /* namespace JSTypes */
|
||||||
|
}; /* namespace JavaScript */
|
||||||
} /* namespace JavaScript */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* jstypes_h */
|
#endif /* jstypes_h */
|
||||||
|
|
|
@ -129,8 +129,8 @@ namespace VM {
|
||||||
}
|
}
|
||||||
|
|
||||||
ICodeOp getBranchOp() \
|
ICodeOp getBranchOp() \
|
||||||
{ return ((opcode >= COMPARE_LT) && (opcode <= COMPARE_GT)) ? \
|
{ return ((opcode >= COMPARE_EQ) && (opcode <= COMPARE_NE)) ? \
|
||||||
(ICodeOp)(BRANCH_LT + (opcode - COMPARE_LT)) : NOP; }
|
(ICodeOp)(BRANCH_EQ + (opcode - COMPARE_EQ)) : NOP; }
|
||||||
|
|
||||||
ICodeOp op() { return opcode; }
|
ICodeOp op() { return opcode; }
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ static void initConsole(StringPtr consoleName,
|
||||||
argc = 1;
|
argc = 1;
|
||||||
argv = mac_argv;
|
argv = mac_argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace JavaScript {
|
namespace JavaScript {
|
||||||
|
@ -287,43 +288,41 @@ namespace JavaScript {
|
||||||
uint32 pos = 0;
|
uint32 pos = 0;
|
||||||
ICodeGenerator icg;
|
ICodeGenerator icg;
|
||||||
|
|
||||||
// var i,j; i = j + 2;
|
// var i,j;
|
||||||
// i is bound to var #0, j to var #1
|
// i is bound to var #0, j to var #1
|
||||||
|
Register r_i = icg.allocateVariable(world.identifiers[widenCString("i")]);
|
||||||
|
Register r_j = icg.allocateVariable(world.identifiers[widenCString("j")]);
|
||||||
|
|
||||||
|
// i = j + 2;
|
||||||
icg.beginStatement(pos);
|
icg.beginStatement(pos);
|
||||||
Register r1 = icg.loadVariable(1);
|
Register r1 = icg.loadImmediate(2.0);
|
||||||
Register r2 = icg.loadImmediate(2.0);
|
icg.move(r_i, icg.op(ADD, r_i, r_j));
|
||||||
icg.saveVariable(0, icg.op(ADD, r1, r2));
|
|
||||||
|
|
||||||
// j = a.b
|
// j = a.b
|
||||||
icg.beginStatement(pos);
|
icg.beginStatement(pos);
|
||||||
Register r4 = icg.loadName(world.identifiers[widenCString("a")]);
|
r1 = icg.loadName(world.identifiers[widenCString("a")]);
|
||||||
Register r5 = icg.getProperty(r4, world.identifiers[widenCString("b")]);
|
r1 = icg.getProperty(r1, world.identifiers[widenCString("b")]);
|
||||||
icg.saveVariable(1, r5);
|
icg.move(r_j, r1);
|
||||||
|
|
||||||
// while (i) i = i + j;
|
// while (i) i = i + j;
|
||||||
icg.beginWhileStatement(pos);
|
icg.beginWhileStatement(pos);
|
||||||
r1 = icg.loadVariable(0);
|
icg.endWhileExpression(r_i);
|
||||||
icg.endWhileExpression(r1);
|
icg.move(r_i, icg.op(ADD, r_i, r_j));
|
||||||
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadVariable(1)));
|
|
||||||
icg.endWhileStatement();
|
icg.endWhileStatement();
|
||||||
|
|
||||||
// if (i) if (j) i = 3; else j = 4;
|
// if (i) if (j) i = 3; else j = 4;
|
||||||
r1 = icg.loadVariable(0);
|
icg.beginIfStatement(pos, r_i);
|
||||||
icg.beginIfStatement(pos, r1);
|
icg.beginIfStatement(pos, r_j);
|
||||||
r2 = icg.loadVariable(1);
|
icg.move(r_i, icg.loadImmediate(3));
|
||||||
icg.beginIfStatement(pos, r2);
|
|
||||||
icg.saveVariable(0, icg.loadImmediate(3));
|
|
||||||
icg.beginElseStatement(true);
|
icg.beginElseStatement(true);
|
||||||
icg.saveVariable(1, icg.loadImmediate(4));
|
icg.move(r_j, icg.loadImmediate(4));
|
||||||
icg.endIfStatement();
|
icg.endIfStatement();
|
||||||
icg.beginElseStatement(false);
|
icg.beginElseStatement(false);
|
||||||
icg.endIfStatement();
|
icg.endIfStatement();
|
||||||
|
|
||||||
|
|
||||||
// switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; }
|
// switch (i) { case 3: case 4: j = 4; break; case 5: j = 5; break; default : j = 6; }
|
||||||
r1 = icg.loadVariable(0);
|
icg.beginSwitchStatement(pos, r_i);
|
||||||
icg.beginSwitchStatement(pos, r1);
|
|
||||||
// case 3, note empty case statement (?necessary???)
|
// case 3, note empty case statement (?necessary???)
|
||||||
icg.endCaseCondition(icg.loadImmediate(3));
|
icg.endCaseCondition(icg.loadImmediate(3));
|
||||||
icg.beginCaseStatement();
|
icg.beginCaseStatement();
|
||||||
|
@ -332,30 +331,29 @@ namespace JavaScript {
|
||||||
icg.endCaseCondition(icg.loadImmediate(4));
|
icg.endCaseCondition(icg.loadImmediate(4));
|
||||||
icg.beginCaseStatement();
|
icg.beginCaseStatement();
|
||||||
icg.beginStatement(pos);
|
icg.beginStatement(pos);
|
||||||
icg.saveVariable(1, icg.loadImmediate(4));
|
icg.move(r_j, icg.loadImmediate(4));
|
||||||
icg.breakStatement();
|
icg.breakStatement();
|
||||||
icg.endCaseStatement();
|
icg.endCaseStatement();
|
||||||
// case 5
|
// case 5
|
||||||
icg.endCaseCondition(icg.loadImmediate(5));
|
icg.endCaseCondition(icg.loadImmediate(5));
|
||||||
icg.beginCaseStatement();
|
icg.beginCaseStatement();
|
||||||
icg.beginStatement(pos);
|
icg.beginStatement(pos);
|
||||||
icg.saveVariable(1, icg.loadImmediate(5));
|
icg.move(r_j, icg.loadImmediate(5));
|
||||||
icg.breakStatement();
|
icg.breakStatement();
|
||||||
icg.endCaseStatement();
|
icg.endCaseStatement();
|
||||||
// default
|
// default
|
||||||
icg.beginDefaultStatement();
|
icg.beginDefaultStatement();
|
||||||
icg.beginStatement(pos);
|
icg.beginStatement(pos);
|
||||||
icg.saveVariable(1, icg.loadImmediate(6));
|
icg.move(r_j, icg.loadImmediate(6));
|
||||||
icg.endDefaultStatement();
|
icg.endDefaultStatement();
|
||||||
icg.endSwitchStatement();
|
icg.endSwitchStatement();
|
||||||
|
|
||||||
// for ( ; i; i + 1 ) j = 99;
|
// for ( ; i; i = i + 1 ) j = 99;
|
||||||
icg.beginForStatement(pos);
|
icg.beginForStatement(pos);
|
||||||
r1 = icg.loadVariable(0);
|
icg.forCondition(r_i);
|
||||||
icg.forCondition(r1);
|
icg.move(r_i, icg.op(ADD, r_i, icg.loadImmediate(1)));
|
||||||
icg.saveVariable(0, icg.op(ADD, icg.loadVariable(0), icg.loadImmediate(1)));
|
|
||||||
icg.forIncrement();
|
icg.forIncrement();
|
||||||
icg.saveVariable(0, icg.loadImmediate(99));
|
icg.move(r_j, icg.loadImmediate(99));
|
||||||
icg.endForStatement();
|
icg.endForStatement();
|
||||||
|
|
||||||
ICodeModule *icm = icg.complete();
|
ICodeModule *icm = icg.complete();
|
||||||
|
@ -374,11 +372,12 @@ namespace JavaScript {
|
||||||
ICodeGenerator fun;
|
ICodeGenerator fun;
|
||||||
// function sum(n) { if (n > 1) return 1 + sum(n - 1); else return 1; }
|
// function sum(n) { if (n > 1) return 1 + sum(n - 1); else return 1; }
|
||||||
// n is bound to var #0.
|
// n is bound to var #0.
|
||||||
|
Register r_n = fun.allocateVariable(world.identifiers[widenCString("n")]);
|
||||||
fun.beginStatement(position);
|
fun.beginStatement(position);
|
||||||
Register r1 = fun.op(COMPARE_GT, fun.loadVariable(0), fun.loadImmediate(1.0));
|
Register r1 = fun.op(COMPARE_GT, r_n, fun.loadImmediate(1.0));
|
||||||
fun.beginIfStatement(position, r1);
|
fun.beginIfStatement(position, r1);
|
||||||
fun.beginStatement(position);
|
fun.beginStatement(position);
|
||||||
r1 = fun.op(SUBTRACT, fun.loadVariable(0), fun.loadImmediate(1.0));
|
r1 = fun.op(SUBTRACT, r_n, fun.loadImmediate(1.0));
|
||||||
RegisterList args(1);
|
RegisterList args(1);
|
||||||
args[0] = r1;
|
args[0] = r1;
|
||||||
r1 = fun.call(fun.loadName(sum), args);
|
r1 = fun.call(fun.loadName(sum), args);
|
||||||
|
@ -419,11 +418,12 @@ namespace JavaScript {
|
||||||
ICodeGenerator icg;
|
ICodeGenerator icg;
|
||||||
|
|
||||||
// fact(n) {
|
// fact(n) {
|
||||||
// n is bound to var #0.
|
|
||||||
// var result = 1;
|
// var result = 1;
|
||||||
// result is bound to var #1.
|
Register r_n = icg.allocateVariable(world.identifiers[widenCString("n")]);
|
||||||
|
Register r_result = icg.allocateVariable(world.identifiers[widenCString("result")]);
|
||||||
|
|
||||||
icg.beginStatement(position);
|
icg.beginStatement(position);
|
||||||
icg.saveVariable(1, icg.loadImmediate(1.0));
|
icg.move(r_result, icg.loadImmediate(1.0));
|
||||||
|
|
||||||
// while (n > 1) {
|
// while (n > 1) {
|
||||||
// result = result * n;
|
// result = result * n;
|
||||||
|
@ -431,24 +431,20 @@ namespace JavaScript {
|
||||||
// }
|
// }
|
||||||
{
|
{
|
||||||
icg.beginWhileStatement(position);
|
icg.beginWhileStatement(position);
|
||||||
Register r0 = icg.loadVariable(0);
|
|
||||||
Register r1 = icg.loadImmediate(1.0);
|
Register r1 = icg.loadImmediate(1.0);
|
||||||
Register r2 = icg.op(COMPARE_GT, r0, r1);
|
Register r2 = icg.op(COMPARE_GT, r_n, r1);
|
||||||
icg.endWhileExpression(r2);
|
icg.endWhileExpression(r2);
|
||||||
r0 = icg.loadVariable(0);
|
r2 = icg.op(MULTIPLY, r_result, r_n);
|
||||||
r1 = icg.loadVariable(1);
|
icg.move(r_result, r2);
|
||||||
r2 = icg.op(MULTIPLY, r1, r0);
|
|
||||||
icg.saveVariable(1, r2);
|
|
||||||
icg.beginStatement(position);
|
icg.beginStatement(position);
|
||||||
r0 = icg.loadVariable(0);
|
|
||||||
r1 = icg.loadImmediate(1.0);
|
r1 = icg.loadImmediate(1.0);
|
||||||
r2 = icg.op(SUBTRACT, r0, r1);
|
r2 = icg.op(SUBTRACT, r_n, r1);
|
||||||
icg.saveVariable(0, r2);
|
icg.move(r_n, r2);
|
||||||
icg.endWhileStatement();
|
icg.endWhileStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
// return result;
|
// return result;
|
||||||
icg.returnStatement(icg.loadVariable(1));
|
icg.returnStatement(r_result);
|
||||||
ICodeModule *icm = icg.complete();
|
ICodeModule *icm = icg.complete();
|
||||||
stdOut << icg;
|
stdOut << icg;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче