From 5e6faaea12130b61641f0d2efd3c81fd68f7faa6 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 16 Dec 2011 11:43:31 +0100 Subject: [PATCH] jscript: Use bytecode for object literal implementation. --- dlls/jscript/compile.c | 49 +++++++++++++++++++++ dlls/jscript/dispex.c | 8 ++++ dlls/jscript/engine.c | 98 +++++++++--------------------------------- dlls/jscript/engine.h | 4 +- dlls/jscript/jscript.h | 5 +++ dlls/jscript/jsutils.c | 47 ++++++++++++-------- dlls/jscript/parser.y | 2 +- 7 files changed, 113 insertions(+), 100 deletions(-) diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 9331910d1f6..daa18466858 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -619,6 +619,24 @@ static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal) } } +static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *str) +{ + switch(literal->type) { + case LT_STRING: + *str = compiler_alloc_bstr(ctx, literal->u.wstr); + break; + case LT_INT: + *str = int_to_bstr(literal->u.lval); + break; + case LT_DOUBLE: + return double_to_bstr(literal->u.dval, str); + default: + assert(0); + } + + return *str ? S_OK : E_OUTOFMEMORY; +} + static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr) { unsigned i, elem_cnt = expr->length; @@ -646,6 +664,35 @@ static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expressi return push_instr_uint(ctx, OP_carray, elem_cnt); } +static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr) +{ + prop_val_t *iter; + unsigned instr; + BSTR name; + HRESULT hres; + + if(push_instr(ctx, OP_new_obj) == -1) + return E_OUTOFMEMORY; + + for(iter = expr->property_list; iter; iter = iter->next) { + hres = literal_as_bstr(ctx, iter->name, &name); + if(FAILED(hres)) + return hres; + + hres = compile_expression(ctx, iter->value); + if(FAILED(hres)) + return hres; + + instr = push_instr(ctx, OP_obj_prop); + if(instr == -1) + return E_OUTOFMEMORY; + + instr_ptr(ctx, instr)->arg1.bstr = name; + } + + return S_OK; +} + static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr) { unsigned instr; @@ -765,6 +812,8 @@ static HRESULT compile_expression_noret(compiler_ctx_t *ctx, expression_t *expr, return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, -1); case EXPR_PREINC: return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, 1); + case EXPR_PROPVAL: + return compile_object_literal(ctx, (property_value_expression_t*)expr); case EXPR_RSHIFT: return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift); case EXPR_RRSHIFT: diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index e40f3701d9f..f2d2992e741 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + #include "jscript.h" #include "wine/unicode.h" @@ -829,6 +831,12 @@ static IDispatchExVtbl DispatchExVtbl = { DispatchEx_GetNameSpaceParent }; +jsdisp_t *as_jsdisp(IDispatch *disp) +{ + assert(disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl); + return impl_from_IDispatchEx((IDispatchEx*)disp); +} + 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 23f457d83d6..210cdf747e6 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -507,49 +507,6 @@ static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret) return S_OK; } -static HRESULT literal_to_var(script_ctx_t *ctx, literal_t *literal, VARIANT *v) -{ - switch(literal->type) { - case LT_NULL: - V_VT(v) = VT_NULL; - break; - case LT_INT: - V_VT(v) = VT_I4; - V_I4(v) = literal->u.lval; - break; - case LT_DOUBLE: - V_VT(v) = VT_R8; - V_R8(v) = literal->u.dval; - break; - case LT_STRING: { - BSTR str = SysAllocString(literal->u.wstr); - if(!str) - return E_OUTOFMEMORY; - - V_VT(v) = VT_BSTR; - V_BSTR(v) = str; - break; - } - case LT_BOOL: - V_VT(v) = VT_BOOL; - V_BOOL(v) = literal->u.bval; - break; - case LT_REGEXP: { - jsdisp_t *regexp; - HRESULT hres; - - hres = create_regexp(ctx, literal->u.regexp.str, literal->u.regexp.str_len, - literal->u.regexp.flags, ®exp); - if(FAILED(hres)) - return hres; - - var_set_jsdisp(v, regexp); - } - } - - return S_OK; -} - static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret) { named_item_t *item; @@ -1958,55 +1915,40 @@ static HRESULT interp_carray(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.1.5 */ -HRESULT property_value_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +HRESULT interp_new_obj(exec_ctx_t *ctx) { - property_value_expression_t *expr = (property_value_expression_t*)_expr; - VARIANT val, tmp; jsdisp_t *obj; - prop_val_t *iter; - exprval_t exprval; - BSTR name; + VARIANT v; HRESULT hres; TRACE("\n"); - hres = create_object(ctx, NULL, &obj); + hres = create_object(ctx->parser->script, NULL, &obj); if(FAILED(hres)) return hres; - for(iter = expr->property_list; iter; iter = iter->next) { - hres = literal_to_var(ctx, iter->name, &tmp); - if(FAILED(hres)) - break; + var_set_jsdisp(&v, obj); + return stack_push(ctx, &v); +} - hres = to_string(ctx, &tmp, ei, &name); - VariantClear(&tmp); - if(FAILED(hres)) - break; +/* ECMA-262 3rd Edition 11.1.5 */ +HRESULT interp_obj_prop(exec_ctx_t *ctx) +{ + const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr; + jsdisp_t *obj; + VARIANT *v; + HRESULT hres; - hres = expr_eval(ctx, iter->value, 0, ei, &exprval); - if(SUCCEEDED(hres)) { - hres = exprval_to_value(ctx, &exprval, ei, &val); - exprval_release(&exprval); - if(SUCCEEDED(hres)) { - hres = jsdisp_propput_name(obj, name, &val, ei, NULL/*FIXME*/); - VariantClear(&val); - } - } + TRACE("%s\n", debugstr_w(name)); - SysFreeString(name); - if(FAILED(hres)) - break; - } + v = stack_pop(ctx); - if(FAILED(hres)) { - jsdisp_release(obj); - return hres; - } + assert(V_VT(stack_top(ctx)) == VT_DISPATCH); + obj = as_jsdisp(V_DISPATCH(stack_top(ctx))); - ret->type = EXPRVAL_VARIANT; - var_set_jsdisp(&ret->u.var, obj); - return S_OK; + hres = jsdisp_propput_name(obj, name, v, &ctx->ei, NULL/*FIXME*/); + VariantClear(v); + return hres; } /* ECMA-262 3rd Edition 11.11 */ diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index fcdc093a8a4..6c1acad6928 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -80,7 +80,9 @@ typedef struct _func_stack { X(neq, 1, 0,0) \ X(neq2, 1, 0,0) \ X(new, 1, ARG_INT, 0) \ + X(new_obj, 1, 0,0) \ X(null, 1, 0,0) \ + X(obj_prop, 1, ARG_BSTR, 0) \ X(or, 1, 0,0) \ X(pop, 1, 0,0) \ X(postinc, 1, ARG_INT, 0) \ @@ -568,8 +570,6 @@ typedef struct { prop_val_t *property_list; } property_value_expression_t; -HRESULT property_value_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN; - HRESULT compiled_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN; HRESULT compile_subscript(parser_ctx_t*,expression_t*,BOOL,unsigned*) DECLSPEC_HIDDEN; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index b8d7e330468..bd00cbe631f 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -189,6 +189,8 @@ static inline IDispatch *to_disp(jsdisp_t *jsdisp) return (IDispatch*)&jsdisp->IDispatchEx_iface; } +jsdisp_t *as_jsdisp(IDispatch*); + static inline void jsdisp_addref(jsdisp_t *jsdisp) { IDispatchEx_AddRef(&jsdisp->IDispatchEx_iface); @@ -257,6 +259,9 @@ HRESULT to_uint32(script_ctx_t*,VARIANT*,jsexcept_t*,DWORD*) DECLSPEC_HIDDEN; HRESULT to_string(script_ctx_t*,VARIANT*,jsexcept_t*,BSTR*) DECLSPEC_HIDDEN; HRESULT to_object(script_ctx_t*,VARIANT*,IDispatch**) DECLSPEC_HIDDEN; +BSTR int_to_bstr(int) DECLSPEC_HIDDEN; +HRESULT double_to_bstr(double,BSTR*) DECLSPEC_HIDDEN; + typedef struct named_item_t { IDispatch *disp; DWORD flags; diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c index d795e7dacf3..2463a0ba1ba 100644 --- a/dlls/jscript/jsutils.c +++ b/dlls/jscript/jsutils.c @@ -497,7 +497,7 @@ HRESULT to_uint32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, DWORD *ret) return S_OK; } -static BSTR int_to_bstr(INT i) +BSTR int_to_bstr(int i) { WCHAR buf[12], *p; BOOL neg = FALSE; @@ -527,6 +527,32 @@ static BSTR int_to_bstr(INT i) return SysAllocString(p); } +HRESULT double_to_bstr(double n, BSTR *str) +{ + const WCHAR NaNW[] = {'N','a','N',0}; + const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0}; + + if(isnan(n)) { + *str = SysAllocString(NaNW); + }else if(isinf(n)) { + *str = SysAllocString(n<0 ? InfinityW : InfinityW+1); + }else { + VARIANT strv, v; + HRESULT hres; + + V_VT(&v) = VT_R8; + V_R8(&v) = n; + V_VT(&strv) = VT_EMPTY; + hres = VariantChangeTypeEx(&strv, &v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR); + if(FAILED(hres)) + return hres; + + *str = V_BSTR(&strv); + } + + return *str ? S_OK : E_OUTOFMEMORY; +} + /* ECMA-262 3rd Edition 9.8 */ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str) { @@ -534,8 +560,6 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str) const WCHAR nullW[] = {'n','u','l','l',0}; const WCHAR trueW[] = {'t','r','u','e',0}; const WCHAR falseW[] = {'f','a','l','s','e',0}; - const WCHAR NaNW[] = {'N','a','N',0}; - const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0}; switch(V_VT(v)) { case VT_EMPTY: @@ -548,22 +572,7 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str) *str = int_to_bstr(V_I4(v)); break; case VT_R8: { - if(isnan(V_R8(v))) - *str = SysAllocString(NaNW); - else if(isinf(V_R8(v))) - *str = SysAllocString(V_R8(v)<0 ? InfinityW : InfinityW+1); - else { - VARIANT strv; - HRESULT hres; - - V_VT(&strv) = VT_EMPTY; - hres = VariantChangeTypeEx(&strv, v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR); - if(FAILED(hres)) - return hres; - - *str = V_BSTR(&strv); - return S_OK; - } + return double_to_bstr(V_R8(v), str); break; } case VT_BSTR: diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 41481ab937e..ab5ebff8146 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -1360,7 +1360,7 @@ static const expression_eval_t expression_eval_table[] = { compiled_expression_eval, compiled_expression_eval, compiled_expression_eval, - property_value_expression_eval, + compiled_expression_eval, compiled_expression_eval };