diff --git a/js/js2/icodegenerator.cpp b/js/js2/icodegenerator.cpp index b236d84d6cc3..d3ddf110ca73 100644 --- a/js/js2/icodegenerator.cpp +++ b/js/js2/icodegenerator.cpp @@ -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(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(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(p); - TypedRegister base = genExpr(b->op1); - ret = getProperty(base, static_cast(b->op2)->name); + const StringAtom &name = static_cast(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(u->op); TypedRegister base = genExpr(b->op1); - ret = getProperty(base, static_cast(b->op2)->name); - ret = op(ADD, ret, loadImmediate(1.0)); - setProperty(base, static_cast(b->op2)->name, ret); + const StringAtom &name = static_cast(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(u->op); TypedRegister base = genExpr(b->op1); - ret = propertyInc(base, static_cast(b->op2)->name); + const StringAtom &name = static_cast(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(u->op); TypedRegister base = genExpr(b->op1); - ret = getProperty(base, static_cast(b->op2)->name); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); - setProperty(base, static_cast(b->op2)->name, ret); + const StringAtom &name = static_cast(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(u->op); TypedRegister base = genExpr(b->op1); - ret = propertyDec(base, static_cast(b->op2)->name); + const StringAtom &name = static_cast(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(b->op1); - TypedRegister base = genExpr(lb->op1); - setProperty(base, static_cast(lb->op2)->name, ret); + TypedRegister base = genExpr(lb->op1); + const StringAtom &name = static_cast(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(b->op1); TypedRegister base = genExpr(lb->op1); - TypedRegister v = getProperty(base, static_cast(lb->op2)->name); - ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret); - setProperty(base, static_cast(lb->op2)->name, ret); + const StringAtom &name = static_cast(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(p); ASSERT(classStmt->name->getKind() == ExprNode::identifier); IdentifierExprNode* nameExpr = static_cast(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)); diff --git a/js/js2/icodegenerator.h b/js/js2/icodegenerator.h index dedc7cb2f04d..e2c32da382ee 100644 --- a/js/js2/icodegenerator.h +++ b/js/js2/icodegenerator.h @@ -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); diff --git a/js/js2/jsclasses.h b/js/js2/jsclasses.h index 50e58d51a7b9..bd0253146cbe 100644 --- a/js/js2/jsclasses.h +++ b/js/js2/jsclasses.h @@ -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]; diff --git a/js/js2/jstypes.h b/js/js2/jstypes.h index eb45c87efc05..a08e4d81860d 100644 --- a/js/js2/jstypes.h +++ b/js/js2/jstypes.h @@ -450,6 +450,8 @@ namespace JSTypes { const String& getName() const { return mName; } + virtual bool isClassType() const { return false; } + int32 distance(const JSType *other) const; }; diff --git a/js/js2/tools/gencode.pl b/js/js2/tools/gencode.pl index 56dd42861ca5..d0332f938484 100644 --- a/js/js2/tools/gencode.pl +++ b/js/js2/tools/gencode.pl @@ -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", diff --git a/js/js2/vmtypes.h b/js/js2/vmtypes.h index d0fd6f72bda0..d18bde9dc9ba 100644 --- a/js/js2/vmtypes.h +++ b/js/js2/vmtypes.h @@ -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 TypedRegister; + typedef std::pair TypedRegister; typedef std::vector RegisterList; typedef std::vector InstructionStream; typedef InstructionStream::iterator InstructionIterator; @@ -610,6 +616,22 @@ namespace VM { } }; + class GetSlot : public Instruction_3 { + public: + /* dest, object, slot number */ + GetSlot (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3) : + Instruction_3 + (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 { public: /* dest, source1, source2 */ @@ -994,6 +1016,22 @@ namespace VM { } }; + class SetSlot : public Instruction_3 { + public: + /* object, slot number, source */ + SetSlot (TypedRegister aOp1, uint32 aOp2, TypedRegister aOp3) : + Instruction_3 + (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 { + public: + /* dest, source, slot number, value */ + SlotXcr (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3, double aOp4) : + Instruction_4 + (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 { public: /* dest, source1, source2 */ diff --git a/js2/src/icodegenerator.cpp b/js2/src/icodegenerator.cpp index b236d84d6cc3..d3ddf110ca73 100644 --- a/js2/src/icodegenerator.cpp +++ b/js2/src/icodegenerator.cpp @@ -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(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(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(p); - TypedRegister base = genExpr(b->op1); - ret = getProperty(base, static_cast(b->op2)->name); + const StringAtom &name = static_cast(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(u->op); TypedRegister base = genExpr(b->op1); - ret = getProperty(base, static_cast(b->op2)->name); - ret = op(ADD, ret, loadImmediate(1.0)); - setProperty(base, static_cast(b->op2)->name, ret); + const StringAtom &name = static_cast(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(u->op); TypedRegister base = genExpr(b->op1); - ret = propertyInc(base, static_cast(b->op2)->name); + const StringAtom &name = static_cast(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(u->op); TypedRegister base = genExpr(b->op1); - ret = getProperty(base, static_cast(b->op2)->name); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); - setProperty(base, static_cast(b->op2)->name, ret); + const StringAtom &name = static_cast(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(u->op); TypedRegister base = genExpr(b->op1); - ret = propertyDec(base, static_cast(b->op2)->name); + const StringAtom &name = static_cast(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(b->op1); - TypedRegister base = genExpr(lb->op1); - setProperty(base, static_cast(lb->op2)->name, ret); + TypedRegister base = genExpr(lb->op1); + const StringAtom &name = static_cast(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(b->op1); TypedRegister base = genExpr(lb->op1); - TypedRegister v = getProperty(base, static_cast(lb->op2)->name); - ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret); - setProperty(base, static_cast(lb->op2)->name, ret); + const StringAtom &name = static_cast(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(p); ASSERT(classStmt->name->getKind() == ExprNode::identifier); IdentifierExprNode* nameExpr = static_cast(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)); diff --git a/js2/src/icodegenerator.h b/js2/src/icodegenerator.h index dedc7cb2f04d..e2c32da382ee 100644 --- a/js2/src/icodegenerator.h +++ b/js2/src/icodegenerator.h @@ -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); diff --git a/js2/src/jsclasses.h b/js2/src/jsclasses.h index 50e58d51a7b9..bd0253146cbe 100644 --- a/js2/src/jsclasses.h +++ b/js2/src/jsclasses.h @@ -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]; diff --git a/js2/src/jstypes.h b/js2/src/jstypes.h index eb45c87efc05..a08e4d81860d 100644 --- a/js2/src/jstypes.h +++ b/js2/src/jstypes.h @@ -450,6 +450,8 @@ namespace JSTypes { const String& getName() const { return mName; } + virtual bool isClassType() const { return false; } + int32 distance(const JSType *other) const; }; diff --git a/js2/src/vmtypes.h b/js2/src/vmtypes.h index d0fd6f72bda0..d18bde9dc9ba 100644 --- a/js2/src/vmtypes.h +++ b/js2/src/vmtypes.h @@ -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 TypedRegister; + typedef std::pair TypedRegister; typedef std::vector RegisterList; typedef std::vector InstructionStream; typedef InstructionStream::iterator InstructionIterator; @@ -610,6 +616,22 @@ namespace VM { } }; + class GetSlot : public Instruction_3 { + public: + /* dest, object, slot number */ + GetSlot (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3) : + Instruction_3 + (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 { public: /* dest, source1, source2 */ @@ -994,6 +1016,22 @@ namespace VM { } }; + class SetSlot : public Instruction_3 { + public: + /* object, slot number, source */ + SetSlot (TypedRegister aOp1, uint32 aOp2, TypedRegister aOp3) : + Instruction_3 + (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 { + public: + /* dest, source, slot number, value */ + SlotXcr (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3, double aOp4) : + Instruction_4 + (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 { public: /* dest, source1, source2 */ diff --git a/js2/tools/gencode.pl b/js2/tools/gencode.pl index 56dd42861ca5..d0332f938484 100644 --- a/js2/tools/gencode.pl +++ b/js2/tools/gencode.pl @@ -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",