From efccdcf4f52f81c161ed808be73419d1cd198bb7 Mon Sep 17 00:00:00 2001 From: "rogerl%netscape.com" Date: Tue, 18 Mar 2003 00:04:45 +0000 Subject: [PATCH] Modifying 'break' to skip block frames... --- js2/src/js2engine.cpp | 13 ++++++++++++- js2/src/js2engine.h | 1 + js2/src/js2metadata.cpp | 33 ++++++++++++++++++++------------- js2/src/js2op_flowcontrol.cpp | 11 +++++++++++ js2/src/parser.h | 1 + 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/js2/src/js2engine.cpp b/js2/src/js2engine.cpp index a379b9cddda9..36f23c3eecfa 100644 --- a/js2/src/js2engine.cpp +++ b/js2/src/js2engine.cpp @@ -430,7 +430,7 @@ namespace MetaData { #ifdef DEBUG - enum { BRANCH_OFFSET = 1, STR_PTR, TYPE_PTR, NAME_INDEX, FRAME_INDEX, BRANCH_PAIR, U16, FLOAT64 }; + enum { BRANCH_OFFSET = 1, STR_PTR, TYPE_PTR, NAME_INDEX, FRAME_INDEX, BRANCH_PAIR, U16, FLOAT64, BREAK_OFFSET_AND_COUNT }; struct { JS2Op op; char *name; @@ -520,6 +520,7 @@ namespace MetaData { { eBranchFalse, "BranchFalse", BRANCH_OFFSET }, // XXX save space with short and long versions instead ? { eBranchTrue, "BranchTrue", BRANCH_OFFSET }, // { eBranch, "Branch", BRANCH_OFFSET }, // + { eBreak, "Break", BREAK_OFFSET_AND_COUNT }, // { eNew, "New", U16 }, // { eCall, "Call", U16 }, // { eTypeof, "Typeof", 0 }, @@ -573,6 +574,15 @@ namespace MetaData { pc += sizeof(int32); } break; + case BREAK_OFFSET_AND_COUNT: + { + int32 offset = BytecodeContainer::getOffset(pc); + stdOut << " " << offset << " --> " << (pc - start) + offset; + pc += sizeof(int32); + printFormat(stdOut, " (%d)", BytecodeContainer::getShort(pc)); + pc += sizeof(short); + } + break; case TYPE_PTR: { JS2Class *c = BytecodeContainer::getType(pc); @@ -744,6 +754,7 @@ namespace MetaData { case eReturnVoid: case eBranch: + case eBreak: return 0; case eVoid: // remove top item, push undefined diff --git a/js2/src/js2engine.h b/js2/src/js2engine.h index f9d9f0c0b7e7..443b7eb70382 100644 --- a/js2/src/js2engine.h +++ b/js2/src/js2engine.h @@ -129,6 +129,7 @@ enum JS2Op { eBranchFalse, // XXX save space with short and long versions instead ? eBranchTrue, // eBranch, // + eBreak, // eNew, // eCall, // eTypeof, diff --git a/js2/src/js2metadata.cpp b/js2/src/js2metadata.cpp index a72dfb5c8c2d..7b6af60fb793 100644 --- a/js2/src/js2metadata.cpp +++ b/js2/src/js2metadata.cpp @@ -161,8 +161,10 @@ namespace MetaData { b->compileFrame = new BlockFrame(); 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); ValidateStmtList(cxt, env, pl, b->statements); env->removeTopFrame(); + targetList.pop_back(); } break; case StmtNode::label: @@ -171,8 +173,8 @@ namespace MetaData { l->labelID = bCon->getLabel(); /* A labelled statement catches contained, named, 'breaks' but simply adds itself as a label for - contained iteration statements. (i.e. you can 'break' out of a labelled statement, but not 'continue' - one, however the statement label becomes a 'continuable' label for all contained iteration statements. + contained iteration statements. (i.e. one can 'break' out of a labelled statement, but not 'continue' + one, however the statement label becomes a 'continuable' label for all contained iteration statements.) */ // Make sure there is no existing break target with the same name for (TargetListIterator si = targetList.begin(), end = targetList.end(); (si != end); si++) { @@ -259,8 +261,9 @@ namespace MetaData { case StmtNode::Break: { GoStmtNode *g = checked_cast(p); - bool found = false; - for (TargetListReverseIterator si = targetList.rbegin(), end = targetList.rend(); (si != end); si++) { + g->blockCount = 0; + g->tgtID = -1; + 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) @@ -268,7 +271,6 @@ namespace MetaData { LabelStmtNode *l = checked_cast(*si); if (l->name == *g->name) { g->tgtID = l->labelID; - found = true; break; } } @@ -276,6 +278,9 @@ namespace MetaData { else { // anything at all will do switch ((*si)->getKind()) { + case StmtNode::block: + g->blockCount++; + break; case StmtNode::label: { LabelStmtNode *l = checked_cast(*si); @@ -303,26 +308,25 @@ namespace MetaData { } break; } - found = true; break; } } - if (!found) + if (g->tgtID == -1) reportError(Exception::syntaxError, "No such break target available", p->pos); } break; case StmtNode::Continue: { GoStmtNode *g = checked_cast(p); - bool found = false; - for (TargetListIterator si = targetList.begin(), end = targetList.end(); (si != end); si++) { + g->blockCount = 0; + g->tgtID = -1; + 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) { LabelStmtNode *l = checked_cast(*si); if (l->name == *g->name) { g->tgtID = l->labelID; - found = true; break; } } @@ -330,6 +334,9 @@ namespace MetaData { else { // only some non-label statements will do switch ((*si)->getKind()) { + case StmtNode::block: + g->blockCount++; + break; case StmtNode::While: case StmtNode::DoWhile: { @@ -344,11 +351,10 @@ namespace MetaData { g->tgtID = f->continueLabelID; } } - found = true; break; } } - if (!found) + if (g->tgtID == -1) reportError(Exception::syntaxError, "No such break target available", p->pos); } break; @@ -742,7 +748,8 @@ namespace MetaData { case StmtNode::Continue: { GoStmtNode *g = checked_cast(p); - bCon->emitBranch(eBranch, g->tgtID, p->pos); + bCon->emitBranch(eBreak, g->tgtID, p->pos); +// bCon-> } break; case StmtNode::ForIn: diff --git a/js2/src/js2op_flowcontrol.cpp b/js2/src/js2op_flowcontrol.cpp index 7ed7063165df..f1a1a7d6d193 100644 --- a/js2/src/js2op_flowcontrol.cpp +++ b/js2/src/js2op_flowcontrol.cpp @@ -64,6 +64,17 @@ } break; + case eBreak: + { + int32 offset = BytecodeContainer::getOffset(pc); + pc += sizeof(int32); + uint32 blockCount = BytecodeContainer::getShort(pc); + pc += sizeof(short); + // + pc += offset; + } + break; + case ePop: { pop(); diff --git a/js2/src/parser.h b/js2/src/parser.h index 2991a39b6c16..b8c2a0d3f390 100644 --- a/js2/src/parser.h +++ b/js2/src/parser.h @@ -647,6 +647,7 @@ namespace JavaScript { void print(PrettyPrinter &f, bool noSemi) const; #ifdef EPIMETHEUS MetaData::LabelID tgtID; + uint32 blockCount; #endif };