Removed all xxxCall, using simple call for everything.

Changed methods to use mMethods vector instead.
Various other fixes etc.
This commit is contained in:
rogerl%netscape.com 2000-07-18 20:53:03 +00:00
parent bb45987123
commit 06f0a5261f
14 changed files with 458 additions and 662 deletions

View File

@ -9,7 +9,7 @@
BRANCH, /* target label */
BRANCH_FALSE, /* target label, condition */
BRANCH_TRUE, /* target label, condition */
CALL, /* result, target, name, args */
CALL, /* result, base, target, args */
CAST, /* dest, rvalue, toType */
COMPARE_EQ, /* dest, source1, source2 */
COMPARE_GE, /* dest, source1, source2 */
@ -18,13 +18,13 @@
COMPARE_LE, /* dest, source1, source2 */
COMPARE_LT, /* dest, source1, source2 */
COMPARE_NE, /* dest, source1, source2 */
CONSTRUCTOR_CALL, /* target class, index, this, args */
DEBUGGER, /* drop to the debugger */
DELETE_PROP, /* dest, object, prop name */
DIVIDE, /* dest, source1, source2 */
ELEM_XCR, /* dest, base, index, value */
GENERIC_BINARY_OP, /* dest, op, source1, source2 */
GET_ELEMENT, /* dest, base, index */
GET_METHOD, /* result, target base, index */
GET_PROP, /* dest, object, prop name */
GET_SLOT, /* dest, object, slot number */
GET_STATIC, /* dest, class, index */
@ -34,7 +34,6 @@
LOAD_IMMEDIATE, /* dest, immediate value (double) */
LOAD_NAME, /* dest, name */
LOAD_STRING, /* dest, immediate value (string) */
METHOD_CALL, /* result, target base, target value, args */
MOVE, /* dest, source */
MULTIPLY, /* dest, source1, source2 */
NAME_XCR, /* dest, name, value */
@ -60,7 +59,6 @@
SHIFTLEFT, /* dest, source1, source2 */
SHIFTRIGHT, /* dest, source1, source2 */
SLOT_XCR, /* dest, source, slot number, value */
STATIC_CALL, /* result, target class, index, args */
STATIC_XCR, /* dest, class, index, value */
STRICT_EQ, /* dest, source1, source2 */
STRICT_NE, /* dest, source1, source2 */
@ -106,7 +104,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -144,18 +142,18 @@
/* print() and printOperands() inherited from GenericBranch */
};
class Call : public Instruction_4<TypedRegister, TypedRegister, const StringAtom*, RegisterList> {
class Call : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, RegisterList> {
public:
/* result, target, name, args */
Call (TypedRegister aOp1, TypedRegister aOp2, const StringAtom* aOp3, RegisterList aOp4) :
Instruction_4<TypedRegister, TypedRegister, const StringAtom*, RegisterList>
/* result, base, target, args */
Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, RegisterList aOp4) :
Instruction_4<TypedRegister, TypedRegister, TypedRegister, RegisterList>
(CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[CALL] << "\t" << mOp1 << ", " << mOp2 << ", " << "'" << *mOp3 << "'" << ", " << mOp4;
f << opcodeNames[CALL] << "\t" << mOp1 << ", " << mOp2 << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << ArgList(mOp4, registers);
f << mOp1.first << ", " << mOp2.first << ", " << mOp3.first << ", " << ArgList(mOp4, registers);
return f;
}
};
@ -171,7 +169,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -239,22 +237,6 @@
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
};
class ConstructorCall : public Instruction_4<JSClass*, uint32, TypedRegister, RegisterList> {
public:
/* target class, index, this, args */
ConstructorCall (JSClass* aOp1, uint32 aOp2, TypedRegister aOp3, RegisterList aOp4) :
Instruction_4<JSClass*, uint32, TypedRegister, RegisterList>
(CONSTRUCTOR_CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[CONSTRUCTOR_CALL] << "\t" << mOp1->getName() << ", " << mOp2 << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp3.first << '=' << registers[mOp3.first] << ", " << ArgList(mOp4, registers);
return f;
}
};
class Debugger : public Instruction {
public:
/* drop to the debugger */
@ -281,7 +263,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -306,7 +288,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp1.first << ", " << mOp2.first << ", " << mOp3.first;
return f;
}
};
@ -322,7 +304,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first] << ", " << "R" << mOp4.first << '=' << registers[mOp4.first];
f << mOp1.first << ", " << mOp3.first << ", " << mOp4.first;
return f;
}
};
@ -338,7 +320,23 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp1.first << ", " << mOp2.first << ", " << mOp3.first;
return f;
}
};
class GetMethod : public Instruction_3<TypedRegister, TypedRegister, uint32> {
public:
/* result, target base, index */
GetMethod (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3) :
Instruction_3<TypedRegister, TypedRegister, uint32>
(GET_METHOD, aOp1, aOp2, aOp3) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[GET_METHOD] << "\t" << mOp1 << ", " << mOp2 << ", " << mOp3;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -354,7 +352,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -370,7 +368,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -386,7 +384,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -426,7 +424,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -442,7 +440,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -458,7 +456,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -474,23 +472,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
return f;
}
};
class MethodCall : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, RegisterList> {
public:
/* result, target base, target value, args */
MethodCall (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, RegisterList aOp4) :
Instruction_4<TypedRegister, TypedRegister, TypedRegister, RegisterList>
(METHOD_CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[METHOD_CALL] << "\t" << mOp1 << ", " << mOp2 << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first] << ", " << ArgList(mOp4, registers);
f << mOp1.first;
return f;
}
};
@ -506,7 +488,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -531,7 +513,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -547,7 +529,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -563,7 +545,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -579,7 +561,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -595,7 +577,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -611,7 +593,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -642,7 +624,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -667,7 +649,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -683,7 +665,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -708,7 +690,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -754,7 +736,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp2.first;
return f;
}
};
@ -770,7 +752,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp1.first << ", " << mOp2.first << ", " << mOp3.first;
return f;
}
};
@ -786,7 +768,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp1.first << ", " << mOp3.first;
return f;
}
};
@ -802,7 +784,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp1.first << ", " << mOp3.first;
return f;
}
};
@ -818,7 +800,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp3.first;
return f;
}
};
@ -852,23 +834,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
return f;
}
};
class StaticCall : public Instruction_4<TypedRegister, JSClass*, uint32, RegisterList> {
public:
/* result, target class, index, args */
StaticCall (TypedRegister aOp1, JSClass* aOp2, uint32 aOp3, RegisterList aOp4) :
Instruction_4<TypedRegister, JSClass*, uint32, RegisterList>
(STATIC_CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[STATIC_CALL] << "\t" << mOp1 << ", " << mOp2->getName() << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << ArgList(mOp4, registers);
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -884,7 +850,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -927,7 +893,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -943,7 +909,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -959,7 +925,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -1014,7 +980,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -1030,7 +996,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -1077,13 +1043,13 @@
"COMPARE_LE ",
"COMPARE_LT ",
"COMPARE_NE ",
"CONSTRUCTOR_CALL ",
"DEBUGGER ",
"DELETE_PROP ",
"DIVIDE ",
"ELEM_XCR ",
"GENERIC_BINARY_OP",
"GET_ELEMENT ",
"GET_METHOD ",
"GET_PROP ",
"GET_SLOT ",
"GET_STATIC ",
@ -1093,7 +1059,6 @@
"LOAD_IMMEDIATE ",
"LOAD_NAME ",
"LOAD_STRING ",
"METHOD_CALL ",
"MOVE ",
"MULTIPLY ",
"NAME_XCR ",
@ -1119,7 +1084,6 @@
"SHIFTLEFT ",
"SHIFTRIGHT ",
"SLOT_XCR ",
"STATIC_CALL ",
"STATIC_XCR ",
"STRICT_EQ ",
"STRICT_NE ",

View File

@ -115,7 +115,7 @@ TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *t
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName)
{
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
return allocateRegister(name, findType(typeName));
}
@ -123,7 +123,7 @@ TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const Str
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name)
{
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
return allocateRegister(name, &Any_Type);
}
@ -315,7 +315,7 @@ TypedRegister ICodeGenerator::propertyXcr(TypedRegister base, const StringAtom &
TypedRegister ICodeGenerator::getStatic(JSClass *base, const StringAtom &name)
TypedRegister ICodeGenerator::getStatic(JSClass *base, const String &name)
{
TypedRegister dest(getTempRegister(), &Any_Type);
const JSSlot& slot = base->getStatic(name);
@ -403,7 +403,7 @@ TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source)
iCode->push_back(instr);
return dest;
}
void ICodeGenerator::move(TypedRegister destination, TypedRegister source)
{
@ -458,45 +458,22 @@ TypedRegister ICodeGenerator::binaryOp(ICodeOp op, TypedRegister source1,
return dest;
}
TypedRegister ICodeGenerator::call(TypedRegister target, const StringAtom &name, RegisterList *args)
TypedRegister ICodeGenerator::call(TypedRegister target, TypedRegister thisArg, RegisterList *args)
{
TypedRegister dest(getTempRegister(), &Any_Type);
Call *instr = new Call(dest, target, &name, *args);
Call *instr = new Call(dest, target, thisArg, *args);
iCode->push_back(instr);
return dest;
}
TypedRegister ICodeGenerator::methodCall(TypedRegister targetBase, TypedRegister targetValue, RegisterList *args)
TypedRegister ICodeGenerator::getMethod(TypedRegister thisArg, uint32 slotIndex)
{
TypedRegister dest(getTempRegister(), &Any_Type);
MethodCall *instr = new MethodCall(dest, targetBase, targetValue, *args);
GetMethod *instr = new GetMethod(dest, thisArg, slotIndex);
iCode->push_back(instr);
return dest;
}
TypedRegister ICodeGenerator::staticCall(JSClass *c, const StringAtom &name, RegisterList *args)
{
TypedRegister dest(getTempRegister(), &Any_Type);
const JSSlot& slot = c->getStatic(name);
StaticCall *instr = new StaticCall(dest, c, slot.mIndex, *args);
iCode->push_back(instr);
return dest;
}
void ICodeGenerator::constructorCall(JSClass *c, const StringAtom &name, TypedRegister thisArg, RegisterList *args)
{
const JSSlot& slot = c->getStatic(name);
ConstructorCall *instr = new ConstructorCall(c, slot.mIndex, thisArg, *args);
iCode->push_back(instr);
}
void ICodeGenerator::constructorCall(JSClass *c, const String &name, TypedRegister thisArg, RegisterList *args)
{
const JSSlot& slot = c->getStatic(name);
ConstructorCall *instr = new ConstructorCall(c, slot.mIndex, thisArg, *args);
iCode->push_back(instr);
}
TypedRegister ICodeGenerator::super()
{
TypedRegister dest(getTempRegister(), &Any_Type);
@ -668,7 +645,6 @@ static bool generatedBoolean(ExprNode *p)
return true;
default:
break;
}
return false;
}
@ -688,6 +664,17 @@ static bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex, JST
return false;
}
static bool isMethodName(JSType *t, const StringAtom &name, uint32 &slotIndex)
{
JSClass* c = dynamic_cast<JSClass*>(t);
while (c) {
if (c->hasMethod(name, slotIndex))
return true;
c = c->getSuperClass();
}
return false;
}
ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex)
{
@ -700,6 +687,8 @@ ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &n
if (!isStaticMethod()) {
if (isSlotName(mClass, name, slotIndex, v.second))
return Slot;
if (isMethodName(mClass, name, slotIndex))
return Method;
}
bool isConstructor = false;
if (mClass->hasStatic(name, v.second, isConstructor)) {
@ -842,17 +831,20 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
case ExprNode::call:
switch (lValueKind) {
case Var:
ret = call(v, name, args);
ret = call(v, TypedRegister(NotARegister, &Null_Type), args);
break;
case Name:
ret = methodCall(TypedRegister(NotARegister, &Null_Type), loadString(name), args);
ret = call(loadName(name), TypedRegister(NotARegister, &Null_Type), args);
break;
case Method:
ret = call(getMethod(thisBase, slotIndex), thisBase, args);
break;
case Static:
ret = staticCall(mClass, name, args);
ret = call(getStatic(mClass, name), TypedRegister(NotARegister, &Null_Type), args);
break;
case Constructor:
ret = newClass(mClass);
constructorCall(mClass, name, ret, args);
call(getStatic(mClass, name), ret, args);
break;
default:
NOT_REACHED("Bad lvalue kind");
@ -900,12 +892,15 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
if (lValueKind == Property) {
if (isSlotName(base.second, fieldName, slotIndex, fieldType))
lValueKind = Slot;
else {
bool isConstructor;
clazz = dynamic_cast<JSClass*>(base.second);
if (clazz && clazz->hasStatic(fieldName, fieldType, isConstructor))
lValueKind = (isConstructor) ? Constructor : Static;
}
else
if (isMethodName(base.second, fieldName, slotIndex))
lValueKind = Method;
else {
bool isConstructor;
clazz = dynamic_cast<JSClass*>(base.second);
if (clazz && clazz->hasStatic(fieldName, fieldType, isConstructor))
lValueKind = (isConstructor) ? Constructor : Static;
}
}
if ((lValueKind == Property) || (base.first == NotARegister))
base = loadName(baseName, base.second);
@ -914,26 +909,32 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
base = genExpr(b->op1);
if (isSlotName(base.second, fieldName, slotIndex, fieldType))
lValueKind = Slot;
else {
bool isConstructor;
clazz = dynamic_cast<JSClass*>(base.second);
if (clazz && clazz->hasStatic(fieldName, fieldType, isConstructor))
lValueKind = (isConstructor) ? Constructor : Static;
}
else
if (isMethodName(base.second, fieldName, slotIndex))
lValueKind = Method;
else {
bool isConstructor;
clazz = dynamic_cast<JSClass*>(base.second);
if (clazz && clazz->hasStatic(fieldName, fieldType, isConstructor))
lValueKind = (isConstructor) ? Constructor : Static;
}
}
TypedRegister v;
switch (use) {
case ExprNode::call:
switch (lValueKind) {
case Static:
ret = staticCall(clazz, fieldName, args);
ret = call(getStatic(clazz, fieldName), TypedRegister(NotARegister, &Null_Type), args);
break;
case Constructor:
ret = newClass(clazz);
constructorCall(clazz, fieldName, ret, args);
call(getStatic(clazz, fieldName), ret, args);
break;
case Property:
ret = methodCall(base, loadString(fieldName), args);
ret = call(getProperty(base, fieldName), base, args);
break;
case Method:
ret = call(getMethod(base, slotIndex), base, args);
break;
default:
NOT_REACHED("Bad lvalue kind");
@ -988,20 +989,26 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
}
break;
case ExprNode::postDecrement:
case ExprNode::postIncrement:
switch (lValueKind) {
case Constructor:
case Static:
ret = staticXcr(clazz, fieldName, xcrementOp);
break;
case Property:
ret = propertyXcr(base, fieldName, xcrementOp);
break;
case Slot:
ret = slotXcr(base, slotIndex, xcrementOp);
break;
default:
NOT_REACHED("Bad lvalue kind");
case ExprNode::postIncrement:
{
// JSClass *clss = dynamic_cast<JSClass*>(fieldType);
// if (clss) {
// clss->findOverloadedOperator(use);
// }
switch (lValueKind) {
case Constructor:
case Static:
ret = staticXcr(clazz, fieldName, xcrementOp);
break;
case Property:
ret = propertyXcr(base, fieldName, xcrementOp);
break;
case Slot:
ret = slotXcr(base, slotIndex, xcrementOp);
break;
default:
NOT_REACHED("Bad lvalue kind");
}
}
break;
case ExprNode::preDecrement:
@ -1094,7 +1101,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
JSClass* clazz = dynamic_cast<JSClass*>(value.type);
if (clazz) {
ret = newClass(clazz);
constructorCall(clazz, className, ret, &args);
call(getStatic(clazz, className), ret, &args);
}
else
NOT_REACHED("New <name>, where <name> is not a known class"); // XXX Runtime error.
@ -1133,7 +1140,8 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
else
if (i->op->getKind() == ExprNode::index) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
ret = methodCall(genExpr(b->op1), genExpr(b->op2), &args);
TypedRegister base = genExpr(b->op1);
ret = call(getElement(base, genExpr(b->op2)), base, &args);
}
else
ASSERT("WAH!");
@ -1457,7 +1465,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
{
FunctionExprNode *f = static_cast<FunctionExprNode *>(p);
ICodeGenerator icg(mWorld, mGlobal);
icg.allocateParameter(mWorld->identifiers[widenCString("this")]); // always parameter #0
icg.allocateParameter(mWorld->identifiers["this"]); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
@ -1530,7 +1538,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator icg(mWorld, mGlobal, mClass, flags);
icg.allocateParameter(mWorld->identifiers[widenCString("this")], (mClass) ? mClass : &Any_Type); // always parameter #0
icg.allocateParameter(mWorld->identifiers["this"], (mClass) ? mClass : &Any_Type); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
@ -1560,11 +1568,11 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
}
}
if (!foundSuperCall) { // invoke the default superclass constructor
icg.constructorCall(superclass, superclass->getName(), thisValue, &args);
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
}
}
const StringAtom &initName = mWorld->identifiers[widenCString("__init__")]; // XXXXXXX
icg.constructorCall(mClass, initName, thisValue, &args); // ok, so it's mis-named
const StringAtom &initName = mWorld->identifiers["__init__"]; // XXXXXXX
icg.call(icg.getStatic(mClass, initName), thisValue, &args); // ok, so it's mis-named
}
icg.genStmt(f->function.body);
return icg.complete();
@ -1577,7 +1585,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
startStatement(p->pos);
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
switch (p->getKind()) {
@ -1605,14 +1613,14 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
// do a pre-processing loop to discover whether it is in fact empty
// and then pass that info through to the genFunction() call for each
// constructor.
const StringAtom &initName = mWorld->identifiers[widenCString("__init__")];
const StringAtom &initName = mWorld->identifiers["__init__"];
thisClass->defineStatic(initName, &Function_Type);
bool hasDefaultConstructor = false;
if (classStmt->body) {
JSScope* thisScope = thisClass->getScope();
ICodeGenerator ccg(mWorld, thisScope, thisClass, kNoFlags); // constructor code generator.
ccg.allocateParameter(mWorld->identifiers[widenCString("this")], thisClass); // always parameter #0
ccg.allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod); // static initializer code generator.
StmtNode* s = classStmt->body->statements;
while (s) {
@ -1678,7 +1686,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
scg.setStatic(thisClass, name, scg.newFunction(icm));
}
else
thisScope->defineFunction(name, icm);
thisClass->defineMethod(name, new JSFunction(icm));
}
}
break;
@ -1698,8 +1706,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
RegisterList args;
ICodeGenerator icg(mWorld, thisScope, thisClass, kIsStaticMethod);
if (superclass)
icg.constructorCall(superclass, superclass->getName(), thisValue, &args);
icg.constructorCall(thisClass, initName, thisValue, &args);
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
icg.call(icg.getStatic(thisClass, initName), thisValue, &args);
thisClass->defineConstructor(nameExpr->name);
scg.setStatic(thisClass, nameExpr->name, scg.newFunction(icg.complete()));
}

