Age | Commit message (Collapse) | Author |
|
* bjorn/compiler/misc:
beam_bool_SUITE: Cover one more line
beam_utils_SUITE: Cover more lines in beam_utils
beam_reorder: Don't confuse beam_validator
beam_bool: Reject potentially unsafe optimization
v3_core: Don't depend on sys_core_fold for cleaning up
beam_type: Eliminate crash
beam_type: Correct handling of setelement/3
beam_validator: Handle cons literals better
beam_validator: Keep better track of tuple literals
|
|
Make sure we don't optimize code such as:
is_tuple Fail Src
test_arity Fail Src Arity
get_tuple_element Src Pos Dst
is_map Fail Src
If we would reorder the instructions like this:
is_tuple Fail Src
test_arity Fail Src Arity
is_map Fail Src
get_tuple_element Src Pos Dst
beam_validator would complain that the type for Src is a map
instead of a tuple. Since the code has problems to begin with,
there is no need to do the optimization.
|
|
When calculating the sets of registers that must be killed or
unused, registers set in a {protected,_,_,_} block were not
considered. That could result in a crash in the
assertion in beam_utils:live_opt_block/4.
|
|
a3ec2644f5 attempted to teach v3_core not to generate code with
unbound variables. The approach taken in that commit is to
discard all expressions following a badmatch. That does not
work if the badmatch is nested:
{[V] = [] = foo,V},
V
That would be rewritten to:
{error({badmatch,foo})},
V
where V is unbound.
If we were to follow the same approach, the tuple construction
code would have to look out for a badmatch. As would list construction,
begin...end, and so on.
Therefore, as it is impractical to discard all expressions that
follow a badmatch, the only other solution is to ensure that the
variables that the pattern binds will somehow be bound. That can
be arranged by rewriting the pattern to a pattern that binds the
same variables. Thus:
error({badmatch,foo}),
E = foo,
case E of
{[V],[]} ->
V;
Other ->
error({badmatch,Other}
end
|
|
The following code:
simple() ->
case try 0 after [] end of
0 -> college;
1 -> 0
end.
would crash the compiler like this:
crash reason: {case_clause,
{'EXIT',
{function_clause,
[{beam_type,simplify_select_val_int,
[{select,select_val,
{x,0},
{f,7},
[{integer,1},{f,9},{integer,0},{f,8}]},
0],
[{file,"beam_type.erl"},{line,169}]},
{beam_type,simplify_basic_1,3,
[{file,"beam_type.erl"},{line,155}]},
{beam_type,opt,3,[{file,"beam_type.erl"},{line,57}]},
{beam_type,function,1,[{file,"beam_type.erl"},{line,36}]},
{beam_type,'-module/2-lc$^0/1-0-',1,
[{file,"beam_type.erl"},{line,30}]},
{beam_type,module,2,[{file,"beam_type.erl"},{line,30}]},
{compile,'-select_passes/2-anonymous-2-',2,
[{file,"compile.erl"},{line,521}]},
{compile,'-internal_comp/4-anonymous-1-',2,
[{file,"compile.erl"},{line,306}]}]}}}
The root cause is that the type representation is not well-defined.
Integers could be represented in three different ways:
integer
{integer,{1,10}}
{integer,0}
However, only the first two forms were handled.
To avoid similar problems in the future:
* Make the type representation stricter. Make sure that integers are
only represented as 'integer' or {integer,{Min,Max}}.
* Call verify_type/1 whenever a new type is added (not only when
merging types) to ensure that only the supported types are added
to the type database).
(ERL-150)
|
|
We must be careful how we treat the type info for the result of:
setelement(Index, Tuple, NewValue)
If Tuple had type information, the result of setelement/3 (in x(0))
would be assigned the same type information. But that is not safe
for:
setelement(1, Tuple, NewValue)
since the type for the first element will be changed.
Therefore, we must take care to remove the type information for
the first element of the tuple if might have been modified by
setelement/3.
|
|
As a preparation for better optimizations in beam_type, a list
literal must be accepted as a 'cons'.
|
|
As a preparation for upcoming better optimizations in beam_type,
we will need to keep better track of tuple literals so that
beam_validator will not falsely reject safe code.
|
|
Specs of various *_arity functions in this module used different types
(integer(), non_neg_integer(), byte()) to refer to the type arity().
|
|
* bjorn/compiler/beam_bool/ERL-143:
Eliminate crash in beam_bool
Add beam_bool_SUITE
Add missing test cases in andor_SUITE and beam_block_SUITE
|
|
beam_bool would crash when attempting to optimize BEAM code similar
to this code:
bif '=:=' Reg1 SomeValue => y(0)
bif '=:=' Reg2 {atom,true} => x(2)
bif '=:=' Reg3 {atom,true} => x(3)
bif 'or' x(2) x(3) => x(2)
is_eq_exact Fail x(2) {atom,true}
The problem is that the first instruction that assigns a value to a Y
register. beam_bool:ssa_assign/2 will not accept a Y register
argument.
We could change ssa_assign/2 to accept a Y register, but that would
only cause the entire optimization to be rejected later because the Y
register is alive in the code that follows. Therefore, a better
solution is to modify extend_block/3 so that the instruction that
assign to Y registers are not added to the block. That is, the
optimizer will only operate on the following code:
bif '=:=' Reg2 {atom,true} => x(2)
bif '=:=' Reg3 {atom,true} => x(3)
bif 'or' x(2) x(3) => x(2)
is_eq_exact Fail x(2) {atom,true}
Usually the optimization will succeed, rewriting the four instructions
to a select_val instruction.
Assembly code such as the above can be produced by code similar to:
Y = Something == SomethingElse,
case Y of
Condition; OtherCondition ->
. . .
end,
. . .,
Y.
Reported-by: http://bugs.erlang.org/browse/ERL-143
Reported-by: José Valim
|
|
Exported functions in this file should appear at the top of the file.
Also add missing spaces after commas.
|
|
I can't remember that clause ever trigger during development.
Remove it to eliminated an uncovered line.
|
|
check_liveness/3 returns {unknown,State} if an instruction is
not handled. All callers will handle 'unknown' the same way as
'used'. Therefore, we can simplify the code and improve the
coverage if we return {used,State} instead of {unknown,State}.
|
|
|
|
All callers only calls code_at/2 for existing labels and they don't
handle the return value 'none'.
|
|
30cc5c902d moved try/3 instruction inside blocks, so the clause for
handling try/3 in live_opt/4 is never executed.
|
|
Two lines were never covered, because '[]' was used instead of 'nil'.
|
|
The clause for handling #c_values{} in is_simple_term/1 is never
executed. It can be safely removed, since there is a default clause
that will return 'false' in the extremly unlikely event that a
Without the clause, code such as:
let <_v1,_v2> = <1,2>
in {_v1,_v2}
would be printed with an extra newline:
let <_v1,_v2> =
<1,2>
in {_v1,_v2}
|
|
Don't try to be nice. Since we now have good test suites for
Core Erlang, just let it crash.
|
|
|
|
We will get more information if we don't catch the exception.
|
|
Map patterns are never represented as literals. Therefore, a map
literal should always be printed with the 'assoc' operator. That also
means that there is no remaining use of the 'class' field and that it
can be removed from the 'ctxt' record.
|
|
Rewrite code such as:
X = not_a_fun,
X()
to:
error({badfun,not_a_fun})
Also generate a warning.
|
|
'callback' and 'optional_callbacks' are no longer wild attributes.
|
|
* bjorn/compiler/core-erlang-fixes:
Slightly optimize core_pp
v3_core: Don't depend on sys_core_fold for cleaning up
|
|
Dialyzer relies heavily on the assumption that the type of a literal
that is used as a pattern is the type of any value that can match that
pattern. For maps, that is not true, and it was causing bad analysis
results. A new help function dialyzer_utils:refold_pattern/1 identifies
maps in literal patterns, and unfolds and labels them, allowing them to
be properly analysed.
|
|
|
|
v3_core would generate unsafe code for the following example:
f() ->
{ok={error,E}} = foo(),
E.
Internally, the code would look similar to:
f() ->
Var = foo(),
error({badmatch,Var}),
E.
That is, there would remain a reference to an unbound variable.
Normally, sys_core_fold would remove the reference to 'E', but if
if optimization was disabled the compiler would crash.
|
|
Use case in compile.erl is cryptographical so use
crypto:strong_rand_bytes/1 instead.
Use case in test suite is not cryptographical so use
other test instead.
|
|
* bjorn/compiler/remove-timestamps/OTP-13504:
Remove timestamps from BEAM files
|
|
As long as anyone can remember, the compilation time has been included
in BEAM files (and can be retrieved using Mod:module_info(compile)).
The timestamp has caused problems for anyone using tools such as 'cmp'
to compare BEAM files or for package managers:
http://erlang.org/pipermail/erlang-questions/2016-April/088717.html
Rarely has the timestamp been of any use. Yes, sometimes the timestamp
could help to figuring out which version of a module was used, but
nowadays a better way is to use Mod:module_info(md5).
To get rid of this problem, remove the timestamp from BEAM files in
OTP 19. Don't add an option to include timestamps.
Utilities that depend on the timestamp will need to be modified.
For example:
http://erlang.org/pipermail/erlang-questions/2016-April/088730.html
Instead of using the compilation time, the MD5 for the BEAM code can
be used. Example:
1> c:module_info(md5).
<<79,26,188,243,168,60,58,45,34,69,19,222,138,190,214,118>>
2> beam_lib:md5(code:which(c)).
{ok,{c,<<79,26,188,243,168,60,58,45,34,69,19,222,138,190,214,118>>}}
3>
|
|
|
|
This will speed up test cases that print all annotations.
|
|
|
|
If we pretty print to a file and read it back in, we expect to
get the same cerl data structures back.
|
|
Annotations would not be accepted for all constructs.
|
|
Make sure that we don't convert a map pattern to a map expression.
|
|
|
|
|
|
* bjorn/compiler/misc-opt:
v3_kernel: Construct literal lists properly
Use the register map in %live in beam_utils:is_killed_block/2
Teach beam_utils to check liveness for put_map instructions
beam_peep: Help out beam_jump
|
|
Use cerl:make_list/1 instead of a home-made make_list/1 to ensure that
literal lists are constructed as literals. In a future release, we
would like to forbid in the loader construction of literal lists using
instructions like:
put_list {atom,a} [] Dst
The proper way is:
move {literal,[a]} {x,0}
Also update the comment about "put_list Const [] Dst" in ops.tab.
|
|
In 1f0ae04d374, a complete register map was introduced in the %live
instructions thar are added by beam_utils:live_opt/1.
Use the register map to improve beam_utils:is_killed_block/2.
|
|
* henrik/update-copyrightyear:
update copyright-year
|
|
|
|
beam_jump fails to optimize the following:
jump 2
label 1
label 2
Since this situation is rare, instead of complicating beam_jump,
add the optimization to beam_peep. It will always succeed, since
adjacent labels have been coalesced.
|
|
Remove the unreachable instructions after a 'raise' instruction
(e.g. a 'jump' or 'deallocate', 'return') to decrease code size.
|
|
compile:forms/1,2 will crash when the current working directory has
been deleted. Fix that problem, and while we are at it, also stop
including {source,""} in module_info() when no source code file is
given.
Reported-at: http://bugs.erlang.org/browse/ERL-113
Reported-by: Adam Lindberg
|
|
Slightly speed up 'erlc' by pre-loading the modules used
by the compiler. Write a test case to ensure that the correct
set of modules are loaded.
|
|
|