mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Removed all xxxCall, using simple call for everything.
Changed methods to use mMethods vector instead. Various other fixes etc.
This commit is contained in:
parent
bb45987123
commit
06f0a5261f
158
js/js2/icode.h
158
js/js2/icode.h
@ -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 ",
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 ¶ms = 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 ¶ms = 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 ¶ms = 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 ¶ms = 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))) {
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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)");
|
||||
}
|
||||
|
158
js2/src/icode.h
158
js2/src/icode.h
@ -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 ",
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 ¶ms = 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 ¶ms = 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 ¶ms = 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 ¶ms = 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))) {
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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)");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user