This commit is contained in:
rogerl%netscape.com 2002-10-21 22:33:41 +00:00
Родитель 2d711c26ac
Коммит 1ad15ae47f
12 изменённых файлов: 127 добавлений и 41 удалений

Просмотреть файл

@ -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"