jscript: Added bytecode version of with statement.
This commit is contained in:
parent
17fedc448b
commit
abffe88e19
|
@ -1097,6 +1097,40 @@ static HRESULT compile_for_statement(compiler_ctx_t *ctx, for_statement_t *stat)
|
|||
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)
|
||||
{
|
||||
switch(stat->type) {
|
||||
|
@ -1114,6 +1148,8 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat)
|
|||
return compile_var_statement(ctx, (var_statement_t*)stat);
|
||||
case STAT_WHILE:
|
||||
return compile_while_statement(ctx, (while_statement_t*)stat);
|
||||
case STAT_WITH:
|
||||
return compile_with_statement(ctx, (with_statement_t*)stat);
|
||||
default:
|
||||
return compile_interp_fallback(ctx, stat);
|
||||
}
|
||||
|
|
|
@ -837,6 +837,11 @@ jsdisp_t *as_jsdisp(IDispatch *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)
|
||||
{
|
||||
TRACE("%p (%p)\n", dispex, prototype);
|
||||
|
|
|
@ -1029,6 +1029,43 @@ HRESULT with_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t
|
|||
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 */
|
||||
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
|
|||
{
|
||||
exec_ctx_t *exec_ctx = ctx->exec_ctx;
|
||||
unsigned prev_ip, prev_top;
|
||||
scope_chain_t *prev_scope;
|
||||
return_type_t *prev_rt;
|
||||
jsexcept_t *prev_ei;
|
||||
jsop_t op;
|
||||
|
@ -2970,6 +3008,7 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
|
|||
|
||||
prev_rt = exec_ctx->rt;
|
||||
prev_top = exec_ctx->top;
|
||||
prev_scope = exec_ctx->scope_chain;
|
||||
prev_ip = exec_ctx->ip;
|
||||
prev_ei = exec_ctx->ei;
|
||||
exec_ctx->ip = stat->instr_off;
|
||||
|
@ -2990,10 +3029,13 @@ HRESULT compiled_statement_eval(script_ctx_t *ctx, statement_t *stat, return_typ
|
|||
|
||||
if(FAILED(hres)) {
|
||||
stack_popn(exec_ctx, exec_ctx->top-prev_top);
|
||||
while(exec_ctx->scope_chain != prev_scope)
|
||||
scope_pop(&exec_ctx->scope_chain);
|
||||
return hres;
|
||||
}
|
||||
|
||||
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)
|
||||
V_VT(ret) = VT_EMPTY;
|
||||
|
|
|
@ -87,8 +87,10 @@ typedef struct _func_stack {
|
|||
X(obj_prop, 1, ARG_BSTR, 0) \
|
||||
X(or, 1, 0,0) \
|
||||
X(pop, 1, 0,0) \
|
||||
X(pop_scope, 1, 0,0) \
|
||||
X(postinc, 1, ARG_INT, 0) \
|
||||
X(preinc, 1, ARG_INT, 0) \
|
||||
X(push_scope, 1, 0,0) \
|
||||
X(regexp, 1, ARG_STR, ARG_INT) \
|
||||
X(rshift, 1, 0,0) \
|
||||
X(rshift2, 1, 0,0) \
|
||||
|
|
|
@ -190,6 +190,7 @@ static inline IDispatch *to_disp(jsdisp_t *jsdisp)
|
|||
}
|
||||
|
||||
jsdisp_t *as_jsdisp(IDispatch*);
|
||||
jsdisp_t *to_jsdisp(IDispatch*);
|
||||
|
||||
static inline void jsdisp_addref(jsdisp_t *jsdisp)
|
||||
{
|
||||
|
|
|
@ -851,7 +851,7 @@ static const statement_eval_t stat_eval_table[] = {
|
|||
try_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)
|
||||
|
|
Loading…
Reference in New Issue