зеркало из https://github.com/mozilla/gecko-dev.git
More try/catch magic.
This commit is contained in:
Родитель
2d711c26ac
Коммит
1ad15ae47f
|
@ -43,6 +43,7 @@
|
|||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
|
||||
#include "reader.h"
|
||||
#include "parser.h"
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
|
@ -97,27 +98,26 @@ namespace MetaData {
|
|||
}
|
||||
}
|
||||
catch (Exception &jsx) {
|
||||
#if 0
|
||||
if (mTryStack.size() > 0) {
|
||||
HandlerData *hndlr = (HandlerData *)mTryStack.top();
|
||||
Activation *curAct = (mActivationStack.size() > 0) ? mActivationStack.top() : NULL;
|
||||
ActivationFrame *curAct = (activationStackEmpty()) ? NULL : (activationStackTop - 1);
|
||||
|
||||
js2val x;
|
||||
if (curAct != hndlr->mActivation) {
|
||||
ASSERT(mActivationStack.size() > 0);
|
||||
Activation *prev;// = mActivationStack.top();
|
||||
ASSERT(!activationStackEmpty());
|
||||
ActivationFrame *prev;
|
||||
do {
|
||||
prev = curAct;
|
||||
if (prev->mPC == NULL) {
|
||||
if (prev->pc == NULL) {
|
||||
// Yikes! the exception is getting thrown across a re-invocation
|
||||
// of the interpreter loop.
|
||||
throw jsx;
|
||||
}
|
||||
mActivationStack.pop();
|
||||
curAct = mActivationStack.top();
|
||||
curAct = --activationStackTop;
|
||||
} while (hndlr->mActivation != curAct);
|
||||
if (jsx.hasKind(Exception::userException)) // snatch the exception before the stack gets clobbered
|
||||
x = popValue();
|
||||
x = pop();
|
||||
/*
|
||||
mNamespaceList = prev->mNamespaceList;
|
||||
mCurModule = prev->mModule;
|
||||
endPC = mCurModule->mCodeBase + mCurModule->mLength;
|
||||
|
@ -126,12 +126,13 @@ namespace MetaData {
|
|||
mStackMax = mCurModule->mStackDepth;
|
||||
mArgumentBase = prev->mArgumentBase;
|
||||
mThis = prev->mThis;
|
||||
*/
|
||||
}
|
||||
else {
|
||||
if (jsx.hasKind(Exception::userException))
|
||||
x = popValue();
|
||||
x = pop();
|
||||
}
|
||||
|
||||
#if 0
|
||||
// make sure there's a JS object for the catch clause to work with
|
||||
if (!jsx.hasKind(Exception::userException)) {
|
||||
js2val argv[1];
|
||||
|
@ -154,14 +155,13 @@ namespace MetaData {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
resizeStack(hndlr->mStackSize);
|
||||
#endif
|
||||
sp = hndlr->mStackTop;
|
||||
pc = hndlr->mPC;
|
||||
pushValue(x);
|
||||
push(x);
|
||||
}
|
||||
else
|
||||
throw jsx; //reportError(Exception::uncaughtError, "No handler for throw");
|
||||
#endif
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -409,6 +409,15 @@ namespace MetaData {
|
|||
case eLogicalNot:
|
||||
return 0;
|
||||
|
||||
case eIs: // pop expr, pop type, bush boolean
|
||||
return 1;
|
||||
|
||||
case eTry: // no exec. stack impact
|
||||
case eHandler:
|
||||
case eCallFinally:
|
||||
case eReturnFinally:
|
||||
return 0;
|
||||
|
||||
case eString:
|
||||
case eTrue:
|
||||
case eFalse:
|
||||
|
@ -601,6 +610,20 @@ namespace MetaData {
|
|||
JS2Object::mark(length_StringAtom);
|
||||
}
|
||||
|
||||
void JS2Engine::pushHandler(uint8 *pc)
|
||||
{
|
||||
ActivationFrame *curAct = (activationStackEmpty()) ? NULL : (activationStackTop - 1);
|
||||
mTryStack.push(new HandlerData(pc, sp, curAct));
|
||||
}
|
||||
|
||||
void JS2Engine::popHandler()
|
||||
{
|
||||
HandlerData *hndlr = mTryStack.top();
|
||||
mTryStack.pop();
|
||||
delete hndlr;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// XXX Only scanning dynamic properties
|
||||
//
|
||||
|
|
|
@ -118,6 +118,7 @@ enum JS2Op {
|
|||
eNew, // <argCount:u16>
|
||||
eCall, // <argCount:u16>
|
||||
eTypeof,
|
||||
eIs,
|
||||
|
||||
ePopv,
|
||||
ePop,
|
||||
|
@ -264,9 +265,20 @@ public:
|
|||
// insert 'x' before the top 'count' stack items
|
||||
void insert(js2val x, int count);
|
||||
|
||||
struct HandlerData {
|
||||
HandlerData(uint8 *pc, js2val *stackTop, ActivationFrame *curAct)
|
||||
: mPC(pc), mStackTop(stackTop), mActivation(curAct) { }
|
||||
|
||||
void pushHandler(uint8 *pc) { }
|
||||
void popHandler() { }
|
||||
uint8 *mPC;
|
||||
js2val *mStackTop;
|
||||
ActivationFrame *mActivation;
|
||||
};
|
||||
|
||||
std::stack<HandlerData *> mTryStack;
|
||||
std::stack<uint8 *> mSubStack;
|
||||
|
||||
void pushHandler(uint8 *pc);
|
||||
void popHandler();
|
||||
|
||||
void mark();
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <assert.h>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
|
@ -851,29 +852,29 @@ namespace MetaData {
|
|||
break;
|
||||
case StmtNode::Try:
|
||||
/*
|
||||
try { // [catch,finally] handler labels are pushed on try stack [eTry]
|
||||
try { // [catchLabel,finallyInvoker] handler labels are pushed on handler stack [eTry]
|
||||
<tryblock>
|
||||
} // catch handler label is popped off try stack [eHandler]
|
||||
} // catch handler label is popped off handler stack [eHandler]
|
||||
jsr finally
|
||||
jump-->finished
|
||||
|
||||
finally: // finally handler label popped off
|
||||
{ // a throw from in here goes to the 'next' handler
|
||||
finally: // finally handler label popped off here.
|
||||
{ // A throw from in here goes to the next handler on the
|
||||
// handler stack
|
||||
}
|
||||
rts
|
||||
|
||||
finallyInvoker: <---
|
||||
push exception |
|
||||
jsr finally |--- the handler labels
|
||||
throw exception |
|
||||
|
|
||||
catchLabel: <---
|
||||
finallyInvoker: // invoked when an exception is caught in the try block
|
||||
push exception // it arranges to call the finally block and then re-throw
|
||||
jsr finally // the exception - reaching the catch block
|
||||
throw exception
|
||||
catchLabel:
|
||||
|
||||
the incoming exception is on the top of the stack at this point
|
||||
|
||||
catch (exception) { // catch handler label popped off
|
||||
// any throw from in here must jump to the finallyInvoker
|
||||
// (i.e. not the catch handler!)
|
||||
catch (exception) { // catch handler label popped off [eHandler]
|
||||
// any throw from in here must jump to the next handler
|
||||
// (i.e. not the this same catch handler!)
|
||||
|
||||
Of the many catch clauses specified, only the one whose exception variable type
|
||||
matches the type of the incoming exception is executed...
|
||||
|
@ -941,19 +942,43 @@ namespace MetaData {
|
|||
bCon->emitBranch(eBranch, finishedLabel, p->pos);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ValidateStmt(cxt, env, t->stmt);
|
||||
if (t->finally)
|
||||
ValidateStmt(cxt, env, t->finally);
|
||||
if (t->catches) {
|
||||
bCon->setLabel(catchClauseLabel);
|
||||
bCon->emitOp(eHandler, p->pos);
|
||||
CatchClause *c = t->catches;
|
||||
// the exception object will be the only thing on the stack
|
||||
ASSERT(bCon->mStackTop == 0);
|
||||
bCon->mStackTop = 1;
|
||||
if (bCon->mStackMax < 1) bCon->mStackMax = 1;
|
||||
BytecodeContainer::LabelID nextCatch = NotALabel;
|
||||
while (c) {
|
||||
ValidateStmt(cxt, env, c->stmt);
|
||||
if (c->type)
|
||||
ValidateExpression(cxt, env, c->type);
|
||||
c = c->next;
|
||||
if (c->next && c->type) {
|
||||
nextCatch = bCon->getLabel();
|
||||
bCon->emitOp(eDup, p->pos);
|
||||
Reference *r = EvalExprNode(env, phase, c->type);
|
||||
if (r) r->emitReadBytecode(bCon, p->pos);
|
||||
bCon->emitOp(eIs, p->pos);
|
||||
bCon->emitBranch(eBranchFalse, nextCatch, p->pos);
|
||||
}
|
||||
*/
|
||||
// write the exception object (on stack top) into the named
|
||||
// local variable
|
||||
Reference *r = new LexicalReference(&c->name, false);
|
||||
r->emitWriteBytecode(bCon, p->pos);
|
||||
bCon->emitOp(ePop, p->pos);
|
||||
EvalStmt(env, phase, c->stmt);
|
||||
if (t->finally) {
|
||||
bCon->emitBranch(eCallFinally, t_finallyLabel, p->pos);
|
||||
}
|
||||
c = c->next;
|
||||
if (c) {
|
||||
bCon->emitBranch(eBranch, finishedLabel, p->pos);
|
||||
bCon->mStackTop = 1;
|
||||
if (nextCatch != NotALabel)
|
||||
bCon->setLabel(nextCatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
bCon->setLabel(finishedLabel);
|
||||
}
|
||||
break;
|
||||
case StmtNode::Return:
|
||||
|
|
|
@ -133,3 +133,15 @@
|
|||
popHandler();
|
||||
}
|
||||
break;
|
||||
|
||||
case eCallFinally:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case eReturnFinally:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
|
|
@ -189,6 +189,13 @@
|
|||
}
|
||||
break;
|
||||
|
||||
case eIs:
|
||||
{
|
||||
a = pop();
|
||||
b = pop();
|
||||
}
|
||||
break;
|
||||
|
||||
case eTypeof:
|
||||
{
|
||||
a = pop();
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
|
|
Загрузка…
Ссылка в новой задаче