Age | Commit message (Collapse) | Author |
|
The run-time system stopped paying attention the 'aligned' flag in bit
syntax construction and matching when bitstrings were introduced in
language.
The beam_asm compiler pass will crash if the 'aligned' flag is given
in bit syntax instructions.
beam_validator still validates the 'aligned' flag. Before
912fea0b712a (which removed the possibility to validate existing
BEAM files), the 'aligned' flag could actually be encountered
when validating a BEAM file.
Since the validation of 'aligned' no longer serves any useful
purpose, remove the validation code.
|
|
set_type_y/3 is far too complicated. Note that we don't need to check
the #st.numy field, because we will detect the error anyway because
the information for the y register will be missing in the #st.y
gb_tree.
There is also a clause that would never match because of a spelling
error (the first "n" was missing in "uninitialized"). That clause
is not needed because the default clause will do fine.
Furthermore, we can break out the special case for handling catch_end
and similar instructions into a new function.
|
|
The fault/1,2 BIF was removed a long time ago.
|
|
When matching a binary literal as in:
<<"abc">> = Bin
the compiler will produce a sequence of three instructions
(some details in the instructions removed for simplicity):
bs_start_match2 Fail BinReg CtxtReg
bs_match_string Fail CtxtReg "abc"
bs_test_tail2 Fail CtxtReg 0
The sequence can be replaced with:
is_eq_exact Fail BinReg "abc"
|
|
To run eprof for a compiler pass:
erlc +'{eprof,beam_asm}' file.erl
The name of the compiler pass is the name as printed when
'time' option is used. It is usually, but not always, the module
name for the compiler pass.
|
|
If we want to have test cases that run eprof, we must make sure that
there are no modules loaded that don't have a working module_info/1
function, since eprof calls module_info(functions) to retrieve the
list of functions in the module. Some test cases load modules compiled
from Core Erlang that don't have any module_info/1 functions, so
we will need make sure that all such modules have been unloaded.
Add z_SUITE:loaded/1 to run after all other test cases to verify that
all modules that the code server consider loaded are indeed loaded and
all have working module_info/0,1 functions.
|
|
For tidiness, always place .core files in data directories.
|
|
The .core or .S files that are compiled in the test cases
may lack module_info/0,1 functions, which will cause problems if
we (for example) try to run eprof later. To avoid that problem,
unload each module directly after testing it.
|
|
Don't unload modules using BIFs; use the code server to ensure
that code:all_loaded/0 only lists code that is actually loaded.
|
|
According to EEP-43 for maps, a 'badmap' exception should be
generated when an attempt is made to update non-map term such as:
<<>>#{a=>42}
That was not implemented in the OTP 17.
José Valim suggested that we should take the opportunity to
improve the errors coming from map operations:
http://erlang.org/pipermail/erlang-questions/2015-February/083588.html
This commit implement better errors from map operations similar
to his suggestion.
When a map update operation (Map#{...}) or a BIF that expects a map
is given a non-map term, the exception will be:
{badmap,Term}
This kind of exception is similar to the {badfun,Term} exception
from operations that expect a fun.
When a map operation requires a key that is not present in a map,
the following exception will be raised:
{badkey,Key}
José Valim suggested that the exception should be
{badkey,Key,Map}. We decided not to do that because the map
could potentially be huge and cause problems if the error
propagated through links to other processes.
For BIFs, it could be argued that the exceptions could be simply
'badmap' and 'badkey', because the bad map and bad key can be found in
the argument list for the BIF in the stack backtrace. However, for the
map update operation (Map#{...}), the bad map or bad key will not be
included in the stack backtrace, so that information must be included
in the exception reason itself. For consistency, the BIFs should raise
the same exceptions as update operation.
If more than one key is missing, it is undefined which of
keys that will be reported in the {badkey,Key} exception.
|
|
The BEAM loader will now sort keys for maps during loading, so
beam_validator should not require the keys to be ordered any order.
However, we must still ensure that literals keys are unique (which
was implicitly guaranteed by the strict ordering requirement).
|
|
To be sure that the compiler and BEAM virtual machine correctly
handles literals maps, we must test it.
|
|
|
|
|
|
* egil/maps/hamt/OTP-12585: (113 commits)
erts: Fix bug in ESTACK and WSTACK
kernel: Add spec for erts_debug:map_info/1
mnesia: Update mnesia tests to reflect new ETS hash
erts: Ensure maps uses _rel functions in halfword
erts: Do not treat errors as fatal in erl_printf_term
erts: Update preloaded erts_internal.beam
erts: Add map decomposition wrappers
erts: Ensure halfword has correct temp-heap for maps
hipe: Handle separate hashmap tag correctly
erts: Fix map bug in dec_term for 32-bit debug VM
stdlib: Update qlc tests to reflect new ETS hash
stdlib: Remove obsolete hashmap references in io_lib
erts: Enhance maps ordering tests
hipe: Fix maps sort order testcase
erts: Remove unused variable in crashdump creation
erts: Fix typo in copy_struct for halfword emulator
erts: Restrict GCC intrinsics by compiler version
erts: Fix windows bug in hashmap_info
erts: Fix typo in make_hash2 for 32-bit arch
Fix beam_load assert
...
Conflicts:
erts/emulator/beam/bif.tab
|
|
where key 1 is less than key 1.0
|
|
Duplicated variables as aliases in patterns, such as:
f({_,_}=Dup=Dup) -> ...
will work, but produce sub-optimal code similar to:
f({_,_}=Dup=NewVar) when Dup =:= NewVar -> ...
with one extra guard test for each duplicated variable.
Rewrite pat_alias/2 to eliminate all duplicated variables. While
we are at it, also simplify handling of tuples, conses, and literals
by using the data functions in the cerl module.
|
|
Optimize away 'not' in sys_core_fold instead of in beam_block
and beam_dead, as we can do a better job in sys_core_fold.
I modified the test suite temporarily to never turn off Core Erlang
modifications and looked at the coverage. With the new optimizations
active in sys_core_fold, the code in beam_block and beam_dead did not
find a single 'not' that it could optimize. That proves that the new
optimization is at least as good as the old one. Manually, I could
also verify that the new optimization would optimize some variations
of 'not' that the old one would not handle.
|
|
The 'try' ... 'catch' is problematic. Firstly, if no optimization
is possible, an exception will always be thrown. Secondly, bugs
in the code will go unnoticed.
|
|
|
|
Make sure that we take extract all possible type information when
optimizing a 'let' construct.
Since the stronger optimization may generate false warnings, we also
need to take special care to suppress false warnings.
|
|
If we have a sequence of put_map_* instructions operating on the
same map, it will be more efficient if we can have one is_map/2
instruction before put_map_* instructions, so that each put_map_*
does not need to test whether the argument is a map.
|
|
When calculating the number of live registers for allocation
instruction, it is not always safe to start with the number of live
registers at the start of the block. We will need to use the register
map to know whether there are any holes (dead registers) that are not
subsequently filled.
If the allocation instruction already has a number of live registers
calculated, there is nothing to be gained by raising it.
|
|
As a preparation for fixing a bug, introduce a complete register
map in the '%live' annotations.
|
|
* bjorn/compiler/beam_jump-share:
beam_jump: Don't jump into the middle of a 'try'
|
|
* bjorn/compiler/sys_core_fold:
sys_core_fold: Fix non-tail-recursive list comprehensions
|
|
* bjorn/compiler/beam_validator:
beam_validator: Exit immediately on crashes
beam_validator: Remove the file/1 and files/1 functions
beam_validator: Remove support for all other unsupported instructions
beam_validator: Remove support for unsupported bit syntax instructions
|
|
649d6e73 simplified opt_simple_let_2/6 a little bit too much,
so that some list comprehensions in effect context were not
properly tail-recursive.
|
|
The code sharing optimization could produce a jump into the
middle of a 'try' block. beam_validator would reject the code.
Reported-by: Ulf Norell
|
|
The beam_validator catches all exceptions and collect them.
It makes more sense to don't catch 'error' and 'exit' exceptions,
but to just print out the name of the current function and pass
on the exception just as all other compilation passes do. Those
kind of exceptions are the symptoms of the kind of severe but
easily catched bugs that occur during development.
|
|
Before the beam_validator was added as compiler pass, it was a
standalone module that could analyse existing .beam files and .S
files.
Even though beam_validator has been part of the compiler for many
releases, it still supports the analysis of .beam and .S files.
To reduce the code bloat and to improve coverage of beam_validator,
remove the file/1 and files/1 functions and all associated help
functions. We'll need to update the test suite, since some of the
checked in .S files have errors that beam_validator ignores, but
that will not be accepted when running them throught the compiler
using the 'from_asm' option. In particular, we will need to export
all functions that should be validated (since the beam_clean pass
will remove any function that is not possible to call).
|
|
|
|
|
|
The assert_strict_literal_termorder/1 function is used to validate the
get_map_elements and has_map_fields instructions. In neither case is
it useful to allow an empty lists of fields, so we should no longer
allow an empty list.
The mmap/2 function is cute, but it is used in only one place, so it
is much simpler to write a special-purpose function to extract the
keys from the list of map pairs.
|
|
|
|
|
|
Introduce access functions to hide the low-level details of how
type information is implemented.
|
|
This module is the last that uses -include() instead of
include_lib(). With that change, a quick smoke test can
be done simply like this:
PATH=$ERL_TOP/bin:$PATH erlc -W0 *.erl
Without the change, you would also need to add
-I $ERL_TOP/lib/test_server/include
to the command line.
|
|
* bjorn/compiler/dup-bug-fix/OTP-12453:
Teach case_opt/3 to avoid unnecessary building
sys_core_fold: Optimize let statements more aggressively
Suppress warnings for expressions that are assigned to '_'
trace_bif_SUITE: Ensure that a call to time/0 is not removed
|
|
* bjorn/compiler/map-core-syntax/OTP-12454:
Make the syntax for map pairs readable
|
|
* maint:
Update primary bootstrap
Correct unsafe optimization of '==' and '/='
Conflicts:
bootstrap/lib/compiler/ebin/sys_core_fold.beam
|
|
Since '=:=' is cheaper than '==', the compiler tries to replace
'==' with '=:=' if the result of comparison will be the same.
As an example:
V == {a,b}
can be rewritten to:
V =:= {a,b}
since the literal on the right side contains no numeric values
that '==' would compare differently to '=:='.
With the introduction of maps, we will need to take them into
account. Since the comparison of maps is planned to change in 18.0,
we will be very conservative and only do the optimization if
both keys and values are non-numeric.
|
|
Given this code:
f(S) ->
F0 = F1 = {S,S},
[F0,F1].
case_opt/3 would "optimize" it like this:
f(S) ->
F1 = {S,S},
F0 = {S,S},
[F0,F1].
Similarly, this code:
g({a,_,_}=T) ->
{b,
[_,_] = [T,none],
x}.
would be rewritten to:
g({a,Tmp1,Tmp2}=T) ->
Tmp3 = {a,Tmp1,Tmp2},
{b,
[Tmp3,none],
x}.
where the tuple is rebuilt instead of using the T variable.
Rewrite case_opt/3 to be more careful while optimizing.
|
|
I originally decided that in 'value' context, rewriting a let statement
where the variables were not in the body to a sequence was not worth
it, because the variables would be unused in only one let in a
thousand lets (roughly).
I have reconsidered.
The main reason is that if we do the rewrite, core_lib:is_var_used/2
will be used much more frequently, which will help us to find bugs
in it sooner.
Another reason is that the way letify/2 is currently implemented
with its own calls to core_lib:is_var_used/2 is only safe as long
as all the bindings are independent of each other. We could make
letify/2 smarter, but if we introduce this new optimization there
is no need.
Measuring compilation speed, I have not seen any significant slowdown.
It seems that although core_lib:is_var_used/2 is called much more
frequently, most calls will be fast because is_var_used/2 will quickly
find a use of the variable.
Also add a test case to cover a line opt_guard_try/1 that was
no longer covered.
|
|
In c34ad2d5, the compiler learned to silence some warnings for
expressions that were explicitly assigned to the '_' variable,
as in this example:
_ = list_to_integer(S),
ok
That commit intentionally only made it possible to silence warnings
for BIFs that could cause an exception. Warnings would still be
produced for:
_ = date(),
ok
because date/0 can never fail and thus making the call completely
useless. The reasoning was that such warnings can always be
eliminated by eliminating the offending code.
While that is true, there is the question about rules and their
consistency. It is surprising that '_' can be used to silence
some warnings, but has no effect on other warnings.
Therefore, we will teach the compiler to silence warnings for
the following constructs:
* Calls to safe BIFs such as date/0
* Expressions that will cause an exception such as 'X/0'
* Terms that are built but not used, such as '{x,X}'
|
|
* maint:
Update primary bootstrap
Be more careful about map patterns when evalutating element/2
Do not convert map patterns to map expressions
Conflicts:
bootstrap/lib/compiler/ebin/sys_core_fold.beam
lib/compiler/test/match_SUITE.erl
|
|
We must not convert map patterns to map expressions.
|
|
In code such as:
case {a,Map} of
{a,#{}}=T ->
T
end
we must NOT rewrite a map pattern to a map expression like this:
case Map of
#{} ->
{a,#{}}
end
because the pattern '#{}' will match any map, but the expression
'#{}' will construct an empty map.
|
|
Use the same syntax for map pairs in Core Erlang code as in the
Erlang Code. This Erlang code:
M#{x:=42,y=>1}
will look like this in Core Erlang:
~{'x':=42,'y'=>1|M}~
|
|
* bjorn/compiler/map-fixes:
cerl: Remove a clause in fold_map_pairs/3 that will never be reached
Move grouping of map constructions from v3_core to v3_kernel
core_pp: Correct printing of map literals
Strengthen and modernize compile_SUITE
core_parse: Always fold literal conses
cerl: Make sure that we preserve the invariants for maps
cerl_clauses: Fix indentation
sys_core_fold: Strengthen optimization of letrecs in effect context
Fix handling of binary map keys in comprehensions
core_lib: Teach is_var_used/2 to handle keys in map patterns
warnings_SUITE: Eliminate compiler warning for a shadowed variable
lc_SUITE: Add shadow/1
Modernize lc_SUITE
|