Module: wine Branch: master Commit: abffe88e1991ec90a368f8a67142ae57c12cc46f URL: http://source.winehq.org/git/wine.git/?a=commit;h=abffe88e1991ec90a368f8a671...
Author: Jacek Caban jacek@codeweavers.com Date: Tue Dec 27 11:16:26 2011 +0100
jscript: Added bytecode version of with statement.
---
dlls/jscript/compile.c | 36 ++++++++++++++++++++++++++++++++++++ dlls/jscript/dispex.c | 5 +++++ dlls/jscript/engine.c | 42 ++++++++++++++++++++++++++++++++++++++++++ dlls/jscript/engine.h | 2 ++ dlls/jscript/jscript.h | 1 + dlls/jscript/parser.y | 2 +- 6 files changed, 87 insertions(+), 1 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 663edf0..c2179d3 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -1097,6 +1097,40 @@ static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat) return S_OK; }
+/* ECMA-262 3rd Edition 12.10 */ +static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat) +{ + unsigned off_backup; + BOOL prev_no_fallback; + HRESULT hres; + + off_backup = ctx->code_off; + + hres = compile_expression(ctx, stat->expr); + if(FAILED(hres)) + return hres; + + if(push_instr(ctx, OP_push_scope) == -1) + return E_OUTOFMEMORY; + + prev_no_fallback = ctx->no_fallback; + ctx->no_fallback = TRUE; + hres = compile_statement(ctx, stat->statement); + ctx->no_fallback = prev_no_fallback; + if(hres == E_NOTIMPL) { + ctx->code_off = off_backup; + stat->stat.eval = with_statement_eval; + return compile_interp_fallback(ctx, &stat->stat); + } + if(FAILED(hres)) + return hres; + + if(push_instr(ctx, OP_pop_scope) == -1) + return E_OUTOFMEMORY; + + return S_OK; +} + static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat) { switch(stat->type) { @@ -1114,6 +1148,8 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat) return compile_var_statement(ctx, (var_statement_t*)stat); case STAT_WHILE: return compile_while_statement(ctx, (while_statement_t*)stat); + case STAT_WITH: + return compile_with_statement(ctx, (with_statement_t*)stat); default: return compile_interp_fallback(ctx, stat); } diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index f2d2992..0b73073 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -837,6 +837,11 @@ jsdisp_t *as_jsdisp(IDispatch *disp) return impl_from_IDispatchEx((IDispatchEx*)disp); }
+jsdisp_t *to_jsdisp(IDispatch *disp) +{ + return disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl ? impl_from_IDispatchEx((IDispatchEx*)disp) : NULL; +} + HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype) { TRACE("%p (%p)\n", dispex, prototype); diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 9f4a5a7..af15a94 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -1029,6 +1029,43 @@ HRESULT with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t return hres; }
+/* ECMA-262 3rd Edition 12.10 */ +HRESULT interp_push_scope(exec_ctx_t *ctx) +{ + IDispatch *disp; + jsdisp_t *obj; + VARIANT *v; + HRESULT hres; + + TRACE("\n"); + + v = stack_pop(ctx); + hres = to_object(ctx->parser->script, v, &disp); + VariantClear(v); + if(FAILED(hres)) + return hres; + + obj = to_jsdisp(disp); + if(!obj) { + IDispatch_Release(disp); + FIXME("disp is not jsdisp\n"); + return E_NOTIMPL; + } + + hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain); + jsdisp_release(obj); + return hres; +} + +/* ECMA-262 3rd Edition 12.10 */ +HRESULT interp_pop_scope(exec_ctx_t *ctx) +{ + TRACE("\n"); + + scope_pop(&ctx->scope_chain); + return S_OK; +} + /* ECMA-262 3rd Edition 12.12 */ HRESULT labelled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) { @@ -2955,6 +2992,7 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ { exec_ctx_t *exec_ctx = ctx->exec_ctx; unsigned prev_ip, prev_top; + scope_chain_t *prev_scope; return_type_t *prev_rt; jsexcept_t *prev_ei; jsop_t op; @@ -2970,6 +3008,7 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
prev_rt = exec_ctx->rt; prev_top = exec_ctx->top; + prev_scope = exec_ctx->scope_chain; prev_ip = exec_ctx->ip; prev_ei = exec_ctx->ei; exec_ctx->ip = stat->instr_off; @@ -2990,10 +3029,13 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
if(FAILED(hres)) { stack_popn(exec_ctx, exec_ctx->top-prev_top); + while(exec_ctx->scope_chain != prev_scope) + scope_pop(&exec_ctx->scope_chain); return hres; }
assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top); + assert(exec_ctx->scope_chain == prev_scope);
if(exec_ctx->top == prev_top) V_VT(ret) = VT_EMPTY; diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index 2f0ba53..1ca6630 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -87,8 +87,10 @@ typedef struct _func_stack { X(obj_prop, 1, ARG_BSTR, 0) \ X(or, 1, 0,0) \ X(pop, 1, 0,0) \ + X(pop_scope, 1, 0,0) \ X(postinc, 1, ARG_INT, 0) \ X(preinc, 1, ARG_INT, 0) \ + X(push_scope, 1, 0,0) \ X(regexp, 1, ARG_STR, ARG_INT) \ X(rshift, 1, 0,0) \ X(rshift2, 1, 0,0) \ diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index bd00cbe..8b1aa2d 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -190,6 +190,7 @@ static inline IDispatch *to_disp(jsdisp_t *jsdisp) }
jsdisp_t *as_jsdisp(IDispatch*); +jsdisp_t *to_jsdisp(IDispatch*);
static inline void jsdisp_addref(jsdisp_t *jsdisp) { diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 008ada2..578ae23 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -851,7 +851,7 @@ static const statement_eval_t stat_eval_table[] = { try_statement_eval, compiled_statement_eval, compiled_statement_eval, - with_statement_eval + compiled_statement_eval };
static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size)