зеркало из https://github.com/mozilla/pjs.git
Adding support for Functions and Vars, preXcrement, object literals.
This commit is contained in:
Родитель
46ff694c0d
Коммит
dae9b1607b
|
@ -69,7 +69,9 @@ ICodeGenerator::ICodeGenerator(World *world)
|
|||
exceptionRegister(NotARegister),
|
||||
variableList(new VariableList()),
|
||||
mWorld(world),
|
||||
mInstructionMap(new InstructionMap())
|
||||
mInstructionMap(new InstructionMap()),
|
||||
mWithinWith(false)
|
||||
|
||||
{
|
||||
iCode = new InstructionStream();
|
||||
iCodeOwner = true;
|
||||
|
@ -196,6 +198,22 @@ Register ICodeGenerator::nameDec(const StringAtom &name)
|
|||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::varInc(Register var)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
VarXcr *instr = new VarXcr(dest, var, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::varDec(Register var)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
VarXcr *instr = new VarXcr(dest, var, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Register ICodeGenerator::getProperty(Register base, const StringAtom &name)
|
||||
|
@ -543,7 +561,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
break;
|
||||
case ExprNode::identifier :
|
||||
{
|
||||
if (mWithinWith) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(p))->name);
|
||||
if (v != NotARegister)
|
||||
ret = v;
|
||||
|
@ -560,6 +578,45 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::string :
|
||||
ret = loadString(mWorld->identifiers[(static_cast<StringExprNode *>(p))->str]);
|
||||
break;
|
||||
case ExprNode::preIncrement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name, ret);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ExprNode::postIncrement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
|
@ -570,8 +627,15 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
// variable or name? see above
|
||||
ret = nameInc((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
ret = varInc(v);
|
||||
else
|
||||
ret = nameInc((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
}
|
||||
else
|
||||
ret = nameInc((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
|
@ -582,6 +646,45 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
}
|
||||
break;
|
||||
case ExprNode::preDecrement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name, ret);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ExprNode::postDecrement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
|
@ -592,8 +695,15 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
// variable or name? see above
|
||||
ret = nameDec((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
ret = varDec(v);
|
||||
else
|
||||
ret = nameDec((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
}
|
||||
else
|
||||
ret = nameDec((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
|
@ -636,9 +746,13 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
ret = genExpr(b->op2);
|
||||
if (b->op1->getKind() == ExprNode::identifier) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v != NotARegister)
|
||||
move(v, ret);
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v != NotARegister)
|
||||
move(v, ret);
|
||||
else
|
||||
saveName((static_cast<IdentifierExprNode *>(b->op1))->name, ret);
|
||||
}
|
||||
else
|
||||
saveName((static_cast<IdentifierExprNode *>(b->op1))->name, ret);
|
||||
}
|
||||
|
@ -789,6 +903,21 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
ret = r1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ExprNode::objectLiteral:
|
||||
{
|
||||
ret = newObject();
|
||||
|
||||
PairListExprNode *plen = static_cast<PairListExprNode *>(p);
|
||||
ExprPairList *e = plen->pairs;
|
||||
while (e) {
|
||||
if (e->field && e->value && (e->field->getKind() == ExprNode::identifier))
|
||||
setProperty(ret, (static_cast<IdentifierExprNode *>(e->field))->name, genExpr(e->value));
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
NOT_REACHED("Unsupported ExprNode kind");
|
||||
|
@ -815,6 +944,104 @@ bool LabelEntry::containsLabel(const StringAtom *label)
|
|||
return false;
|
||||
}
|
||||
|
||||
void ICodeGenerator::preprocess(StmtNode *p)
|
||||
{
|
||||
switch (p->getKind()) {
|
||||
case StmtNode::block:
|
||||
{
|
||||
BlockStmtNode *b = static_cast<BlockStmtNode *>(p);
|
||||
StmtNode *s = b->statements;
|
||||
while (s) {
|
||||
preprocess(s);
|
||||
s = s->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::Var:
|
||||
{
|
||||
VariableStmtNode *vs = static_cast<VariableStmtNode *>(p);
|
||||
VariableBinding *v = vs->bindings;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier))
|
||||
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name);
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::DoWhile:
|
||||
{
|
||||
UnaryStmtNode *d = static_cast<UnaryStmtNode *>(p);
|
||||
preprocess(d->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::While:
|
||||
{
|
||||
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
|
||||
preprocess(w->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::For:
|
||||
{
|
||||
ForStmtNode *f = static_cast<ForStmtNode *>(p);
|
||||
if (f->initializer)
|
||||
preprocess(f->initializer);
|
||||
preprocess(f->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::If:
|
||||
{
|
||||
UnaryStmtNode *i = static_cast<UnaryStmtNode *>(p);
|
||||
preprocess(i->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::IfElse:
|
||||
{
|
||||
BinaryStmtNode *i = static_cast<BinaryStmtNode *>(p);
|
||||
preprocess(i->stmt);
|
||||
preprocess(i->stmt2);
|
||||
}
|
||||
break;
|
||||
case StmtNode::With:
|
||||
{
|
||||
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
|
||||
preprocess(w->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Switch:
|
||||
{
|
||||
SwitchStmtNode *sw = static_cast<SwitchStmtNode *>(p);
|
||||
StmtNode *s = sw->statements;
|
||||
while (s) {
|
||||
if (s->getKind() != StmtNode::Case)
|
||||
preprocess(s);
|
||||
s = s->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::label:
|
||||
{
|
||||
LabelStmtNode *l = static_cast<LabelStmtNode *>(p);
|
||||
preprocess(l->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Try:
|
||||
{
|
||||
TryStmtNode *t = static_cast<TryStmtNode *>(p);
|
||||
genStmt(t->stmt);
|
||||
if (t->catches) {
|
||||
CatchClause *c = t->catches;
|
||||
while (c) {
|
||||
preprocess(c->stmt);
|
||||
c = c->next;
|
||||
}
|
||||
}
|
||||
if (t->finally)
|
||||
genStmt(t->finally);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
{
|
||||
Register ret = NotARegister;
|
||||
|
@ -825,6 +1052,47 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
}
|
||||
|
||||
switch (p->getKind()) {
|
||||
case StmtNode::Function:
|
||||
{
|
||||
FunctionStmtNode *f = static_cast<FunctionStmtNode *>(p);
|
||||
ICodeGenerator icg(mWorld);
|
||||
VariableBinding *v = f->function.parameters;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier))
|
||||
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name);
|
||||
v = v->next;
|
||||
}
|
||||
icg.preprocess(f->function.body);
|
||||
icg.genStmt(f->function.body);
|
||||
stdOut << icg;
|
||||
ICodeModule *icm = icg.complete();
|
||||
if (f->function.name->getKind() == ExprNode::identifier)
|
||||
defFunction((static_cast<IdentifierExprNode *>(f->function.name))->name, icm);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Var:
|
||||
{
|
||||
VariableStmtNode *vs = static_cast<VariableStmtNode *>(p);
|
||||
VariableBinding *v = vs->bindings;
|
||||
while (v) {
|
||||
if (v->name && v->initializer) {
|
||||
if (v->name->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register r = genExpr(v->name);
|
||||
Register val = genExpr(v->initializer);
|
||||
move(r, val);
|
||||
}
|
||||
else {
|
||||
Register val = genExpr(v->initializer);
|
||||
saveName((static_cast<IdentifierExprNode *>(v->name))->name, val);
|
||||
}
|
||||
}
|
||||
// XXX what's the else case here, when does a VariableBinding NOT have an identifier child?
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::expression:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
|
@ -840,7 +1108,10 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
case StmtNode::Return:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
returnStmt(ret = genExpr(e->expr));
|
||||
if (e->expr)
|
||||
returnStmt(ret = genExpr(e->expr));
|
||||
else
|
||||
returnStmt(NotARegister);
|
||||
}
|
||||
break;
|
||||
case StmtNode::If:
|
||||
|
@ -866,6 +1137,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
branch(beyondLabel);
|
||||
setLabel(falseLabel);
|
||||
genStmt(i->stmt2);
|
||||
setLabel(beyondLabel);
|
||||
}
|
||||
break;
|
||||
case StmtNode::With:
|
||||
|
|
|
@ -153,6 +153,8 @@ namespace ICG {
|
|||
void endWith()
|
||||
{ iCode->push_back(new Without()); }
|
||||
|
||||
void defFunction(const StringAtom& name, ICodeModule *code)
|
||||
{ iCode->push_back(new FunctionDef(name, code)); }
|
||||
|
||||
void resetStatement() { resetTopRegister(); }
|
||||
|
||||
|
@ -189,8 +191,10 @@ namespace ICG {
|
|||
bool needBoolValueInBranch = false,
|
||||
Label *trueBranch = NULL,
|
||||
Label *falseBranch = NULL);
|
||||
void preprocess(StmtNode *p);
|
||||
Register genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL);
|
||||
|
||||
void isScript() { mWithinWith = true; }
|
||||
|
||||
void returnStmt(Register r);
|
||||
void throwStmt(Register r)
|
||||
|
@ -226,7 +230,7 @@ namespace ICG {
|
|||
void saveName(const StringAtom &name, Register value);
|
||||
Register nameInc(const StringAtom &name);
|
||||
Register nameDec(const StringAtom &name);
|
||||
|
||||
|
||||
Register getProperty(Register base, const StringAtom &name);
|
||||
void setProperty(Register base, const StringAtom &name, Register value);
|
||||
Register propertyInc(Register base, const StringAtom &name);
|
||||
|
@ -236,7 +240,10 @@ namespace ICG {
|
|||
void setElement(Register base, Register index, Register value);
|
||||
Register elementInc(Register base, Register index);
|
||||
Register elementDec(Register base, Register index);
|
||||
|
||||
|
||||
Register varInc(Register var);
|
||||
Register varDec(Register var);
|
||||
|
||||
Register getRegisterBase() { return topRegister; }
|
||||
InstructionStream *get_iCode() { return iCode; }
|
||||
|
||||
|
|
|
@ -458,6 +458,13 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
|
||||
Instruction* instruction = *mPC;
|
||||
switch (instruction->op()) {
|
||||
case FUNCTION:
|
||||
{
|
||||
FunctionDef* fnDef = static_cast<FunctionDef*>(instruction);
|
||||
mGlobal->defineFunction(fnDef->name, fnDef->code);
|
||||
}
|
||||
break;
|
||||
|
||||
case CALL:
|
||||
{
|
||||
Call* call = static_cast<Call*>(instruction);
|
||||
|
@ -697,6 +704,17 @@ using JSString throughout.
|
|||
}
|
||||
break;
|
||||
|
||||
case VAR_XCR:
|
||||
{
|
||||
VarXcr *vx = static_cast<VarXcr*>(instruction);
|
||||
JSValue& dest = (*registers)[dst(vx)];
|
||||
JSValue r = (*registers)[src1(vx)].toNumber();
|
||||
dest = r;
|
||||
r.f64 += val3(vx);
|
||||
(*registers)[src1(vx)] = r;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_XCR:
|
||||
{
|
||||
PropXcr *px = static_cast<PropXcr*>(instruction);
|
||||
|
|
|
@ -189,7 +189,7 @@ Formatter& operator<<(Formatter& f, const JSValue& value)
|
|||
printFormat(f, "Function @ 0x%08X", value.object);
|
||||
break;
|
||||
case JSValue::string_tag:
|
||||
f << *value.string;
|
||||
f << "\"" << *value.string << "\"";
|
||||
break;
|
||||
case JSValue::boolean_tag:
|
||||
f << ((value.boolean) ? "true" : "false");
|
||||
|
|
|
@ -39,6 +39,13 @@
|
|||
#include "world.h"
|
||||
#include <vector>
|
||||
|
||||
/* forward declare classes from JavaScript::ICG */
|
||||
namespace JavaScript {
|
||||
namespace ICG {
|
||||
class ICodeModule;
|
||||
} /* namespace ICG */
|
||||
} /* namespace JavaScript */
|
||||
|
||||
namespace JavaScript {
|
||||
namespace VM {
|
||||
|
||||
|
@ -63,6 +70,7 @@ namespace VM {
|
|||
COMPARE_NE, /* dest, source1, source2 */
|
||||
DIVIDE, /* dest, source1, source2 */
|
||||
ELEM_XCR, /* dest, base, index, value */
|
||||
FUNCTION, /* Defines a function */
|
||||
GET_ELEMENT, /* dest, base, index */
|
||||
GET_PROP, /* dest, object, prop name */
|
||||
INSTANCEOF, /* dest, source1, source2 */
|
||||
|
@ -126,6 +134,7 @@ namespace VM {
|
|||
"COMPARE_NE ",
|
||||
"DIVIDE ",
|
||||
"ELEM_XCR ",
|
||||
"FUNCTION ",
|
||||
"GET_ELEMENT ",
|
||||
"GET_PROP ",
|
||||
"INSTANCEOF ",
|
||||
|
@ -197,6 +206,23 @@ namespace VM {
|
|||
|
||||
};
|
||||
|
||||
|
||||
class FunctionDef : public Instruction
|
||||
{
|
||||
public:
|
||||
const StringAtom &name;
|
||||
ICG::ICodeModule *code;
|
||||
|
||||
virtual Formatter& print(Formatter& f)
|
||||
{
|
||||
f << opcodeNames[mOpcode] << "\t" << name;
|
||||
return f;
|
||||
}
|
||||
|
||||
FunctionDef(const StringAtom& name, ICG::ICodeModule *code)
|
||||
: Instruction(FUNCTION), name(name), code(code) { }
|
||||
};
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
enum { NotARegister = 0xFFFFFFFF };
|
||||
|
|
|
@ -69,7 +69,9 @@ ICodeGenerator::ICodeGenerator(World *world)
|
|||
exceptionRegister(NotARegister),
|
||||
variableList(new VariableList()),
|
||||
mWorld(world),
|
||||
mInstructionMap(new InstructionMap())
|
||||
mInstructionMap(new InstructionMap()),
|
||||
mWithinWith(false)
|
||||
|
||||
{
|
||||
iCode = new InstructionStream();
|
||||
iCodeOwner = true;
|
||||
|
@ -196,6 +198,22 @@ Register ICodeGenerator::nameDec(const StringAtom &name)
|
|||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::varInc(Register var)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
VarXcr *instr = new VarXcr(dest, var, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::varDec(Register var)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
VarXcr *instr = new VarXcr(dest, var, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Register ICodeGenerator::getProperty(Register base, const StringAtom &name)
|
||||
|
@ -543,7 +561,7 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
break;
|
||||
case ExprNode::identifier :
|
||||
{
|
||||
if (mWithinWith) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(p))->name);
|
||||
if (v != NotARegister)
|
||||
ret = v;
|
||||
|
@ -560,6 +578,45 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::string :
|
||||
ret = loadString(mWorld->identifiers[(static_cast<StringExprNode *>(p))->str]);
|
||||
break;
|
||||
case ExprNode::preIncrement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name, ret);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ExprNode::postIncrement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
|
@ -570,8 +627,15 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
// variable or name? see above
|
||||
ret = nameInc((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
ret = varInc(v);
|
||||
else
|
||||
ret = nameInc((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
}
|
||||
else
|
||||
ret = nameInc((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
|
@ -582,6 +646,45 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
}
|
||||
break;
|
||||
case ExprNode::preDecrement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name, ret);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1);
|
||||
Register index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ExprNode::postDecrement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
|
@ -592,8 +695,15 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
// variable or name? see above
|
||||
ret = nameDec((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
ret = varDec(v);
|
||||
else
|
||||
ret = nameDec((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
}
|
||||
else
|
||||
ret = nameDec((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
|
@ -636,9 +746,13 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
ret = genExpr(b->op2);
|
||||
if (b->op1->getKind() == ExprNode::identifier) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v != NotARegister)
|
||||
move(v, ret);
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v != NotARegister)
|
||||
move(v, ret);
|
||||
else
|
||||
saveName((static_cast<IdentifierExprNode *>(b->op1))->name, ret);
|
||||
}
|
||||
else
|
||||
saveName((static_cast<IdentifierExprNode *>(b->op1))->name, ret);
|
||||
}
|
||||
|
@ -789,6 +903,21 @@ Register ICodeGenerator::genExpr(ExprNode *p,
|
|||
ret = r1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ExprNode::objectLiteral:
|
||||
{
|
||||
ret = newObject();
|
||||
|
||||
PairListExprNode *plen = static_cast<PairListExprNode *>(p);
|
||||
ExprPairList *e = plen->pairs;
|
||||
while (e) {
|
||||
if (e->field && e->value && (e->field->getKind() == ExprNode::identifier))
|
||||
setProperty(ret, (static_cast<IdentifierExprNode *>(e->field))->name, genExpr(e->value));
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
NOT_REACHED("Unsupported ExprNode kind");
|
||||
|
@ -815,6 +944,104 @@ bool LabelEntry::containsLabel(const StringAtom *label)
|
|||
return false;
|
||||
}
|
||||
|
||||
void ICodeGenerator::preprocess(StmtNode *p)
|
||||
{
|
||||
switch (p->getKind()) {
|
||||
case StmtNode::block:
|
||||
{
|
||||
BlockStmtNode *b = static_cast<BlockStmtNode *>(p);
|
||||
StmtNode *s = b->statements;
|
||||
while (s) {
|
||||
preprocess(s);
|
||||
s = s->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::Var:
|
||||
{
|
||||
VariableStmtNode *vs = static_cast<VariableStmtNode *>(p);
|
||||
VariableBinding *v = vs->bindings;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier))
|
||||
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name);
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::DoWhile:
|
||||
{
|
||||
UnaryStmtNode *d = static_cast<UnaryStmtNode *>(p);
|
||||
preprocess(d->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::While:
|
||||
{
|
||||
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
|
||||
preprocess(w->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::For:
|
||||
{
|
||||
ForStmtNode *f = static_cast<ForStmtNode *>(p);
|
||||
if (f->initializer)
|
||||
preprocess(f->initializer);
|
||||
preprocess(f->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::If:
|
||||
{
|
||||
UnaryStmtNode *i = static_cast<UnaryStmtNode *>(p);
|
||||
preprocess(i->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::IfElse:
|
||||
{
|
||||
BinaryStmtNode *i = static_cast<BinaryStmtNode *>(p);
|
||||
preprocess(i->stmt);
|
||||
preprocess(i->stmt2);
|
||||
}
|
||||
break;
|
||||
case StmtNode::With:
|
||||
{
|
||||
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
|
||||
preprocess(w->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Switch:
|
||||
{
|
||||
SwitchStmtNode *sw = static_cast<SwitchStmtNode *>(p);
|
||||
StmtNode *s = sw->statements;
|
||||
while (s) {
|
||||
if (s->getKind() != StmtNode::Case)
|
||||
preprocess(s);
|
||||
s = s->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::label:
|
||||
{
|
||||
LabelStmtNode *l = static_cast<LabelStmtNode *>(p);
|
||||
preprocess(l->stmt);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Try:
|
||||
{
|
||||
TryStmtNode *t = static_cast<TryStmtNode *>(p);
|
||||
genStmt(t->stmt);
|
||||
if (t->catches) {
|
||||
CatchClause *c = t->catches;
|
||||
while (c) {
|
||||
preprocess(c->stmt);
|
||||
c = c->next;
|
||||
}
|
||||
}
|
||||
if (t->finally)
|
||||
genStmt(t->finally);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
{
|
||||
Register ret = NotARegister;
|
||||
|
@ -825,6 +1052,47 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
}
|
||||
|
||||
switch (p->getKind()) {
|
||||
case StmtNode::Function:
|
||||
{
|
||||
FunctionStmtNode *f = static_cast<FunctionStmtNode *>(p);
|
||||
ICodeGenerator icg(mWorld);
|
||||
VariableBinding *v = f->function.parameters;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier))
|
||||
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name);
|
||||
v = v->next;
|
||||
}
|
||||
icg.preprocess(f->function.body);
|
||||
icg.genStmt(f->function.body);
|
||||
stdOut << icg;
|
||||
ICodeModule *icm = icg.complete();
|
||||
if (f->function.name->getKind() == ExprNode::identifier)
|
||||
defFunction((static_cast<IdentifierExprNode *>(f->function.name))->name, icm);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Var:
|
||||
{
|
||||
VariableStmtNode *vs = static_cast<VariableStmtNode *>(p);
|
||||
VariableBinding *v = vs->bindings;
|
||||
while (v) {
|
||||
if (v->name && v->initializer) {
|
||||
if (v->name->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register r = genExpr(v->name);
|
||||
Register val = genExpr(v->initializer);
|
||||
move(r, val);
|
||||
}
|
||||
else {
|
||||
Register val = genExpr(v->initializer);
|
||||
saveName((static_cast<IdentifierExprNode *>(v->name))->name, val);
|
||||
}
|
||||
}
|
||||
// XXX what's the else case here, when does a VariableBinding NOT have an identifier child?
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case StmtNode::expression:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
|
@ -840,7 +1108,10 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
case StmtNode::Return:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
returnStmt(ret = genExpr(e->expr));
|
||||
if (e->expr)
|
||||
returnStmt(ret = genExpr(e->expr));
|
||||
else
|
||||
returnStmt(NotARegister);
|
||||
}
|
||||
break;
|
||||
case StmtNode::If:
|
||||
|
@ -866,6 +1137,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
branch(beyondLabel);
|
||||
setLabel(falseLabel);
|
||||
genStmt(i->stmt2);
|
||||
setLabel(beyondLabel);
|
||||
}
|
||||
break;
|
||||
case StmtNode::With:
|
||||
|
|
|
@ -153,6 +153,8 @@ namespace ICG {
|
|||
void endWith()
|
||||
{ iCode->push_back(new Without()); }
|
||||
|
||||
void defFunction(const StringAtom& name, ICodeModule *code)
|
||||
{ iCode->push_back(new FunctionDef(name, code)); }
|
||||
|
||||
void resetStatement() { resetTopRegister(); }
|
||||
|
||||
|
@ -189,8 +191,10 @@ namespace ICG {
|
|||
bool needBoolValueInBranch = false,
|
||||
Label *trueBranch = NULL,
|
||||
Label *falseBranch = NULL);
|
||||
void preprocess(StmtNode *p);
|
||||
Register genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL);
|
||||
|
||||
void isScript() { mWithinWith = true; }
|
||||
|
||||
void returnStmt(Register r);
|
||||
void throwStmt(Register r)
|
||||
|
@ -226,7 +230,7 @@ namespace ICG {
|
|||
void saveName(const StringAtom &name, Register value);
|
||||
Register nameInc(const StringAtom &name);
|
||||
Register nameDec(const StringAtom &name);
|
||||
|
||||
|
||||
Register getProperty(Register base, const StringAtom &name);
|
||||
void setProperty(Register base, const StringAtom &name, Register value);
|
||||
Register propertyInc(Register base, const StringAtom &name);
|
||||
|
@ -236,7 +240,10 @@ namespace ICG {
|
|||
void setElement(Register base, Register index, Register value);
|
||||
Register elementInc(Register base, Register index);
|
||||
Register elementDec(Register base, Register index);
|
||||
|
||||
|
||||
Register varInc(Register var);
|
||||
Register varDec(Register var);
|
||||
|
||||
Register getRegisterBase() { return topRegister; }
|
||||
InstructionStream *get_iCode() { return iCode; }
|
||||
|
||||
|
|
|
@ -458,6 +458,13 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
|
||||
Instruction* instruction = *mPC;
|
||||
switch (instruction->op()) {
|
||||
case FUNCTION:
|
||||
{
|
||||
FunctionDef* fnDef = static_cast<FunctionDef*>(instruction);
|
||||
mGlobal->defineFunction(fnDef->name, fnDef->code);
|
||||
}
|
||||
break;
|
||||
|
||||
case CALL:
|
||||
{
|
||||
Call* call = static_cast<Call*>(instruction);
|
||||
|
@ -697,6 +704,17 @@ using JSString throughout.
|
|||
}
|
||||
break;
|
||||
|
||||
case VAR_XCR:
|
||||
{
|
||||
VarXcr *vx = static_cast<VarXcr*>(instruction);
|
||||
JSValue& dest = (*registers)[dst(vx)];
|
||||
JSValue r = (*registers)[src1(vx)].toNumber();
|
||||
dest = r;
|
||||
r.f64 += val3(vx);
|
||||
(*registers)[src1(vx)] = r;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_XCR:
|
||||
{
|
||||
PropXcr *px = static_cast<PropXcr*>(instruction);
|
||||
|
|
|
@ -189,7 +189,7 @@ Formatter& operator<<(Formatter& f, const JSValue& value)
|
|||
printFormat(f, "Function @ 0x%08X", value.object);
|
||||
break;
|
||||
case JSValue::string_tag:
|
||||
f << *value.string;
|
||||
f << "\"" << *value.string << "\"";
|
||||
break;
|
||||
case JSValue::boolean_tag:
|
||||
f << ((value.boolean) ? "true" : "false");
|
||||
|
|
|
@ -39,6 +39,13 @@
|
|||
#include "world.h"
|
||||
#include <vector>
|
||||
|
||||
/* forward declare classes from JavaScript::ICG */
|
||||
namespace JavaScript {
|
||||
namespace ICG {
|
||||
class ICodeModule;
|
||||
} /* namespace ICG */
|
||||
} /* namespace JavaScript */
|
||||
|
||||
namespace JavaScript {
|
||||
namespace VM {
|
||||
|
||||
|
@ -63,6 +70,7 @@ namespace VM {
|
|||
COMPARE_NE, /* dest, source1, source2 */
|
||||
DIVIDE, /* dest, source1, source2 */
|
||||
ELEM_XCR, /* dest, base, index, value */
|
||||
FUNCTION, /* Defines a function */
|
||||
GET_ELEMENT, /* dest, base, index */
|
||||
GET_PROP, /* dest, object, prop name */
|
||||
INSTANCEOF, /* dest, source1, source2 */
|
||||
|
@ -126,6 +134,7 @@ namespace VM {
|
|||
"COMPARE_NE ",
|
||||
"DIVIDE ",
|
||||
"ELEM_XCR ",
|
||||
"FUNCTION ",
|
||||
"GET_ELEMENT ",
|
||||
"GET_PROP ",
|
||||
"INSTANCEOF ",
|
||||
|
@ -197,6 +206,23 @@ namespace VM {
|
|||
|
||||
};
|
||||
|
||||
|
||||
class FunctionDef : public Instruction
|
||||
{
|
||||
public:
|
||||
const StringAtom &name;
|
||||
ICG::ICodeModule *code;
|
||||
|
||||
virtual Formatter& print(Formatter& f)
|
||||
{
|
||||
f << opcodeNames[mOpcode] << "\t" << name;
|
||||
return f;
|
||||
}
|
||||
|
||||
FunctionDef(const StringAtom& name, ICG::ICodeModule *code)
|
||||
: Instruction(FUNCTION), name(name), code(code) { }
|
||||
};
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
enum { NotARegister = 0xFFFFFFFF };
|
||||
|
|
Загрузка…
Ссылка в новой задаче