Jacek Caban : jscript: Use already running interpreter for execution of member source function.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Mar 30 10:00:30 CDT 2016


Module: wine
Branch: master
Commit: 66632091bf31929dc50fdaf60cab819ff0088157
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=66632091bf31929dc50fdaf60cab819ff0088157

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Mar 29 17:49:01 2016 +0200

jscript: Use already running interpreter for execution of member source function.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/jscript/dispex.c   |  9 +++++++--
 dlls/jscript/engine.c   | 36 ++++++++++++++++++++++++++++--------
 dlls/jscript/engine.h   |  1 +
 dlls/jscript/function.c | 12 ++++++++----
 dlls/jscript/jscript.h  |  8 ++++++++
 5 files changed, 52 insertions(+), 14 deletions(-)

diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 40e1749..5abb3a7 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -377,6 +377,7 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t
         if(prop->name || This->builtin_info->class != JSCLASS_FUNCTION) {
             vdisp_t vthis;
 
+            flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
             if(jsthis)
                 set_disp(&vthis, jsthis);
             else
@@ -1060,7 +1061,7 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsig
 {
     HRESULT hres;
 
-    assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT)));
+    assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT|DISPATCH_JSCRIPT_INTERNAL_MASK)));
 
     if(is_class(jsfunc, JSCLASS_FUNCTION)) {
         hres = Function_invoke(jsfunc, jsthis, flags, argc, argv, r);
@@ -1073,6 +1074,7 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsig
         }
 
         set_disp(&vdisp, jsthis);
+        flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
         hres = jsfunc->builtin_info->value_prop.invoke(jsfunc->ctx, &vdisp, flags, argc, argv, r);
         vdisp_release(&vdisp);
     }
@@ -1123,6 +1125,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
         return hres;
     }
 
+    flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
     if(ret && argc)
         flags |= DISPATCH_PROPERTYGET;
 
@@ -1187,6 +1190,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
         hres = variant_to_jsval(&retv, ret);
         VariantClear(&retv);
     }
+
     return hres;
 }
 
@@ -1200,7 +1204,7 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
     unsigned i;
     HRESULT hres;
 
-    assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT)));
+    assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT|DISPATCH_JSCRIPT_INTERNAL_MASK)));
 
     jsdisp = iface_to_jsdisp((IUnknown*)disp);
     if(jsdisp) {
@@ -1209,6 +1213,7 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
         return hres;
     }
 
+    flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
     if(r && argc && flags == DISPATCH_METHOD)
         flags |= DISPATCH_PROPERTYGET;
 
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index e600e62..31c592c 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -1002,7 +1002,7 @@ static HRESULT interp_call_member(script_ctx_t *ctx)
         return throw_type_error(ctx, id, NULL);
 
     clear_ret(frame);
-    return disp_call(ctx, obj, id, DISPATCH_METHOD,
+    return disp_call(ctx, obj, id, DISPATCH_METHOD | DISPATCH_JSCRIPT_CALLEREXECSSOURCE,
             argn, stack_args(ctx, argn), do_ret ? &frame->ret : NULL);
 }
 
