Commit abffe88e authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

jscript: Added bytecode version of with statement.

parent 17fedc44
...@@ -1097,6 +1097,40 @@ static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat) ...@@ -1097,6 +1097,40 @@ static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
return S_OK; return S_OK;
} }
/* ECMA-262 3rd Edition 12.10 */
static HRESULT compile_with_statement(compiler_ctx_t *ctx, with_statement_t *stat)
{
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;
if(push_instr(ctx, OP_push_scope) == -1)
return E_OUTOFMEMORY;
prev_no_fallback = ctx->no_fallback;
ctx->no_fallback = TRUE;
hres = compile_statement(ctx, stat->statement);
ctx->no_fallback = prev_no_fallback;
if(hres == E_NOTIMPL) {
ctx->code_off = off_backup;
stat->stat.eval = with_statement_eval;
return compile_interp_fallback(ctx, &stat->stat);
}
if(FAILED(hres))
return hres;
if(push_instr(ctx, OP_pop_scope) == -1)
return E_OUTOFMEMORY;
return S_OK;
}
static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat) static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat)
{ {
switch(stat->type) { switch(stat->type) {
...@@ -1114,6 +1148,8 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat) ...@@ -1114,6 +1148,8 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat)
return compile_var_statement(ctx, (var_statement_t*)stat); return compile_var_statement(ctx, (var_statement_t*)stat);
case STAT_WHILE: case STAT_WHILE:
return compile_while_statement(ctx, (while_statement_t*)stat); return compile_while_statement(ctx, (while_statement_t*)stat);
case STAT_WITH:
return compile_with_statement(ctx, (with_statement_t*)stat);
default: default:
return compile_interp_fallback(ctx, stat); return compile_interp_fallback(ctx, stat);
} }
......
...@@ -837,6 +837,11 @@ jsdisp_t *as_jsdisp(IDispatch *disp) ...@@ -837,6 +837,11 @@ jsdisp_t *as_jsdisp(IDispatch *disp)
return impl_from_IDispatchEx((IDispatchEx*)disp); return impl_from_IDispatchEx((IDispatchEx*)disp);
} }
jsdisp_t *to_jsdisp(IDispatch *disp)
{
return disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl ? impl_from_IDispatchEx((IDispatchEx*)disp) : NULL;
}
HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype) HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype)
{ {
TRACE("%p (%p)\n", dispex, prototype); TRACE("%p (%p)\n", dispex, prototype);
......
...@@ -1029,6 +1029,43 @@ HRESULT with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t ...@@ -1029,6 +1029,43 @@ HRESULT with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t
return hres; return hres;
} }
/* ECMA-262 3rd Edition 12.10 */
HRESULT interp_push_scope(exec_ctx_t *ctx)
{
IDispatch *disp;
jsdisp_t *obj;
VARIANT *v;
HRESULT hres;
TRACE("\n");
v = stack_pop(ctx);
hres = to_object(ctx->parser->script, v, &disp);
VariantClear(v);
if(FAILED(hres))
return hres;
obj = to_jsdisp(disp);
if(!obj) {
IDispatch_Release(disp);
FIXME("disp is not jsdisp\n");
return E_NOTIMPL;
}
hres = scope_push(ctx->scope_chain, obj, &ctx->scope_chain);
jsdisp_release(obj);
return hres;
}
/* ECMA-262 3rd Edition 12.10 */
HRESULT interp_pop_scope(exec_ctx_t *ctx)
{
TRACE("\n");
scope_pop(&ctx->scope_chain);
return S_OK;
}
/* ECMA-262 3rd Edition 12.12 */ /* ECMA-262 3rd Edition 12.12 */
HRESULT labelled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) HRESULT labelled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret)
{ {
...@@ -2955,6 +2992,7 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ ...@@ -2955,6 +2992,7 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
{ {
exec_ctx_t *exec_ctx = ctx->exec_ctx; exec_ctx_t *exec_ctx = ctx->exec_ctx;
unsigned prev_ip, prev_top; unsigned prev_ip, prev_top;
scope_chain_t *prev_scope;
return_type_t *prev_rt; return_type_t *prev_rt;
jsexcept_t *prev_ei; jsexcept_t *prev_ei;
jsop_t op; jsop_t op;
...@@ -2970,6 +3008,7 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ ...@@ -2970,6 +3008,7 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
prev_rt = exec_ctx->rt; prev_rt = exec_ctx->rt;
prev_top = exec_ctx->top; prev_top = exec_ctx->top;
prev_scope = exec_ctx->scope_chain;
prev_ip = exec_ctx->ip; prev_ip = exec_ctx->ip;
prev_ei = exec_ctx->ei; prev_ei = exec_ctx->ei;
exec_ctx->ip = stat->instr_off; exec_ctx->ip = stat->instr_off;
...@@ -2990,10 +3029,13 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ ...@@ -2990,10 +3029,13 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
if(FAILED(hres)) { if(FAILED(hres)) {
stack_popn(exec_ctx, exec_ctx->top-prev_top); stack_popn(exec_ctx, exec_ctx->top-prev_top);
while(exec_ctx->scope_chain != prev_scope)
scope_pop(&exec_ctx->scope_chain);
return hres; return hres;
} }
assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top); assert(exec_ctx->top == prev_top+1 || exec_ctx->top == prev_top);
assert(exec_ctx->scope_chain == prev_scope);
if(exec_ctx->top == prev_top) if(exec_ctx->top == prev_top)
V_VT(ret) = VT_EMPTY; V_VT(ret) = VT_EMPTY;
......
...@@ -87,8 +87,10 @@ typedef struct _func_stack { ...@@ -87,8 +87,10 @@ typedef struct _func_stack {
X(obj_prop, 1, ARG_BSTR, 0) \ X(obj_prop, 1, ARG_BSTR, 0) \
X(or, 1, 0,0) \ X(or, 1, 0,0) \
X(pop, 1, 0,0) \ X(pop, 1, 0,0) \
X(pop_scope, 1, 0,0) \
X(postinc, 1, ARG_INT, 0) \ X(postinc, 1, ARG_INT, 0) \
X(preinc, 1, ARG_INT, 0) \ X(preinc, 1, ARG_INT, 0) \
X(push_scope, 1, 0,0) \
X(regexp, 1, ARG_STR, ARG_INT) \ X(regexp, 1, ARG_STR, ARG_INT) \
X(rshift, 1, 0,0) \ X(rshift, 1, 0,0) \
X(rshift2, 1, 0,0) \ X(rshift2, 1, 0,0) \
......
...@@ -190,6 +190,7 @@ static inline IDispatch *to_disp(jsdisp_t *jsdisp) ...@@ -190,6 +190,7 @@ static inline IDispatch *to_disp(jsdisp_t *jsdisp)
} }
jsdisp_t *as_jsdisp(IDispatch*); jsdisp_t *as_jsdisp(IDispatch*);
jsdisp_t *to_jsdisp(IDispatch*);
static inline void jsdisp_addref(jsdisp_t *jsdisp) static inline void jsdisp_addref(jsdisp_t *jsdisp)
{ {
......
...@@ -851,7 +851,7 @@ static const statement_eval_t stat_eval_table[] = { ...@@ -851,7 +851,7 @@ static const statement_eval_t stat_eval_table[] = {
try_statement_eval, try_statement_eval,
compiled_statement_eval, compiled_statement_eval,
compiled_statement_eval, compiled_statement_eval,
with_statement_eval compiled_statement_eval
}; };
static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size) static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment