From d76b675ea8ae66a14cbaab7005a58cfcc703ea15 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Tue, 24 Apr 2012 17:39:09 +0200 Subject: [PATCH] jscript: Use compiler-generated struct for representing function code. --- dlls/jscript/compile.c | 34 +++++++++++++++++++--------------- dlls/jscript/engine.c | 47 +++++++++++++++++++++++++---------------------- dlls/jscript/engine.h | 21 ++++++++++++++++----- dlls/jscript/function.c | 18 ++++++++---------- dlls/jscript/global.c | 2 +- dlls/jscript/jscript.c | 4 ++-- dlls/jscript/parser.y | 3 +-- 7 files changed, 72 insertions(+), 57 deletions(-) diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 16eed9e49c4..e2d33907ae9 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -52,6 +52,7 @@ typedef struct { unsigned labels_cnt; statement_ctx_t *stat_ctx; + function_code_t *func; } compiler_ctx_t; static const struct { @@ -811,18 +812,13 @@ static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expres static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr) { - unsigned instr; - /* FIXME: not exactly right */ - if(expr->identifier) + if(expr->identifier) { + ctx->func->func_cnt++; return push_instr_bstr(ctx, OP_ident, expr->identifier); + } - instr = push_instr(ctx, OP_func); - if(!instr) - return E_OUTOFMEMORY; - - instr_ptr(ctx, instr)->arg1.func = expr; - return S_OK; + return push_instr_uint(ctx, OP_func, ctx->func->func_cnt++); } static HRESULT compile_expression_noret(compiler_ctx_t *ctx, expression_t *expr, BOOL *no_ret) @@ -1775,15 +1771,16 @@ static HRESULT init_code(compiler_ctx_t *compiler, const WCHAR *source) return S_OK; } -static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, BOOL from_eval) +static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, BOOL from_eval, function_code_t *func) { function_declaration_t *iter; - unsigned off; + unsigned off, i; HRESULT hres; TRACE("\n"); off = ctx->code_off; + ctx->func = func; hres = compile_block_statement(ctx, source->statement); if(FAILED(hres)) return hres; @@ -1798,14 +1795,21 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, if(TRACE_ON(jscript_disas)) dump_code(ctx, off); - source->instr_off = off; + func->instr_off = off; + func->source_elements = source; + + func->funcs = heap_alloc_zero(func->func_cnt * sizeof(*func->funcs)); + if(!func->funcs) + return E_OUTOFMEMORY; - for(iter = source->functions; iter; iter = iter->next) { - hres = compile_function(ctx, iter->expr->source_elements, FALSE); + for(iter = source->functions, i=0; iter; iter = iter->next, i++) { + hres = compile_function(ctx, iter->expr->source_elements, FALSE, func->funcs+i); if(FAILED(hres)) return hres; + func->funcs[i].expr = iter->expr; } + assert(i == func->func_cnt); return S_OK; } @@ -1835,7 +1839,7 @@ HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, const WCHAR *delimi compiler.code->parser = compiler.parser; - hres = compile_function(&compiler, compiler.parser->source, from_eval); + hres = compile_function(&compiler, compiler.parser->source, from_eval, &compiler.code->global_code); if(FAILED(hres)) { release_bytecode(compiler.code); return hres; diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 29425e536b3..7baa8c65411 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -803,15 +803,18 @@ static HRESULT interp_end_finally(exec_ctx_t *ctx) /* ECMA-262 3rd Edition 13 */ static HRESULT interp_func(exec_ctx_t *ctx) { - function_expression_t *expr = ctx->code->instrs[ctx->ip].arg1.func; + unsigned func_idx = ctx->code->instrs[ctx->ip].arg1.uint; + function_expression_t *expr; jsdisp_t *dispex; VARIANT v; HRESULT hres; - TRACE("\n"); + TRACE("%d\n", func_idx); + + expr = ctx->func_code->funcs[func_idx].expr; - hres = create_source_function(ctx->script, ctx->code, expr->parameter_list, expr->source_elements, ctx->scope_chain, - expr->src_str, expr->src_len, &dispex); + hres = create_source_function(ctx->script, ctx->code, expr->parameter_list, ctx->func_code->funcs+func_idx, + ctx->scope_chain, expr->src_str, expr->src_len, &dispex); if(FAILED(hres)) return hres; @@ -2540,10 +2543,11 @@ static HRESULT unwind_exception(exec_ctx_t *ctx) return hres; } -static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, unsigned ip, jsexcept_t *ei, VARIANT *ret) +static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, function_code_t *func, jsexcept_t *ei, VARIANT *ret) { exec_ctx_t *exec_ctx = ctx->exec_ctx; except_frame_t *prev_except_frame; + function_code_t *prev_func; unsigned prev_ip, prev_top; scope_chain_t *prev_scope; bytecode_t *prev_code; @@ -2559,10 +2563,12 @@ static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, unsigned ip, prev_ip = exec_ctx->ip; prev_ei = exec_ctx->ei; prev_code = exec_ctx->code; - exec_ctx->ip = ip; + prev_func = exec_ctx->func_code; + exec_ctx->ip = func->instr_off; exec_ctx->ei = ei; exec_ctx->except_frame = NULL; exec_ctx->code = code; + exec_ctx->func_code = func; while(exec_ctx->ip != -1) { op = code->instrs[exec_ctx->ip].op; @@ -2585,6 +2591,7 @@ static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, unsigned ip, exec_ctx->ei = prev_ei; exec_ctx->except_frame = prev_except_frame; exec_ctx->code = prev_code; + exec_ctx->func_code = prev_func; if(FAILED(hres)) { while(exec_ctx->scope_chain != prev_scope) @@ -2603,35 +2610,37 @@ static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, unsigned ip, return S_OK; } -HRESULT exec_source(exec_ctx_t *ctx, bytecode_t *code, source_elements_t *source, BOOL from_eval, +HRESULT exec_source(exec_ctx_t *ctx, bytecode_t *code, function_code_t *func, BOOL from_eval, jsexcept_t *ei, VARIANT *retv) { - function_declaration_t *func; + exec_ctx_t *prev_ctx; var_list_t *var; VARIANT val; - exec_ctx_t *prev_ctx; + unsigned i; HRESULT hres = S_OK; - for(func = source->functions; func; func = func->next) { + for(i = 0; i < func->func_cnt; i++) { + function_expression_t *expr; jsdisp_t *func_obj; VARIANT var; - if(!func->expr->identifier) + if(!func->funcs[i].expr->identifier) continue; - hres = create_source_function(ctx->script, code, func->expr->parameter_list, func->expr->source_elements, - ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj); + expr = func->funcs[i].expr; + hres = create_source_function(ctx->script, code, expr->parameter_list, func->funcs+i, + ctx->scope_chain, expr->src_str, expr->src_len, &func_obj); if(FAILED(hres)) return hres; var_set_jsdisp(&var, func_obj); - hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, &var, ei); + hres = jsdisp_propput_name(ctx->var_disp, expr->identifier, &var, ei); jsdisp_release(func_obj); if(FAILED(hres)) return hres; } - for(var = source->variables; var; var = var->next) { + for(var = func->source_elements->variables; var; var = var->next) { DISPID id = 0; BSTR name; @@ -2649,13 +2658,7 @@ HRESULT exec_source(exec_ctx_t *ctx, bytecode_t *code, source_elements_t *source prev_ctx = ctx->script->exec_ctx; ctx->script->exec_ctx = ctx; - if(source->statement) { - assert(source->instr_off); - hres = enter_bytecode(ctx->script, code, source->instr_off, ei, &val); - }else { - V_VT(&val) = VT_EMPTY; - } - + hres = enter_bytecode(ctx->script, code, func, ei, &val); assert(ctx->script->exec_ctx == ctx); ctx->script->exec_ctx = prev_ctx; if(FAILED(hres)) diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index f2145010b86..3234ed9a1cb 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -81,7 +81,7 @@ typedef struct { X(eq, 1, 0,0) \ X(eq2, 1, 0,0) \ X(forin, 0, ARG_ADDR, 0) \ - X(func, 1, ARG_FUNC, 0) \ + X(func, 1, ARG_UINT, 0) \ X(gt, 1, 0,0) \ X(gteq, 1, 0,0) \ X(ident, 1, ARG_BSTR, 0) \ @@ -147,7 +147,6 @@ typedef union { LONG lng; WCHAR *str; unsigned uint; - function_expression_t *func; /* FIXME */ } instr_arg_t; typedef enum { @@ -167,12 +166,24 @@ typedef struct { instr_arg_t arg2; } instr_t; +typedef struct _function_code_t { + unsigned instr_off; + + function_expression_t *expr; /* FIXME */ + source_elements_t *source_elements; /* FIXME */ + + unsigned func_cnt; + struct _function_code_t *funcs; +} function_code_t; + typedef struct _bytecode_t { LONG ref; instr_t *instrs; jsheap_t heap; + function_code_t global_code; + WCHAR *source; BSTR *bstr_pool; @@ -232,6 +243,7 @@ struct _exec_ctx_t { scope_chain_t *scope_chain; jsdisp_t *var_disp; IDispatch *this_obj; + function_code_t *func_code; BOOL is_global; VARIANT *stack; @@ -250,11 +262,11 @@ static inline void exec_addref(exec_ctx_t *ctx) void exec_release(exec_ctx_t*) DECLSPEC_HIDDEN; HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,jsdisp_t*,scope_chain_t*,BOOL,exec_ctx_t**) DECLSPEC_HIDDEN; -HRESULT exec_source(exec_ctx_t*,bytecode_t*,source_elements_t*,BOOL,jsexcept_t*,VARIANT*) DECLSPEC_HIDDEN; +HRESULT exec_source(exec_ctx_t*,bytecode_t*,function_code_t*,BOOL,jsexcept_t*,VARIANT*) DECLSPEC_HIDDEN; typedef struct _parameter_t parameter_t; -HRESULT create_source_function(script_ctx_t*,bytecode_t*,parameter_t*,source_elements_t*,scope_chain_t*, +HRESULT create_source_function(script_ctx_t*,bytecode_t*,parameter_t*,function_code_t*,scope_chain_t*, const WCHAR*,DWORD,jsdisp_t**) DECLSPEC_HIDDEN; typedef enum { @@ -494,7 +506,6 @@ struct _source_elements_t { statement_t *statement_tail; function_declaration_t *functions; var_list_t *variables; - unsigned instr_off; }; struct _function_expression_t { diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 8c7fff9efd0..f79ac04520c 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -28,10 +28,10 @@ typedef struct { builtin_invoke_t value_proc; const WCHAR *name; DWORD flags; - source_elements_t *source; parameter_t *parameters; scope_chain_t *scope_chain; bytecode_t *code; + function_code_t *func_code; const WCHAR *src_str; DWORD src_len; DWORD length; @@ -191,7 +191,7 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis scope_chain_t *scope; HRESULT hres; - if(!function->source) { + if(!function->func_code) { FIXME("no source\n"); return E_FAIL; } @@ -217,7 +217,7 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis prev_args = function->arguments; function->arguments = arg_disp; - hres = exec_source(exec_ctx, function->code, function->source, FALSE, ei, retv); + hres = exec_source(exec_ctx, function->code, function->func_code, FALSE, ei, retv); function->arguments = prev_args; jsdisp_release(arg_disp); @@ -660,7 +660,7 @@ HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, return S_OK; } -HRESULT create_source_function(script_ctx_t *ctx, bytecode_t *code, parameter_t *parameters, source_elements_t *source, +HRESULT create_source_function(script_ctx_t *ctx, bytecode_t *code, parameter_t *parameters, function_code_t *func_code, scope_chain_t *scope_chain, const WCHAR *src_str, DWORD src_len, jsdisp_t **ret) { FunctionInstance *function; @@ -683,7 +683,7 @@ HRESULT create_source_function(script_ctx_t *ctx, bytecode_t *code, parameter_t if(FAILED(hres)) return hres; - function->source = source; + function->func_code = func_code; function->parameters = parameters; if(scope_chain) { @@ -710,7 +710,6 @@ static HRESULT construct_function(script_ctx_t *ctx, DISPPARAMS *dp, jsexcept_t function_expression_t *expr; WCHAR *str = NULL, *ptr; DWORD argc, len = 0, l; - parser_ctx_t *parser; bytecode_t *code; jsdisp_t *function; BSTR *params = NULL; @@ -780,15 +779,14 @@ static HRESULT construct_function(script_ctx_t *ctx, DISPPARAMS *dp, jsexcept_t if(FAILED(hres)) return hres; - parser = code->parser; - if(!parser->source || !parser->source->functions || parser->source->functions->next || parser->source->variables) { + if(code->global_code.func_cnt != 1 || code->parser->source->variables) { ERR("Invalid parser result!\n"); release_bytecode(code); return E_UNEXPECTED; } - expr = parser->source->functions->expr; + expr = code->global_code.funcs[0].expr; - hres = create_source_function(ctx, code, expr->parameter_list, expr->source_elements, NULL, expr->src_str, + hres = create_source_function(ctx, code, expr->parameter_list, code->global_code.funcs, NULL, expr->src_str, expr->src_len, &function); release_bytecode(code); if(FAILED(hres)) diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index 92c70bcd652..63239c8a025 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -377,7 +377,7 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DIS return throw_syntax_error(ctx, ei, hres, NULL); } - hres = exec_source(ctx->exec_ctx, code, code->parser->source, TRUE, ei, retv); + hres = exec_source(ctx->exec_ctx, code, &code->global_code, TRUE, ei, retv); release_bytecode(code); return hres; diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 07f3efee443..dfd7d6c86b0 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -109,7 +109,7 @@ static HRESULT exec_global_code(JScript *This, bytecode_t *code) IActiveScriptSite_OnEnterScript(This->site); memset(&jsexcept, 0, sizeof(jsexcept)); - hres = exec_source(exec_ctx, code, code->parser->source, FALSE, &jsexcept, NULL); + hres = exec_source(exec_ctx, code, &code->global_code, FALSE, &jsexcept, NULL); VariantClear(&jsexcept.var); exec_release(exec_ctx); @@ -836,7 +836,7 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars return hres; } - hres = create_source_function(This->ctx, code, NULL, code->parser->source, NULL, NULL, 0, &dispex); + hres = create_source_function(This->ctx, code, NULL, &code->global_code, NULL, NULL, 0, &dispex); release_bytecode(code); if(FAILED(hres)) return hres; diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 4eb3f1da88a..6f31e1571a8 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -293,7 +293,7 @@ Statement : Block { $$ = $1; } | VariableStatement { $$ = $1; } | EmptyStatement { $$ = $1; } - | FunctionExpression { $$ = new_statement(ctx, STAT_EMPTY, 0); } + | FunctionExpression { $$ = new_expression_statement(ctx, $1); } | ExpressionStatement { $$ = $1; } | IfStatement { $$ = $1; } | IterationStatement { $$ = $1; } @@ -1468,7 +1468,6 @@ static source_elements_t *new_source_elements(parser_ctx_t *ctx) source_elements_t *ret = parser_alloc(ctx, sizeof(source_elements_t)); memset(ret, 0, sizeof(*ret)); - ret->instr_off = 0; return ret; } -- 2.11.4.GIT