Changed use of Register to TypedRegister throughout.
This commit is contained in:
Родитель
c23aa15cea
Коммит
0bb6f588ba
|
@ -61,14 +61,15 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
|
|||
// ICodeGenerator
|
||||
//
|
||||
|
||||
ICodeGenerator::ICodeGenerator(World *world)
|
||||
ICodeGenerator::ICodeGenerator(World *world, JSScope *global)
|
||||
: topRegister(0),
|
||||
registerBase(0),
|
||||
maxRegister(0),
|
||||
parameterCount(0),
|
||||
exceptionRegister(NotARegister),
|
||||
exceptionRegister(TypedRegister(NotARegister, &None_Type)),
|
||||
variableList(new VariableList()),
|
||||
mWorld(world),
|
||||
mGlobal(global),
|
||||
mInstructionMap(new InstructionMap()),
|
||||
mWithinWith(false)
|
||||
|
||||
|
@ -77,12 +78,28 @@ ICodeGenerator::ICodeGenerator(World *world)
|
|||
iCodeOwner = true;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::allocateVariable(const StringAtom& name)
|
||||
const JSType *ICodeGenerator::findType(const StringAtom& typeName)
|
||||
{
|
||||
const JSValue& type = mGlobal->getVariable(typeName);
|
||||
if (type.isType())
|
||||
return type.type;
|
||||
return &Any_Type;
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName)
|
||||
{
|
||||
if (exceptionRegister == NotARegister) {
|
||||
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")]);
|
||||
if (exceptionRegister.first == NotARegister) {
|
||||
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
|
||||
}
|
||||
return grabRegister(name);
|
||||
return grabRegister(name, findType(typeName));
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name)
|
||||
{
|
||||
if (exceptionRegister.first == NotARegister) {
|
||||
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
|
||||
}
|
||||
return grabRegister(name, &Any_Type);
|
||||
}
|
||||
|
||||
ICodeModule *ICodeGenerator::complete()
|
||||
|
@ -126,41 +143,41 @@ ICodeModule *ICodeGenerator::complete()
|
|||
|
||||
/********************************************************************/
|
||||
|
||||
Register ICodeGenerator::loadImmediate(double value)
|
||||
TypedRegister ICodeGenerator::loadImmediate(double value)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
LoadImmediate *instr = new LoadImmediate(dest, value);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::loadString(String &value)
|
||||
TypedRegister ICodeGenerator::loadString(String &value)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &String_Type);
|
||||
LoadString *instr = new LoadString(dest, new JSString(value));
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::loadValue(JSValue value)
|
||||
TypedRegister ICodeGenerator::loadBoolean(bool value)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
LoadValue *instr = new LoadValue(dest, value);
|
||||
TypedRegister dest(getRegister(), &Boolean_Type);
|
||||
LoadBoolean *instr = new LoadBoolean(dest, value);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::newObject()
|
||||
TypedRegister ICodeGenerator::newObject()
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
NewObject *instr = new NewObject(dest);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::newArray()
|
||||
TypedRegister ICodeGenerator::newArray()
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Array_Type);
|
||||
NewArray *instr = new NewArray(dest);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
|
@ -168,47 +185,47 @@ Register ICodeGenerator::newArray()
|
|||
|
||||
|
||||
|
||||
Register ICodeGenerator::loadName(const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::loadName(const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
LoadName *instr = new LoadName(dest, &name);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void ICodeGenerator::saveName(const StringAtom &name, Register value)
|
||||
void ICodeGenerator::saveName(const StringAtom &name, TypedRegister value)
|
||||
{
|
||||
SaveName *instr = new SaveName(&name, value);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
Register ICodeGenerator::nameInc(const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::nameInc(const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
NameXcr *instr = new NameXcr(dest, &name, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::nameDec(const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::nameDec(const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
NameXcr *instr = new NameXcr(dest, &name, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::varInc(Register var)
|
||||
TypedRegister ICodeGenerator::varInc(TypedRegister var)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
VarXcr *instr = new VarXcr(dest, var, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::varDec(Register var)
|
||||
TypedRegister ICodeGenerator::varDec(TypedRegister var)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
VarXcr *instr = new VarXcr(dest, var, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
|
@ -216,32 +233,32 @@ Register ICodeGenerator::varDec(Register var)
|
|||
|
||||
|
||||
|
||||
Register ICodeGenerator::getProperty(Register base, const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::getProperty(TypedRegister base, const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
GetProp *instr = new GetProp(dest, base, &name);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void ICodeGenerator::setProperty(Register base, const StringAtom &name,
|
||||
Register value)
|
||||
void ICodeGenerator::setProperty(TypedRegister base, const StringAtom &name,
|
||||
TypedRegister value)
|
||||
{
|
||||
SetProp *instr = new SetProp(base, &name, value);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
Register ICodeGenerator::propertyInc(Register base, const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::propertyInc(TypedRegister base, const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
PropXcr *instr = new PropXcr(dest, base, &name, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::propertyDec(Register base, const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::propertyDec(TypedRegister base, const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
PropXcr *instr = new PropXcr(dest, base, &name, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
|
@ -249,94 +266,94 @@ Register ICodeGenerator::propertyDec(Register base, const StringAtom &name)
|
|||
|
||||
|
||||
|
||||
Register ICodeGenerator::getElement(Register base, Register index)
|
||||
TypedRegister ICodeGenerator::getElement(TypedRegister base, TypedRegister index)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
GetElement *instr = new GetElement(dest, base, index);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void ICodeGenerator::setElement(Register base, Register index,
|
||||
Register value)
|
||||
void ICodeGenerator::setElement(TypedRegister base, TypedRegister index,
|
||||
TypedRegister value)
|
||||
{
|
||||
SetElement *instr = new SetElement(base, index, value);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
Register ICodeGenerator::elementInc(Register base, Register index)
|
||||
TypedRegister ICodeGenerator::elementInc(TypedRegister base, TypedRegister index)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
ElemXcr *instr = new ElemXcr(dest, base, index, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::elementDec(Register base, Register index)
|
||||
TypedRegister ICodeGenerator::elementDec(TypedRegister base, TypedRegister index)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
ElemXcr *instr = new ElemXcr(dest, base, index, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
Register ICodeGenerator::op(ICodeOp op, Register source)
|
||||
TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
ASSERT(source != NotARegister);
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
ASSERT(source.first != NotARegister);
|
||||
Unary *instr = new Unary (op, dest, source);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
void ICodeGenerator::move(Register destination, Register source)
|
||||
void ICodeGenerator::move(TypedRegister destination, TypedRegister source)
|
||||
{
|
||||
ASSERT(destination != NotARegister);
|
||||
ASSERT(source != NotARegister);
|
||||
ASSERT(destination.first != NotARegister);
|
||||
ASSERT(source.first != NotARegister);
|
||||
Move *instr = new Move(destination, source);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
Register ICodeGenerator::logicalNot(Register source)
|
||||
TypedRegister ICodeGenerator::logicalNot(TypedRegister source)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
Not *instr = new Not(dest, source);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::test(Register source)
|
||||
TypedRegister ICodeGenerator::test(TypedRegister source)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
Test *instr = new Test(dest, source);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::op(ICodeOp op, Register source1,
|
||||
Register source2)
|
||||
TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source1,
|
||||
TypedRegister source2)
|
||||
{
|
||||
ASSERT(source1 != NotARegister);
|
||||
ASSERT(source2 != NotARegister);
|
||||
Register dest = getRegister();
|
||||
ASSERT(source1.first != NotARegister);
|
||||
ASSERT(source2.first != NotARegister);
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
Arithmetic *instr = new Arithmetic(op, dest, source1, source2);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::call(Register target, RegisterList args)
|
||||
TypedRegister ICodeGenerator::call(TypedRegister target, RegisterList args)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
Call *instr = new Call(dest, target, args);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void ICodeGenerator::callVoid(Register target, RegisterList args)
|
||||
void ICodeGenerator::callVoid(TypedRegister target, RegisterList args)
|
||||
{
|
||||
Call *instr = new Call(NotARegister, target, args);
|
||||
Call *instr = new Call(TypedRegister(NotARegister, &Void_Type), target, args);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
|
@ -346,23 +363,23 @@ void ICodeGenerator::branch(Label *label)
|
|||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
GenericBranch *ICodeGenerator::branchTrue(Label *label, Register condition)
|
||||
GenericBranch *ICodeGenerator::branchTrue(Label *label, TypedRegister condition)
|
||||
{
|
||||
GenericBranch *instr = new GenericBranch(BRANCH_TRUE, label, condition);
|
||||
iCode->push_back(instr);
|
||||
return instr;
|
||||
}
|
||||
|
||||
GenericBranch *ICodeGenerator::branchFalse(Label *label, Register condition)
|
||||
GenericBranch *ICodeGenerator::branchFalse(Label *label, TypedRegister condition)
|
||||
{
|
||||
GenericBranch *instr = new GenericBranch(BRANCH_FALSE, label, condition);
|
||||
iCode->push_back(instr);
|
||||
return instr;
|
||||
}
|
||||
|
||||
void ICodeGenerator::returnStmt(Register r)
|
||||
void ICodeGenerator::returnStmt(TypedRegister r)
|
||||
{
|
||||
if (r == NotARegister)
|
||||
if (r.first == NotARegister)
|
||||
iCode->push_back(new ReturnVoid());
|
||||
else
|
||||
iCode->push_back(new Return(r));
|
||||
|
@ -504,37 +521,37 @@ static bool generatedBoolean(ExprNode *p)
|
|||
a conditional branch to the appropriate target. If either branch is NULL, it
|
||||
indicates that the label is immediately forthcoming.
|
||||
*/
|
||||
Result ICodeGenerator::genExpr(ExprNode *p,
|
||||
TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
bool needBoolValueInBranch,
|
||||
Label *trueBranch,
|
||||
Label *falseBranch)
|
||||
{
|
||||
Register ret = NotARegister;
|
||||
TypedRegister ret(NotARegister, &None_Type);
|
||||
switch (p->getKind()) {
|
||||
case ExprNode::True:
|
||||
if (trueBranch || falseBranch) {
|
||||
if (needBoolValueInBranch)
|
||||
ret = loadValue(kTrue);
|
||||
ret = loadBoolean(true);
|
||||
if (trueBranch)
|
||||
branch(trueBranch);
|
||||
}
|
||||
else
|
||||
ret = loadValue(kTrue);
|
||||
ret = loadBoolean(true);
|
||||
break;
|
||||
case ExprNode::False:
|
||||
if (trueBranch || falseBranch) {
|
||||
if (needBoolValueInBranch)
|
||||
ret = loadValue(kFalse);
|
||||
ret = loadBoolean(false);
|
||||
if (falseBranch)
|
||||
branch(falseBranch);
|
||||
}
|
||||
else
|
||||
ret = loadValue(kFalse);
|
||||
ret = loadBoolean(false);
|
||||
break;
|
||||
case ExprNode::parentheses:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
ret = genExpr(u->op, needBoolValueInBranch, trueBranch, falseBranch).reg;
|
||||
ret = genExpr(u->op, needBoolValueInBranch, trueBranch, falseBranch);
|
||||
}
|
||||
break;
|
||||
case ExprNode::New:
|
||||
|
@ -546,11 +563,11 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::call :
|
||||
{
|
||||
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
|
||||
Register fn = genExpr(i->op).reg;
|
||||
TypedRegister fn = genExpr(i->op);
|
||||
RegisterList args;
|
||||
ExprPairList *p = i->pairs;
|
||||
while (p) {
|
||||
args.push_back(genExpr(p->value).reg);
|
||||
args.push_back(genExpr(p->value));
|
||||
p = p->next;
|
||||
}
|
||||
ret = call(fn, args);
|
||||
|
@ -559,23 +576,23 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::index :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
}
|
||||
break;
|
||||
case ExprNode::dot :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
break;
|
||||
case ExprNode::identifier :
|
||||
{
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(p))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(p))->name);
|
||||
if (v.first != NotARegister)
|
||||
ret = v;
|
||||
else
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(p))->name);
|
||||
|
@ -595,7 +612,7 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
TypedRegister 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);
|
||||
|
@ -603,8 +620,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v.first != NotARegister)
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
|
@ -621,8 +638,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
|
@ -634,14 +651,14 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = propertyInc(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v.first != NotARegister)
|
||||
ret = varInc(v);
|
||||
else
|
||||
ret = nameInc((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
|
@ -652,8 +669,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = elementInc(base, index);
|
||||
}
|
||||
}
|
||||
|
@ -663,7 +680,7 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
TypedRegister 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);
|
||||
|
@ -671,8 +688,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v.first != NotARegister)
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
|
@ -689,8 +706,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
|
@ -702,14 +719,14 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = propertyDec(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v.first != NotARegister)
|
||||
ret = varDec(v);
|
||||
else
|
||||
ret = nameDec((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
|
@ -720,8 +737,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = elementInc(base, index);
|
||||
}
|
||||
}
|
||||
|
@ -731,7 +748,7 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::complement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
Register r = genExpr(u->op).reg;
|
||||
TypedRegister r = genExpr(u->op);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r);
|
||||
}
|
||||
break;
|
||||
|
@ -748,19 +765,19 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::bitwiseOr:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r1 = genExpr(b->op1);
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
}
|
||||
break;
|
||||
case ExprNode::assignment:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
ret = genExpr(b->op2).reg;
|
||||
ret = genExpr(b->op2);
|
||||
if (b->op1->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v.first != NotARegister)
|
||||
move(v, ret);
|
||||
else
|
||||
saveName((static_cast<IdentifierExprNode *>(b->op1))->name, ret);
|
||||
|
@ -771,14 +788,14 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name, ret);
|
||||
}
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register index = genExpr(lb->op2).reg;
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
TypedRegister index = genExpr(lb->op2);
|
||||
setElement(base, index, ret);
|
||||
}
|
||||
}
|
||||
|
@ -796,11 +813,11 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::bitwiseOrEquals:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
ret = genExpr(b->op2).reg;
|
||||
ret = genExpr(b->op2);
|
||||
if (b->op1->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v != NotARegister) {
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v.first != NotARegister) {
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
move(v, ret);
|
||||
}
|
||||
|
@ -811,7 +828,7 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
}
|
||||
else {
|
||||
Register v = loadName((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
TypedRegister v = loadName((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
saveName((static_cast<IdentifierExprNode *>(b->op1))->name, ret);
|
||||
}
|
||||
|
@ -819,17 +836,17 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register v = getProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name);
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
TypedRegister v = getProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name, ret);
|
||||
}
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register index = genExpr(lb->op2).reg;
|
||||
Register v = getElement(base, index);
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
TypedRegister index = genExpr(lb->op2);
|
||||
TypedRegister v = getElement(base, index);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setElement(base, index, ret);
|
||||
}
|
||||
|
@ -843,8 +860,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::Instanceof:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r1 = genExpr(b->op1);
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -861,8 +878,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::greaterThanOrEqual:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r1 = genExpr(b->op1);
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r2, r1); // will return reverse case
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -880,8 +897,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::notIdentical:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r1 = genExpr(b->op1);
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -907,12 +924,12 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else {
|
||||
Label *fBranch = getLabel();
|
||||
Register r1 = genExpr(b->op1, true, NULL, fBranch).reg;
|
||||
TypedRegister r1 = genExpr(b->op1, true, NULL, fBranch);
|
||||
if (!generatedBoolean(b->op1)) {
|
||||
r1 = test(r1);
|
||||
branchFalse(fBranch, r1);
|
||||
}
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
if (!generatedBoolean(b->op2)) {
|
||||
r2 = test(r2);
|
||||
}
|
||||
|
@ -932,12 +949,12 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else {
|
||||
Label *tBranch = getLabel();
|
||||
Register r1 = genExpr(b->op1, true, tBranch, NULL).reg;
|
||||
TypedRegister r1 = genExpr(b->op1, true, tBranch, NULL);
|
||||
if (!generatedBoolean(b->op1)) {
|
||||
r1 = test(r1);
|
||||
branchTrue(tBranch, r1);
|
||||
}
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
if (!generatedBoolean(b->op2)) {
|
||||
r2 = test(r2);
|
||||
}
|
||||
|
@ -954,13 +971,13 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
TernaryExprNode *t = static_cast<TernaryExprNode *>(p);
|
||||
Label *fBranch = getLabel();
|
||||
Label *beyondBranch = getLabel();
|
||||
Register c = genExpr(t->op1, false, NULL, fBranch).reg;
|
||||
TypedRegister c = genExpr(t->op1, false, NULL, fBranch);
|
||||
if (!generatedBoolean(t->op1))
|
||||
branchFalse(fBranch, test(c));
|
||||
Register r1 = genExpr(t->op2).reg;
|
||||
TypedRegister r1 = genExpr(t->op2);
|
||||
branch(beyondBranch);
|
||||
setLabel(fBranch);
|
||||
Register r2 = genExpr(t->op3).reg;
|
||||
TypedRegister r2 = genExpr(t->op3);
|
||||
if (r1 != r2) // FIXME, need a way to specify a dest???
|
||||
move(r1, r2);
|
||||
setLabel(beyondBranch);
|
||||
|
@ -976,7 +993,7 @@ Result ICodeGenerator::genExpr(ExprNode *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).reg);
|
||||
setProperty(ret, (static_cast<IdentifierExprNode *>(e->field))->name, genExpr(e->value));
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
|
@ -987,7 +1004,7 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
NOT_REACHED("Unsupported ExprNode kind");
|
||||
}
|
||||
}
|
||||
return Result(ret, Any_Type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1110,20 +1127,20 @@ void ICodeGenerator::preprocess(StmtNode *p)
|
|||
}
|
||||
}
|
||||
|
||||
Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
{
|
||||
Register ret = NotARegister;
|
||||
TypedRegister ret(NotARegister, &None_Type);
|
||||
|
||||
startStatement(p->pos);
|
||||
if (exceptionRegister == NotARegister) {
|
||||
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")]);
|
||||
if (exceptionRegister.first == NotARegister) {
|
||||
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
|
||||
}
|
||||
|
||||
switch (p->getKind()) {
|
||||
case StmtNode::Function:
|
||||
{
|
||||
FunctionStmtNode *f = static_cast<FunctionStmtNode *>(p);
|
||||
ICodeGenerator icg(mWorld);
|
||||
ICodeGenerator icg(mWorld, mGlobal);
|
||||
VariableBinding *v = f->function.parameters;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier))
|
||||
|
@ -1146,12 +1163,12 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
if (v->name && v->initializer) {
|
||||
if (v->name->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register r = genExpr(v->name).reg;
|
||||
Register val = genExpr(v->initializer).reg;
|
||||
TypedRegister r = genExpr(v->name);
|
||||
TypedRegister val = genExpr(v->initializer);
|
||||
move(r, val);
|
||||
}
|
||||
else {
|
||||
Register val = genExpr(v->initializer).reg;
|
||||
TypedRegister val = genExpr(v->initializer);
|
||||
saveName((static_cast<IdentifierExprNode *>(v->name))->name, val);
|
||||
}
|
||||
}
|
||||
|
@ -1164,29 +1181,29 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
case StmtNode::expression:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
ret = genExpr(e->expr).reg;
|
||||
ret = genExpr(e->expr);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Throw:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
throwStmt(genExpr(e->expr).reg);
|
||||
throwStmt(genExpr(e->expr));
|
||||
}
|
||||
break;
|
||||
case StmtNode::Return:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
if (e->expr)
|
||||
returnStmt(ret = genExpr(e->expr).reg);
|
||||
returnStmt(ret = genExpr(e->expr));
|
||||
else
|
||||
returnStmt(NotARegister);
|
||||
returnStmt(TypedRegister(NotARegister, &Void_Type));
|
||||
}
|
||||
break;
|
||||
case StmtNode::If:
|
||||
{
|
||||
Label *falseLabel = getLabel();
|
||||
UnaryStmtNode *i = static_cast<UnaryStmtNode *>(p);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel).reg;
|
||||
TypedRegister c = genExpr(i->expr, false, NULL, falseLabel);
|
||||
if (!generatedBoolean(i->expr))
|
||||
branchFalse(falseLabel, test(c));
|
||||
genStmt(i->stmt);
|
||||
|
@ -1198,7 +1215,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
Label *falseLabel = getLabel();
|
||||
Label *beyondLabel = getLabel();
|
||||
BinaryStmtNode *i = static_cast<BinaryStmtNode *>(p);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel).reg;
|
||||
TypedRegister c = genExpr(i->expr, false, NULL, falseLabel);
|
||||
if (!generatedBoolean(i->expr))
|
||||
branchFalse(falseLabel, test(c));
|
||||
genStmt(i->stmt);
|
||||
|
@ -1211,7 +1228,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
case StmtNode::With:
|
||||
{
|
||||
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
|
||||
Register o = genExpr(w->expr).reg;
|
||||
TypedRegister o = genExpr(w->expr);
|
||||
bool withinWith = mWithinWith;
|
||||
mWithinWith = true;
|
||||
beginWith(o);
|
||||
|
@ -1226,7 +1243,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
LabelEntry *e = new LabelEntry(currentLabelSet, getLabel());
|
||||
mLabelStack.push_back(e);
|
||||
SwitchStmtNode *sw = static_cast<SwitchStmtNode *>(p);
|
||||
Register sc = genExpr(sw->expr).reg;
|
||||
TypedRegister sc = genExpr(sw->expr);
|
||||
StmtNode *s = sw->statements;
|
||||
// ECMA requires case & default statements to be immediate children of switch
|
||||
// unlike C where they can be arbitrarily deeply nested in other statements.
|
||||
|
@ -1239,8 +1256,8 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
if (nextCaseLabel)
|
||||
setLabel(nextCaseLabel);
|
||||
nextCaseLabel = getLabel();
|
||||
Register r = genExpr(c->expr).reg;
|
||||
Register eq = op(COMPARE_EQ, r, sc);
|
||||
TypedRegister r = genExpr(c->expr);
|
||||
TypedRegister eq = op(COMPARE_EQ, r, sc);
|
||||
lastBranch = branchFalse(nextCaseLabel, eq);
|
||||
}
|
||||
else {
|
||||
|
@ -1270,7 +1287,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
setLabel(doBodyTopLabel);
|
||||
genStmt(d->stmt);
|
||||
setLabel(e->continueLabel);
|
||||
Register c = genExpr(d->expr, false, doBodyTopLabel, NULL).reg;
|
||||
TypedRegister c = genExpr(d->expr, false, doBodyTopLabel, NULL);
|
||||
if (!generatedBoolean(d->expr))
|
||||
branchTrue(doBodyTopLabel, test(c));
|
||||
setLabel(e->breakLabel);
|
||||
|
@ -1290,7 +1307,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
genStmt(w->stmt);
|
||||
|
||||
setLabel(e->continueLabel);
|
||||
Register c = genExpr(w->expr, false, whileBodyTopLabel, NULL).reg;
|
||||
TypedRegister c = genExpr(w->expr, false, whileBodyTopLabel, NULL);
|
||||
if (!generatedBoolean(w->expr))
|
||||
branchTrue(whileBodyTopLabel, test(c));
|
||||
|
||||
|
@ -1315,11 +1332,11 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
|
||||
setLabel(e->continueLabel);
|
||||
if (f->expr3)
|
||||
genExpr(f->expr3).reg;
|
||||
genExpr(f->expr3);
|
||||
|
||||
setLabel(forTestLabel);
|
||||
if (f->expr2) {
|
||||
Register c = genExpr(f->expr2, false, forBlockTop, NULL).reg;
|
||||
TypedRegister c = genExpr(f->expr2, false, forBlockTop, NULL);
|
||||
if (!generatedBoolean(f->expr2))
|
||||
branchTrue(forBlockTop, test(c));
|
||||
}
|
||||
|
|
|
@ -46,9 +46,9 @@ namespace JavaScript {
|
|||
namespace ICG {
|
||||
|
||||
using namespace VM;
|
||||
using namespace JSTypes;
|
||||
|
||||
|
||||
typedef std::map<String, Register, std::less<String> > VariableList;
|
||||
typedef std::map<String, TypedRegister, std::less<String> > VariableList;
|
||||
typedef std::pair<uint32, uint32> InstructionMapping;
|
||||
typedef std::vector<InstructionMapping *> InstructionMap;
|
||||
|
||||
|
@ -105,12 +105,6 @@ namespace ICG {
|
|||
// function/script, adds statements and expressions to it and then
|
||||
// converts it into an ICodeModule, ready for execution.
|
||||
|
||||
struct Result {
|
||||
Result(Register reg, JSTypes::JSType type) : reg(reg), type(type) {}
|
||||
Register reg;
|
||||
JSTypes::JSType type;
|
||||
};
|
||||
|
||||
class ICodeGenerator {
|
||||
private:
|
||||
InstructionStream *iCode;
|
||||
|
@ -122,10 +116,11 @@ namespace ICG {
|
|||
uint32 maxRegister; // highest (ever) allocated register
|
||||
uint32 parameterCount; // number of parameters declared for the function
|
||||
// these must come before any variables declared.
|
||||
Register exceptionRegister; // reserved to carry the exception object.
|
||||
TypedRegister exceptionRegister;// reserved to carry the exception object.
|
||||
VariableList *variableList; // name|register pair for each variable
|
||||
|
||||
World *mWorld; // used to register strings
|
||||
World *mWorld; // used to register strings
|
||||
JSScope *mGlobal; // the scope for compiling within
|
||||
LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct
|
||||
InstructionMap *mInstructionMap;// maps source position to instruction index
|
||||
|
||||
|
@ -146,15 +141,15 @@ namespace ICG {
|
|||
void jsr(Label *label) { iCode->push_back(new Jsr(label)); }
|
||||
void rts() { iCode->push_back(new Rts()); }
|
||||
void branch(Label *label);
|
||||
GenericBranch *branchTrue(Label *label, Register condition);
|
||||
GenericBranch *branchFalse(Label *label, Register condition);
|
||||
GenericBranch *branchTrue(Label *label, TypedRegister condition);
|
||||
GenericBranch *branchFalse(Label *label, TypedRegister condition);
|
||||
|
||||
void beginTry(Label *catchLabel, Label *finallyLabel)
|
||||
{ iCode->push_back(new Tryin(catchLabel, finallyLabel)); }
|
||||
void endTry()
|
||||
{ iCode->push_back(new Tryout()); }
|
||||
|
||||
void beginWith(Register obj)
|
||||
void beginWith(TypedRegister obj)
|
||||
{ iCode->push_back(new Within(obj)); }
|
||||
void endWith()
|
||||
{ iCode->push_back(new Without()); }
|
||||
|
@ -164,7 +159,7 @@ namespace ICG {
|
|||
|
||||
void resetStatement() { resetTopRegister(); }
|
||||
|
||||
void setRegisterForVariable(const StringAtom& name, Register r)
|
||||
void setRegisterForVariable(const StringAtom& name, TypedRegister r)
|
||||
{ (*variableList)[name] = r; }
|
||||
|
||||
|
||||
|
@ -172,16 +167,18 @@ namespace ICG {
|
|||
|
||||
ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind);
|
||||
|
||||
Register grabRegister(const StringAtom& name)
|
||||
TypedRegister grabRegister(const StringAtom& name, const JSType *type)
|
||||
{
|
||||
Register result = getRegister();
|
||||
TypedRegister result(getRegister(), type);
|
||||
(*variableList)[name] = result;
|
||||
registerBase = topRegister;
|
||||
return result;
|
||||
}
|
||||
|
||||
const JSType *findType(const StringAtom& typeName);
|
||||
|
||||
public:
|
||||
ICodeGenerator(World *world = NULL);
|
||||
ICodeGenerator(World *world, JSScope *global);
|
||||
|
||||
~ICodeGenerator()
|
||||
{
|
||||
|
@ -193,65 +190,66 @@ namespace ICG {
|
|||
|
||||
ICodeModule *complete();
|
||||
|
||||
Result genExpr(ExprNode *p,
|
||||
TypedRegister genExpr(ExprNode *p,
|
||||
bool needBoolValueInBranch = false,
|
||||
Label *trueBranch = NULL,
|
||||
Label *falseBranch = NULL);
|
||||
void preprocess(StmtNode *p);
|
||||
Register genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL);
|
||||
TypedRegister genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL);
|
||||
|
||||
void isScript() { mWithinWith = true; }
|
||||
|
||||
void returnStmt(Register r);
|
||||
void throwStmt(Register r)
|
||||
void returnStmt(TypedRegister r);
|
||||
void throwStmt(TypedRegister r)
|
||||
{ iCode->push_back(new Throw(r)); }
|
||||
|
||||
Register allocateVariable(const StringAtom& name);
|
||||
Register allocateVariable(const StringAtom& name, const StringAtom& /*type */)
|
||||
{ return allocateVariable(name); }
|
||||
TypedRegister allocateVariable(const StringAtom& name);
|
||||
TypedRegister allocateVariable(const StringAtom& name, const StringAtom& typeName);
|
||||
|
||||
Register findVariable(const StringAtom& name)
|
||||
TypedRegister findVariable(const StringAtom& name)
|
||||
{ VariableList::iterator i = variableList->find(name);
|
||||
return (i == variableList->end()) ? NotARegister : (*i).second; }
|
||||
return (i == variableList->end()) ? TypedRegister(NotARegister, &None_Type) : (*i).second; }
|
||||
|
||||
Register allocateParameter(const StringAtom& name)
|
||||
{ parameterCount++; return grabRegister(name); }
|
||||
TypedRegister allocateParameter(const StringAtom& name)
|
||||
{ parameterCount++; return grabRegister(name, &Any_Type); }
|
||||
TypedRegister allocateParameter(const StringAtom& name, const StringAtom& typeName)
|
||||
{ parameterCount++; return grabRegister(name, findType(typeName)); }
|
||||
|
||||
Formatter& print(Formatter& f);
|
||||
|
||||
Register op(ICodeOp op, Register source);
|
||||
Register op(ICodeOp op, Register source1, Register source2);
|
||||
Register call(Register target, RegisterList args);
|
||||
void callVoid(Register target, RegisterList args);
|
||||
TypedRegister op(ICodeOp op, TypedRegister source);
|
||||
TypedRegister op(ICodeOp op, TypedRegister source1, TypedRegister source2);
|
||||
TypedRegister call(TypedRegister target, RegisterList args);
|
||||
void callVoid(TypedRegister target, RegisterList args);
|
||||
|
||||
void move(Register destination, Register source);
|
||||
Register logicalNot(Register source);
|
||||
Register test(Register source);
|
||||
void move(TypedRegister destination, TypedRegister source);
|
||||
TypedRegister logicalNot(TypedRegister source);
|
||||
TypedRegister test(TypedRegister source);
|
||||
|
||||
Register loadValue(JSValue value);
|
||||
Register loadImmediate(double value);
|
||||
Register loadString(String &value);
|
||||
TypedRegister loadBoolean(bool value);
|
||||
TypedRegister loadImmediate(double value);
|
||||
TypedRegister loadString(String &value);
|
||||
|
||||
Register newObject();
|
||||
Register newArray();
|
||||
TypedRegister newObject();
|
||||
TypedRegister newArray();
|
||||
|
||||
Register loadName(const StringAtom &name);
|
||||
void saveName(const StringAtom &name, Register value);
|
||||
Register nameInc(const StringAtom &name);
|
||||
Register nameDec(const StringAtom &name);
|
||||
TypedRegister loadName(const StringAtom &name);
|
||||
void saveName(const StringAtom &name, TypedRegister value);
|
||||
TypedRegister nameInc(const StringAtom &name);
|
||||
TypedRegister 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);
|
||||
Register propertyDec(Register base, const StringAtom &name);
|
||||
TypedRegister getProperty(TypedRegister base, const StringAtom &name);
|
||||
void setProperty(TypedRegister base, const StringAtom &name, TypedRegister value);
|
||||
TypedRegister propertyInc(TypedRegister base, const StringAtom &name);
|
||||
TypedRegister propertyDec(TypedRegister base, const StringAtom &name);
|
||||
|
||||
Register getElement(Register base, Register index);
|
||||
void setElement(Register base, Register index, Register value);
|
||||
Register elementInc(Register base, Register index);
|
||||
Register elementDec(Register base, Register index);
|
||||
TypedRegister getElement(TypedRegister base, TypedRegister index);
|
||||
void setElement(TypedRegister base, TypedRegister index, TypedRegister value);
|
||||
TypedRegister elementInc(TypedRegister base, TypedRegister index);
|
||||
TypedRegister elementDec(TypedRegister base, TypedRegister index);
|
||||
|
||||
Register varInc(Register var);
|
||||
Register varDec(Register var);
|
||||
TypedRegister varInc(TypedRegister var);
|
||||
TypedRegister varDec(TypedRegister var);
|
||||
|
||||
Register getRegisterBase() { return topRegister; }
|
||||
InstructionStream *get_iCode() { return iCode; }
|
||||
|
|
|
@ -98,7 +98,7 @@ struct Activation : public gc_base {
|
|||
const JSValues& params = caller->mRegisters;
|
||||
for (RegisterList::const_iterator src = list.begin(),
|
||||
end = list.end(); src != end; ++src, ++dest) {
|
||||
*dest = params[*src];
|
||||
*dest = params[(*src).first];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,10 +128,10 @@ struct Linkage : public Context::Frame, public gc_base {
|
|||
Linkage* mNext; // next linkage in linkage stack.
|
||||
InstructionIterator mReturnPC;
|
||||
Activation* mActivation; // caller's activation.
|
||||
Register mResult; // the desired target register for the return value
|
||||
TypedRegister mResult; // the desired target register for the return value
|
||||
|
||||
Linkage(Linkage* linkage, InstructionIterator returnPC,
|
||||
Activation* activation, Register result)
|
||||
Activation* activation, TypedRegister result)
|
||||
: mNext(linkage), mReturnPC(returnPC),
|
||||
mActivation(activation), mResult(result)
|
||||
{
|
||||
|
@ -146,31 +146,6 @@ void getState(InstructionIterator& pc, JSValues*& registers, ICodeModule*& iCode
|
|||
iCode = mActivation->mICode;
|
||||
}
|
||||
};
|
||||
/*
|
||||
void Context::doCall(JSFunction *target, Instruction *pc)
|
||||
{
|
||||
if (target->isNative()) {
|
||||
RegisterList ¶ms = op3(call);
|
||||
JSValues argv(params.size());
|
||||
JSValues::size_type i = 0;
|
||||
for (RegisterList::const_iterator src = params.begin(), end = params.end();
|
||||
src != end; ++src, ++i) {
|
||||
argv[i] = (*registers)[*src];
|
||||
}
|
||||
if (op2(call) != NotARegister)
|
||||
(*registers)[op2(call)] = static_cast<JSNativeFunction*>(target)->mCode(argv);
|
||||
return pc;
|
||||
}
|
||||
else {
|
||||
mLinkage = new Linkage(mLinkage, ++mPC,
|
||||
mActivation, op1(call));
|
||||
iCode = target->getICode();
|
||||
mActivation = new Activation(iCode, mActivation, op3(call));
|
||||
registers = &mActivation->mRegisters;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static JSValue shiftLeft_Default(const JSValue& r1, const JSValue& r2)
|
||||
{
|
||||
|
@ -517,17 +492,17 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
case CALL:
|
||||
{
|
||||
Call* call = static_cast<Call*>(instruction);
|
||||
JSFunction *target = (*registers)[op2(call)].function;
|
||||
JSFunction *target = (*registers)[op2(call).first].function;
|
||||
if (target->isNative()) {
|
||||
RegisterList ¶ms = op3(call);
|
||||
JSValues argv(params.size());
|
||||
JSValues::size_type i = 0;
|
||||
for (RegisterList::const_iterator src = params.begin(), end = params.end();
|
||||
src != end; ++src, ++i) {
|
||||
argv[i] = (*registers)[*src];
|
||||
argv[i] = (*registers)[src->first];
|
||||
}
|
||||
if (op2(call) != NotARegister)
|
||||
(*registers)[op2(call)] = static_cast<JSNativeFunction*>(target)->mCode(argv);
|
||||
if (op2(call).first != NotARegister)
|
||||
(*registers)[op2(call).first] = static_cast<JSNativeFunction*>(target)->mCode(argv);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
@ -553,7 +528,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
mLinkage = linkage->mNext;
|
||||
mActivation = linkage->mActivation;
|
||||
registers = &mActivation->mRegisters;
|
||||
(*registers)[linkage->mResult] = result;
|
||||
(*registers)[linkage->mResult.first] = result;
|
||||
mPC = linkage->mReturnPC;
|
||||
}
|
||||
continue;
|
||||
|
@ -562,8 +537,8 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
{
|
||||
Return* ret = static_cast<Return*>(instruction);
|
||||
JSValue result;
|
||||
if (op1(ret) != NotARegister)
|
||||
result = (*registers)[op1(ret)];
|
||||
if (op1(ret).first != NotARegister)
|
||||
result = (*registers)[op1(ret).first];
|
||||
Linkage* linkage = mLinkage;
|
||||
if (!linkage)
|
||||
{
|
||||
|
@ -574,57 +549,57 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
mLinkage = linkage->mNext;
|
||||
mActivation = linkage->mActivation;
|
||||
registers = &mActivation->mRegisters;
|
||||
(*registers)[linkage->mResult] = result;
|
||||
(*registers)[linkage->mResult.first] = result;
|
||||
mPC = linkage->mReturnPC;
|
||||
}
|
||||
continue;
|
||||
case MOVE:
|
||||
{
|
||||
Move* mov = static_cast<Move*>(instruction);
|
||||
(*registers)[dst(mov)] = (*registers)[src1(mov)];
|
||||
(*registers)[dst(mov).first] = (*registers)[src1(mov).first];
|
||||
}
|
||||
break;
|
||||
case LOAD_NAME:
|
||||
{
|
||||
LoadName* ln = static_cast<LoadName*>(instruction);
|
||||
(*registers)[dst(ln)] = mGlobal->getVariable(*src1(ln));
|
||||
(*registers)[dst(ln).first] = mGlobal->getVariable(*src1(ln));
|
||||
}
|
||||
break;
|
||||
case SAVE_NAME:
|
||||
{
|
||||
SaveName* sn = static_cast<SaveName*>(instruction);
|
||||
mGlobal->setVariable(*dst(sn), (*registers)[src1(sn)]);
|
||||
mGlobal->setVariable(*dst(sn), (*registers)[src1(sn).first]);
|
||||
}
|
||||
break;
|
||||
case NEW_OBJECT:
|
||||
{
|
||||
NewObject* no = static_cast<NewObject*>(instruction);
|
||||
(*registers)[dst(no)] = JSValue(new JSObject());
|
||||
(*registers)[dst(no).first] = JSValue(new JSObject());
|
||||
}
|
||||
break;
|
||||
case NEW_ARRAY:
|
||||
{
|
||||
NewArray* na = static_cast<NewArray*>(instruction);
|
||||
(*registers)[dst(na)] = JSValue(new JSArray());
|
||||
(*registers)[dst(na).first] = JSValue(new JSArray());
|
||||
}
|
||||
break;
|
||||
case GET_PROP:
|
||||
{
|
||||
GetProp* gp = static_cast<GetProp*>(instruction);
|
||||
JSValue& value = (*registers)[src1(gp)];
|
||||
JSValue& value = (*registers)[src1(gp).first];
|
||||
if (value.tag == JSValue::object_tag) {
|
||||
JSObject* object = value.object;
|
||||
(*registers)[dst(gp)] = object->getProperty(*src2(gp));
|
||||
(*registers)[dst(gp).first] = object->getProperty(*src2(gp));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SET_PROP:
|
||||
{
|
||||
SetProp* sp = static_cast<SetProp*>(instruction);
|
||||
JSValue& value = (*registers)[dst(sp)];
|
||||
JSValue& value = (*registers)[dst(sp).first];
|
||||
if (value.tag == JSValue::object_tag) {
|
||||
JSObject* object = value.object;
|
||||
object->setProperty(*src1(sp), (*registers)[src2(sp)]);
|
||||
object->setProperty(*src1(sp), (*registers)[src2(sp).first]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -647,20 +622,20 @@ using JSString throughout.
|
|||
case GET_ELEMENT:
|
||||
{
|
||||
GetElement* ge = static_cast<GetElement*>(instruction);
|
||||
JSValue& value = (*registers)[src1(ge)];
|
||||
JSValue& value = (*registers)[src1(ge).first];
|
||||
if (value.tag == JSValue::array_tag) {
|
||||
JSArray* array = value.array;
|
||||
(*registers)[dst(ge)] = (*array)[(*registers)[src2(ge)]];
|
||||
(*registers)[dst(ge).first] = (*array)[(*registers)[src2(ge).first]];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SET_ELEMENT:
|
||||
{
|
||||
SetElement* se = static_cast<SetElement*>(instruction);
|
||||
JSValue& value = (*registers)[dst(se)];
|
||||
JSValue& value = (*registers)[dst(se).first];
|
||||
if (value.tag == JSValue::array_tag) {
|
||||
JSArray* array = value.array;
|
||||
(*array)[(*registers)[src1(se)]] = (*registers)[src2(se)];
|
||||
(*array)[(*registers)[src1(se).first]] = (*registers)[src2(se).first];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -668,19 +643,19 @@ using JSString throughout.
|
|||
case LOAD_IMMEDIATE:
|
||||
{
|
||||
LoadImmediate* li = static_cast<LoadImmediate*>(instruction);
|
||||
(*registers)[dst(li)] = JSValue(src1(li));
|
||||
(*registers)[dst(li).first] = JSValue(src1(li));
|
||||
}
|
||||
break;
|
||||
case LOAD_STRING:
|
||||
{
|
||||
LoadString* ls = static_cast<LoadString*>(instruction);
|
||||
(*registers)[dst(ls)] = JSValue(src1(ls));
|
||||
(*registers)[dst(ls).first] = JSValue(src1(ls));
|
||||
}
|
||||
break;
|
||||
case LOAD_VALUE:
|
||||
case LOAD_BOOLEAN:
|
||||
{
|
||||
LoadValue* lv = static_cast<LoadValue*>(instruction);
|
||||
(*registers)[dst(lv)] = src1(lv);
|
||||
LoadBoolean* lb = static_cast<LoadBoolean*>(instruction);
|
||||
(*registers)[dst(lb).first] = JSValue(src1(lb));
|
||||
}
|
||||
break;
|
||||
case BRANCH:
|
||||
|
@ -695,8 +670,8 @@ using JSString throughout.
|
|||
{
|
||||
GenericBranch* bc =
|
||||
static_cast<GenericBranch*>(instruction);
|
||||
ASSERT((*registers)[src1(bc)].isBoolean());
|
||||
if ((*registers)[src1(bc)].boolean) {
|
||||
ASSERT((*registers)[src1(bc).first].isBoolean());
|
||||
if ((*registers)[src1(bc).first].boolean) {
|
||||
mPC = mActivation->mICode->its_iCode->begin() + ofs(bc);
|
||||
continue;
|
||||
}
|
||||
|
@ -706,8 +681,8 @@ using JSString throughout.
|
|||
{
|
||||
GenericBranch* bc =
|
||||
static_cast<GenericBranch*>(instruction);
|
||||
ASSERT((*registers)[src1(bc)].isBoolean());
|
||||
if (!(*registers)[src1(bc)].boolean) {
|
||||
ASSERT((*registers)[src1(bc).first].isBoolean());
|
||||
if (!(*registers)[src1(bc).first].boolean) {
|
||||
mPC = mActivation->mICode->its_iCode->begin() + ofs(bc);
|
||||
continue;
|
||||
}
|
||||
|
@ -730,9 +705,9 @@ using JSString throughout.
|
|||
case STRICT_EQ:
|
||||
{
|
||||
Arithmetic* mul = static_cast<Arithmetic*>(instruction);
|
||||
JSValue& dest = (*registers)[dst(mul)];
|
||||
JSValue& r1 = (*registers)[src1(mul)];
|
||||
JSValue& r2 = (*registers)[src2(mul)];
|
||||
JSValue& dest = (*registers)[dst(mul).first];
|
||||
JSValue& r1 = (*registers)[src1(mul).first];
|
||||
JSValue& r2 = (*registers)[src2(mul).first];
|
||||
const JSValue ovr = findBinaryOverride(r1, r2, BinaryOperator::mapICodeOp(instruction->op()));
|
||||
JSFunction *target = ovr.function;
|
||||
if (target->isNative()) {
|
||||
|
@ -756,19 +731,19 @@ using JSString throughout.
|
|||
case VAR_XCR:
|
||||
{
|
||||
VarXcr *vx = static_cast<VarXcr*>(instruction);
|
||||
JSValue& dest = (*registers)[dst(vx)];
|
||||
JSValue r = (*registers)[src1(vx)].toNumber();
|
||||
JSValue& dest = (*registers)[dst(vx).first];
|
||||
JSValue r = (*registers)[src1(vx).first].toNumber();
|
||||
dest = r;
|
||||
r.f64 += val3(vx);
|
||||
(*registers)[src1(vx)] = r;
|
||||
(*registers)[src1(vx).first] = r;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_XCR:
|
||||
{
|
||||
PropXcr *px = static_cast<PropXcr*>(instruction);
|
||||
JSValue& dest = (*registers)[dst(px)];
|
||||
JSValue& base = (*registers)[src1(px)];
|
||||
JSValue& dest = (*registers)[dst(px).first];
|
||||
JSValue& base = (*registers)[src1(px).first];
|
||||
JSObject *object = base.object;
|
||||
JSValue r = object->getProperty(*src2(px)).toNumber();
|
||||
dest = r;
|
||||
|
@ -780,7 +755,7 @@ using JSString throughout.
|
|||
case NAME_XCR:
|
||||
{
|
||||
NameXcr *nx = static_cast<NameXcr*>(instruction);
|
||||
JSValue& dest = (*registers)[dst(nx)];
|
||||
JSValue& dest = (*registers)[dst(nx).first];
|
||||
JSValue r = mGlobal->getVariable(*src1(nx)).toNumber();
|
||||
dest = r;
|
||||
r.f64 += val3(nx);
|
||||
|
@ -791,38 +766,38 @@ using JSString throughout.
|
|||
case TEST:
|
||||
{
|
||||
Test* tst = static_cast<Test*>(instruction);
|
||||
(*registers)[dst(tst)] = (*registers)[src1(tst)].toBoolean();
|
||||
(*registers)[dst(tst).first] = (*registers)[src1(tst).first].toBoolean();
|
||||
}
|
||||
break;
|
||||
case NEGATE:
|
||||
{
|
||||
Negate* neg = static_cast<Negate*>(instruction);
|
||||
(*registers)[dst(neg)] = JSValue(-(*registers)[src1(neg)].toNumber().f64);
|
||||
(*registers)[dst(neg).first] = JSValue(-(*registers)[src1(neg).first].toNumber().f64);
|
||||
}
|
||||
break;
|
||||
case POSATE:
|
||||
{
|
||||
Posate* pos = static_cast<Posate*>(instruction);
|
||||
(*registers)[dst(pos)] = (*registers)[src1(pos)].toNumber();
|
||||
(*registers)[dst(pos).first] = (*registers)[src1(pos).first].toNumber();
|
||||
}
|
||||
break;
|
||||
case BITNOT:
|
||||
{
|
||||
Bitnot* bn = static_cast<Bitnot*>(instruction);
|
||||
(*registers)[dst(bn)] = JSValue(~(*registers)[src1(bn)].toInt32().i32);
|
||||
(*registers)[dst(bn).first] = JSValue(~(*registers)[src1(bn).first].toInt32().i32);
|
||||
}
|
||||
break;
|
||||
case NOT:
|
||||
{
|
||||
Not* nt = static_cast<Not*>(instruction);
|
||||
ASSERT((*registers)[src1(nt)].isBoolean());
|
||||
(*registers)[dst(nt)] = JSValue(!(*registers)[src1(nt)].boolean);
|
||||
ASSERT((*registers)[src1(nt).first].isBoolean());
|
||||
(*registers)[dst(nt).first] = JSValue(!(*registers)[src1(nt).first].boolean);
|
||||
}
|
||||
break;
|
||||
case THROW:
|
||||
{
|
||||
Throw* thrw = static_cast<Throw*>(instruction);
|
||||
throw new JSException((*registers)[op1(thrw)]);
|
||||
throw new JSException((*registers)[op1(thrw).first]);
|
||||
}
|
||||
|
||||
case TRYIN:
|
||||
|
@ -857,7 +832,7 @@ using JSString throughout.
|
|||
case WITHIN:
|
||||
{
|
||||
Within* within = static_cast<Within*>(instruction);
|
||||
JSValue& value = (*registers)[op1(within)];
|
||||
JSValue& value = (*registers)[op1(within).first];
|
||||
assert(value.tag == JSValue::object_tag);
|
||||
mGlobal = new JSScope(mGlobal, value.object);
|
||||
}
|
||||
|
|
|
@ -101,9 +101,10 @@ static JSValue print(const JSValues &argv)
|
|||
|
||||
static void genCode(World &world, Context &cx, StmtNode *p)
|
||||
{
|
||||
ICodeGenerator icg(&world);
|
||||
JSScope glob;
|
||||
ICodeGenerator icg(&world, &glob);
|
||||
icg.isScript();
|
||||
Register ret = NotARegister;
|
||||
TypedRegister ret(NotARegister, &None_Type);
|
||||
while (p) {
|
||||
ret = icg.genStmt(p);
|
||||
p = p->next;
|
||||
|
@ -210,86 +211,6 @@ class Tracer : public Context::Listener {
|
|||
};
|
||||
|
||||
|
||||
static float64 testFactorial(World &world, float64 n)
|
||||
{
|
||||
JSScope glob;
|
||||
Context cx(world, &glob);
|
||||
// generate code for factorial, and interpret it.
|
||||
uint32 pos = 0;
|
||||
ICodeGenerator icg(&world);
|
||||
|
||||
// fact(n) {
|
||||
// var result = 1;
|
||||
|
||||
StringAtom &n_name = world.identifiers[widenCString("n")];
|
||||
StringAtom &result_name = world.identifiers[widenCString("result")];
|
||||
|
||||
Register r_n = icg.allocateParameter(n_name);
|
||||
Register r_result = icg.allocateVariable(result_name);
|
||||
|
||||
Arena a;
|
||||
|
||||
ExprStmtNode *e = new(a) ExprStmtNode(pos, StmtNode::expression, new(a) BinaryExprNode(pos, ExprNode::assignment,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, result_name),
|
||||
new(a) NumberExprNode(pos, 1.0) ) );
|
||||
icg.genStmt(e);
|
||||
|
||||
// while (n > 1) {
|
||||
// result = result * n;
|
||||
// n = n - 1;
|
||||
// }
|
||||
{
|
||||
BinaryExprNode *c = new(a) BinaryExprNode(pos, ExprNode::greaterThan,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, n_name),
|
||||
new(a) NumberExprNode(pos, 1.0) ) ;
|
||||
ExprStmtNode *e1 = new(a) ExprStmtNode(pos, StmtNode::expression, new(a) BinaryExprNode(pos, ExprNode::assignment,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, result_name),
|
||||
new(a) BinaryExprNode(pos, ExprNode::multiply,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, result_name),
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, n_name) ) ) );
|
||||
ExprStmtNode *e2 = new(a) ExprStmtNode(pos, StmtNode::expression, new(a) BinaryExprNode(pos, ExprNode::assignment,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, n_name),
|
||||
new(a) BinaryExprNode(pos, ExprNode::subtract,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, n_name),
|
||||
new(a) NumberExprNode(pos, 1.0) ) ) );
|
||||
e1->next = e2;
|
||||
BlockStmtNode *b = new(a) BlockStmtNode(pos, StmtNode::block, NULL, e1);
|
||||
|
||||
UnaryStmtNode *w = new(a) UnaryStmtNode(pos, StmtNode::While, c, b);
|
||||
|
||||
icg.genStmt(w);
|
||||
|
||||
}
|
||||
|
||||
// return result;
|
||||
icg.returnStmt(r_result);
|
||||
ICodeModule *icm = icg.complete();
|
||||
stdOut << icg;
|
||||
|
||||
// preset the global property "fact" to contain the above function
|
||||
StringAtom& fact = world.identifiers[widenCString("fact")];
|
||||
glob.defineFunction(fact, icm);
|
||||
|
||||
// now a script :
|
||||
// return fact(n);
|
||||
ICodeGenerator script(&world);
|
||||
RegisterList args(1);
|
||||
args[0] = script.loadImmediate(n);
|
||||
script.returnStmt(script.call(script.loadName(fact), args));
|
||||
stdOut << script;
|
||||
|
||||
// install a listener so we can trace execution of factorial.
|
||||
Tracer t;
|
||||
cx.addListener(&t);
|
||||
|
||||
// test the iCode interpreter.
|
||||
JSValue result = cx.interpret(script.complete(), JSValues());
|
||||
stdOut << "fact(" << n << ") = " << result.f64 << "\n";
|
||||
|
||||
delete icm;
|
||||
|
||||
return result.f64;
|
||||
}
|
||||
|
||||
char * tests[] = {
|
||||
"function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" ,
|
||||
|
@ -308,8 +229,8 @@ void testCompile()
|
|||
Arena a;
|
||||
Parser p(world, a, testScript, widenCString("testCompile"));
|
||||
StmtNode *parsedStatements = p.parseProgram();
|
||||
|
||||
ICodeGenerator icg(&world);
|
||||
JSScope glob;
|
||||
ICodeGenerator icg(&world, &glob);
|
||||
icg.isScript();
|
||||
while (parsedStatements) {
|
||||
icg.genStmt(parsedStatements);
|
||||
|
@ -333,7 +254,6 @@ int main(int argc, char **argv)
|
|||
using namespace JavaScript;
|
||||
using namespace Shell;
|
||||
#if 0
|
||||
assert(testFactorial(world, 5) == 120);
|
||||
testCompile();
|
||||
#endif
|
||||
readEvalPrint(stdin, world);
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
namespace JavaScript {
|
||||
namespace VM {
|
||||
|
||||
using namespace JSTypes;
|
||||
|
||||
Formatter& operator<< (Formatter& f, Instruction& i)
|
||||
{
|
||||
|
@ -44,11 +46,11 @@ namespace VM {
|
|||
|
||||
Formatter& operator<< (Formatter& f, RegisterList& rl)
|
||||
{
|
||||
Register* e = rl.end();
|
||||
TypedRegister* e = rl.end();
|
||||
|
||||
f << "(";
|
||||
for (RegisterList::iterator r = rl.begin(); r != e; r++) {
|
||||
f << "R" << (*r);
|
||||
f << "R" << r->first;
|
||||
if ((r + 1) != e)
|
||||
f << ", ";
|
||||
}
|
||||
|
@ -64,11 +66,11 @@ namespace VM {
|
|||
f << "(";
|
||||
RegisterList::const_iterator i = rl.begin(), e = rl.end();
|
||||
if (i != e) {
|
||||
Register r = *i++;
|
||||
f << "R" << r << '=' << registers[r];
|
||||
TypedRegister r = *i++;
|
||||
f << "R" << r.first << '=' << registers[r.first];
|
||||
while (i != e) {
|
||||
r = *i++;
|
||||
f << ", R" << r << '=' << registers[r];
|
||||
f << ", R" << r.first << '=' << registers[r.first];
|
||||
}
|
||||
}
|
||||
f << ")";
|
||||
|
|
433
js/js2/vmtypes.h
433
js/js2/vmtypes.h
|
@ -49,9 +49,7 @@ namespace ICG {
|
|||
namespace JavaScript {
|
||||
namespace VM {
|
||||
|
||||
using JSTypes::JSValue;
|
||||
using JSTypes::JSValues;
|
||||
using JSTypes::JSString;
|
||||
using namespace JSTypes;
|
||||
|
||||
enum ICodeOp {
|
||||
ADD, /* dest, source1, source2 */
|
||||
|
@ -75,10 +73,10 @@ namespace VM {
|
|||
GET_PROP, /* dest, object, prop name */
|
||||
INSTANCEOF, /* dest, source1, source2 */
|
||||
JSR, /* target */
|
||||
LOAD_BOOLEAN, /* dest, immediate value (boolean) */
|
||||
LOAD_IMMEDIATE, /* dest, immediate value (double) */
|
||||
LOAD_NAME, /* dest, name */
|
||||
LOAD_STRING, /* dest, immediate value (string) */
|
||||
LOAD_VALUE, /* dest, immediate value (JSValue) */
|
||||
MOVE, /* dest, source */
|
||||
MULTIPLY, /* dest, source1, source2 */
|
||||
NAME_XCR, /* dest, name, value */
|
||||
|
@ -113,8 +111,6 @@ namespace VM {
|
|||
XOR, /* dest, source1, source2 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
static char *opcodeNames[] = {
|
||||
|
@ -139,10 +135,10 @@ namespace VM {
|
|||
"GET_PROP ",
|
||||
"INSTANCEOF ",
|
||||
"JSR ",
|
||||
"LOAD_BOOLEAN ",
|
||||
"LOAD_IMMEDIATE",
|
||||
"LOAD_NAME ",
|
||||
"LOAD_STRING ",
|
||||
"LOAD_VALUE ",
|
||||
"MOVE ",
|
||||
"MULTIPLY ",
|
||||
"NAME_XCR ",
|
||||
|
@ -233,10 +229,12 @@ namespace VM {
|
|||
/********************************************************************/
|
||||
|
||||
typedef uint32 Register;
|
||||
typedef std::vector<Register> RegisterList;
|
||||
typedef std::pair<Register, const JSType*> TypedRegister;
|
||||
typedef std::vector<TypedRegister> RegisterList;
|
||||
typedef std::vector<Instruction *> InstructionStream;
|
||||
typedef InstructionStream::iterator InstructionIterator;
|
||||
typedef std::map<String, Register, std::less<String> > VariableMap;
|
||||
typedef std::map<String, TypedRegister, std::less<String> > VariableMap;
|
||||
|
||||
|
||||
/**
|
||||
* Helper to print Call operands.
|
||||
|
@ -343,60 +341,59 @@ namespace VM {
|
|||
|
||||
/* Instruction groups */
|
||||
|
||||
class Arithmetic : public Instruction_3<Register, Register, Register> {
|
||||
class Arithmetic : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
Arithmetic (ICodeOp aOpcode, Register aDest, Register aSrc1,
|
||||
Register aSrc2) :
|
||||
Instruction_3<Register, Register, Register>(aOpcode, aDest, aSrc1,
|
||||
aSrc2) {}
|
||||
Arithmetic (ICodeOp aOpcode, TypedRegister aDest, TypedRegister aSrc1,
|
||||
TypedRegister aSrc2) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>(aOpcode, aDest, aSrc1, aSrc2) {}
|
||||
virtual Formatter& print(Formatter& f)
|
||||
{
|
||||
f << opcodeNames[mOpcode] << "\tR" << mOp1 << ", R" << mOp2 << ", R" << mOp3;
|
||||
f << opcodeNames[mOpcode] << "\tR" << mOp1.first << ", R" << mOp2.first << ", R" << mOp3.first;
|
||||
return f;
|
||||
}
|
||||
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers)
|
||||
{
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2] << ", " << "R" << mOp3 << '=' << registers[mOp3];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Unary : public Instruction_2<Register, Register> {
|
||||
class Unary : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
Unary(ICodeOp aOpcode, Register aDest, Register aSrc) :
|
||||
Instruction_2<Register, Register>(aOpcode, aDest, aSrc) {}
|
||||
Unary(ICodeOp aOpcode, TypedRegister aDest, TypedRegister aSrc) :
|
||||
Instruction_2<TypedRegister, TypedRegister>(aOpcode, aDest, aSrc) {}
|
||||
virtual Formatter& print (Formatter& f) {
|
||||
f << opcodeNames[mOpcode] << "\tR" << mOp1 << ", R" << mOp2;
|
||||
f << opcodeNames[mOpcode] << "\tR" << mOp1.first << ", R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers)
|
||||
{
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class GenericBranch : public Instruction_2<Label*, Register> {
|
||||
class GenericBranch : public Instruction_2<Label*, TypedRegister> {
|
||||
public:
|
||||
GenericBranch (ICodeOp aOpcode, Label* aLabel,
|
||||
Register aR = NotARegister) :
|
||||
Instruction_2<Label*, Register>(aOpcode, aLabel, aR) {}
|
||||
TypedRegister aR = TypedRegister(NotARegister, &Any_Type) ) :
|
||||
Instruction_2<Label*, TypedRegister>(aOpcode, aLabel, aR) {}
|
||||
virtual Formatter& print (Formatter& f) {
|
||||
f << opcodeNames[mOpcode] << "\tOffset " << mOp1->mOffset;
|
||||
if (mOp2 == NotARegister) {
|
||||
if (mOp2.first == NotARegister) {
|
||||
f << ", R~";
|
||||
} else {
|
||||
f << ", R" << mOp2;
|
||||
f << ", R" << mOp2.first;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers)
|
||||
{
|
||||
if (mOp2 != NotARegister)
|
||||
f << "R" << mOp2 << '=' << registers[mOp2];
|
||||
if (mOp2.first != NotARegister)
|
||||
f << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
|
||||
|
@ -411,7 +408,7 @@ namespace VM {
|
|||
class Add : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Add (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Add (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(ADD, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
|
@ -420,24 +417,24 @@ namespace VM {
|
|||
class And : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
And (Register aOp1, Register aOp2, Register aOp3) :
|
||||
And (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(AND, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class Bitnot : public Instruction_2<Register, Register> {
|
||||
class Bitnot : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Bitnot (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Bitnot (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(BITNOT, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[BITNOT] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[BITNOT] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -460,7 +457,7 @@ namespace VM {
|
|||
class BranchFalse : public GenericBranch {
|
||||
public:
|
||||
/* target label, condition */
|
||||
BranchFalse (Label* aOp1, Register aOp2) :
|
||||
BranchFalse (Label* aOp1, TypedRegister aOp2) :
|
||||
GenericBranch
|
||||
(BRANCH_FALSE, aOp1, aOp2) {};
|
||||
/* print() and printOperands() inherited from GenericBranch */
|
||||
|
@ -469,155 +466,155 @@ namespace VM {
|
|||
class BranchTrue : public GenericBranch {
|
||||
public:
|
||||
/* target label, condition */
|
||||
BranchTrue (Label* aOp1, Register aOp2) :
|
||||
BranchTrue (Label* aOp1, TypedRegister aOp2) :
|
||||
GenericBranch
|
||||
(BRANCH_TRUE, aOp1, aOp2) {};
|
||||
/* print() and printOperands() inherited from GenericBranch */
|
||||
};
|
||||
|
||||
class Call : public Instruction_3<Register, Register, RegisterList> {
|
||||
class Call : public Instruction_3<TypedRegister, TypedRegister, RegisterList> {
|
||||
public:
|
||||
/* result, target, args */
|
||||
Call (Register aOp1, Register aOp2, RegisterList aOp3) :
|
||||
Instruction_3<Register, Register, RegisterList>
|
||||
Call (TypedRegister aOp1, TypedRegister aOp2, RegisterList aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, RegisterList>
|
||||
(CALL, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[CALL] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << mOp3;
|
||||
f << opcodeNames[CALL] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << mOp3;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2] << ", " << ArgList(mOp3, registers);
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << ArgList(mOp3, registers);
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class CompareEQ : public Instruction_3<Register, Register, Register> {
|
||||
class CompareEQ : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareEQ (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareEQ (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_EQ, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareGE : public Instruction_3<Register, Register, Register> {
|
||||
class CompareGE : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareGE (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareGE (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_GE, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareGT : public Instruction_3<Register, Register, Register> {
|
||||
class CompareGT : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareGT (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareGT (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_GT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareIN : public Instruction_3<Register, Register, Register> {
|
||||
class CompareIN : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareIN (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareIN (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_IN, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareLE : public Instruction_3<Register, Register, Register> {
|
||||
class CompareLE : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareLE (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareLE (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_LE, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareLT : public Instruction_3<Register, Register, Register> {
|
||||
class CompareLT : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareLT (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareLT (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_LT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareNE : public Instruction_3<Register, Register, Register> {
|
||||
class CompareNE : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareNE (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareNE (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_NE, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class Divide : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Divide (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Divide (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(DIVIDE, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class ElemXcr : public Instruction_4<Register, Register, Register, double> {
|
||||
class ElemXcr : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, double> {
|
||||
public:
|
||||
/* dest, base, index, value */
|
||||
ElemXcr (Register aOp1, Register aOp2, Register aOp3, double aOp4) :
|
||||
Instruction_4<Register, Register, Register, double>
|
||||
ElemXcr (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, double aOp4) :
|
||||
Instruction_4<TypedRegister, TypedRegister, TypedRegister, double>
|
||||
(ELEM_XCR, aOp1, aOp2, aOp3, aOp4) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[ELEM_XCR] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << "R" << mOp3 << ", " << mOp4;
|
||||
f << opcodeNames[ELEM_XCR] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << "R" << mOp3.first << ", " << mOp4;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2] << ", " << "R" << mOp3 << '=' << registers[mOp3];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class GetElement : public Instruction_3<Register, Register, Register> {
|
||||
class GetElement : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, base, index */
|
||||
GetElement (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
GetElement (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(GET_ELEMENT, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[GET_ELEMENT] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << "R" << mOp3;
|
||||
f << opcodeNames[GET_ELEMENT] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << "R" << mOp3.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2] << ", " << "R" << mOp3 << '=' << registers[mOp3];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class GetProp : public Instruction_3<Register, Register, const StringAtom*> {
|
||||
class GetProp : public Instruction_3<TypedRegister, TypedRegister, const StringAtom*> {
|
||||
public:
|
||||
/* dest, object, prop name */
|
||||
GetProp (Register aOp1, Register aOp2, const StringAtom* aOp3) :
|
||||
Instruction_3<Register, Register, const StringAtom*>
|
||||
GetProp (TypedRegister aOp1, TypedRegister aOp2, const StringAtom* aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, const StringAtom*>
|
||||
(GET_PROP, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[GET_PROP] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << "'" << *mOp3 << "'";
|
||||
f << opcodeNames[GET_PROP] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << "'" << *mOp3 << "'";
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Instanceof : public Instruction_3<Register, Register, Register> {
|
||||
class Instanceof : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Instanceof (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
Instanceof (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(INSTANCEOF, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class Jsr : public GenericBranch {
|
||||
|
@ -635,82 +632,82 @@ namespace VM {
|
|||
}
|
||||
};
|
||||
|
||||
class LoadImmediate : public Instruction_2<Register, double> {
|
||||
class LoadBoolean : public Instruction_2<TypedRegister, bool> {
|
||||
public:
|
||||
/* dest, immediate value (boolean) */
|
||||
LoadBoolean (TypedRegister aOp1, bool aOp2) :
|
||||
Instruction_2<TypedRegister, bool>
|
||||
(LOAD_BOOLEAN, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[LOAD_BOOLEAN] << "\t" << "R" << mOp1.first << ", " << "'" << ((mOp2) ? "true" : "false") << "'";
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadImmediate : public Instruction_2<TypedRegister, double> {
|
||||
public:
|
||||
/* dest, immediate value (double) */
|
||||
LoadImmediate (Register aOp1, double aOp2) :
|
||||
Instruction_2<Register, double>
|
||||
LoadImmediate (TypedRegister aOp1, double aOp2) :
|
||||
Instruction_2<TypedRegister, double>
|
||||
(LOAD_IMMEDIATE, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[LOAD_IMMEDIATE] << "\t" << "R" << mOp1 << ", " << mOp2;
|
||||
f << opcodeNames[LOAD_IMMEDIATE] << "\t" << "R" << mOp1.first << ", " << mOp2;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadName : public Instruction_2<Register, const StringAtom*> {
|
||||
class LoadName : public Instruction_2<TypedRegister, const StringAtom*> {
|
||||
public:
|
||||
/* dest, name */
|
||||
LoadName (Register aOp1, const StringAtom* aOp2) :
|
||||
Instruction_2<Register, const StringAtom*>
|
||||
LoadName (TypedRegister aOp1, const StringAtom* aOp2) :
|
||||
Instruction_2<TypedRegister, const StringAtom*>
|
||||
(LOAD_NAME, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[LOAD_NAME] << "\t" << "R" << mOp1 << ", " << "'" << *mOp2 << "'";
|
||||
f << opcodeNames[LOAD_NAME] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'";
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadString : public Instruction_2<Register, JSString*> {
|
||||
class LoadString : public Instruction_2<TypedRegister, JSString*> {
|
||||
public:
|
||||
/* dest, immediate value (string) */
|
||||
LoadString (Register aOp1, JSString* aOp2) :
|
||||
Instruction_2<Register, JSString*>
|
||||
LoadString (TypedRegister aOp1, JSString* aOp2) :
|
||||
Instruction_2<TypedRegister, JSString*>
|
||||
(LOAD_STRING, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[LOAD_STRING] << "\t" << "R" << mOp1 << ", " << "'" << *mOp2 << "'";
|
||||
f << opcodeNames[LOAD_STRING] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'";
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadValue : public Instruction_2<Register, JSValue> {
|
||||
public:
|
||||
/* dest, immediate value (JSValue) */
|
||||
LoadValue (Register aOp1, JSValue aOp2) :
|
||||
Instruction_2<Register, JSValue>
|
||||
(LOAD_VALUE, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[LOAD_VALUE] << "\t" << "R" << mOp1 << ", " << mOp2;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Move : public Instruction_2<Register, Register> {
|
||||
class Move : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Move (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Move (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(MOVE, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[MOVE] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[MOVE] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -718,72 +715,72 @@ namespace VM {
|
|||
class Multiply : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Multiply (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Multiply (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(MULTIPLY, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class NameXcr : public Instruction_3<Register, const StringAtom*, double> {
|
||||
class NameXcr : public Instruction_3<TypedRegister, const StringAtom*, double> {
|
||||
public:
|
||||
/* dest, name, value */
|
||||
NameXcr (Register aOp1, const StringAtom* aOp2, double aOp3) :
|
||||
Instruction_3<Register, const StringAtom*, double>
|
||||
NameXcr (TypedRegister aOp1, const StringAtom* aOp2, double aOp3) :
|
||||
Instruction_3<TypedRegister, const StringAtom*, double>
|
||||
(NAME_XCR, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[NAME_XCR] << "\t" << "R" << mOp1 << ", " << "'" << *mOp2 << "'" << ", " << mOp3;
|
||||
f << opcodeNames[NAME_XCR] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << mOp3;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Negate : public Instruction_2<Register, Register> {
|
||||
class Negate : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Negate (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Negate (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(NEGATE, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[NEGATE] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[NEGATE] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class NewArray : public Instruction_1<Register> {
|
||||
class NewArray : public Instruction_1<TypedRegister> {
|
||||
public:
|
||||
/* dest */
|
||||
NewArray (Register aOp1) :
|
||||
Instruction_1<Register>
|
||||
NewArray (TypedRegister aOp1) :
|
||||
Instruction_1<TypedRegister>
|
||||
(NEW_ARRAY, aOp1) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[NEW_ARRAY] << "\t" << "R" << mOp1;
|
||||
f << opcodeNames[NEW_ARRAY] << "\t" << "R" << mOp1.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class NewObject : public Instruction_1<Register> {
|
||||
class NewObject : public Instruction_1<TypedRegister> {
|
||||
public:
|
||||
/* dest */
|
||||
NewObject (Register aOp1) :
|
||||
Instruction_1<Register>
|
||||
NewObject (TypedRegister aOp1) :
|
||||
Instruction_1<TypedRegister>
|
||||
(NEW_OBJECT, aOp1) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[NEW_OBJECT] << "\t" << "R" << mOp1;
|
||||
f << opcodeNames[NEW_OBJECT] << "\t" << "R" << mOp1.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -803,18 +800,18 @@ namespace VM {
|
|||
}
|
||||
};
|
||||
|
||||
class Not : public Instruction_2<Register, Register> {
|
||||
class Not : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Not (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Not (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(NOT, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[NOT] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[NOT] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -822,40 +819,40 @@ namespace VM {
|
|||
class Or : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Or (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Or (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(OR, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class Posate : public Instruction_2<Register, Register> {
|
||||
class Posate : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Posate (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Posate (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(POSATE, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[POSATE] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[POSATE] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class PropXcr : public Instruction_4<Register, Register, const StringAtom*, double> {
|
||||
class PropXcr : public Instruction_4<TypedRegister, TypedRegister, const StringAtom*, double> {
|
||||
public:
|
||||
/* dest, source, name, value */
|
||||
PropXcr (Register aOp1, Register aOp2, const StringAtom* aOp3, double aOp4) :
|
||||
Instruction_4<Register, Register, const StringAtom*, double>
|
||||
PropXcr (TypedRegister aOp1, TypedRegister aOp2, const StringAtom* aOp3, double aOp4) :
|
||||
Instruction_4<TypedRegister, TypedRegister, const StringAtom*, double>
|
||||
(PROP_XCR, aOp1, aOp2, aOp3, aOp4) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[PROP_XCR] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << "'" << *mOp3 << "'" << ", " << mOp4;
|
||||
f << opcodeNames[PROP_XCR] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << "'" << *mOp3 << "'" << ", " << mOp4;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -863,24 +860,24 @@ namespace VM {
|
|||
class Remainder : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Remainder (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Remainder (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(REMAINDER, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class Return : public Instruction_1<Register> {
|
||||
class Return : public Instruction_1<TypedRegister> {
|
||||
public:
|
||||
/* return value */
|
||||
Return (Register aOp1) :
|
||||
Instruction_1<Register>
|
||||
Return (TypedRegister aOp1) :
|
||||
Instruction_1<TypedRegister>
|
||||
(RETURN, aOp1) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[RETURN] << "\t" << "R" << mOp1;
|
||||
f << opcodeNames[RETURN] << "\t" << "R" << mOp1.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -915,50 +912,50 @@ namespace VM {
|
|||
}
|
||||
};
|
||||
|
||||
class SaveName : public Instruction_2<const StringAtom*, Register> {
|
||||
class SaveName : public Instruction_2<const StringAtom*, TypedRegister> {
|
||||
public:
|
||||
/* name, source */
|
||||
SaveName (const StringAtom* aOp1, Register aOp2) :
|
||||
Instruction_2<const StringAtom*, Register>
|
||||
SaveName (const StringAtom* aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<const StringAtom*, TypedRegister>
|
||||
(SAVE_NAME, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[SAVE_NAME] << "\t" << "'" << *mOp1 << "'" << ", " << "R" << mOp2;
|
||||
f << opcodeNames[SAVE_NAME] << "\t" << "'" << *mOp1 << "'" << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class SetElement : public Instruction_3<Register, Register, Register> {
|
||||
class SetElement : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* base, index, value */
|
||||
SetElement (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
SetElement (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(SET_ELEMENT, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[SET_ELEMENT] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << "R" << mOp3;
|
||||
f << opcodeNames[SET_ELEMENT] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << "R" << mOp3.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2] << ", " << "R" << mOp3 << '=' << registers[mOp3];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class SetProp : public Instruction_3<Register, const StringAtom*, Register> {
|
||||
class SetProp : public Instruction_3<TypedRegister, const StringAtom*, TypedRegister> {
|
||||
public:
|
||||
/* object, name, source */
|
||||
SetProp (Register aOp1, const StringAtom* aOp2, Register aOp3) :
|
||||
Instruction_3<Register, const StringAtom*, Register>
|
||||
SetProp (TypedRegister aOp1, const StringAtom* aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, const StringAtom*, TypedRegister>
|
||||
(SET_PROP, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[SET_PROP] << "\t" << "R" << mOp1 << ", " << "'" << *mOp2 << "'" << ", " << "R" << mOp3;
|
||||
f << opcodeNames[SET_PROP] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << "R" << mOp3.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp3 << '=' << registers[mOp3];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -966,7 +963,7 @@ namespace VM {
|
|||
class Shiftleft : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Shiftleft (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Shiftleft (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(SHIFTLEFT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
|
@ -975,67 +972,67 @@ namespace VM {
|
|||
class Shiftright : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Shiftright (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Shiftright (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(SHIFTRIGHT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class StrictEQ : public Instruction_3<Register, Register, Register> {
|
||||
class StrictEQ : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
StrictEQ (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
StrictEQ (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(STRICT_EQ, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class StrictNE : public Instruction_3<Register, Register, Register> {
|
||||
class StrictNE : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
StrictNE (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
StrictNE (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(STRICT_NE, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class Subtract : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Subtract (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Subtract (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(SUBTRACT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class Test : public Instruction_2<Register, Register> {
|
||||
class Test : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Test (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Test (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(TEST, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[TEST] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[TEST] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Throw : public Instruction_1<Register> {
|
||||
class Throw : public Instruction_1<TypedRegister> {
|
||||
public:
|
||||
/* exception value */
|
||||
Throw (Register aOp1) :
|
||||
Instruction_1<Register>
|
||||
Throw (TypedRegister aOp1) :
|
||||
Instruction_1<TypedRegister>
|
||||
(THROW, aOp1) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[THROW] << "\t" << "R" << mOp1;
|
||||
f << opcodeNames[THROW] << "\t" << "R" << mOp1.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -1073,40 +1070,40 @@ namespace VM {
|
|||
class Ushiftright : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Ushiftright (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Ushiftright (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(USHIFTRIGHT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class VarXcr : public Instruction_3<Register, Register, double> {
|
||||
class VarXcr : public Instruction_3<TypedRegister, TypedRegister, double> {
|
||||
public:
|
||||
/* dest, source, value */
|
||||
VarXcr (Register aOp1, Register aOp2, double aOp3) :
|
||||
Instruction_3<Register, Register, double>
|
||||
VarXcr (TypedRegister aOp1, TypedRegister aOp2, double aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, double>
|
||||
(VAR_XCR, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[VAR_XCR] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << mOp3;
|
||||
f << opcodeNames[VAR_XCR] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << mOp3;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Within : public Instruction_1<Register> {
|
||||
class Within : public Instruction_1<TypedRegister> {
|
||||
public:
|
||||
/* within this object */
|
||||
Within (Register aOp1) :
|
||||
Instruction_1<Register>
|
||||
Within (TypedRegister aOp1) :
|
||||
Instruction_1<TypedRegister>
|
||||
(WITHIN, aOp1) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[WITHIN] << "\t" << "R" << mOp1;
|
||||
f << opcodeNames[WITHIN] << "\t" << "R" << mOp1.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -1129,14 +1126,12 @@ namespace VM {
|
|||
class Xor : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Xor (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Xor (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(XOR, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
|
||||
|
||||
} /* namespace VM */
|
||||
|
||||
} /* namespace JavaScript */
|
||||
|
|
|
@ -61,14 +61,15 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
|
|||
// ICodeGenerator
|
||||
//
|
||||
|
||||
ICodeGenerator::ICodeGenerator(World *world)
|
||||
ICodeGenerator::ICodeGenerator(World *world, JSScope *global)
|
||||
: topRegister(0),
|
||||
registerBase(0),
|
||||
maxRegister(0),
|
||||
parameterCount(0),
|
||||
exceptionRegister(NotARegister),
|
||||
exceptionRegister(TypedRegister(NotARegister, &None_Type)),
|
||||
variableList(new VariableList()),
|
||||
mWorld(world),
|
||||
mGlobal(global),
|
||||
mInstructionMap(new InstructionMap()),
|
||||
mWithinWith(false)
|
||||
|
||||
|
@ -77,12 +78,28 @@ ICodeGenerator::ICodeGenerator(World *world)
|
|||
iCodeOwner = true;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::allocateVariable(const StringAtom& name)
|
||||
const JSType *ICodeGenerator::findType(const StringAtom& typeName)
|
||||
{
|
||||
const JSValue& type = mGlobal->getVariable(typeName);
|
||||
if (type.isType())
|
||||
return type.type;
|
||||
return &Any_Type;
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName)
|
||||
{
|
||||
if (exceptionRegister == NotARegister) {
|
||||
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")]);
|
||||
if (exceptionRegister.first == NotARegister) {
|
||||
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
|
||||
}
|
||||
return grabRegister(name);
|
||||
return grabRegister(name, findType(typeName));
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name)
|
||||
{
|
||||
if (exceptionRegister.first == NotARegister) {
|
||||
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
|
||||
}
|
||||
return grabRegister(name, &Any_Type);
|
||||
}
|
||||
|
||||
ICodeModule *ICodeGenerator::complete()
|
||||
|
@ -126,41 +143,41 @@ ICodeModule *ICodeGenerator::complete()
|
|||
|
||||
/********************************************************************/
|
||||
|
||||
Register ICodeGenerator::loadImmediate(double value)
|
||||
TypedRegister ICodeGenerator::loadImmediate(double value)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
LoadImmediate *instr = new LoadImmediate(dest, value);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::loadString(String &value)
|
||||
TypedRegister ICodeGenerator::loadString(String &value)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &String_Type);
|
||||
LoadString *instr = new LoadString(dest, new JSString(value));
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::loadValue(JSValue value)
|
||||
TypedRegister ICodeGenerator::loadBoolean(bool value)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
LoadValue *instr = new LoadValue(dest, value);
|
||||
TypedRegister dest(getRegister(), &Boolean_Type);
|
||||
LoadBoolean *instr = new LoadBoolean(dest, value);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::newObject()
|
||||
TypedRegister ICodeGenerator::newObject()
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
NewObject *instr = new NewObject(dest);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::newArray()
|
||||
TypedRegister ICodeGenerator::newArray()
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Array_Type);
|
||||
NewArray *instr = new NewArray(dest);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
|
@ -168,47 +185,47 @@ Register ICodeGenerator::newArray()
|
|||
|
||||
|
||||
|
||||
Register ICodeGenerator::loadName(const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::loadName(const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
LoadName *instr = new LoadName(dest, &name);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void ICodeGenerator::saveName(const StringAtom &name, Register value)
|
||||
void ICodeGenerator::saveName(const StringAtom &name, TypedRegister value)
|
||||
{
|
||||
SaveName *instr = new SaveName(&name, value);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
Register ICodeGenerator::nameInc(const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::nameInc(const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
NameXcr *instr = new NameXcr(dest, &name, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::nameDec(const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::nameDec(const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
NameXcr *instr = new NameXcr(dest, &name, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::varInc(Register var)
|
||||
TypedRegister ICodeGenerator::varInc(TypedRegister var)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
VarXcr *instr = new VarXcr(dest, var, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::varDec(Register var)
|
||||
TypedRegister ICodeGenerator::varDec(TypedRegister var)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
VarXcr *instr = new VarXcr(dest, var, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
|
@ -216,32 +233,32 @@ Register ICodeGenerator::varDec(Register var)
|
|||
|
||||
|
||||
|
||||
Register ICodeGenerator::getProperty(Register base, const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::getProperty(TypedRegister base, const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
GetProp *instr = new GetProp(dest, base, &name);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void ICodeGenerator::setProperty(Register base, const StringAtom &name,
|
||||
Register value)
|
||||
void ICodeGenerator::setProperty(TypedRegister base, const StringAtom &name,
|
||||
TypedRegister value)
|
||||
{
|
||||
SetProp *instr = new SetProp(base, &name, value);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
Register ICodeGenerator::propertyInc(Register base, const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::propertyInc(TypedRegister base, const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
PropXcr *instr = new PropXcr(dest, base, &name, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::propertyDec(Register base, const StringAtom &name)
|
||||
TypedRegister ICodeGenerator::propertyDec(TypedRegister base, const StringAtom &name)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
PropXcr *instr = new PropXcr(dest, base, &name, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
|
@ -249,94 +266,94 @@ Register ICodeGenerator::propertyDec(Register base, const StringAtom &name)
|
|||
|
||||
|
||||
|
||||
Register ICodeGenerator::getElement(Register base, Register index)
|
||||
TypedRegister ICodeGenerator::getElement(TypedRegister base, TypedRegister index)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
GetElement *instr = new GetElement(dest, base, index);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void ICodeGenerator::setElement(Register base, Register index,
|
||||
Register value)
|
||||
void ICodeGenerator::setElement(TypedRegister base, TypedRegister index,
|
||||
TypedRegister value)
|
||||
{
|
||||
SetElement *instr = new SetElement(base, index, value);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
Register ICodeGenerator::elementInc(Register base, Register index)
|
||||
TypedRegister ICodeGenerator::elementInc(TypedRegister base, TypedRegister index)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
ElemXcr *instr = new ElemXcr(dest, base, index, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::elementDec(Register base, Register index)
|
||||
TypedRegister ICodeGenerator::elementDec(TypedRegister base, TypedRegister index)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Number_Type);
|
||||
ElemXcr *instr = new ElemXcr(dest, base, index, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
Register ICodeGenerator::op(ICodeOp op, Register source)
|
||||
TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
ASSERT(source != NotARegister);
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
ASSERT(source.first != NotARegister);
|
||||
Unary *instr = new Unary (op, dest, source);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
void ICodeGenerator::move(Register destination, Register source)
|
||||
void ICodeGenerator::move(TypedRegister destination, TypedRegister source)
|
||||
{
|
||||
ASSERT(destination != NotARegister);
|
||||
ASSERT(source != NotARegister);
|
||||
ASSERT(destination.first != NotARegister);
|
||||
ASSERT(source.first != NotARegister);
|
||||
Move *instr = new Move(destination, source);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
Register ICodeGenerator::logicalNot(Register source)
|
||||
TypedRegister ICodeGenerator::logicalNot(TypedRegister source)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
Not *instr = new Not(dest, source);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::test(Register source)
|
||||
TypedRegister ICodeGenerator::test(TypedRegister source)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
Test *instr = new Test(dest, source);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::op(ICodeOp op, Register source1,
|
||||
Register source2)
|
||||
TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source1,
|
||||
TypedRegister source2)
|
||||
{
|
||||
ASSERT(source1 != NotARegister);
|
||||
ASSERT(source2 != NotARegister);
|
||||
Register dest = getRegister();
|
||||
ASSERT(source1.first != NotARegister);
|
||||
ASSERT(source2.first != NotARegister);
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
Arithmetic *instr = new Arithmetic(op, dest, source1, source2);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
Register ICodeGenerator::call(Register target, RegisterList args)
|
||||
TypedRegister ICodeGenerator::call(TypedRegister target, RegisterList args)
|
||||
{
|
||||
Register dest = getRegister();
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
Call *instr = new Call(dest, target, args);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void ICodeGenerator::callVoid(Register target, RegisterList args)
|
||||
void ICodeGenerator::callVoid(TypedRegister target, RegisterList args)
|
||||
{
|
||||
Call *instr = new Call(NotARegister, target, args);
|
||||
Call *instr = new Call(TypedRegister(NotARegister, &Void_Type), target, args);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
|
@ -346,23 +363,23 @@ void ICodeGenerator::branch(Label *label)
|
|||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
GenericBranch *ICodeGenerator::branchTrue(Label *label, Register condition)
|
||||
GenericBranch *ICodeGenerator::branchTrue(Label *label, TypedRegister condition)
|
||||
{
|
||||
GenericBranch *instr = new GenericBranch(BRANCH_TRUE, label, condition);
|
||||
iCode->push_back(instr);
|
||||
return instr;
|
||||
}
|
||||
|
||||
GenericBranch *ICodeGenerator::branchFalse(Label *label, Register condition)
|
||||
GenericBranch *ICodeGenerator::branchFalse(Label *label, TypedRegister condition)
|
||||
{
|
||||
GenericBranch *instr = new GenericBranch(BRANCH_FALSE, label, condition);
|
||||
iCode->push_back(instr);
|
||||
return instr;
|
||||
}
|
||||
|
||||
void ICodeGenerator::returnStmt(Register r)
|
||||
void ICodeGenerator::returnStmt(TypedRegister r)
|
||||
{
|
||||
if (r == NotARegister)
|
||||
if (r.first == NotARegister)
|
||||
iCode->push_back(new ReturnVoid());
|
||||
else
|
||||
iCode->push_back(new Return(r));
|
||||
|
@ -504,37 +521,37 @@ static bool generatedBoolean(ExprNode *p)
|
|||
a conditional branch to the appropriate target. If either branch is NULL, it
|
||||
indicates that the label is immediately forthcoming.
|
||||
*/
|
||||
Result ICodeGenerator::genExpr(ExprNode *p,
|
||||
TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
bool needBoolValueInBranch,
|
||||
Label *trueBranch,
|
||||
Label *falseBranch)
|
||||
{
|
||||
Register ret = NotARegister;
|
||||
TypedRegister ret(NotARegister, &None_Type);
|
||||
switch (p->getKind()) {
|
||||
case ExprNode::True:
|
||||
if (trueBranch || falseBranch) {
|
||||
if (needBoolValueInBranch)
|
||||
ret = loadValue(kTrue);
|
||||
ret = loadBoolean(true);
|
||||
if (trueBranch)
|
||||
branch(trueBranch);
|
||||
}
|
||||
else
|
||||
ret = loadValue(kTrue);
|
||||
ret = loadBoolean(true);
|
||||
break;
|
||||
case ExprNode::False:
|
||||
if (trueBranch || falseBranch) {
|
||||
if (needBoolValueInBranch)
|
||||
ret = loadValue(kFalse);
|
||||
ret = loadBoolean(false);
|
||||
if (falseBranch)
|
||||
branch(falseBranch);
|
||||
}
|
||||
else
|
||||
ret = loadValue(kFalse);
|
||||
ret = loadBoolean(false);
|
||||
break;
|
||||
case ExprNode::parentheses:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
ret = genExpr(u->op, needBoolValueInBranch, trueBranch, falseBranch).reg;
|
||||
ret = genExpr(u->op, needBoolValueInBranch, trueBranch, falseBranch);
|
||||
}
|
||||
break;
|
||||
case ExprNode::New:
|
||||
|
@ -546,11 +563,11 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::call :
|
||||
{
|
||||
InvokeExprNode *i = static_cast<InvokeExprNode *>(p);
|
||||
Register fn = genExpr(i->op).reg;
|
||||
TypedRegister fn = genExpr(i->op);
|
||||
RegisterList args;
|
||||
ExprPairList *p = i->pairs;
|
||||
while (p) {
|
||||
args.push_back(genExpr(p->value).reg);
|
||||
args.push_back(genExpr(p->value));
|
||||
p = p->next;
|
||||
}
|
||||
ret = call(fn, args);
|
||||
|
@ -559,23 +576,23 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::index :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
}
|
||||
break;
|
||||
case ExprNode::dot :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
break;
|
||||
case ExprNode::identifier :
|
||||
{
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(p))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(p))->name);
|
||||
if (v.first != NotARegister)
|
||||
ret = v;
|
||||
else
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(p))->name);
|
||||
|
@ -595,7 +612,7 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
TypedRegister 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);
|
||||
|
@ -603,8 +620,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v.first != NotARegister)
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
|
@ -621,8 +638,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
|
@ -634,14 +651,14 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = propertyInc(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v.first != NotARegister)
|
||||
ret = varInc(v);
|
||||
else
|
||||
ret = nameInc((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
|
@ -652,8 +669,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = elementInc(base, index);
|
||||
}
|
||||
}
|
||||
|
@ -663,7 +680,7 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
TypedRegister 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);
|
||||
|
@ -671,8 +688,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v.first != NotARegister)
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
else {
|
||||
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
|
@ -689,8 +706,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setElement(base, index, ret);
|
||||
|
@ -702,14 +719,14 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = propertyDec(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
if (v.first != NotARegister)
|
||||
ret = varDec(v);
|
||||
else
|
||||
ret = nameDec((static_cast<IdentifierExprNode *>(u->op))->name);
|
||||
|
@ -720,8 +737,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (u->op->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
Register base = genExpr(b->op1).reg;
|
||||
Register index = genExpr(b->op2).reg;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = elementInc(base, index);
|
||||
}
|
||||
}
|
||||
|
@ -731,7 +748,7 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::complement:
|
||||
{
|
||||
UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
|
||||
Register r = genExpr(u->op).reg;
|
||||
TypedRegister r = genExpr(u->op);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r);
|
||||
}
|
||||
break;
|
||||
|
@ -748,19 +765,19 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::bitwiseOr:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r1 = genExpr(b->op1);
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
}
|
||||
break;
|
||||
case ExprNode::assignment:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
ret = genExpr(b->op2).reg;
|
||||
ret = genExpr(b->op2);
|
||||
if (b->op1->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v != NotARegister)
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v.first != NotARegister)
|
||||
move(v, ret);
|
||||
else
|
||||
saveName((static_cast<IdentifierExprNode *>(b->op1))->name, ret);
|
||||
|
@ -771,14 +788,14 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name, ret);
|
||||
}
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register index = genExpr(lb->op2).reg;
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
TypedRegister index = genExpr(lb->op2);
|
||||
setElement(base, index, ret);
|
||||
}
|
||||
}
|
||||
|
@ -796,11 +813,11 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::bitwiseOrEquals:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
ret = genExpr(b->op2).reg;
|
||||
ret = genExpr(b->op2);
|
||||
if (b->op1->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v != NotARegister) {
|
||||
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
if (v.first != NotARegister) {
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
move(v, ret);
|
||||
}
|
||||
|
@ -811,7 +828,7 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
}
|
||||
else {
|
||||
Register v = loadName((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
TypedRegister v = loadName((static_cast<IdentifierExprNode *>(b->op1))->name);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
saveName((static_cast<IdentifierExprNode *>(b->op1))->name, ret);
|
||||
}
|
||||
|
@ -819,17 +836,17 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
else
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register v = getProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name);
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
TypedRegister v = getProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name, ret);
|
||||
}
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
Register base = genExpr(lb->op1).reg;
|
||||
Register index = genExpr(lb->op2).reg;
|
||||
Register v = getElement(base, index);
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
TypedRegister index = genExpr(lb->op2);
|
||||
TypedRegister v = getElement(base, index);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setElement(base, index, ret);
|
||||
}
|
||||
|
@ -843,8 +860,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::Instanceof:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r1 = genExpr(b->op1);
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -861,8 +878,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::greaterThanOrEqual:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r1 = genExpr(b->op1);
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r2, r1); // will return reverse case
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -880,8 +897,8 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
case ExprNode::notIdentical:
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
Register r1 = genExpr(b->op1).reg;
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r1 = genExpr(b->op1);
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), r1, r2);
|
||||
if (trueBranch || falseBranch) {
|
||||
if (trueBranch == NULL)
|
||||
|
@ -907,12 +924,12 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else {
|
||||
Label *fBranch = getLabel();
|
||||
Register r1 = genExpr(b->op1, true, NULL, fBranch).reg;
|
||||
TypedRegister r1 = genExpr(b->op1, true, NULL, fBranch);
|
||||
if (!generatedBoolean(b->op1)) {
|
||||
r1 = test(r1);
|
||||
branchFalse(fBranch, r1);
|
||||
}
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
if (!generatedBoolean(b->op2)) {
|
||||
r2 = test(r2);
|
||||
}
|
||||
|
@ -932,12 +949,12 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
}
|
||||
else {
|
||||
Label *tBranch = getLabel();
|
||||
Register r1 = genExpr(b->op1, true, tBranch, NULL).reg;
|
||||
TypedRegister r1 = genExpr(b->op1, true, tBranch, NULL);
|
||||
if (!generatedBoolean(b->op1)) {
|
||||
r1 = test(r1);
|
||||
branchTrue(tBranch, r1);
|
||||
}
|
||||
Register r2 = genExpr(b->op2).reg;
|
||||
TypedRegister r2 = genExpr(b->op2);
|
||||
if (!generatedBoolean(b->op2)) {
|
||||
r2 = test(r2);
|
||||
}
|
||||
|
@ -954,13 +971,13 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
TernaryExprNode *t = static_cast<TernaryExprNode *>(p);
|
||||
Label *fBranch = getLabel();
|
||||
Label *beyondBranch = getLabel();
|
||||
Register c = genExpr(t->op1, false, NULL, fBranch).reg;
|
||||
TypedRegister c = genExpr(t->op1, false, NULL, fBranch);
|
||||
if (!generatedBoolean(t->op1))
|
||||
branchFalse(fBranch, test(c));
|
||||
Register r1 = genExpr(t->op2).reg;
|
||||
TypedRegister r1 = genExpr(t->op2);
|
||||
branch(beyondBranch);
|
||||
setLabel(fBranch);
|
||||
Register r2 = genExpr(t->op3).reg;
|
||||
TypedRegister r2 = genExpr(t->op3);
|
||||
if (r1 != r2) // FIXME, need a way to specify a dest???
|
||||
move(r1, r2);
|
||||
setLabel(beyondBranch);
|
||||
|
@ -976,7 +993,7 @@ Result ICodeGenerator::genExpr(ExprNode *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).reg);
|
||||
setProperty(ret, (static_cast<IdentifierExprNode *>(e->field))->name, genExpr(e->value));
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
|
@ -987,7 +1004,7 @@ Result ICodeGenerator::genExpr(ExprNode *p,
|
|||
NOT_REACHED("Unsupported ExprNode kind");
|
||||
}
|
||||
}
|
||||
return Result(ret, Any_Type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1110,20 +1127,20 @@ void ICodeGenerator::preprocess(StmtNode *p)
|
|||
}
|
||||
}
|
||||
|
||||
Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
{
|
||||
Register ret = NotARegister;
|
||||
TypedRegister ret(NotARegister, &None_Type);
|
||||
|
||||
startStatement(p->pos);
|
||||
if (exceptionRegister == NotARegister) {
|
||||
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")]);
|
||||
if (exceptionRegister.first == NotARegister) {
|
||||
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
|
||||
}
|
||||
|
||||
switch (p->getKind()) {
|
||||
case StmtNode::Function:
|
||||
{
|
||||
FunctionStmtNode *f = static_cast<FunctionStmtNode *>(p);
|
||||
ICodeGenerator icg(mWorld);
|
||||
ICodeGenerator icg(mWorld, mGlobal);
|
||||
VariableBinding *v = f->function.parameters;
|
||||
while (v) {
|
||||
if (v->name && (v->name->getKind() == ExprNode::identifier))
|
||||
|
@ -1146,12 +1163,12 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
if (v->name && v->initializer) {
|
||||
if (v->name->getKind() == ExprNode::identifier) {
|
||||
if (!mWithinWith) {
|
||||
Register r = genExpr(v->name).reg;
|
||||
Register val = genExpr(v->initializer).reg;
|
||||
TypedRegister r = genExpr(v->name);
|
||||
TypedRegister val = genExpr(v->initializer);
|
||||
move(r, val);
|
||||
}
|
||||
else {
|
||||
Register val = genExpr(v->initializer).reg;
|
||||
TypedRegister val = genExpr(v->initializer);
|
||||
saveName((static_cast<IdentifierExprNode *>(v->name))->name, val);
|
||||
}
|
||||
}
|
||||
|
@ -1164,29 +1181,29 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
case StmtNode::expression:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
ret = genExpr(e->expr).reg;
|
||||
ret = genExpr(e->expr);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Throw:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
throwStmt(genExpr(e->expr).reg);
|
||||
throwStmt(genExpr(e->expr));
|
||||
}
|
||||
break;
|
||||
case StmtNode::Return:
|
||||
{
|
||||
ExprStmtNode *e = static_cast<ExprStmtNode *>(p);
|
||||
if (e->expr)
|
||||
returnStmt(ret = genExpr(e->expr).reg);
|
||||
returnStmt(ret = genExpr(e->expr));
|
||||
else
|
||||
returnStmt(NotARegister);
|
||||
returnStmt(TypedRegister(NotARegister, &Void_Type));
|
||||
}
|
||||
break;
|
||||
case StmtNode::If:
|
||||
{
|
||||
Label *falseLabel = getLabel();
|
||||
UnaryStmtNode *i = static_cast<UnaryStmtNode *>(p);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel).reg;
|
||||
TypedRegister c = genExpr(i->expr, false, NULL, falseLabel);
|
||||
if (!generatedBoolean(i->expr))
|
||||
branchFalse(falseLabel, test(c));
|
||||
genStmt(i->stmt);
|
||||
|
@ -1198,7 +1215,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
Label *falseLabel = getLabel();
|
||||
Label *beyondLabel = getLabel();
|
||||
BinaryStmtNode *i = static_cast<BinaryStmtNode *>(p);
|
||||
Register c = genExpr(i->expr, false, NULL, falseLabel).reg;
|
||||
TypedRegister c = genExpr(i->expr, false, NULL, falseLabel);
|
||||
if (!generatedBoolean(i->expr))
|
||||
branchFalse(falseLabel, test(c));
|
||||
genStmt(i->stmt);
|
||||
|
@ -1211,7 +1228,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
case StmtNode::With:
|
||||
{
|
||||
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
|
||||
Register o = genExpr(w->expr).reg;
|
||||
TypedRegister o = genExpr(w->expr);
|
||||
bool withinWith = mWithinWith;
|
||||
mWithinWith = true;
|
||||
beginWith(o);
|
||||
|
@ -1226,7 +1243,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
LabelEntry *e = new LabelEntry(currentLabelSet, getLabel());
|
||||
mLabelStack.push_back(e);
|
||||
SwitchStmtNode *sw = static_cast<SwitchStmtNode *>(p);
|
||||
Register sc = genExpr(sw->expr).reg;
|
||||
TypedRegister sc = genExpr(sw->expr);
|
||||
StmtNode *s = sw->statements;
|
||||
// ECMA requires case & default statements to be immediate children of switch
|
||||
// unlike C where they can be arbitrarily deeply nested in other statements.
|
||||
|
@ -1239,8 +1256,8 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
if (nextCaseLabel)
|
||||
setLabel(nextCaseLabel);
|
||||
nextCaseLabel = getLabel();
|
||||
Register r = genExpr(c->expr).reg;
|
||||
Register eq = op(COMPARE_EQ, r, sc);
|
||||
TypedRegister r = genExpr(c->expr);
|
||||
TypedRegister eq = op(COMPARE_EQ, r, sc);
|
||||
lastBranch = branchFalse(nextCaseLabel, eq);
|
||||
}
|
||||
else {
|
||||
|
@ -1270,7 +1287,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
setLabel(doBodyTopLabel);
|
||||
genStmt(d->stmt);
|
||||
setLabel(e->continueLabel);
|
||||
Register c = genExpr(d->expr, false, doBodyTopLabel, NULL).reg;
|
||||
TypedRegister c = genExpr(d->expr, false, doBodyTopLabel, NULL);
|
||||
if (!generatedBoolean(d->expr))
|
||||
branchTrue(doBodyTopLabel, test(c));
|
||||
setLabel(e->breakLabel);
|
||||
|
@ -1290,7 +1307,7 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
genStmt(w->stmt);
|
||||
|
||||
setLabel(e->continueLabel);
|
||||
Register c = genExpr(w->expr, false, whileBodyTopLabel, NULL).reg;
|
||||
TypedRegister c = genExpr(w->expr, false, whileBodyTopLabel, NULL);
|
||||
if (!generatedBoolean(w->expr))
|
||||
branchTrue(whileBodyTopLabel, test(c));
|
||||
|
||||
|
@ -1315,11 +1332,11 @@ Register ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
|||
|
||||
setLabel(e->continueLabel);
|
||||
if (f->expr3)
|
||||
genExpr(f->expr3).reg;
|
||||
genExpr(f->expr3);
|
||||
|
||||
setLabel(forTestLabel);
|
||||
if (f->expr2) {
|
||||
Register c = genExpr(f->expr2, false, forBlockTop, NULL).reg;
|
||||
TypedRegister c = genExpr(f->expr2, false, forBlockTop, NULL);
|
||||
if (!generatedBoolean(f->expr2))
|
||||
branchTrue(forBlockTop, test(c));
|
||||
}
|
||||
|
|
|
@ -46,9 +46,9 @@ namespace JavaScript {
|
|||
namespace ICG {
|
||||
|
||||
using namespace VM;
|
||||
using namespace JSTypes;
|
||||
|
||||
|
||||
typedef std::map<String, Register, std::less<String> > VariableList;
|
||||
typedef std::map<String, TypedRegister, std::less<String> > VariableList;
|
||||
typedef std::pair<uint32, uint32> InstructionMapping;
|
||||
typedef std::vector<InstructionMapping *> InstructionMap;
|
||||
|
||||
|
@ -105,12 +105,6 @@ namespace ICG {
|
|||
// function/script, adds statements and expressions to it and then
|
||||
// converts it into an ICodeModule, ready for execution.
|
||||
|
||||
struct Result {
|
||||
Result(Register reg, JSTypes::JSType type) : reg(reg), type(type) {}
|
||||
Register reg;
|
||||
JSTypes::JSType type;
|
||||
};
|
||||
|
||||
class ICodeGenerator {
|
||||
private:
|
||||
InstructionStream *iCode;
|
||||
|
@ -122,10 +116,11 @@ namespace ICG {
|
|||
uint32 maxRegister; // highest (ever) allocated register
|
||||
uint32 parameterCount; // number of parameters declared for the function
|
||||
// these must come before any variables declared.
|
||||
Register exceptionRegister; // reserved to carry the exception object.
|
||||
TypedRegister exceptionRegister;// reserved to carry the exception object.
|
||||
VariableList *variableList; // name|register pair for each variable
|
||||
|
||||
World *mWorld; // used to register strings
|
||||
World *mWorld; // used to register strings
|
||||
JSScope *mGlobal; // the scope for compiling within
|
||||
LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct
|
||||
InstructionMap *mInstructionMap;// maps source position to instruction index
|
||||
|
||||
|
@ -146,15 +141,15 @@ namespace ICG {
|
|||
void jsr(Label *label) { iCode->push_back(new Jsr(label)); }
|
||||
void rts() { iCode->push_back(new Rts()); }
|
||||
void branch(Label *label);
|
||||
GenericBranch *branchTrue(Label *label, Register condition);
|
||||
GenericBranch *branchFalse(Label *label, Register condition);
|
||||
GenericBranch *branchTrue(Label *label, TypedRegister condition);
|
||||
GenericBranch *branchFalse(Label *label, TypedRegister condition);
|
||||
|
||||
void beginTry(Label *catchLabel, Label *finallyLabel)
|
||||
{ iCode->push_back(new Tryin(catchLabel, finallyLabel)); }
|
||||
void endTry()
|
||||
{ iCode->push_back(new Tryout()); }
|
||||
|
||||
void beginWith(Register obj)
|
||||
void beginWith(TypedRegister obj)
|
||||
{ iCode->push_back(new Within(obj)); }
|
||||
void endWith()
|
||||
{ iCode->push_back(new Without()); }
|
||||
|
@ -164,7 +159,7 @@ namespace ICG {
|
|||
|
||||
void resetStatement() { resetTopRegister(); }
|
||||
|
||||
void setRegisterForVariable(const StringAtom& name, Register r)
|
||||
void setRegisterForVariable(const StringAtom& name, TypedRegister r)
|
||||
{ (*variableList)[name] = r; }
|
||||
|
||||
|
||||
|
@ -172,16 +167,18 @@ namespace ICG {
|
|||
|
||||
ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind);
|
||||
|
||||
Register grabRegister(const StringAtom& name)
|
||||
TypedRegister grabRegister(const StringAtom& name, const JSType *type)
|
||||
{
|
||||
Register result = getRegister();
|
||||
TypedRegister result(getRegister(), type);
|
||||
(*variableList)[name] = result;
|
||||
registerBase = topRegister;
|
||||
return result;
|
||||
}
|
||||
|
||||
const JSType *findType(const StringAtom& typeName);
|
||||
|
||||
public:
|
||||
ICodeGenerator(World *world = NULL);
|
||||
ICodeGenerator(World *world, JSScope *global);
|
||||
|
||||
~ICodeGenerator()
|
||||
{
|
||||
|
@ -193,65 +190,66 @@ namespace ICG {
|
|||
|
||||
ICodeModule *complete();
|
||||
|
||||
Result genExpr(ExprNode *p,
|
||||
TypedRegister genExpr(ExprNode *p,
|
||||
bool needBoolValueInBranch = false,
|
||||
Label *trueBranch = NULL,
|
||||
Label *falseBranch = NULL);
|
||||
void preprocess(StmtNode *p);
|
||||
Register genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL);
|
||||
TypedRegister genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL);
|
||||
|
||||
void isScript() { mWithinWith = true; }
|
||||
|
||||
void returnStmt(Register r);
|
||||
void throwStmt(Register r)
|
||||
void returnStmt(TypedRegister r);
|
||||
void throwStmt(TypedRegister r)
|
||||
{ iCode->push_back(new Throw(r)); }
|
||||
|
||||
Register allocateVariable(const StringAtom& name);
|
||||
Register allocateVariable(const StringAtom& name, const StringAtom& /*type */)
|
||||
{ return allocateVariable(name); }
|
||||
TypedRegister allocateVariable(const StringAtom& name);
|
||||
TypedRegister allocateVariable(const StringAtom& name, const StringAtom& typeName);
|
||||
|
||||
Register findVariable(const StringAtom& name)
|
||||
TypedRegister findVariable(const StringAtom& name)
|
||||
{ VariableList::iterator i = variableList->find(name);
|
||||
return (i == variableList->end()) ? NotARegister : (*i).second; }
|
||||
return (i == variableList->end()) ? TypedRegister(NotARegister, &None_Type) : (*i).second; }
|
||||
|
||||
Register allocateParameter(const StringAtom& name)
|
||||
{ parameterCount++; return grabRegister(name); }
|
||||
TypedRegister allocateParameter(const StringAtom& name)
|
||||
{ parameterCount++; return grabRegister(name, &Any_Type); }
|
||||
TypedRegister allocateParameter(const StringAtom& name, const StringAtom& typeName)
|
||||
{ parameterCount++; return grabRegister(name, findType(typeName)); }
|
||||
|
||||
Formatter& print(Formatter& f);
|
||||
|
||||
Register op(ICodeOp op, Register source);
|
||||
Register op(ICodeOp op, Register source1, Register source2);
|
||||
Register call(Register target, RegisterList args);
|
||||
void callVoid(Register target, RegisterList args);
|
||||
TypedRegister op(ICodeOp op, TypedRegister source);
|
||||
TypedRegister op(ICodeOp op, TypedRegister source1, TypedRegister source2);
|
||||
TypedRegister call(TypedRegister target, RegisterList args);
|
||||
void callVoid(TypedRegister target, RegisterList args);
|
||||
|
||||
void move(Register destination, Register source);
|
||||
Register logicalNot(Register source);
|
||||
Register test(Register source);
|
||||
void move(TypedRegister destination, TypedRegister source);
|
||||
TypedRegister logicalNot(TypedRegister source);
|
||||
TypedRegister test(TypedRegister source);
|
||||
|
||||
Register loadValue(JSValue value);
|
||||
Register loadImmediate(double value);
|
||||
Register loadString(String &value);
|
||||
TypedRegister loadBoolean(bool value);
|
||||
TypedRegister loadImmediate(double value);
|
||||
TypedRegister loadString(String &value);
|
||||
|
||||
Register newObject();
|
||||
Register newArray();
|
||||
TypedRegister newObject();
|
||||
TypedRegister newArray();
|
||||
|
||||
Register loadName(const StringAtom &name);
|
||||
void saveName(const StringAtom &name, Register value);
|
||||
Register nameInc(const StringAtom &name);
|
||||
Register nameDec(const StringAtom &name);
|
||||
TypedRegister loadName(const StringAtom &name);
|
||||
void saveName(const StringAtom &name, TypedRegister value);
|
||||
TypedRegister nameInc(const StringAtom &name);
|
||||
TypedRegister 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);
|
||||
Register propertyDec(Register base, const StringAtom &name);
|
||||
TypedRegister getProperty(TypedRegister base, const StringAtom &name);
|
||||
void setProperty(TypedRegister base, const StringAtom &name, TypedRegister value);
|
||||
TypedRegister propertyInc(TypedRegister base, const StringAtom &name);
|
||||
TypedRegister propertyDec(TypedRegister base, const StringAtom &name);
|
||||
|
||||
Register getElement(Register base, Register index);
|
||||
void setElement(Register base, Register index, Register value);
|
||||
Register elementInc(Register base, Register index);
|
||||
Register elementDec(Register base, Register index);
|
||||
TypedRegister getElement(TypedRegister base, TypedRegister index);
|
||||
void setElement(TypedRegister base, TypedRegister index, TypedRegister value);
|
||||
TypedRegister elementInc(TypedRegister base, TypedRegister index);
|
||||
TypedRegister elementDec(TypedRegister base, TypedRegister index);
|
||||
|
||||
Register varInc(Register var);
|
||||
Register varDec(Register var);
|
||||
TypedRegister varInc(TypedRegister var);
|
||||
TypedRegister varDec(TypedRegister var);
|
||||
|
||||
Register getRegisterBase() { return topRegister; }
|
||||
InstructionStream *get_iCode() { return iCode; }
|
||||
|
|
|
@ -98,7 +98,7 @@ struct Activation : public gc_base {
|
|||
const JSValues& params = caller->mRegisters;
|
||||
for (RegisterList::const_iterator src = list.begin(),
|
||||
end = list.end(); src != end; ++src, ++dest) {
|
||||
*dest = params[*src];
|
||||
*dest = params[(*src).first];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,10 +128,10 @@ struct Linkage : public Context::Frame, public gc_base {
|
|||
Linkage* mNext; // next linkage in linkage stack.
|
||||
InstructionIterator mReturnPC;
|
||||
Activation* mActivation; // caller's activation.
|
||||
Register mResult; // the desired target register for the return value
|
||||
TypedRegister mResult; // the desired target register for the return value
|
||||
|
||||
Linkage(Linkage* linkage, InstructionIterator returnPC,
|
||||
Activation* activation, Register result)
|
||||
Activation* activation, TypedRegister result)
|
||||
: mNext(linkage), mReturnPC(returnPC),
|
||||
mActivation(activation), mResult(result)
|
||||
{
|
||||
|
@ -146,31 +146,6 @@ void getState(InstructionIterator& pc, JSValues*& registers, ICodeModule*& iCode
|
|||
iCode = mActivation->mICode;
|
||||
}
|
||||
};
|
||||
/*
|
||||
void Context::doCall(JSFunction *target, Instruction *pc)
|
||||
{
|
||||
if (target->isNative()) {
|
||||
RegisterList ¶ms = op3(call);
|
||||
JSValues argv(params.size());
|
||||
JSValues::size_type i = 0;
|
||||
for (RegisterList::const_iterator src = params.begin(), end = params.end();
|
||||
src != end; ++src, ++i) {
|
||||
argv[i] = (*registers)[*src];
|
||||
}
|
||||
if (op2(call) != NotARegister)
|
||||
(*registers)[op2(call)] = static_cast<JSNativeFunction*>(target)->mCode(argv);
|
||||
return pc;
|
||||
}
|
||||
else {
|
||||
mLinkage = new Linkage(mLinkage, ++mPC,
|
||||
mActivation, op1(call));
|
||||
iCode = target->getICode();
|
||||
mActivation = new Activation(iCode, mActivation, op3(call));
|
||||
registers = &mActivation->mRegisters;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static JSValue shiftLeft_Default(const JSValue& r1, const JSValue& r2)
|
||||
{
|
||||
|
@ -517,17 +492,17 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
case CALL:
|
||||
{
|
||||
Call* call = static_cast<Call*>(instruction);
|
||||
JSFunction *target = (*registers)[op2(call)].function;
|
||||
JSFunction *target = (*registers)[op2(call).first].function;
|
||||
if (target->isNative()) {
|
||||
RegisterList ¶ms = op3(call);
|
||||
JSValues argv(params.size());
|
||||
JSValues::size_type i = 0;
|
||||
for (RegisterList::const_iterator src = params.begin(), end = params.end();
|
||||
src != end; ++src, ++i) {
|
||||
argv[i] = (*registers)[*src];
|
||||
argv[i] = (*registers)[src->first];
|
||||
}
|
||||
if (op2(call) != NotARegister)
|
||||
(*registers)[op2(call)] = static_cast<JSNativeFunction*>(target)->mCode(argv);
|
||||
if (op2(call).first != NotARegister)
|
||||
(*registers)[op2(call).first] = static_cast<JSNativeFunction*>(target)->mCode(argv);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
@ -553,7 +528,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
mLinkage = linkage->mNext;
|
||||
mActivation = linkage->mActivation;
|
||||
registers = &mActivation->mRegisters;
|
||||
(*registers)[linkage->mResult] = result;
|
||||
(*registers)[linkage->mResult.first] = result;
|
||||
mPC = linkage->mReturnPC;
|
||||
}
|
||||
continue;
|
||||
|
@ -562,8 +537,8 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
{
|
||||
Return* ret = static_cast<Return*>(instruction);
|
||||
JSValue result;
|
||||
if (op1(ret) != NotARegister)
|
||||
result = (*registers)[op1(ret)];
|
||||
if (op1(ret).first != NotARegister)
|
||||
result = (*registers)[op1(ret).first];
|
||||
Linkage* linkage = mLinkage;
|
||||
if (!linkage)
|
||||
{
|
||||
|
@ -574,57 +549,57 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
mLinkage = linkage->mNext;
|
||||
mActivation = linkage->mActivation;
|
||||
registers = &mActivation->mRegisters;
|
||||
(*registers)[linkage->mResult] = result;
|
||||
(*registers)[linkage->mResult.first] = result;
|
||||
mPC = linkage->mReturnPC;
|
||||
}
|
||||
continue;
|
||||
case MOVE:
|
||||
{
|
||||
Move* mov = static_cast<Move*>(instruction);
|
||||
(*registers)[dst(mov)] = (*registers)[src1(mov)];
|
||||
(*registers)[dst(mov).first] = (*registers)[src1(mov).first];
|
||||
}
|
||||
break;
|
||||
case LOAD_NAME:
|
||||
{
|
||||
LoadName* ln = static_cast<LoadName*>(instruction);
|
||||
(*registers)[dst(ln)] = mGlobal->getVariable(*src1(ln));
|
||||
(*registers)[dst(ln).first] = mGlobal->getVariable(*src1(ln));
|
||||
}
|
||||
break;
|
||||
case SAVE_NAME:
|
||||
{
|
||||
SaveName* sn = static_cast<SaveName*>(instruction);
|
||||
mGlobal->setVariable(*dst(sn), (*registers)[src1(sn)]);
|
||||
mGlobal->setVariable(*dst(sn), (*registers)[src1(sn).first]);
|
||||
}
|
||||
break;
|
||||
case NEW_OBJECT:
|
||||
{
|
||||
NewObject* no = static_cast<NewObject*>(instruction);
|
||||
(*registers)[dst(no)] = JSValue(new JSObject());
|
||||
(*registers)[dst(no).first] = JSValue(new JSObject());
|
||||
}
|
||||
break;
|
||||
case NEW_ARRAY:
|
||||
{
|
||||
NewArray* na = static_cast<NewArray*>(instruction);
|
||||
(*registers)[dst(na)] = JSValue(new JSArray());
|
||||
(*registers)[dst(na).first] = JSValue(new JSArray());
|
||||
}
|
||||
break;
|
||||
case GET_PROP:
|
||||
{
|
||||
GetProp* gp = static_cast<GetProp*>(instruction);
|
||||
JSValue& value = (*registers)[src1(gp)];
|
||||
JSValue& value = (*registers)[src1(gp).first];
|
||||
if (value.tag == JSValue::object_tag) {
|
||||
JSObject* object = value.object;
|
||||
(*registers)[dst(gp)] = object->getProperty(*src2(gp));
|
||||
(*registers)[dst(gp).first] = object->getProperty(*src2(gp));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SET_PROP:
|
||||
{
|
||||
SetProp* sp = static_cast<SetProp*>(instruction);
|
||||
JSValue& value = (*registers)[dst(sp)];
|
||||
JSValue& value = (*registers)[dst(sp).first];
|
||||
if (value.tag == JSValue::object_tag) {
|
||||
JSObject* object = value.object;
|
||||
object->setProperty(*src1(sp), (*registers)[src2(sp)]);
|
||||
object->setProperty(*src1(sp), (*registers)[src2(sp).first]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -647,20 +622,20 @@ using JSString throughout.
|
|||
case GET_ELEMENT:
|
||||
{
|
||||
GetElement* ge = static_cast<GetElement*>(instruction);
|
||||
JSValue& value = (*registers)[src1(ge)];
|
||||
JSValue& value = (*registers)[src1(ge).first];
|
||||
if (value.tag == JSValue::array_tag) {
|
||||
JSArray* array = value.array;
|
||||
(*registers)[dst(ge)] = (*array)[(*registers)[src2(ge)]];
|
||||
(*registers)[dst(ge).first] = (*array)[(*registers)[src2(ge).first]];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SET_ELEMENT:
|
||||
{
|
||||
SetElement* se = static_cast<SetElement*>(instruction);
|
||||
JSValue& value = (*registers)[dst(se)];
|
||||
JSValue& value = (*registers)[dst(se).first];
|
||||
if (value.tag == JSValue::array_tag) {
|
||||
JSArray* array = value.array;
|
||||
(*array)[(*registers)[src1(se)]] = (*registers)[src2(se)];
|
||||
(*array)[(*registers)[src1(se).first]] = (*registers)[src2(se).first];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -668,19 +643,19 @@ using JSString throughout.
|
|||
case LOAD_IMMEDIATE:
|
||||
{
|
||||
LoadImmediate* li = static_cast<LoadImmediate*>(instruction);
|
||||
(*registers)[dst(li)] = JSValue(src1(li));
|
||||
(*registers)[dst(li).first] = JSValue(src1(li));
|
||||
}
|
||||
break;
|
||||
case LOAD_STRING:
|
||||
{
|
||||
LoadString* ls = static_cast<LoadString*>(instruction);
|
||||
(*registers)[dst(ls)] = JSValue(src1(ls));
|
||||
(*registers)[dst(ls).first] = JSValue(src1(ls));
|
||||
}
|
||||
break;
|
||||
case LOAD_VALUE:
|
||||
case LOAD_BOOLEAN:
|
||||
{
|
||||
LoadValue* lv = static_cast<LoadValue*>(instruction);
|
||||
(*registers)[dst(lv)] = src1(lv);
|
||||
LoadBoolean* lb = static_cast<LoadBoolean*>(instruction);
|
||||
(*registers)[dst(lb).first] = JSValue(src1(lb));
|
||||
}
|
||||
break;
|
||||
case BRANCH:
|
||||
|
@ -695,8 +670,8 @@ using JSString throughout.
|
|||
{
|
||||
GenericBranch* bc =
|
||||
static_cast<GenericBranch*>(instruction);
|
||||
ASSERT((*registers)[src1(bc)].isBoolean());
|
||||
if ((*registers)[src1(bc)].boolean) {
|
||||
ASSERT((*registers)[src1(bc).first].isBoolean());
|
||||
if ((*registers)[src1(bc).first].boolean) {
|
||||
mPC = mActivation->mICode->its_iCode->begin() + ofs(bc);
|
||||
continue;
|
||||
}
|
||||
|
@ -706,8 +681,8 @@ using JSString throughout.
|
|||
{
|
||||
GenericBranch* bc =
|
||||
static_cast<GenericBranch*>(instruction);
|
||||
ASSERT((*registers)[src1(bc)].isBoolean());
|
||||
if (!(*registers)[src1(bc)].boolean) {
|
||||
ASSERT((*registers)[src1(bc).first].isBoolean());
|
||||
if (!(*registers)[src1(bc).first].boolean) {
|
||||
mPC = mActivation->mICode->its_iCode->begin() + ofs(bc);
|
||||
continue;
|
||||
}
|
||||
|
@ -730,9 +705,9 @@ using JSString throughout.
|
|||
case STRICT_EQ:
|
||||
{
|
||||
Arithmetic* mul = static_cast<Arithmetic*>(instruction);
|
||||
JSValue& dest = (*registers)[dst(mul)];
|
||||
JSValue& r1 = (*registers)[src1(mul)];
|
||||
JSValue& r2 = (*registers)[src2(mul)];
|
||||
JSValue& dest = (*registers)[dst(mul).first];
|
||||
JSValue& r1 = (*registers)[src1(mul).first];
|
||||
JSValue& r2 = (*registers)[src2(mul).first];
|
||||
const JSValue ovr = findBinaryOverride(r1, r2, BinaryOperator::mapICodeOp(instruction->op()));
|
||||
JSFunction *target = ovr.function;
|
||||
if (target->isNative()) {
|
||||
|
@ -756,19 +731,19 @@ using JSString throughout.
|
|||
case VAR_XCR:
|
||||
{
|
||||
VarXcr *vx = static_cast<VarXcr*>(instruction);
|
||||
JSValue& dest = (*registers)[dst(vx)];
|
||||
JSValue r = (*registers)[src1(vx)].toNumber();
|
||||
JSValue& dest = (*registers)[dst(vx).first];
|
||||
JSValue r = (*registers)[src1(vx).first].toNumber();
|
||||
dest = r;
|
||||
r.f64 += val3(vx);
|
||||
(*registers)[src1(vx)] = r;
|
||||
(*registers)[src1(vx).first] = r;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_XCR:
|
||||
{
|
||||
PropXcr *px = static_cast<PropXcr*>(instruction);
|
||||
JSValue& dest = (*registers)[dst(px)];
|
||||
JSValue& base = (*registers)[src1(px)];
|
||||
JSValue& dest = (*registers)[dst(px).first];
|
||||
JSValue& base = (*registers)[src1(px).first];
|
||||
JSObject *object = base.object;
|
||||
JSValue r = object->getProperty(*src2(px)).toNumber();
|
||||
dest = r;
|
||||
|
@ -780,7 +755,7 @@ using JSString throughout.
|
|||
case NAME_XCR:
|
||||
{
|
||||
NameXcr *nx = static_cast<NameXcr*>(instruction);
|
||||
JSValue& dest = (*registers)[dst(nx)];
|
||||
JSValue& dest = (*registers)[dst(nx).first];
|
||||
JSValue r = mGlobal->getVariable(*src1(nx)).toNumber();
|
||||
dest = r;
|
||||
r.f64 += val3(nx);
|
||||
|
@ -791,38 +766,38 @@ using JSString throughout.
|
|||
case TEST:
|
||||
{
|
||||
Test* tst = static_cast<Test*>(instruction);
|
||||
(*registers)[dst(tst)] = (*registers)[src1(tst)].toBoolean();
|
||||
(*registers)[dst(tst).first] = (*registers)[src1(tst).first].toBoolean();
|
||||
}
|
||||
break;
|
||||
case NEGATE:
|
||||
{
|
||||
Negate* neg = static_cast<Negate*>(instruction);
|
||||
(*registers)[dst(neg)] = JSValue(-(*registers)[src1(neg)].toNumber().f64);
|
||||
(*registers)[dst(neg).first] = JSValue(-(*registers)[src1(neg).first].toNumber().f64);
|
||||
}
|
||||
break;
|
||||
case POSATE:
|
||||
{
|
||||
Posate* pos = static_cast<Posate*>(instruction);
|
||||
(*registers)[dst(pos)] = (*registers)[src1(pos)].toNumber();
|
||||
(*registers)[dst(pos).first] = (*registers)[src1(pos).first].toNumber();
|
||||
}
|
||||
break;
|
||||
case BITNOT:
|
||||
{
|
||||
Bitnot* bn = static_cast<Bitnot*>(instruction);
|
||||
(*registers)[dst(bn)] = JSValue(~(*registers)[src1(bn)].toInt32().i32);
|
||||
(*registers)[dst(bn).first] = JSValue(~(*registers)[src1(bn).first].toInt32().i32);
|
||||
}
|
||||
break;
|
||||
case NOT:
|
||||
{
|
||||
Not* nt = static_cast<Not*>(instruction);
|
||||
ASSERT((*registers)[src1(nt)].isBoolean());
|
||||
(*registers)[dst(nt)] = JSValue(!(*registers)[src1(nt)].boolean);
|
||||
ASSERT((*registers)[src1(nt).first].isBoolean());
|
||||
(*registers)[dst(nt).first] = JSValue(!(*registers)[src1(nt).first].boolean);
|
||||
}
|
||||
break;
|
||||
case THROW:
|
||||
{
|
||||
Throw* thrw = static_cast<Throw*>(instruction);
|
||||
throw new JSException((*registers)[op1(thrw)]);
|
||||
throw new JSException((*registers)[op1(thrw).first]);
|
||||
}
|
||||
|
||||
case TRYIN:
|
||||
|
@ -857,7 +832,7 @@ using JSString throughout.
|
|||
case WITHIN:
|
||||
{
|
||||
Within* within = static_cast<Within*>(instruction);
|
||||
JSValue& value = (*registers)[op1(within)];
|
||||
JSValue& value = (*registers)[op1(within).first];
|
||||
assert(value.tag == JSValue::object_tag);
|
||||
mGlobal = new JSScope(mGlobal, value.object);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
namespace JavaScript {
|
||||
namespace VM {
|
||||
|
||||
using namespace JSTypes;
|
||||
|
||||
Formatter& operator<< (Formatter& f, Instruction& i)
|
||||
{
|
||||
|
@ -44,11 +46,11 @@ namespace VM {
|
|||
|
||||
Formatter& operator<< (Formatter& f, RegisterList& rl)
|
||||
{
|
||||
Register* e = rl.end();
|
||||
TypedRegister* e = rl.end();
|
||||
|
||||
f << "(";
|
||||
for (RegisterList::iterator r = rl.begin(); r != e; r++) {
|
||||
f << "R" << (*r);
|
||||
f << "R" << r->first;
|
||||
if ((r + 1) != e)
|
||||
f << ", ";
|
||||
}
|
||||
|
@ -64,11 +66,11 @@ namespace VM {
|
|||
f << "(";
|
||||
RegisterList::const_iterator i = rl.begin(), e = rl.end();
|
||||
if (i != e) {
|
||||
Register r = *i++;
|
||||
f << "R" << r << '=' << registers[r];
|
||||
TypedRegister r = *i++;
|
||||
f << "R" << r.first << '=' << registers[r.first];
|
||||
while (i != e) {
|
||||
r = *i++;
|
||||
f << ", R" << r << '=' << registers[r];
|
||||
f << ", R" << r.first << '=' << registers[r.first];
|
||||
}
|
||||
}
|
||||
f << ")";
|
||||
|
|
|
@ -49,9 +49,7 @@ namespace ICG {
|
|||
namespace JavaScript {
|
||||
namespace VM {
|
||||
|
||||
using JSTypes::JSValue;
|
||||
using JSTypes::JSValues;
|
||||
using JSTypes::JSString;
|
||||
using namespace JSTypes;
|
||||
|
||||
enum ICodeOp {
|
||||
ADD, /* dest, source1, source2 */
|
||||
|
@ -75,10 +73,10 @@ namespace VM {
|
|||
GET_PROP, /* dest, object, prop name */
|
||||
INSTANCEOF, /* dest, source1, source2 */
|
||||
JSR, /* target */
|
||||
LOAD_BOOLEAN, /* dest, immediate value (boolean) */
|
||||
LOAD_IMMEDIATE, /* dest, immediate value (double) */
|
||||
LOAD_NAME, /* dest, name */
|
||||
LOAD_STRING, /* dest, immediate value (string) */
|
||||
LOAD_VALUE, /* dest, immediate value (JSValue) */
|
||||
MOVE, /* dest, source */
|
||||
MULTIPLY, /* dest, source1, source2 */
|
||||
NAME_XCR, /* dest, name, value */
|
||||
|
@ -113,8 +111,6 @@ namespace VM {
|
|||
XOR, /* dest, source1, source2 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
static char *opcodeNames[] = {
|
||||
|
@ -139,10 +135,10 @@ namespace VM {
|
|||
"GET_PROP ",
|
||||
"INSTANCEOF ",
|
||||
"JSR ",
|
||||
"LOAD_BOOLEAN ",
|
||||
"LOAD_IMMEDIATE",
|
||||
"LOAD_NAME ",
|
||||
"LOAD_STRING ",
|
||||
"LOAD_VALUE ",
|
||||
"MOVE ",
|
||||
"MULTIPLY ",
|
||||
"NAME_XCR ",
|
||||
|
@ -233,10 +229,12 @@ namespace VM {
|
|||
/********************************************************************/
|
||||
|
||||
typedef uint32 Register;
|
||||
typedef std::vector<Register> RegisterList;
|
||||
typedef std::pair<Register, const JSType*> TypedRegister;
|
||||
typedef std::vector<TypedRegister> RegisterList;
|
||||
typedef std::vector<Instruction *> InstructionStream;
|
||||
typedef InstructionStream::iterator InstructionIterator;
|
||||
typedef std::map<String, Register, std::less<String> > VariableMap;
|
||||
typedef std::map<String, TypedRegister, std::less<String> > VariableMap;
|
||||
|
||||
|
||||
/**
|
||||
* Helper to print Call operands.
|
||||
|
@ -343,60 +341,59 @@ namespace VM {
|
|||
|
||||
/* Instruction groups */
|
||||
|
||||
class Arithmetic : public Instruction_3<Register, Register, Register> {
|
||||
class Arithmetic : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
Arithmetic (ICodeOp aOpcode, Register aDest, Register aSrc1,
|
||||
Register aSrc2) :
|
||||
Instruction_3<Register, Register, Register>(aOpcode, aDest, aSrc1,
|
||||
aSrc2) {}
|
||||
Arithmetic (ICodeOp aOpcode, TypedRegister aDest, TypedRegister aSrc1,
|
||||
TypedRegister aSrc2) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>(aOpcode, aDest, aSrc1, aSrc2) {}
|
||||
virtual Formatter& print(Formatter& f)
|
||||
{
|
||||
f << opcodeNames[mOpcode] << "\tR" << mOp1 << ", R" << mOp2 << ", R" << mOp3;
|
||||
f << opcodeNames[mOpcode] << "\tR" << mOp1.first << ", R" << mOp2.first << ", R" << mOp3.first;
|
||||
return f;
|
||||
}
|
||||
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers)
|
||||
{
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2] << ", " << "R" << mOp3 << '=' << registers[mOp3];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Unary : public Instruction_2<Register, Register> {
|
||||
class Unary : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
Unary(ICodeOp aOpcode, Register aDest, Register aSrc) :
|
||||
Instruction_2<Register, Register>(aOpcode, aDest, aSrc) {}
|
||||
Unary(ICodeOp aOpcode, TypedRegister aDest, TypedRegister aSrc) :
|
||||
Instruction_2<TypedRegister, TypedRegister>(aOpcode, aDest, aSrc) {}
|
||||
virtual Formatter& print (Formatter& f) {
|
||||
f << opcodeNames[mOpcode] << "\tR" << mOp1 << ", R" << mOp2;
|
||||
f << opcodeNames[mOpcode] << "\tR" << mOp1.first << ", R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers)
|
||||
{
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class GenericBranch : public Instruction_2<Label*, Register> {
|
||||
class GenericBranch : public Instruction_2<Label*, TypedRegister> {
|
||||
public:
|
||||
GenericBranch (ICodeOp aOpcode, Label* aLabel,
|
||||
Register aR = NotARegister) :
|
||||
Instruction_2<Label*, Register>(aOpcode, aLabel, aR) {}
|
||||
TypedRegister aR = TypedRegister(NotARegister, &Any_Type) ) :
|
||||
Instruction_2<Label*, TypedRegister>(aOpcode, aLabel, aR) {}
|
||||
virtual Formatter& print (Formatter& f) {
|
||||
f << opcodeNames[mOpcode] << "\tOffset " << mOp1->mOffset;
|
||||
if (mOp2 == NotARegister) {
|
||||
if (mOp2.first == NotARegister) {
|
||||
f << ", R~";
|
||||
} else {
|
||||
f << ", R" << mOp2;
|
||||
f << ", R" << mOp2.first;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers)
|
||||
{
|
||||
if (mOp2 != NotARegister)
|
||||
f << "R" << mOp2 << '=' << registers[mOp2];
|
||||
if (mOp2.first != NotARegister)
|
||||
f << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
|
||||
|
@ -411,7 +408,7 @@ namespace VM {
|
|||
class Add : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Add (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Add (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(ADD, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
|
@ -420,24 +417,24 @@ namespace VM {
|
|||
class And : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
And (Register aOp1, Register aOp2, Register aOp3) :
|
||||
And (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(AND, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class Bitnot : public Instruction_2<Register, Register> {
|
||||
class Bitnot : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Bitnot (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Bitnot (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(BITNOT, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[BITNOT] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[BITNOT] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -460,7 +457,7 @@ namespace VM {
|
|||
class BranchFalse : public GenericBranch {
|
||||
public:
|
||||
/* target label, condition */
|
||||
BranchFalse (Label* aOp1, Register aOp2) :
|
||||
BranchFalse (Label* aOp1, TypedRegister aOp2) :
|
||||
GenericBranch
|
||||
(BRANCH_FALSE, aOp1, aOp2) {};
|
||||
/* print() and printOperands() inherited from GenericBranch */
|
||||
|
@ -469,155 +466,155 @@ namespace VM {
|
|||
class BranchTrue : public GenericBranch {
|
||||
public:
|
||||
/* target label, condition */
|
||||
BranchTrue (Label* aOp1, Register aOp2) :
|
||||
BranchTrue (Label* aOp1, TypedRegister aOp2) :
|
||||
GenericBranch
|
||||
(BRANCH_TRUE, aOp1, aOp2) {};
|
||||
/* print() and printOperands() inherited from GenericBranch */
|
||||
};
|
||||
|
||||
class Call : public Instruction_3<Register, Register, RegisterList> {
|
||||
class Call : public Instruction_3<TypedRegister, TypedRegister, RegisterList> {
|
||||
public:
|
||||
/* result, target, args */
|
||||
Call (Register aOp1, Register aOp2, RegisterList aOp3) :
|
||||
Instruction_3<Register, Register, RegisterList>
|
||||
Call (TypedRegister aOp1, TypedRegister aOp2, RegisterList aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, RegisterList>
|
||||
(CALL, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[CALL] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << mOp3;
|
||||
f << opcodeNames[CALL] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << mOp3;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2] << ", " << ArgList(mOp3, registers);
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << ArgList(mOp3, registers);
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class CompareEQ : public Instruction_3<Register, Register, Register> {
|
||||
class CompareEQ : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareEQ (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareEQ (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_EQ, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareGE : public Instruction_3<Register, Register, Register> {
|
||||
class CompareGE : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareGE (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareGE (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_GE, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareGT : public Instruction_3<Register, Register, Register> {
|
||||
class CompareGT : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareGT (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareGT (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_GT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareIN : public Instruction_3<Register, Register, Register> {
|
||||
class CompareIN : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareIN (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareIN (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_IN, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareLE : public Instruction_3<Register, Register, Register> {
|
||||
class CompareLE : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareLE (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareLE (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_LE, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareLT : public Instruction_3<Register, Register, Register> {
|
||||
class CompareLT : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareLT (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareLT (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_LT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class CompareNE : public Instruction_3<Register, Register, Register> {
|
||||
class CompareNE : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
CompareNE (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
CompareNE (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(COMPARE_NE, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class Divide : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Divide (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Divide (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(DIVIDE, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class ElemXcr : public Instruction_4<Register, Register, Register, double> {
|
||||
class ElemXcr : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, double> {
|
||||
public:
|
||||
/* dest, base, index, value */
|
||||
ElemXcr (Register aOp1, Register aOp2, Register aOp3, double aOp4) :
|
||||
Instruction_4<Register, Register, Register, double>
|
||||
ElemXcr (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, double aOp4) :
|
||||
Instruction_4<TypedRegister, TypedRegister, TypedRegister, double>
|
||||
(ELEM_XCR, aOp1, aOp2, aOp3, aOp4) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[ELEM_XCR] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << "R" << mOp3 << ", " << mOp4;
|
||||
f << opcodeNames[ELEM_XCR] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << "R" << mOp3.first << ", " << mOp4;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2] << ", " << "R" << mOp3 << '=' << registers[mOp3];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class GetElement : public Instruction_3<Register, Register, Register> {
|
||||
class GetElement : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, base, index */
|
||||
GetElement (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
GetElement (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(GET_ELEMENT, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[GET_ELEMENT] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << "R" << mOp3;
|
||||
f << opcodeNames[GET_ELEMENT] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << "R" << mOp3.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2] << ", " << "R" << mOp3 << '=' << registers[mOp3];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class GetProp : public Instruction_3<Register, Register, const StringAtom*> {
|
||||
class GetProp : public Instruction_3<TypedRegister, TypedRegister, const StringAtom*> {
|
||||
public:
|
||||
/* dest, object, prop name */
|
||||
GetProp (Register aOp1, Register aOp2, const StringAtom* aOp3) :
|
||||
Instruction_3<Register, Register, const StringAtom*>
|
||||
GetProp (TypedRegister aOp1, TypedRegister aOp2, const StringAtom* aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, const StringAtom*>
|
||||
(GET_PROP, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[GET_PROP] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << "'" << *mOp3 << "'";
|
||||
f << opcodeNames[GET_PROP] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << "'" << *mOp3 << "'";
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Instanceof : public Instruction_3<Register, Register, Register> {
|
||||
class Instanceof : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Instanceof (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
Instanceof (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(INSTANCEOF, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class Jsr : public GenericBranch {
|
||||
|
@ -635,82 +632,82 @@ namespace VM {
|
|||
}
|
||||
};
|
||||
|
||||
class LoadImmediate : public Instruction_2<Register, double> {
|
||||
class LoadBoolean : public Instruction_2<TypedRegister, bool> {
|
||||
public:
|
||||
/* dest, immediate value (boolean) */
|
||||
LoadBoolean (TypedRegister aOp1, bool aOp2) :
|
||||
Instruction_2<TypedRegister, bool>
|
||||
(LOAD_BOOLEAN, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[LOAD_BOOLEAN] << "\t" << "R" << mOp1.first << ", " << "'" << ((mOp2) ? "true" : "false") << "'";
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadImmediate : public Instruction_2<TypedRegister, double> {
|
||||
public:
|
||||
/* dest, immediate value (double) */
|
||||
LoadImmediate (Register aOp1, double aOp2) :
|
||||
Instruction_2<Register, double>
|
||||
LoadImmediate (TypedRegister aOp1, double aOp2) :
|
||||
Instruction_2<TypedRegister, double>
|
||||
(LOAD_IMMEDIATE, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[LOAD_IMMEDIATE] << "\t" << "R" << mOp1 << ", " << mOp2;
|
||||
f << opcodeNames[LOAD_IMMEDIATE] << "\t" << "R" << mOp1.first << ", " << mOp2;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadName : public Instruction_2<Register, const StringAtom*> {
|
||||
class LoadName : public Instruction_2<TypedRegister, const StringAtom*> {
|
||||
public:
|
||||
/* dest, name */
|
||||
LoadName (Register aOp1, const StringAtom* aOp2) :
|
||||
Instruction_2<Register, const StringAtom*>
|
||||
LoadName (TypedRegister aOp1, const StringAtom* aOp2) :
|
||||
Instruction_2<TypedRegister, const StringAtom*>
|
||||
(LOAD_NAME, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[LOAD_NAME] << "\t" << "R" << mOp1 << ", " << "'" << *mOp2 << "'";
|
||||
f << opcodeNames[LOAD_NAME] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'";
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadString : public Instruction_2<Register, JSString*> {
|
||||
class LoadString : public Instruction_2<TypedRegister, JSString*> {
|
||||
public:
|
||||
/* dest, immediate value (string) */
|
||||
LoadString (Register aOp1, JSString* aOp2) :
|
||||
Instruction_2<Register, JSString*>
|
||||
LoadString (TypedRegister aOp1, JSString* aOp2) :
|
||||
Instruction_2<TypedRegister, JSString*>
|
||||
(LOAD_STRING, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[LOAD_STRING] << "\t" << "R" << mOp1 << ", " << "'" << *mOp2 << "'";
|
||||
f << opcodeNames[LOAD_STRING] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'";
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadValue : public Instruction_2<Register, JSValue> {
|
||||
public:
|
||||
/* dest, immediate value (JSValue) */
|
||||
LoadValue (Register aOp1, JSValue aOp2) :
|
||||
Instruction_2<Register, JSValue>
|
||||
(LOAD_VALUE, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[LOAD_VALUE] << "\t" << "R" << mOp1 << ", " << mOp2;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Move : public Instruction_2<Register, Register> {
|
||||
class Move : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Move (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Move (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(MOVE, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[MOVE] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[MOVE] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -718,72 +715,72 @@ namespace VM {
|
|||
class Multiply : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Multiply (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Multiply (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(MULTIPLY, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class NameXcr : public Instruction_3<Register, const StringAtom*, double> {
|
||||
class NameXcr : public Instruction_3<TypedRegister, const StringAtom*, double> {
|
||||
public:
|
||||
/* dest, name, value */
|
||||
NameXcr (Register aOp1, const StringAtom* aOp2, double aOp3) :
|
||||
Instruction_3<Register, const StringAtom*, double>
|
||||
NameXcr (TypedRegister aOp1, const StringAtom* aOp2, double aOp3) :
|
||||
Instruction_3<TypedRegister, const StringAtom*, double>
|
||||
(NAME_XCR, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[NAME_XCR] << "\t" << "R" << mOp1 << ", " << "'" << *mOp2 << "'" << ", " << mOp3;
|
||||
f << opcodeNames[NAME_XCR] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << mOp3;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Negate : public Instruction_2<Register, Register> {
|
||||
class Negate : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Negate (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Negate (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(NEGATE, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[NEGATE] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[NEGATE] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class NewArray : public Instruction_1<Register> {
|
||||
class NewArray : public Instruction_1<TypedRegister> {
|
||||
public:
|
||||
/* dest */
|
||||
NewArray (Register aOp1) :
|
||||
Instruction_1<Register>
|
||||
NewArray (TypedRegister aOp1) :
|
||||
Instruction_1<TypedRegister>
|
||||
(NEW_ARRAY, aOp1) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[NEW_ARRAY] << "\t" << "R" << mOp1;
|
||||
f << opcodeNames[NEW_ARRAY] << "\t" << "R" << mOp1.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class NewObject : public Instruction_1<Register> {
|
||||
class NewObject : public Instruction_1<TypedRegister> {
|
||||
public:
|
||||
/* dest */
|
||||
NewObject (Register aOp1) :
|
||||
Instruction_1<Register>
|
||||
NewObject (TypedRegister aOp1) :
|
||||
Instruction_1<TypedRegister>
|
||||
(NEW_OBJECT, aOp1) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[NEW_OBJECT] << "\t" << "R" << mOp1;
|
||||
f << opcodeNames[NEW_OBJECT] << "\t" << "R" << mOp1.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -803,18 +800,18 @@ namespace VM {
|
|||
}
|
||||
};
|
||||
|
||||
class Not : public Instruction_2<Register, Register> {
|
||||
class Not : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Not (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Not (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(NOT, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[NOT] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[NOT] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -822,40 +819,40 @@ namespace VM {
|
|||
class Or : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Or (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Or (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(OR, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class Posate : public Instruction_2<Register, Register> {
|
||||
class Posate : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Posate (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Posate (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(POSATE, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[POSATE] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[POSATE] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class PropXcr : public Instruction_4<Register, Register, const StringAtom*, double> {
|
||||
class PropXcr : public Instruction_4<TypedRegister, TypedRegister, const StringAtom*, double> {
|
||||
public:
|
||||
/* dest, source, name, value */
|
||||
PropXcr (Register aOp1, Register aOp2, const StringAtom* aOp3, double aOp4) :
|
||||
Instruction_4<Register, Register, const StringAtom*, double>
|
||||
PropXcr (TypedRegister aOp1, TypedRegister aOp2, const StringAtom* aOp3, double aOp4) :
|
||||
Instruction_4<TypedRegister, TypedRegister, const StringAtom*, double>
|
||||
(PROP_XCR, aOp1, aOp2, aOp3, aOp4) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[PROP_XCR] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << "'" << *mOp3 << "'" << ", " << mOp4;
|
||||
f << opcodeNames[PROP_XCR] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << "'" << *mOp3 << "'" << ", " << mOp4;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -863,24 +860,24 @@ namespace VM {
|
|||
class Remainder : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Remainder (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Remainder (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(REMAINDER, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class Return : public Instruction_1<Register> {
|
||||
class Return : public Instruction_1<TypedRegister> {
|
||||
public:
|
||||
/* return value */
|
||||
Return (Register aOp1) :
|
||||
Instruction_1<Register>
|
||||
Return (TypedRegister aOp1) :
|
||||
Instruction_1<TypedRegister>
|
||||
(RETURN, aOp1) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[RETURN] << "\t" << "R" << mOp1;
|
||||
f << opcodeNames[RETURN] << "\t" << "R" << mOp1.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -915,50 +912,50 @@ namespace VM {
|
|||
}
|
||||
};
|
||||
|
||||
class SaveName : public Instruction_2<const StringAtom*, Register> {
|
||||
class SaveName : public Instruction_2<const StringAtom*, TypedRegister> {
|
||||
public:
|
||||
/* name, source */
|
||||
SaveName (const StringAtom* aOp1, Register aOp2) :
|
||||
Instruction_2<const StringAtom*, Register>
|
||||
SaveName (const StringAtom* aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<const StringAtom*, TypedRegister>
|
||||
(SAVE_NAME, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[SAVE_NAME] << "\t" << "'" << *mOp1 << "'" << ", " << "R" << mOp2;
|
||||
f << opcodeNames[SAVE_NAME] << "\t" << "'" << *mOp1 << "'" << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class SetElement : public Instruction_3<Register, Register, Register> {
|
||||
class SetElement : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* base, index, value */
|
||||
SetElement (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
SetElement (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(SET_ELEMENT, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[SET_ELEMENT] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << "R" << mOp3;
|
||||
f << opcodeNames[SET_ELEMENT] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << "R" << mOp3.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2] << ", " << "R" << mOp3 << '=' << registers[mOp3];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class SetProp : public Instruction_3<Register, const StringAtom*, Register> {
|
||||
class SetProp : public Instruction_3<TypedRegister, const StringAtom*, TypedRegister> {
|
||||
public:
|
||||
/* object, name, source */
|
||||
SetProp (Register aOp1, const StringAtom* aOp2, Register aOp3) :
|
||||
Instruction_3<Register, const StringAtom*, Register>
|
||||
SetProp (TypedRegister aOp1, const StringAtom* aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, const StringAtom*, TypedRegister>
|
||||
(SET_PROP, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[SET_PROP] << "\t" << "R" << mOp1 << ", " << "'" << *mOp2 << "'" << ", " << "R" << mOp3;
|
||||
f << opcodeNames[SET_PROP] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << "R" << mOp3.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp3 << '=' << registers[mOp3];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -966,7 +963,7 @@ namespace VM {
|
|||
class Shiftleft : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Shiftleft (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Shiftleft (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(SHIFTLEFT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
|
@ -975,67 +972,67 @@ namespace VM {
|
|||
class Shiftright : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Shiftright (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Shiftright (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(SHIFTRIGHT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class StrictEQ : public Instruction_3<Register, Register, Register> {
|
||||
class StrictEQ : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
StrictEQ (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
StrictEQ (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(STRICT_EQ, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class StrictNE : public Instruction_3<Register, Register, Register> {
|
||||
class StrictNE : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
StrictNE (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Instruction_3<Register, Register, Register>
|
||||
StrictNE (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, TypedRegister>
|
||||
(STRICT_NE, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Instruction_3<Register, Register, Register> */
|
||||
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
|
||||
};
|
||||
|
||||
class Subtract : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Subtract (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Subtract (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(SUBTRACT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class Test : public Instruction_2<Register, Register> {
|
||||
class Test : public Instruction_2<TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source */
|
||||
Test (Register aOp1, Register aOp2) :
|
||||
Instruction_2<Register, Register>
|
||||
Test (TypedRegister aOp1, TypedRegister aOp2) :
|
||||
Instruction_2<TypedRegister, TypedRegister>
|
||||
(TEST, aOp1, aOp2) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[TEST] << "\t" << "R" << mOp1 << ", " << "R" << mOp2;
|
||||
f << opcodeNames[TEST] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Throw : public Instruction_1<Register> {
|
||||
class Throw : public Instruction_1<TypedRegister> {
|
||||
public:
|
||||
/* exception value */
|
||||
Throw (Register aOp1) :
|
||||
Instruction_1<Register>
|
||||
Throw (TypedRegister aOp1) :
|
||||
Instruction_1<TypedRegister>
|
||||
(THROW, aOp1) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[THROW] << "\t" << "R" << mOp1;
|
||||
f << opcodeNames[THROW] << "\t" << "R" << mOp1.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -1073,40 +1070,40 @@ namespace VM {
|
|||
class Ushiftright : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Ushiftright (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Ushiftright (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(USHIFTRIGHT, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class VarXcr : public Instruction_3<Register, Register, double> {
|
||||
class VarXcr : public Instruction_3<TypedRegister, TypedRegister, double> {
|
||||
public:
|
||||
/* dest, source, value */
|
||||
VarXcr (Register aOp1, Register aOp2, double aOp3) :
|
||||
Instruction_3<Register, Register, double>
|
||||
VarXcr (TypedRegister aOp1, TypedRegister aOp2, double aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, double>
|
||||
(VAR_XCR, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[VAR_XCR] << "\t" << "R" << mOp1 << ", " << "R" << mOp2 << ", " << mOp3;
|
||||
f << opcodeNames[VAR_XCR] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << mOp3;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1] << ", " << "R" << mOp2 << '=' << registers[mOp2];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Within : public Instruction_1<Register> {
|
||||
class Within : public Instruction_1<TypedRegister> {
|
||||
public:
|
||||
/* within this object */
|
||||
Within (Register aOp1) :
|
||||
Instruction_1<Register>
|
||||
Within (TypedRegister aOp1) :
|
||||
Instruction_1<TypedRegister>
|
||||
(WITHIN, aOp1) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[WITHIN] << "\t" << "R" << mOp1;
|
||||
f << opcodeNames[WITHIN] << "\t" << "R" << mOp1.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1 << '=' << registers[mOp1];
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
@ -1129,14 +1126,12 @@ namespace VM {
|
|||
class Xor : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
Xor (Register aOp1, Register aOp2, Register aOp3) :
|
||||
Xor (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3) :
|
||||
Arithmetic
|
||||
(XOR, aOp1, aOp2, aOp3) {};
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
|
||||
|
||||
} /* namespace VM */
|
||||
|
||||
} /* namespace JavaScript */
|
||||
|
|
|
@ -101,9 +101,10 @@ static JSValue print(const JSValues &argv)
|
|||
|
||||
static void genCode(World &world, Context &cx, StmtNode *p)
|
||||
{
|
||||
ICodeGenerator icg(&world);
|
||||
JSScope glob;
|
||||
ICodeGenerator icg(&world, &glob);
|
||||
icg.isScript();
|
||||
Register ret = NotARegister;
|
||||
TypedRegister ret(NotARegister, &None_Type);
|
||||
while (p) {
|
||||
ret = icg.genStmt(p);
|
||||
p = p->next;
|
||||
|
@ -210,86 +211,6 @@ class Tracer : public Context::Listener {
|
|||
};
|
||||
|
||||
|
||||
static float64 testFactorial(World &world, float64 n)
|
||||
{
|
||||
JSScope glob;
|
||||
Context cx(world, &glob);
|
||||
// generate code for factorial, and interpret it.
|
||||
uint32 pos = 0;
|
||||
ICodeGenerator icg(&world);
|
||||
|
||||
// fact(n) {
|
||||
// var result = 1;
|
||||
|
||||
StringAtom &n_name = world.identifiers[widenCString("n")];
|
||||
StringAtom &result_name = world.identifiers[widenCString("result")];
|
||||
|
||||
Register r_n = icg.allocateParameter(n_name);
|
||||
Register r_result = icg.allocateVariable(result_name);
|
||||
|
||||
Arena a;
|
||||
|
||||
ExprStmtNode *e = new(a) ExprStmtNode(pos, StmtNode::expression, new(a) BinaryExprNode(pos, ExprNode::assignment,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, result_name),
|
||||
new(a) NumberExprNode(pos, 1.0) ) );
|
||||
icg.genStmt(e);
|
||||
|
||||
// while (n > 1) {
|
||||
// result = result * n;
|
||||
// n = n - 1;
|
||||
// }
|
||||
{
|
||||
BinaryExprNode *c = new(a) BinaryExprNode(pos, ExprNode::greaterThan,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, n_name),
|
||||
new(a) NumberExprNode(pos, 1.0) ) ;
|
||||
ExprStmtNode *e1 = new(a) ExprStmtNode(pos, StmtNode::expression, new(a) BinaryExprNode(pos, ExprNode::assignment,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, result_name),
|
||||
new(a) BinaryExprNode(pos, ExprNode::multiply,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, result_name),
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, n_name) ) ) );
|
||||
ExprStmtNode *e2 = new(a) ExprStmtNode(pos, StmtNode::expression, new(a) BinaryExprNode(pos, ExprNode::assignment,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, n_name),
|
||||
new(a) BinaryExprNode(pos, ExprNode::subtract,
|
||||
new(a) IdentifierExprNode(pos, ExprNode::identifier, n_name),
|
||||
new(a) NumberExprNode(pos, 1.0) ) ) );
|
||||
e1->next = e2;
|
||||
BlockStmtNode *b = new(a) BlockStmtNode(pos, StmtNode::block, NULL, e1);
|
||||
|
||||
UnaryStmtNode *w = new(a) UnaryStmtNode(pos, StmtNode::While, c, b);
|
||||
|
||||
icg.genStmt(w);
|
||||
|
||||
}
|
||||
|
||||
// return result;
|
||||
icg.returnStmt(r_result);
|
||||
ICodeModule *icm = icg.complete();
|
||||
stdOut << icg;
|
||||
|
||||
// preset the global property "fact" to contain the above function
|
||||
StringAtom& fact = world.identifiers[widenCString("fact")];
|
||||
glob.defineFunction(fact, icm);
|
||||
|
||||
// now a script :
|
||||
// return fact(n);
|
||||
ICodeGenerator script(&world);
|
||||
RegisterList args(1);
|
||||
args[0] = script.loadImmediate(n);
|
||||
script.returnStmt(script.call(script.loadName(fact), args));
|
||||
stdOut << script;
|
||||
|
||||
// install a listener so we can trace execution of factorial.
|
||||
Tracer t;
|
||||
cx.addListener(&t);
|
||||
|
||||
// test the iCode interpreter.
|
||||
JSValue result = cx.interpret(script.complete(), JSValues());
|
||||
stdOut << "fact(" << n << ") = " << result.f64 << "\n";
|
||||
|
||||
delete icm;
|
||||
|
||||
return result.f64;
|
||||
}
|
||||
|
||||
char * tests[] = {
|
||||
"function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" ,
|
||||
|
@ -308,8 +229,8 @@ void testCompile()
|
|||
Arena a;
|
||||
Parser p(world, a, testScript, widenCString("testCompile"));
|
||||
StmtNode *parsedStatements = p.parseProgram();
|
||||
|
||||
ICodeGenerator icg(&world);
|
||||
JSScope glob;
|
||||
ICodeGenerator icg(&world, &glob);
|
||||
icg.isScript();
|
||||
while (parsedStatements) {
|
||||
icg.genStmt(parsedStatements);
|
||||
|
@ -333,7 +254,6 @@ int main(int argc, char **argv)
|
|||
using namespace JavaScript;
|
||||
using namespace Shell;
|
||||
#if 0
|
||||
assert(testFactorial(world, 5) == 120);
|
||||
testCompile();
|
||||
#endif
|
||||
readEvalPrint(stdin, world);
|
||||
|
|
Загрузка…
Ссылка в новой задаче