Commit 60232cc7 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

jscript: Always jump to finally block from OP_pop_exept when available.

parent 685cd437
...@@ -1399,8 +1399,9 @@ static HRESULT pop_to_stat(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx) ...@@ -1399,8 +1399,9 @@ static HRESULT pop_to_stat(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx)
return hres; return hres;
stack_pop = 0; stack_pop = 0;
} }
if(!push_instr(ctx, OP_pop_except)) hres = push_instr_uint(ctx, OP_pop_except, ctx->code_off+1);
return E_OUTOFMEMORY; if(FAILED(hres))
return hres;
} }
stack_pop += iter->stack_use; stack_pop += iter->stack_use;
} }
...@@ -1688,9 +1689,8 @@ static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement ...@@ -1688,9 +1689,8 @@ static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement
/* ECMA-262 3rd Edition 12.14 */ /* ECMA-262 3rd Edition 12.14 */
static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat) static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
{ {
statement_ctx_t try_ctx = {0, FALSE, TRUE}, catch_ctx = {0, TRUE, FALSE}; statement_ctx_t try_ctx = {0, FALSE, TRUE}, finally_ctx = {2, FALSE, FALSE};
statement_ctx_t finally_ctx = {2, FALSE, FALSE}; unsigned push_except, finally_off = 0, catch_off = 0, pop_except, catch_pop_except = 0;
unsigned push_except, finally_off = 0, catch_off = 0;
BSTR ident; BSTR ident;
HRESULT hres; HRESULT hres;
...@@ -1706,24 +1706,19 @@ static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat) ...@@ -1706,24 +1706,19 @@ static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
ident = NULL; ident = NULL;
} }
instr_ptr(ctx, push_except)->u.arg[1].bstr = ident;
if(!stat->catch_block)
try_ctx.stack_use = 2;
hres = compile_statement(ctx, &try_ctx, stat->try_statement); hres = compile_statement(ctx, &try_ctx, stat->try_statement);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
if(!push_instr(ctx, OP_pop_except)) pop_except = push_instr(ctx, OP_pop_except);
if(!pop_except)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if(stat->catch_block) { if(stat->catch_block) {
unsigned jmp_finally; statement_ctx_t catch_ctx = {0, TRUE, stat->finally_statement != NULL};
jmp_finally = push_instr(ctx, OP_jmp); if(stat->finally_statement)
if(!jmp_finally) catch_ctx.using_except = TRUE;
return E_OUTOFMEMORY;
catch_off = ctx->code_off; catch_off = ctx->code_off;
...@@ -1738,21 +1733,31 @@ static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat) ...@@ -1738,21 +1733,31 @@ static HRESULT compile_try_statement(compiler_ctx_t *ctx, try_statement_t *stat)
if(!push_instr(ctx, OP_pop_scope)) if(!push_instr(ctx, OP_pop_scope))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
set_arg_uint(ctx, jmp_finally, ctx->code_off); if(stat->finally_statement) {
}else { catch_pop_except = push_instr(ctx, OP_pop_except);
set_arg_uint(ctx, push_except, ctx->code_off); if(!catch_pop_except)
return E_OUTOFMEMORY;
}
} }
if(stat->finally_statement) { if(stat->finally_statement) {
/*
* finally block expects two elements on the stack, which may be:
* - (true, return_addr) set by OP_pop_except, OP_end_finally jumps back to passed addres
* - (false, exception_value) set when unwinding an exception, which OP_end_finally rethrows
*/
finally_off = ctx->code_off; finally_off = ctx->code_off;
hres = compile_statement(ctx, stat->catch_block ? NULL : &finally_ctx, stat->finally_statement); hres = compile_statement(ctx, &finally_ctx, stat->finally_statement);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
if(!stat->catch_block && !push_instr(ctx, OP_end_finally)) if(!push_instr(ctx, OP_end_finally))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
instr_ptr(ctx, pop_except)->u.arg[0].uint = ctx->code_off;
if(catch_pop_except)
instr_ptr(ctx, catch_pop_except)->u.arg[0].uint = ctx->code_off;
instr_ptr(ctx, push_except)->u.arg[0].uint = catch_off; instr_ptr(ctx, push_except)->u.arg[0].uint = catch_off;
instr_ptr(ctx, push_except)->u.arg[1].uint = finally_off; instr_ptr(ctx, push_except)->u.arg[1].uint = finally_off;
return S_OK; return S_OK;
......
...@@ -901,28 +901,14 @@ static HRESULT interp_push_except(script_ctx_t *ctx) ...@@ -901,28 +901,14 @@ static HRESULT interp_push_except(script_ctx_t *ctx)
const unsigned finally_off = get_op_uint(ctx, 1); const unsigned finally_off = get_op_uint(ctx, 1);
call_frame_t *frame = ctx->call_ctx; call_frame_t *frame = ctx->call_ctx;
except_frame_t *except; except_frame_t *except;
unsigned stack_top;
TRACE("\n"); TRACE("\n");
stack_top = ctx->stack_top;
if(!catch_off) {
HRESULT hres;
hres = stack_push(ctx, jsval_bool(TRUE));
if(FAILED(hres))
return hres;
hres = stack_push(ctx, jsval_bool(TRUE));
if(FAILED(hres))
return hres;
}
except = heap_alloc(sizeof(*except)); except = heap_alloc(sizeof(*except));
if(!except) if(!except)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
except->stack_top = stack_top; except->stack_top = ctx->stack_top;
except->scope = frame->scope; except->scope = frame->scope;
except->catch_off = catch_off; except->catch_off = catch_off;
except->finally_off = finally_off; except->finally_off = finally_off;
...@@ -934,22 +920,41 @@ static HRESULT interp_push_except(script_ctx_t *ctx) ...@@ -934,22 +920,41 @@ static HRESULT interp_push_except(script_ctx_t *ctx)
/* ECMA-262 3rd Edition 12.14 */ /* ECMA-262 3rd Edition 12.14 */
static HRESULT interp_pop_except(script_ctx_t *ctx) static HRESULT interp_pop_except(script_ctx_t *ctx)
{ {
const unsigned ret_off = get_op_uint(ctx, 0);
call_frame_t *frame = ctx->call_ctx; call_frame_t *frame = ctx->call_ctx;
except_frame_t *except; except_frame_t *except;
unsigned finally_off;
TRACE("\n"); TRACE("%u\n", ret_off);
except = frame->except_frame; except = frame->except_frame;
assert(except != NULL); assert(except != NULL);
finally_off = except->finally_off;
frame->except_frame = except->next; frame->except_frame = except->next;
heap_free(except); heap_free(except);
if(finally_off) {
HRESULT hres;
hres = stack_push(ctx, jsval_number(ret_off));
if(FAILED(hres))
return hres;
hres = stack_push(ctx, jsval_bool(TRUE));
if(FAILED(hres))
return hres;
frame->ip = finally_off;
}else {
frame->ip = ret_off;
}
return S_OK; return S_OK;
} }
/* ECMA-262 3rd Edition 12.14 */ /* ECMA-262 3rd Edition 12.14 */
static HRESULT interp_end_finally(script_ctx_t *ctx) static HRESULT interp_end_finally(script_ctx_t *ctx)
{ {
call_frame_t *frame = ctx->call_ctx;
jsval_t v; jsval_t v;
TRACE("\n"); TRACE("\n");
...@@ -964,7 +969,9 @@ static HRESULT interp_end_finally(script_ctx_t *ctx) ...@@ -964,7 +969,9 @@ static HRESULT interp_end_finally(script_ctx_t *ctx)
return DISP_E_EXCEPTION; return DISP_E_EXCEPTION;
} }
stack_pop(ctx); v = stack_pop(ctx);
assert(is_number(v));
frame->ip = get_number(v);
return S_OK; return S_OK;
} }
...@@ -2676,7 +2683,6 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres) ...@@ -2676,7 +2683,6 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres)
except_frame = frame->except_frame; except_frame = frame->except_frame;
catch_off = except_frame->catch_off; catch_off = except_frame->catch_off;
frame->except_frame = except_frame->next;
assert(except_frame->stack_top <= ctx->stack_top); assert(except_frame->stack_top <= ctx->stack_top);
stack_popn(ctx, ctx->stack_top - except_frame->stack_top); stack_popn(ctx, ctx->stack_top - except_frame->stack_top);
...@@ -2691,7 +2697,13 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres) ...@@ -2691,7 +2697,13 @@ static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres)
ctx->ei.val = jsval_undefined(); ctx->ei.val = jsval_undefined();
clear_ei(ctx); clear_ei(ctx);
heap_free(except_frame); /* keep current except_frame if we're entering catch block with finally block associated */
if(catch_off && except_frame->finally_off) {
except_frame->catch_off = 0;
}else {
frame->except_frame = except_frame->next;
heap_free(except_frame);
}
hres = stack_push(ctx, except_val); hres = stack_push(ctx, except_val);
if(FAILED(hres)) if(FAILED(hres))
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
X(delete_ident,1,ARG_BSTR, 0) \ X(delete_ident,1,ARG_BSTR, 0) \
X(div, 1, 0,0) \ X(div, 1, 0,0) \
X(double, 1, ARG_DBL, 0) \ X(double, 1, ARG_DBL, 0) \
X(end_finally,1, 0,0) \ X(end_finally,0, 0,0) \
X(enter_catch,1, ARG_BSTR, 0) \ X(enter_catch,1, ARG_BSTR, 0) \
X(eq, 1, 0,0) \ X(eq, 1, 0,0) \
X(eq2, 1, 0,0) \ X(eq2, 1, 0,0) \
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
X(obj_prop, 1, ARG_BSTR, 0) \ X(obj_prop, 1, ARG_BSTR, 0) \
X(or, 1, 0,0) \ X(or, 1, 0,0) \
X(pop, 1, ARG_UINT, 0) \ X(pop, 1, ARG_UINT, 0) \
X(pop_except, 1, 0,0) \ X(pop_except, 0, ARG_ADDR, 0) \
X(pop_scope, 1, 0,0) \ X(pop_scope, 1, 0,0) \
X(postinc, 1, ARG_INT, 0) \ X(postinc, 1, ARG_INT, 0) \
X(preinc, 1, ARG_INT, 0) \ X(preinc, 1, ARG_INT, 0) \
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
X(typeofid, 1, 0,0) \ X(typeofid, 1, 0,0) \
X(typeofident,1, 0,0) \ X(typeofident,1, 0,0) \
X(refval, 1, 0,0) \ X(refval, 1, 0,0) \
X(ret, 0, 0,0) \ X(ret, 0, ARG_UINT, 0) \
X(setret, 1, 0,0) \ X(setret, 1, 0,0) \
X(sub, 1, 0,0) \ X(sub, 1, 0,0) \
X(undefined, 1, 0,0) \ X(undefined, 1, 0,0) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment