Module: wine Branch: master Commit: 66632091bf31929dc50fdaf60cab819ff0088157 URL: http://source.winehq.org/git/wine.git/?a=commit;h=66632091bf31929dc50fdaf60c...
Author: Jacek Caban jacek@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@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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,