зеркало из https://github.com/mozilla/pjs.git
Removed preprocess step, consolidated identifier handling.
This commit is contained in:
Родитель
6c2f34f1b0
Коммит
f677b9a1dd
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args)
|
|
||||||
|
ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex)
|
||||||
{
|
{
|
||||||
enum {Property, Slot, Static} lValueKind;
|
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)
|
||||||
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args)
|
|
||||||
|
ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex)
|
||||||
{
|
{
|
||||||
enum {Property, Slot, Static} lValueKind;
|
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)
|
||||||
|
{
|
||||||
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче