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