From b1eb71fadb6b9804ef5c839770c2bca01a686d74 Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Wed, 28 Jun 2000 18:41:30 +0000 Subject: [PATCH] First set of unified 'dot' handling changes for statics. git-svn-id: svn://10.0.0.236/trunk@73418 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js/js2/icodegenerator.cpp | 443 ++++++++++++++-------------- mozilla/js/js2/icodegenerator.h | 33 +-- mozilla/js/js2/interpreter.cpp | 40 ++- mozilla/js/js2/js2.cpp | 19 ++ mozilla/js/js2/tools/gencode.pl | 6 + mozilla/js/js2/vmtypes.h | 19 +- mozilla/js2/src/icodegenerator.cpp | 443 ++++++++++++++-------------- mozilla/js2/src/icodegenerator.h | 33 +-- mozilla/js2/src/interpreter.cpp | 40 ++- mozilla/js2/src/vmtypes.h | 19 +- mozilla/js2/tests/cpp/js2_shell.cpp | 19 ++ mozilla/js2/tools/gencode.pl | 6 + 12 files changed, 628 insertions(+), 492 deletions(-) diff --git a/mozilla/js/js2/icodegenerator.cpp b/mozilla/js/js2/icodegenerator.cpp index 974814271a5..c29d8f04ce8 100644 --- a/mozilla/js/js2/icodegenerator.cpp +++ b/mozilla/js/js2/icodegenerator.cpp @@ -223,6 +223,8 @@ TypedRegister ICodeGenerator::newArray() return dest; } + + TypedRegister ICodeGenerator::loadName(const StringAtom &name) { TypedRegister dest(getRegister(), &Any_Type); @@ -237,37 +239,24 @@ void ICodeGenerator::saveName(const StringAtom &name, TypedRegister value) iCode->push_back(instr); } -TypedRegister ICodeGenerator::nameInc(const StringAtom &name) +TypedRegister ICodeGenerator::nameXcr(const StringAtom &name, ICodeOp op) { TypedRegister dest(getRegister(), &Number_Type); - NameXcr *instr = new NameXcr(dest, &name, 1.0); + NameXcr *instr = new NameXcr(dest, &name, (op == ADD) ? 1.0 : -1.0); iCode->push_back(instr); return dest; } -TypedRegister ICodeGenerator::nameDec(const StringAtom &name) + + +TypedRegister ICodeGenerator::varXcr(TypedRegister var, ICodeOp op) { TypedRegister dest(getRegister(), &Number_Type); - NameXcr *instr = new NameXcr(dest, &name, -1.0); + VarXcr *instr = new VarXcr(dest, var, (op == ADD) ? 1.0 : -1.0); iCode->push_back(instr); return dest; } -TypedRegister ICodeGenerator::varInc(TypedRegister var) -{ - TypedRegister dest(getRegister(), &Number_Type); - VarXcr *instr = new VarXcr(dest, var, 1.0); - iCode->push_back(instr); - return dest; -} - -TypedRegister ICodeGenerator::varDec(TypedRegister var) -{ - TypedRegister dest(getRegister(), &Number_Type); - VarXcr *instr = new VarXcr(dest, var, -1.0); - iCode->push_back(instr); - return dest; -} @@ -286,21 +275,14 @@ void ICodeGenerator::setProperty(TypedRegister base, const StringAtom &name, iCode->push_back(instr); } -TypedRegister ICodeGenerator::propertyInc(TypedRegister base, const StringAtom &name) +TypedRegister ICodeGenerator::propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op) { TypedRegister dest(getRegister(), &Any_Type); - PropXcr *instr = new PropXcr(dest, base, &name, 1.0); + PropXcr *instr = new PropXcr(dest, base, &name, (op == ADD) ? 1.0 : -1.0); iCode->push_back(instr); return dest; } -TypedRegister ICodeGenerator::propertyDec(TypedRegister base, const StringAtom &name) -{ - TypedRegister dest(getRegister(), &Any_Type); - PropXcr *instr = new PropXcr(dest, base, &name, -1.0); - iCode->push_back(instr); - return dest; -} @@ -322,7 +304,7 @@ void ICodeGenerator::setStatic(JSClass *base, const StringAtom &name, iCode->push_back(instr); } -TypedRegister ICodeGenerator::staticInc(JSClass *base, const StringAtom &name) +TypedRegister ICodeGenerator::staticXcr(JSClass *base, const StringAtom &name, ICodeOp op) { TypedRegister dest(getRegister(), &Any_Type); const JSSlot& slot = base->getStatic(name); @@ -331,14 +313,6 @@ TypedRegister ICodeGenerator::staticInc(JSClass *base, const StringAtom &name) return dest; } -TypedRegister ICodeGenerator::staticDec(JSClass *base, const StringAtom &name) -{ - TypedRegister dest(getRegister(), &Any_Type); - const JSSlot& slot = base->getStatic(name); - StaticXcr *instr = new StaticXcr(dest, base, slot.mIndex, -1.0); - iCode->push_back(instr); - return dest; -} @@ -357,21 +331,14 @@ void ICodeGenerator::setSlot(TypedRegister base, uint32 slot, iCode->push_back(instr); } -TypedRegister ICodeGenerator::slotInc(TypedRegister base, uint32 slot) +TypedRegister ICodeGenerator::slotXcr(TypedRegister base, uint32 slot, ICodeOp op) { TypedRegister dest(getRegister(), &Any_Type); - SlotXcr *instr = new SlotXcr(dest, base, slot, 1.0); + SlotXcr *instr = new SlotXcr(dest, base, slot, (op == ADD) ? 1.0 : -1.0); iCode->push_back(instr); return dest; } -TypedRegister ICodeGenerator::slotDec(TypedRegister base, uint32 slot) -{ - TypedRegister dest(getRegister(), &Any_Type); - SlotXcr *instr = new SlotXcr(dest, base, slot, -1.0); - iCode->push_back(instr); - return dest; -} @@ -390,21 +357,14 @@ void ICodeGenerator::setElement(TypedRegister base, TypedRegister index, iCode->push_back(instr); } -TypedRegister ICodeGenerator::elementInc(TypedRegister base, TypedRegister index) +TypedRegister ICodeGenerator::elementXcr(TypedRegister base, TypedRegister index, ICodeOp op) { TypedRegister dest(getRegister(), &Number_Type); - ElemXcr *instr = new ElemXcr(dest, base, index, 1.0); + ElemXcr *instr = new ElemXcr(dest, base, index, (op == ADD) ? 1.0 : -1.0); iCode->push_back(instr); return dest; } -TypedRegister ICodeGenerator::elementDec(TypedRegister base, TypedRegister index) -{ - TypedRegister dest(getRegister(), &Number_Type); - ElemXcr *instr = new ElemXcr(dest, base, index, -1.0); - iCode->push_back(instr); - return dest; -} TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source) @@ -468,6 +428,14 @@ TypedRegister ICodeGenerator::methodCall(TypedRegister targetBase, TypedRegister return dest; } +TypedRegister ICodeGenerator::staticCall(JSClass *c, const StringAtom &name, RegisterList args) +{ + TypedRegister dest(getRegister(), &Any_Type); + StaticCall *instr = new StaticCall(dest, c, &name, args); + iCode->push_back(instr); + return dest; +} + void ICodeGenerator::branch(Label *label) { Branch *instr = new Branch(label); @@ -630,19 +598,140 @@ static bool generatedBoolean(ExprNode *p) static bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex) { JSClass* c = dynamic_cast(t); - if (c) { - do { - if (c->hasSlot(name)) { - const JSSlot &s = c->getSlot(name); - slotIndex = s.mIndex; - return true; - } - c = c->getSuperClass(); - } while (c); + while (c) { + if (c->hasSlot(name)) { + const JSSlot &s = c->getSlot(name); + slotIndex = s.mIndex; + return true; + } + c = c->getSuperClass(); } return false; } +TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret) +{ + enum {Property, Slot, Static} lValueKind; + + ASSERT(b->getKind() == ExprNode::dot); + + if (b->op2->getKind() != ExprNode::identifier) { + NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] ) + } + else { + const StringAtom &name = static_cast(b->op2)->name; + TypedRegister base; + JSClass* c = NULL; + uint32 slotIndex; + if ((b->op1->getKind() == ExprNode::identifier) && !mWithinWith) { + const StringAtom &baseName = (static_cast(b->op1))->name; + JSType *baseType = &Any_Type; + base = findVariable(baseName); + + if (base.first != NotARegister) + baseType = base.second; + else { + // implicit 'this' has a big impact here + baseType = mGlobal->getType(baseName); + } + lValueKind = Property; + if (baseType == &Type_Type) { + const JSValue &v = mGlobal->getVariable(baseName); + c = dynamic_cast(v.type); + if (c && c->hasStatic(name)) + lValueKind = Static; + } + if (base.first == NotARegister) + base = loadName(baseName); + } + else { + base = genExpr(b->op1); + if (isSlotName(base.second, name, slotIndex)) + lValueKind = Slot; + else { + c = dynamic_cast(base.second); + if (c && c->hasStatic(name)) + lValueKind = Static; + else + lValueKind = Property; + } + } + TypedRegister v; + switch (use) { + case ExprNode::addEquals: + case ExprNode::subtractEquals: + case ExprNode::multiplyEquals: + case ExprNode::divideEquals: + case ExprNode::moduloEquals: + case ExprNode::leftShiftEquals: + case ExprNode::rightShiftEquals: + case ExprNode::logicalRightShiftEquals: + case ExprNode::bitwiseAndEquals: + case ExprNode::bitwiseXorEquals: + case ExprNode::bitwiseOrEquals: + switch (lValueKind) { + case Static: + v = getStatic(c, name); + break; + case Property: + v = getProperty(base, name); + break; + case Slot: + v = getSlot(base, slotIndex); + break; + } + ret = op(mapExprNodeToICodeOp(use), v, ret); + // fall thru... + case ExprNode::assignment: + switch (lValueKind) { + case Static: + setStatic(c, name, ret); + break; + case Property: + setProperty(base, name, ret); + break; + case Slot: + setSlot(base, slotIndex, ret); + break; + } + break; + case ExprNode::postDecrement: + case ExprNode::postIncrement: + switch (lValueKind) { + case Static: + ret = staticXcr(c, name, xcrementOp); + break; + case Property: + ret = propertyXcr(base, name, xcrementOp); + break; + case Slot: + ret = slotXcr(base, slotIndex, xcrementOp); + } + break; + case ExprNode::preDecrement: + case ExprNode::preIncrement: + switch (lValueKind) { + case Static: + ret = op(xcrementOp, getStatic(c, name), loadImmediate(1.0)); + setStatic(c, name, ret); + break; + case Property: + ret = op(xcrementOp, getProperty(base, name), loadImmediate(1.0)); + setProperty(base, name, ret); + break; + case Slot: + ret = op(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0)); + setSlot(base, slotIndex, ret); + break; + } + break; + } + } + return ret; +} + + + /* if trueBranch OR falseBranch are not null, the sub-expression should generate a conditional branch to the appropriate target. If either branch is NULL, it @@ -654,6 +743,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, Label *falseBranch) { TypedRegister ret(NotARegister, &None_Type); + ICodeOp xcrementOp = ADD; switch (p->getKind()) { case ExprNode::True: if (trueBranch || falseBranch) { @@ -703,8 +793,20 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, if (i->op->getKind() == ExprNode::dot) { BinaryExprNode *b = static_cast(i->op); - TypedRegister base = genExpr(b->op1); - ret = methodCall(base, loadString(static_cast(b->op2)->name), args); + TypedRegister base = genExpr(b->op1); + // might be Class.() + const StringAtom &name = static_cast(b->op2)->name; + if ((base.second == &Type_Type) + && (b->op1->getKind() == ExprNode::identifier)) { + const StringAtom &className = (static_cast(b->op1))->name; + const JSValue &v = mGlobal->getVariable(className); + JSClass* c = dynamic_cast(v.type); + if (c && c->getScope()->hasProperty(name)) { + ret = staticCall(c, name, args); + break; + } + } + ret = methodCall(base, loadString(name), args); } else if (i->op->getKind() == ExprNode::identifier) { @@ -738,17 +840,32 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, case ExprNode::dot : { BinaryExprNode *b = static_cast(p); - const StringAtom &name = static_cast(b->op2)->name; - TypedRegister base = genExpr(b->op1); - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) - ret = getSlot(base, slotIndex); + if (b->op2->getKind() != ExprNode::identifier) { + NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] ) + } else { - JSClass* c = dynamic_cast(base.second); - if (c && c->hasStatic(name)) - ret = getStatic(c, name); - else - ret = getProperty(base, name); + const StringAtom &name = static_cast(b->op2)->name; + TypedRegister base = genExpr(b->op1); + uint32 slotIndex; + if (isSlotName(base.second, name, slotIndex)) + ret = getSlot(base, slotIndex); + else { + // + // look for .m + // + // XXX redundant work done by genExpr(b->op1), seems a pity + if ((base.second == &Type_Type) + && (b->op1->getKind() == ExprNode::identifier)) { + const StringAtom &className = (static_cast(b->op1))->name; + const JSValue &v = mGlobal->getVariable(className); + JSClass* c = dynamic_cast(v.type); + if (c && c->hasStatic(name)) { + ret = getStatic(c, name); + break; + } + } + } + ret = getProperty(base, name); } } break; @@ -765,12 +882,11 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, if (v.first != NotARegister) ret = v; else { + // When we support implicit this AND we're in a method (instance or static), look + // to see if the class has a slot(for an instance field) or property(static field) + // by this name. ret = loadName(name); - if (mAtTopLevel) { - if (mGlobal->hasProperty(name)) { - ret.second = mGlobal->getType(name); - } - } + ret.second = mGlobal->getType(name); } } else @@ -783,126 +899,30 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, case ExprNode::string : ret = loadString(mWorld->identifiers[(static_cast(p))->str]); break; - case ExprNode::preIncrement: - { - UnaryExprNode *u = static_cast(p); - if (u->op->getKind() == ExprNode::dot) { - BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - const StringAtom &name = static_cast(b->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) { - ret = slotInc(base, slotIndex); - ret = op(ADD, ret, loadImmediate(1.0)); - setSlot(base, slotIndex, ret); - } - else { - ret = getProperty(base, name); - ret = op(ADD, ret, loadImmediate(1.0)); - setProperty(base, name, ret); - } - } - else - if (u->op->getKind() == ExprNode::identifier) { - if (!mWithinWith) { - TypedRegister v = findVariable((static_cast(u->op))->name); - if (v.first != NotARegister) - ret = op(ADD, ret, loadImmediate(1.0)); - else { - ret = loadName((static_cast(u->op))->name); - ret = op(ADD, ret, loadImmediate(1.0)); - saveName((static_cast(u->op))->name, ret); - } - } - else { - ret = loadName((static_cast(u->op))->name); - ret = op(ADD, ret, loadImmediate(1.0)); - saveName((static_cast(u->op))->name, ret); - } - } - else - if (u->op->getKind() == ExprNode::index) { - BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - TypedRegister index = genExpr(b->op2); - ret = getElement(base, index); - ret = op(ADD, ret, loadImmediate(1.0)); - setElement(base, index, ret); - } - else - ASSERT("WAH!"); - } - break; - case ExprNode::postIncrement: - { - UnaryExprNode *u = static_cast(p); - if (u->op->getKind() == ExprNode::dot) { - BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - const StringAtom &name = static_cast(b->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) - ret = slotInc(base, slotIndex); - else - ret = propertyInc(base, name); - } - else - if (u->op->getKind() == ExprNode::identifier) { - if (!mWithinWith) { - TypedRegister v = findVariable((static_cast(u->op))->name); - if (v.first != NotARegister) - ret = varInc(v); - else - ret = nameInc((static_cast(u->op))->name); - } - else - ret = nameInc((static_cast(u->op))->name); - } - else - if (u->op->getKind() == ExprNode::index) { - BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - TypedRegister index = genExpr(b->op2); - ret = elementInc(base, index); - } - else - ASSERT("WAH!"); - } - break; case ExprNode::preDecrement: - { + xcrementOp = SUBTRACT; + case ExprNode::preIncrement: + { UnaryExprNode *u = static_cast(p); if (u->op->getKind() == ExprNode::dot) { BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - const StringAtom &name = static_cast(b->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) { - ret = getSlot(base, slotIndex); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); - setSlot(base, slotIndex, ret); - } - else { - ret = getProperty(base, name); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); - setProperty(base, name, ret); - } + ret = handleDot(b, p->getKind(), xcrementOp, ret); } else if (u->op->getKind() == ExprNode::identifier) { if (!mWithinWith) { TypedRegister v = findVariable((static_cast(u->op))->name); if (v.first != NotARegister) - ret = op(SUBTRACT, ret, loadImmediate(1.0)); + ret = op(xcrementOp, ret, loadImmediate(1.0)); else { ret = loadName((static_cast(u->op))->name); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); + ret = op(xcrementOp, ret, loadImmediate(1.0)); saveName((static_cast(u->op))->name, ret); } } else { ret = loadName((static_cast(u->op))->name); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); + ret = op(xcrementOp, ret, loadImmediate(1.0)); saveName((static_cast(u->op))->name, ret); } } @@ -912,7 +932,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, TypedRegister base = genExpr(b->op1); TypedRegister index = genExpr(b->op2); ret = getElement(base, index); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); + ret = op(xcrementOp, ret, loadImmediate(1.0)); setElement(base, index, ret); } else @@ -920,41 +940,38 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, } break; case ExprNode::postDecrement: + xcrementOp = SUBTRACT; + case ExprNode::postIncrement: { UnaryExprNode *u = static_cast(p); if (u->op->getKind() == ExprNode::dot) { BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - const StringAtom &name = static_cast(b->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) - slotDec(base, slotIndex); - else - ret = propertyDec(base, name); + ret = handleDot(b, p->getKind(), xcrementOp, ret); } else if (u->op->getKind() == ExprNode::identifier) { if (!mWithinWith) { TypedRegister v = findVariable((static_cast(u->op))->name); if (v.first != NotARegister) - ret = varDec(v); + ret = varXcr(v, xcrementOp); else - ret = nameDec((static_cast(u->op))->name); + ret = nameXcr((static_cast(u->op))->name, xcrementOp); } else - ret = nameDec((static_cast(u->op))->name); + ret = nameXcr((static_cast(u->op))->name, xcrementOp); } else if (u->op->getKind() == ExprNode::index) { BinaryExprNode *b = static_cast(u->op); TypedRegister base = genExpr(b->op1); TypedRegister index = genExpr(b->op2); - ret = elementInc(base, index); + ret = elementXcr(base, index, xcrementOp); } else ASSERT("WAH!"); } break; + case ExprNode::plus: case ExprNode::minus: case ExprNode::complement: @@ -1000,18 +1017,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, else if (b->op1->getKind() == ExprNode::dot) { BinaryExprNode *lb = static_cast(b->op1); - TypedRegister base = genExpr(lb->op1); - const StringAtom &name = static_cast(lb->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) - setSlot(base, slotIndex, ret); - else { - JSClass* c = dynamic_cast(base.second); - if (c && c->hasStatic(name)) - setStatic(c, name, ret); - else - setProperty(base, name, ret); - } + ret = handleDot(lb, p->getKind(), xcrementOp, ret); } else if (b->op1->getKind() == ExprNode::index) { @@ -1060,19 +1066,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, else if (b->op1->getKind() == ExprNode::dot) { BinaryExprNode *lb = static_cast(b->op1); - TypedRegister base = genExpr(lb->op1); - const StringAtom &name = static_cast(lb->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) { - TypedRegister v = getSlot(base, slotIndex); - ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret); - setSlot(base, slotIndex, ret); - } - else { - TypedRegister v = getProperty(base, name); - ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret); - setProperty(base, name, ret); - } + ret = handleDot(lb, p->getKind(), xcrementOp, ret); } else if (b->op1->getKind() == ExprNode::index) { @@ -1430,6 +1424,10 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) JSScope* thisScope = thisClass->getScope(); ICodeGenerator ccg(mWorld, thisScope, thisClass, false); // constructor code generator. ccg.allocateParameter(mWorld->identifiers[widenCString("this")], thisClass); // always parameter #0 + // XXX + // The only use for mcg is to establish a new container class ('thisClass' instead of 'mClass') + // and set up a new scope, maybe we could just do that inline? + // XXX ICodeGenerator mcg(mWorld, thisScope, thisClass, false); // method code generator. ICodeGenerator scg(mWorld, thisScope, thisClass, false); // static initializer code generator. StmtNode* s = classStmt->body->statements; @@ -1501,6 +1499,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) case StmtNode::Function: { FunctionStmtNode *f = static_cast(p); + bool isStatic = hasAttribute(f->attributes, Token::Static); ICodeGenerator icg(mWorld, mGlobal, mClass, false); icg.allocateParameter(mWorld->identifiers[widenCString("this")], (mClass) ? mClass : &Any_Type); // always parameter #0 VariableBinding *v = f->function.parameters; @@ -1514,6 +1513,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) //stdOut << icg; ICodeModule *icm = icg.complete(); if (f->function.name->getKind() == ExprNode::identifier) + // XXX what to do with static methods? + // if (isStatic && mClass)... mGlobal->defineFunction((static_cast(f->function.name))->name, icm); } break; diff --git a/mozilla/js/js2/icodegenerator.h b/mozilla/js/js2/icodegenerator.h index fc63027ede4..555ac7f7e57 100644 --- a/mozilla/js/js2/icodegenerator.h +++ b/mozilla/js/js2/icodegenerator.h @@ -181,6 +181,7 @@ namespace ICG { } JSType *findType(const StringAtom& typeName); + TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret); public: ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, bool atTopLevel = true); @@ -205,23 +206,23 @@ namespace ICG { void returnStmt(TypedRegister r); void returnStmt(); void throwStmt(TypedRegister r) - { iCode->push_back(new Throw(r)); } + { iCode->push_back(new Throw(r)); } void debuggerStmt() - { iCode->push_back(new Debugger()); } + { iCode->push_back(new Debugger()); } TypedRegister allocateVariable(const StringAtom& name); TypedRegister allocateVariable(const StringAtom& name, const StringAtom& typeName); TypedRegister findVariable(const StringAtom& name) - { VariableList::iterator i = variableList->find(name); + { VariableList::iterator i = variableList->find(name); return (i == variableList->end()) ? TypedRegister(NotARegister, &None_Type) : (*i).second; } TypedRegister allocateParameter(const StringAtom& name) - { parameterCount++; return grabRegister(name, &Any_Type); } + { parameterCount++; return grabRegister(name, &Any_Type); } TypedRegister allocateParameter(const StringAtom& name, const StringAtom& typeName) - { parameterCount++; return grabRegister(name, findType(typeName)); } + { parameterCount++; return grabRegister(name, findType(typeName)); } TypedRegister allocateParameter(const StringAtom& name, JSType *type) - { parameterCount++; return grabRegister(name, type); } + { parameterCount++; return grabRegister(name, type); } Formatter& print(Formatter& f); @@ -229,6 +230,7 @@ namespace ICG { TypedRegister op(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 move(TypedRegister destination, TypedRegister source); TypedRegister logicalNot(TypedRegister source); @@ -246,31 +248,25 @@ namespace ICG { TypedRegister loadName(const StringAtom &name); void saveName(const StringAtom &name, TypedRegister value); - TypedRegister nameInc(const StringAtom &name); - TypedRegister nameDec(const StringAtom &name); + TypedRegister nameXcr(const StringAtom &name, ICodeOp op); TypedRegister getProperty(TypedRegister base, const StringAtom &name); void setProperty(TypedRegister base, const StringAtom &name, TypedRegister value); - TypedRegister propertyInc(TypedRegister base, const StringAtom &name); - TypedRegister propertyDec(TypedRegister base, const StringAtom &name); + TypedRegister propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op); TypedRegister getStatic(JSClass *base, const StringAtom &name); void setStatic(JSClass *base, const StringAtom &name, TypedRegister value); - TypedRegister staticInc(JSClass *base, const StringAtom &name); - TypedRegister staticDec(JSClass *base, const StringAtom &name); + TypedRegister staticXcr(JSClass *base, const StringAtom &name, ICodeOp op); TypedRegister getElement(TypedRegister base, TypedRegister index); void setElement(TypedRegister base, TypedRegister index, TypedRegister value); - TypedRegister elementInc(TypedRegister base, TypedRegister index); - TypedRegister elementDec(TypedRegister base, TypedRegister index); + TypedRegister elementXcr(TypedRegister base, TypedRegister index, ICodeOp op); TypedRegister getSlot(TypedRegister base, uint32 slot); void setSlot(TypedRegister base, uint32 slot, TypedRegister value); - TypedRegister slotInc(TypedRegister base, uint32 slot); - TypedRegister slotDec(TypedRegister base, uint32 slot); + TypedRegister slotXcr(TypedRegister base, uint32 slot, ICodeOp op); - TypedRegister varInc(TypedRegister var); - TypedRegister varDec(TypedRegister var); + TypedRegister varXcr(TypedRegister var, ICodeOp op); Register getRegisterBase() { return topRegister; } InstructionStream *getICode() { return iCode; } @@ -280,6 +276,7 @@ namespace ICG { }; Formatter& operator<<(Formatter &f, ICodeGenerator &i); + Formatter& operator<<(Formatter &f, ICodeModule &i); /* std::ostream &operator<<(std::ostream &s, ICodeGenerator &i); std::ostream &operator<<(std::ostream &s, StringAtom &str); diff --git a/mozilla/js/js2/interpreter.cpp b/mozilla/js/js2/interpreter.cpp index 83a4baebd6a..de5a853f8a1 100644 --- a/mozilla/js/js2/interpreter.cpp +++ b/mozilla/js/js2/interpreter.cpp @@ -233,8 +233,7 @@ static JSValue less_Default(const JSValue& r1, const JSValue& r2) JSValue lv = r1.toPrimitive(JSValue::Number); JSValue rv = r2.toPrimitive(JSValue::Number); if (lv.isString() && rv.isString()) { - // XXX FIXME urgh, call w_strcmp ??? on a JSString ??? - return JSValue(double(lv.string->compare(*rv.string) < 0)); + return JSValue(bool(lv.string->compare(*rv.string) < 0)); } else { lv = lv.toNumber(); @@ -250,8 +249,7 @@ static JSValue lessEqual_Default(const JSValue& r1, const JSValue& r2) JSValue lv = r1.toPrimitive(JSValue::Number); JSValue rv = r2.toPrimitive(JSValue::Number); if (lv.isString() && rv.isString()) { - // XXX FIXME urgh, call w_strcmp ??? on a JSString ??? - return JSValue(); + return JSValue(bool(lv.string->compare(*rv.string) <= 0)); } else { lv = lv.toNumber(); @@ -267,8 +265,7 @@ static JSValue equal_Default(const JSValue& r1, const JSValue& r2) JSValue lv = r1.toPrimitive(JSValue::Number); JSValue rv = r2.toPrimitive(JSValue::Number); if (lv.isString() && rv.isString()) { - // XXX FIXME urgh, call w_strcmp ??? on a JSString ??? - return JSValue(); + return JSValue(bool(lv.string->compare(*rv.string) == 0)); } else { lv = lv.toNumber(); @@ -530,6 +527,37 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) } } + case STATIC_CALL: + { + StaticCall* call = static_cast(instruction); + ASSERT(op2(call)->getScope()->getProperty(*op3(call)).isFunction()); + JSFunction *target = op2(call)->getScope()->getProperty(*op3(call)).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(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 CALL: { Call* call = static_cast(instruction); diff --git a/mozilla/js/js2/js2.cpp b/mozilla/js/js2/js2.cpp index e217d10103f..53272b06cb2 100644 --- a/mozilla/js/js2/js2.cpp +++ b/mozilla/js/js2/js2.cpp @@ -123,6 +123,24 @@ static JSValue print(const JSValues &argv) return kUndefinedValue; } +static JSValue dump(const JSValues &argv) +{ + size_t n = argv.size(); + if (n > 1) { // the 'this' parameter is un-interesting + if (argv[1].isFunction()) { + JSFunction *f = static_cast(argv[1].function); + if (f->isNative()) + stdOut << "Native function"; + else + stdOut << *f->getICode(); + } + else + stdOut << "Not a function"; + } + stdOut << "\n"; + return kUndefinedValue; +} + static ICodeModule* genCode(Context &cx, StmtNode *p, const String &fileName) { ICodeGenerator icg(&cx.getWorld(), cx.getGlobalObject()); @@ -221,6 +239,7 @@ static void readEvalPrint(FILE *in, World &world) jsd.attachToContext (&cx); #endif global.defineNativeFunction(world.identifiers[widenCString("print")], print); + global.defineNativeFunction(world.identifiers[widenCString("dump")], dump); global.defineNativeFunction(world.identifiers[widenCString("load")], load); String buffer; diff --git a/mozilla/js/js2/tools/gencode.pl b/mozilla/js/js2/tools/gencode.pl index b883bc219f1..344192d191b 100644 --- a/mozilla/js/js2/tools/gencode.pl +++ b/mozilla/js/js2/tools/gencode.pl @@ -273,6 +273,12 @@ $ops{"CALL"} = rem => "result, target, name, args", params => [ ("TypedRegister" , "TypedRegister", "const StringAtom*", "RegisterList") ] }; +$ops{"STATIC_CALL"} = + { + super => "Instruction_4", + rem => "result, target class, name, args", + params => [ ("TypedRegister" , "JSClass*", "const StringAtom*", "RegisterList") ] + }; $ops{"METHOD_CALL"} = { super => "Instruction_4", diff --git a/mozilla/js/js2/vmtypes.h b/mozilla/js/js2/vmtypes.h index be7bbe01a45..f06ed4081ee 100644 --- a/mozilla/js/js2/vmtypes.h +++ b/mozilla/js/js2/vmtypes.h @@ -107,6 +107,7 @@ namespace VM { SHIFTLEFT, /* dest, source1, source2 */ SHIFTRIGHT, /* dest, source1, source2 */ SLOT_XCR, /* dest, source, slot number, value */ + STATIC_CALL, /* result, target class, name, args */ STATIC_XCR, /* dest, class, name, value */ STRICT_EQ, /* dest, source1, source2 */ STRICT_NE, /* dest, source1, source2 */ @@ -179,6 +180,7 @@ namespace VM { "SHIFTLEFT ", "SHIFTRIGHT ", "SLOT_XCR ", + "STATIC_CALL ", "STATIC_XCR ", "STRICT_EQ ", "STRICT_NE ", @@ -1125,6 +1127,22 @@ namespace VM { } }; + class StaticCall : public Instruction_4 { + public: + /* result, target class, name, args */ + StaticCall (TypedRegister aOp1, JSClass* aOp2, const StringAtom* aOp3, RegisterList aOp4) : + Instruction_4 + (STATIC_CALL, aOp1, aOp2, aOp3, aOp4) {}; + virtual Formatter& print(Formatter& f) { + f << opcodeNames[STATIC_CALL] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << "'" << *mOp3 << "'" << ", " << mOp4; + return f; + } + virtual Formatter& printOperands(Formatter& f, const JSValues& registers) { + f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << ArgList(mOp4, registers); + return f; + } + }; + class StaticXcr : public Instruction_4 { public: /* dest, class, index, value */ @@ -1295,7 +1313,6 @@ namespace VM { /* print() and printOperands() inherited from Arithmetic */ }; - } /* namespace VM */ } /* namespace JavaScript */ diff --git a/mozilla/js2/src/icodegenerator.cpp b/mozilla/js2/src/icodegenerator.cpp index 974814271a5..c29d8f04ce8 100644 --- a/mozilla/js2/src/icodegenerator.cpp +++ b/mozilla/js2/src/icodegenerator.cpp @@ -223,6 +223,8 @@ TypedRegister ICodeGenerator::newArray() return dest; } + + TypedRegister ICodeGenerator::loadName(const StringAtom &name) { TypedRegister dest(getRegister(), &Any_Type); @@ -237,37 +239,24 @@ void ICodeGenerator::saveName(const StringAtom &name, TypedRegister value) iCode->push_back(instr); } -TypedRegister ICodeGenerator::nameInc(const StringAtom &name) +TypedRegister ICodeGenerator::nameXcr(const StringAtom &name, ICodeOp op) { TypedRegister dest(getRegister(), &Number_Type); - NameXcr *instr = new NameXcr(dest, &name, 1.0); + NameXcr *instr = new NameXcr(dest, &name, (op == ADD) ? 1.0 : -1.0); iCode->push_back(instr); return dest; } -TypedRegister ICodeGenerator::nameDec(const StringAtom &name) + + +TypedRegister ICodeGenerator::varXcr(TypedRegister var, ICodeOp op) { TypedRegister dest(getRegister(), &Number_Type); - NameXcr *instr = new NameXcr(dest, &name, -1.0); + VarXcr *instr = new VarXcr(dest, var, (op == ADD) ? 1.0 : -1.0); iCode->push_back(instr); return dest; } -TypedRegister ICodeGenerator::varInc(TypedRegister var) -{ - TypedRegister dest(getRegister(), &Number_Type); - VarXcr *instr = new VarXcr(dest, var, 1.0); - iCode->push_back(instr); - return dest; -} - -TypedRegister ICodeGenerator::varDec(TypedRegister var) -{ - TypedRegister dest(getRegister(), &Number_Type); - VarXcr *instr = new VarXcr(dest, var, -1.0); - iCode->push_back(instr); - return dest; -} @@ -286,21 +275,14 @@ void ICodeGenerator::setProperty(TypedRegister base, const StringAtom &name, iCode->push_back(instr); } -TypedRegister ICodeGenerator::propertyInc(TypedRegister base, const StringAtom &name) +TypedRegister ICodeGenerator::propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op) { TypedRegister dest(getRegister(), &Any_Type); - PropXcr *instr = new PropXcr(dest, base, &name, 1.0); + PropXcr *instr = new PropXcr(dest, base, &name, (op == ADD) ? 1.0 : -1.0); iCode->push_back(instr); return dest; } -TypedRegister ICodeGenerator::propertyDec(TypedRegister base, const StringAtom &name) -{ - TypedRegister dest(getRegister(), &Any_Type); - PropXcr *instr = new PropXcr(dest, base, &name, -1.0); - iCode->push_back(instr); - return dest; -} @@ -322,7 +304,7 @@ void ICodeGenerator::setStatic(JSClass *base, const StringAtom &name, iCode->push_back(instr); } -TypedRegister ICodeGenerator::staticInc(JSClass *base, const StringAtom &name) +TypedRegister ICodeGenerator::staticXcr(JSClass *base, const StringAtom &name, ICodeOp op) { TypedRegister dest(getRegister(), &Any_Type); const JSSlot& slot = base->getStatic(name); @@ -331,14 +313,6 @@ TypedRegister ICodeGenerator::staticInc(JSClass *base, const StringAtom &name) return dest; } -TypedRegister ICodeGenerator::staticDec(JSClass *base, const StringAtom &name) -{ - TypedRegister dest(getRegister(), &Any_Type); - const JSSlot& slot = base->getStatic(name); - StaticXcr *instr = new StaticXcr(dest, base, slot.mIndex, -1.0); - iCode->push_back(instr); - return dest; -} @@ -357,21 +331,14 @@ void ICodeGenerator::setSlot(TypedRegister base, uint32 slot, iCode->push_back(instr); } -TypedRegister ICodeGenerator::slotInc(TypedRegister base, uint32 slot) +TypedRegister ICodeGenerator::slotXcr(TypedRegister base, uint32 slot, ICodeOp op) { TypedRegister dest(getRegister(), &Any_Type); - SlotXcr *instr = new SlotXcr(dest, base, slot, 1.0); + SlotXcr *instr = new SlotXcr(dest, base, slot, (op == ADD) ? 1.0 : -1.0); iCode->push_back(instr); return dest; } -TypedRegister ICodeGenerator::slotDec(TypedRegister base, uint32 slot) -{ - TypedRegister dest(getRegister(), &Any_Type); - SlotXcr *instr = new SlotXcr(dest, base, slot, -1.0); - iCode->push_back(instr); - return dest; -} @@ -390,21 +357,14 @@ void ICodeGenerator::setElement(TypedRegister base, TypedRegister index, iCode->push_back(instr); } -TypedRegister ICodeGenerator::elementInc(TypedRegister base, TypedRegister index) +TypedRegister ICodeGenerator::elementXcr(TypedRegister base, TypedRegister index, ICodeOp op) { TypedRegister dest(getRegister(), &Number_Type); - ElemXcr *instr = new ElemXcr(dest, base, index, 1.0); + ElemXcr *instr = new ElemXcr(dest, base, index, (op == ADD) ? 1.0 : -1.0); iCode->push_back(instr); return dest; } -TypedRegister ICodeGenerator::elementDec(TypedRegister base, TypedRegister index) -{ - TypedRegister dest(getRegister(), &Number_Type); - ElemXcr *instr = new ElemXcr(dest, base, index, -1.0); - iCode->push_back(instr); - return dest; -} TypedRegister ICodeGenerator::op(ICodeOp op, TypedRegister source) @@ -468,6 +428,14 @@ TypedRegister ICodeGenerator::methodCall(TypedRegister targetBase, TypedRegister return dest; } +TypedRegister ICodeGenerator::staticCall(JSClass *c, const StringAtom &name, RegisterList args) +{ + TypedRegister dest(getRegister(), &Any_Type); + StaticCall *instr = new StaticCall(dest, c, &name, args); + iCode->push_back(instr); + return dest; +} + void ICodeGenerator::branch(Label *label) { Branch *instr = new Branch(label); @@ -630,19 +598,140 @@ static bool generatedBoolean(ExprNode *p) static bool isSlotName(JSType *t, const StringAtom &name, uint32 &slotIndex) { JSClass* c = dynamic_cast(t); - if (c) { - do { - if (c->hasSlot(name)) { - const JSSlot &s = c->getSlot(name); - slotIndex = s.mIndex; - return true; - } - c = c->getSuperClass(); - } while (c); + while (c) { + if (c->hasSlot(name)) { + const JSSlot &s = c->getSlot(name); + slotIndex = s.mIndex; + return true; + } + c = c->getSuperClass(); } return false; } +TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret) +{ + enum {Property, Slot, Static} lValueKind; + + ASSERT(b->getKind() == ExprNode::dot); + + if (b->op2->getKind() != ExprNode::identifier) { + NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] ) + } + else { + const StringAtom &name = static_cast(b->op2)->name; + TypedRegister base; + JSClass* c = NULL; + uint32 slotIndex; + if ((b->op1->getKind() == ExprNode::identifier) && !mWithinWith) { + const StringAtom &baseName = (static_cast(b->op1))->name; + JSType *baseType = &Any_Type; + base = findVariable(baseName); + + if (base.first != NotARegister) + baseType = base.second; + else { + // implicit 'this' has a big impact here + baseType = mGlobal->getType(baseName); + } + lValueKind = Property; + if (baseType == &Type_Type) { + const JSValue &v = mGlobal->getVariable(baseName); + c = dynamic_cast(v.type); + if (c && c->hasStatic(name)) + lValueKind = Static; + } + if (base.first == NotARegister) + base = loadName(baseName); + } + else { + base = genExpr(b->op1); + if (isSlotName(base.second, name, slotIndex)) + lValueKind = Slot; + else { + c = dynamic_cast(base.second); + if (c && c->hasStatic(name)) + lValueKind = Static; + else + lValueKind = Property; + } + } + TypedRegister v; + switch (use) { + case ExprNode::addEquals: + case ExprNode::subtractEquals: + case ExprNode::multiplyEquals: + case ExprNode::divideEquals: + case ExprNode::moduloEquals: + case ExprNode::leftShiftEquals: + case ExprNode::rightShiftEquals: + case ExprNode::logicalRightShiftEquals: + case ExprNode::bitwiseAndEquals: + case ExprNode::bitwiseXorEquals: + case ExprNode::bitwiseOrEquals: + switch (lValueKind) { + case Static: + v = getStatic(c, name); + break; + case Property: + v = getProperty(base, name); + break; + case Slot: + v = getSlot(base, slotIndex); + break; + } + ret = op(mapExprNodeToICodeOp(use), v, ret); + // fall thru... + case ExprNode::assignment: + switch (lValueKind) { + case Static: + setStatic(c, name, ret); + break; + case Property: + setProperty(base, name, ret); + break; + case Slot: + setSlot(base, slotIndex, ret); + break; + } + break; + case ExprNode::postDecrement: + case ExprNode::postIncrement: + switch (lValueKind) { + case Static: + ret = staticXcr(c, name, xcrementOp); + break; + case Property: + ret = propertyXcr(base, name, xcrementOp); + break; + case Slot: + ret = slotXcr(base, slotIndex, xcrementOp); + } + break; + case ExprNode::preDecrement: + case ExprNode::preIncrement: + switch (lValueKind) { + case Static: + ret = op(xcrementOp, getStatic(c, name), loadImmediate(1.0)); + setStatic(c, name, ret); + break; + case Property: + ret = op(xcrementOp, getProperty(base, name), loadImmediate(1.0)); + setProperty(base, name, ret); + break; + case Slot: + ret = op(xcrementOp, getSlot(base, slotIndex), loadImmediate(1.0)); + setSlot(base, slotIndex, ret); + break; + } + break; + } + } + return ret; +} + + + /* if trueBranch OR falseBranch are not null, the sub-expression should generate a conditional branch to the appropriate target. If either branch is NULL, it @@ -654,6 +743,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, Label *falseBranch) { TypedRegister ret(NotARegister, &None_Type); + ICodeOp xcrementOp = ADD; switch (p->getKind()) { case ExprNode::True: if (trueBranch || falseBranch) { @@ -703,8 +793,20 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, if (i->op->getKind() == ExprNode::dot) { BinaryExprNode *b = static_cast(i->op); - TypedRegister base = genExpr(b->op1); - ret = methodCall(base, loadString(static_cast(b->op2)->name), args); + TypedRegister base = genExpr(b->op1); + // might be Class.() + const StringAtom &name = static_cast(b->op2)->name; + if ((base.second == &Type_Type) + && (b->op1->getKind() == ExprNode::identifier)) { + const StringAtom &className = (static_cast(b->op1))->name; + const JSValue &v = mGlobal->getVariable(className); + JSClass* c = dynamic_cast(v.type); + if (c && c->getScope()->hasProperty(name)) { + ret = staticCall(c, name, args); + break; + } + } + ret = methodCall(base, loadString(name), args); } else if (i->op->getKind() == ExprNode::identifier) { @@ -738,17 +840,32 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, case ExprNode::dot : { BinaryExprNode *b = static_cast(p); - const StringAtom &name = static_cast(b->op2)->name; - TypedRegister base = genExpr(b->op1); - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) - ret = getSlot(base, slotIndex); + if (b->op2->getKind() != ExprNode::identifier) { + NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] ) + } else { - JSClass* c = dynamic_cast(base.second); - if (c && c->hasStatic(name)) - ret = getStatic(c, name); - else - ret = getProperty(base, name); + const StringAtom &name = static_cast(b->op2)->name; + TypedRegister base = genExpr(b->op1); + uint32 slotIndex; + if (isSlotName(base.second, name, slotIndex)) + ret = getSlot(base, slotIndex); + else { + // + // look for .m + // + // XXX redundant work done by genExpr(b->op1), seems a pity + if ((base.second == &Type_Type) + && (b->op1->getKind() == ExprNode::identifier)) { + const StringAtom &className = (static_cast(b->op1))->name; + const JSValue &v = mGlobal->getVariable(className); + JSClass* c = dynamic_cast(v.type); + if (c && c->hasStatic(name)) { + ret = getStatic(c, name); + break; + } + } + } + ret = getProperty(base, name); } } break; @@ -765,12 +882,11 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, if (v.first != NotARegister) ret = v; else { + // When we support implicit this AND we're in a method (instance or static), look + // to see if the class has a slot(for an instance field) or property(static field) + // by this name. ret = loadName(name); - if (mAtTopLevel) { - if (mGlobal->hasProperty(name)) { - ret.second = mGlobal->getType(name); - } - } + ret.second = mGlobal->getType(name); } } else @@ -783,126 +899,30 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, case ExprNode::string : ret = loadString(mWorld->identifiers[(static_cast(p))->str]); break; - case ExprNode::preIncrement: - { - UnaryExprNode *u = static_cast(p); - if (u->op->getKind() == ExprNode::dot) { - BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - const StringAtom &name = static_cast(b->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) { - ret = slotInc(base, slotIndex); - ret = op(ADD, ret, loadImmediate(1.0)); - setSlot(base, slotIndex, ret); - } - else { - ret = getProperty(base, name); - ret = op(ADD, ret, loadImmediate(1.0)); - setProperty(base, name, ret); - } - } - else - if (u->op->getKind() == ExprNode::identifier) { - if (!mWithinWith) { - TypedRegister v = findVariable((static_cast(u->op))->name); - if (v.first != NotARegister) - ret = op(ADD, ret, loadImmediate(1.0)); - else { - ret = loadName((static_cast(u->op))->name); - ret = op(ADD, ret, loadImmediate(1.0)); - saveName((static_cast(u->op))->name, ret); - } - } - else { - ret = loadName((static_cast(u->op))->name); - ret = op(ADD, ret, loadImmediate(1.0)); - saveName((static_cast(u->op))->name, ret); - } - } - else - if (u->op->getKind() == ExprNode::index) { - BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - TypedRegister index = genExpr(b->op2); - ret = getElement(base, index); - ret = op(ADD, ret, loadImmediate(1.0)); - setElement(base, index, ret); - } - else - ASSERT("WAH!"); - } - break; - case ExprNode::postIncrement: - { - UnaryExprNode *u = static_cast(p); - if (u->op->getKind() == ExprNode::dot) { - BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - const StringAtom &name = static_cast(b->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) - ret = slotInc(base, slotIndex); - else - ret = propertyInc(base, name); - } - else - if (u->op->getKind() == ExprNode::identifier) { - if (!mWithinWith) { - TypedRegister v = findVariable((static_cast(u->op))->name); - if (v.first != NotARegister) - ret = varInc(v); - else - ret = nameInc((static_cast(u->op))->name); - } - else - ret = nameInc((static_cast(u->op))->name); - } - else - if (u->op->getKind() == ExprNode::index) { - BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - TypedRegister index = genExpr(b->op2); - ret = elementInc(base, index); - } - else - ASSERT("WAH!"); - } - break; case ExprNode::preDecrement: - { + xcrementOp = SUBTRACT; + case ExprNode::preIncrement: + { UnaryExprNode *u = static_cast(p); if (u->op->getKind() == ExprNode::dot) { BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - const StringAtom &name = static_cast(b->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) { - ret = getSlot(base, slotIndex); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); - setSlot(base, slotIndex, ret); - } - else { - ret = getProperty(base, name); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); - setProperty(base, name, ret); - } + ret = handleDot(b, p->getKind(), xcrementOp, ret); } else if (u->op->getKind() == ExprNode::identifier) { if (!mWithinWith) { TypedRegister v = findVariable((static_cast(u->op))->name); if (v.first != NotARegister) - ret = op(SUBTRACT, ret, loadImmediate(1.0)); + ret = op(xcrementOp, ret, loadImmediate(1.0)); else { ret = loadName((static_cast(u->op))->name); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); + ret = op(xcrementOp, ret, loadImmediate(1.0)); saveName((static_cast(u->op))->name, ret); } } else { ret = loadName((static_cast(u->op))->name); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); + ret = op(xcrementOp, ret, loadImmediate(1.0)); saveName((static_cast(u->op))->name, ret); } } @@ -912,7 +932,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, TypedRegister base = genExpr(b->op1); TypedRegister index = genExpr(b->op2); ret = getElement(base, index); - ret = op(SUBTRACT, ret, loadImmediate(1.0)); + ret = op(xcrementOp, ret, loadImmediate(1.0)); setElement(base, index, ret); } else @@ -920,41 +940,38 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, } break; case ExprNode::postDecrement: + xcrementOp = SUBTRACT; + case ExprNode::postIncrement: { UnaryExprNode *u = static_cast(p); if (u->op->getKind() == ExprNode::dot) { BinaryExprNode *b = static_cast(u->op); - TypedRegister base = genExpr(b->op1); - const StringAtom &name = static_cast(b->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) - slotDec(base, slotIndex); - else - ret = propertyDec(base, name); + ret = handleDot(b, p->getKind(), xcrementOp, ret); } else if (u->op->getKind() == ExprNode::identifier) { if (!mWithinWith) { TypedRegister v = findVariable((static_cast(u->op))->name); if (v.first != NotARegister) - ret = varDec(v); + ret = varXcr(v, xcrementOp); else - ret = nameDec((static_cast(u->op))->name); + ret = nameXcr((static_cast(u->op))->name, xcrementOp); } else - ret = nameDec((static_cast(u->op))->name); + ret = nameXcr((static_cast(u->op))->name, xcrementOp); } else if (u->op->getKind() == ExprNode::index) { BinaryExprNode *b = static_cast(u->op); TypedRegister base = genExpr(b->op1); TypedRegister index = genExpr(b->op2); - ret = elementInc(base, index); + ret = elementXcr(base, index, xcrementOp); } else ASSERT("WAH!"); } break; + case ExprNode::plus: case ExprNode::minus: case ExprNode::complement: @@ -1000,18 +1017,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, else if (b->op1->getKind() == ExprNode::dot) { BinaryExprNode *lb = static_cast(b->op1); - TypedRegister base = genExpr(lb->op1); - const StringAtom &name = static_cast(lb->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) - setSlot(base, slotIndex, ret); - else { - JSClass* c = dynamic_cast(base.second); - if (c && c->hasStatic(name)) - setStatic(c, name, ret); - else - setProperty(base, name, ret); - } + ret = handleDot(lb, p->getKind(), xcrementOp, ret); } else if (b->op1->getKind() == ExprNode::index) { @@ -1060,19 +1066,7 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p, else if (b->op1->getKind() == ExprNode::dot) { BinaryExprNode *lb = static_cast(b->op1); - TypedRegister base = genExpr(lb->op1); - const StringAtom &name = static_cast(lb->op2)->name; - uint32 slotIndex; - if (isSlotName(base.second, name, slotIndex)) { - TypedRegister v = getSlot(base, slotIndex); - ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret); - setSlot(base, slotIndex, ret); - } - else { - TypedRegister v = getProperty(base, name); - ret = op(mapExprNodeToICodeOp(p->getKind()), v, ret); - setProperty(base, name, ret); - } + ret = handleDot(lb, p->getKind(), xcrementOp, ret); } else if (b->op1->getKind() == ExprNode::index) { @@ -1430,6 +1424,10 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) JSScope* thisScope = thisClass->getScope(); ICodeGenerator ccg(mWorld, thisScope, thisClass, false); // constructor code generator. ccg.allocateParameter(mWorld->identifiers[widenCString("this")], thisClass); // always parameter #0 + // XXX + // The only use for mcg is to establish a new container class ('thisClass' instead of 'mClass') + // and set up a new scope, maybe we could just do that inline? + // XXX ICodeGenerator mcg(mWorld, thisScope, thisClass, false); // method code generator. ICodeGenerator scg(mWorld, thisScope, thisClass, false); // static initializer code generator. StmtNode* s = classStmt->body->statements; @@ -1501,6 +1499,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) case StmtNode::Function: { FunctionStmtNode *f = static_cast(p); + bool isStatic = hasAttribute(f->attributes, Token::Static); ICodeGenerator icg(mWorld, mGlobal, mClass, false); icg.allocateParameter(mWorld->identifiers[widenCString("this")], (mClass) ? mClass : &Any_Type); // always parameter #0 VariableBinding *v = f->function.parameters; @@ -1514,6 +1513,8 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet) //stdOut << icg; ICodeModule *icm = icg.complete(); if (f->function.name->getKind() == ExprNode::identifier) + // XXX what to do with static methods? + // if (isStatic && mClass)... mGlobal->defineFunction((static_cast(f->function.name))->name, icm); } break; diff --git a/mozilla/js2/src/icodegenerator.h b/mozilla/js2/src/icodegenerator.h index fc63027ede4..555ac7f7e57 100644 --- a/mozilla/js2/src/icodegenerator.h +++ b/mozilla/js2/src/icodegenerator.h @@ -181,6 +181,7 @@ namespace ICG { } JSType *findType(const StringAtom& typeName); + TypedRegister handleDot(BinaryExprNode *b, ExprNode::Kind use, ICodeOp xcrementOp, TypedRegister ret); public: ICodeGenerator(World *world, JSScope *global, JSClass *aClass = NULL, bool atTopLevel = true); @@ -205,23 +206,23 @@ namespace ICG { void returnStmt(TypedRegister r); void returnStmt(); void throwStmt(TypedRegister r) - { iCode->push_back(new Throw(r)); } + { iCode->push_back(new Throw(r)); } void debuggerStmt() - { iCode->push_back(new Debugger()); } + { iCode->push_back(new Debugger()); } TypedRegister allocateVariable(const StringAtom& name); TypedRegister allocateVariable(const StringAtom& name, const StringAtom& typeName); TypedRegister findVariable(const StringAtom& name) - { VariableList::iterator i = variableList->find(name); + { VariableList::iterator i = variableList->find(name); return (i == variableList->end()) ? TypedRegister(NotARegister, &None_Type) : (*i).second; } TypedRegister allocateParameter(const StringAtom& name) - { parameterCount++; return grabRegister(name, &Any_Type); } + { parameterCount++; return grabRegister(name, &Any_Type); } TypedRegister allocateParameter(const StringAtom& name, const StringAtom& typeName) - { parameterCount++; return grabRegister(name, findType(typeName)); } + { parameterCount++; return grabRegister(name, findType(typeName)); } TypedRegister allocateParameter(const StringAtom& name, JSType *type) - { parameterCount++; return grabRegister(name, type); } + { parameterCount++; return grabRegister(name, type); } Formatter& print(Formatter& f); @@ -229,6 +230,7 @@ namespace ICG { TypedRegister op(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 move(TypedRegister destination, TypedRegister source); TypedRegister logicalNot(TypedRegister source); @@ -246,31 +248,25 @@ namespace ICG { TypedRegister loadName(const StringAtom &name); void saveName(const StringAtom &name, TypedRegister value); - TypedRegister nameInc(const StringAtom &name); - TypedRegister nameDec(const StringAtom &name); + TypedRegister nameXcr(const StringAtom &name, ICodeOp op); TypedRegister getProperty(TypedRegister base, const StringAtom &name); void setProperty(TypedRegister base, const StringAtom &name, TypedRegister value); - TypedRegister propertyInc(TypedRegister base, const StringAtom &name); - TypedRegister propertyDec(TypedRegister base, const StringAtom &name); + TypedRegister propertyXcr(TypedRegister base, const StringAtom &name, ICodeOp op); TypedRegister getStatic(JSClass *base, const StringAtom &name); void setStatic(JSClass *base, const StringAtom &name, TypedRegister value); - TypedRegister staticInc(JSClass *base, const StringAtom &name); - TypedRegister staticDec(JSClass *base, const StringAtom &name); + TypedRegister staticXcr(JSClass *base, const StringAtom &name, ICodeOp op); TypedRegister getElement(TypedRegister base, TypedRegister index); void setElement(TypedRegister base, TypedRegister index, TypedRegister value); - TypedRegister elementInc(TypedRegister base, TypedRegister index); - TypedRegister elementDec(TypedRegister base, TypedRegister index); + TypedRegister elementXcr(TypedRegister base, TypedRegister index, ICodeOp op); TypedRegister getSlot(TypedRegister base, uint32 slot); void setSlot(TypedRegister base, uint32 slot, TypedRegister value); - TypedRegister slotInc(TypedRegister base, uint32 slot); - TypedRegister slotDec(TypedRegister base, uint32 slot); + TypedRegister slotXcr(TypedRegister base, uint32 slot, ICodeOp op); - TypedRegister varInc(TypedRegister var); - TypedRegister varDec(TypedRegister var); + TypedRegister varXcr(TypedRegister var, ICodeOp op); Register getRegisterBase() { return topRegister; } InstructionStream *getICode() { return iCode; } @@ -280,6 +276,7 @@ namespace ICG { }; Formatter& operator<<(Formatter &f, ICodeGenerator &i); + Formatter& operator<<(Formatter &f, ICodeModule &i); /* std::ostream &operator<<(std::ostream &s, ICodeGenerator &i); std::ostream &operator<<(std::ostream &s, StringAtom &str); diff --git a/mozilla/js2/src/interpreter.cpp b/mozilla/js2/src/interpreter.cpp index 83a4baebd6a..de5a853f8a1 100644 --- a/mozilla/js2/src/interpreter.cpp +++ b/mozilla/js2/src/interpreter.cpp @@ -233,8 +233,7 @@ static JSValue less_Default(const JSValue& r1, const JSValue& r2) JSValue lv = r1.toPrimitive(JSValue::Number); JSValue rv = r2.toPrimitive(JSValue::Number); if (lv.isString() && rv.isString()) { - // XXX FIXME urgh, call w_strcmp ??? on a JSString ??? - return JSValue(double(lv.string->compare(*rv.string) < 0)); + return JSValue(bool(lv.string->compare(*rv.string) < 0)); } else { lv = lv.toNumber(); @@ -250,8 +249,7 @@ static JSValue lessEqual_Default(const JSValue& r1, const JSValue& r2) JSValue lv = r1.toPrimitive(JSValue::Number); JSValue rv = r2.toPrimitive(JSValue::Number); if (lv.isString() && rv.isString()) { - // XXX FIXME urgh, call w_strcmp ??? on a JSString ??? - return JSValue(); + return JSValue(bool(lv.string->compare(*rv.string) <= 0)); } else { lv = lv.toNumber(); @@ -267,8 +265,7 @@ static JSValue equal_Default(const JSValue& r1, const JSValue& r2) JSValue lv = r1.toPrimitive(JSValue::Number); JSValue rv = r2.toPrimitive(JSValue::Number); if (lv.isString() && rv.isString()) { - // XXX FIXME urgh, call w_strcmp ??? on a JSString ??? - return JSValue(); + return JSValue(bool(lv.string->compare(*rv.string) == 0)); } else { lv = lv.toNumber(); @@ -530,6 +527,37 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) } } + case STATIC_CALL: + { + StaticCall* call = static_cast(instruction); + ASSERT(op2(call)->getScope()->getProperty(*op3(call)).isFunction()); + JSFunction *target = op2(call)->getScope()->getProperty(*op3(call)).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(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 CALL: { Call* call = static_cast(instruction); diff --git a/mozilla/js2/src/vmtypes.h b/mozilla/js2/src/vmtypes.h index be7bbe01a45..f06ed4081ee 100644 --- a/mozilla/js2/src/vmtypes.h +++ b/mozilla/js2/src/vmtypes.h @@ -107,6 +107,7 @@ namespace VM { SHIFTLEFT, /* dest, source1, source2 */ SHIFTRIGHT, /* dest, source1, source2 */ SLOT_XCR, /* dest, source, slot number, value */ + STATIC_CALL, /* result, target class, name, args */ STATIC_XCR, /* dest, class, name, value */ STRICT_EQ, /* dest, source1, source2 */ STRICT_NE, /* dest, source1, source2 */ @@ -179,6 +180,7 @@ namespace VM { "SHIFTLEFT ", "SHIFTRIGHT ", "SLOT_XCR ", + "STATIC_CALL ", "STATIC_XCR ", "STRICT_EQ ", "STRICT_NE ", @@ -1125,6 +1127,22 @@ namespace VM { } }; + class StaticCall : public Instruction_4 { + public: + /* result, target class, name, args */ + StaticCall (TypedRegister aOp1, JSClass* aOp2, const StringAtom* aOp3, RegisterList aOp4) : + Instruction_4 + (STATIC_CALL, aOp1, aOp2, aOp3, aOp4) {}; + virtual Formatter& print(Formatter& f) { + f << opcodeNames[STATIC_CALL] << "\t" << "R" << mOp1.first << ", " << "'" << *mOp2 << "'" << ", " << "'" << *mOp3 << "'" << ", " << mOp4; + return f; + } + virtual Formatter& printOperands(Formatter& f, const JSValues& registers) { + f << "R" << mOp1.first << '=' << registers[mOp1.first] << ", " << ArgList(mOp4, registers); + return f; + } + }; + class StaticXcr : public Instruction_4 { public: /* dest, class, index, value */ @@ -1295,7 +1313,6 @@ namespace VM { /* print() and printOperands() inherited from Arithmetic */ }; - } /* namespace VM */ } /* namespace JavaScript */ diff --git a/mozilla/js2/tests/cpp/js2_shell.cpp b/mozilla/js2/tests/cpp/js2_shell.cpp index e217d10103f..53272b06cb2 100644 --- a/mozilla/js2/tests/cpp/js2_shell.cpp +++ b/mozilla/js2/tests/cpp/js2_shell.cpp @@ -123,6 +123,24 @@ static JSValue print(const JSValues &argv) return kUndefinedValue; } +static JSValue dump(const JSValues &argv) +{ + size_t n = argv.size(); + if (n > 1) { // the 'this' parameter is un-interesting + if (argv[1].isFunction()) { + JSFunction *f = static_cast(argv[1].function); + if (f->isNative()) + stdOut << "Native function"; + else + stdOut << *f->getICode(); + } + else + stdOut << "Not a function"; + } + stdOut << "\n"; + return kUndefinedValue; +} + static ICodeModule* genCode(Context &cx, StmtNode *p, const String &fileName) { ICodeGenerator icg(&cx.getWorld(), cx.getGlobalObject()); @@ -221,6 +239,7 @@ static void readEvalPrint(FILE *in, World &world) jsd.attachToContext (&cx); #endif global.defineNativeFunction(world.identifiers[widenCString("print")], print); + global.defineNativeFunction(world.identifiers[widenCString("dump")], dump); global.defineNativeFunction(world.identifiers[widenCString("load")], load); String buffer; diff --git a/mozilla/js2/tools/gencode.pl b/mozilla/js2/tools/gencode.pl index b883bc219f1..344192d191b 100644 --- a/mozilla/js2/tools/gencode.pl +++ b/mozilla/js2/tools/gencode.pl @@ -273,6 +273,12 @@ $ops{"CALL"} = rem => "result, target, name, args", params => [ ("TypedRegister" , "TypedRegister", "const StringAtom*", "RegisterList") ] }; +$ops{"STATIC_CALL"} = + { + super => "Instruction_4", + rem => "result, target class, name, args", + params => [ ("TypedRegister" , "JSClass*", "const StringAtom*", "RegisterList") ] + }; $ops{"METHOD_CALL"} = { super => "Instruction_4",