Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
3b56e49e
Commit
3b56e49e
authored
Dec 28, 2011
by
Jacek Caban
Committed by
Alexandre Julliard
Dec 28, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
jscript: Added bytecode version of try statement.
parent
02ff8d18
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
276 additions
and
5 deletions
+276
-5
compile.c
dlls/jscript/compile.c
+92
-0
engine.c
dlls/jscript/engine.c
+154
-3
engine.h
dlls/jscript/engine.h
+6
-1
parser.y
dlls/jscript/parser.y
+1
-1
lang.js
dlls/jscript/tests/lang.js
+23
-0
No files found.
dlls/jscript/compile.c
View file @
3b56e49e
...
...
@@ -1311,6 +1311,96 @@ static HRESULT compile_throw_statement(compiler_ctx_t *ctx, expression_statement
return
push_instr
(
ctx
,
OP_throw
)
==
-
1
?
E_OUTOFMEMORY
:
S_OK
;
}
/* ECMA-262 3rd Edition 12.14 */
static
HRESULT
compile_try_statement
(
compiler_ctx_t
*
ctx
,
try_statement_t
*
stat
)
{
unsigned
off_backup
,
push_except
;
BOOL
prev_no_fallback
;
BSTR
ident
;
HRESULT
hres
;
off_backup
=
ctx
->
code_off
;
prev_no_fallback
=
ctx
->
no_fallback
;
push_except
=
push_instr
(
ctx
,
OP_push_except
);
if
(
push_except
==
-
1
)
return
E_OUTOFMEMORY
;
if
(
stat
->
catch_block
)
{
ident
=
compiler_alloc_bstr
(
ctx
,
stat
->
catch_block
->
identifier
);
if
(
!
ident
)
return
E_OUTOFMEMORY
;
}
else
{
ident
=
NULL
;
}
instr_ptr
(
ctx
,
push_except
)
->
arg2
.
bstr
=
ident
;
ctx
->
no_fallback
=
TRUE
;
hres
=
compile_statement
(
ctx
,
stat
->
try_statement
);
ctx
->
no_fallback
=
prev_no_fallback
;
if
(
hres
==
E_NOTIMPL
)
{
ctx
->
code_off
=
off_backup
;
stat
->
stat
.
eval
=
try_statement_eval
;
return
compile_interp_fallback
(
ctx
,
&
stat
->
stat
);
}
if
(
FAILED
(
hres
))
return
hres
;
if
(
push_instr
(
ctx
,
OP_pop_except
)
==
-
1
)
return
E_OUTOFMEMORY
;
if
(
stat
->
catch_block
)
{
unsigned
jmp_finally
;
jmp_finally
=
push_instr
(
ctx
,
OP_jmp
);
if
(
jmp_finally
==
-
1
)
return
E_OUTOFMEMORY
;
instr_ptr
(
ctx
,
push_except
)
->
arg1
.
uint
=
ctx
->
code_off
;
ctx
->
no_fallback
=
TRUE
;
hres
=
compile_statement
(
ctx
,
stat
->
catch_block
->
statement
);
ctx
->
no_fallback
=
prev_no_fallback
;
if
(
hres
==
E_NOTIMPL
)
{
ctx
->
code_off
=
off_backup
;
stat
->
stat
.
eval
=
try_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
;
instr_ptr
(
ctx
,
jmp_finally
)
->
arg1
.
uint
=
ctx
->
code_off
;
}
else
{
instr_ptr
(
ctx
,
push_except
)
->
arg1
.
uint
=
ctx
->
code_off
;
}
if
(
stat
->
finally_statement
)
{
/* FIXME: avoid */
if
(
push_instr
(
ctx
,
OP_pop
)
==
-
1
)
return
E_OUTOFMEMORY
;
ctx
->
no_fallback
=
TRUE
;
hres
=
compile_statement
(
ctx
,
stat
->
finally_statement
);
ctx
->
no_fallback
=
prev_no_fallback
;
if
(
hres
==
E_NOTIMPL
)
{
ctx
->
code_off
=
off_backup
;
stat
->
stat
.
eval
=
try_statement_eval
;
return
compile_interp_fallback
(
ctx
,
&
stat
->
stat
);
}
if
(
FAILED
(
hres
))
return
hres
;
if
(
!
stat
->
catch_block
&&
push_instr
(
ctx
,
OP_end_finally
)
==
-
1
)
return
E_OUTOFMEMORY
;
}
return
S_OK
;
}
static
HRESULT
compile_statement
(
compiler_ctx_t
*
ctx
,
statement_t
*
stat
)
{
switch
(
stat
->
type
)
{
...
...
@@ -1332,6 +1422,8 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_t *stat)
return
compile_switch_statement
(
ctx
,
(
switch_statement_t
*
)
stat
);
case
STAT_THROW
:
return
compile_throw_statement
(
ctx
,
(
expression_statement_t
*
)
stat
);
case
STAT_TRY
:
return
compile_try_statement
(
ctx
,
(
try_statement_t
*
)
stat
);
case
STAT_VAR
:
return
compile_var_statement
(
ctx
,
(
var_statement_t
*
)
stat
);
case
STAT_WHILE
:
...
...
dlls/jscript/engine.c
View file @
3b56e49e
...
...
@@ -47,6 +47,15 @@ struct _return_type_t {
jsexcept_t
ei
;
};
struct
_except_frame_t
{
unsigned
stack_top
;
scope_chain_t
*
scope
;
unsigned
catch_off
;
BSTR
ident
;
except_frame_t
*
next
;
};
static
inline
HRESULT
stat_eval
(
script_ctx_t
*
ctx
,
statement_t
*
stat
,
return_type_t
*
rt
,
VARIANT
*
ret
)
{
return
stat
->
eval
(
ctx
,
stat
,
rt
,
ret
);
...
...
@@ -1324,6 +1333,77 @@ HRESULT try_statement_eval(script_ctx_t *ctx, statement_t *_stat, return_type_t
return
S_OK
;
}
/* ECMA-262 3rd Edition 12.14 */
static
HRESULT
interp_push_except
(
exec_ctx_t
*
ctx
)
{
const
unsigned
arg1
=
ctx
->
parser
->
code
->
instrs
[
ctx
->
ip
].
arg1
.
uint
;
const
BSTR
arg2
=
ctx
->
parser
->
code
->
instrs
[
ctx
->
ip
].
arg2
.
bstr
;
except_frame_t
*
except
;
unsigned
stack_top
;
TRACE
(
"
\n
"
);
stack_top
=
ctx
->
top
;
if
(
!
arg2
)
{
HRESULT
hres
;
hres
=
stack_push_bool
(
ctx
,
TRUE
);
if
(
FAILED
(
hres
))
return
hres
;
}
except
=
heap_alloc
(
sizeof
(
*
except
));
if
(
!
except
)
return
E_OUTOFMEMORY
;
except
->
stack_top
=
stack_top
;
except
->
scope
=
ctx
->
scope_chain
;
except
->
catch_off
=
arg1
;
except
->
ident
=
arg2
;
except
->
next
=
ctx
->
except_frame
;
ctx
->
except_frame
=
except
;
return
S_OK
;
}
/* ECMA-262 3rd Edition 12.14 */
static
HRESULT
interp_pop_except
(
exec_ctx_t
*
ctx
)
{
except_frame_t
*
except
;
TRACE
(
"
\n
"
);
except
=
ctx
->
except_frame
;
assert
(
except
!=
NULL
);
ctx
->
except_frame
=
except
->
next
;
heap_free
(
except
);
return
S_OK
;
}
/* ECMA-262 3rd Edition 12.14 */
static
HRESULT
interp_end_finally
(
exec_ctx_t
*
ctx
)
{
VARIANT
*
v
;
TRACE
(
"
\n
"
);
v
=
stack_pop
(
ctx
);
assert
(
V_VT
(
stack_top
(
ctx
))
==
VT_BOOL
);
if
(
!
V_BOOL
(
stack_top
(
ctx
)))
{
TRACE
(
"passing exception
\n
"
);
VariantClear
(
v
);
stack_popn
(
ctx
,
1
);
ctx
->
rt
->
ei
.
var
=
*
stack_pop
(
ctx
);
return
DISP_E_EXCEPTION
;
}
*
stack_top
(
ctx
)
=
*
v
;
return
S_OK
;
}
/* ECMA-262 3rd Edition 13 */
static
HRESULT
interp_func
(
exec_ctx_t
*
ctx
)
{
...
...
@@ -3072,9 +3152,68 @@ OP_LIST
#undef X
};
static
HRESULT
unwind_exception
(
exec_ctx_t
*
ctx
)
{
except_frame_t
*
except_frame
;
VARIANT
except_val
;
BSTR
ident
;
HRESULT
hres
;
except_frame
=
ctx
->
except_frame
;
ctx
->
except_frame
=
except_frame
->
next
;
assert
(
except_frame
->
stack_top
<=
ctx
->
top
);
stack_popn
(
ctx
,
ctx
->
top
-
except_frame
->
stack_top
);
while
(
except_frame
->
scope
!=
ctx
->
scope_chain
)
scope_pop
(
&
ctx
->
scope_chain
);
ctx
->
ip
=
except_frame
->
catch_off
;
assert
(
ctx
->
rt
->
type
==
RT_NORMAL
);
except_val
=
ctx
->
rt
->
ei
.
var
;
memset
(
&
ctx
->
rt
->
ei
,
0
,
sizeof
(
ctx
->
rt
->
ei
));
ident
=
except_frame
->
ident
;
heap_free
(
except_frame
);
if
(
ident
)
{
jsdisp_t
*
scope_obj
;
hres
=
create_dispex
(
ctx
->
parser
->
script
,
NULL
,
NULL
,
&
scope_obj
);
if
(
SUCCEEDED
(
hres
))
{
hres
=
jsdisp_propput_name
(
scope_obj
,
ident
,
&
except_val
,
&
ctx
->
rt
->
ei
,
NULL
/*FIXME*/
);
if
(
FAILED
(
hres
))
jsdisp_release
(
scope_obj
);
}
VariantClear
(
&
except_val
);
if
(
FAILED
(
hres
))
return
hres
;
hres
=
scope_push
(
ctx
->
scope_chain
,
scope_obj
,
&
ctx
->
scope_chain
);
jsdisp_release
(
scope_obj
);
}
else
{
VARIANT
v
;
hres
=
stack_push
(
ctx
,
&
except_val
);
if
(
FAILED
(
hres
))
return
hres
;
hres
=
stack_push_bool
(
ctx
,
FALSE
);
if
(
FAILED
(
hres
))
return
hres
;
V_VT
(
&
v
)
=
VT_EMPTY
;
hres
=
stack_push
(
ctx
,
&
v
);
}
return
hres
;
}
HRESULT
compiled_statement_eval
(
script_ctx_t
*
ctx
,
statement_t
*
stat
,
return_type_t
*
rt
,
VARIANT
*
ret
)
{
exec_ctx_t
*
exec_ctx
=
ctx
->
exec_ctx
;
except_frame_t
*
prev_except_frame
;
unsigned
prev_ip
,
prev_top
;
scope_chain_t
*
prev_scope
;
return_type_t
*
prev_rt
;
...
...
@@ -3093,23 +3232,35 @@ 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_except_frame
=
exec_ctx
->
except_frame
;
prev_ip
=
exec_ctx
->
ip
;
prev_ei
=
exec_ctx
->
ei
;
exec_ctx
->
ip
=
stat
->
instr_off
;
exec_ctx
->
rt
=
rt
;
exec_ctx
->
ei
=
&
rt
->
ei
;
exec_ctx
->
except_frame
=
NULL
;
while
(
exec_ctx
->
ip
!=
-
1
&&
exec_ctx
->
rt
->
type
==
RT_NORMAL
)
{
op
=
exec_ctx
->
parser
->
code
->
instrs
[
exec_ctx
->
ip
].
op
;
hres
=
op_funcs
[
op
](
exec_ctx
);
if
(
FAILED
(
hres
))
break
;
exec_ctx
->
ip
+=
op_move
[
op
];
if
(
FAILED
(
hres
))
{
TRACE
(
"EXCEPTION
\n
"
);
if
(
!
exec_ctx
->
except_frame
)
break
;
hres
=
unwind_exception
(
exec_ctx
);
if
(
FAILED
(
hres
))
break
;
}
else
{
exec_ctx
->
ip
+=
op_move
[
op
];
}
}
exec_ctx
->
rt
=
prev_rt
;
exec_ctx
->
ip
=
prev_ip
;
exec_ctx
->
ei
=
prev_ei
;
exec_ctx
->
except_frame
=
prev_except_frame
;
if
(
FAILED
(
hres
))
{
stack_popn
(
exec_ctx
,
exec_ctx
->
top
-
prev_top
);
...
...
dlls/jscript/engine.h
View file @
3b56e49e
...
...
@@ -58,7 +58,8 @@ typedef struct _func_stack {
X(delete, 1, 0,0) \
X(delete_ident,1,ARG_BSTR, 0) \
X(div, 1, 0,0) \
X(double, 1, ARG_SBL, 0) \
X(double, 1, ARG_DBL, 0) \
X(end_finally,1, 0,0) \
X(eq, 1, 0,0) \
X(eq2, 1, 0,0) \
X(forin, 0, ARG_UINT, 0) \
...
...
@@ -90,9 +91,11 @@ typedef struct _func_stack {
X(obj_prop, 1, ARG_BSTR, 0) \
X(or, 1, 0,0) \
X(pop, 1, 0,0) \
X(pop_except, 1, 0,0) \
X(pop_scope, 1, 0,0) \
X(postinc, 1, ARG_INT, 0) \
X(preinc, 1, ARG_INT, 0) \
X(push_except,1, ARG_UINT, ARG_BSTR) \
X(push_scope, 1, 0,0) \
X(regexp, 1, ARG_STR, ARG_INT) \
X(rshift, 1, 0,0) \
...
...
@@ -222,6 +225,7 @@ static inline void scope_addref(scope_chain_t *scope)
}
typedef
struct
_return_type_t
return_type_t
;
typedef
struct
_except_frame_t
except_frame_t
;
struct
_exec_ctx_t
{
LONG
ref
;
...
...
@@ -235,6 +239,7 @@ struct _exec_ctx_t {
VARIANT
*
stack
;
unsigned
stack_size
;
unsigned
top
;
except_frame_t
*
except_frame
;
unsigned
ip
;
jsexcept_t
*
ei
;
...
...
dlls/jscript/parser.y
View file @
3b56e49e
...
...
@@ -848,7 +848,7 @@ static const statement_eval_t stat_eval_table[] = {
return_statement_eval,
compiled_statement_eval,
compiled_statement_eval,
try
_statement_eval,
compiled
_statement_eval,
compiled_statement_eval,
compiled_statement_eval,
compiled_statement_eval
...
...
dlls/jscript/tests/lang.js
View file @
3b56e49e
...
...
@@ -564,6 +564,29 @@ ok(state === "finally", "state = " + state + " expected finally");
state
=
""
;
try
{
try
{
throw
0
;
}
finally
{
state
=
"finally"
;
}
}
catch
(
e
)
{
ok
(
state
===
"finally"
,
"state = "
+
state
+
" expected finally"
);
state
=
"catch"
;
}
ok
(
state
===
"catch"
,
"state = "
+
state
+
" expected catch"
);
try
{
try
{
throw
0
;
}
finally
{
throw
1
;
}
}
catch
(
e
)
{
ok
(
e
===
1
,
"e = "
+
e
);
}
state
=
""
;
try
{
ok
(
state
===
""
,
"try: state = "
+
state
);
state
=
"try"
;
}
catch
(
ex
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment