Jacek Caban : jscript: Build local references map in compiler and use it to search the scope.
Alexandre Julliard
julliard at winehq.org
Wed Aug 3 18:09:17 CDT 2016
Module: wine
Branch: master
Commit: b652a9787ca7d1e7d441cfe8754ef1c24ad83f18
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b652a9787ca7d1e7d441cfe8754ef1c24ad83f18
Author: Jacek Caban <jacek at 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 at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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 {
More information about the wine-cvs
mailing list