Removed preprocess step, consolidated identifier handling.

This commit is contained in:
rogerl%netscape.com 2000-07-06 18:26:26 +00:00
Родитель 6c2f34f1b0
Коммит f677b9a1dd
12 изменённых файлов: 624 добавлений и 714 удалений

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

@ -66,11 +66,9 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, ICodeGeneratorFlags flags) ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, ICodeGeneratorFlags flags)
: topRegister(0), : mTopRegister(0),
registerBase(0), mParameterCount(0),
maxRegister(0), mExceptionRegister(TypedRegister(NotARegister, &None_Type)),
parameterCount(0),
exceptionRegister(TypedRegister(NotARegister, &None_Type)),
variableList(new VariableList()), variableList(new VariableList()),
mWorld(world), mWorld(world),
mGlobal(global), mGlobal(global),
@ -90,20 +88,39 @@ JSType *ICodeGenerator::findType(const StringAtom& typeName)
return &Any_Type; return &Any_Type;
} }
TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *type)
{
Register r = mTopRegister;
while (r < mPermanentRegister.size())
if (!mPermanentRegister[r])
break;
else
++r;
if (r == mPermanentRegister.size())
mPermanentRegister.resize(r + 1);
mPermanentRegister[r] = true;
TypedRegister result(r, type);
(*variableList)[name] = result;
mTopRegister = ++r;
return result;
}
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName) TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName)
{ {
if (exceptionRegister.first == NotARegister) { if (mExceptionRegister.first == NotARegister) {
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type); mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
} }
return grabRegister(name, findType(typeName)); return allocateRegister(name, findType(typeName));
} }
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name) TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name)
{ {
if (exceptionRegister.first == NotARegister) { if (mExceptionRegister.first == NotARegister) {
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type); mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
} }
return grabRegister(name, &Any_Type); return allocateRegister(name, &Any_Type);
} }
ICodeModule *ICodeGenerator::complete() ICodeModule *ICodeGenerator::complete()
@ -149,8 +166,7 @@ ICodeModule *ICodeGenerator::complete()
} }
} }
*/ */
markMaxRegister(); ICodeModule* module = new ICodeModule(iCode, variableList, mPermanentRegister.size(), 0, mInstructionMap);
ICodeModule* module = new ICodeModule(iCode, variableList, maxRegister, 0, mInstructionMap);
iCodeOwner = false; // give ownership to the module. iCodeOwner = false; // give ownership to the module.
return module; return module;
} }
@ -160,7 +176,7 @@ ICodeModule *ICodeGenerator::complete()
TypedRegister ICodeGenerator::loadImmediate(double value) TypedRegister ICodeGenerator::loadImmediate(double value)
{ {
TypedRegister dest(getRegister(), &Number_Type); TypedRegister dest(getTempRegister(), &Number_Type);
LoadImmediate *instr = new LoadImmediate(dest, value); LoadImmediate *instr = new LoadImmediate(dest, value);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -168,7 +184,7 @@ TypedRegister ICodeGenerator::loadImmediate(double value)
TypedRegister ICodeGenerator::loadString(String &value) TypedRegister ICodeGenerator::loadString(String &value)
{ {
TypedRegister dest(getRegister(), &String_Type); TypedRegister dest(getTempRegister(), &String_Type);
LoadString *instr = new LoadString(dest, new JSString(value)); LoadString *instr = new LoadString(dest, new JSString(value));
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -176,7 +192,7 @@ TypedRegister ICodeGenerator::loadString(String &value)
TypedRegister ICodeGenerator::loadString(const StringAtom &value) TypedRegister ICodeGenerator::loadString(const StringAtom &value)
{ {
TypedRegister dest(getRegister(), &String_Type); TypedRegister dest(getTempRegister(), &String_Type);
LoadString *instr = new LoadString(dest, new JSString(value)); LoadString *instr = new LoadString(dest, new JSString(value));
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -184,7 +200,7 @@ TypedRegister ICodeGenerator::loadString(const StringAtom &value)
TypedRegister ICodeGenerator::loadBoolean(bool value) TypedRegister ICodeGenerator::loadBoolean(bool value)
{ {
TypedRegister dest(getRegister(), &Boolean_Type); TypedRegister dest(getTempRegister(), &Boolean_Type);
LoadBoolean *instr = new LoadBoolean(dest, value); LoadBoolean *instr = new LoadBoolean(dest, value);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -192,7 +208,7 @@ TypedRegister ICodeGenerator::loadBoolean(bool value)
TypedRegister ICodeGenerator::newObject() TypedRegister ICodeGenerator::newObject()
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
NewObject *instr = new NewObject(dest); NewObject *instr = new NewObject(dest);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -200,7 +216,7 @@ TypedRegister ICodeGenerator::newObject()
TypedRegister ICodeGenerator::newClass(const StringAtom &name) TypedRegister ICodeGenerator::newClass(const StringAtom &name)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
NewClass *instr = new NewClass(dest, &name); NewClass *instr = new NewClass(dest, &name);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -208,7 +224,7 @@ TypedRegister ICodeGenerator::newClass(const StringAtom &name)
TypedRegister ICodeGenerator::newFunction(ICodeModule *icm) TypedRegister ICodeGenerator::newFunction(ICodeModule *icm)
{ {
TypedRegister dest(getRegister(), &Function_Type); TypedRegister dest(getTempRegister(), &Function_Type);
NewFunction *instr = new NewFunction(dest, icm); NewFunction *instr = new NewFunction(dest, icm);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -216,7 +232,7 @@ TypedRegister ICodeGenerator::newFunction(ICodeModule *icm)
TypedRegister ICodeGenerator::newArray() TypedRegister ICodeGenerator::newArray()
{ {
TypedRegister dest(getRegister(), &Array_Type); TypedRegister dest(getTempRegister(), &Array_Type);
NewArray *instr = new NewArray(dest); NewArray *instr = new NewArray(dest);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -226,7 +242,7 @@ TypedRegister ICodeGenerator::newArray()
TypedRegister ICodeGenerator::loadName(const StringAtom &name) TypedRegister ICodeGenerator::loadName(const StringAtom &name)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
LoadName *instr = new LoadName(dest, &name); LoadName *instr = new LoadName(dest, &name);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -240,7 +256,7 @@ void ICodeGenerator::saveName(const StringAtom &name, TypedRegister value)
TypedRegister ICodeGenerator::nameXcr(const StringAtom &name, ICodeOp op) TypedRegister ICodeGenerator::nameXcr(const StringAtom &name, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Number_Type); TypedRegister dest(getTempRegister(), &Number_Type);
NameXcr *instr = new NameXcr(dest, &name, (op == ADD) ? 1.0 : -1.0); NameXcr *instr = new NameXcr(dest, &name, (op == ADD) ? 1.0 : -1.0);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -250,7 +266,7 @@ TypedRegister ICodeGenerator::nameXcr(const StringAtom &name, ICodeOp op)
TypedRegister ICodeGenerator::varXcr(TypedRegister var, ICodeOp op) TypedRegister ICodeGenerator::varXcr(TypedRegister var, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Number_Type); TypedRegister dest(getTempRegister(), &Number_Type);
VarXcr *instr = new VarXcr(dest, var, (op == ADD) ? 1.0 : -1.0); VarXcr *instr = new VarXcr(dest, var, (op == ADD) ? 1.0 : -1.0);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -261,7 +277,7 @@ TypedRegister ICodeGenerator::varXcr(TypedRegister var, ICodeOp op)
TypedRegister ICodeGenerator::deleteProperty(TypedRegister base, const StringAtom &name) TypedRegister ICodeGenerator::deleteProperty(TypedRegister base, const StringAtom &name)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
DeleteProp *instr = new DeleteProp(dest, base, &name); DeleteProp *instr = new DeleteProp(dest, base, &name);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -269,7 +285,7 @@ TypedRegister ICodeGenerator::deleteProperty(TypedRegister base, const StringAto
TypedRegister ICodeGenerator::getProperty(TypedRegister base, const StringAtom &name) TypedRegister ICodeGenerator::getProperty(TypedRegister base, const StringAtom &name)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
GetProp *instr = new GetProp(dest, base, &name); GetProp *instr = new GetProp(dest, base, &name);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -284,7 +300,7 @@ void ICodeGenerator::setProperty(TypedRegister base, const StringAtom &name,
TypedRegister ICodeGenerator::propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op) TypedRegister ICodeGenerator::propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
PropXcr *instr = new PropXcr(dest, base, &name, (op == ADD) ? 1.0 : -1.0); PropXcr *instr = new PropXcr(dest, base, &name, (op == ADD) ? 1.0 : -1.0);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -296,7 +312,7 @@ TypedRegister ICodeGenerator::propertyXcr(TypedRegister base, const StringAtom &
TypedRegister ICodeGenerator::getStatic(JSClass *base, const StringAtom &name) TypedRegister ICodeGenerator::getStatic(JSClass *base, const StringAtom &name)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
const JSSlot& slot = base->getStatic(name); const JSSlot& slot = base->getStatic(name);
GetStatic *instr = new GetStatic(dest, base, slot.mIndex); GetStatic *instr = new GetStatic(dest, base, slot.mIndex);
iCode->push_back(instr); iCode->push_back(instr);
@ -313,7 +329,7 @@ void ICodeGenerator::setStatic(JSClass *base, const StringAtom &name,
TypedRegister ICodeGenerator::staticXcr(JSClass *base, const StringAtom &name, ICodeOp op) TypedRegister ICodeGenerator::staticXcr(JSClass *base, const StringAtom &name, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
const JSSlot& slot = base->getStatic(name); const JSSlot& slot = base->getStatic(name);
StaticXcr *instr = new StaticXcr(dest, base, slot.mIndex, 1.0); StaticXcr *instr = new StaticXcr(dest, base, slot.mIndex, 1.0);
iCode->push_back(instr); iCode->push_back(instr);
@ -325,7 +341,7 @@ TypedRegister ICodeGenerator::staticXcr(JSClass *base, const StringAtom &name, I
TypedRegister ICodeGenerator::getSlot(TypedRegister base, uint32 slot) TypedRegister ICodeGenerator::getSlot(TypedRegister base, uint32 slot)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
GetSlot *instr = new GetSlot(dest, base, slot); GetSlot *instr = new GetSlot(dest, base, slot);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -340,7 +356,7 @@ void ICodeGenerator::setSlot(TypedRegister base, uint32 slot,
TypedRegister ICodeGenerator::slotXcr(TypedRegister base, uint32 slot, ICodeOp op) TypedRegister ICodeGenerator::slotXcr(TypedRegister base, uint32 slot, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
SlotXcr *instr = new SlotXcr(dest, base, slot, (op == ADD) ? 1.0 : -1.0); SlotXcr *instr = new SlotXcr(dest, base, slot, (op == ADD) ? 1.0 : -1.0);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -351,7 +367,7 @@ TypedRegister ICodeGenerator::slotXcr(TypedRegister base, uint32 slot, ICodeOp o
TypedRegister ICodeGenerator::getElement(TypedRegister base, TypedRegister index) TypedRegister ICodeGenerator::getElement(TypedRegister base, TypedRegister index)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
GetElement *instr = new GetElement(dest, base, index); GetElement *instr = new GetElement(dest, base, index);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -366,7 +382,7 @@ void ICodeGenerator::setElement(TypedRegister base, TypedRegister index,
TypedRegister ICodeGenerator::elementXcr(TypedRegister base, TypedRegister index, ICodeOp op) TypedRegister ICodeGenerator::elementXcr(TypedRegister base, TypedRegister index, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Number_Type); TypedRegister dest(getTempRegister(), &Number_Type);
ElemXcr *instr = new ElemXcr(dest, base, index, (op == ADD) ? 1.0 : -1.0); ElemXcr *instr = new ElemXcr(dest, base, index, (op == ADD) ? 1.0 : -1.0);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -376,7 +392,7 @@ TypedRegister ICodeGenerator::elementXcr(TypedRegister base, TypedRegister index
TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source) TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
ASSERT(source.first != NotARegister); ASSERT(source.first != NotARegister);
Unary *instr = new Unary (op, dest, source); Unary *instr = new Unary (op, dest, source);
iCode->push_back(instr); iCode->push_back(instr);
@ -394,7 +410,7 @@ void ICodeGenerator::move(TypedRegister destination, TypedRegister source)
TypedRegister ICodeGenerator::logicalNot(TypedRegister source) TypedRegister ICodeGenerator::logicalNot(TypedRegister source)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
Not *instr = new Not(dest, source); Not *instr = new Not(dest, source);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -402,7 +418,7 @@ TypedRegister ICodeGenerator::logicalNot(TypedRegister source)
TypedRegister ICodeGenerator::test(TypedRegister source) TypedRegister ICodeGenerator::test(TypedRegister source)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
Test *instr = new Test(dest, source); Test *instr = new Test(dest, source);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -413,7 +429,7 @@ TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source1,
{ {
ASSERT(source1.first != NotARegister); ASSERT(source1.first != NotARegister);
ASSERT(source2.first != NotARegister); ASSERT(source2.first != NotARegister);
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
Arithmetic *instr = new Arithmetic(op, dest, source1, source2); Arithmetic *instr = new Arithmetic(op, dest, source1, source2);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -421,7 +437,7 @@ TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source1,
TypedRegister ICodeGenerator::call(TypedRegister target, const StringAtom &name, RegisterList args) TypedRegister ICodeGenerator::call(TypedRegister target, const StringAtom &name, RegisterList args)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
Call *instr = new Call(dest, target, &name, args); Call *instr = new Call(dest, target, &name, args);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -429,7 +445,7 @@ TypedRegister ICodeGenerator::call(TypedRegister target, const StringAtom &name,
TypedRegister ICodeGenerator::methodCall(TypedRegister targetBase, TypedRegister targetValue, RegisterList args) TypedRegister ICodeGenerator::methodCall(TypedRegister targetBase, TypedRegister targetValue, RegisterList args)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
MethodCall *instr = new MethodCall(dest, targetBase, targetValue, args); MethodCall *instr = new MethodCall(dest, targetBase, targetValue, args);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -437,7 +453,7 @@ TypedRegister ICodeGenerator::methodCall(TypedRegister targetBase, TypedRegister
TypedRegister ICodeGenerator::staticCall(JSClass *c, const StringAtom &name, RegisterList args) TypedRegister ICodeGenerator::staticCall(JSClass *c, const StringAtom &name, RegisterList args)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
const JSSlot& slot = c->getStatic(name); const JSSlot& slot = c->getStatic(name);
StaticCall *instr = new StaticCall(dest, c, slot.mIndex, args); StaticCall *instr = new StaticCall(dest, c, slot.mIndex, args);
iCode->push_back(instr); iCode->push_back(instr);
@ -618,46 +634,161 @@ static bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex, JST
return false; return false;
} }
ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex)
{
if (!isWithinWith()) {
v = findVariable(name);
if (v.first != NotARegister)
return Var;
else {
if (mClass) { // we're compiling a method of a class
if (!isStaticMethod()) {
if (isSlotName(mClass, name, slotIndex, v.second))
return Slot;
}
if (mClass->hasStatic(name, v.second)) {
return Static;
}
}
v.second = mGlobal->getType(name);
return Name;
}
}
v.second = &Any_Type;
return Name;
}
TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::Kind use, ICodeOp xcrementOp, RegisterList *args)
{
ASSERT(p->getKind() == ExprNode::identifier);
JSType *vType = &Any_Type;
uint32 slotIndex;
TypedRegister ret;
TypedRegister v;
const StringAtom &name = (static_cast<IdentifierExprNode *>(p))->name;
LValueKind lValueKind = resolveIdentifier(name, ret, slotIndex);
TypedRegister thisBase = TypedRegister(0, mClass ? mClass : &Any_Type);
switch (use) {
case ExprNode::identifier:
switch (lValueKind) {
case Var:
break;
case Name:
ret = loadName(name);
break;
case Slot:
ret = getSlot(thisBase, slotIndex);
break;
case Static:
ret = getStatic(mClass, name);
break;
default:
NOT_REACHED("Bad lvalue kind");
}
break;
case ExprNode::preDecrement:
case ExprNode::preIncrement:
switch (lValueKind) {
case Var:
ret = op(xcrementOp, ret, loadImmediate(1.0));
break;
case Name:
ret = loadName(name);
ret = op(xcrementOp, ret, loadImmediate(1.0));
saveName(name, ret);
break;
case Slot:
ret = op(xcrementOp, getSlot(thisBase, slotIndex), loadImmediate(1.0));
setSlot(thisBase, slotIndex, ret);
break;
case Static:
ret = op(xcrementOp, getStatic(mClass, name), loadImmediate(1.0));
setStatic(mClass, name, ret);
break;
default:
NOT_REACHED("Bad lvalue kind");
}
break;
case ExprNode::postDecrement:
case ExprNode::postIncrement:
switch (lValueKind) {
case Var:
ret = varXcr(ret, xcrementOp);
break;
case Name:
ret = nameXcr(name, xcrementOp);
break;
case Slot:
ret = slotXcr(thisBase, slotIndex, xcrementOp);
break;
case Static:
ret = staticXcr(mClass, name, xcrementOp);
break;
default:
NOT_REACHED("Bad lvalue kind");
}
break;
case ExprNode::call:
switch (lValueKind) {
case Var:
ret = call(ret, name, *args);
break;
case Name:
ret = methodCall(TypedRegister(NotARegister, &Null_Type), loadString(name), *args);
break;
case Static:
ret = staticCall(mClass, name, *args);
break;
default:
NOT_REACHED("Bad lvalue kind");
}
break;
}
return ret;
}
TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args) TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args)
{ {
enum {Property, Slot, Static} lValueKind;
ASSERT(b->getKind() == ExprNode::dot); ASSERT(b->getKind() == ExprNode::dot);
LValueKind lValueKind;
if (b->op2->getKind() != ExprNode::identifier) { if (b->op2->getKind() != ExprNode::identifier) {
NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] ) NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] )
} }
else { else {
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name; const StringAtom &fieldName = static_cast<IdentifierExprNode *>(b->op2)->name;
TypedRegister base; TypedRegister base;
JSClass *c = NULL; JSClass *clazz = NULL;
JSType *fieldType = &Any_Type; JSType *fieldType = &Any_Type;
uint32 slotIndex; uint32 slotIndex;
if ((b->op1->getKind() == ExprNode::identifier) && !isWithinWith()) { if ((b->op1->getKind() == ExprNode::identifier) && !isWithinWith()) {
const StringAtom &baseName = (static_cast<IdentifierExprNode *>(b->op1))->name; const StringAtom &baseName = (static_cast<IdentifierExprNode *>(b->op1))->name;
JSType *baseType = &Any_Type; resolveIdentifier(baseName, base, slotIndex);
base = findVariable(baseName);
if (base.first != NotARegister)
baseType = base.second;
else {
// implicit 'this' has a big impact here
baseType = mGlobal->getType(baseName);
}
lValueKind = Property; lValueKind = Property;
if (baseType == &Type_Type) { //
// handle <class name>.<static field>
//
if (base.second == &Type_Type) {
const JSValue &v = mGlobal->getVariable(baseName); const JSValue &v = mGlobal->getVariable(baseName);
c = dynamic_cast<JSClass*>(v.type); clazz = dynamic_cast<JSClass*>(v.type);
if (c && c->hasStatic(name, fieldType)) { if (clazz && clazz->hasStatic(fieldName, fieldType)) {
lValueKind = Static; lValueKind = Static;
} }
} }
if (lValueKind == Property) { if (lValueKind == Property) {
if (isSlotName(baseType, name, slotIndex, fieldType)) if (isSlotName(base.second, fieldName, slotIndex, fieldType))
lValueKind = Slot; lValueKind = Slot;
else { else {
c = dynamic_cast<JSClass*>(baseType); clazz = dynamic_cast<JSClass*>(base.second);
if (c && c->hasStatic(name, fieldType)) if (clazz && clazz->hasStatic(fieldName, fieldType))
lValueKind = Static; lValueKind = Static;
else else
lValueKind = Property; lValueKind = Property;
@ -668,11 +799,11 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
} }
else { else {
base = genExpr(b->op1); base = genExpr(b->op1);
if (isSlotName(base.second, name, slotIndex, fieldType)) if (isSlotName(base.second, fieldName, slotIndex, fieldType))
lValueKind = Slot; lValueKind = Slot;
else { else {
c = dynamic_cast<JSClass*>(base.second); clazz = dynamic_cast<JSClass*>(base.second);
if (c && c->hasStatic(name, fieldType)) if (clazz && clazz->hasStatic(fieldName, fieldType))
lValueKind = Static; lValueKind = Static;
else else
lValueKind = Property; lValueKind = Property;
@ -683,10 +814,10 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
case ExprNode::call: case ExprNode::call:
switch (lValueKind) { switch (lValueKind) {
case Static: case Static:
ret = staticCall(c, name, *args); ret = staticCall(clazz, fieldName, *args);
break; break;
case Property: case Property:
ret = methodCall(base, loadString(name), *args); ret = methodCall(base, loadString(fieldName), *args);
break; break;
default: default:
NOT_REACHED("Bad lvalue kind"); NOT_REACHED("Bad lvalue kind");
@ -706,10 +837,10 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
case ExprNode::bitwiseOrEquals: case ExprNode::bitwiseOrEquals:
switch (lValueKind) { switch (lValueKind) {
case Static: case Static:
v = getStatic(c, name); v = getStatic(clazz, fieldName);
break; break;
case Property: case Property:
v = getProperty(base, name); v = getProperty(base, fieldName);
break; break;
case Slot: case Slot:
v = getSlot(base, slotIndex); v = getSlot(base, slotIndex);
@ -726,10 +857,10 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
case ExprNode::assignment: case ExprNode::assignment:
switch (lValueKind) { switch (lValueKind) {
case Static: case Static:
setStatic(c, name, ret); setStatic(clazz, fieldName, ret);
break; break;
case Property: case Property:
setProperty(base, name, ret); setProperty(base, fieldName, ret);
break; break;
case Slot: case Slot:
setSlot(base, slotIndex, ret); setSlot(base, slotIndex, ret);
@ -742,10 +873,10 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
case ExprNode::postIncrement: case ExprNode::postIncrement:
switch (lValueKind) { switch (lValueKind) {
case Static: case Static:
ret = staticXcr(c, name, xcrementOp); ret = staticXcr(clazz, fieldName, xcrementOp);
break; break;
case Property: case Property:
ret = propertyXcr(base, name, xcrementOp); ret = propertyXcr(base, fieldName, xcrementOp);
break; break;
case Slot: case Slot:
ret = slotXcr(base, slotIndex, xcrementOp); ret = slotXcr(base, slotIndex, xcrementOp);
@ -757,12 +888,12 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
case ExprNode::preIncrement: case ExprNode::preIncrement:
switch (lValueKind) { switch (lValueKind) {
case Static: case Static:
ret = op(xcrementOp, getStatic(c, name), loadImmediate(1.0)); ret = op(xcrementOp, getStatic(clazz, fieldName), loadImmediate(1.0));
setStatic(c, name, ret); setStatic(clazz, fieldName, ret);
break; break;
case Property: case Property:
ret = op(xcrementOp, getProperty(base, name), loadImmediate(1.0)); ret = op(xcrementOp, getProperty(base, fieldName), loadImmediate(1.0));
setProperty(base, name, ret); setProperty(base, fieldName, ret);
break; break;
case Slot: case Slot:
ret = op(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0)); ret = op(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0));
@ -774,7 +905,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
break; break;
case ExprNode::Delete: case ExprNode::Delete:
if (lValueKind == Property) { if (lValueKind == Property) {
ret = deleteProperty(base, name); ret = deleteProperty(base, fieldName);
} }
break; break;
default: default:
@ -857,34 +988,10 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
if (i->op->getKind() == ExprNode::dot) { if (i->op->getKind() == ExprNode::dot) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op); BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
ret = handleDot(b, ExprNode::call, xcrementOp, ret, &args); ret = handleDot(b, ExprNode::call, xcrementOp, ret, &args);
/*
TypedRegister base = genExpr(b->op1);
// might be Class.<method>()
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
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 = staticCall(c, name, args);
break;
}
}
ret = methodCall(base, loadString(name), args);
*/
} }
else else
if (i->op->getKind() == ExprNode::identifier) { if (i->op->getKind() == ExprNode::identifier) {
if (!isWithinWith()) { ret = handleIdentifier(static_cast<IdentifierExprNode *>(i->op), ExprNode::call, xcrementOp, &args);
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(i->op))->name);
if (v.first != NotARegister)
ret = call(v, static_cast<IdentifierExprNode *>(i->op)->name, args);
else
ret = call(TypedRegister(NotARegister, &Null_Type), static_cast<IdentifierExprNode *>(i->op)->name, args);
}
else
ret = methodCall(TypedRegister(NotARegister, &Null_Type), loadString(static_cast<IdentifierExprNode *>(i->op)->name), args);
} }
else else
if (i->op->getKind() == ExprNode::index) { if (i->op->getKind() == ExprNode::index) {
@ -916,34 +1023,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
break; break;
case ExprNode::identifier : case ExprNode::identifier :
{ {
const StringAtom &name = (static_cast<IdentifierExprNode *>(p))->name; ret = handleIdentifier(static_cast<IdentifierExprNode *>(p), ExprNode::identifier, xcrementOp, NULL);
if (!isWithinWith()) {
TypedRegister v = findVariable(name);
if (v.first != NotARegister)
ret = v;
else {
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);
}
}
else
ret = loadName(name);
} }
break; break;
case ExprNode::number : case ExprNode::number :
@ -958,26 +1038,11 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
{ {
UnaryExprNode *u = static_cast<UnaryExprNode *>(p); UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
if (u->op->getKind() == ExprNode::dot) { if (u->op->getKind() == ExprNode::dot) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op); ret = handleDot(static_cast<BinaryExprNode *>(u->op), p->getKind(), xcrementOp, ret, NULL);
ret = handleDot(b, p->getKind(), xcrementOp, ret, NULL);
} }
else else
if (u->op->getKind() == ExprNode::identifier) { if (u->op->getKind() == ExprNode::identifier) {
if (!isWithinWith()) { ret = handleIdentifier(static_cast<IdentifierExprNode *>(u->op), p->getKind(), xcrementOp, NULL);
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
if (v.first != NotARegister)
ret = op(xcrementOp, ret, loadImmediate(1.0));
else {
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
ret = op(xcrementOp, ret, loadImmediate(1.0));
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
}
}
else {
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
ret = op(xcrementOp, ret, loadImmediate(1.0));
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
}
} }
else else
if (u->op->getKind() == ExprNode::index) { if (u->op->getKind() == ExprNode::index) {
@ -998,20 +1063,11 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
{ {
UnaryExprNode *u = static_cast<UnaryExprNode *>(p); UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
if (u->op->getKind() == ExprNode::dot) { if (u->op->getKind() == ExprNode::dot) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op); ret = handleDot(static_cast<BinaryExprNode *>(u->op), p->getKind(), xcrementOp, ret, NULL);
ret = handleDot(b, p->getKind(), xcrementOp, ret, NULL);
} }
else else
if (u->op->getKind() == ExprNode::identifier) { if (u->op->getKind() == ExprNode::identifier) {
if (!isWithinWith()) { ret = handleIdentifier(static_cast<IdentifierExprNode *>(u->op), p->getKind(), xcrementOp, NULL);
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
if (v.first != NotARegister)
ret = varXcr(v, xcrementOp);
else
ret = nameXcr((static_cast<IdentifierExprNode *>(u->op))->name, xcrementOp);
}
else
ret = nameXcr((static_cast<IdentifierExprNode *>(u->op))->name, xcrementOp);
} }
else else
if (u->op->getKind() == ExprNode::index) { if (u->op->getKind() == ExprNode::index) {
@ -1291,7 +1347,6 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name); icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name);
v = v->next; v = v->next;
} }
icg.preprocess(f->function.body);
icg.genStmt(f->function.body); icg.genStmt(f->function.body);
//stdOut << icg; //stdOut << icg;
ICodeModule *icm = icg.complete(); ICodeModule *icm = icg.complete();
@ -1325,116 +1380,6 @@ bool LabelEntry::containsLabel(const StringAtom *label)
return false; return false;
} }
void ICodeGenerator::preprocess(StmtNode *p)
{
switch (p->getKind()) {
case StmtNode::block:
{
BlockStmtNode *b = static_cast<BlockStmtNode *>(p);
StmtNode *s = b->statements;
while (s) {
preprocess(s);
s = s->next;
}
}
break;
case StmtNode::Var:
{
VariableStmtNode *vs = static_cast<VariableStmtNode *>(p);
VariableBinding *v = vs->bindings;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
if (v->type && (v->type->getKind() == ExprNode::identifier))
if (isTopLevel())
mGlobal->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name,
findType((static_cast<IdentifierExprNode *>(v->type))->name));
else
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name,
(static_cast<IdentifierExprNode *>(v->type))->name);
else
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name);
v = v->next;
}
}
break;
case StmtNode::DoWhile:
{
UnaryStmtNode *d = static_cast<UnaryStmtNode *>(p);
preprocess(d->stmt);
}
break;
case StmtNode::While:
{
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
preprocess(w->stmt);
}
break;
case StmtNode::For:
{
ForStmtNode *f = static_cast<ForStmtNode *>(p);
if (f->initializer)
preprocess(f->initializer);
preprocess(f->stmt);
}
break;
case StmtNode::If:
{
UnaryStmtNode *i = static_cast<UnaryStmtNode *>(p);
preprocess(i->stmt);
}
break;
case StmtNode::IfElse:
{
BinaryStmtNode *i = static_cast<BinaryStmtNode *>(p);
preprocess(i->stmt);
preprocess(i->stmt2);
}
break;
case StmtNode::With:
{
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
preprocess(w->stmt);
}
break;
case StmtNode::Switch:
{
SwitchStmtNode *sw = static_cast<SwitchStmtNode *>(p);
StmtNode *s = sw->statements;
while (s) {
if (s->getKind() != StmtNode::Case)
preprocess(s);
s = s->next;
}
}
break;
case StmtNode::label:
{
LabelStmtNode *l = static_cast<LabelStmtNode *>(p);
preprocess(l->stmt);
}
break;
case StmtNode::Try:
{
TryStmtNode *t = static_cast<TryStmtNode *>(p);
genStmt(t->stmt);
if (t->catches) {
CatchClause *c = t->catches;
while (c) {
preprocess(c->stmt);
c = c->next;
}
}
if (t->finally)
genStmt(t->finally);
}
break;
default:
break;
}
}
static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKind) static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKind)
{ {
while (identifiers) { while (identifiers) {
@ -1458,7 +1403,6 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f)
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name); icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name);
v = v->next; v = v->next;
} }
icg.preprocess(f->function.body);
icg.genStmt(f->function.body); icg.genStmt(f->function.body);
return icg.complete(); return icg.complete();
@ -1469,8 +1413,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
TypedRegister ret(NotARegister, &None_Type); TypedRegister ret(NotARegister, &None_Type);
startStatement(p->pos); startStatement(p->pos);
if (exceptionRegister.first == NotARegister) { if (mExceptionRegister.first == NotARegister) {
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type); mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
} }
switch (p->getKind()) { switch (p->getKind()) {
@ -1565,7 +1509,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
// freeze the class. // freeze the class.
thisClass->complete(); thisClass->complete();
if (ccg.getICode()->size()) if (ccg.getICode()->size())
thisClass->setConstructor(ccg.complete()); thisClass->setInitializer(ccg.complete());
// REVISIT: using the scope of the class to store both methods and statics. // REVISIT: using the scope of the class to store both methods and statics.
if (scg.getICode()->size()) { if (scg.getICode()->size()) {
Interpreter::Context cx(*mWorld, thisScope); Interpreter::Context cx(*mWorld, thisScope);
@ -1591,8 +1535,18 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
VariableStmtNode *vs = static_cast<VariableStmtNode *>(p); VariableStmtNode *vs = static_cast<VariableStmtNode *>(p);
VariableBinding *v = vs->bindings; VariableBinding *v = vs->bindings;
while (v) { while (v) {
if (v->name && v->initializer) { if (v->name && (v->name->getKind() == ExprNode::identifier)) {
if (v->name->getKind() == ExprNode::identifier) { if (v->type && (v->type->getKind() == ExprNode::identifier)) {
if (isTopLevel())
mGlobal->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name,
findType((static_cast<IdentifierExprNode *>(v->type))->name));
else
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name,
(static_cast<IdentifierExprNode *>(v->type))->name);
}
else
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name);
if (v->initializer) {
if (!isTopLevel() && !isWithinWith()) { if (!isTopLevel() && !isWithinWith()) {
TypedRegister r = genExpr(v->name); TypedRegister r = genExpr(v->name);
TypedRegister val = genExpr(v->initializer); TypedRegister val = genExpr(v->initializer);
@ -1603,7 +1557,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
saveName((static_cast<IdentifierExprNode *>(v->name))->name, val); saveName((static_cast<IdentifierExprNode *>(v->name))->name, val);
} }
} }
// XXX what's the else case here, when does a VariableBinding NOT have an identifier child?
} }
v = v->next; v = v->next;
} }
@ -1889,19 +1842,19 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
CatchClause *c = t->catches; CatchClause *c = t->catches;
while (c) { while (c) {
// Bind the incoming exception ... // Bind the incoming exception ...
setRegisterForVariable(c->name, exceptionRegister); setRegisterForVariable(c->name, mExceptionRegister);
genStmt(c->stmt); genStmt(c->stmt);
if (finallyLabel) if (finallyLabel)
jsr(finallyLabel); jsr(finallyLabel);
throwStmt(exceptionRegister); throwStmt(mExceptionRegister);
c = c->next; c = c->next;
} }
} }
if (finallyLabel) { if (finallyLabel) {
setLabel(finallyInvoker); setLabel(finallyInvoker);
jsr(finallyLabel); jsr(finallyLabel);
throwStmt(exceptionRegister); throwStmt(mExceptionRegister);
setLabel(finallyLabel); setLabel(finallyLabel);
genStmt(t->finally); genStmt(t->finally);

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

@ -118,69 +118,70 @@ namespace ICG {
bool iCodeOwner; bool iCodeOwner;
LabelList labels; LabelList labels;
Register topRegister; // highest (currently) alloacated register Register mTopRegister; // highest (currently) alloacated register
Register registerBase; // start of registers available for expression temps uint32 mParameterCount; // number of parameters declared for the function
uint32 maxRegister; // highest (ever) allocated register // these must come before any variables declared.
uint32 parameterCount; // number of parameters declared for the function TypedRegister mExceptionRegister; // reserved to carry the exception object.
// these must come before any variables declared. VariableList *variableList; // name|register pair for each variable
TypedRegister exceptionRegister;// reserved to carry the exception object.
VariableList *variableList; // name|register pair for each variable
World *mWorld; // used to register strings World *mWorld; // used to register strings
JSScope *mGlobal; // the scope for compiling within JSScope *mGlobal; // the scope for compiling within
LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct
// maps source position to instruction index // maps source position to instruction index
InstructionMap *mInstructionMap; InstructionMap *mInstructionMap;
JSClass *mClass; // enclosing class when generating code for methods JSClass *mClass; // enclosing class when generating code for methods
ICodeGeneratorFlags mFlags; // assorted flags ICodeGeneratorFlags mFlags; // assorted flags
std::vector<bool> mPermanentRegister;
Register getTempRegister()
{
while (mTopRegister < mPermanentRegister.size())
if (!mPermanentRegister[mTopRegister])
return mTopRegister++;
else
++mTopRegister;
mPermanentRegister.resize(mTopRegister + 1);
mPermanentRegister[mTopRegister] = false;
return mTopRegister++;
}
void resetTopRegister() { mTopRegister = mParameterCount; }
void resetStatement() { resetTopRegister(); }
TypedRegister allocateRegister(const StringAtom& name, JSType *type);
void setRegisterForVariable(const StringAtom& name, TypedRegister r) { (*variableList)[name] = r; }
JSType *findType(const StringAtom& typeName);
void markMaxRegister()
{ if (topRegister > maxRegister) maxRegister = topRegister; }
Register getRegister()
{ return topRegister++; }
void resetTopRegister()
{ markMaxRegister(); topRegister = registerBase; }
void setLabel(Label *label); void setLabel(Label *label);
void jsr(Label *label) { iCode->push_back(new Jsr(label)); } void jsr(Label *label) { iCode->push_back(new Jsr(label)); }
void rts() { iCode->push_back(new Rts()); } void rts() { iCode->push_back(new Rts()); }
void branch(Label *label); void branch(Label *label);
GenericBranch *branchTrue(Label *label, TypedRegister condition); GenericBranch *branchTrue(Label *label, TypedRegister condition);
GenericBranch *branchFalse(Label *label, TypedRegister condition); GenericBranch *branchFalse(Label *label, TypedRegister condition);
void beginTry(Label *catchLabel, Label *finallyLabel) void beginTry(Label *catchLabel, Label *finallyLabel)
{ iCode->push_back(new Tryin(catchLabel, finallyLabel)); } { iCode->push_back(new Tryin(catchLabel, finallyLabel)); }
void endTry() void endTry() { iCode->push_back(new Tryout()); }
{ iCode->push_back(new Tryout()); }
void beginWith(TypedRegister obj) void beginWith(TypedRegister obj) { iCode->push_back(new Within(obj)); }
{ iCode->push_back(new Within(obj)); } void endWith() { iCode->push_back(new Without()); }
void endWith()
{ iCode->push_back(new Without()); }
void resetStatement() { resetTopRegister(); }
void setRegisterForVariable(const StringAtom& name, TypedRegister r)
{ (*variableList)[name] = r; }
void startStatement(uint32 pos) void startStatement(uint32 pos) { (*mInstructionMap)[iCode->size()] = pos; }
{ (*mInstructionMap)[iCode->size()] = pos; }
ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind); ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind);
TypedRegister grabRegister(const StringAtom& name, JSType *type)
{
TypedRegister result(getRegister(), type);
(*variableList)[name] = result;
registerBase = topRegister;
return result;
}
bool isTopLevel() { return (mFlags & kIsTopLevel) != 0; } bool isTopLevel() { return (mFlags & kIsTopLevel) != 0; }
bool isWithinWith() { return (mFlags & kIsWithinWith) != 0; } bool isWithinWith() { return (mFlags & kIsWithinWith) != 0; }
@ -188,7 +189,11 @@ namespace ICG {
void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); } void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); }
JSType *findType(const StringAtom& typeName);
typedef enum {Var, Property, Slot, Static, Name} LValueKind;
LValueKind resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex);
TypedRegister handleIdentifier(IdentifierExprNode *p, ExprNode::Kind use, ICodeOp xcrementOp, RegisterList *args);
TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args); TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args);
ICodeModule *genFunction(FunctionStmtNode *f); ICodeModule *genFunction(FunctionStmtNode *f);
@ -207,32 +212,30 @@ namespace ICG {
ICodeModule *complete(); ICodeModule *complete();
TypedRegister genExpr(ExprNode *p, TypedRegister genExpr(ExprNode *p,
bool needBoolValueInBranch = false, bool needBoolValueInBranch = false,
Label *trueBranch = NULL, Label *trueBranch = NULL,
Label *falseBranch = NULL); Label *falseBranch = NULL);
void preprocess(StmtNode *p);
TypedRegister genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL); TypedRegister genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL);
void returnStmt(TypedRegister r); void returnStmt(TypedRegister r);
void returnStmt(); void returnStmt();
void throwStmt(TypedRegister r) void throwStmt(TypedRegister r) { iCode->push_back(new Throw(r)); }
{ iCode->push_back(new Throw(r)); } void debuggerStmt() { iCode->push_back(new Debugger()); }
void debuggerStmt()
{ iCode->push_back(new Debugger()); }
TypedRegister allocateVariable(const StringAtom& name); TypedRegister allocateVariable(const StringAtom& name);
TypedRegister allocateVariable(const StringAtom& name, const StringAtom& typeName); TypedRegister allocateVariable(const StringAtom& name, const StringAtom& typeName);
TypedRegister findVariable(const StringAtom& name) TypedRegister findVariable(const StringAtom& name)
{ VariableList::iterator i = variableList->find(name); {
return (i == variableList->end()) ? TypedRegister(NotARegister, &None_Type) : (*i).second; } VariableList::iterator i = variableList->find(name);
return (i == variableList->end()) ? TypedRegister(NotARegister, &None_Type) : (*i).second;
}
TypedRegister allocateParameter(const StringAtom& name) TypedRegister allocateParameter(const StringAtom& name) { mParameterCount++; return allocateRegister(name, &Any_Type); }
{ parameterCount++; return grabRegister(name, &Any_Type); }
TypedRegister allocateParameter(const StringAtom& name, const StringAtom& typeName) TypedRegister allocateParameter(const StringAtom& name, const StringAtom& typeName)
{ parameterCount++; return grabRegister(name, findType(typeName)); } { mParameterCount++; return allocateRegister(name, findType(typeName)); }
TypedRegister allocateParameter(const StringAtom& name, JSType *type) TypedRegister allocateParameter(const StringAtom& name, JSType *type)
{ parameterCount++; return grabRegister(name, type); } { mParameterCount++; return allocateRegister(name, type); }
Formatter& print(Formatter& f); Formatter& print(Formatter& f);
@ -279,8 +282,7 @@ namespace ICG {
TypedRegister varXcr(TypedRegister var, ICodeOp op); TypedRegister varXcr(TypedRegister var, ICodeOp op);
Register getRegisterBase() { return topRegister; } InstructionStream *getICode() { return iCode; }
InstructionStream *getICode() { return iCode; }
Label *getLabel(); Label *getLabel();

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

@ -679,14 +679,14 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
InstructionIterator nextPC = ++mPC; InstructionIterator nextPC = ++mPC;
do { do {
// call the constructor(s), if any. // call the constructor(s), if any.
ICodeModule* ctor = thisClass->getConstructor(); ICodeModule* init = thisClass->getInitializer();
if (ctor) { if (init) {
mLinkage = new Linkage(mLinkage, nextPC, mLinkage = new Linkage(mLinkage, nextPC,
mActivation, mGlobal, voidRegister); mActivation, mGlobal, voidRegister);
mActivation = new Activation(ctor, args); mActivation = new Activation(init, args);
registers = &mActivation->mRegisters; registers = &mActivation->mRegisters;
nextPC = ctor->its_iCode->begin(); nextPC = init->its_iCode->begin();
endPC = ctor->its_iCode->end(); endPC = init->its_iCode->end();
} }
thisClass = thisClass->getSuperClass(); thisClass = thisClass->getSuperClass();
} while (thisClass); } while (thisClass);

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

@ -147,7 +147,6 @@ static ICodeModule* genCode(Context &cx, StmtNode *p, const String &fileName)
TypedRegister ret(NotARegister, &None_Type); TypedRegister ret(NotARegister, &None_Type);
while (p) { while (p) {
icg.preprocess(p);
ret = icg.genStmt(p); ret = icg.genStmt(p);
p = p->next; p = p->next;
} }
@ -155,7 +154,7 @@ static ICodeModule* genCode(Context &cx, StmtNode *p, const String &fileName)
ICodeModule *icm = icg.complete(); ICodeModule *icm = icg.complete();
//stdOut << icg; stdOut << icg;
icm->setFileName (fileName); icm->setFileName (fileName);
return icm; return icm;
@ -344,7 +343,8 @@ class Tracer : public Context::Listener {
char * tests[] = { char * tests[] = {
"function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" , "function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" ,
"a = { f1: 1, f2: 2}; print(a.f2++, \" should be 2\"); print(a.f2 <<= 1, \" should be 6\"); return;" "a = { f1: 1, f2: 2}; print(a.f2++, \" should be 2\"); print(a.f2 <<= 1, \" should be 6\"); return;" ,
"class A { static var b = 3; static function s() { return b++; } } var a:A = new A; print(a.s()); print(A.b); return;"
}; };
static void testCompile() static void testCompile()
@ -361,15 +361,11 @@ static void testCompile()
StmtNode *parsedStatements = p.parseProgram(); StmtNode *parsedStatements = p.parseProgram();
ICodeGenerator icg(&world, &glob); ICodeGenerator icg(&world, &glob);
StmtNode *s = parsedStatements; StmtNode *s = parsedStatements;
while (s) {
icg.preprocess(s);
s = s->next;
}
s = parsedStatements;
while (s) { while (s) {
icg.genStmt(s); icg.genStmt(s);
s = s->next; s = s->next;
} }
// stdOut << icg;
cx.interpret(icg.complete(), JSValues()); cx.interpret(icg.complete(), JSValues());
} }
} }

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

@ -79,7 +79,7 @@ namespace JSClasses {
uint32 mStaticCount; uint32 mStaticCount;
JSSlots mStaticSlots; JSSlots mStaticSlots;
JSValue* mStaticData; JSValue* mStaticData;
ICodeModule* mConstructor; ICodeModule* mInitializer;
// typedef std::vector<ICodeModule*, gc_allocator<ICodeModule*> > JSMethods; // typedef std::vector<ICodeModule*, gc_allocator<ICodeModule*> > JSMethods;
// JSMethods mMethods; // JSMethods mMethods;
public: public:
@ -89,7 +89,7 @@ namespace JSClasses {
mSlotCount(superClass ? superClass->mSlotCount : 0), mSlotCount(superClass ? superClass->mSlotCount : 0),
mStaticCount(0), mStaticCount(0),
mStaticData(0), mStaticData(0),
mConstructor(0) mInitializer(0)
{ {
// to "inherit" superClass methods. // to "inherit" superClass methods.
if (superClass) if (superClass)
@ -106,14 +106,14 @@ namespace JSClasses {
return mScope; return mScope;
} }
void setConstructor(ICodeModule* ctor) void setInitializer(ICodeModule* init)
{ {
mConstructor = ctor; mInitializer = init;
} }
ICodeModule* getConstructor() ICodeModule* getInitializer()
{ {
return mConstructor; return mInitializer;
} }
const JSSlot& defineSlot(const String& name, JSType* type) const JSSlot& defineSlot(const String& name, JSType* type)

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

@ -175,6 +175,10 @@ SOURCE=..\hash.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\icode.h
# End Source File
# Begin Source File
SOURCE=..\icodegenerator.h SOURCE=..\icodegenerator.h
# End Source File # End Source File
# Begin Source File # Begin Source File

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

@ -66,11 +66,9 @@ Formatter& operator<<(Formatter &f, ICodeModule &i)
ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, ICodeGeneratorFlags flags) ICodeGenerator::ICodeGenerator(World *world, JSScope *global, JSClass *aClass, ICodeGeneratorFlags flags)
: topRegister(0), : mTopRegister(0),
registerBase(0), mParameterCount(0),
maxRegister(0), mExceptionRegister(TypedRegister(NotARegister, &None_Type)),
parameterCount(0),
exceptionRegister(TypedRegister(NotARegister, &None_Type)),
variableList(new VariableList()), variableList(new VariableList()),
mWorld(world), mWorld(world),
mGlobal(global), mGlobal(global),
@ -90,20 +88,39 @@ JSType *ICodeGenerator::findType(const StringAtom& typeName)
return &Any_Type; return &Any_Type;
} }
TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *type)
{
Register r = mTopRegister;
while (r < mPermanentRegister.size())
if (!mPermanentRegister[r])
break;
else
++r;
if (r == mPermanentRegister.size())
mPermanentRegister.resize(r + 1);
mPermanentRegister[r] = true;
TypedRegister result(r, type);
(*variableList)[name] = result;
mTopRegister = ++r;
return result;
}
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName) TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName)
{ {
if (exceptionRegister.first == NotARegister) { if (mExceptionRegister.first == NotARegister) {
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type); mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
} }
return grabRegister(name, findType(typeName)); return allocateRegister(name, findType(typeName));
} }
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name) TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name)
{ {
if (exceptionRegister.first == NotARegister) { if (mExceptionRegister.first == NotARegister) {
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type); mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
} }
return grabRegister(name, &Any_Type); return allocateRegister(name, &Any_Type);
} }
ICodeModule *ICodeGenerator::complete() ICodeModule *ICodeGenerator::complete()
@ -149,8 +166,7 @@ ICodeModule *ICodeGenerator::complete()
} }
} }
*/ */
markMaxRegister(); ICodeModule* module = new ICodeModule(iCode, variableList, mPermanentRegister.size(), 0, mInstructionMap);
ICodeModule* module = new ICodeModule(iCode, variableList, maxRegister, 0, mInstructionMap);
iCodeOwner = false; // give ownership to the module. iCodeOwner = false; // give ownership to the module.
return module; return module;
} }
@ -160,7 +176,7 @@ ICodeModule *ICodeGenerator::complete()
TypedRegister ICodeGenerator::loadImmediate(double value) TypedRegister ICodeGenerator::loadImmediate(double value)
{ {
TypedRegister dest(getRegister(), &Number_Type); TypedRegister dest(getTempRegister(), &Number_Type);
LoadImmediate *instr = new LoadImmediate(dest, value); LoadImmediate *instr = new LoadImmediate(dest, value);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -168,7 +184,7 @@ TypedRegister ICodeGenerator::loadImmediate(double value)
TypedRegister ICodeGenerator::loadString(String &value) TypedRegister ICodeGenerator::loadString(String &value)
{ {
TypedRegister dest(getRegister(), &String_Type); TypedRegister dest(getTempRegister(), &String_Type);
LoadString *instr = new LoadString(dest, new JSString(value)); LoadString *instr = new LoadString(dest, new JSString(value));
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -176,7 +192,7 @@ TypedRegister ICodeGenerator::loadString(String &value)
TypedRegister ICodeGenerator::loadString(const StringAtom &value) TypedRegister ICodeGenerator::loadString(const StringAtom &value)
{ {
TypedRegister dest(getRegister(), &String_Type); TypedRegister dest(getTempRegister(), &String_Type);
LoadString *instr = new LoadString(dest, new JSString(value)); LoadString *instr = new LoadString(dest, new JSString(value));
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -184,7 +200,7 @@ TypedRegister ICodeGenerator::loadString(const StringAtom &value)
TypedRegister ICodeGenerator::loadBoolean(bool value) TypedRegister ICodeGenerator::loadBoolean(bool value)
{ {
TypedRegister dest(getRegister(), &Boolean_Type); TypedRegister dest(getTempRegister(), &Boolean_Type);
LoadBoolean *instr = new LoadBoolean(dest, value); LoadBoolean *instr = new LoadBoolean(dest, value);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -192,7 +208,7 @@ TypedRegister ICodeGenerator::loadBoolean(bool value)
TypedRegister ICodeGenerator::newObject() TypedRegister ICodeGenerator::newObject()
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
NewObject *instr = new NewObject(dest); NewObject *instr = new NewObject(dest);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -200,7 +216,7 @@ TypedRegister ICodeGenerator::newObject()
TypedRegister ICodeGenerator::newClass(const StringAtom &name) TypedRegister ICodeGenerator::newClass(const StringAtom &name)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
NewClass *instr = new NewClass(dest, &name); NewClass *instr = new NewClass(dest, &name);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -208,7 +224,7 @@ TypedRegister ICodeGenerator::newClass(const StringAtom &name)
TypedRegister ICodeGenerator::newFunction(ICodeModule *icm) TypedRegister ICodeGenerator::newFunction(ICodeModule *icm)
{ {
TypedRegister dest(getRegister(), &Function_Type); TypedRegister dest(getTempRegister(), &Function_Type);
NewFunction *instr = new NewFunction(dest, icm); NewFunction *instr = new NewFunction(dest, icm);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -216,7 +232,7 @@ TypedRegister ICodeGenerator::newFunction(ICodeModule *icm)
TypedRegister ICodeGenerator::newArray() TypedRegister ICodeGenerator::newArray()
{ {
TypedRegister dest(getRegister(), &Array_Type); TypedRegister dest(getTempRegister(), &Array_Type);
NewArray *instr = new NewArray(dest); NewArray *instr = new NewArray(dest);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -226,7 +242,7 @@ TypedRegister ICodeGenerator::newArray()
TypedRegister ICodeGenerator::loadName(const StringAtom &name) TypedRegister ICodeGenerator::loadName(const StringAtom &name)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
LoadName *instr = new LoadName(dest, &name); LoadName *instr = new LoadName(dest, &name);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -240,7 +256,7 @@ void ICodeGenerator::saveName(const StringAtom &name, TypedRegister value)
TypedRegister ICodeGenerator::nameXcr(const StringAtom &name, ICodeOp op) TypedRegister ICodeGenerator::nameXcr(const StringAtom &name, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Number_Type); TypedRegister dest(getTempRegister(), &Number_Type);
NameXcr *instr = new NameXcr(dest, &name, (op == ADD) ? 1.0 : -1.0); NameXcr *instr = new NameXcr(dest, &name, (op == ADD) ? 1.0 : -1.0);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -250,7 +266,7 @@ TypedRegister ICodeGenerator::nameXcr(const StringAtom &name, ICodeOp op)
TypedRegister ICodeGenerator::varXcr(TypedRegister var, ICodeOp op) TypedRegister ICodeGenerator::varXcr(TypedRegister var, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Number_Type); TypedRegister dest(getTempRegister(), &Number_Type);
VarXcr *instr = new VarXcr(dest, var, (op == ADD) ? 1.0 : -1.0); VarXcr *instr = new VarXcr(dest, var, (op == ADD) ? 1.0 : -1.0);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -261,7 +277,7 @@ TypedRegister ICodeGenerator::varXcr(TypedRegister var, ICodeOp op)
TypedRegister ICodeGenerator::deleteProperty(TypedRegister base, const StringAtom &name) TypedRegister ICodeGenerator::deleteProperty(TypedRegister base, const StringAtom &name)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
DeleteProp *instr = new DeleteProp(dest, base, &name); DeleteProp *instr = new DeleteProp(dest, base, &name);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -269,7 +285,7 @@ TypedRegister ICodeGenerator::deleteProperty(TypedRegister base, const StringAto
TypedRegister ICodeGenerator::getProperty(TypedRegister base, const StringAtom &name) TypedRegister ICodeGenerator::getProperty(TypedRegister base, const StringAtom &name)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
GetProp *instr = new GetProp(dest, base, &name); GetProp *instr = new GetProp(dest, base, &name);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -284,7 +300,7 @@ void ICodeGenerator::setProperty(TypedRegister base, const StringAtom &name,
TypedRegister ICodeGenerator::propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op) TypedRegister ICodeGenerator::propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
PropXcr *instr = new PropXcr(dest, base, &name, (op == ADD) ? 1.0 : -1.0); PropXcr *instr = new PropXcr(dest, base, &name, (op == ADD) ? 1.0 : -1.0);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -296,7 +312,7 @@ TypedRegister ICodeGenerator::propertyXcr(TypedRegister base, const StringAtom &
TypedRegister ICodeGenerator::getStatic(JSClass *base, const StringAtom &name) TypedRegister ICodeGenerator::getStatic(JSClass *base, const StringAtom &name)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
const JSSlot& slot = base->getStatic(name); const JSSlot& slot = base->getStatic(name);
GetStatic *instr = new GetStatic(dest, base, slot.mIndex); GetStatic *instr = new GetStatic(dest, base, slot.mIndex);
iCode->push_back(instr); iCode->push_back(instr);
@ -313,7 +329,7 @@ void ICodeGenerator::setStatic(JSClass *base, const StringAtom &name,
TypedRegister ICodeGenerator::staticXcr(JSClass *base, const StringAtom &name, ICodeOp op) TypedRegister ICodeGenerator::staticXcr(JSClass *base, const StringAtom &name, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
const JSSlot& slot = base->getStatic(name); const JSSlot& slot = base->getStatic(name);
StaticXcr *instr = new StaticXcr(dest, base, slot.mIndex, 1.0); StaticXcr *instr = new StaticXcr(dest, base, slot.mIndex, 1.0);
iCode->push_back(instr); iCode->push_back(instr);
@ -325,7 +341,7 @@ TypedRegister ICodeGenerator::staticXcr(JSClass *base, const StringAtom &name, I
TypedRegister ICodeGenerator::getSlot(TypedRegister base, uint32 slot) TypedRegister ICodeGenerator::getSlot(TypedRegister base, uint32 slot)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
GetSlot *instr = new GetSlot(dest, base, slot); GetSlot *instr = new GetSlot(dest, base, slot);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -340,7 +356,7 @@ void ICodeGenerator::setSlot(TypedRegister base, uint32 slot,
TypedRegister ICodeGenerator::slotXcr(TypedRegister base, uint32 slot, ICodeOp op) TypedRegister ICodeGenerator::slotXcr(TypedRegister base, uint32 slot, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
SlotXcr *instr = new SlotXcr(dest, base, slot, (op == ADD) ? 1.0 : -1.0); SlotXcr *instr = new SlotXcr(dest, base, slot, (op == ADD) ? 1.0 : -1.0);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -351,7 +367,7 @@ TypedRegister ICodeGenerator::slotXcr(TypedRegister base, uint32 slot, ICodeOp o
TypedRegister ICodeGenerator::getElement(TypedRegister base, TypedRegister index) TypedRegister ICodeGenerator::getElement(TypedRegister base, TypedRegister index)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
GetElement *instr = new GetElement(dest, base, index); GetElement *instr = new GetElement(dest, base, index);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -366,7 +382,7 @@ void ICodeGenerator::setElement(TypedRegister base, TypedRegister index,
TypedRegister ICodeGenerator::elementXcr(TypedRegister base, TypedRegister index, ICodeOp op) TypedRegister ICodeGenerator::elementXcr(TypedRegister base, TypedRegister index, ICodeOp op)
{ {
TypedRegister dest(getRegister(), &Number_Type); TypedRegister dest(getTempRegister(), &Number_Type);
ElemXcr *instr = new ElemXcr(dest, base, index, (op == ADD) ? 1.0 : -1.0); ElemXcr *instr = new ElemXcr(dest, base, index, (op == ADD) ? 1.0 : -1.0);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -376,7 +392,7 @@ TypedRegister ICodeGenerator::elementXcr(TypedRegister base, TypedRegister index
TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source) TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
ASSERT(source.first != NotARegister); ASSERT(source.first != NotARegister);
Unary *instr = new Unary (op, dest, source); Unary *instr = new Unary (op, dest, source);
iCode->push_back(instr); iCode->push_back(instr);
@ -394,7 +410,7 @@ void ICodeGenerator::move(TypedRegister destination, TypedRegister source)
TypedRegister ICodeGenerator::logicalNot(TypedRegister source) TypedRegister ICodeGenerator::logicalNot(TypedRegister source)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
Not *instr = new Not(dest, source); Not *instr = new Not(dest, source);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -402,7 +418,7 @@ TypedRegister ICodeGenerator::logicalNot(TypedRegister source)
TypedRegister ICodeGenerator::test(TypedRegister source) TypedRegister ICodeGenerator::test(TypedRegister source)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
Test *instr = new Test(dest, source); Test *instr = new Test(dest, source);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -413,7 +429,7 @@ TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source1,
{ {
ASSERT(source1.first != NotARegister); ASSERT(source1.first != NotARegister);
ASSERT(source2.first != NotARegister); ASSERT(source2.first != NotARegister);
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
Arithmetic *instr = new Arithmetic(op, dest, source1, source2); Arithmetic *instr = new Arithmetic(op, dest, source1, source2);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -421,7 +437,7 @@ TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source1,
TypedRegister ICodeGenerator::call(TypedRegister target, const StringAtom &name, RegisterList args) TypedRegister ICodeGenerator::call(TypedRegister target, const StringAtom &name, RegisterList args)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
Call *instr = new Call(dest, target, &name, args); Call *instr = new Call(dest, target, &name, args);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -429,7 +445,7 @@ TypedRegister ICodeGenerator::call(TypedRegister target, const StringAtom &name,
TypedRegister ICodeGenerator::methodCall(TypedRegister targetBase, TypedRegister targetValue, RegisterList args) TypedRegister ICodeGenerator::methodCall(TypedRegister targetBase, TypedRegister targetValue, RegisterList args)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
MethodCall *instr = new MethodCall(dest, targetBase, targetValue, args); MethodCall *instr = new MethodCall(dest, targetBase, targetValue, args);
iCode->push_back(instr); iCode->push_back(instr);
return dest; return dest;
@ -437,7 +453,7 @@ TypedRegister ICodeGenerator::methodCall(TypedRegister targetBase, TypedRegister
TypedRegister ICodeGenerator::staticCall(JSClass *c, const StringAtom &name, RegisterList args) TypedRegister ICodeGenerator::staticCall(JSClass *c, const StringAtom &name, RegisterList args)
{ {
TypedRegister dest(getRegister(), &Any_Type); TypedRegister dest(getTempRegister(), &Any_Type);
const JSSlot& slot = c->getStatic(name); const JSSlot& slot = c->getStatic(name);
StaticCall *instr = new StaticCall(dest, c, slot.mIndex, args); StaticCall *instr = new StaticCall(dest, c, slot.mIndex, args);
iCode->push_back(instr); iCode->push_back(instr);
@ -618,46 +634,161 @@ static bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex, JST
return false; return false;
} }
ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex)
{
if (!isWithinWith()) {
v = findVariable(name);
if (v.first != NotARegister)
return Var;
else {
if (mClass) { // we're compiling a method of a class
if (!isStaticMethod()) {
if (isSlotName(mClass, name, slotIndex, v.second))
return Slot;
}
if (mClass->hasStatic(name, v.second)) {
return Static;
}
}
v.second = mGlobal->getType(name);
return Name;
}
}
v.second = &Any_Type;
return Name;
}
TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::Kind use, ICodeOp xcrementOp, RegisterList *args)
{
ASSERT(p->getKind() == ExprNode::identifier);
JSType *vType = &Any_Type;
uint32 slotIndex;
TypedRegister ret;
TypedRegister v;
const StringAtom &name = (static_cast<IdentifierExprNode *>(p))->name;
LValueKind lValueKind = resolveIdentifier(name, ret, slotIndex);
TypedRegister thisBase = TypedRegister(0, mClass ? mClass : &Any_Type);
switch (use) {
case ExprNode::identifier:
switch (lValueKind) {
case Var:
break;
case Name:
ret = loadName(name);
break;
case Slot:
ret = getSlot(thisBase, slotIndex);
break;
case Static:
ret = getStatic(mClass, name);
break;
default:
NOT_REACHED("Bad lvalue kind");
}
break;
case ExprNode::preDecrement:
case ExprNode::preIncrement:
switch (lValueKind) {
case Var:
ret = op(xcrementOp, ret, loadImmediate(1.0));
break;
case Name:
ret = loadName(name);
ret = op(xcrementOp, ret, loadImmediate(1.0));
saveName(name, ret);
break;
case Slot:
ret = op(xcrementOp, getSlot(thisBase, slotIndex), loadImmediate(1.0));
setSlot(thisBase, slotIndex, ret);
break;
case Static:
ret = op(xcrementOp, getStatic(mClass, name), loadImmediate(1.0));
setStatic(mClass, name, ret);
break;
default:
NOT_REACHED("Bad lvalue kind");
}
break;
case ExprNode::postDecrement:
case ExprNode::postIncrement:
switch (lValueKind) {
case Var:
ret = varXcr(ret, xcrementOp);
break;
case Name:
ret = nameXcr(name, xcrementOp);
break;
case Slot:
ret = slotXcr(thisBase, slotIndex, xcrementOp);
break;
case Static:
ret = staticXcr(mClass, name, xcrementOp);
break;
default:
NOT_REACHED("Bad lvalue kind");
}
break;
case ExprNode::call:
switch (lValueKind) {
case Var:
ret = call(ret, name, *args);
break;
case Name:
ret = methodCall(TypedRegister(NotARegister, &Null_Type), loadString(name), *args);
break;
case Static:
ret = staticCall(mClass, name, *args);
break;
default:
NOT_REACHED("Bad lvalue kind");
}
break;
}
return ret;
}
TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args) TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args)
{ {
enum {Property, Slot, Static} lValueKind;
ASSERT(b->getKind() == ExprNode::dot); ASSERT(b->getKind() == ExprNode::dot);
LValueKind lValueKind;
if (b->op2->getKind() != ExprNode::identifier) { if (b->op2->getKind() != ExprNode::identifier) {
NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] ) NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] )
} }
else { else {
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name; const StringAtom &fieldName = static_cast<IdentifierExprNode *>(b->op2)->name;
TypedRegister base; TypedRegister base;
JSClass *c = NULL; JSClass *clazz = NULL;
JSType *fieldType = &Any_Type; JSType *fieldType = &Any_Type;
uint32 slotIndex; uint32 slotIndex;
if ((b->op1->getKind() == ExprNode::identifier) && !isWithinWith()) { if ((b->op1->getKind() == ExprNode::identifier) && !isWithinWith()) {
const StringAtom &baseName = (static_cast<IdentifierExprNode *>(b->op1))->name; const StringAtom &baseName = (static_cast<IdentifierExprNode *>(b->op1))->name;
JSType *baseType = &Any_Type; resolveIdentifier(baseName, base, slotIndex);
base = findVariable(baseName);
if (base.first != NotARegister)
baseType = base.second;
else {
// implicit 'this' has a big impact here
baseType = mGlobal->getType(baseName);
}
lValueKind = Property; lValueKind = Property;
if (baseType == &Type_Type) { //
// handle <class name>.<static field>
//
if (base.second == &Type_Type) {
const JSValue &v = mGlobal->getVariable(baseName); const JSValue &v = mGlobal->getVariable(baseName);
c = dynamic_cast<JSClass*>(v.type); clazz = dynamic_cast<JSClass*>(v.type);
if (c && c->hasStatic(name, fieldType)) { if (clazz && clazz->hasStatic(fieldName, fieldType)) {
lValueKind = Static; lValueKind = Static;
} }
} }
if (lValueKind == Property) { if (lValueKind == Property) {
if (isSlotName(baseType, name, slotIndex, fieldType)) if (isSlotName(base.second, fieldName, slotIndex, fieldType))
lValueKind = Slot; lValueKind = Slot;
else { else {
c = dynamic_cast<JSClass*>(baseType); clazz = dynamic_cast<JSClass*>(base.second);
if (c && c->hasStatic(name, fieldType)) if (clazz && clazz->hasStatic(fieldName, fieldType))
lValueKind = Static; lValueKind = Static;
else else
lValueKind = Property; lValueKind = Property;
@ -668,11 +799,11 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
} }
else { else {
base = genExpr(b->op1); base = genExpr(b->op1);
if (isSlotName(base.second, name, slotIndex, fieldType)) if (isSlotName(base.second, fieldName, slotIndex, fieldType))
lValueKind = Slot; lValueKind = Slot;
else { else {
c = dynamic_cast<JSClass*>(base.second); clazz = dynamic_cast<JSClass*>(base.second);
if (c && c->hasStatic(name, fieldType)) if (clazz && clazz->hasStatic(fieldName, fieldType))
lValueKind = Static; lValueKind = Static;
else else
lValueKind = Property; lValueKind = Property;
@ -683,10 +814,10 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
case ExprNode::call: case ExprNode::call:
switch (lValueKind) { switch (lValueKind) {
case Static: case Static:
ret = staticCall(c, name, *args); ret = staticCall(clazz, fieldName, *args);
break; break;
case Property: case Property:
ret = methodCall(base, loadString(name), *args); ret = methodCall(base, loadString(fieldName), *args);
break; break;
default: default:
NOT_REACHED("Bad lvalue kind"); NOT_REACHED("Bad lvalue kind");
@ -706,10 +837,10 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
case ExprNode::bitwiseOrEquals: case ExprNode::bitwiseOrEquals:
switch (lValueKind) { switch (lValueKind) {
case Static: case Static:
v = getStatic(c, name); v = getStatic(clazz, fieldName);
break; break;
case Property: case Property:
v = getProperty(base, name); v = getProperty(base, fieldName);
break; break;
case Slot: case Slot:
v = getSlot(base, slotIndex); v = getSlot(base, slotIndex);
@ -726,10 +857,10 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
case ExprNode::assignment: case ExprNode::assignment:
switch (lValueKind) { switch (lValueKind) {
case Static: case Static:
setStatic(c, name, ret); setStatic(clazz, fieldName, ret);
break; break;
case Property: case Property:
setProperty(base, name, ret); setProperty(base, fieldName, ret);
break; break;
case Slot: case Slot:
setSlot(base, slotIndex, ret); setSlot(base, slotIndex, ret);
@ -742,10 +873,10 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
case ExprNode::postIncrement: case ExprNode::postIncrement:
switch (lValueKind) { switch (lValueKind) {
case Static: case Static:
ret = staticXcr(c, name, xcrementOp); ret = staticXcr(clazz, fieldName, xcrementOp);
break; break;
case Property: case Property:
ret = propertyXcr(base, name, xcrementOp); ret = propertyXcr(base, fieldName, xcrementOp);
break; break;
case Slot: case Slot:
ret = slotXcr(base, slotIndex, xcrementOp); ret = slotXcr(base, slotIndex, xcrementOp);
@ -757,12 +888,12 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
case ExprNode::preIncrement: case ExprNode::preIncrement:
switch (lValueKind) { switch (lValueKind) {
case Static: case Static:
ret = op(xcrementOp, getStatic(c, name), loadImmediate(1.0)); ret = op(xcrementOp, getStatic(clazz, fieldName), loadImmediate(1.0));
setStatic(c, name, ret); setStatic(clazz, fieldName, ret);
break; break;
case Property: case Property:
ret = op(xcrementOp, getProperty(base, name), loadImmediate(1.0)); ret = op(xcrementOp, getProperty(base, fieldName), loadImmediate(1.0));
setProperty(base, name, ret); setProperty(base, fieldName, ret);
break; break;
case Slot: case Slot:
ret = op(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0)); ret = op(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0));
@ -774,7 +905,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
break; break;
case ExprNode::Delete: case ExprNode::Delete:
if (lValueKind == Property) { if (lValueKind == Property) {
ret = deleteProperty(base, name); ret = deleteProperty(base, fieldName);
} }
break; break;
default: default:
@ -857,34 +988,10 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
if (i->op->getKind() == ExprNode::dot) { if (i->op->getKind() == ExprNode::dot) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op); BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
ret = handleDot(b, ExprNode::call, xcrementOp, ret, &args); ret = handleDot(b, ExprNode::call, xcrementOp, ret, &args);
/*
TypedRegister base = genExpr(b->op1);
// might be Class.<method>()
const StringAtom &name = static_cast<IdentifierExprNode *>(b->op2)->name;
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 = staticCall(c, name, args);
break;
}
}
ret = methodCall(base, loadString(name), args);
*/
} }
else else
if (i->op->getKind() == ExprNode::identifier) { if (i->op->getKind() == ExprNode::identifier) {
if (!isWithinWith()) { ret = handleIdentifier(static_cast<IdentifierExprNode *>(i->op), ExprNode::call, xcrementOp, &args);
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(i->op))->name);
if (v.first != NotARegister)
ret = call(v, static_cast<IdentifierExprNode *>(i->op)->name, args);
else
ret = call(TypedRegister(NotARegister, &Null_Type), static_cast<IdentifierExprNode *>(i->op)->name, args);
}
else
ret = methodCall(TypedRegister(NotARegister, &Null_Type), loadString(static_cast<IdentifierExprNode *>(i->op)->name), args);
} }
else else
if (i->op->getKind() == ExprNode::index) { if (i->op->getKind() == ExprNode::index) {
@ -916,34 +1023,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
break; break;
case ExprNode::identifier : case ExprNode::identifier :
{ {
const StringAtom &name = (static_cast<IdentifierExprNode *>(p))->name; ret = handleIdentifier(static_cast<IdentifierExprNode *>(p), ExprNode::identifier, xcrementOp, NULL);
if (!isWithinWith()) {
TypedRegister v = findVariable(name);
if (v.first != NotARegister)
ret = v;
else {
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);
}
}
else
ret = loadName(name);
} }
break; break;
case ExprNode::number : case ExprNode::number :
@ -958,26 +1038,11 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
{ {
UnaryExprNode *u = static_cast<UnaryExprNode *>(p); UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
if (u->op->getKind() == ExprNode::dot) { if (u->op->getKind() == ExprNode::dot) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op); ret = handleDot(static_cast<BinaryExprNode *>(u->op), p->getKind(), xcrementOp, ret, NULL);
ret = handleDot(b, p->getKind(), xcrementOp, ret, NULL);
} }
else else
if (u->op->getKind() == ExprNode::identifier) { if (u->op->getKind() == ExprNode::identifier) {
if (!isWithinWith()) { ret = handleIdentifier(static_cast<IdentifierExprNode *>(u->op), p->getKind(), xcrementOp, NULL);
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
if (v.first != NotARegister)
ret = op(xcrementOp, ret, loadImmediate(1.0));
else {
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
ret = op(xcrementOp, ret, loadImmediate(1.0));
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
}
}
else {
ret = loadName((static_cast<IdentifierExprNode *>(u->op))->name);
ret = op(xcrementOp, ret, loadImmediate(1.0));
saveName((static_cast<IdentifierExprNode *>(u->op))->name, ret);
}
} }
else else
if (u->op->getKind() == ExprNode::index) { if (u->op->getKind() == ExprNode::index) {
@ -998,20 +1063,11 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
{ {
UnaryExprNode *u = static_cast<UnaryExprNode *>(p); UnaryExprNode *u = static_cast<UnaryExprNode *>(p);
if (u->op->getKind() == ExprNode::dot) { if (u->op->getKind() == ExprNode::dot) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(u->op); ret = handleDot(static_cast<BinaryExprNode *>(u->op), p->getKind(), xcrementOp, ret, NULL);
ret = handleDot(b, p->getKind(), xcrementOp, ret, NULL);
} }
else else
if (u->op->getKind() == ExprNode::identifier) { if (u->op->getKind() == ExprNode::identifier) {
if (!isWithinWith()) { ret = handleIdentifier(static_cast<IdentifierExprNode *>(u->op), p->getKind(), xcrementOp, NULL);
TypedRegister v = findVariable((static_cast<IdentifierExprNode *>(u->op))->name);
if (v.first != NotARegister)
ret = varXcr(v, xcrementOp);
else
ret = nameXcr((static_cast<IdentifierExprNode *>(u->op))->name, xcrementOp);
}
else
ret = nameXcr((static_cast<IdentifierExprNode *>(u->op))->name, xcrementOp);
} }
else else
if (u->op->getKind() == ExprNode::index) { if (u->op->getKind() == ExprNode::index) {
@ -1291,7 +1347,6 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name); icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name);
v = v->next; v = v->next;
} }
icg.preprocess(f->function.body);
icg.genStmt(f->function.body); icg.genStmt(f->function.body);
//stdOut << icg; //stdOut << icg;
ICodeModule *icm = icg.complete(); ICodeModule *icm = icg.complete();
@ -1325,116 +1380,6 @@ bool LabelEntry::containsLabel(const StringAtom *label)
return false; return false;
} }
void ICodeGenerator::preprocess(StmtNode *p)
{
switch (p->getKind()) {
case StmtNode::block:
{
BlockStmtNode *b = static_cast<BlockStmtNode *>(p);
StmtNode *s = b->statements;
while (s) {
preprocess(s);
s = s->next;
}
}
break;
case StmtNode::Var:
{
VariableStmtNode *vs = static_cast<VariableStmtNode *>(p);
VariableBinding *v = vs->bindings;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
if (v->type && (v->type->getKind() == ExprNode::identifier))
if (isTopLevel())
mGlobal->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name,
findType((static_cast<IdentifierExprNode *>(v->type))->name));
else
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name,
(static_cast<IdentifierExprNode *>(v->type))->name);
else
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name);
v = v->next;
}
}
break;
case StmtNode::DoWhile:
{
UnaryStmtNode *d = static_cast<UnaryStmtNode *>(p);
preprocess(d->stmt);
}
break;
case StmtNode::While:
{
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
preprocess(w->stmt);
}
break;
case StmtNode::For:
{
ForStmtNode *f = static_cast<ForStmtNode *>(p);
if (f->initializer)
preprocess(f->initializer);
preprocess(f->stmt);
}
break;
case StmtNode::If:
{
UnaryStmtNode *i = static_cast<UnaryStmtNode *>(p);
preprocess(i->stmt);
}
break;
case StmtNode::IfElse:
{
BinaryStmtNode *i = static_cast<BinaryStmtNode *>(p);
preprocess(i->stmt);
preprocess(i->stmt2);
}
break;
case StmtNode::With:
{
UnaryStmtNode *w = static_cast<UnaryStmtNode *>(p);
preprocess(w->stmt);
}
break;
case StmtNode::Switch:
{
SwitchStmtNode *sw = static_cast<SwitchStmtNode *>(p);
StmtNode *s = sw->statements;
while (s) {
if (s->getKind() != StmtNode::Case)
preprocess(s);
s = s->next;
}
}
break;
case StmtNode::label:
{
LabelStmtNode *l = static_cast<LabelStmtNode *>(p);
preprocess(l->stmt);
}
break;
case StmtNode::Try:
{
TryStmtNode *t = static_cast<TryStmtNode *>(p);
genStmt(t->stmt);
if (t->catches) {
CatchClause *c = t->catches;
while (c) {
preprocess(c->stmt);
c = c->next;
}
}
if (t->finally)
genStmt(t->finally);
}
break;
default:
break;
}
}
static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKind) static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKind)
{ {
while (identifiers) { while (identifiers) {
@ -1458,7 +1403,6 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f)
icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name); icg.allocateParameter((static_cast<IdentifierExprNode *>(v->name))->name);
v = v->next; v = v->next;
} }
icg.preprocess(f->function.body);
icg.genStmt(f->function.body); icg.genStmt(f->function.body);
return icg.complete(); return icg.complete();
@ -1469,8 +1413,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
TypedRegister ret(NotARegister, &None_Type); TypedRegister ret(NotARegister, &None_Type);
startStatement(p->pos); startStatement(p->pos);
if (exceptionRegister.first == NotARegister) { if (mExceptionRegister.first == NotARegister) {
exceptionRegister = grabRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type); mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
} }
switch (p->getKind()) { switch (p->getKind()) {
@ -1565,7 +1509,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
// freeze the class. // freeze the class.
thisClass->complete(); thisClass->complete();
if (ccg.getICode()->size()) if (ccg.getICode()->size())
thisClass->setConstructor(ccg.complete()); thisClass->setInitializer(ccg.complete());
// REVISIT: using the scope of the class to store both methods and statics. // REVISIT: using the scope of the class to store both methods and statics.
if (scg.getICode()->size()) { if (scg.getICode()->size()) {
Interpreter::Context cx(*mWorld, thisScope); Interpreter::Context cx(*mWorld, thisScope);
@ -1591,8 +1535,18 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
VariableStmtNode *vs = static_cast<VariableStmtNode *>(p); VariableStmtNode *vs = static_cast<VariableStmtNode *>(p);
VariableBinding *v = vs->bindings; VariableBinding *v = vs->bindings;
while (v) { while (v) {
if (v->name && v->initializer) { if (v->name && (v->name->getKind() == ExprNode::identifier)) {
if (v->name->getKind() == ExprNode::identifier) { if (v->type && (v->type->getKind() == ExprNode::identifier)) {
if (isTopLevel())
mGlobal->defineVariable((static_cast<IdentifierExprNode *>(v->name))->name,
findType((static_cast<IdentifierExprNode *>(v->type))->name));
else
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name,
(static_cast<IdentifierExprNode *>(v->type))->name);
}
else
allocateVariable((static_cast<IdentifierExprNode *>(v->name))->name);
if (v->initializer) {
if (!isTopLevel() && !isWithinWith()) { if (!isTopLevel() && !isWithinWith()) {
TypedRegister r = genExpr(v->name); TypedRegister r = genExpr(v->name);
TypedRegister val = genExpr(v->initializer); TypedRegister val = genExpr(v->initializer);
@ -1603,7 +1557,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
saveName((static_cast<IdentifierExprNode *>(v->name))->name, val); saveName((static_cast<IdentifierExprNode *>(v->name))->name, val);
} }
} }
// XXX what's the else case here, when does a VariableBinding NOT have an identifier child?
} }
v = v->next; v = v->next;
} }
@ -1889,19 +1842,19 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
CatchClause *c = t->catches; CatchClause *c = t->catches;
while (c) { while (c) {
// Bind the incoming exception ... // Bind the incoming exception ...
setRegisterForVariable(c->name, exceptionRegister); setRegisterForVariable(c->name, mExceptionRegister);
genStmt(c->stmt); genStmt(c->stmt);
if (finallyLabel) if (finallyLabel)
jsr(finallyLabel); jsr(finallyLabel);
throwStmt(exceptionRegister); throwStmt(mExceptionRegister);
c = c->next; c = c->next;
} }
} }
if (finallyLabel) { if (finallyLabel) {
setLabel(finallyInvoker); setLabel(finallyInvoker);
jsr(finallyLabel); jsr(finallyLabel);
throwStmt(exceptionRegister); throwStmt(mExceptionRegister);
setLabel(finallyLabel); setLabel(finallyLabel);
genStmt(t->finally); genStmt(t->finally);

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

@ -118,69 +118,70 @@ namespace ICG {
bool iCodeOwner; bool iCodeOwner;
LabelList labels; LabelList labels;
Register topRegister; // highest (currently) alloacated register Register mTopRegister; // highest (currently) alloacated register
Register registerBase; // start of registers available for expression temps uint32 mParameterCount; // number of parameters declared for the function
uint32 maxRegister; // highest (ever) allocated register // these must come before any variables declared.
uint32 parameterCount; // number of parameters declared for the function TypedRegister mExceptionRegister; // reserved to carry the exception object.
// these must come before any variables declared. VariableList *variableList; // name|register pair for each variable
TypedRegister exceptionRegister;// reserved to carry the exception object.
VariableList *variableList; // name|register pair for each variable
World *mWorld; // used to register strings World *mWorld; // used to register strings
JSScope *mGlobal; // the scope for compiling within JSScope *mGlobal; // the scope for compiling within
LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct LabelStack mLabelStack; // stack of LabelEntry objects, one per nested looping construct
// maps source position to instruction index // maps source position to instruction index
InstructionMap *mInstructionMap; InstructionMap *mInstructionMap;
JSClass *mClass; // enclosing class when generating code for methods JSClass *mClass; // enclosing class when generating code for methods
ICodeGeneratorFlags mFlags; // assorted flags ICodeGeneratorFlags mFlags; // assorted flags
std::vector<bool> mPermanentRegister;
Register getTempRegister()
{
while (mTopRegister < mPermanentRegister.size())
if (!mPermanentRegister[mTopRegister])
return mTopRegister++;
else
++mTopRegister;
mPermanentRegister.resize(mTopRegister + 1);
mPermanentRegister[mTopRegister] = false;
return mTopRegister++;
}
void resetTopRegister() { mTopRegister = mParameterCount; }
void resetStatement() { resetTopRegister(); }
TypedRegister allocateRegister(const StringAtom& name, JSType *type);
void setRegisterForVariable(const StringAtom& name, TypedRegister r) { (*variableList)[name] = r; }
JSType *findType(const StringAtom& typeName);
void markMaxRegister()
{ if (topRegister > maxRegister) maxRegister = topRegister; }
Register getRegister()
{ return topRegister++; }
void resetTopRegister()
{ markMaxRegister(); topRegister = registerBase; }
void setLabel(Label *label); void setLabel(Label *label);
void jsr(Label *label) { iCode->push_back(new Jsr(label)); } void jsr(Label *label) { iCode->push_back(new Jsr(label)); }
void rts() { iCode->push_back(new Rts()); } void rts() { iCode->push_back(new Rts()); }
void branch(Label *label); void branch(Label *label);
GenericBranch *branchTrue(Label *label, TypedRegister condition); GenericBranch *branchTrue(Label *label, TypedRegister condition);
GenericBranch *branchFalse(Label *label, TypedRegister condition); GenericBranch *branchFalse(Label *label, TypedRegister condition);
void beginTry(Label *catchLabel, Label *finallyLabel) void beginTry(Label *catchLabel, Label *finallyLabel)
{ iCode->push_back(new Tryin(catchLabel, finallyLabel)); } { iCode->push_back(new Tryin(catchLabel, finallyLabel)); }
void endTry() void endTry() { iCode->push_back(new Tryout()); }
{ iCode->push_back(new Tryout()); }
void beginWith(TypedRegister obj) void beginWith(TypedRegister obj) { iCode->push_back(new Within(obj)); }
{ iCode->push_back(new Within(obj)); } void endWith() { iCode->push_back(new Without()); }
void endWith()
{ iCode->push_back(new Without()); }
void resetStatement() { resetTopRegister(); }
void setRegisterForVariable(const StringAtom& name, TypedRegister r)
{ (*variableList)[name] = r; }
void startStatement(uint32 pos) void startStatement(uint32 pos) { (*mInstructionMap)[iCode->size()] = pos; }
{ (*mInstructionMap)[iCode->size()] = pos; }
ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind); ICodeOp mapExprNodeToICodeOp(ExprNode::Kind kind);
TypedRegister grabRegister(const StringAtom& name, JSType *type)
{
TypedRegister result(getRegister(), type);
(*variableList)[name] = result;
registerBase = topRegister;
return result;
}
bool isTopLevel() { return (mFlags & kIsTopLevel) != 0; } bool isTopLevel() { return (mFlags & kIsTopLevel) != 0; }
bool isWithinWith() { return (mFlags & kIsWithinWith) != 0; } bool isWithinWith() { return (mFlags & kIsWithinWith) != 0; }
@ -188,7 +189,11 @@ namespace ICG {
void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); } void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); }
JSType *findType(const StringAtom& typeName);
typedef enum {Var, Property, Slot, Static, Name} LValueKind;
LValueKind resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex);
TypedRegister handleIdentifier(IdentifierExprNode *p, ExprNode::Kind use, ICodeOp xcrementOp, RegisterList *args);
TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args); TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args);
ICodeModule *genFunction(FunctionStmtNode *f); ICodeModule *genFunction(FunctionStmtNode *f);
@ -207,32 +212,30 @@ namespace ICG {
ICodeModule *complete(); ICodeModule *complete();
TypedRegister genExpr(ExprNode *p, TypedRegister genExpr(ExprNode *p,
bool needBoolValueInBranch = false, bool needBoolValueInBranch = false,
Label *trueBranch = NULL, Label *trueBranch = NULL,
Label *falseBranch = NULL); Label *falseBranch = NULL);
void preprocess(StmtNode *p);
TypedRegister genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL); TypedRegister genStmt(StmtNode *p, LabelSet *currentLabelSet = NULL);
void returnStmt(TypedRegister r); void returnStmt(TypedRegister r);
void returnStmt(); void returnStmt();
void throwStmt(TypedRegister r) void throwStmt(TypedRegister r) { iCode->push_back(new Throw(r)); }
{ iCode->push_back(new Throw(r)); } void debuggerStmt() { iCode->push_back(new Debugger()); }
void debuggerStmt()
{ iCode->push_back(new Debugger()); }
TypedRegister allocateVariable(const StringAtom& name); TypedRegister allocateVariable(const StringAtom& name);
TypedRegister allocateVariable(const StringAtom& name, const StringAtom& typeName); TypedRegister allocateVariable(const StringAtom& name, const StringAtom& typeName);
TypedRegister findVariable(const StringAtom& name) TypedRegister findVariable(const StringAtom& name)
{ VariableList::iterator i = variableList->find(name); {
return (i == variableList->end()) ? TypedRegister(NotARegister, &None_Type) : (*i).second; } VariableList::iterator i = variableList->find(name);
return (i == variableList->end()) ? TypedRegister(NotARegister, &None_Type) : (*i).second;
}
TypedRegister allocateParameter(const StringAtom& name) TypedRegister allocateParameter(const StringAtom& name) { mParameterCount++; return allocateRegister(name, &Any_Type); }
{ parameterCount++; return grabRegister(name, &Any_Type); }
TypedRegister allocateParameter(const StringAtom& name, const StringAtom& typeName) TypedRegister allocateParameter(const StringAtom& name, const StringAtom& typeName)
{ parameterCount++; return grabRegister(name, findType(typeName)); } { mParameterCount++; return allocateRegister(name, findType(typeName)); }
TypedRegister allocateParameter(const StringAtom& name, JSType *type) TypedRegister allocateParameter(const StringAtom& name, JSType *type)
{ parameterCount++; return grabRegister(name, type); } { mParameterCount++; return allocateRegister(name, type); }
Formatter& print(Formatter& f); Formatter& print(Formatter& f);
@ -279,8 +282,7 @@ namespace ICG {
TypedRegister varXcr(TypedRegister var, ICodeOp op); TypedRegister varXcr(TypedRegister var, ICodeOp op);
Register getRegisterBase() { return topRegister; } InstructionStream *getICode() { return iCode; }
InstructionStream *getICode() { return iCode; }
Label *getLabel(); Label *getLabel();

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

@ -679,14 +679,14 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
InstructionIterator nextPC = ++mPC; InstructionIterator nextPC = ++mPC;
do { do {
// call the constructor(s), if any. // call the constructor(s), if any.
ICodeModule* ctor = thisClass->getConstructor(); ICodeModule* init = thisClass->getInitializer();
if (ctor) { if (init) {
mLinkage = new Linkage(mLinkage, nextPC, mLinkage = new Linkage(mLinkage, nextPC,
mActivation, mGlobal, voidRegister); mActivation, mGlobal, voidRegister);
mActivation = new Activation(ctor, args); mActivation = new Activation(init, args);
registers = &mActivation->mRegisters; registers = &mActivation->mRegisters;
nextPC = ctor->its_iCode->begin(); nextPC = init->its_iCode->begin();
endPC = ctor->its_iCode->end(); endPC = init->its_iCode->end();
} }
thisClass = thisClass->getSuperClass(); thisClass = thisClass->getSuperClass();
} while (thisClass); } while (thisClass);

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

@ -79,7 +79,7 @@ namespace JSClasses {
uint32 mStaticCount; uint32 mStaticCount;
JSSlots mStaticSlots; JSSlots mStaticSlots;
JSValue* mStaticData; JSValue* mStaticData;
ICodeModule* mConstructor; ICodeModule* mInitializer;
// typedef std::vector<ICodeModule*, gc_allocator<ICodeModule*> > JSMethods; // typedef std::vector<ICodeModule*, gc_allocator<ICodeModule*> > JSMethods;
// JSMethods mMethods; // JSMethods mMethods;
public: public:
@ -89,7 +89,7 @@ namespace JSClasses {
mSlotCount(superClass ? superClass->mSlotCount : 0), mSlotCount(superClass ? superClass->mSlotCount : 0),
mStaticCount(0), mStaticCount(0),
mStaticData(0), mStaticData(0),
mConstructor(0) mInitializer(0)
{ {
// to "inherit" superClass methods. // to "inherit" superClass methods.
if (superClass) if (superClass)
@ -106,14 +106,14 @@ namespace JSClasses {
return mScope; return mScope;
} }
void setConstructor(ICodeModule* ctor) void setInitializer(ICodeModule* init)
{ {
mConstructor = ctor; mInitializer = init;
} }
ICodeModule* getConstructor() ICodeModule* getInitializer()
{ {
return mConstructor; return mInitializer;
} }
const JSSlot& defineSlot(const String& name, JSType* type) const JSSlot& defineSlot(const String& name, JSType* type)

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

@ -175,6 +175,10 @@ SOURCE=..\hash.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\icode.h
# End Source File
# Begin Source File
SOURCE=..\icodegenerator.h SOURCE=..\icodegenerator.h
# End Source File # End Source File
# Begin Source File # Begin Source File

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

@ -147,7 +147,6 @@ static ICodeModule* genCode(Context &cx, StmtNode *p, const String &fileName)
TypedRegister ret(NotARegister, &None_Type); TypedRegister ret(NotARegister, &None_Type);
while (p) { while (p) {
icg.preprocess(p);
ret = icg.genStmt(p); ret = icg.genStmt(p);
p = p->next; p = p->next;
} }
@ -155,7 +154,7 @@ static ICodeModule* genCode(Context &cx, StmtNode *p, const String &fileName)
ICodeModule *icm = icg.complete(); ICodeModule *icm = icg.complete();
//stdOut << icg; stdOut << icg;
icm->setFileName (fileName); icm->setFileName (fileName);
return icm; return icm;
@ -344,7 +343,8 @@ class Tracer : public Context::Listener {
char * tests[] = { char * tests[] = {
"function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" , "function fact(n) { if (n > 1) return n * fact(n-1); else return 1; } print(fact(6), \" should be 720\"); return;" ,
"a = { f1: 1, f2: 2}; print(a.f2++, \" should be 2\"); print(a.f2 <<= 1, \" should be 6\"); return;" "a = { f1: 1, f2: 2}; print(a.f2++, \" should be 2\"); print(a.f2 <<= 1, \" should be 6\"); return;" ,
"class A { static var b = 3; static function s() { return b++; } } var a:A = new A; print(a.s()); print(A.b); return;"
}; };
static void testCompile() static void testCompile()
@ -361,15 +361,11 @@ static void testCompile()
StmtNode *parsedStatements = p.parseProgram(); StmtNode *parsedStatements = p.parseProgram();
ICodeGenerator icg(&world, &glob); ICodeGenerator icg(&world, &glob);
StmtNode *s = parsedStatements; StmtNode *s = parsedStatements;
while (s) {
icg.preprocess(s);
s = s->next;
}
s = parsedStatements;
while (s) { while (s) {
icg.genStmt(s); icg.genStmt(s);
s = s->next; s = s->next;
} }
// stdOut << icg;
cx.interpret(icg.complete(), JSValues()); cx.interpret(icg.complete(), JSValues());
} }
} }