From 27ebcb10151a42ff8a322edc92c00af3394c848e Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Wed, 19 Mar 2003 00:14:23 +0000 Subject: [PATCH] Fixed parameter frame leaking. --- js2/src/epimetheus.cpp | 6 ++++++ js2/src/js2engine.cpp | 14 +++++++++----- js2/src/js2engine.h | 1 + js2/src/js2metadata.cpp | 21 ++++++--------------- js2/src/js2metadata.h | 2 ++ js2/src/js2op_flowcontrol.cpp | 9 +++++---- js2/src/js2op_invocation.cpp | 4 ++-- 7 files changed, 31 insertions(+), 26 deletions(-) diff --git a/js2/src/epimetheus.cpp b/js2/src/epimetheus.cpp index 4bfe9f993e99..d4ce611d32f0 100644 --- a/js2/src/epimetheus.cpp +++ b/js2/src/epimetheus.cpp @@ -316,6 +316,12 @@ js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint DynamicPropertyBinding *dpb = *dpi; stdOut << "\t" << dpb->name << " = " << *meta->toString(dpb->v.value) << "\n"; } + if (pInst->type == meta->functionClass) { + FunctionWrapper *fWrap = (checked_cast(fObj))->fWrap; + stdOut << "Function:" << "\n"; + stdOut << "Environment depth " << fWrap->env->getSize() << "\n"; + dumpBytecode(fWrap->bCon); + } } } } diff --git a/js2/src/js2engine.cpp b/js2/src/js2engine.cpp index 36f23c3eecfa..3d997aa63829 100644 --- a/js2/src/js2engine.cpp +++ b/js2/src/js2engine.cpp @@ -561,7 +561,9 @@ namespace MetaData { for (uint32 i = 0; i < (30 - bCon->fName.length()); i++) stdOut << " "; } - printFormat(stdOut, "%.4d %.4d ", pc - start, (int32)(engine->sp - engine->execStack)); + printFormat(stdOut, "%.4d %.4d %.4d ", pc - start, + (int32)(engine->sp - engine->execStack), + (int32)(engine->activationStackTop - engine->activationStack)); } else printFormat(stdOut, "%.4d ", pc - start); @@ -859,10 +861,10 @@ namespace MetaData { activationStackTop->bCon = bCon; activationStackTop->pc = pc; activationStackTop->phase = phase; -// activationStackTop->topFrame = meta->env->getTopFrame(); activationStackTop->execStackBase = stackBase; activationStackTop->retval = returnVal; - activationStackTop->env = meta->env; + activationStackTop->env = meta->env; // save current env. + activationStackTop->topFrame = env->getTopFrame(); // remember how big the new env. is supposed to be activationStackTop++; bCon = new_bCon; if ((int32)bCon->getMaxStack() >= (execStackLimit - sp)) { @@ -888,9 +890,11 @@ namespace MetaData { bCon = activationStackTop->bCon; pc = activationStackTop->pc; phase = activationStackTop->phase; + // reset the env. top + while (meta->env->getTopFrame() != activationStackTop->topFrame) + meta->env->removeTopFrame(); + // reset to previous env. meta->env = activationStackTop->env; -// while (meta->env->getTopFrame() != activationStackTop->topFrame) -// meta->env->removeTopFrame(); sp = execStack + activationStackTop->execStackBase; if (!JS2VAL_IS_VOID(activationStackTop->retval)) // XXX might need an actual 'returnValue' flag instead retval = activationStackTop->retval; diff --git a/js2/src/js2engine.h b/js2/src/js2engine.h index 443b7eb70382..666e0e902e58 100644 --- a/js2/src/js2engine.h +++ b/js2/src/js2engine.h @@ -273,6 +273,7 @@ public: js2val retval; uint32 execStackBase; Environment *env; + Frame *topFrame; }; void jsr(Phase execPhase, BytecodeContainer *bCon, uint32 stackBase, js2val returnVal, Environment *env); bool activationStackEmpty() { return (activationStackTop == activationStack); } diff --git a/js2/src/js2metadata.cpp b/js2/src/js2metadata.cpp index 7b6af60fb793..6a1db37b05e4 100644 --- a/js2/src/js2metadata.cpp +++ b/js2/src/js2metadata.cpp @@ -263,7 +263,8 @@ namespace MetaData { GoStmtNode *g = checked_cast(p); g->blockCount = 0; g->tgtID = -1; - for (TargetListReverseIterator si = targetList.rbegin(), end = targetList.rend(); (g->tgtID == -1) && (si != end); si++) { + for (TargetListReverseIterator si = targetList.rbegin(), end = targetList.rend(); + ((g->tgtID == -1) && (si != end)); si++) { if (g->name) { // Make sure the name is on the targetList as a viable break target... // (only label statements can introduce names) @@ -301,14 +302,13 @@ namespace MetaData { g->tgtID = f->breakLabelID; } break; - case StmtNode::Switch: + case StmtNode::Switch: { SwitchStmtNode *s = checked_cast(*si); g->tgtID = s->breakLabelID; } break; } - break; } } if (g->tgtID == -1) @@ -320,7 +320,8 @@ namespace MetaData { GoStmtNode *g = checked_cast(p); g->blockCount = 0; g->tgtID = -1; - for (TargetListIterator si = targetList.begin(), end = targetList.end(); (g->tgtID == -1) && (si != end); si++) { + for (TargetListIterator si = targetList.begin(), end = targetList.end(); + ((g->tgtID == -1) && (si != end)); si++) { if (g->name) { // Make sure the name is on the targetList as a viable continue target... if ((*si)->getKind() == StmtNode::label) { @@ -351,7 +352,6 @@ namespace MetaData { g->tgtID = f->continueLabelID; } } - break; } } if (g->tgtID == -1) @@ -749,7 +749,7 @@ namespace MetaData { { GoStmtNode *g = checked_cast(p); bCon->emitBranch(eBreak, g->tgtID, p->pos); -// bCon-> + bCon->addShort(g->blockCount); } break; case StmtNode::ForIn: @@ -813,7 +813,6 @@ namespace MetaData { v->emitWriteBytecode(bCon, p->pos); bCon->emitOp(ePop, p->pos); // clear iterator value from stack SetupStmt(env, phase, f->stmt); - targetList.pop_back(); bCon->setLabel(f->continueLabelID); bCon->emitOp(eNext, p->pos); bCon->emitBranch(eBranchTrue, loopTop, p->pos); @@ -832,9 +831,7 @@ 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); @@ -915,7 +912,6 @@ 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) { @@ -926,7 +922,6 @@ namespace MetaData { SetupStmt(env, phase, s); s = s->next; } - targetList.pop_back(); bCon->setLabel(sw->breakLabelID); } @@ -937,9 +932,7 @@ 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); @@ -952,9 +945,7 @@ 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/js2/src/js2metadata.h b/js2/src/js2metadata.h index 8abaf2c515a3..401362f98073 100644 --- a/js2/src/js2metadata.h +++ b/js2/src/js2metadata.h @@ -608,6 +608,8 @@ public: void markChildren(); + uint32 getSize() { return frameList.size(); } + private: FrameList frameList; }; diff --git a/js2/src/js2op_flowcontrol.cpp b/js2/src/js2op_flowcontrol.cpp index f1a1a7d6d193..20165b3d336c 100644 --- a/js2/src/js2op_flowcontrol.cpp +++ b/js2/src/js2op_flowcontrol.cpp @@ -66,11 +66,12 @@ case eBreak: { + // don't update the pc in order to get the blockcount + // since the branch calculation doesn't include that. int32 offset = BytecodeContainer::getOffset(pc); - pc += sizeof(int32); - uint32 blockCount = BytecodeContainer::getShort(pc); - pc += sizeof(short); - // + uint32 blockCount = BytecodeContainer::getShort(pc + sizeof(int32)); + for (uint32 i = 0; i < blockCount; i++) + meta->env->removeTopFrame(); pc += offset; } break; diff --git a/js2/src/js2op_invocation.cpp b/js2/src/js2op_invocation.cpp index 628a4f13bb4d..f97ba4bcb0df 100644 --- a/js2/src/js2op_invocation.cpp +++ b/js2/src/js2op_invocation.cpp @@ -210,7 +210,7 @@ if (pc == NULL) return retval; push(retval); - } + } break; case eReturnVoid: @@ -219,7 +219,7 @@ if (pc == NULL) return retval; push(retval); - } + } break; case ePushFrame: