Age | Commit message (Collapse) | Author |
|
* maint:
Update primary bootstrap
beam_bool: Correct live calculation for GC BIFs
beam_bool: Correct indentation for try...catch
sys_core_fold: Correct optimization of 'case'
Conflicts:
bootstrap/bin/start.boot
bootstrap/bin/start_clean.boot
bootstrap/lib/compiler/ebin/beam_asm.beam
bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
|
|
* bjorn/compiler/map-in-record-bug/OTP-12402:
sys_core_fold: Correct optimization of 'case'
|
|
When optimizing boolean expressions, it is not always possible
to find a number of live registers for a GC BIF that both preserves
all source registers that will be tested and at the same time
does not include registers that are not initialized.
As currently implemented, we have incomplete information about
the register calculated from the free variables. Some registers
are marked as "reserved". Reserved registers means that we don't
know anything about them; they may or may not be initialized.
As a conservative correction (suitable for a maintenance release), we
will abort the optimization if we find any reserved registers when
calculating the number of live registers. We will not attempt to
improve the information about the registers in this commit.
By examining the coverage when running the existing compiler test
suite we find that the optimization is aborted 15 times (before
adding any new test cases). To put that in perspective, the
optimization is successfully applied 4927 times, and aborted for
other reasons 547 times.
Reported-by: Ulf Norell
Reported-by: Anthony Ramine
|
|
The optimization of a 'case' statement could lead to incorrect
code that would cause an exception at run-time.
Here is an example to show how the optimization went wrong. Start
with the following code:
f({r,#{key:=Val},X}=S) ->
case S of
{r,_,_} ->
setelement(3, Val, S)
end.
(The record operations have already been translated to the
corresponding tuple operations.) The first step in case_opt/3 is
to substitute S to obtain:
f({r,#{key:=Val},X}=S) ->
case {r,#{key:=Val},X} of
{r,_,_} ->
setelement(3, Val, S)
end.
After that substitution the 'case' can be simplified to:
f({r,#{key:=Val},_}=S) ->
case #{key:=Val} of
NewVar ->
setelement(3, Val, S)
end.
That is the result from case_opt/3. Now eval_case/2 notices
that since there is only one clause left in the 'case', the
'case' can eliminated:
f({r,#{key:=Val},_}=S) ->
NewVar = #{key:=Val},
setelement(3, Val, S).
Since the map construction may have a side effect, it was not
eliminated, but assigned to a variable that is never used.
The problem is that '#{key:=Val}' is fine as a pattern, but in a
construction of a new map, the '=>' operator must be used. So the
map construction will fail, generating an exception.
As a conservative correction for a maintenance release, we will
abort the 'case' optimization if the substitution into the 'case'
expression is anything but data items (tuples, conses, or
literals) or variables.
Reported-by: Dmitry Aleksandrov
|
|
While we are, clean up the comments and rearrange the code for
clarity. Also add a test to cover the last uncovered line in
beam_dead.erl.
|
|
Amend the test suite to call beam_dead as originally intended (and not
beam_block), and modify the input data so that the exception will
occur within the try ... catch block in function/2.
|
|
The BEAM compiler translates code such as:
is_hex_digit(D) when $0 =< D, D =< $9 -> true;
is_hex_digit(D) when $a =< D, D =< $z -> true;
is_hex_digit(D) when $A =< D, D =< $Z -> true;
is_hex_digit(_) -> false.
to something like this:
L0: test is_ge L1 {x,0} 48
test is_ge L1 57 {x,0}
move true {x,0}
return.
L1: test is_ge L2 {x,0} 97
test is_ge L2 122 {x,0}
move true {x,0}
return
L2: test is_ge L3 {x,0} 65
test is_ge L3 90 {x,0}
move true {x,0}
return
L3: move false {x,0}
return
We can see that tests will be repeated even if they cannot possibly
succeed. For instance, if we pass in {x,0} equal to 32, the first
test that {x,0} is greater than or equal to 48 at L0 will fail.
The control will transfer to L1, where it will be tested whether
{x,0} is greater than 97. That test will fail and control
will pass to L2, where again the test will fail.
The compiler can do better by short-circuiting repeating tests:
L0: test is_ge L3 {x,0} 48
test is_ge L1 57 {x,0}
move true {x,0}
return.
L1: test is_ge L2 {x,0} 97
test is_ge L3 122 {x,0}
move true {x,0}
return
L2: test is_ge L3 {x,0} 65
test is_ge L3 90 {x,0}
move true {x,0}
return
L3: move false {x,0}
return
|
|
* maint:
Fix miscompilation when module contains multiple named funs
Fix locations of shadowing warnings in ms_transform
|
|
A module containing two named funs bearing the same name and arity could be
miscompiled.
Reported-by: Sam Chapin
|
|
* tuncer/compiler/finalize-asm-deprecation/OTP-12100:
compiler: finalize 18.x 'asm' deprecation
|
|
* egil/maps/variable-keys/OTP-12218: (22 commits)
compiler: Update test for Maps aliasing
compiler: Properly support Map aliasing
compiler: Refactor Map pairs aliasing
compiler: Fix harmless need_heap error for Maps
stdlib: Update Map tests
stdlib: Use environment bindings for Maps keys in erl_eval matching
debugger: Update Map tests
compiler: Update Map tests
compiler: Fix v3_core Maps pair chains
compiler: Use expressions in core patterns
compiler: Use variables in Map cerl inliner
compiler: Reintroduce binary limit for Map keys
compiler: Shameless v3_core hack for variables
compiler: Use variables in Map beam assmebler
compiler: Use variables in Map kernel pass
compiler: Use variables in Map core pass
compiler: Normalize unary ops on Maps key literals
stdlib: Update Map tests
stdlib: erl_lint Map key variables
compiler: Maps are always patterns never values in matching
...
|
|
|
|
|
|
'asm' was deprecated in 18315c16, to be removed in 18.x.
|
|
* nox/compiler/improve-core-lint:
Remove obsolete comment in core_lint
Handle return mismatches for calls and primops
Check for more return mismatches
Use +clint0 in compiler's test suites
|
|
|
|
The fallback to latin-1 encoding would not work if the invalid
UTF-8 characters occurred in a skipped branch in an -ifdef/-ifndef.
|
|
|
|
* egil/maps-compiler-coverage:
compiler: Do not evaluate map expressions with bad keys
compiler: Throw 'nomatch' on matching with bad binary keys
compiler: Variable keys are not allowed in Maps
compiler: Strengthen Maps warnings tests
compiler: map_pair cannot be a type clause in v3_life
compiler: Remove redudant code in v3_codegen
compiler: Test deep map structure
compiler: Remove redundant clause in v3_codegen
compiler: Cover #{ [] => Var } in testcase
|
|
Map keys with large (non literal) binary keys must fail.
|
|
Even if a binary key is written as a literal the compiler may
choose to make an expression. Emit a warning in those cases
and saying the case will not match.
This is a limitation in current implementation.
|
|
Increases coverage.
|
|
The pass sys_core_fold did not correctly handle non-matching patterns in code
such as:
0 = case <<>> of
<<>> -> 0;
a -> 1
end.
Function case_opt_lit/3 is rewritten in two passes to first remove any
non-matching clause and only then potentially remove the related patterns
in each clause.
Reported-by: Ulf Norell
|
|
|
|
Coverage removed by literals.
|
|
* nox/maps-v3_core-lit_vars:
Properly collect variables in map expressions in v3_core
|
|
* bjorn/compiler/utf8-warning/OTP-11791:
Don't fail compilation for modules that contain invalid UTF-8
epp: Make it possible to specify a default encoding
|
|
The default encoding for Erlang modules is now UTF-8, and the
compilation would fail if a module contained byte sequences that
are not valid UTF-8 sequences.
In a large project with say many hundreds of Erlang modules
with names of developers such as "Björn" or "Håkan" encoded in
latin-1, that could mean that many hundreds of files would need
to be modified just to get started testing OTP 17.
As a temporary measure to ease the transition, automatically
fall back to the latin-1 encoding with a warning for any module
that contains invalid byte sequences and for which no encoding
has been specified.
The intention is to remove this workaround in OTP 18 or 19.
|
|
Reported-by: José Valim
|
|
Ex.
Instead of:
M~{~<K,V>}~
The format is now:
~{~<K,V>|M}~
This also removes a shift/reduce warning.
The changes in core_pp now requires compiler-5.0 to compile
because of is_map/1 guard, i.e. a need for a compiler with Maps know-how.
|
|
* nox/compiler/beam_bool-mixed-boolean:
Properly detect reused boolean values in beam_bool
|
|
Boolean case expressions with redundant clauses could make the compiler
crash:
case X == 0 of
false -> no;
false -> no;
true -> yes
end.
Reported-by: Ulf Norell
|
|
The following code could crash the compiler:
f(X = true) when X or true or X -> ok.
Reported-by: Ulf Norell
|
|
* nox/maps-beam_jump-put_map:
Properly collect labels in put_map instructions in beam_jump
|
|
* nox/maps-cerl_clauses:
Support maps in cerl_clauses:match/2
|
|
* nox/maps-beam_jump:
Properly check label use in get_map_elements in beam_jump
|
|
* nox/maps-v3_codegen-sort-nil-keys:
Properly sort map pairs in v3_codegen
|
|
* nox/maps-complex-mixed-values:
Properly order Kernel code for maps with mixed pairs
|
|
* nox/compiler/v3_core-comprehension-no-export:
Do not export variables from comprehension cases in v3_core
OTP-11770
|
|
* nox/compiler/beam_bool-not_boolean_expr:
Compile BIF calls and operator expressions to Core the same way
Do not try to optimize non-boolean guards
|
|
Reported-by: Ulf Norell
|
|
* nox/compiler/beam_bool-bad-protected:
Properly detect nonboolean protected expressions in beam_bool
|
|
* nox/compiler/live_opt-wait_timeout-nil:
Handle nil as a wait_timeout argument in beam_utils:live_opt/4
|
|
* nox/compiler/sys_core_fold-erlang-is_function-2:
Do not mark all calls to erlang:is_function/2 as safe
|
|
Code like the following snippet could make the compiler crash:
f() -> [X = a || false] ++ [X = a || false].
Reported-by: Ulf Norell
|
|
Expressions such as erlang:'or'(bar, true) can make beam_bool crash if it tries
to optimize them, as this code is not quite really written by users, no attempt
to rewrite them more efficiently should be done, for simplicity's sake.
Reported-by: Ulf Norell
|
|
Reported-by: Ulf Norell
|
|
Without this, sys_core_fold could crash on non-matching clauses using maps
patterns.
Reported-by: Ulf Norell
|
|
The Kernel instructions were not properly ordered when compiling maps with
complex values mixed in assoc and exact pairs.
Reported-by: Ulf Norell
|
|
Literal nil values aren't tagged tuple but the bare atom nil.
The function lists:sort/2 expects the passed function to return true if the first
element is less than or equal to the second, not strictly less than. The original
base clause is changed accordingly.
Reported-by: Ulf Norell
|