Module: wine Branch: master Commit: b652a9787ca7d1e7d441cfe8754ef1c24ad83f18 URL: http://source.winehq.org/git/wine.git/?a=commit;h=b652a9787ca7d1e7d441cfe875...
Author: Jacek Caban jacek@codeweavers.com Date: Wed Aug 3 16:27:35 2016 +0200
jscript: Build local references map in compiler and use it to search the scope.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/jscript/compile.c | 99 +++++++++++++++++++++++++++++++++++++++----------- dlls/jscript/engine.c | 19 ++++++---- dlls/jscript/engine.h | 8 ++++ 3 files changed, 97 insertions(+), 29 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 77bbc89..7b844b7 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -54,6 +54,10 @@ typedef struct { unsigned labels_size; unsigned labels_cnt;
+ local_ref_t *locals_buf; + unsigned locals_buf_size; + unsigned locals_cnt; + statement_ctx_t *stat_ctx; function_code_t *func;
@@ -1782,6 +1786,46 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx, return hres; }
+static int local_cmp(const void *key, const void *ref) +{ + return strcmpW((const WCHAR*)key, ((const local_ref_t*)ref)->name); +} + +static inline local_ref_t *find_local(compiler_ctx_t *ctx, BSTR name) +{ + return bsearch(name, ctx->locals_buf, ctx->locals_cnt, sizeof(*ctx->locals_buf), local_cmp); +} + +static BOOL alloc_local(compiler_ctx_t *ctx, BSTR name, int ref) +{ + unsigned i; + + if(!ctx->locals_buf_size) { + ctx->locals_buf = heap_alloc(4 * sizeof(*ctx->locals_buf)); + if(!ctx->locals_buf) + return FALSE; + ctx->locals_buf_size = 4; + }else if(ctx->locals_buf_size == ctx->locals_cnt) { + local_ref_t *new_buf = heap_realloc(ctx->locals_buf, ctx->locals_buf_size * 2 * sizeof(*ctx->locals_buf)); + if(!new_buf) + return FALSE; + ctx->locals_buf = new_buf; + ctx->locals_buf_size *= 2; + } + + for(i = 0; i < ctx->locals_cnt; i++) { + if(strcmpW(ctx->locals_buf[i].name, name) > 0) { + memmove(ctx->locals_buf + i+1, ctx->locals_buf + i, (ctx->locals_cnt - i) * sizeof(*ctx->locals_buf)); + break; + } + } + + ctx->locals_buf[i].name = name; + ctx->locals_buf[i].ref = ref; + ctx->locals_cnt++; + return TRUE; +} + static void resolve_labels(compiler_ctx_t *ctx, unsigned off) { instr_t *instr; @@ -1856,9 +1900,35 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, ctx->var_head = ctx->var_tail = NULL; ctx->func_head = ctx->func_tail = NULL; ctx->from_eval = from_eval; + ctx->func = func; + ctx->locals_cnt = 0; + + if(func_expr) { + parameter_t *param_iter; + + func->source = func_expr->src_str; + func->source_len = func_expr->src_len; + + for(param_iter = func_expr->parameter_list; param_iter; param_iter = param_iter->next) + func->param_cnt++; + + func->params = compiler_alloc(ctx->code, func->param_cnt * sizeof(*func->params)); + if(!func->params) + return E_OUTOFMEMORY; + + for(param_iter = func_expr->parameter_list, i=0; param_iter; param_iter = param_iter->next, i++) { + func->params[i] = compiler_alloc_bstr(ctx, param_iter->identifier); + if(!func->params[i]) + return E_OUTOFMEMORY; + } + } + + for(i = 0; i < func->param_cnt; i++) { + if(!find_local(ctx, func->params[i]) && !alloc_local(ctx, func->params[i], -i-1)) + return E_OUTOFMEMORY; + }
off = ctx->code_off; - ctx->func = func; hres = compile_block_statement(ctx, source->statement); if(FAILED(hres)) return hres; @@ -1888,26 +1958,6 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, } }
- if(func_expr) { - parameter_t *param_iter; - - func->source = func_expr->src_str; - func->source_len = func_expr->src_len; - - for(param_iter = func_expr->parameter_list; param_iter; param_iter = param_iter->next) - func->param_cnt++; - - func->params = compiler_alloc(ctx->code, func->param_cnt * sizeof(*func->params)); - if(!func->params) - return E_OUTOFMEMORY; - - for(param_iter = func_expr->parameter_list, i=0; param_iter; param_iter = param_iter->next, i++) { - func->params[i] = compiler_alloc_bstr(ctx, param_iter->identifier); - if(!func->params[i]) - return E_OUTOFMEMORY; - } - } - func->variables = compiler_alloc(ctx->code, func->var_cnt * sizeof(*func->variables)); if(!func->variables) return E_OUTOFMEMORY; @@ -1920,6 +1970,12 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source,
assert(i == func->var_cnt);
+ func->locals = compiler_alloc(ctx->code, ctx->locals_cnt * sizeof(*func->locals)); + if(!func->locals) + return E_OUTOFMEMORY; + func->locals_cnt = ctx->locals_cnt; + memcpy(func->locals, ctx->locals_buf, func->locals_cnt * sizeof(*func->locals)); + func->funcs = compiler_alloc(ctx->code, func->func_cnt * sizeof(*func->funcs)); if(!func->funcs) return E_OUTOFMEMORY; @@ -2038,6 +2094,7 @@ HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, const WCHAR *args,
hres = compile_function(&compiler, compiler.parser->source, NULL, from_eval, &compiler.code->global_code); parser_release(compiler.parser); + heap_free(compiler.locals_buf); if(FAILED(hres)) { release_bytecode(compiler.code); return hres; diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 11b5618..187a8b7 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -589,6 +589,11 @@ static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t return FALSE; }
+static int local_ref_cmp(const void *key, const void *ref) +{ + return strcmpW((const WCHAR*)key, ((const local_ref_t*)ref)->name); +} + /* ECMA-262 3rd Edition 10.1.4 */ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *ret) { @@ -603,14 +608,12 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re for(scope = ctx->call_ctx->scope; scope; scope = scope->next) { if(scope->frame) { function_code_t *func = scope->frame->function; - int i; - - for(i = 0; i < func->param_cnt; i++) { - if(!strcmpW(identifier, func->params[i])) { - ret->type = EXPRVAL_STACK_REF; - ret->u.off = scope->frame->arguments_off+i; - return S_OK; - } + local_ref_t *ref = bsearch(identifier, func->locals, func->locals_cnt, sizeof(*func->locals), local_ref_cmp); + + if(ref) { + ret->type = EXPRVAL_STACK_REF; + ret->u.off = scope->frame->arguments_off - ref->ref - 1; + return S_OK; } } if(scope->jsobj) diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index 3a3f37b..1aebfd7 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -126,6 +126,11 @@ typedef struct { } u; } instr_t;
+typedef struct { + BSTR name; + int ref; +} local_ref_t; + typedef struct _function_code_t { BSTR name; BSTR event_target; @@ -142,6 +147,9 @@ typedef struct _function_code_t {
unsigned param_cnt; BSTR *params; + + unsigned locals_cnt; + local_ref_t *locals; } function_code_t;
typedef struct _bytecode_t {