Jacek Caban : jscript: Added bytecode version of for..in statement.
Alexandre Julliard
julliard at winehq.org
Wed Dec 28 13:44:34 CST 2011
Module: wine
Branch: master
Commit: 661241a392bb90b931e8637f4f3e28f1369bc3a1
URL: http://source.winehq.org/git/wine.git/?a=commit;h=661241a392bb90b931e8637f4f3e28f1369bc3a1
Author: Jacek Caban <jacek at codeweavers.com>
Date: Wed Dec 28 12:05:53 2011 +0100
jscript: Added bytecode version of for..in statement.
---
dlls/jscript/compile.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
dlls/jscript/engine.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++
dlls/jscript/engine.h | 1 +
dlls/jscript/parser.y | 2 +-
4 files changed, 137 insertions(+), 1 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c
index 5f25598..585520d 100644
--- a/dlls/jscript/compile.c
+++ b/dlls/jscript/compile.c
@@ -1097,6 +1097,72 @@ static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
return S_OK;
}
+/* ECMA-262 3rd Edition 12.6.4 */
+static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *stat)
+{
+ unsigned loop_addr, off_backup = ctx->code_off;
+ BOOL prev_no_fallback;
+ HRESULT hres;
+
+ if(stat->variable) {
+ hres = compile_variable_list(ctx, stat->variable);
+ if(FAILED(hres))
+ return hres;
+ }
+
+ hres = compile_expression(ctx, stat->in_expr);
+ if(FAILED(hres))
+ return hres;
+
+ if(stat->variable) {
+ hres = push_instr_bstr_uint(ctx, OP_identid, stat->variable->identifier, fdexNameEnsure);
+ if(FAILED(hres))
+ return hres;
+ }else if(is_memberid_expr(stat->expr->type)) {
+ hres = compile_memberid_expression(ctx, stat->expr, fdexNameEnsure);
+ if(FAILED(hres))
+ return hres;
+ }else {
+ hres = push_instr_uint(ctx, OP_throw, JS_E_ILLEGAL_ASSIGN);
+ if(FAILED(hres))
+ return hres;
+
+ /* FIXME: compile statement anyways when we depend on compiler to check errors */
+ return S_OK;
+ }
+
+ hres = push_instr_int(ctx, OP_int, DISPID_STARTENUM);
+ if(FAILED(hres))
+ return hres;
+
+ /* FIXME: avoid */
+ if(push_instr(ctx, OP_undefined) == -1)
+ return E_OUTOFMEMORY;
+
+ loop_addr = ctx->code_off;
+ if(push_instr(ctx, OP_forin) == -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 = forin_statement_eval;
+ return compile_interp_fallback(ctx, &stat->stat);
+ }
+ if(FAILED(hres))
+ return hres;
+
+ hres = push_instr_uint(ctx, OP_jmp, loop_addr);
+ if(FAILED(hres))
+ return hres;
+
+ instr_ptr(ctx, loop_addr)->arg1.uint = ctx->code_off;
+ return S_OK;
+}
+
/* ECMA-262 3rd Edition 12.10 */
static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat)
{
@@ -1244,6 +1310,8 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat)
return compile_expression_statement(ctx, (expression_statement_t*)stat);
case STAT_FOR:
return compile_for_statement(ctx, (for_statement_t*)stat);
+ case STAT_FORIN:
+ return compile_forin_statement(ctx, (forin_statement_t*)stat);
case STAT_IF:
return compile_if_statement(ctx, (if_statement_t*)stat);
case STAT_LABEL:
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index fbeee6f..f3268ba 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -936,6 +936,73 @@ HRESULT forin_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_
return S_OK;
}
+/* ECMA-262 3rd Edition 12.6.4 */
+static HRESULT interp_forin(exec_ctx_t *ctx)
+{
+ const HRESULT arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
+ IDispatch *var_obj, *obj = NULL;
+ IDispatchEx *dispex;
+ DISPID id, var_id;
+ BSTR name = NULL;
+ VARIANT *val;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ val = stack_pop(ctx);
+
+ assert(V_VT(stack_top(ctx)) == VT_I4);
+ id = V_I4(stack_top(ctx));
+
+ var_obj = stack_topn_objid(ctx, 1, &var_id);
+ if(!var_obj) {
+ FIXME("invalid ref\n");
+ VariantClear(val);
+ return E_FAIL;
+ }
+
+ if(V_VT(stack_topn(ctx, 3)) == VT_DISPATCH)
+ obj = V_DISPATCH(stack_topn(ctx, 3));
+
+ if(obj) {
+ hres = IDispatch_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
+ if(SUCCEEDED(hres)) {
+ hres = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, id, &id);
+ if(hres == S_OK)
+ hres = IDispatchEx_GetMemberName(dispex, id, &name);
+ IDispatchEx_Release(dispex);
+ if(FAILED(hres)) {
+ VariantClear(val);
+ return hres;
+ }
+ }else {
+ TRACE("No IDispatchEx\n");
+ }
+ }
+
+ if(name) {
+ VARIANT v;
+
+ VariantClear(val);
+
+ V_I4(stack_top(ctx)) = id;
+
+ V_VT(&v) = VT_BSTR;
+ V_BSTR(&v) = name;
+ hres = disp_propput(ctx->parser->script, var_obj, var_id, &v, ctx->ei, NULL/*FIXME*/);
+ SysFreeString(name);
+ if(FAILED(hres))
+ return hres;
+
+ ctx->ip++;
+ }else {
+ stack_popn(ctx, 4);
+ ctx->ip = arg;
+ return stack_push(ctx, val);
+ }
+ return S_OK;
+}
+
/* ECMA-262 3rd Edition 12.7 */
HRESULT continue_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
{
diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h
index 7dbaeb2..b2f2f82 100644
--- a/dlls/jscript/engine.h
+++ b/dlls/jscript/engine.h
@@ -61,6 +61,7 @@ typedef struct _func_stack {
X(double, 1, ARG_SBL, 0) \
X(eq, 1, 0,0) \
X(eq2, 1, 0,0) \
+ X(forin, 0, ARG_UINT, 0) \
X(func, 1, ARG_FUNC, 0) \
X(gt, 1, 0,0) \
X(gteq, 1, 0,0) \
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y
index 02d35bd..a184202 100644
--- a/dlls/jscript/parser.y
+++ b/dlls/jscript/parser.y
@@ -842,7 +842,7 @@ static const statement_eval_t stat_eval_table[] = {
compiled_statement_eval,
compiled_statement_eval,
compiled_statement_eval,
- forin_statement_eval,
+ compiled_statement_eval,
compiled_statement_eval,
compiled_statement_eval,
return_statement_eval,
More information about the wine-cvs
mailing list