From f236eeaaff28a5cded384d3f0d438c073ea25ac0 Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Tue, 18 Jul 2000 20:53:03 +0000 Subject: [PATCH] Removed all xxxCall, using simple call for everything. Changed methods to use mMethods vector instead. Various other fixes etc. git-svn-id: svn://10.0.0.236/trunk@74388 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js/js2/icode.h | 158 +++++++++++---------------- mozilla/js/js2/icodegenerator.cpp | 164 +++++++++++++++------------- mozilla/js/js2/icodegenerator.h | 11 +- mozilla/js/js2/interpreter.cpp | 148 +++++-------------------- mozilla/js/js2/js2.cpp | 4 +- mozilla/js/js2/jsclasses.h | 50 ++++++++- mozilla/js/js2/tools/gencode.pl | 25 ++--- mozilla/js2/src/icode.h | 158 +++++++++++---------------- mozilla/js2/src/icodegenerator.cpp | 164 +++++++++++++++------------- mozilla/js2/src/icodegenerator.h | 11 +- mozilla/js2/src/interpreter.cpp | 148 +++++-------------------- mozilla/js2/src/jsclasses.h | 50 ++++++++- mozilla/js2/tests/cpp/js2_shell.cpp | 4 +- mozilla/js2/tools/gencode.pl | 25 ++--- 14 files changed, 458 insertions(+), 662 deletions(-) diff --git a/mozilla/js/js2/icode.h b/mozilla/js/js2/icode.h index 635dd80362e..a0a98afbca1 100644 --- a/mozilla/js/js2/icode.h +++ b/mozilla/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 { + class Call : public Instruction_4 { public: - /* result, target, name, args */ - Call (TypedRegister aOp1, TypedRegister aOp2, const StringAtom* aOp3, RegisterList aOp4) : - Instruction_4 + /* result, base, target, args */ + Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, RegisterList aOp4) : + Instruction_4 (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 */ }; - class ConstructorCall : public Instruction_4 { - public: - /* target class, index, this, args */ - ConstructorCall (JSClass* aOp1, uint32 aOp2, TypedRegister aOp3, RegisterList aOp4) : - Instruction_4 - (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 { + public: + /* result, target base, index */ + GetMethod (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3) : + Instruction_3 + (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 { - public: - /* result, target base, target value, args */ - MethodCall (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, RegisterList aOp4) : - Instruction_4 - (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 { - public: - /* result, target class, index, args */ - StaticCall (TypedRegister aOp1, JSClass* aOp2, uint32 aOp3, RegisterList aOp4) : - Instruction_4 - (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 ", diff --git a/mozilla/js/js2/icodegenerator.cpp b/mozilla/js/js2/icodegenerator.cpp index e93c723df47..3180a263270 100644 --- a/mozilla/js/js2/icodegenerator.cpp +++ b/mozilla/js/js2/icodegenerator.cpp @@ -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(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(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(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(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(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(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(value.type); if (clazz) { ret = newClass(clazz); - constructorCall(clazz, className, ret, &args); + call(getStatic(clazz, className), ret, &args); } else NOT_REACHED("New , where 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(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(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())); } diff --git a/mozilla/js/js2/icodegenerator.h b/mozilla/js/js2/icodegenerator.h index 10e69ddfeb2..51ab22fca50 100644 --- a/mozilla/js/js2/icodegenerator.h +++ b/mozilla/js/js2/icodegenerator.h @@ -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); diff --git a/mozilla/js/js2/interpreter.cpp b/mozilla/js/js2/interpreter.cpp index b708491e332..9a648aacbba 100644 --- a/mozilla/js/js2/interpreter.cpp +++ b/mozilla/js/js2/interpreter.cpp @@ -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(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(instruction); + JSValue base = (*registers)[src1(gm).first]; + ASSERT(base.isObject()); // XXX runtime error + JSClass *theClass = dynamic_cast(base.object->getType()); + ASSERT(theClass); + (*registers)[dst(gm).first] = theClass->getMethod(src2(gm)); + } + break; + + case CALL: + { + Call* call = static_cast(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(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(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(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(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(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(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(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(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(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(value.object); if (thisClass && thisClass->hasStatic(*src1(sp))) { diff --git a/mozilla/js/js2/js2.cpp b/mozilla/js/js2/js2.cpp index d25b68a41a6..dd4e49a006f 100644 --- a/mozilla/js/js2/js2.cpp +++ b/mozilla/js/js2/js2.cpp @@ -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() diff --git a/mozilla/js/js2/jsclasses.h b/mozilla/js/js2/jsclasses.h index 83450dc37be..3aa8edfe300 100644 --- a/mozilla/js/js2/jsclasses.h +++ b/mozilla/js/js2/jsclasses.h @@ -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 gc_slot_allocator; #endif - typedef std::map, gc_slot_allocator> JSSlots; + typedef std::map, gc_slot_allocator> JSSlots; + + + typedef std::pair MethodEntry; + typedef std::vector 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 > 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(mType); diff --git a/mozilla/js/js2/tools/gencode.pl b/mozilla/js/js2/tools/gencode.pl index d44a5c2705d..1c7ba2d7fba 100644 --- a/mozilla/js/js2/tools/gencode.pl +++ b/mozilla/js/js2/tools/gencode.pl @@ -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)"); } diff --git a/mozilla/js2/src/icode.h b/mozilla/js2/src/icode.h index 635dd80362e..a0a98afbca1 100644 --- a/mozilla/js2/src/icode.h +++ b/mozilla/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 { + class Call : public Instruction_4 { public: - /* result, target, name, args */ - Call (TypedRegister aOp1, TypedRegister aOp2, const StringAtom* aOp3, RegisterList aOp4) : - Instruction_4 + /* result, base, target, args */ + Call (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, RegisterList aOp4) : + Instruction_4 (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 */ }; - class ConstructorCall : public Instruction_4 { - public: - /* target class, index, this, args */ - ConstructorCall (JSClass* aOp1, uint32 aOp2, TypedRegister aOp3, RegisterList aOp4) : - Instruction_4 - (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 { + public: + /* result, target base, index */ + GetMethod (TypedRegister aOp1, TypedRegister aOp2, uint32 aOp3) : + Instruction_3 + (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 { - public: - /* result, target base, target value, args */ - MethodCall (TypedRegister aOp1, TypedRegister aOp2, TypedRegister aOp3, RegisterList aOp4) : - Instruction_4 - (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 { - public: - /* result, target class, index, args */ - StaticCall (TypedRegister aOp1, JSClass* aOp2, uint32 aOp3, RegisterList aOp4) : - Instruction_4 - (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 ", diff --git a/mozilla/js2/src/icodegenerator.cpp b/mozilla/js2/src/icodegenerator.cpp index e93c723df47..3180a263270 100644 --- a/mozilla/js2/src/icodegenerator.cpp +++ b/mozilla/js2/src/icodegenerator.cpp @@ -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(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(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(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(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(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(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(value.type); if (clazz) { ret = newClass(clazz); - constructorCall(clazz, className, ret, &args); + call(getStatic(clazz, className), ret, &args); } else NOT_REACHED("New , where 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(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(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())); } diff --git a/mozilla/js2/src/icodegenerator.h b/mozilla/js2/src/icodegenerator.h index 10e69ddfeb2..51ab22fca50 100644 --- a/mozilla/js2/src/icodegenerator.h +++ b/mozilla/js2/src/icodegenerator.h @@ -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); diff --git a/mozilla/js2/src/interpreter.cpp b/mozilla/js2/src/interpreter.cpp index b708491e332..9a648aacbba 100644 --- a/mozilla/js2/src/interpreter.cpp +++ b/mozilla/js2/src/interpreter.cpp @@ -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(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(instruction); + JSValue base = (*registers)[src1(gm).first]; + ASSERT(base.isObject()); // XXX runtime error + JSClass *theClass = dynamic_cast(base.object->getType()); + ASSERT(theClass); + (*registers)[dst(gm).first] = theClass->getMethod(src2(gm)); + } + break; + + case CALL: + { + Call* call = static_cast(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(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(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(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(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(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(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(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(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(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(value.object); if (thisClass && thisClass->hasStatic(*src1(sp))) { diff --git a/mozilla/js2/src/jsclasses.h b/mozilla/js2/src/jsclasses.h index 83450dc37be..3aa8edfe300 100644 --- a/mozilla/js2/src/jsclasses.h +++ b/mozilla/js2/src/jsclasses.h @@ -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 gc_slot_allocator; #endif - typedef std::map, gc_slot_allocator> JSSlots; + typedef std::map, gc_slot_allocator> JSSlots; + + + typedef std::pair MethodEntry; + typedef std::vector 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 > 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(mType); diff --git a/mozilla/js2/tests/cpp/js2_shell.cpp b/mozilla/js2/tests/cpp/js2_shell.cpp index d25b68a41a6..dd4e49a006f 100644 --- a/mozilla/js2/tests/cpp/js2_shell.cpp +++ b/mozilla/js2/tests/cpp/js2_shell.cpp @@ -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() diff --git a/mozilla/js2/tools/gencode.pl b/mozilla/js2/tools/gencode.pl index d44a5c2705d..1c7ba2d7fba 100644 --- a/mozilla/js2/tools/gencode.pl +++ b/mozilla/js2/tools/gencode.pl @@ -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)"); }