Omit needless setjmp guard over catch block in try/catch statement.

Make the catch opcodes only set the scope chain, and add explicit
try/endtry opcodes for the catch block in try/catch/finally statements.
This commit is contained in:
Tor Andersson
2014-01-23 17:07:04 +01:00
parent 40572172a5
commit 2b209d3f55
4 changed files with 24 additions and 33 deletions

View File

@@ -666,8 +666,14 @@ static void cexit(JF, js_AstType T, js_Ast *node, js_Ast *target)
}
/* came from catch block */
if (prev == node->c) {
emit(J, F, OP_ENDCATCH);
if (node->d) cstm(J, F, node->d); /* finally */
/* ... with finally */
if (node->d) {
emit(J, F, OP_ENDCATCH);
emit(J, F, OP_ENDTRY);
cstm(J, F, node->d); /* finally */
} else {
emit(J, F, OP_ENDCATCH);
}
}
break;
}
@@ -693,25 +699,19 @@ static void ctryfinally(JF, js_Ast *trystm, js_Ast *finallystm)
static void ctrycatch(JF, js_Ast *trystm, js_Ast *catchvar, js_Ast *catchstm)
{
int L1, L2, L3;
int L1, L2;
L1 = jump(J, F, OP_TRY);
{
/* if we get here, we have caught an exception in the try block */
L2 = jump(J, F, OP_CATCH);
emitraw(J, F, addstring(J, F, catchvar->string));
{
/* if we get here, we have caught an exception in the catch block */
emit(J, F, OP_THROW); /* rethrow exception */
}
label(J, F, L2);
emitstring(J, F, OP_CATCH, catchvar->string);
cstm(J, F, catchstm);
emit(J, F, OP_ENDCATCH);
L3 = jump(J, F, OP_JUMP); /* skip past the try block */
L2 = jump(J, F, OP_JUMP); /* skip past the try block */
}
label(J, F, L1);
cstm(J, F, trystm);
emit(J, F, OP_ENDTRY);
label(J, F, L3);
label(J, F, L2);
}
static void ctrycatchfinally(JF, js_Ast *trystm, js_Ast *catchvar, js_Ast *catchstm, js_Ast *finallystm)
@@ -720,14 +720,14 @@ static void ctrycatchfinally(JF, js_Ast *trystm, js_Ast *catchvar, js_Ast *catch
L1 = jump(J, F, OP_TRY);
{
/* if we get here, we have caught an exception in the try block */
L2 = jump(J, F, OP_CATCH);
emitraw(J, F, addstring(J, F, catchvar->string));
L2 = jump(J, F, OP_TRY);
{
/* if we get here, we have caught an exception in the catch block */
cstm(J, F, finallystm); /* inline finally block */
emit(J, F, OP_THROW); /* rethrow exception */
}
label(J, F, L2);
emitstring(J, F, OP_CATCH, catchvar->string);
cstm(J, F, catchstm);
emit(J, F, OP_ENDCATCH);
L3 = jump(J, F, OP_JUMP); /* skip past the try block to the finally block */

View File

@@ -89,8 +89,9 @@ enum js_OpCode
OP_TRY, /* -ADDR- /jump/ or -ADDR- <exception> */
OP_ENDTRY,
OP_CATCH, /* -ADDR,S- /jump/ or -ADDR,S- <exception> */
OP_CATCH, /* push scope chain with exception variable */
OP_ENDCATCH,
OP_WITH,
OP_ENDWITH,

View File

@@ -651,6 +651,7 @@ void jsC_dumpfunction(js_State *J, js_Function *F)
case OP_GETPROPS:
case OP_SETPROPS:
case OP_DELPROPS:
case OP_CATCH:
pc(' ');
ps(F->strtab[*p++]);
break;
@@ -664,11 +665,6 @@ void jsC_dumpfunction(js_State *J, js_Function *F)
case OP_TRY:
printf(" %d", *p++);
break;
case OP_CATCH:
printf(" %d", *p++);
pc(' ');
ps(F->strtab[*p++]);
break;
}
nl();
@@ -713,6 +709,7 @@ void js_dumpvalue(js_State *J, js_Value v)
case JS_CNUMBER: printf("[Number %g]", v.u.object->u.number); break;
case JS_CSTRING: printf("[String'%s']", v.u.object->u.string); break;
case JS_CERROR: printf("[Error %s]", v.u.object->u.string); break;
case JS_CITERATOR: printf("[Iterator %p]", v.u.object); break;
default: printf("[Object %p]", v.u.object); break;
}
break;

19
jsrun.c
View File

@@ -822,23 +822,16 @@ static void jsR_run(js_State *J, js_Function *F)
break;
case OP_CATCH:
offset = *pc++;
str = ST[*pc++];
if (js_trypc(J, pc)) {
pc = J->trybuf[J->trylen].pc;
} else {
obj = jsV_newobject(J, JS_COBJECT, NULL);
js_pushobject(J, obj);
js_rot2(J);
js_setproperty(J, -2, str);
J->E = jsR_newenvironment(J, obj, J->E);
js_pop(J, 1);
pc = pcstart + offset;
}
obj = jsV_newobject(J, JS_COBJECT, NULL);
js_pushobject(J, obj);
js_rot2(J);
js_setproperty(J, -2, str);
J->E = jsR_newenvironment(J, obj, J->E);
js_pop(J, 1);
break;
case OP_ENDCATCH:
js_endtry(J);
J->E = J->E->outer;
break;