@@ -2403,21 +2403,25 @@ static void release_call_frame(call_frame_t *frame)
 
 static HRESULT unwind_exception(script_ctx_t *ctx, HRESULT exception_hres)
 {
-    call_frame_t *frame = ctx->call_ctx;
     except_frame_t *except_frame;
+    call_frame_t *frame;
     jsval_t except_val;
     BSTR ident;
     HRESULT hres;
 
-    if(!frame->except_frame) {
+    for(frame = ctx->call_ctx; !frame->except_frame; frame = ctx->call_ctx) {
+        DWORD flags;
+
         while(frame->scope != frame->base_scope)
             scope_pop(&frame->scope);
 
         stack_popn(ctx, ctx->stack_top-frame->stack_base);
 
         ctx->call_ctx = frame->prev_frame;
+        flags = frame->flags;
         release_call_frame(frame);
-        return exception_hres;
+        if(!(flags & EXEC_RETURN_TO_INTERP))
+            return exception_hres;
     }
 
     except_frame = frame->except_frame;
@@ -2472,9 +2476,8 @@ static HRESULT enter_bytecode(script_ctx_t *ctx, jsval_t *r)
 
     TRACE("\n");
 
-    frame = ctx->call_ctx;
-
     while(1) {
+        frame = ctx->call_ctx;
         op = frame->bytecode->instrs[frame->ip].op;
         hres = op_funcs[op](ctx);
         if(FAILED(hres)) {
@@ -2484,14 +2487,21 @@ static HRESULT enter_bytecode(script_ctx_t *ctx, jsval_t *r)
             if(FAILED(hres))
                 return hres;
         }else if(frame->ip == -1) {
+            const DWORD return_to_interp = frame->flags & EXEC_RETURN_TO_INTERP;
+
             assert(ctx->stack_top == frame->stack_base);
             assert(frame->scope == frame->base_scope);
 
             ctx->call_ctx = frame->prev_frame;
-            if(r)
+            if(return_to_interp) {
+                clear_ret(ctx->call_ctx);
+                ctx->call_ctx->ret = steal_ret(frame);
+            }else if(r) {
                 *r = steal_ret(frame);
+            }
             release_call_frame(frame);
-            break;
+            if(!return_to_interp)
+                break;
         }else {
             frame->ip += op_move[op];
         }
@@ -2617,5 +2627,15 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi
     frame->prev_frame = ctx->call_ctx;
     ctx->call_ctx = frame;
 
+    if(flags & EXEC_RETURN_TO_INTERP) {
+        /*
+         * We're called directly from interpreter, so we may just setup call frame and return.
+         * Already running interpreter will take care of execution.
+         */
+        if(r)
+            *r = jsval_undefined();
+        return S_OK;
+    }
+
     return enter_bytecode(ctx, r);
 }
diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h
index 4c29694..4094303 100644
--- a/dlls/jscript/engine.h
+++ b/dlls/jscript/engine.h
@@ -216,6 +216,7 @@ typedef struct _call_frame_t {
 
 #define EXEC_GLOBAL            0x0001
 #define EXEC_CONSTRUCTOR       0x0002
+#define EXEC_RETURN_TO_INTERP  0x0004
 
 HRESULT exec_source(script_ctx_t*,DWORD,bytecode_t*,function_code_t*,scope_chain_t*,IDispatch*,
         jsdisp_t*,jsdisp_t*,jsdisp_t*,jsval_t*) DECLSPEC_HIDDEN;
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c
index 51d1060..55a34e1 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -202,7 +202,7 @@ static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, un
 }
 
 static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, unsigned argc, jsval_t *argv,
-        BOOL is_constructor, jsval_t *r)
+        BOOL is_constructor, BOOL caller_execs_source, jsval_t *r)
 {
     jsdisp_t *var_disp, *arg_disp;
     scope_chain_t *scope;
@@ -239,6 +239,8 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis
     if(SUCCEEDED(hres)) {
         DWORD exec_flags = 0;
 
+        if(caller_execs_source)
+            exec_flags |= EXEC_RETURN_TO_INTERP;
         if(is_constructor)
             exec_flags |= EXEC_CONSTRUCTOR;
         hres = exec_source(ctx, exec_flags, function->code, function->func_code, scope, this_obj,
@@ -277,7 +279,7 @@ static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDis
     if(function->value_proc)
         return invoke_value_proc(ctx, function, this_obj, DISPATCH_METHOD, argc, argv, r);
 
-    return invoke_source(ctx, function, this_obj, argc, argv, FALSE, r);
+    return invoke_source(ctx, function, this_obj, argc, argv, FALSE, FALSE, r);
 }
 
 static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret)
@@ -312,6 +314,7 @@ static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret)
 
 HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
 {
+    const BOOL caller_execs_source = (flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) != 0;
     FunctionInstance *function;
 
     TRACE("func %p this %p\n", func_this, jsthis);
@@ -319,6 +322,7 @@ HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsi
     assert(is_class(func_this, JSCLASS_FUNCTION));
     function = (FunctionInstance*)func_this;
 
+    flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
     if(function->value_proc)
         return invoke_value_proc(function->dispex.ctx, function, jsthis, flags, argc, argv, r);
 
@@ -330,13 +334,13 @@ HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsi
         if(FAILED(hres))
             return hres;
 
-        hres = invoke_source(function->dispex.ctx, function, to_disp(this_obj), argc, argv, TRUE, r);
+        hres = invoke_source(function->dispex.ctx, function, to_disp(this_obj), argc, argv, TRUE, FALSE, r);
         jsdisp_release(this_obj);
         return hres;
     }
 
     assert(flags == DISPATCH_METHOD);
-    return invoke_source(function->dispex.ctx, function, jsthis, argc, argv, FALSE, r);
+    return invoke_source(function->dispex.ctx, function, jsthis, argc, argv, FALSE, caller_execs_source, r);
 }
 
 static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 53272c9..cc66418 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -101,6 +101,14 @@ extern HINSTANCE jscript_hinstance DECLSPEC_HIDDEN;
 #define PROPF_CONST       0x0800
 #define PROPF_DONTDELETE  0x1000
 
+/*
+ * This is our internal dispatch flag informing calee that it's called directly from interpreter.
+ * If calee is executed as interpreted function, we may let already running interpreter to take
+ * of execution.
+ */
+#define DISPATCH_JSCRIPT_CALLEREXECSSOURCE  0x8000
+#define DISPATCH_JSCRIPT_INTERNAL_MASK      DISPATCH_JSCRIPT_CALLEREXECSSOURCE
+
 /* NOTE: Keep in sync with names in Object.toString implementation */
 typedef enum {
     JSCLASS_NONE,




More information about the wine-cvs mailing list