Implicit this and class lookup stuff.

This commit is contained in:
rogerl%netscape.com 2000-06-29 01:21:41 +00:00
Родитель da1b32ec38
Коммит 8d0b4fe645
12 изменённых файлов: 264 добавлений и 174 удалений

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

@ -64,7 +64,8 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
// ICodeGenerator
//
ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, bool atTopLevel)
ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, ICodeGeneratorFlags flags)
: topRegister(0),
registerBase(0),
maxRegister(0),
@ -74,10 +75,8 @@ ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, b
mWorld(world),
mGlobal(global),
mInstructionMap(new InstructionMap()),
mWithinWith(false),
mAtTopLevel(atTopLevel),
mFlags(flags),
mClass(aClass)
{
iCode = new InstructionStream();
iCodeOwner = true;
@ -595,13 +594,14 @@ static bool generatedBoolean(ExprNode *p)
return false;
}
static bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex)
static bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex, JSType *&type)
{
JSClass* c = dynamic_cast<JSClass*>(t);
while (c) {
if (c->hasSlot(name)) {
const JSSlot &s = c->getSlot(name);
slotIndex = s.mIndex;
type = s.mType;
return true;
}
c = c->getSuperClass();
@ -621,9 +621,10 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
else {
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
TypedRegister base;
JSClass* c = NULL;
JSClass *c = NULL;
JSType *fieldType = &Any_Type;
uint32 slotIndex;
if ((b->op1->getKind() == ExprNode::identifier) && !mWithinWith) {
if ((b->op1->getKind() == ExprNode::identifier) && !isWithinWith()) {
const StringAtom &baseName = (static_cast<IdentifierExprNode *>(b->op1))->name;
JSType *baseType = &Any_Type;
base = findVariable(baseName);
@ -638,19 +639,31 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
if (baseType == &Type_Type) {
const JSValue &v = mGlobal->getVariable(baseName);
c = dynamic_cast<JSClass*>(v.type);
if (c && c->hasStatic(name))
if (c && c->hasStatic(name, fieldType)) {
lValueKind = Static;
}
}
if (lValueKind == Property) {
if (base.first == NotARegister)
base = loadName(baseName);
if (isSlotName(baseType, name, slotIndex, fieldType))
lValueKind = Slot;
else {
c = dynamic_cast<JSClass*>(base.second);
if (c && c->hasStatic(name, fieldType))
lValueKind = Static;
else
lValueKind = Property;
}
}
if (base.first == NotARegister)
base = loadName(baseName);
}
else {
base = genExpr(b->op1);
if (isSlotName(base.second, name, slotIndex))
if (isSlotName(base.second, name, slotIndex, fieldType))
lValueKind = Slot;
else {
c = dynamic_cast<JSClass*>(base.second);
if (c && c->hasStatic(name))
if (c && c->hasStatic(name, fieldType))
lValueKind = Static;
else
lValueKind = Property;
@ -658,6 +671,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
}
TypedRegister v;
switch (use) {
case ExprNode::dot:
case ExprNode::addEquals:
case ExprNode::subtractEquals:
case ExprNode::multiplyEquals:
@ -680,6 +694,8 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
v = getSlot(base, slotIndex);
break;
}
if (use == ExprNode::dot)
break;
ret = op(mapExprNodeToICodeOp(use), v, ret);
// fall thru...
case ExprNode::assignment:
@ -726,6 +742,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
}
break;
}
ret.second = fieldType;
}
return ret;
}
@ -810,7 +827,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
}
else
if (i->op->getKind() == ExprNode::identifier) {
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(i->op))->name);
if (v.first != NotARegister)
ret = call(v, static_cast<IdentifierExprNode *>(i->op)->name, args);
@ -840,33 +857,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::dot :
{
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
if (b->op2->getKind() != ExprNode::identifier) {
NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] )
}
else {
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 {
//
// look for <class name>.m
//
// XXX redundant work done by genExpr(b->op1), seems a pity
if ((base.second == &Type_Type)
&& (b->op1->getKind() == ExprNode::identifier)) {
const StringAtom &className = (static_cast<IdentifierExprNode *>(b->op1))->name;
const JSValue &v = mGlobal->getVariable(className);
JSClass* c = dynamic_cast<JSClass*>(v.type);
if (c && c->hasStatic(name)) {
ret = getStatic(c, name);
break;
}
}
}
ret = getProperty(base, name);
}
ret = handleDot(b, p->getKind(), xcrementOp, ret);
}
break;
case ExprNode::This :
@ -877,14 +868,27 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::identifier :
{
const StringAtom &name = (static_cast<IdentifierExprNode *>(p))->name;
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable(name);
if (v.first != NotARegister)
ret = v;
else {
// When we support implicit this AND we're in a method (instance or static), look
// to see if the class has a slot(for an instance field) or property(static field)
// by this name.
if (mClass) { // we're compiling a method of a class
JSType *fieldType;
if (!isStaticMethod()) {
uint32 slotIndex;
if (isSlotName(mClass, name, slotIndex, fieldType)) {
ret = getSlot(TypedRegister(0, mClass), slotIndex);
ret.second = fieldType;
break;
}
}
if (mClass->hasStatic(name, fieldType)) {
ret = getStatic(mClass, name);
ret.second = fieldType;
break;
}
}
ret = loadName(name);
ret.second = mGlobal->getType(name);
}
@ -910,7 +914,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
}
else
if (u->op->getKind() == ExprNode::identifier) {
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
if (v.first != NotARegister)
ret = op(xcrementOp, ret, loadImmediate(1.0));
@ -950,7 +954,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
}
else
if (u->op->getKind() == ExprNode::identifier) {
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
if (v.first != NotARegister)
ret = varXcr(v, xcrementOp);
@ -1004,7 +1008,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
ret = genExpr(b->op2);
if (b->op1->getKind() == ExprNode::identifier) {
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
if (v.first != NotARegister)
move(v, ret);
@ -1045,7 +1049,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
ret = genExpr(b->op2);
if (b->op1->getKind() == ExprNode::identifier) {
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
if (v.first != NotARegister) {
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
@ -1292,7 +1296,7 @@ void ICodeGenerator::preprocess(StmtNode *p)
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
if (v->type && (v->type->getKind() == ExprNode::identifier))
if (mAtTopLevel)
if (isTopLevel())
mGlobal->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name,
findType((static_cast<IdentifierExprNode *>(v->type))->name));
else
@ -1392,6 +1396,25 @@ static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKin
return false;
}
ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f)
{
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator icg(mWorld, mGlobal, mClass, flags);
icg.allocateParameter(mWorld->identifiers[widenCString("this")], (mClass) ? mClass : &Any_Type); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name);
v = v->next;
}
icg.preprocess(f->function.body);
icg.genStmt(f->function.body);
return icg.complete();
}
TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
{
TypedRegister ret(NotARegister, &None_Type);
@ -1422,14 +1445,9 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
mGlobal->defineVariable(nameExpr->name, &Type_Type, JSValue(thisClass));
if (classStmt->body) {
JSScope* thisScope = thisClass->getScope();
ICodeGenerator ccg(mWorld, thisScope, thisClass, false); // constructor code generator.
ICodeGenerator ccg(mWorld, thisScope, thisClass, kNoFlags); // constructor code generator.
ccg.allocateParameter(mWorld->identifiers[widenCString("this")], thisClass); // always parameter #0
// XXX
// The only use for mcg is to establish a new container class ('thisClass' instead of 'mClass')
// and set up a new scope, maybe we could just do that inline?
// XXX
ICodeGenerator mcg(mWorld, thisScope, thisClass, false); // method code generator.
ICodeGenerator scg(mWorld, thisScope, thisClass, false); // static initializer code generator.
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod); // static initializer code generator.
StmtNode* s = classStmt->body->statements;
while (s) {
switch (s->getKind()) {
@ -1472,9 +1490,22 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
break;
case StmtNode::Function:
{
mcg.preprocess(s);
mcg.genStmt(s);
}
FunctionStmtNode *f = static_cast<FunctionStmtNode *>(s);
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator mcg(mWorld, thisScope, thisClass, flags); // method code generator.
ICodeModule *icm = mcg.genFunction(f);
if (f->function.name->getKind() == ExprNode::identifier) {
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
if (isStatic) {
thisClass->defineStatic(name, &Function_Type);
scg.setStatic(thisClass, name, scg.newFunction(icm));
}
else
thisScope->defineFunction(name, icm);
}
}
break;
default:
NOT_REACHED("unimplemented class member statement");
@ -1499,23 +1530,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
case StmtNode::Function:
{
FunctionStmtNode *f = static_cast<FunctionStmtNode *>(p);
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeGenerator icg(mWorld, mGlobal, mClass, false);
icg.allocateParameter(mWorld->identifiers[widenCString("this")], (mClass) ? mClass : &Any_Type); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name);
v = v->next;
ICodeModule *icm = genFunction(f);
if (f->function.name->getKind() == ExprNode::identifier) {
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
mGlobal->defineFunction(name, icm);
}
icg.preprocess(f->function.body);
icg.genStmt(f->function.body);
//stdOut << icg;
ICodeModule *icm = icg.complete();
if (f->function.name->getKind() == ExprNode::identifier)
// XXX what to do with static methods?
// if (isStatic && mClass)...
mGlobal->defineFunction((static_cast<IdentifierExprNode *>(f->function.name))->name, icm);
}
break;
case StmtNode::Var:
@ -1525,7 +1544,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
while (v) {
if (v->name && v->initializer) {
if (v->name->getKind() == ExprNode::identifier) {
if (!mWithinWith && !mAtTopLevel) {
if (!isTopLevel() && !isWithinWith()) {
TypedRegister r = genExpr(v->name);
TypedRegister val = genExpr(v->initializer);
move(r, val);
@ -1597,12 +1616,12 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
{
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
TypedRegister o = genExpr(w->expr);
bool withinWith = mWithinWith;
mWithinWith = true;
bool withinWith = isWithinWith();
setFlag(kIsWithinWith, true);
beginWith(o);
genStmt(w->stmt);
endWith();
mWithinWith = withinWith;
setFlag(kIsWithinWith, withinWith);
}
break;
case StmtNode::Switch:

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

@ -111,6 +111,8 @@ namespace ICG {
// converts it into an ICodeModule, ready for execution.
class ICodeGenerator {
public:
typedef enum { kNoFlags = 0, kIsTopLevel = 0x01, kIsStaticMethod = 0x02, kIsWithinWith = 0x04 } ICodeGeneratorFlags;
private:
InstructionStream *iCode;
bool iCodeOwner;
@ -130,9 +132,8 @@ namespace ICG {
// maps source position to instruction index
InstructionMap *mInstructionMap;
bool mWithinWith; // state from genStmt that indicates generating code beneath a with statement
bool mAtTopLevel; // compiling at top level
JSClass *mClass; // enclosing class when generating code for methods
ICodeGeneratorFlags mFlags; // assorted flags
void markMaxRegister()
{ if (topRegister > maxRegister) maxRegister = topRegister; }
@ -180,11 +181,20 @@ namespace ICG {
return result;
}
bool isTopLevel() { return (mFlags & kIsTopLevel) != 0; }
bool isWithinWith() { return (mFlags & kIsWithinWith) != 0; }
bool isStaticMethod() { return (mFlags & kIsStaticMethod) != 0; }
void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); }
JSType *findType(const StringAtom& typeName);
TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret);
ICodeModule *genFunction(FunctionStmtNode *f);
public:
ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, bool atTopLevel = true);
ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
~ICodeGenerator()
{

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

@ -154,6 +154,9 @@ static ICodeModule* genCode(Context &cx, StmtNode *p, const String &fileName)
icg.returnStmt(ret);
ICodeModule *icm = icg.complete();
//stdOut << icg;
icm->setFileName (fileName);
return icm;
}

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

@ -162,6 +162,16 @@ namespace JSClasses {
return mStaticSlots[name];
}
bool hasStatic(const String& name, JSType*& type)
{
JSSlots::const_iterator i = mStaticSlots.find(name);
if (i != mStaticSlots.end()) {
type = i->second.mType;
return true;
}
return false;
}
bool hasStatic(const String& name)
{
return (mStaticSlots.find(name) != mStaticSlots.end());

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

@ -509,12 +509,14 @@ sub get_print_body {
push (@oplist, "\"R\" << mOp$op.first");
} elsif ($type eq "Label*") {
push (@oplist, "\"Offset \" << ((mOp$op) ? mOp$op->mOffset : NotAnOffset)")
} elsif ($type =~ /String|JSClass\*/) {
} elsif ($type =~ /String/) {
push (@oplist, "\"'\" << *mOp$op << \"'\"");
} elsif ($type =~ /bool/) {
push (@oplist, "\"'\" << ((mOp$op) ? \"true\" : \"false\") << \"'\"");
} elsif ($type =~ /ICodeModule/) {
push (@oplist, "\"ICodeModule\"");
} elsif ($type =~ /JSClass\*/) {
push (@oplist, "mOp$op->getName()");
} else {
push (@oplist, "mOp$op");
}

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

@ -652,7 +652,7 @@ namespace VM {
Instruction_3<TypedRegister, JSClass*, uint32>
(GET_STATIC, aOp1, aOp2, aOp3) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[GET_STATIC] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << mOp3;
f << opcodeNames[GET_STATIC] << "\t" << "R" << mOp1.first << ", " << mOp2->getName() << ", " << mOp3;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
@ -1084,7 +1084,7 @@ namespace VM {
Instruction_3<JSClass*, uint32, TypedRegister>
(SET_STATIC, aOp1, aOp2, aOp3) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[SET_STATIC] << "\t" << "'" << *mOp1 << "'" << ", " << mOp2 << ", " << "R" << mOp3.first;
f << opcodeNames[SET_STATIC] << "\t" << mOp1->getName() << ", " << mOp2 << ", " << "R" << mOp3.first;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
@ -1134,7 +1134,7 @@ namespace VM {
Instruction_4<TypedRegister, JSClass*, const StringAtom*, RegisterList>
(STATIC_CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[STATIC_CALL] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << "'" << *mOp3 << "'" << ", " << mOp4;
f << opcodeNames[STATIC_CALL] << "\t" << "R" << mOp1.first << ", " << mOp2->getName() << ", " << "'" << *mOp3 << "'" << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
@ -1150,7 +1150,7 @@ namespace VM {
Instruction_4<TypedRegister, JSClass*, uint32, double>
(STATIC_XCR, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[STATIC_XCR] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << mOp3 << ", " << mOp4;
f << opcodeNames[STATIC_XCR] << "\t" << "R" << mOp1.first << ", " << mOp2->getName() << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
@ -1313,6 +1313,7 @@ namespace VM {
/* print() and printOperands() inherited from Arithmetic */
};
} /* namespace VM */
} /* namespace JavaScript */

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

@ -64,7 +64,8 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
// ICodeGenerator
//
ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, bool atTopLevel)
ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, ICodeGeneratorFlags flags)
: topRegister(0),
registerBase(0),
maxRegister(0),
@ -74,10 +75,8 @@ ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, b
mWorld(world),
mGlobal(global),
mInstructionMap(new InstructionMap()),
mWithinWith(false),
mAtTopLevel(atTopLevel),
mFlags(flags),
mClass(aClass)
{
iCode = new InstructionStream();
iCodeOwner = true;
@ -595,13 +594,14 @@ static bool generatedBoolean(ExprNode *p)
return false;
}
static bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex)
static bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex, JSType *&type)
{
JSClass* c = dynamic_cast<JSClass*>(t);
while (c) {
if (c->hasSlot(name)) {
const JSSlot &s = c->getSlot(name);
slotIndex = s.mIndex;
type = s.mType;
return true;
}
c = c->getSuperClass();
@ -621,9 +621,10 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
else {
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
TypedRegister base;
JSClass* c = NULL;
JSClass *c = NULL;
JSType *fieldType = &Any_Type;
uint32 slotIndex;
if ((b->op1->getKind() == ExprNode::identifier) && !mWithinWith) {
if ((b->op1->getKind() == ExprNode::identifier) && !isWithinWith()) {
const StringAtom &baseName = (static_cast<IdentifierExprNode *>(b->op1))->name;
JSType *baseType = &Any_Type;
base = findVariable(baseName);
@ -638,19 +639,31 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
if (baseType == &Type_Type) {
const JSValue &v = mGlobal->getVariable(baseName);
c = dynamic_cast<JSClass*>(v.type);
if (c && c->hasStatic(name))
if (c && c->hasStatic(name, fieldType)) {
lValueKind = Static;
}
}
if (lValueKind == Property) {
if (base.first == NotARegister)
base = loadName(baseName);
if (isSlotName(baseType, name, slotIndex, fieldType))
lValueKind = Slot;
else {
c = dynamic_cast<JSClass*>(base.second);
if (c && c->hasStatic(name, fieldType))
lValueKind = Static;
else
lValueKind = Property;
}
}
if (base.first == NotARegister)
base = loadName(baseName);
}
else {
base = genExpr(b->op1);
if (isSlotName(base.second, name, slotIndex))
if (isSlotName(base.second, name, slotIndex, fieldType))
lValueKind = Slot;
else {
c = dynamic_cast<JSClass*>(base.second);
if (c && c->hasStatic(name))
if (c && c->hasStatic(name, fieldType))
lValueKind = Static;
else
lValueKind = Property;
@ -658,6 +671,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
}
TypedRegister v;
switch (use) {
case ExprNode::dot:
case ExprNode::addEquals:
case ExprNode::subtractEquals:
case ExprNode::multiplyEquals:
@ -680,6 +694,8 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
v = getSlot(base, slotIndex);
break;
}
if (use == ExprNode::dot)
break;
ret = op(mapExprNodeToICodeOp(use), v, ret);
// fall thru...
case ExprNode::assignment:
@ -726,6 +742,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
}
break;
}
ret.second = fieldType;
}
return ret;
}
@ -810,7 +827,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
}
else
if (i->op->getKind() == ExprNode::identifier) {
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(i->op))->name);
if (v.first != NotARegister)
ret = call(v, static_cast<IdentifierExprNode *>(i->op)->name, args);
@ -840,33 +857,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::dot :
{
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
if (b->op2->getKind() != ExprNode::identifier) {
NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] )
}
else {
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 {
//
// look for <class name>.m
//
// XXX redundant work done by genExpr(b->op1), seems a pity
if ((base.second == &Type_Type)
&& (b->op1->getKind() == ExprNode::identifier)) {
const StringAtom &className = (static_cast<IdentifierExprNode *>(b->op1))->name;
const JSValue &v = mGlobal->getVariable(className);
JSClass* c = dynamic_cast<JSClass*>(v.type);
if (c && c->hasStatic(name)) {
ret = getStatic(c, name);
break;
}
}
}
ret = getProperty(base, name);
}
ret = handleDot(b, p->getKind(), xcrementOp, ret);
}
break;
case ExprNode::This :
@ -877,14 +868,27 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::identifier :
{
const StringAtom &name = (static_cast<IdentifierExprNode *>(p))->name;
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable(name);
if (v.first != NotARegister)
ret = v;
else {
// When we support implicit this AND we're in a method (instance or static), look
// to see if the class has a slot(for an instance field) or property(static field)
// by this name.
if (mClass) { // we're compiling a method of a class
JSType *fieldType;
if (!isStaticMethod()) {
uint32 slotIndex;
if (isSlotName(mClass, name, slotIndex, fieldType)) {
ret = getSlot(TypedRegister(0, mClass), slotIndex);
ret.second = fieldType;
break;
}
}
if (mClass->hasStatic(name, fieldType)) {
ret = getStatic(mClass, name);
ret.second = fieldType;
break;
}
}
ret = loadName(name);
ret.second = mGlobal->getType(name);
}
@ -910,7 +914,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
}
else
if (u->op->getKind() == ExprNode::identifier) {
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
if (v.first != NotARegister)
ret = op(xcrementOp, ret, loadImmediate(1.0));
@ -950,7 +954,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
}
else
if (u->op->getKind() == ExprNode::identifier) {
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
if (v.first != NotARegister)
ret = varXcr(v, xcrementOp);
@ -1004,7 +1008,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
ret = genExpr(b->op2);
if (b->op1->getKind() == ExprNode::identifier) {
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
if (v.first != NotARegister)
move(v, ret);
@ -1045,7 +1049,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
ret = genExpr(b->op2);
if (b->op1->getKind() == ExprNode::identifier) {
if (!mWithinWith) {
if (!isWithinWith()) {
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(b->op1))->name);
if (v.first != NotARegister) {
ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret);
@ -1292,7 +1296,7 @@ void ICodeGenerator::preprocess(StmtNode *p)
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
if (v->type && (v->type->getKind() == ExprNode::identifier))
if (mAtTopLevel)
if (isTopLevel())
mGlobal->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name,
findType((static_cast<IdentifierExprNode *>(v->type))->name));
else
@ -1392,6 +1396,25 @@ static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKin
return false;
}
ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f)
{
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator icg(mWorld, mGlobal, mClass, flags);
icg.allocateParameter(mWorld->identifiers[widenCString("this")], (mClass) ? mClass : &Any_Type); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name);
v = v->next;
}
icg.preprocess(f->function.body);
icg.genStmt(f->function.body);
return icg.complete();
}
TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
{
TypedRegister ret(NotARegister, &None_Type);
@ -1422,14 +1445,9 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
mGlobal->defineVariable(nameExpr->name, &Type_Type, JSValue(thisClass));
if (classStmt->body) {
JSScope* thisScope = thisClass->getScope();
ICodeGenerator ccg(mWorld, thisScope, thisClass, false); // constructor code generator.
ICodeGenerator ccg(mWorld, thisScope, thisClass, kNoFlags); // constructor code generator.
ccg.allocateParameter(mWorld->identifiers[widenCString("this")], thisClass); // always parameter #0
// XXX
// The only use for mcg is to establish a new container class ('thisClass' instead of 'mClass')
// and set up a new scope, maybe we could just do that inline?
// XXX
ICodeGenerator mcg(mWorld, thisScope, thisClass, false); // method code generator.
ICodeGenerator scg(mWorld, thisScope, thisClass, false); // static initializer code generator.
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod); // static initializer code generator.
StmtNode* s = classStmt->body->statements;
while (s) {
switch (s->getKind()) {
@ -1472,9 +1490,22 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
break;
case StmtNode::Function:
{
mcg.preprocess(s);
mcg.genStmt(s);
}
FunctionStmtNode *f = static_cast<FunctionStmtNode *>(s);
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator mcg(mWorld, thisScope, thisClass, flags); // method code generator.
ICodeModule *icm = mcg.genFunction(f);
if (f->function.name->getKind() == ExprNode::identifier) {
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
if (isStatic) {
thisClass->defineStatic(name, &Function_Type);
scg.setStatic(thisClass, name, scg.newFunction(icm));
}
else
thisScope->defineFunction(name, icm);
}
}
break;
default:
NOT_REACHED("unimplemented class member statement");
@ -1499,23 +1530,11 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
case StmtNode::Function:
{
FunctionStmtNode *f = static_cast<FunctionStmtNode *>(p);
bool isStatic = hasAttribute(f->attributes, Token::Static);
ICodeGenerator icg(mWorld, mGlobal, mClass, false);
icg.allocateParameter(mWorld->identifiers[widenCString("this")], (mClass) ? mClass : &Any_Type); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name);
v = v->next;
ICodeModule *icm = genFunction(f);
if (f->function.name->getKind() == ExprNode::identifier) {
const StringAtom& name = (static_cast<IdentifierExprNode *>(f->function.name))->name;
mGlobal->defineFunction(name, icm);
}
icg.preprocess(f->function.body);
icg.genStmt(f->function.body);
//stdOut << icg;
ICodeModule *icm = icg.complete();
if (f->function.name->getKind() == ExprNode::identifier)
// XXX what to do with static methods?
// if (isStatic && mClass)...
mGlobal->defineFunction((static_cast<IdentifierExprNode *>(f->function.name))->name, icm);
}
break;
case StmtNode::Var:
@ -1525,7 +1544,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
while (v) {
if (v->name && v->initializer) {
if (v->name->getKind() == ExprNode::identifier) {
if (!mWithinWith && !mAtTopLevel) {
if (!isTopLevel() && !isWithinWith()) {
TypedRegister r = genExpr(v->name);
TypedRegister val = genExpr(v->initializer);
move(r, val);
@ -1597,12 +1616,12 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
{
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
TypedRegister o = genExpr(w->expr);
bool withinWith = mWithinWith;
mWithinWith = true;
bool withinWith = isWithinWith();
setFlag(kIsWithinWith, true);
beginWith(o);
genStmt(w->stmt);
endWith();
mWithinWith = withinWith;
setFlag(kIsWithinWith, withinWith);
}
break;
case StmtNode::Switch:

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

@ -111,6 +111,8 @@ namespace ICG {
// converts it into an ICodeModule, ready for execution.
class ICodeGenerator {
public:
typedef enum { kNoFlags = 0, kIsTopLevel = 0x01, kIsStaticMethod = 0x02, kIsWithinWith = 0x04 } ICodeGeneratorFlags;
private:
InstructionStream *iCode;
bool iCodeOwner;
@ -130,9 +132,8 @@ namespace ICG {
// maps source position to instruction index
InstructionMap *mInstructionMap;
bool mWithinWith; // state from genStmt that indicates generating code beneath a with statement
bool mAtTopLevel; // compiling at top level
JSClass *mClass; // enclosing class when generating code for methods
ICodeGeneratorFlags mFlags; // assorted flags
void markMaxRegister()
{ if (topRegister > maxRegister) maxRegister = topRegister; }
@ -180,11 +181,20 @@ namespace ICG {
return result;
}
bool isTopLevel() { return (mFlags & kIsTopLevel) != 0; }
bool isWithinWith() { return (mFlags & kIsWithinWith) != 0; }
bool isStaticMethod() { return (mFlags & kIsStaticMethod) != 0; }
void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); }
JSType *findType(const StringAtom& typeName);
TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret);
ICodeModule *genFunction(FunctionStmtNode *f);
public:
ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, bool atTopLevel = true);
ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, ICodeGeneratorFlags flags = kIsTopLevel);
~ICodeGenerator()
{

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

@ -162,6 +162,16 @@ namespace JSClasses {
return mStaticSlots[name];
}
bool hasStatic(const String& name, JSType*& type)
{
JSSlots::const_iterator i = mStaticSlots.find(name);
if (i != mStaticSlots.end()) {
type = i->second.mType;
return true;
}
return false;
}
bool hasStatic(const String& name)
{
return (mStaticSlots.find(name) != mStaticSlots.end());

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

@ -652,7 +652,7 @@ namespace VM {
Instruction_3<TypedRegister, JSClass*, uint32>
(GET_STATIC, aOp1, aOp2, aOp3) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[GET_STATIC] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << mOp3;
f << opcodeNames[GET_STATIC] << "\t" << "R" << mOp1.first << ", " << mOp2->getName() << ", " << mOp3;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
@ -1084,7 +1084,7 @@ namespace VM {
Instruction_3<JSClass*, uint32, TypedRegister>
(SET_STATIC, aOp1, aOp2, aOp3) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[SET_STATIC] << "\t" << "'" << *mOp1 << "'" << ", " << mOp2 << ", " << "R" << mOp3.first;
f << opcodeNames[SET_STATIC] << "\t" << mOp1->getName() << ", " << mOp2 << ", " << "R" << mOp3.first;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
@ -1134,7 +1134,7 @@ namespace VM {
Instruction_4<TypedRegister, JSClass*, const StringAtom*, RegisterList>
(STATIC_CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[STATIC_CALL] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << "'" << *mOp3 << "'" << ", " << mOp4;
f << opcodeNames[STATIC_CALL] << "\t" << "R" << mOp1.first << ", " << mOp2->getName() << ", " << "'" << *mOp3 << "'" << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
@ -1150,7 +1150,7 @@ namespace VM {
Instruction_4<TypedRegister, JSClass*, uint32, double>
(STATIC_XCR, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[STATIC_XCR] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << mOp3 << ", " << mOp4;
f << opcodeNames[STATIC_XCR] << "\t" << "R" << mOp1.first << ", " << mOp2->getName() << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
@ -1313,6 +1313,7 @@ namespace VM {
/* print() and printOperands() inherited from Arithmetic */
};
} /* namespace VM */
} /* namespace JavaScript */

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

@ -154,6 +154,9 @@ static ICodeModule* genCode(Context &cx, StmtNode *p, const String &fileName)
icg.returnStmt(ret);
ICodeModule *icm = icg.complete();
//stdOut << icg;
icm->setFileName (fileName);
return icm;
}

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

@ -509,12 +509,14 @@ sub get_print_body {
push (@oplist, "\"R\" << mOp$op.first");
} elsif ($type eq "Label*") {
push (@oplist, "\"Offset \" << ((mOp$op) ? mOp$op->mOffset : NotAnOffset)")
} elsif ($type =~ /String|JSClass\*/) {
} elsif ($type =~ /String/) {
push (@oplist, "\"'\" << *mOp$op << \"'\"");
} elsif ($type =~ /bool/) {
push (@oplist, "\"'\" << ((mOp$op) ? \"true\" : \"false\") << \"'\"");
} elsif ($type =~ /ICodeModule/) {
push (@oplist, "\"ICodeModule\"");
} elsif ($type =~ /JSClass\*/) {
push (@oplist, "mOp$op->getName()");
} else {
push (@oplist, "mOp$op");
}