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