View File

@ -190,7 +190,7 @@ namespace ICG {
void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); }
typedef enum {Var, Property, Slot, Static, Constructor, Name} LValueKind;
typedef enum {Var, Property, Slot, Static, Constructor, Name, Method} LValueKind;
LValueKind resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex);
TypedRegister handleIdentifier(IdentifierExprNode *p, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args);
@ -242,11 +242,8 @@ namespace ICG {
TypedRegister op(ICodeOp op, TypedRegister source);
TypedRegister op(ICodeOp op, TypedRegister source1, TypedRegister source2);
TypedRegister binaryOp(ICodeOp op, TypedRegister source1, TypedRegister source2);
TypedRegister call(TypedRegister target, const StringAtom &name, RegisterList *args);
TypedRegister methodCall(TypedRegister targetBase, TypedRegister targetValue, RegisterList *args);
TypedRegister staticCall(JSClass *c, const StringAtom &name, RegisterList *args);
void constructorCall(JSClass *c, const StringAtom &name, TypedRegister thisArg, RegisterList *args);
void constructorCall(JSClass *c, const String &name, TypedRegister thisArg, RegisterList *args);
TypedRegister call(TypedRegister base, TypedRegister target, RegisterList *args);
TypedRegister getMethod(TypedRegister thisArg, uint32 slotIndex);
void move(TypedRegister destination, TypedRegister source);
TypedRegister logicalNot(TypedRegister source);
@ -274,7 +271,7 @@ namespace ICG {
void setProperty(TypedRegister base, const StringAtom &name, TypedRegister value);
TypedRegister propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op);
TypedRegister getStatic(JSClass *base, const StringAtom &name);
TypedRegister getStatic(JSClass *base, const String &name);
void setStatic(JSClass *base, const StringAtom &name, TypedRegister value);
TypedRegister staticXcr(JSClass *base, const StringAtom &name, ICodeOp op);

View File

@ -583,138 +583,32 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
(*registers)[dst(su).first] = s;
}
break;
case METHOD_CALL:
{
MethodCall* call = static_cast<MethodCall*>(instruction);
ASSERT((*registers)[op3(call).first].isString());
JSValue base;
JSValue prop;
if (op2(call).first == NotARegister) {
base = mGlobal;
prop = mGlobal->getProperty(*((*registers)[op3(call).first].string));
}
else {
base = (*registers)[op2(call).first];
ASSERT(base.isObject()); // XXX runtime error
prop = base.object->getProperty(*((*registers)[op3(call).first].string));
}
ASSERT(prop.isFunction()); // XXX runtime error
JSFunction *target = prop.function;
case GET_METHOD:
{
GetMethod* gm = static_cast<GetMethod*>(instruction);
JSValue base = (*registers)[src1(gm).first];
ASSERT(base.isObject()); // XXX runtime error
JSClass *theClass = dynamic_cast<JSClass*>(base.object->getType());
ASSERT(theClass);
(*registers)[dst(gm).first] = theClass->getMethod(src2(gm));
}
break;
case CALL:
{
Call* call = static_cast<Call*>(instruction);
ASSERT((*registers)[op2(call).first].isFunction()); // XXX runtime error
JSFunction *target = (*registers)[op2(call).first].function;
if (target->isNative()) {
RegisterList &params = op4(call);
JSValues argv(params.size() + 1);
argv[0] = base;
JSValues::size_type i = 1;
for (RegisterList::const_iterator src = params.begin(), end = params.end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first];
}
JSValue result = static_cast<JSNativeFunction*>(target)->mCode(this, argv);
if (op1(call).first != NotARegister)
(*registers)[op1(call).first] = result;
break;
}
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, op1(call));
mActivation = new Activation(target->getICode(), mActivation, base, op4(call));
JSClass *thisClass = dynamic_cast<JSClass*>(base.object->getType());
if (thisClass)
mGlobal = thisClass->getScope();
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
continue;
}
}
case STATIC_CALL:
{
StaticCall* call = static_cast<StaticCall*>(instruction);
JSClass* thisClass = op2(call);
const JSValue& value = (*thisClass)[op3(call)];
// FIXME: throw runtime error if not a function value.
ASSERT(value.isFunction());
JSFunction *target = value.function;
if (target->isNative()) {
RegisterList &params = op4(call);
JSValues argv(params.size() + 1, kNullValue);
JSValues::size_type i = 1;
for (RegisterList::const_iterator src = params.begin(), end = params.end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first];
}
JSValue result = static_cast<JSNativeFunction*>(target)->mCode(this, argv);
if (op1(call).first != NotARegister)
(*registers)[op1(call).first] = result;
break;
}
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, op1(call));
mActivation = new Activation(target->getICode(), mActivation, kNullValue, op4(call));
mGlobal = op2(call)->getScope();
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
continue;
}
}
case CONSTRUCTOR_CALL:
{
ConstructorCall* call = static_cast<ConstructorCall*>(instruction);
JSClass* thisClass = op1(call);
const JSValue& value = (*thisClass)[op2(call)];
// FIXME: throw runtime error if not a function value.
ASSERT(value.isFunction());
JSFunction *target = value.function;
if (target->isNative()) {
RegisterList &params = op4(call);
JSValues argv(params.size() + 1, kNullValue);
argv[0] = (*registers)[op3(call).first];
JSValues::size_type i = 1;
for (RegisterList::const_iterator src = params.begin(), end = params.end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first];
}
/*JSValue result = static_cast<JSNativeFunction*>(target)->mCode(this, argv);*/
break;
}
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, TypedRegister(NotARegister, &Any_Type));
mActivation = new Activation(target->getICode(), mActivation, (*registers)[op3(call).first], op4(call));
mGlobal = op1(call)->getScope();
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
continue;
}
}
case CALL:
{
Call* call = static_cast<Call*>(instruction);
JSFunction *target;
if (op2(call).first == NotARegister) {
ASSERT(mGlobal->getVariable(*op3(call)).isFunction());
target = mGlobal->getVariable(*op3(call)).function;
}
else {
ASSERT((*registers)[op2(call).first].isFunction()); // XXX runtime error
target = (*registers)[op2(call).first].function;
}
if (target->isNative()) {
RegisterList &params = op4(call);
JSValues argv(params.size() + 1);
argv[0] = kNullValue;
JSValues::size_type i = 1;
for (RegisterList::const_iterator src = params.begin(), end = params.end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first];
}
JSValue result = static_cast<JSNativeFunction*>(target)->mCode(this, argv);
if (op1(call).first != NotARegister)
(*registers)[op1(call).first] = result;
@ -723,7 +617,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, op1(call));
mActivation = new Activation(target->getICode(), mActivation, kNullValue, op4(call));
mActivation = new Activation(target->getICode(), mActivation, (*registers)[op3(call).first], op4(call));
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
@ -833,6 +727,10 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSValue& value = (*registers)[src1(gp).first];
if (value.isObject()) {
if (value.isType()) {
// I don't think this is necessary anymore - any get property
// on a class name should have been turned into a GET_STATIC
// by the codegen.
ASSERT(false);
// REVISIT: should signal error if slot doesn't exist.
JSClass* thisClass = dynamic_cast<JSClass*>(value.type);
if (thisClass && thisClass->hasStatic(*src2(gp))) {
@ -852,6 +750,10 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSValue& value = (*registers)[dst(sp).first];
if (value.isObject()) {
if (value.isType()) {
// I don't think this is necessary anymore - any set property
// on a class name should have been turned into a SET_STATIC
// by the codegen.
ASSERT(false);
// REVISIT: should signal error if slot doesn't exist.
JSClass* thisClass = dynamic_cast<JSClass*>(value.object);
if (thisClass && thisClass->hasStatic(*src1(sp))) {

View File

@ -192,7 +192,6 @@ static void readEvalPrint(FILE *in, World &world)
global.defineNativeFunction(world.identifiers["dump"], dump);
global.defineNativeFunction(world.identifiers["load"], load);
// global.defineNativeFunction(world.identifiers["time"], time);
// global.defineVariable(
String buffer;
string line;
@ -294,7 +293,8 @@ class Tracer : public Context::Listener {
char * tests[] = {
"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;" ,
"class A { static var b = 3; static function s() { return b++; } } var a:A = new A; print(a.s(), \" should be 3\"); print(A.b, \" should be 4\"); return;"
"class A { static var b = 3; static function s() { return b++; }function x() { return \"Ax\"; } function y() { return \"Ay\"; } } var a:A = new A; print(a.s(), \" should be 3\"); print(A.b, \" should be 4\"); return;",
"class B extends A { function x() { return \"Bx\"; } } var b:B = new B; print(b.x(), \" should be Bx\"); print(b.y(), \" should be Ay\"); return;"
};
static void testCompile()

View File

@ -43,6 +43,7 @@ namespace JSClasses {
using JSTypes::JSObject;
using JSTypes::JSType;
using JSTypes::JSScope;
using JSTypes::JSFunction;
using ICG::ICodeModule;
@ -69,7 +70,11 @@ namespace JSClasses {
typedef gc_allocator<JSSlot> gc_slot_allocator;
#endif
typedef std::map<String, JSSlot, std::less<const String>, gc_slot_allocator> JSSlots;
typedef std::map<String, JSSlot, std::less<const String>, gc_slot_allocator> JSSlots;
typedef std::pair<String, JSFunction*> MethodEntry;
typedef std::vector<MethodEntry> JSMethods;
/**
* Represents a class in the JavaScript 2 (ECMA 4) language.
@ -85,8 +90,7 @@ namespace JSClasses {
uint32 mStaticCount;
JSSlots mStaticSlots;
JSValue* mStaticData;
// typedef std::vector<ICodeModule*, gc_allocator<ICodeModule*> > JSMethods;
// JSMethods mMethods;
JSMethods mMethods;
public:
JSClass(JSScope* scope, const String& name, JSClass* superClass = 0)
: JSType(name, superClass),
@ -95,9 +99,12 @@ namespace JSClasses {
mStaticCount(0),
mStaticData(0)
{
// to "inherit" superClass methods.
if (superClass)
mScope->setPrototype(superClass->mScope);
if (superClass) {
// inherit superclass methods
JSMethods::iterator end = superClass->mMethods.end();
for (JSMethods::iterator i = superClass->mMethods.begin(); i != end; i++)
mMethods.push_back(*i);
}
}
JSClass* getSuperClass()
@ -209,6 +216,32 @@ namespace JSClasses {
f << i->first << " : " << mStaticData[i->second.mIndex] << "\n";
}
}
void defineMethod(const String& name, JSFunction *f)
{
uint32 slot;
if (hasMethod(name, slot))
mMethods[slot] = MethodEntry(name, f);
else
mMethods.push_back(MethodEntry(name, f));
}
bool hasMethod(const String& name, uint32& index)
{
JSMethods::iterator end = mMethods.end();
for (JSMethods::iterator i = mMethods.begin(); i != end; i++) {
if (i->first == name) {
index = i - mMethods.begin();
return true;
}
}
return false;
}
JSFunction* getMethod(uint32 index)
{
return mMethods[index].second;
}
};
/**
@ -242,6 +275,11 @@ namespace JSClasses {
setPrototype(thisClass->getScope());
}
JSFunction* getMethod(uint32 index)
{
return getClass()->getMethod(index);
}
JSClass* getClass()
{
return static_cast<JSClass*>(mType);

View File

@ -288,26 +288,14 @@ $ops{"RETURN_VOID"} =
$ops{"CALL"} =
{
super => "Instruction_4",
rem => "result, target, name, args",
params => [ ("TypedRegister", "TypedRegister", "const StringAtom*", "RegisterList") ]
};
$ops{"STATIC_CALL"} =
{
super => "Instruction_4",
rem => "result, target class, index, args",
params => [ ("TypedRegister", "JSClass*", "uint32", "RegisterList") ]
};
$ops{"METHOD_CALL"} =
{
super => "Instruction_4",
rem => "result, target base, target value, args",
rem => "result, base, target, args",
params => [ ("TypedRegister", "TypedRegister", "TypedRegister", "RegisterList") ]
};
$ops{"CONSTRUCTOR_CALL"} =
$ops{"GET_METHOD"} =
{
super => "Instruction_4",
rem => "target class, index, this, args",
params => [ ("JSClass*", "uint32", "TypedRegister", "RegisterList") ]
super => "Instruction_3",
rem => "result, target base, index",
params => [ ("TypedRegister", "TypedRegister", "uint32") ]
};
$ops{"THROW"} =
{
@ -589,7 +577,8 @@ sub get_printops_body {
for $type (@types) {
if ($type eq "TypedRegister") {
push (@oplist, "\"R\" << mOp$op.first << '=' << registers[mOp$op.first]");
push (@oplist, "mOp$op.first");
# push (@oplist, "\"R\" << mOp$op.first << '=' << registers[mOp$op.first]");
} elsif ($type eq "RegisterList") {
push (@oplist, "ArgList(mOp$op, registers)");
}

View File

@ -9,7 +9,7 @@
BRANCH, /* target label */
BRANCH_FALSE, /* target label, condition */
BRANCH_TRUE, /* target label, condition */
CALL, /* result, target, name, args */
CALL, /* result, base, target, args */
CAST, /* dest, rvalue, toType */
COMPARE_EQ, /* dest, source1, source2 */
COMPARE_GE, /* dest, source1, source2 */
@ -18,13 +18,13 @@
COMPARE_LE, /* dest, source1, source2 */
COMPARE_LT, /* dest, source1, source2 */
COMPARE_NE, /* dest, source1, source2 */
CONSTRUCTOR_CALL, /* target class, index, this, args */
DEBUGGER, /* drop to the debugger */
DELETE_PROP, /* dest, object, prop name */
DIVIDE, /* dest, source1, source2 */
ELEM_XCR, /* dest, base, index, value */
GENERIC_BINARY_OP, /* dest, op, source1, source2 */
GET_ELEMENT, /* dest, base, index */
GET_METHOD, /* result, target base, index */
GET_PROP, /* dest, object, prop name */
GET_SLOT, /* dest, object, slot number */
GET_STATIC, /* dest, class, index */
@ -34,7 +34,6 @@
LOAD_IMMEDIATE, /* dest, immediate value (double) */
LOAD_NAME, /* dest, name */
LOAD_STRING, /* dest, immediate value (string) */
METHOD_CALL, /* result, target base, target value, args */
MOVE, /* dest, source */
MULTIPLY, /* dest, source1, source2 */
NAME_XCR, /* dest, name, value */
@ -60,7 +59,6 @@
SHIFTLEFT, /* dest, source1, source2 */
SHIFTRIGHT, /* dest, source1, source2 */
SLOT_XCR, /* dest, source, slot number, value */
STATIC_CALL, /* result, target class, index, args */
STATIC_XCR, /* dest, class, index, value */
STRICT_EQ, /* dest, source1, source2 */
STRICT_NE, /* dest, source1, source2 */
@ -106,7 +104,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -144,18 +142,18 @@
/* print() and printOperands() inherited from GenericBranch */
};
class Call : public Instruction_4<TypedRegister, TypedRegister, const StringAtom*, RegisterList> {
class Call : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, RegisterList> {
public:
/* result, target, name, args */
Call (TypedRegister aOp1, TypedRegister aOp2, const StringAtom* aOp3, RegisterList aOp4) :
Instruction_4<TypedRegister, TypedRegister, const StringAtom*, RegisterList>
/* result, base, target, args */
Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, RegisterList aOp4) :
Instruction_4<TypedRegister, TypedRegister, TypedRegister, RegisterList>
(CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[CALL] << "\t" << mOp1 << ", " << mOp2 << ", " << "'" << *mOp3 << "'" << ", " << mOp4;
f << opcodeNames[CALL] << "\t" << mOp1 << ", " << mOp2 << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << ArgList(mOp4, registers);
f << mOp1.first << ", " << mOp2.first << ", " << mOp3.first << ", " << ArgList(mOp4, registers);
return f;
}
};
@ -171,7 +169,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -239,22 +237,6 @@
/* print() and printOperands() inherited from Instruction_3<TypedRegister, TypedRegister, TypedRegister> */
};
class ConstructorCall : public Instruction_4<JSClass*, uint32, TypedRegister, RegisterList> {
public:
/* target class, index, this, args */
ConstructorCall (JSClass* aOp1, uint32 aOp2, TypedRegister aOp3, RegisterList aOp4) :
Instruction_4<JSClass*, uint32, TypedRegister, RegisterList>
(CONSTRUCTOR_CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[CONSTRUCTOR_CALL] << "\t" << mOp1->getName() << ", " << mOp2 << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp3.first << '=' << registers[mOp3.first] << ", " << ArgList(mOp4, registers);
return f;
}
};
class Debugger : public Instruction {
public:
/* drop to the debugger */
@ -281,7 +263,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -306,7 +288,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp1.first << ", " << mOp2.first << ", " << mOp3.first;
return f;
}
};
@ -322,7 +304,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first] << ", " << "R" << mOp4.first << '=' << registers[mOp4.first];
f << mOp1.first << ", " << mOp3.first << ", " << mOp4.first;
return f;
}
};
@ -338,7 +320,23 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp1.first << ", " << mOp2.first << ", " << mOp3.first;
return f;
}
};
class GetMethod : public Instruction_3<TypedRegister, TypedRegister, uint32> {
public:
/* result, target base, index */
GetMethod (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3) :
Instruction_3<TypedRegister, TypedRegister, uint32>
(GET_METHOD, aOp1, aOp2, aOp3) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[GET_METHOD] << "\t" << mOp1 << ", " << mOp2 << ", " << mOp3;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -354,7 +352,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -370,7 +368,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -386,7 +384,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -426,7 +424,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -442,7 +440,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -458,7 +456,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -474,23 +472,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
return f;
}
};
class MethodCall : public Instruction_4<TypedRegister, TypedRegister, TypedRegister, RegisterList> {
public:
/* result, target base, target value, args */
MethodCall (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, RegisterList aOp4) :
Instruction_4<TypedRegister, TypedRegister, TypedRegister, RegisterList>
(METHOD_CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[METHOD_CALL] << "\t" << mOp1 << ", " << mOp2 << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first] << ", " << ArgList(mOp4, registers);
f << mOp1.first;
return f;
}
};
@ -506,7 +488,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -531,7 +513,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -547,7 +529,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -563,7 +545,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -579,7 +561,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -595,7 +577,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -611,7 +593,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -642,7 +624,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -667,7 +649,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -683,7 +665,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -708,7 +690,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -754,7 +736,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp2.first;
return f;
}
};
@ -770,7 +752,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp1.first << ", " << mOp2.first << ", " << mOp3.first;
return f;
}
};
@ -786,7 +768,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp1.first << ", " << mOp3.first;
return f;
}
};
@ -802,7 +784,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp1.first << ", " << mOp3.first;
return f;
}
};
@ -818,7 +800,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp3.first << '=' << registers[mOp3.first];
f << mOp3.first;
return f;
}
};
@ -852,23 +834,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
return f;
}
};
class StaticCall : public Instruction_4<TypedRegister, JSClass*, uint32, RegisterList> {
public:
/* result, target class, index, args */
StaticCall (TypedRegister aOp1, JSClass* aOp2, uint32 aOp3, RegisterList aOp4) :
Instruction_4<TypedRegister, JSClass*, uint32, RegisterList>
(STATIC_CALL, aOp1, aOp2, aOp3, aOp4) {};
virtual Formatter& print(Formatter& f) {
f << opcodeNames[STATIC_CALL] << "\t" << mOp1 << ", " << mOp2->getName() << ", " << mOp3 << ", " << mOp4;
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << ArgList(mOp4, registers);
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -884,7 +850,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -927,7 +893,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -943,7 +909,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -959,7 +925,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -1014,7 +980,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << "R" << mOp2.first << '=' << registers[mOp2.first];
f << mOp1.first << ", " << mOp2.first;
return f;
}
};
@ -1030,7 +996,7 @@
return f;
}
virtual Formatter& printOperands(Formatter& f, const JSValues& registers) {
f << "R" << mOp1.first << '=' << registers[mOp1.first];
f << mOp1.first;
return f;
}
};
@ -1077,13 +1043,13 @@
"COMPARE_LE ",
"COMPARE_LT ",
"COMPARE_NE ",
"CONSTRUCTOR_CALL ",
"DEBUGGER ",
"DELETE_PROP ",
"DIVIDE ",
"ELEM_XCR ",
"GENERIC_BINARY_OP",
"GET_ELEMENT ",
"GET_METHOD ",
"GET_PROP ",
"GET_SLOT ",
"GET_STATIC ",
@ -1093,7 +1059,6 @@
"LOAD_IMMEDIATE ",
"LOAD_NAME ",
"LOAD_STRING ",
"METHOD_CALL ",
"MOVE ",
"MULTIPLY ",
"NAME_XCR ",
@ -1119,7 +1084,6 @@
"SHIFTLEFT ",
"SHIFTRIGHT ",
"SLOT_XCR ",
"STATIC_CALL ",
"STATIC_XCR ",
"STRICT_EQ ",
"STRICT_NE ",

