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
2e06686e
Commit
2e06686e
authored
Aug 04, 2016
by
Jacek Caban
Committed by
Alexandre Julliard
Aug 04, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
jscript: Use locals map for local variables.
Signed-off-by:
Jacek Caban
<
jacek@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
2fc67209
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
366 additions
and
32 deletions
+366
-32
compile.c
dlls/jscript/compile.c
+364
-31
engine.c
dlls/jscript/engine.c
+1
-1
parser.h
dlls/jscript/parser.h
+1
-0
No files found.
dlls/jscript/compile.c
View file @
2e06686e
...
...
@@ -61,9 +61,6 @@ typedef struct {
statement_ctx_t
*
stat_ctx
;
function_code_t
*
func
;
variable_declaration_t
*
var_head
;
variable_declaration_t
*
var_tail
;
function_expression_t
*
func_head
;
function_expression_t
*
func_tail
;
}
compiler_ctx_t
;
...
...
@@ -878,9 +875,7 @@ static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expres
static
HRESULT
compile_function_expression
(
compiler_ctx_t
*
ctx
,
function_expression_t
*
expr
,
BOOL
emit_ret
)
{
unsigned
func_id
=
ctx
->
func
->
func_cnt
++
;
ctx
->
func_tail
=
ctx
->
func_tail
?
(
ctx
->
func_tail
->
next
=
expr
)
:
(
ctx
->
func_head
=
expr
);
return
emit_ret
?
push_instr_uint
(
ctx
,
OP_func
,
func_id
)
:
S_OK
;
return
emit_ret
?
push_instr_uint
(
ctx
,
OP_func
,
expr
->
func_id
)
:
S_OK
;
}
static
HRESULT
compile_expression
(
compiler_ctx_t
*
ctx
,
expression_t
*
expr
,
BOOL
emit_ret
)
...
...
@@ -1096,17 +1091,7 @@ static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t
assert
(
list
!=
NULL
);
if
(
ctx
->
var_tail
)
ctx
->
var_tail
->
global_next
=
list
;
else
ctx
->
var_head
=
list
;
for
(
iter
=
list
;
iter
;
iter
=
iter
->
next
)
{
ctx
->
func
->
var_cnt
++
;
iter
->
global_next
=
iter
->
next
;
if
(
!
iter
->
next
)
ctx
->
var_tail
=
iter
;
if
(
!
iter
->
expr
)
continue
;
...
...
@@ -1791,7 +1776,7 @@ static int local_cmp(const void *key, const void *ref)
return
strcmpW
((
const
WCHAR
*
)
key
,
((
const
local_ref_t
*
)
ref
)
->
name
);
}
static
inline
local_ref_t
*
find_local
(
compiler_ctx_t
*
ctx
,
BSTR
name
)
static
inline
local_ref_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
);
}
...
...
@@ -1826,6 +1811,351 @@ static BOOL alloc_local(compiler_ctx_t *ctx, BSTR name, int ref)
return
TRUE
;
}
static
BOOL
alloc_variable
(
compiler_ctx_t
*
ctx
,
const
WCHAR
*
name
)
{
BSTR
ident
;
if
(
find_local
(
ctx
,
name
))
return
TRUE
;
ident
=
compiler_alloc_bstr
(
ctx
,
name
);
if
(
!
ident
)
return
FALSE
;
return
alloc_local
(
ctx
,
ident
,
ctx
->
func
->
var_cnt
++
);
}
static
void
visit_function_expression
(
compiler_ctx_t
*
ctx
,
function_expression_t
*
expr
)
{
expr
->
func_id
=
ctx
->
func
->
func_cnt
++
;
ctx
->
func_tail
=
ctx
->
func_tail
?
(
ctx
->
func_tail
->
next
=
expr
)
:
(
ctx
->
func_head
=
expr
);
}
static
HRESULT
visit_expression
(
compiler_ctx_t
*
ctx
,
expression_t
*
expr
)
{
HRESULT
hres
=
S_OK
;
switch
(
expr
->
type
)
{
case
EXPR_ADD
:
case
EXPR_AND
:
case
EXPR_ARRAY
:
case
EXPR_ASSIGN
:
case
EXPR_ASSIGNADD
:
case
EXPR_ASSIGNAND
:
case
EXPR_ASSIGNSUB
:
case
EXPR_ASSIGNMUL
:
case
EXPR_ASSIGNDIV
:
case
EXPR_ASSIGNMOD
:
case
EXPR_ASSIGNOR
:
case
EXPR_ASSIGNLSHIFT
:
case
EXPR_ASSIGNRSHIFT
:
case
EXPR_ASSIGNRRSHIFT
:
case
EXPR_ASSIGNXOR
:
case
EXPR_BAND
:
case
EXPR_BOR
:
case
EXPR_COMMA
:
case
EXPR_DIV
:
case
EXPR_EQ
:
case
EXPR_EQEQ
:
case
EXPR_GREATER
:
case
EXPR_GREATEREQ
:
case
EXPR_IN
:
case
EXPR_INSTANCEOF
:
case
EXPR_LESS
:
case
EXPR_LESSEQ
:
case
EXPR_LSHIFT
:
case
EXPR_MOD
:
case
EXPR_MUL
:
case
EXPR_NOTEQ
:
case
EXPR_NOTEQEQ
:
case
EXPR_OR
:
case
EXPR_RSHIFT
:
case
EXPR_RRSHIFT
:
case
EXPR_SUB
:
case
EXPR_BXOR
:
{
binary_expression_t
*
binary_expr
=
(
binary_expression_t
*
)
expr
;
hres
=
visit_expression
(
ctx
,
binary_expr
->
expression1
);
if
(
FAILED
(
hres
))
return
hres
;
hres
=
visit_expression
(
ctx
,
binary_expr
->
expression2
);
break
;
}
case
EXPR_BITNEG
:
case
EXPR_DELETE
:
case
EXPR_LOGNEG
:
case
EXPR_MINUS
:
case
EXPR_PLUS
:
case
EXPR_POSTDEC
:
case
EXPR_POSTINC
:
case
EXPR_PREDEC
:
case
EXPR_PREINC
:
case
EXPR_TYPEOF
:
case
EXPR_VOID
:
hres
=
visit_expression
(
ctx
,
((
unary_expression_t
*
)
expr
)
->
expression
);
break
;
case
EXPR_IDENT
:
case
EXPR_LITERAL
:
case
EXPR_THIS
:
break
;
case
EXPR_ARRAYLIT
:
{
array_literal_expression_t
*
array_expr
=
(
array_literal_expression_t
*
)
expr
;
array_element_t
*
iter
;
for
(
iter
=
array_expr
->
element_list
;
iter
;
iter
=
iter
->
next
)
{
hres
=
visit_expression
(
ctx
,
iter
->
expr
);
if
(
FAILED
(
hres
))
return
hres
;
}
break
;
}
case
EXPR_CALL
:
case
EXPR_NEW
:
{
call_expression_t
*
call_expr
=
(
call_expression_t
*
)
expr
;
argument_t
*
arg
;
hres
=
visit_expression
(
ctx
,
call_expr
->
expression
);
if
(
FAILED
(
hres
))
return
hres
;
for
(
arg
=
call_expr
->
argument_list
;
arg
;
arg
=
arg
->
next
)
{
hres
=
visit_expression
(
ctx
,
arg
->
expr
);
if
(
FAILED
(
hres
))
return
hres
;
}
break
;
}
case
EXPR_COND
:
{
conditional_expression_t
*
cond_expr
=
(
conditional_expression_t
*
)
expr
;
hres
=
visit_expression
(
ctx
,
cond_expr
->
expression
);
if
(
FAILED
(
hres
))
return
hres
;
hres
=
visit_expression
(
ctx
,
cond_expr
->
true_expression
);
if
(
FAILED
(
hres
))
return
hres
;
hres
=
visit_expression
(
ctx
,
cond_expr
->
false_expression
);
break
;
}
case
EXPR_FUNC
:
visit_function_expression
(
ctx
,
(
function_expression_t
*
)
expr
);
break
;
case
EXPR_MEMBER
:
hres
=
visit_expression
(
ctx
,
((
member_expression_t
*
)
expr
)
->
expression
);
break
;
case
EXPR_PROPVAL
:
{
prop_val_t
*
iter
;
for
(
iter
=
((
property_value_expression_t
*
)
expr
)
->
property_list
;
iter
;
iter
=
iter
->
next
)
{
hres
=
visit_expression
(
ctx
,
iter
->
value
);
if
(
FAILED
(
hres
))
return
hres
;
}
break
;
}
DEFAULT_UNREACHABLE
;
}
return
hres
;
}
static
HRESULT
visit_variable_list
(
compiler_ctx_t
*
ctx
,
variable_declaration_t
*
list
)
{
variable_declaration_t
*
iter
;
HRESULT
hres
;
for
(
iter
=
list
;
iter
;
iter
=
iter
->
next
)
{
if
(
!
alloc_variable
(
ctx
,
iter
->
identifier
))
return
E_OUTOFMEMORY
;
if
(
iter
->
expr
)
{
hres
=
visit_expression
(
ctx
,
iter
->
expr
);
if
(
FAILED
(
hres
))
return
hres
;
}
}
return
S_OK
;
}
static
HRESULT
visit_statement
(
compiler_ctx_t
*
,
statement_t
*
);
static
HRESULT
visit_block_statement
(
compiler_ctx_t
*
ctx
,
statement_t
*
iter
)
{
HRESULT
hres
;
while
(
iter
)
{
hres
=
visit_statement
(
ctx
,
iter
);
if
(
FAILED
(
hres
))
return
hres
;
iter
=
iter
->
next
;
}
return
S_OK
;
}
static
HRESULT
visit_statement
(
compiler_ctx_t
*
ctx
,
statement_t
*
stat
)
{
HRESULT
hres
=
S_OK
;
switch
(
stat
->
type
)
{
case
STAT_BLOCK
:
hres
=
visit_block_statement
(
ctx
,
((
block_statement_t
*
)
stat
)
->
stat_list
);
break
;
case
STAT_BREAK
:
case
STAT_CONTINUE
:
case
STAT_EMPTY
:
break
;
case
STAT_EXPR
:
case
STAT_RETURN
:
case
STAT_THROW
:
{
expression_statement_t
*
expr_stat
=
(
expression_statement_t
*
)
stat
;
if
(
expr_stat
->
expr
)
hres
=
visit_expression
(
ctx
,
expr_stat
->
expr
);
break
;
}
case
STAT_FOR
:
{
for_statement_t
*
for_stat
=
(
for_statement_t
*
)
stat
;
if
(
for_stat
->
variable_list
)
hres
=
visit_variable_list
(
ctx
,
for_stat
->
variable_list
);
else
if
(
for_stat
->
begin_expr
)
hres
=
visit_expression
(
ctx
,
for_stat
->
begin_expr
);
if
(
FAILED
(
hres
))
break
;
if
(
for_stat
->
expr
)
{
hres
=
visit_expression
(
ctx
,
for_stat
->
expr
);
if
(
FAILED
(
hres
))
break
;
}
hres
=
visit_statement
(
ctx
,
for_stat
->
statement
);
if
(
FAILED
(
hres
))
break
;
if
(
for_stat
->
end_expr
)
hres
=
visit_expression
(
ctx
,
for_stat
->
end_expr
);
break
;
}
case
STAT_FORIN
:
{
forin_statement_t
*
forin_stat
=
(
forin_statement_t
*
)
stat
;
if
(
forin_stat
->
variable
)
{
hres
=
visit_variable_list
(
ctx
,
forin_stat
->
variable
);
if
(
FAILED
(
hres
))
break
;
}
hres
=
visit_expression
(
ctx
,
forin_stat
->
in_expr
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
forin_stat
->
expr
)
{
hres
=
visit_expression
(
ctx
,
forin_stat
->
expr
);
if
(
FAILED
(
hres
))
return
hres
;
}
hres
=
visit_statement
(
ctx
,
forin_stat
->
statement
);
break
;
}
case
STAT_IF
:
{
if_statement_t
*
if_stat
=
(
if_statement_t
*
)
stat
;
hres
=
visit_expression
(
ctx
,
if_stat
->
expr
);
if
(
FAILED
(
hres
))
return
hres
;
hres
=
visit_statement
(
ctx
,
if_stat
->
if_stat
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
if_stat
->
else_stat
)
hres
=
visit_statement
(
ctx
,
if_stat
->
else_stat
);
break
;
}
case
STAT_LABEL
:
hres
=
visit_statement
(
ctx
,
((
labelled_statement_t
*
)
stat
)
->
statement
);
break
;
case
STAT_SWITCH
:
{
switch_statement_t
*
switch_stat
=
(
switch_statement_t
*
)
stat
;
statement_t
*
stat_iter
;
case_clausule_t
*
iter
;
hres
=
visit_expression
(
ctx
,
switch_stat
->
expr
);
if
(
FAILED
(
hres
))
return
hres
;
for
(
iter
=
switch_stat
->
case_list
;
iter
;
iter
=
iter
->
next
)
{
if
(
!
iter
->
expr
)
continue
;
hres
=
visit_expression
(
ctx
,
iter
->
expr
);
if
(
FAILED
(
hres
))
return
hres
;
}
for
(
iter
=
switch_stat
->
case_list
;
iter
;
iter
=
iter
->
next
)
{
while
(
iter
->
next
&&
iter
->
next
->
stat
==
iter
->
stat
)
iter
=
iter
->
next
;
for
(
stat_iter
=
iter
->
stat
;
stat_iter
&&
(
!
iter
->
next
||
iter
->
next
->
stat
!=
stat_iter
);
stat_iter
=
stat_iter
->
next
)
{
hres
=
visit_statement
(
ctx
,
stat_iter
);
if
(
FAILED
(
hres
))
return
hres
;
}
}
break
;
}
case
STAT_TRY
:
{
try_statement_t
*
try_stat
=
(
try_statement_t
*
)
stat
;
hres
=
visit_statement
(
ctx
,
try_stat
->
try_statement
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
try_stat
->
catch_block
)
{
hres
=
visit_statement
(
ctx
,
try_stat
->
catch_block
->
statement
);
if
(
FAILED
(
hres
))
return
hres
;
}
if
(
try_stat
->
finally_statement
)
hres
=
visit_statement
(
ctx
,
try_stat
->
finally_statement
);
break
;
}
case
STAT_VAR
:
hres
=
visit_variable_list
(
ctx
,
((
var_statement_t
*
)
stat
)
->
variable_list
);
break
;
case
STAT_WHILE
:
{
while_statement_t
*
while_stat
=
(
while_statement_t
*
)
stat
;
hres
=
visit_expression
(
ctx
,
while_stat
->
expr
);
if
(
FAILED
(
hres
))
return
hres
;
hres
=
visit_statement
(
ctx
,
while_stat
->
statement
);
break
;
}
case
STAT_WITH
:
{
with_statement_t
*
with_stat
=
(
with_statement_t
*
)
stat
;
hres
=
visit_expression
(
ctx
,
with_stat
->
expr
);
if
(
FAILED
(
hres
))
return
hres
;
hres
=
visit_statement
(
ctx
,
with_stat
->
statement
);
break
;
}
DEFAULT_UNREACHABLE
;
}
return
hres
;
}
static
void
resolve_labels
(
compiler_ctx_t
*
ctx
,
unsigned
off
)
{
instr_t
*
instr
;
...
...
@@ -1890,14 +2220,12 @@ static HRESULT init_code(compiler_ctx_t *compiler, const WCHAR *source)
static
HRESULT
compile_function
(
compiler_ctx_t
*
ctx
,
source_elements_t
*
source
,
function_expression_t
*
func_expr
,
BOOL
from_eval
,
function_code_t
*
func
)
{
variable_declaration_t
*
var_iter
;
function_expression_t
*
iter
;
unsigned
off
,
i
;
unsigned
off
,
i
,
j
;
HRESULT
hres
;
TRACE
(
"
\n
"
);
ctx
->
var_head
=
ctx
->
var_tail
=
NULL
;
ctx
->
func_head
=
ctx
->
func_tail
=
NULL
;
ctx
->
from_eval
=
from_eval
;
ctx
->
func
=
func
;
...
...
@@ -1928,6 +2256,10 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source,
return
E_OUTOFMEMORY
;
}
hres
=
visit_block_statement
(
ctx
,
source
->
statement
);
if
(
FAILED
(
hres
))
return
hres
;
off
=
ctx
->
code_off
;
hres
=
compile_block_statement
(
ctx
,
source
->
statement
);
if
(
FAILED
(
hres
))
...
...
@@ -1958,23 +2290,24 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source,
}
}
func
->
locals
=
compiler_alloc
(
ctx
->
code
,
ctx
->
locals_cnt
*
sizeof
(
*
func
->
locals
));
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
(
var_iter
=
ctx
->
var_head
,
i
=
0
;
var_iter
;
var_iter
=
var_iter
->
global_next
,
i
++
)
{
func
->
variables
[
i
]
=
compiler_alloc_bstr
(
ctx
,
var_iter
->
identifier
);
if
(
!
func
->
variables
[
i
])
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
]
=
func
->
locals
[
i
].
name
;
j
++
;
}
assert
(
i
==
func
->
var_cnt
);
func
->
locals
=
compiler_alloc
(
ctx
->
code
,
ctx
->
locals_cnt
*
sizeof
(
*
func
->
locals
));
if
(
!
func
->
locals
)
return
E_OUTOFMEMORY
;
func
->
locals_cnt
=
ctx
->
locals_cnt
;
memcpy
(
func
->
locals
,
ctx
->
locals_buf
,
func
->
locals_cnt
*
sizeof
(
*
func
->
locals
));
assert
(
j
==
func
->
var_cnt
);
func
->
funcs
=
compiler_alloc
(
ctx
->
code
,
func
->
func_cnt
*
sizeof
(
*
func
->
funcs
));
if
(
!
func
->
funcs
)
...
...
dlls/jscript/engine.c
View file @
2e06686e
...
...
@@ -617,7 +617,7 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re
local_ref_t
*
ref
=
bsearch
(
identifier
,
func
->
locals
,
func
->
locals_cnt
,
sizeof
(
*
func
->
locals
),
local_ref_cmp
);
static
const
WCHAR
argumentsW
[]
=
{
'a'
,
'r'
,
'g'
,
'u'
,
'm'
,
'e'
,
'n'
,
't'
,
's'
,
0
};
if
(
ref
)
{
if
(
ref
&&
ref
->
ref
<
0
)
{
ret
->
type
=
EXPRVAL_STACK_REF
;
ret
->
u
.
off
=
scope
->
frame
->
arguments_off
-
ref
->
ref
-
1
;
return
S_OK
;
...
...
dlls/jscript/parser.h
View file @
2e06686e
...
...
@@ -294,6 +294,7 @@ typedef struct _function_expression_t {
source_elements_t
*
source_elements
;
const
WCHAR
*
src_str
;
DWORD
src_len
;
unsigned
func_id
;
struct
_function_expression_t
*
next
;
/* for compiler */
}
function_expression_t
;
...
...
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