Jacek Caban : jscript: Added bytecode version of with statement.
Alexandre Julliard
julliard at winehq.org
Tue Dec 27 11:27:56 CST 2011
Module: wine
Branch: master
Commit: abffe88e1991ec90a368f8a67142ae57c12cc46f
URL: http://source.winehq.org/git/wine.git/?a=commit;h=abffe88e1991ec90a368f8a67142ae57c12cc46f
Author: Jacek Caban <jacek at 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)
More information about the wine-cvs
mailing list