Adding support for Functions and Vars, preXcrement, object literals.

This commit is contained in:
rogerl%netscape.com 2000-06-14 23:26:15 +00:00
Родитель 46ff694c0d
Коммит dae9b1607b
10 изменённых файлов: 672 добавлений и 26 удалений

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

@ -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 };