diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index a1b2207184b..fe3e043e48c 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -23,6 +23,7 @@ #include "engine.h" #include "parser.h" +#include "wine/rbtree.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(jscript); @@ -41,6 +42,12 @@ typedef struct _statement_ctx_t { struct _statement_ctx_t *next; } statement_ctx_t; +typedef struct { + struct wine_rb_entry entry; + BSTR name; + int ref; +} function_local_t; + typedef struct { parser_ctx_t *parser; bytecode_t *code; @@ -54,8 +61,7 @@ typedef struct { unsigned labels_size; unsigned labels_cnt; - local_ref_t *locals_buf; - unsigned locals_buf_size; + struct wine_rb_tree locals; unsigned locals_cnt; statement_ctx_t *stat_ctx; @@ -63,6 +69,8 @@ typedef struct { function_expression_t *func_head; function_expression_t *func_tail; + + heap_pool_t heap; } compiler_ctx_t; static const struct { @@ -1812,42 +1820,29 @@ 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) +static int function_local_cmp(const void *key, const struct wine_rb_entry *entry) { - return strcmpW((const WCHAR*)key, ((const local_ref_t*)ref)->name); + function_local_t *local = WINE_RB_ENTRY_VALUE(entry, function_local_t, entry); + return strcmpW(key, local->name); } -static inline local_ref_t *find_local(compiler_ctx_t *ctx, const WCHAR *name) +static inline function_local_t *find_local(compiler_ctx_t *ctx, const WCHAR *name) { - return bsearch(name, ctx->locals_buf, ctx->locals_cnt, sizeof(*ctx->locals_buf), local_cmp); + struct wine_rb_entry *entry = wine_rb_get(&ctx->locals, name); + return entry ? WINE_RB_ENTRY_VALUE(entry, function_local_t, entry) : NULL; } static BOOL alloc_local(compiler_ctx_t *ctx, BSTR name, int ref) { - unsigned i; + function_local_t *local; - 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; - } + local = heap_pool_alloc(&ctx->heap, sizeof(*local)); + if(!local) + return FALSE; - 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; + local->name = name; + local->ref = ref; + wine_rb_put(&ctx->locals, name, &local->entry); ctx->locals_cnt++; return TRUE; } @@ -2264,7 +2259,8 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, BOOL from_eval, function_code_t *func) { function_expression_t *iter; - unsigned off, i, j; + function_local_t *local; + unsigned off, i; HRESULT hres; TRACE("\n"); @@ -2273,6 +2269,7 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, ctx->from_eval = from_eval; ctx->func = func; ctx->locals_cnt = 0; + wine_rb_init(&ctx->locals, function_local_cmp); if(func_expr) { parameter_t *param_iter; @@ -2319,21 +2316,22 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, 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->variables = compiler_alloc(ctx->code, func->var_cnt * sizeof(*func->variables)); if(!func->variables) return E_OUTOFMEMORY; - for(i = 0, j = 0; i < func->locals_cnt; i++) { - if(func->locals[i].ref < 0) - continue; /* skip arguments */ - func->variables[func->locals[i].ref].name = func->locals[i].name; - func->variables[func->locals[i].ref].func_id = -1; - j++; + i = 0; + WINE_RB_FOR_EACH_ENTRY(local, &ctx->locals, function_local_t, entry) { + func->locals[i].name = local->name; + func->locals[i].ref = local->ref; + if(local->ref >= 0) { + func->variables[local->ref].name = local->name; + func->variables[local->ref].func_id = -1; + } + i++; } - - assert(j == func->var_cnt); + assert(i == ctx->locals_cnt); func->funcs = compiler_alloc(ctx->code, func->func_cnt * sizeof(*func->funcs)); if(!func->funcs) @@ -2476,9 +2474,10 @@ HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, const WCHAR *args, return hres; } + heap_pool_init(&compiler.heap); hres = compile_function(&compiler, compiler.parser->source, NULL, from_eval, &compiler.code->global_code); + heap_pool_free(&compiler.heap); parser_release(compiler.parser); - heap_free(compiler.locals_buf); if(FAILED(hres)) { release_bytecode(compiler.code); return hres;