View File

@ -115,7 +115,7 @@ TypedRegister ICodeGenerator::allocateRegister(const StringAtom& name, JSType *t
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const StringAtom& typeName)
{
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
return allocateRegister(name, findType(typeName));
}
@ -123,7 +123,7 @@ TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name, const Str
TypedRegister ICodeGenerator::allocateVariable(const StringAtom& name)
{
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
return allocateRegister(name, &Any_Type);
}
@ -315,7 +315,7 @@ TypedRegister ICodeGenerator::propertyXcr(TypedRegister base, const StringAtom &
TypedRegister ICodeGenerator::getStatic(JSClass *base, const StringAtom &name)
TypedRegister ICodeGenerator::getStatic(JSClass *base, const String &name)
{
TypedRegister dest(getTempRegister(), &Any_Type);
const JSSlot& slot = base->getStatic(name);
@ -403,7 +403,7 @@ TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source)
iCode->push_back(instr);
return dest;
}
void ICodeGenerator::move(TypedRegister destination, TypedRegister source)
{
@ -458,45 +458,22 @@ TypedRegister ICodeGenerator::binaryOp(ICodeOp op, TypedRegister source1,
return dest;
}
TypedRegister ICodeGenerator::call(TypedRegister target, const StringAtom &name, RegisterList *args)
TypedRegister ICodeGenerator::call(TypedRegister target, TypedRegister thisArg, RegisterList *args)
{
TypedRegister dest(getTempRegister(), &Any_Type);
Call *instr = new Call(dest, target, &name, *args);
Call *instr = new Call(dest, target, thisArg, *args);
iCode->push_back(instr);
return dest;
}
TypedRegister ICodeGenerator::methodCall(TypedRegister targetBase, TypedRegister targetValue, RegisterList *args)
TypedRegister ICodeGenerator::getMethod(TypedRegister thisArg, uint32 slotIndex)
{
TypedRegister dest(getTempRegister(), &Any_Type);
MethodCall *instr = new MethodCall(dest, targetBase, targetValue, *args);
GetMethod *instr = new GetMethod(dest, thisArg, slotIndex);
iCode->push_back(instr);
return dest;
}
TypedRegister ICodeGenerator::staticCall(JSClass *c, const StringAtom &name, RegisterList *args)
{
TypedRegister dest(getTempRegister(), &Any_Type);
const JSSlot& slot = c->getStatic(name);
StaticCall *instr = new StaticCall(dest, c, slot.mIndex, *args);
iCode->push_back(instr);
return dest;
}
void ICodeGenerator::constructorCall(JSClass *c, const StringAtom &name, TypedRegister thisArg, RegisterList *args)
{
const JSSlot& slot = c->getStatic(name);
ConstructorCall *instr = new ConstructorCall(c, slot.mIndex, thisArg, *args);
iCode->push_back(instr);
}
void ICodeGenerator::constructorCall(JSClass *c, const String &name, TypedRegister thisArg, RegisterList *args)
{
const JSSlot& slot = c->getStatic(name);
ConstructorCall *instr = new ConstructorCall(c, slot.mIndex, thisArg, *args);
iCode->push_back(instr);
}
TypedRegister ICodeGenerator::super()
{
TypedRegister dest(getTempRegister(), &Any_Type);
@ -668,7 +645,6 @@ static bool generatedBoolean(ExprNode *p)
return true;
default:
break;
}
return false;
}
@ -688,6 +664,17 @@ static bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex, JST
return false;
}
static bool isMethodName(JSType *t, const StringAtom &name, uint32 &slotIndex)
{
JSClass* c = dynamic_cast<JSClass*>(t);
while (c) {
if (c->hasMethod(name, slotIndex))
return true;
c = c->getSuperClass();
}
return false;
}
ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex)
{
@ -700,6 +687,8 @@ ICodeGenerator::LValueKind ICodeGenerator::resolveIdentifier(const StringAtom &n
if (!isStaticMethod()) {
if (isSlotName(mClass, name, slotIndex, v.second))
return Slot;
if (isMethodName(mClass, name, slotIndex))
return Method;
}
bool isConstructor = false;
if (mClass->hasStatic(name, v.second, isConstructor)) {
@ -842,17 +831,20 @@ TypedRegister ICodeGenerator::handleIdentifier(IdentifierExprNode *p, ExprNode::
case ExprNode::call:
switch (lValueKind) {
case Var:
ret = call(v, name, args);
ret = call(v, TypedRegister(NotARegister, &Null_Type), args);
break;
case Name:
ret = methodCall(TypedRegister(NotARegister, &Null_Type), loadString(name), args);
ret = call(loadName(name), TypedRegister(NotARegister, &Null_Type), args);
break;
case Method:
ret = call(getMethod(thisBase, slotIndex), thisBase, args);
break;
case Static:
ret = staticCall(mClass, name, args);
ret = call(getStatic(mClass, name), TypedRegister(NotARegister, &Null_Type), args);
break;
case Constructor:
ret = newClass(mClass);
constructorCall(mClass, name, ret, args);
call(getStatic(mClass, name), ret, args);
break;
default:
NOT_REACHED("Bad lvalue kind");
@ -900,12 +892,15 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
if (lValueKind == Property) {
if (isSlotName(base.second, fieldName, slotIndex, fieldType))
lValueKind = Slot;
else {
bool isConstructor;
clazz = dynamic_cast<JSClass*>(base.second);
if (clazz && clazz->hasStatic(fieldName, fieldType, isConstructor))
lValueKind = (isConstructor) ? Constructor : Static;
}
else
if (isMethodName(base.second, fieldName, slotIndex))
lValueKind = Method;
else {
bool isConstructor;
clazz = dynamic_cast<JSClass*>(base.second);
if (clazz && clazz->hasStatic(fieldName, fieldType, isConstructor))
lValueKind = (isConstructor) ? Constructor : Static;
}
}
if ((lValueKind == Property) || (base.first == NotARegister))
base = loadName(baseName, base.second);
@ -914,26 +909,32 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
base = genExpr(b->op1);
if (isSlotName(base.second, fieldName, slotIndex, fieldType))
lValueKind = Slot;
else {
bool isConstructor;
clazz = dynamic_cast<JSClass*>(base.second);
if (clazz && clazz->hasStatic(fieldName, fieldType, isConstructor))
lValueKind = (isConstructor) ? Constructor : Static;
}
else
if (isMethodName(base.second, fieldName, slotIndex))
lValueKind = Method;
else {
bool isConstructor;
clazz = dynamic_cast<JSClass*>(base.second);
if (clazz && clazz->hasStatic(fieldName, fieldType, isConstructor))
lValueKind = (isConstructor) ? Constructor : Static;
}
}
TypedRegister v;
switch (use) {
case ExprNode::call:
switch (lValueKind) {
case Static:
ret = staticCall(clazz, fieldName, args);
ret = call(getStatic(clazz, fieldName), TypedRegister(NotARegister, &Null_Type), args);
break;
case Constructor:
ret = newClass(clazz);
constructorCall(clazz, fieldName, ret, args);
call(getStatic(clazz, fieldName), ret, args);
break;
case Property:
ret = methodCall(base, loadString(fieldName), args);
ret = call(getProperty(base, fieldName), base, args);
break;
case Method:
ret = call(getMethod(base, slotIndex), base, args);
break;
default:
NOT_REACHED("Bad lvalue kind");
@ -988,20 +989,26 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I
}
break;
case ExprNode::postDecrement:
case ExprNode::postIncrement:
switch (lValueKind) {
case Constructor:
case Static:
ret = staticXcr(clazz, fieldName, xcrementOp);
break;
case Property:
ret = propertyXcr(base, fieldName, xcrementOp);
break;
case Slot:
ret = slotXcr(base, slotIndex, xcrementOp);
break;
default:
NOT_REACHED("Bad lvalue kind");
case ExprNode::postIncrement:
{
// JSClass *clss = dynamic_cast<JSClass*>(fieldType);
// if (clss) {
// clss->findOverloadedOperator(use);
// }
switch (lValueKind) {
case Constructor:
case Static:
ret = staticXcr(clazz, fieldName, xcrementOp);
break;
case Property:
ret = propertyXcr(base, fieldName, xcrementOp);
break;
case Slot:
ret = slotXcr(base, slotIndex, xcrementOp);
break;
default:
NOT_REACHED("Bad lvalue kind");
}
}
break;
case ExprNode::preDecrement:
@ -1094,7 +1101,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
JSClass* clazz = dynamic_cast<JSClass*>(value.type);
if (clazz) {
ret = newClass(clazz);
constructorCall(clazz, className, ret, &args);
call(getStatic(clazz, className), ret, &args);
}
else
NOT_REACHED("New <name>, where <name> is not a known class"); // XXX Runtime error.
@ -1133,7 +1140,8 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
else
if (i->op->getKind() == ExprNode::index) {
BinaryExprNode *b = static_cast<BinaryExprNode *>(i->op);
ret = methodCall(genExpr(b->op1), genExpr(b->op2), &args);
TypedRegister base = genExpr(b->op1);
ret = call(getElement(base, genExpr(b->op2)), base, &args);
}
else
ASSERT("WAH!");
@ -1457,7 +1465,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
{
FunctionExprNode *f = static_cast<FunctionExprNode *>(p);
ICodeGenerator icg(mWorld, mGlobal);
icg.allocateParameter(mWorld->identifiers[widenCString("this")]); // always parameter #0
icg.allocateParameter(mWorld->identifiers["this"]); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
@ -1530,7 +1538,7 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
ICodeGeneratorFlags flags = (isStatic) ? kIsStaticMethod : kNoFlags;
ICodeGenerator icg(mWorld, mGlobal, mClass, flags);
icg.allocateParameter(mWorld->identifiers[widenCString("this")], (mClass) ? mClass : &Any_Type); // always parameter #0
icg.allocateParameter(mWorld->identifiers["this"], (mClass) ? mClass : &Any_Type); // always parameter #0
VariableBinding *v = f->function.parameters;
while (v) {
if (v->name && (v->name->getKind() == ExprNode::identifier))
@ -1560,11 +1568,11 @@ ICodeModule *ICodeGenerator::genFunction(FunctionStmtNode *f, bool isConstructor
}
}
if (!foundSuperCall) { // invoke the default superclass constructor
icg.constructorCall(superclass, superclass->getName(), thisValue, &args);
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
}
}
const StringAtom &initName = mWorld->identifiers[widenCString("__init__")]; // XXXXXXX
icg.constructorCall(mClass, initName, thisValue, &args); // ok, so it's mis-named
const StringAtom &initName = mWorld->identifiers["__init__"]; // XXXXXXX
icg.call(icg.getStatic(mClass, initName), thisValue, &args); // ok, so it's mis-named
}
icg.genStmt(f->function.body);
return icg.complete();
@ -1577,7 +1585,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
startStatement(p->pos);
if (mExceptionRegister.first == NotARegister) {
mExceptionRegister = allocateRegister(mWorld->identifiers[widenCString("__exceptionObject__")], &Any_Type);
mExceptionRegister = allocateRegister(mWorld->identifiers["__exceptionObject__"], &Any_Type);
}
switch (p->getKind()) {
@ -1605,14 +1613,14 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
// do a pre-processing loop to discover whether it is in fact empty
// and then pass that info through to the genFunction() call for each
// constructor.
const StringAtom &initName = mWorld->identifiers[widenCString("__init__")];
const StringAtom &initName = mWorld->identifiers["__init__"];
thisClass->defineStatic(initName, &Function_Type);
bool hasDefaultConstructor = false;
if (classStmt->body) {
JSScope* thisScope = thisClass->getScope();
ICodeGenerator ccg(mWorld, thisScope, thisClass, kNoFlags); // constructor code generator.
ccg.allocateParameter(mWorld->identifiers[widenCString("this")], thisClass); // always parameter #0
ccg.allocateParameter(mWorld->identifiers["this"], thisClass); // always parameter #0
ICodeGenerator scg(mWorld, thisScope, thisClass, kIsStaticMethod); // static initializer code generator.
StmtNode* s = classStmt->body->statements;
while (s) {
@ -1678,7 +1686,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
scg.setStatic(thisClass, name, scg.newFunction(icm));
}
else
thisScope->defineFunction(name, icm);
thisClass->defineMethod(name, new JSFunction(icm));
}
}
break;
@ -1698,8 +1706,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
RegisterList args;
ICodeGenerator icg(mWorld, thisScope, thisClass, kIsStaticMethod);
if (superclass)
icg.constructorCall(superclass, superclass->getName(), thisValue, &args);
icg.constructorCall(thisClass, initName, thisValue, &args);
icg.call(icg.getStatic(superclass, superclass->getName()), thisValue, &args);
icg.call(icg.getStatic(thisClass, initName), thisValue, &args);
thisClass->defineConstructor(nameExpr->name);
scg.setStatic(thisClass, nameExpr->name, scg.newFunction(icg.complete()));
}

View File

@ -190,7 +190,7 @@ namespace ICG {
void setFlag(uint32 flag, bool v) { mFlags = (ICodeGeneratorFlags)((v) ? mFlags | flag : mFlags & ~flag); }
typedef enum {Var, Property, Slot, Static, Constructor, Name} LValueKind;
typedef enum {Var, Property, Slot, Static, Constructor, Name, Method} LValueKind;
LValueKind resolveIdentifier(const StringAtom &name, TypedRegister &v, uint32 &slotIndex);
TypedRegister handleIdentifier(IdentifierExprNode *p, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret, RegisterList *args);
@ -242,11 +242,8 @@ namespace ICG {
TypedRegister op(ICodeOp op, TypedRegister source);
TypedRegister op(ICodeOp op, TypedRegister source1, TypedRegister source2);
TypedRegister binaryOp(ICodeOp op, TypedRegister source1, TypedRegister source2);
TypedRegister call(TypedRegister target, const StringAtom &name, RegisterList *args);
TypedRegister methodCall(TypedRegister targetBase, TypedRegister targetValue, RegisterList *args);
TypedRegister staticCall(JSClass *c, const StringAtom &name, RegisterList *args);
void constructorCall(JSClass *c, const StringAtom &name, TypedRegister thisArg, RegisterList *args);
void constructorCall(JSClass *c, const String &name, TypedRegister thisArg, RegisterList *args);
TypedRegister call(TypedRegister base, TypedRegister target, RegisterList *args);
TypedRegister getMethod(TypedRegister thisArg, uint32 slotIndex);
void move(TypedRegister destination, TypedRegister source);
TypedRegister logicalNot(TypedRegister source);
@ -274,7 +271,7 @@ namespace ICG {
void setProperty(TypedRegister base, const StringAtom &name, TypedRegister value);
TypedRegister propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op);
TypedRegister getStatic(JSClass *base, const StringAtom &name);
TypedRegister getStatic(JSClass *base, const String &name);
void setStatic(JSClass *base, const StringAtom &name, TypedRegister value);
TypedRegister staticXcr(JSClass *base, const StringAtom &name, ICodeOp op);

View File

@ -583,138 +583,32 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
(*registers)[dst(su).first] = s;
}
break;
case METHOD_CALL:
{
MethodCall* call = static_cast<MethodCall*>(instruction);
ASSERT((*registers)[op3(call).first].isString());
JSValue base;
JSValue prop;
if (op2(call).first == NotARegister) {
base = mGlobal;
prop = mGlobal->getProperty(*((*registers)[op3(call).first].string));
}
else {
base = (*registers)[op2(call).first];
ASSERT(base.isObject()); // XXX runtime error
prop = base.object->getProperty(*((*registers)[op3(call).first].string));
}
ASSERT(prop.isFunction()); // XXX runtime error
JSFunction *target = prop.function;
case GET_METHOD:
{
GetMethod* gm = static_cast<GetMethod*>(instruction);
JSValue base = (*registers)[src1(gm).first];
ASSERT(base.isObject()); // XXX runtime error
JSClass *theClass = dynamic_cast<JSClass*>(base.object->getType());
ASSERT(theClass);
(*registers)[dst(gm).first] = theClass->getMethod(src2(gm));
}
break;
case CALL:
{
Call* call = static_cast<Call*>(instruction);
ASSERT((*registers)[op2(call).first].isFunction()); // XXX runtime error
JSFunction *target = (*registers)[op2(call).first].function;
if (target->isNative()) {
RegisterList &params = op4(call);
JSValues argv(params.size() + 1);
argv[0] = base;
JSValues::size_type i = 1;
for (RegisterList::const_iterator src = params.begin(), end = params.end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first];
}
JSValue result = static_cast<JSNativeFunction*>(target)->mCode(this, argv);
if (op1(call).first != NotARegister)
(*registers)[op1(call).first] = result;
break;
}
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, op1(call));
mActivation = new Activation(target->getICode(), mActivation, base, op4(call));
JSClass *thisClass = dynamic_cast<JSClass*>(base.object->getType());
if (thisClass)
mGlobal = thisClass->getScope();
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
continue;
}
}
case STATIC_CALL:
{
StaticCall* call = static_cast<StaticCall*>(instruction);
JSClass* thisClass = op2(call);
const JSValue& value = (*thisClass)[op3(call)];
// FIXME: throw runtime error if not a function value.
ASSERT(value.isFunction());
JSFunction *target = value.function;
if (target->isNative()) {
RegisterList &params = op4(call);
JSValues argv(params.size() + 1, kNullValue);
JSValues::size_type i = 1;
for (RegisterList::const_iterator src = params.begin(), end = params.end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first];
}
JSValue result = static_cast<JSNativeFunction*>(target)->mCode(this, argv);
if (op1(call).first != NotARegister)
(*registers)[op1(call).first] = result;
break;
}
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, op1(call));
mActivation = new Activation(target->getICode(), mActivation, kNullValue, op4(call));
mGlobal = op2(call)->getScope();
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
continue;
}
}
case CONSTRUCTOR_CALL:
{
ConstructorCall* call = static_cast<ConstructorCall*>(instruction);
JSClass* thisClass = op1(call);
const JSValue& value = (*thisClass)[op2(call)];
// FIXME: throw runtime error if not a function value.
ASSERT(value.isFunction());
JSFunction *target = value.function;
if (target->isNative()) {
RegisterList &params = op4(call);
JSValues argv(params.size() + 1, kNullValue);
argv[0] = (*registers)[op3(call).first];
JSValues::size_type i = 1;
for (RegisterList::const_iterator src = params.begin(), end = params.end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first];
}
/*JSValue result = static_cast<JSNativeFunction*>(target)->mCode(this, argv);*/
break;
}
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, TypedRegister(NotARegister, &Any_Type));
mActivation = new Activation(target->getICode(), mActivation, (*registers)[op3(call).first], op4(call));
mGlobal = op1(call)->getScope();
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
continue;
}
}
case CALL:
{
Call* call = static_cast<Call*>(instruction);
JSFunction *target;
if (op2(call).first == NotARegister) {
ASSERT(mGlobal->getVariable(*op3(call)).isFunction());
target = mGlobal->getVariable(*op3(call)).function;
}
else {
ASSERT((*registers)[op2(call).first].isFunction()); // XXX runtime error
target = (*registers)[op2(call).first].function;
}
if (target->isNative()) {
RegisterList &params = op4(call);
JSValues argv(params.size() + 1);
argv[0] = kNullValue;
JSValues::size_type i = 1;
for (RegisterList::const_iterator src = params.begin(), end = params.end();
src != end; ++src, ++i) {
argv[i] = (*registers)[src->first];
}
JSValue result = static_cast<JSNativeFunction*>(target)->mCode(this, argv);
if (op1(call).first != NotARegister)
(*registers)[op1(call).first] = result;
@ -723,7 +617,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
else {
mLinkage = new Linkage(mLinkage, ++mPC,
mActivation, mGlobal, op1(call));
mActivation = new Activation(target->getICode(), mActivation, kNullValue, op4(call));
mActivation = new Activation(target->getICode(), mActivation, (*registers)[op3(call).first], op4(call));
registers = &mActivation->mRegisters;
mPC = mActivation->mICode->its_iCode->begin();
endPC = mActivation->mICode->its_iCode->end();
@ -833,6 +727,10 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSValue& value = (*registers)[src1(gp).first];
if (value.isObject()) {
if (value.isType()) {
// I don't think this is necessary anymore - any get property
// on a class name should have been turned into a GET_STATIC
// by the codegen.
ASSERT(false);
// REVISIT: should signal error if slot doesn't exist.
JSClass* thisClass = dynamic_cast<JSClass*>(value.type);
if (thisClass && thisClass->hasStatic(*src2(gp))) {
@ -852,6 +750,10 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSValue& value = (*registers)[dst(sp).first];
if (value.isObject()) {
if (value.isType()) {
// I don't think this is necessary anymore - any set property
// on a class name should have been turned into a SET_STATIC
// by the codegen.
ASSERT(false);
// REVISIT: should signal error if slot doesn't exist.
JSClass* thisClass = dynamic_cast<JSClass*>(value.object);
if (thisClass && thisClass->hasStatic(*src1(sp))) {

View File

@ -43,6 +43,7 @@ namespace JSClasses {
using JSTypes::JSObject;
using JSTypes::JSType;
using JSTypes::JSScope;
using JSTypes::JSFunction;
using ICG::ICodeModule;
@ -69,7 +70,11 @@ namespace JSClasses {
typedef gc_allocator<JSSlot> gc_slot_allocator;
#endif
typedef std::map<String, JSSlot, std::less<const String>, gc_slot_allocator> JSSlots;
typedef std::map<String, JSSlot, std::less<const String>, gc_slot_allocator> JSSlots;
typedef std::pair<String, JSFunction*> MethodEntry;
typedef std::vector<MethodEntry> JSMethods;
/**
* Represents a class in the JavaScript 2 (ECMA 4) language.
@ -85,8 +90,7 @@ namespace JSClasses {
uint32 mStaticCount;
JSSlots mStaticSlots;
JSValue* mStaticData;
// typedef std::vector<ICodeModule*, gc_allocator<ICodeModule*> > JSMethods;
// JSMethods mMethods;
JSMethods mMethods;
public:
JSClass(JSScope* scope, const String& name, JSClass* superClass = 0)
: JSType(name, superClass),
@ -95,9 +99,12 @@ namespace JSClasses {
mStaticCount(0),
mStaticData(0)
{
// to "inherit" superClass methods.
if (superClass)
mScope->setPrototype(superClass->mScope);
if (superClass) {
// inherit superclass methods
JSMethods::iterator end = superClass->mMethods.end();
for (JSMethods::iterator i = superClass->mMethods.begin(); i != end; i++)
mMethods.push_back(*i);
}
}
JSClass* getSuperClass()
@ -209,6 +216,32 @@ namespace JSClasses {
f << i->first << " : " << mStaticData[i->second.mIndex] << "\n";
}
}
void defineMethod(const String& name, JSFunction *f)
{
uint32 slot;
if (hasMethod(name, slot))
mMethods[slot] = MethodEntry(name, f);
else
mMethods.push_back(MethodEntry(name, f));
}
bool hasMethod(const String& name, uint32& index)
{
JSMethods::iterator end = mMethods.end();
for (JSMethods::iterator i = mMethods.begin(); i != end; i++) {
if (i->first == name) {
index = i - mMethods.begin();
return true;
}
}
return false;
}
JSFunction* getMethod(uint32 index)
{
return mMethods[index].second;
}
};
/**
@ -242,6 +275,11 @@ namespace JSClasses {
setPrototype(thisClass->getScope());
}
JSFunction* getMethod(uint32 index)
{
return getClass()->getMethod(index);
}
JSClass* getClass()
{
return static_cast<JSClass*>(mType);

View File

@ -192,7 +192,6 @@ static void readEvalPrint(FILE *in, World &world)
global.defineNativeFunction(world.identifiers["dump"], dump);
global.defineNativeFunction(world.identifiers["load"], load);
// global.defineNativeFunction(world.identifiers["time"], time);
// global.defineVariable(
String buffer;
string line;
@ -294,7 +293,8 @@ class Tracer : public Context::Listener {
char * tests[] = {
"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;" ,
"class A { static var b = 3; static function s() { return b++; } } var a:A = new A; print(a.s(), \" should be 3\"); print(A.b, \" should be 4\"); return;"
"class A { static var b = 3; static function s() { return b++; }function x() { return \"Ax\"; } function y() { return \"Ay\"; } } var a:A = new A; print(a.s(), \" should be 3\"); print(A.b, \" should be 4\"); return;",
"class B extends A { function x() { return \"Bx\"; } } var b:B = new B; print(b.x(), \" should be Bx\"); print(b.y(), \" should be Ay\"); return;"
};
static void testCompile()

View File

@ -288,26 +288,14 @@ $ops{"RETURN_VOID"} =
$ops{"CALL"} =
{
super => "Instruction_4",
rem => "result, target, name, args",
params => [ ("TypedRegister", "TypedRegister", "const StringAtom*", "RegisterList") ]
};
$ops{"STATIC_CALL"} =
{
super => "Instruction_4",
rem => "result, target class, index, args",
params => [ ("TypedRegister", "JSClass*", "uint32", "RegisterList") ]
};
$ops{"METHOD_CALL"} =
{
super => "Instruction_4",
rem => "result, target base, target value, args",
rem => "result, base, target, args",
params => [ ("TypedRegister", "TypedRegister", "TypedRegister", "RegisterList") ]
};
$ops{"CONSTRUCTOR_CALL"} =
$ops{"GET_METHOD"} =
{
super => "Instruction_4",
rem => "target class, index, this, args",
params => [ ("JSClass*", "uint32", "TypedRegister", "RegisterList") ]
super => "Instruction_3",
rem => "result, target base, index",
params => [ ("TypedRegister", "TypedRegister", "uint32") ]
};
$ops{"THROW"} =
{
@ -589,7 +577,8 @@ sub get_printops_body {
for $type (@types) {
if ($type eq "TypedRegister") {
push (@oplist, "\"R\" << mOp$op.first << '=' << registers[mOp$op.first]");
push (@oplist, "mOp$op.first");
# push (@oplist, "\"R\" << mOp$op.first << '=' << registers[mOp$op.first]");
} elsif ($type eq "RegisterList") {
push (@oplist, "ArgList(mOp$op, registers)");
}