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