From f38cc3c2b59fc53a1518f3d19a022b34275f7e11 Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Thu, 19 Jun 2003 21:43:15 +0000 Subject: [PATCH] Performance updates git-svn-id: svn://10.0.0.236/trunk@143950 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js2/src/js2engine.cpp | 7 +++ mozilla/js2/src/js2engine.h | 3 + mozilla/js2/src/js2metadata.cpp | 91 ++++++++++++++++++++++------ mozilla/js2/src/js2metadata.h | 9 ++- mozilla/js2/src/js2op_arithmetic.cpp | 13 +++- mozilla/js2/src/parser.h | 1 - mozilla/js2/src/world.h | 4 +- 7 files changed, 101 insertions(+), 27 deletions(-) diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index 1f226b28418..6a5f2d08693 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -688,6 +688,9 @@ namespace MetaData { { eSlotPreInc, "SlotPreInc", U16 }, // { eSlotPreDec, "SlotPreDec", U16 }, // + + { eNop, "Nop", 0 }, + }; uint8 *printInstruction(uint8 *pc, uint8 *start, BytecodeContainer *bCon, JS2Engine *engine) @@ -1009,6 +1012,10 @@ namespace MetaData { case eBracketWriteRef: // pop base and index, leave value return -2; + + case eNop: + return 0; + default: ASSERT(false); } diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 98f392ca582..d7c006ae24a 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -190,6 +190,9 @@ enum JS2Op { eSlotPreInc, // eSlotPreDec, // + + eNop + }; diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index 7b634e69fc7..22246bce2cb 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -250,6 +250,7 @@ namespace MetaData { { BlockStmtNode *b = checked_cast(p); b->compileFrame = new (this) BlockFrame(); + b->compileFrame->isFunctionFrame = (env->getTopFrame()->kind == ParameterFrameKind); bCon->saveFrame(b->compileFrame); // stash this frame so it doesn't get gc'd before eval pass. env->addFrame(b->compileFrame); targetList.push_back(p); @@ -347,7 +348,6 @@ namespace MetaData { case StmtNode::Break: { GoStmtNode *g = checked_cast(p); - g->blockCount = 0; g->tgtID = -1; if (g->name) { // need to find the closest 'breakable' statement covered by the named label @@ -366,9 +366,6 @@ namespace MetaData { } } break; - case StmtNode::block: - g->blockCount++; - break; } } } @@ -377,9 +374,6 @@ namespace MetaData { for (TargetListReverseIterator si = targetList.rbegin(), end = targetList.rend(); ((g->tgtID == -1) && (si != end)); si++) { switch ((*si)->getKind()) { - case StmtNode::block: - g->blockCount++; - break; case StmtNode::While: case StmtNode::DoWhile: { @@ -410,7 +404,6 @@ namespace MetaData { case StmtNode::Continue: { GoStmtNode *g = checked_cast(p); - g->blockCount = 0; g->tgtID = -1; if (g->name) { // need to find the closest 'continuable' statement covered by the named label @@ -429,9 +422,6 @@ namespace MetaData { } } break; - case StmtNode::block: - g->blockCount++; - break; case StmtNode::While: case StmtNode::DoWhile: { @@ -456,9 +446,6 @@ namespace MetaData { // only some non-label statements will do StmtNode *s = *si; switch (s->getKind()) { - case StmtNode::block: - g->blockCount++; - break; case StmtNode::While: case StmtNode::DoWhile: { @@ -909,24 +896,32 @@ namespace MetaData { case StmtNode::block: case StmtNode::group: { + targetList.push_back(p); + bool pushed = false; BlockStmtNode *b = checked_cast(p); -// BlockFrame *runtimeFrame = new (this) BlockFrame(b->compileFrame); - env->addFrame(b->compileFrame); // XXX is this right? shouldn't this be the compile frame until execution occurs? - bCon->emitOp(ePushFrame, p->pos); - bCon->addFrame(b->compileFrame); + if (b->compileFrame->isFunctionFrame || b->compileFrame->localBindings.size()) { + bCon->emitOp(ePushFrame, p->pos); + bCon->addFrame(b->compileFrame); + pushed = true; + } + env->addFrame(b->compileFrame); StmtNode *bp = b->statements; while (bp) { SetupStmt(env, phase, bp); bp = bp->next; } - bCon->emitOp(ePopFrame, p->pos); + if (pushed) + bCon->emitOp(ePopFrame, p->pos); env->removeTopFrame(); + targetList.pop_back(); } break; case StmtNode::label: { LabelStmtNode *l = checked_cast(p); + targetList.push_back(p); SetupStmt(env, phase, l->stmt); + targetList.pop_back(); // labelled statements target are break targets bCon->setLabel(l->labelID); } @@ -965,7 +960,53 @@ namespace MetaData { { GoStmtNode *g = checked_cast(p); bCon->emitBranch(eBreak, g->tgtID, p->pos); - bCon->addShort(g->blockCount); + uint32 blockCount = 0; + bool foundit = false; + for (TargetListReverseIterator si = targetList.rbegin(), end = targetList.rend(); + ((si != end) && !foundit); si++) + { + switch ((*si)->getKind()) { + case StmtNode::label: + { + LabelStmtNode *l = checked_cast(*si); + if (g->tgtID == l->labelID) + foundit = true; + } + break; + case StmtNode::While: + case StmtNode::DoWhile: + { + UnaryStmtNode *w = checked_cast(*si); + if ((g->tgtID == w->breakLabelID) || (g->tgtID == w->continueLabelID)) + foundit = true; + } + break; + case StmtNode::For: + case StmtNode::ForIn: + { + ForStmtNode *f = checked_cast(*si); + if ((g->tgtID == f->breakLabelID) || (g->tgtID == f->continueLabelID)) + foundit = true; + } + break; + case StmtNode::Switch: + { + SwitchStmtNode *s = checked_cast(*si); + if (g->tgtID == s->breakLabelID) + foundit = true; + } + break; + case StmtNode::block: + { + BlockStmtNode *b = checked_cast(*si); + if (b->compileFrame->isFunctionFrame || b->compileFrame->localBindings.size()) + blockCount++; + } + break; + } + } + ASSERT(foundit); + bCon->addShort(blockCount); } break; case StmtNode::ForIn: @@ -1028,7 +1069,9 @@ namespace MetaData { } v->emitWriteBytecode(bCon, p->pos); bCon->emitOp(ePop, p->pos); // clear iterator value from stack + targetList.push_back(p); SetupStmt(env, phase, f->stmt); + targetList.pop_back(); bCon->setLabel(f->continueLabelID); bCon->emitOp(eNext, p->pos); bCon->emitBranch(eBranchTrue, loopTop, p->pos); @@ -1047,7 +1090,9 @@ namespace MetaData { if (f->expr2) bCon->emitBranch(eBranch, testLocation, p->pos); bCon->setLabel(loopTop); + targetList.push_back(p); SetupStmt(env, phase, f->stmt); + targetList.pop_back(); bCon->setLabel(f->continueLabelID); if (f->expr3) { Reference *r = SetupExprNode(env, phase, f->expr3, &exprType); @@ -1138,6 +1183,7 @@ namespace MetaData { else bCon->emitBranch(eBranch, defaultLabel, p->pos); // Now emit the contents + targetList.push_back(p); s = sw->statements; while (s) { if (s->getKind() == StmtNode::Case) { @@ -1148,6 +1194,7 @@ namespace MetaData { SetupStmt(env, phase, s); s = s->next; } + targetList.pop_back(); bCon->setLabel(sw->breakLabelID); delete frV; @@ -1159,7 +1206,9 @@ namespace MetaData { BytecodeContainer::LabelID loopTop = bCon->getLabel(); bCon->emitBranch(eBranch, w->continueLabelID, p->pos); bCon->setLabel(loopTop); + targetList.push_back(p); SetupStmt(env, phase, w->stmt); + targetList.pop_back(); bCon->setLabel(w->continueLabelID); Reference *r = SetupExprNode(env, phase, w->expr, &exprType); if (r) r->emitReadBytecode(bCon, p->pos); @@ -1172,7 +1221,9 @@ namespace MetaData { UnaryStmtNode *w = checked_cast(p); BytecodeContainer::LabelID loopTop = bCon->getLabel(); bCon->setLabel(loopTop); + targetList.push_back(p); SetupStmt(env, phase, w->stmt); + targetList.pop_back(); bCon->setLabel(w->continueLabelID); Reference *r = SetupExprNode(env, phase, w->expr, &exprType); if (r) r->emitReadBytecode(bCon, p->pos); diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index e1701c0ea58..2dfc6e2ff30 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -655,6 +655,7 @@ public: typedef BindingEntry LocalBindingEntry; + // A LocalBindingMap maps names to a list of LocalBindings. Each LocalBinding in the list // will have the same QualifiedName.name, but (potentially) different QualifiedName.namespace values typedef HashTable LocalBindingMap; @@ -1409,10 +1410,11 @@ public: class BlockFrame : public NonWithFrame { public: - BlockFrame() : NonWithFrame(BlockFrameKind) { } - BlockFrame(BlockFrame *pluralFrame) : NonWithFrame(BlockFrameKind, pluralFrame) { } + BlockFrame() : NonWithFrame(BlockFrameKind), isFunctionFrame(false) { } + BlockFrame(BlockFrame *pluralFrame) : NonWithFrame(BlockFrameKind, pluralFrame), isFunctionFrame(false) { } Plurality plurality; + bool isFunctionFrame; virtual void instantiate(Environment *env); virtual ~BlockFrame() { } @@ -1751,6 +1753,9 @@ inline bool operator!=(MetaData::LocalBindingEntry *s1, const StringAtom &s2) { inline bool operator==(MetaData::InstanceBindingEntry *s1, const StringAtom &s2) { return s1->name == s2;} inline bool operator!=(MetaData::InstanceBindingEntry *s1, const StringAtom &s2) { return s1->name != s2;} +inline HashNumber hashString(const StringAtom &s) { return s.hash; } + + }; // namespace Javascript using namespace JavaScript; diff --git a/mozilla/js2/src/js2op_arithmetic.cpp b/mozilla/js2/src/js2op_arithmetic.cpp index 5d5a3702cf2..040d600db58 100644 --- a/mozilla/js2/src/js2op_arithmetic.cpp +++ b/mozilla/js2/src/js2op_arithmetic.cpp @@ -1154,9 +1154,16 @@ pc += sizeof(short); ASSERT(slotIndex < localFrame->frameSlots->size()); a = (*localFrame->frameSlots)[slotIndex]; - float64 num = meta->toFloat64(a); - (*localFrame->frameSlots)[slotIndex] = allocNumber(num + 1.0); - pushNumber(num); + int32 i; + if (JS2VAL_IS_INT(a) && ((i = JS2VAL_TO_INT(a)) < JS2VAL_INT_MAX)) { + (*localFrame->frameSlots)[slotIndex] = INT_TO_JS2VAL(i + 1); + push(a); + } + else { + float64 num = meta->toFloat64(a); + (*localFrame->frameSlots)[slotIndex] = allocNumber(num + 1.0); + pushNumber(num); + } } break; case eFrameSlotPostDec: diff --git a/mozilla/js2/src/parser.h b/mozilla/js2/src/parser.h index ad2cc137045..0474d5867dd 100644 --- a/mozilla/js2/src/parser.h +++ b/mozilla/js2/src/parser.h @@ -644,7 +644,6 @@ namespace JavaScript { void print(PrettyPrinter &f, bool noSemi) const; #ifdef EPIMETHEUS MetaData::LabelID tgtID; - uint32 blockCount; #endif }; diff --git a/mozilla/js2/src/world.h b/mozilla/js2/src/world.h index c67f36002be..5f31c2d5e93 100644 --- a/mozilla/js2/src/world.h +++ b/mozilla/js2/src/world.h @@ -53,7 +53,9 @@ namespace JavaScript { public: Token::Kind tokenKind; // Token::Kind if this is a keyword; Token::identifier if not - explicit StringAtom(const String &s): String(s), tokenKind(Token::identifier) {} + HashNumber hash; + + explicit StringAtom(const String &s): String(s), tokenKind(Token::identifier), hash(hashString(s)) {} private: StringAtom(const StringAtom &); // No copy constructor void operator=(const StringAtom &); // No assignment operator