mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-23 13:04:28 +00:00
Adding slot handling to code gen.
This commit is contained in:
parent
841b79b5eb
commit
e939fbddc4
@ -46,6 +46,7 @@ namespace ICG {
|
||||
|
||||
using namespace VM;
|
||||
using namespace JSTypes;
|
||||
using namespace JSClasses;
|
||||
|
||||
uint32 ICodeModule::sMaxID = 0;
|
||||
|
||||
@ -80,7 +81,7 @@ ICodeGenerator::ICodeGenerator(World *world, JSScope *global)
|
||||
iCodeOwner = true;
|
||||
}
|
||||
|
||||
const JSType *ICodeGenerator::findType(const StringAtom& typeName)
|
||||
JSType *ICodeGenerator::findType(const StringAtom& typeName)
|
||||
{
|
||||
const JSValue& type = mGlobal->getVariable(typeName);
|
||||
if (type.isType())
|
||||
@ -293,6 +294,39 @@ TypedRegister ICodeGenerator::propertyDec(TypedRegister base, const StringAtom &
|
||||
|
||||
|
||||
|
||||
TypedRegister ICodeGenerator::getSlot(TypedRegister base, uint32 slot)
|
||||
{
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
GetSlot *instr = new GetSlot(dest, base, slot);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void ICodeGenerator::setSlot(TypedRegister base, uint32 slot,
|
||||
TypedRegister value)
|
||||
{
|
||||
SetSlot *instr = new SetSlot(base, slot, value);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::slotInc(TypedRegister base, uint32 slot)
|
||||
{
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
SlotXcr *instr = new SlotXcr(dest, base, slot, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::slotDec(TypedRegister base, uint32 slot)
|
||||
{
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
SlotXcr *instr = new SlotXcr(dest, base, slot, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TypedRegister ICodeGenerator::getElement(TypedRegister base, TypedRegister index)
|
||||
{
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
@ -545,6 +579,19 @@ static bool generatedBoolean(ExprNode *p)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex)
|
||||
{
|
||||
if (t->isClassType()) {
|
||||
JSClass *c = static_cast<JSClass *>(t);
|
||||
if (c->hasSlot(name)) {
|
||||
JSSlot &s = c->getSlot(name);
|
||||
slotIndex = s.mIndex;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if trueBranch OR falseBranch are not null, the sub-expression should generate
|
||||
a conditional branch to the appropriate target. If either branch is NULL, it
|
||||
@ -628,7 +675,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
case ExprNode::index :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
}
|
||||
@ -636,8 +683,13 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
case ExprNode::dot :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex))
|
||||
ret = getSlot(base, slotIndex);
|
||||
else
|
||||
ret = getProperty(base, name);
|
||||
}
|
||||
break;
|
||||
case ExprNode::This :
|
||||
@ -670,9 +722,18 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
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);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex)) {
|
||||
ret = slotInc(base, slotIndex);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setSlot(base, slotIndex, ret);
|
||||
}
|
||||
else {
|
||||
ret = getProperty(base, name);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setProperty(base, name, ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
@ -711,7 +772,12 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = propertyInc(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex))
|
||||
ret = slotInc(base, slotIndex);
|
||||
else
|
||||
ret = propertyInc(base, name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
@ -742,9 +808,18 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
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);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex)) {
|
||||
ret = getSlot(base, slotIndex);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setSlot(base, slotIndex, ret);
|
||||
}
|
||||
else {
|
||||
ret = getProperty(base, name);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setProperty(base, name, ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
@ -783,7 +858,12 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = propertyDec(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex))
|
||||
slotDec(base, slotIndex);
|
||||
else
|
||||
ret = propertyDec(base, name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
@ -853,8 +933,13 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name, ret);
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex))
|
||||
setSlot(base, slotIndex, ret);
|
||||
else
|
||||
setProperty(base, name, ret);
|
||||
}
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
@ -904,9 +989,18 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
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);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(lb->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex)) {
|
||||
TypedRegister v = getSlot(base, slotIndex);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setSlot(base, slotIndex, ret);
|
||||
}
|
||||
else {
|
||||
TypedRegister v = getProperty(base, name);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setProperty(base, name, ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
@ -1232,7 +1326,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
case StmtNode::Class:
|
||||
{
|
||||
// FIXME: need a semantic check to make sure a class isn't being redefined(?)
|
||||
using JSClasses::JSClass;
|
||||
ClassStmtNode *classStmt = static_cast<ClassStmtNode *>(p);
|
||||
ASSERT(classStmt->name->getKind() == ExprNode::identifier);
|
||||
IdentifierExprNode* nameExpr = static_cast<IdentifierExprNode*>(classStmt->name);
|
||||
@ -1490,11 +1583,14 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
genStmt(f->stmt);
|
||||
|
||||
setLabel(e->continueLabel);
|
||||
if (f->expr3)
|
||||
if (f->expr3) {
|
||||
(*mInstructionMap)[iCode->size()] = f->expr3->pos;
|
||||
genExpr(f->expr3);
|
||||
}
|
||||
|
||||
setLabel(forTestLabel);
|
||||
if (f->expr2) {
|
||||
(*mInstructionMap)[iCode->size()] = f->expr2->pos;
|
||||
TypedRegister c = genExpr(f->expr2, false, forBlockTop, NULL);
|
||||
if (!generatedBoolean(f->expr2))
|
||||
branchTrue(forBlockTop, test(c));
|
||||
|
@ -168,7 +168,7 @@ namespace ICG {
|
||||
|
||||
ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind);
|
||||
|
||||
TypedRegister grabRegister(const StringAtom& name, const JSType *type)
|
||||
TypedRegister grabRegister(const StringAtom& name, JSType *type)
|
||||
{
|
||||
TypedRegister result(getRegister(), type);
|
||||
(*variableList)[name] = result;
|
||||
@ -176,7 +176,7 @@ namespace ICG {
|
||||
return result;
|
||||
}
|
||||
|
||||
const JSType *findType(const StringAtom& typeName);
|
||||
JSType *findType(const StringAtom& typeName);
|
||||
|
||||
public:
|
||||
ICodeGenerator(World *world, JSScope *global);
|
||||
@ -254,6 +254,11 @@ namespace ICG {
|
||||
TypedRegister elementInc(TypedRegister base, TypedRegister index);
|
||||
TypedRegister elementDec(TypedRegister base, TypedRegister index);
|
||||
|
||||
TypedRegister getSlot(TypedRegister base, uint32 slot);
|
||||
void setSlot(TypedRegister base, uint32 slot, TypedRegister value);
|
||||
TypedRegister slotInc(TypedRegister base, uint32 slot);
|
||||
TypedRegister slotDec(TypedRegister base, uint32 slot);
|
||||
|
||||
TypedRegister varInc(TypedRegister var);
|
||||
TypedRegister varDec(TypedRegister var);
|
||||
|
||||
|
@ -88,6 +88,8 @@ namespace JSClasses {
|
||||
JSClass* getSuperClass() { return mSuperClass; }
|
||||
JSScope* getScope() { return mScope; }
|
||||
|
||||
virtual bool isClassType() const { return true; }
|
||||
|
||||
JSSlot& addSlot(const String& name, const JSType* type)
|
||||
{
|
||||
JSSlot& slot = mSlots[name];
|
||||
|
@ -450,6 +450,8 @@ namespace JSTypes {
|
||||
|
||||
const String& getName() const { return mName; }
|
||||
|
||||
virtual bool isClassType() const { return false; }
|
||||
|
||||
int32 distance(const JSType *other) const;
|
||||
};
|
||||
|
||||
|
@ -150,6 +150,24 @@ $ops{"SET_PROP"} =
|
||||
rem => "object, name, source",
|
||||
params => [ ("TypedRegister", "const StringAtom*", "TypedRegister") ]
|
||||
};
|
||||
$ops{"GET_SLOT"} =
|
||||
{
|
||||
super => "Instruction_3",
|
||||
rem => "dest, object, slot number",
|
||||
params => [ ("TypedRegister", "TypedRegister", "uint32") ]
|
||||
};
|
||||
$ops{"SET_SLOT"} =
|
||||
{
|
||||
super => "Instruction_3",
|
||||
rem => "object, slot number, source",
|
||||
params => [ ("TypedRegister", "uint32", "TypedRegister") ]
|
||||
};
|
||||
$ops{"SLOT_XCR"} =
|
||||
{
|
||||
super => "Instruction_4",
|
||||
rem => "dest, source, slot number, value",
|
||||
params => [ ("TypedRegister", "TypedRegister", "uint32", "double") ]
|
||||
};
|
||||
$ops{"PROP_XCR"} =
|
||||
{
|
||||
super => "Instruction_4",
|
||||
|
@ -71,6 +71,7 @@ namespace VM {
|
||||
ELEM_XCR, /* dest, base, index, value */
|
||||
GET_ELEMENT, /* dest, base, index */
|
||||
GET_PROP, /* dest, object, prop name */
|
||||
GET_SLOT, /* dest, object, slot number */
|
||||
INSTANCEOF, /* dest, source1, source2 */
|
||||
JSR, /* target */
|
||||
LOAD_BOOLEAN, /* dest, immediate value (boolean) */
|
||||
@ -97,8 +98,10 @@ namespace VM {
|
||||
SAVE_NAME, /* name, source */
|
||||
SET_ELEMENT, /* base, index, value */
|
||||
SET_PROP, /* object, name, source */
|
||||
SET_SLOT, /* object, slot number, source */
|
||||
SHIFTLEFT, /* dest, source1, source2 */
|
||||
SHIFTRIGHT, /* dest, source1, source2 */
|
||||
SLOT_XCR, /* dest, source, slot number, value */
|
||||
STRICT_EQ, /* dest, source1, source2 */
|
||||
STRICT_NE, /* dest, source1, source2 */
|
||||
SUBTRACT, /* dest, source1, source2 */
|
||||
@ -135,6 +138,7 @@ namespace VM {
|
||||
"ELEM_XCR ",
|
||||
"GET_ELEMENT ",
|
||||
"GET_PROP ",
|
||||
"GET_SLOT ",
|
||||
"INSTANCEOF ",
|
||||
"JSR ",
|
||||
"LOAD_BOOLEAN ",
|
||||
@ -161,8 +165,10 @@ namespace VM {
|
||||
"SAVE_NAME ",
|
||||
"SET_ELEMENT ",
|
||||
"SET_PROP ",
|
||||
"SET_SLOT ",
|
||||
"SHIFTLEFT ",
|
||||
"SHIFTRIGHT ",
|
||||
"SLOT_XCR ",
|
||||
"STRICT_EQ ",
|
||||
"STRICT_NE ",
|
||||
"SUBTRACT ",
|
||||
@ -216,7 +222,7 @@ namespace VM {
|
||||
/********************************************************************/
|
||||
|
||||
typedef uint32 Register;
|
||||
typedef std::pair<Register, const JSType*> TypedRegister;
|
||||
typedef std::pair<Register, JSType*> TypedRegister;
|
||||
typedef std::vector<TypedRegister> RegisterList;
|
||||
typedef std::vector<Instruction *> InstructionStream;
|
||||
typedef InstructionStream::iterator InstructionIterator;
|
||||
@ -610,6 +616,22 @@ namespace VM {
|
||||
}
|
||||
};
|
||||
|
||||
class GetSlot : public Instruction_3<TypedRegister, TypedRegister, uint32> {
|
||||
public:
|
||||
/* dest, object, slot number */
|
||||
GetSlot (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, uint32>
|
||||
(GET_SLOT, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[GET_SLOT] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << mOp3;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Instanceof : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
@ -994,6 +1016,22 @@ namespace VM {
|
||||
}
|
||||
};
|
||||
|
||||
class SetSlot : public Instruction_3<TypedRegister, uint32, TypedRegister> {
|
||||
public:
|
||||
/* object, slot number, source */
|
||||
SetSlot (TypedRegister aOp1, uint32 aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, uint32, TypedRegister>
|
||||
(SET_SLOT, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[SET_SLOT] << "\t" << "R" << mOp1.first << ", " << mOp2 << ", " << "R" << mOp3.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Shiftleft : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
@ -1012,6 +1050,22 @@ namespace VM {
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class SlotXcr : public Instruction_4<TypedRegister, TypedRegister, uint32, double> {
|
||||
public:
|
||||
/* dest, source, slot number, value */
|
||||
SlotXcr (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3, double aOp4) :
|
||||
Instruction_4<TypedRegister, TypedRegister, uint32, double>
|
||||
(SLOT_XCR, aOp1, aOp2, aOp3, aOp4) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[SLOT_XCR] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << mOp3 << ", " << mOp4;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class StrictEQ : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
|
@ -46,6 +46,7 @@ namespace ICG {
|
||||
|
||||
using namespace VM;
|
||||
using namespace JSTypes;
|
||||
using namespace JSClasses;
|
||||
|
||||
uint32 ICodeModule::sMaxID = 0;
|
||||
|
||||
@ -80,7 +81,7 @@ ICodeGenerator::ICodeGenerator(World *world, JSScope *global)
|
||||
iCodeOwner = true;
|
||||
}
|
||||
|
||||
const JSType *ICodeGenerator::findType(const StringAtom& typeName)
|
||||
JSType *ICodeGenerator::findType(const StringAtom& typeName)
|
||||
{
|
||||
const JSValue& type = mGlobal->getVariable(typeName);
|
||||
if (type.isType())
|
||||
@ -293,6 +294,39 @@ TypedRegister ICodeGenerator::propertyDec(TypedRegister base, const StringAtom &
|
||||
|
||||
|
||||
|
||||
TypedRegister ICodeGenerator::getSlot(TypedRegister base, uint32 slot)
|
||||
{
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
GetSlot *instr = new GetSlot(dest, base, slot);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void ICodeGenerator::setSlot(TypedRegister base, uint32 slot,
|
||||
TypedRegister value)
|
||||
{
|
||||
SetSlot *instr = new SetSlot(base, slot, value);
|
||||
iCode->push_back(instr);
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::slotInc(TypedRegister base, uint32 slot)
|
||||
{
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
SlotXcr *instr = new SlotXcr(dest, base, slot, 1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
TypedRegister ICodeGenerator::slotDec(TypedRegister base, uint32 slot)
|
||||
{
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
SlotXcr *instr = new SlotXcr(dest, base, slot, -1.0);
|
||||
iCode->push_back(instr);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TypedRegister ICodeGenerator::getElement(TypedRegister base, TypedRegister index)
|
||||
{
|
||||
TypedRegister dest(getRegister(), &Any_Type);
|
||||
@ -545,6 +579,19 @@ static bool generatedBoolean(ExprNode *p)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex)
|
||||
{
|
||||
if (t->isClassType()) {
|
||||
JSClass *c = static_cast<JSClass *>(t);
|
||||
if (c->hasSlot(name)) {
|
||||
JSSlot &s = c->getSlot(name);
|
||||
slotIndex = s.mIndex;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
if trueBranch OR falseBranch are not null, the sub-expression should generate
|
||||
a conditional branch to the appropriate target. If either branch is NULL, it
|
||||
@ -628,7 +675,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
case ExprNode::index :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
TypedRegister index = genExpr(b->op2);
|
||||
ret = getElement(base, index);
|
||||
}
|
||||
@ -636,8 +683,13 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
case ExprNode::dot :
|
||||
{
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = getProperty(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex))
|
||||
ret = getSlot(base, slotIndex);
|
||||
else
|
||||
ret = getProperty(base, name);
|
||||
}
|
||||
break;
|
||||
case ExprNode::This :
|
||||
@ -670,9 +722,18 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
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);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex)) {
|
||||
ret = slotInc(base, slotIndex);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setSlot(base, slotIndex, ret);
|
||||
}
|
||||
else {
|
||||
ret = getProperty(base, name);
|
||||
ret = op(ADD, ret, loadImmediate(1.0));
|
||||
setProperty(base, name, ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
@ -711,7 +772,12 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = propertyInc(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex))
|
||||
ret = slotInc(base, slotIndex);
|
||||
else
|
||||
ret = propertyInc(base, name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
@ -742,9 +808,18 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
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);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex)) {
|
||||
ret = getSlot(base, slotIndex);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setSlot(base, slotIndex, ret);
|
||||
}
|
||||
else {
|
||||
ret = getProperty(base, name);
|
||||
ret = op(SUBTRACT, ret, loadImmediate(1.0));
|
||||
setProperty(base, name, ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
@ -783,7 +858,12 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (u->op->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op);
|
||||
TypedRegister base = genExpr(b->op1);
|
||||
ret = propertyDec(base, static_cast<IdentifierExprNode *>(b->op2)->name);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex))
|
||||
slotDec(base, slotIndex);
|
||||
else
|
||||
ret = propertyDec(base, name);
|
||||
}
|
||||
else
|
||||
if (u->op->getKind() == ExprNode::identifier) {
|
||||
@ -853,8 +933,13 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
setProperty(base, static_cast<IdentifierExprNode *>(lb->op2)->name, ret);
|
||||
TypedRegister base = genExpr(lb->op1);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex))
|
||||
setSlot(base, slotIndex, ret);
|
||||
else
|
||||
setProperty(base, name, ret);
|
||||
}
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
@ -904,9 +989,18 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
|
||||
if (b->op1->getKind() == ExprNode::dot) {
|
||||
BinaryExprNode *lb = static_cast<BinaryExprNode *>(b->op1);
|
||||
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);
|
||||
const StringAtom &name = static_cast<IdentifierExprNode *>(lb->op2)->name;
|
||||
uint32 slotIndex;
|
||||
if (isSlotName(base.second, name, slotIndex)) {
|
||||
TypedRegister v = getSlot(base, slotIndex);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setSlot(base, slotIndex, ret);
|
||||
}
|
||||
else {
|
||||
TypedRegister v = getProperty(base, name);
|
||||
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
|
||||
setProperty(base, name, ret);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (b->op1->getKind() == ExprNode::index) {
|
||||
@ -1232,7 +1326,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
case StmtNode::Class:
|
||||
{
|
||||
// FIXME: need a semantic check to make sure a class isn't being redefined(?)
|
||||
using JSClasses::JSClass;
|
||||
ClassStmtNode *classStmt = static_cast<ClassStmtNode *>(p);
|
||||
ASSERT(classStmt->name->getKind() == ExprNode::identifier);
|
||||
IdentifierExprNode* nameExpr = static_cast<IdentifierExprNode*>(classStmt->name);
|
||||
@ -1490,11 +1583,14 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
|
||||
genStmt(f->stmt);
|
||||
|
||||
setLabel(e->continueLabel);
|
||||
if (f->expr3)
|
||||
if (f->expr3) {
|
||||
(*mInstructionMap)[iCode->size()] = f->expr3->pos;
|
||||
genExpr(f->expr3);
|
||||
}
|
||||
|
||||
setLabel(forTestLabel);
|
||||
if (f->expr2) {
|
||||
(*mInstructionMap)[iCode->size()] = f->expr2->pos;
|
||||
TypedRegister c = genExpr(f->expr2, false, forBlockTop, NULL);
|
||||
if (!generatedBoolean(f->expr2))
|
||||
branchTrue(forBlockTop, test(c));
|
||||
|
@ -168,7 +168,7 @@ namespace ICG {
|
||||
|
||||
ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind);
|
||||
|
||||
TypedRegister grabRegister(const StringAtom& name, const JSType *type)
|
||||
TypedRegister grabRegister(const StringAtom& name, JSType *type)
|
||||
{
|
||||
TypedRegister result(getRegister(), type);
|
||||
(*variableList)[name] = result;
|
||||
@ -176,7 +176,7 @@ namespace ICG {
|
||||
return result;
|
||||
}
|
||||
|
||||
const JSType *findType(const StringAtom& typeName);
|
||||
JSType *findType(const StringAtom& typeName);
|
||||
|
||||
public:
|
||||
ICodeGenerator(World *world, JSScope *global);
|
||||
@ -254,6 +254,11 @@ namespace ICG {
|
||||
TypedRegister elementInc(TypedRegister base, TypedRegister index);
|
||||
TypedRegister elementDec(TypedRegister base, TypedRegister index);
|
||||
|
||||
TypedRegister getSlot(TypedRegister base, uint32 slot);
|
||||
void setSlot(TypedRegister base, uint32 slot, TypedRegister value);
|
||||
TypedRegister slotInc(TypedRegister base, uint32 slot);
|
||||
TypedRegister slotDec(TypedRegister base, uint32 slot);
|
||||
|
||||
TypedRegister varInc(TypedRegister var);
|
||||
TypedRegister varDec(TypedRegister var);
|
||||
|
||||
|
@ -88,6 +88,8 @@ namespace JSClasses {
|
||||
JSClass* getSuperClass() { return mSuperClass; }
|
||||
JSScope* getScope() { return mScope; }
|
||||
|
||||
virtual bool isClassType() const { return true; }
|
||||
|
||||
JSSlot& addSlot(const String& name, const JSType* type)
|
||||
{
|
||||
JSSlot& slot = mSlots[name];
|
||||
|
@ -450,6 +450,8 @@ namespace JSTypes {
|
||||
|
||||
const String& getName() const { return mName; }
|
||||
|
||||
virtual bool isClassType() const { return false; }
|
||||
|
||||
int32 distance(const JSType *other) const;
|
||||
};
|
||||
|
||||
|
@ -71,6 +71,7 @@ namespace VM {
|
||||
ELEM_XCR, /* dest, base, index, value */
|
||||
GET_ELEMENT, /* dest, base, index */
|
||||
GET_PROP, /* dest, object, prop name */
|
||||
GET_SLOT, /* dest, object, slot number */
|
||||
INSTANCEOF, /* dest, source1, source2 */
|
||||
JSR, /* target */
|
||||
LOAD_BOOLEAN, /* dest, immediate value (boolean) */
|
||||
@ -97,8 +98,10 @@ namespace VM {
|
||||
SAVE_NAME, /* name, source */
|
||||
SET_ELEMENT, /* base, index, value */
|
||||
SET_PROP, /* object, name, source */
|
||||
SET_SLOT, /* object, slot number, source */
|
||||
SHIFTLEFT, /* dest, source1, source2 */
|
||||
SHIFTRIGHT, /* dest, source1, source2 */
|
||||
SLOT_XCR, /* dest, source, slot number, value */
|
||||
STRICT_EQ, /* dest, source1, source2 */
|
||||
STRICT_NE, /* dest, source1, source2 */
|
||||
SUBTRACT, /* dest, source1, source2 */
|
||||
@ -135,6 +138,7 @@ namespace VM {
|
||||
"ELEM_XCR ",
|
||||
"GET_ELEMENT ",
|
||||
"GET_PROP ",
|
||||
"GET_SLOT ",
|
||||
"INSTANCEOF ",
|
||||
"JSR ",
|
||||
"LOAD_BOOLEAN ",
|
||||
@ -161,8 +165,10 @@ namespace VM {
|
||||
"SAVE_NAME ",
|
||||
"SET_ELEMENT ",
|
||||
"SET_PROP ",
|
||||
"SET_SLOT ",
|
||||
"SHIFTLEFT ",
|
||||
"SHIFTRIGHT ",
|
||||
"SLOT_XCR ",
|
||||
"STRICT_EQ ",
|
||||
"STRICT_NE ",
|
||||
"SUBTRACT ",
|
||||
@ -216,7 +222,7 @@ namespace VM {
|
||||
/********************************************************************/
|
||||
|
||||
typedef uint32 Register;
|
||||
typedef std::pair<Register, const JSType*> TypedRegister;
|
||||
typedef std::pair<Register, JSType*> TypedRegister;
|
||||
typedef std::vector<TypedRegister> RegisterList;
|
||||
typedef std::vector<Instruction *> InstructionStream;
|
||||
typedef InstructionStream::iterator InstructionIterator;
|
||||
@ -610,6 +616,22 @@ namespace VM {
|
||||
}
|
||||
};
|
||||
|
||||
class GetSlot : public Instruction_3<TypedRegister, TypedRegister, uint32> {
|
||||
public:
|
||||
/* dest, object, slot number */
|
||||
GetSlot (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3) :
|
||||
Instruction_3<TypedRegister, TypedRegister, uint32>
|
||||
(GET_SLOT, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[GET_SLOT] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << mOp3;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Instanceof : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
@ -994,6 +1016,22 @@ namespace VM {
|
||||
}
|
||||
};
|
||||
|
||||
class SetSlot : public Instruction_3<TypedRegister, uint32, TypedRegister> {
|
||||
public:
|
||||
/* object, slot number, source */
|
||||
SetSlot (TypedRegister aOp1, uint32 aOp2, TypedRegister aOp3) :
|
||||
Instruction_3<TypedRegister, uint32, TypedRegister>
|
||||
(SET_SLOT, aOp1, aOp2, aOp3) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[SET_SLOT] << "\t" << "R" << mOp1.first << ", " << mOp2 << ", " << "R" << mOp3.first;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class Shiftleft : public Arithmetic {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
@ -1012,6 +1050,22 @@ namespace VM {
|
||||
/* print() and printOperands() inherited from Arithmetic */
|
||||
};
|
||||
|
||||
class SlotXcr : public Instruction_4<TypedRegister, TypedRegister, uint32, double> {
|
||||
public:
|
||||
/* dest, source, slot number, value */
|
||||
SlotXcr (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3, double aOp4) :
|
||||
Instruction_4<TypedRegister, TypedRegister, uint32, double>
|
||||
(SLOT_XCR, aOp1, aOp2, aOp3, aOp4) {};
|
||||
virtual Formatter& print(Formatter& f) {
|
||||
f << opcodeNames[SLOT_XCR] << "\t" << "R" << mOp1.first << ", " << "R" << mOp2.first << ", " << mOp3 << ", " << mOp4;
|
||||
return f;
|
||||
}
|
||||
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
|
||||
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
|
||||
return f;
|
||||
}
|
||||
};
|
||||
|
||||
class StrictEQ : public Instruction_3<TypedRegister, TypedRegister, TypedRegister> {
|
||||
public:
|
||||
/* dest, source1, source2 */
|
||||
|
@ -150,6 +150,24 @@ $ops{"SET_PROP"} =
|
||||
rem => "object, name, source",
|
||||
params => [ ("TypedRegister", "const StringAtom*", "TypedRegister") ]
|
||||
};
|
||||
$ops{"GET_SLOT"} =
|
||||
{
|
||||
super => "Instruction_3",
|
||||
rem => "dest, object, slot number",
|
||||
params => [ ("TypedRegister", "TypedRegister", "uint32") ]
|
||||
};
|
||||
$ops{"SET_SLOT"} =
|
||||
{
|
||||
super => "Instruction_3",
|
||||
rem => "object, slot number, source",
|
||||
params => [ ("TypedRegister", "uint32", "TypedRegister") ]
|
||||
};
|
||||
$ops{"SLOT_XCR"} =
|
||||
{
|
||||
super => "Instruction_4",
|
||||
rem => "dest, source, slot number, value",
|
||||
params => [ ("TypedRegister", "TypedRegister", "uint32", "double") ]
|
||||
};
|
||||
$ops{"PROP_XCR"} =
|
||||
{
|
||||
super => "Instruction_4",
|
||||
|
Loading…
x
Reference in New Issue
Block a user