Jacek Caban : jscript: Added bytecode version of switch statement.
Alexandre Julliard
julliard at winehq.org
Tue Dec 27 11:27:56 CST 2011
Module: wine
Branch: master
Commit: c57dd899a4bfd9b6326d7ae851bcaf9d38219f30
URL: http://source.winehq.org/git/wine.git/?a=commit;h=c57dd899a4bfd9b6326d7ae851bcaf9d38219f30
Author: Jacek Caban <jacek at codeweavers.com>
Date: Tue Dec 27 11:16:40 2011 +0100
jscript: Added bytecode version of switch statement.
---
dlls/jscript/compile.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++
dlls/jscript/engine.c | 25 +++++++++++
dlls/jscript/engine.h | 1 +
dlls/jscript/parser.y | 2 +-
4 files changed, 131 insertions(+), 1 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c
index c2179d3..e54c16a 100644
--- a/dlls/jscript/compile.c
+++ b/dlls/jscript/compile.c
@@ -1131,6 +1131,108 @@ static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *sta
return S_OK;
}
+/* ECMA-262 3rd Edition 12.13 */
+static HRESULT compile_switch_statement(compiler_ctx_t *ctx, switch_statement_t *stat)
+{
+ unsigned case_cnt = 0, *case_jmps, i, default_jmp;
+ BOOL have_default = FALSE;
+ statement_t *stat_iter;
+ case_clausule_t *iter;
+ unsigned off_backup;
+ BOOL prev_no_fallback;
+ HRESULT hres;
+
+ off_backup = ctx->code_off;
+
+ hres = compile_expression(ctx, stat->expr);
+ if(FAILED(hres))
+ return hres;
+
+ for(iter = stat->case_list; iter; iter = iter->next) {
+ if(iter->expr)
+ case_cnt++;
+ }
+
+ case_jmps = heap_alloc(case_cnt * sizeof(*case_jmps));
+ if(!case_jmps)
+ return E_OUTOFMEMORY;
+
+ i = 0;
+ for(iter = stat->case_list; iter; iter = iter->next) {
+ if(!iter->expr) {
+ have_default = TRUE;
+ continue;
+ }
+
+ hres = compile_expression(ctx, iter->expr);
+ if(FAILED(hres))
+ break;
+
+ case_jmps[i] = push_instr(ctx, OP_case);
+ if(case_jmps[i] == -1) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ i++;
+ }
+
+ if(SUCCEEDED(hres)) {
+ if(push_instr(ctx, OP_pop) != -1) {
+ default_jmp = push_instr(ctx, OP_jmp);
+ if(default_jmp == -1)
+ hres = E_OUTOFMEMORY;
+ }else {
+ hres = E_OUTOFMEMORY;
+ }
+ }
+
+ if(FAILED(hres)) {
+ heap_free(case_jmps);
+ return hres;
+ }
+
+ i = 0;
+ for(iter = stat->case_list; iter; iter = iter->next) {
+ while(iter->next && iter->next->stat == iter->stat) {
+ instr_ptr(ctx, iter->expr ? case_jmps[i++] : default_jmp)->arg1.uint = ctx->code_off;
+ iter = iter->next;
+ }
+
+ instr_ptr(ctx, iter->expr ? case_jmps[i++] : default_jmp)->arg1.uint = ctx->code_off;
+
+ for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter); stat_iter = stat_iter->next) {
+ prev_no_fallback = ctx->no_fallback;
+ ctx->no_fallback = TRUE;
+ hres = compile_statement(ctx, stat_iter);
+ ctx->no_fallback = prev_no_fallback;
+ if(hres == E_NOTIMPL) {
+ ctx->code_off = off_backup;
+ stat->stat.eval = switch_statement_eval;
+ return compile_interp_fallback(ctx, &stat->stat);
+ }
+ if(FAILED(hres))
+ break;
+
+ if(stat_iter->next && push_instr(ctx, OP_pop) == -1) {
+ hres = E_OUTOFMEMORY;
+ break;
+ }
+ }
+ if(FAILED(hres))
+ break;
+ }
+
+ heap_free(case_jmps);
+ if(FAILED(hres))
+ return hres;
+ assert(i == case_cnt);
+
+ if(!have_default)
+ instr_ptr(ctx, default_jmp)->arg1.uint = ctx->code_off;
+
+ return S_OK;
+}
+
static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat)
{
switch(stat->type) {
@@ -1144,6 +1246,8 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat)
return compile_for_statement(ctx, (for_statement_t*)stat);
case STAT_IF:
return compile_if_statement(ctx, (if_statement_t*)stat);
+ case STAT_SWITCH:
+ return compile_switch_statement(ctx, (switch_statement_t*)stat);
case STAT_VAR:
return compile_var_statement(ctx, (var_statement_t*)stat);
case STAT_WHILE:
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index af15a94..99c492f 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -1074,6 +1074,31 @@ HRESULT labelled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
}
/* ECMA-262 3rd Edition 12.13 */
+static HRESULT interp_case(exec_ctx_t *ctx)
+{
+ const unsigned arg = ctx->parser->code->instrs[ctx->ip].arg1.uint;
+ VARIANT *v;
+ BOOL b;
+ HRESULT hres;
+
+ TRACE("\n");
+
+ v = stack_pop(ctx);
+ hres = equal2_values(stack_top(ctx), v, &b);
+ VariantClear(v);
+ if(FAILED(hres))
+ return hres;
+
+ if(b) {
+ stack_popn(ctx, 1);
+ ctx->ip = arg;
+ }else {
+ ctx->ip++;
+ }
+ return S_OK;
+}
+
+/* ECMA-262 3rd Edition 12.13 */
HRESULT switch_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret)
{
switch_statement_t *stat = (switch_statement_t*)_stat;
diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h
index 1ca6630..263548e 100644
--- a/dlls/jscript/engine.h
+++ b/dlls/jscript/engine.h
@@ -52,6 +52,7 @@ typedef struct _func_stack {
X(call, 1, ARG_UINT, ARG_UINT) \
X(call_member,1, ARG_UINT, ARG_UINT) \
X(carray, 1, ARG_UINT, 0) \
+ X(case, 0, ARG_ADDR, 0) \
X(cnd_nz, 0, ARG_ADDR, 0) \
X(cnd_z, 0, ARG_ADDR, 0) \
X(delete, 1, 0,0) \
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y
index 578ae23..aaec649 100644
--- a/dlls/jscript/parser.y
+++ b/dlls/jscript/parser.y
@@ -846,7 +846,7 @@ static const statement_eval_t stat_eval_table[] = {
compiled_statement_eval,
labelled_statement_eval,
return_statement_eval,
- switch_statement_eval,
+ compiled_statement_eval,
throw_statement_eval,
try_statement_eval,
compiled_statement_eval,
More information about the wine-cvs
mailing list