aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
AgeCommit message (Collapse)Author
2018-08-10Merge branch ↵Erlang/OTP
'john/compiler/fix-deterministic-include-paths/OTP-15204/ERL-679' into maint-21 * john/compiler/fix-deterministic-include-paths/OTP-15204/ERL-679: Omit include path debug info for +deterministic builds # Conflicts: # lib/compiler/test/compile_SUITE.erl
2018-08-09Omit include path debug info for +deterministic buildsJohn Högberg
Compiling the same file with different include paths resulted in different files with the `+deterministic` flag even if everything but the paths were identical. This was caused by the absolute path of each include directory being unconditionally included in a debug information chunk. This commit fixes this by only including this information in non-deterministic builds.
2018-06-29Merge branch 'bjorn/compiler/fix-beam_jump-crash/ERL-660/OTP-15166' into ↵Erlang/OTP
maint-21 * bjorn/compiler/fix-beam_jump-crash/ERL-660/OTP-15166: Eliminate a crash in the beam_jump pass
2018-06-29Merge branch 'bjorn/compiler/fix-map_get/OTP-15157' into maint-21Erlang/OTP
* bjorn/compiler/fix-map_get/OTP-15157: Fix internal compiler error for map_get/2
2018-06-29Merge branch 'bjorn/compiler/fix-skipped-matching/ERL-655/OTP-15156' into ↵Erlang/OTP
maint-21 * bjorn/compiler/fix-skipped-matching/ERL-655/OTP-15156: beam_type: Fix unsafe optimization
2018-06-29Eliminate a crash in the beam_jump passBjörn Gustavsson
https://bugs.erlang.org/browse/ERL-660
2018-06-27Fix internal compiler error for map_get/2Björn Gustavsson
Code such as that the following: Val = map_get(a, Map), Map#{a:=z} %Could be any map update would incorrectly cause an internal consistency check failure: Internal consistency check failed - please report this bug. Instruction: {put_map_exact,{f,0},{x,0},{x,0},1,{list,[{atom,a},{atom,z}]}} Error: {bad_type,{needed,map},{actual,term}}: Update beam_validator so that it understands that the second argument for map_get/2 is a map.
2018-06-27beam_type: Fix unsafe optimizationBjörn Gustavsson
beam_type assumed that the operand for the bs_context_to_binary instruction must be a binary. That is not correct; bs_context_to_binary accepts anything. Based on the incorrect assumption, beam_type would remove other test instructions. The bug was introduced in eee8655788d2, which was supposed to be just a refactoring commit. https://bugs.erlang.org/browse/ERL-655
2018-06-25Fix unsafe optimization when running beam_block the second timeBjörn Gustavsson
The compiler would crash when compiling code such as: serialize(#{tag := value, id := Id, domain := Domain}) -> [case Id of nil -> error(id({required, id})); _ -> <<10, 1:16/signed, Id:16/signed>> end, case Domain of nil -> error(id({required, domain})); _ -> <<8, 2:16/signed, Domain:32/signed>> end]. The crash would look like this: Function: serialize/1 t.erl: internal error in block2; crash reason: {badmatch,false} in function beam_utils:live_opt/4 (beam_utils.erl, line 861) in call from beam_utils:live_opt/1 (beam_utils.erl, line 285) in call from beam_block:function/2 (beam_block.erl, line 47) in call from beam_block:'-module/2-lc$^0/1-0-'/2 (beam_block.erl, line 33) in call from beam_block:'-module/2-lc$^0/1-0-'/2 (beam_block.erl, line 33) in call from beam_block:module/2 (beam_block.erl, line 33) in call from compile:block2/2 (compile.erl, line 1358) in call from compile:'-internal_comp/5-anonymous-1-'/3 (compile.erl, line 349) The reason for the crash is an assertion failure caused by a previous unsafe optimization. Here is the code before the unsafe optimization: . . . {bs_init2,{f,0},7,0,0,{field_flags,[]},{x,1}}. {bs_put_string,3,{string,[8,0,2]}}. {bs_put_integer,{f,0},{integer,32},1,{field_flags,[signed,big]},{y,1}}. {move,{x,1},{x,0}}. {test_heap,4,1}. . . . beam_block:move_allocate/1 moved up the test_heap/2 instruction past the move/2 instruction, adjusting the number of live registers at the same time: . . . {bs_init2,{f,0},7,0,0,{field_flags,[]},{x,1}}. %% Only x1 is live now. {bs_put_string,3,{string,[8,0,2]}}. {bs_put_integer,{f,0},{integer,32},1,{field_flags,[signed,big]},{y,1}}. {test_heap,4,2}. %Unsafe. x0 is dead. {move,{x,1},{x,0}}. . . . This optimization is unsafe because the bs_init2 instruction killed x0. The bug is in beam_utils:anno_defs/1, which adds annotations indicating the registers that are defined at the beginning of each block. The annotation before the move/2 instruction incorrectly indicated that x0 was live. https://bugs.erlang.org/browse/ERL-650 https://github.com/elixir-lang/elixir/issues/7782
2018-06-18Update copyright yearHenrik Nord
2018-06-07Merge pull request #1832 from josevalim/jv-revert-beam-jumpBjörn Gustavsson
Revert "Run the sharing optimisation in beam_jump until fixpoint"
2018-06-07Merge pull request #1831 from bjorng/bjorn/compiler/fix-name-captureBjörn Gustavsson
Fix name capture problem in sys_core_fold OTP-15115
2018-06-04Revert "Run the sharing optimisation in beam_jump until fixpoint"José Valim
We have found cases where compilation drastically slows down due to this commit. We are working on a minimal cases and plan to bring this patch back once we can work our the performance issues. This reverts commit f7c9383f4c3d4b6819b5ba4d54c7093df806fe4a.
2018-06-04sys_core_fold: Fix name capture problemBjörn Gustavsson
sys_core_fold could do unsafe transformations on the code from the old inliner (invoked using the compiler option `{inline,[{F/A}]}` to request inlining of specific functions). To explain the bug, let's first look at an example that sys_core_fold handles correctly. Consider this code: 'foo'/2 = fun (Arg1,Arg2) -> let <B> = Arg2 in let <A,B> = <B,Arg1> in {A,B} In this example, the lets can be completely eliminated, since the arguments for the lets are variables (as opposed to expressions). Since the variable B is rebound in the inner let, `sys_core_fold` must take special care when doing the substitutions. Here is the correct result: 'foo'/2 = fun (Arg1, Arg2) -> {Arg2,Arg1} Consider a slight modifictation of the example: 'bar'/2 = fun (Arg1,Arg2) -> let <B> = [Arg2] in let <A,B> = <B,[Arg1]> in {A,B} Here some of the arguments for the lets are expressions, so the lets must be kept. sys_core_fold does not handle this example correctly: 'bar'/2 = fun (Arg1,Arg2) -> let <B> = [Arg2] in let <B> = [Arg1] in {B,B} In the inner let, the variable A has been eliminated and replaced with the variable B in the body (the first B in the tuple). Since the B in the outer let is never used, the outer let will be eliminated, giving: 'bar'/2 = fun (Arg1,Arg2) -> let <B> = [Arg1] in {B,B} To handle this example correctly, sys_core_fold must rename the variable B in the inner let like this to avoid capturing B: 'bar'/2 = fun (Arg1,Arg2) -> let <B> = [Arg2] in let <NewName> = [Arg1] in {B,NewName} (Note: The `v3_kernel` pass alreday handles those examples correctly in case `sys_core_fold` has been disabled.)
2018-06-04sys_core_inline: Avoid spurious warningsBjörn Gustavsson
Add more `compiler_generated` attributes to avoid spurious compiler warnings triggered by the bug fix in the next commit.
2018-05-28compiler: Improve a contractHans Bolinder
2018-05-16Merge branch 'richcarl/eliminate_lib_module/PR-1786/OTP-15072'Hans Bolinder
* richcarl/eliminate_lib_module/PR-1786/OTP-15072: Fix minor issues Eliminate call to ct:get_progname() in ts_erl_config Use \n escape instead of integer 10 Move error formatting to erl_error.erl and delete lib.erl Move extended parse functions in lib.erl to erl_eval.erl Move lib:eval_str/1 into mod_esi.erl Remove lib:progname/0 Eliminate call to lib:progname/1 in slave.erl Add ct:get_progname/0 Remove lib:error_message/2 Remove lib:flush_receive/0 Remove lib:send/2 and lib:sendw/2 Move lib:nonl/1 into yecc.erl
2018-05-07Merge pull request #1800 from erszcz/masterHans Bolinder
Fix syntactic issues in EDoc comments across some libs
2018-05-07Merge pull request #1802 from michalmuskala/map-is-key-bifBjörn Gustavsson
Introduce is_map_key/2 guard BIF OTP-15037
2018-05-04Fix syntactic issues in EDoc comments across some libsRadek Szymczyszyn
See https://github.com/erszcz/docsh/issues/23 for an explanation about how the files were found.
2018-05-04Move error formatting to erl_error.erl and delete lib.erlRichard Carlsson
2018-04-29Introduce is_map_key/2 guard BIFMichał Muskała
This complements the `map_get/2` guard BIF introduced in #1784. Rationale. `map_get/2` allows accessing map fields in guards, but it might be problematic in more complex guard expressions, for example: foo(X) when map_get(a, X) =:= 1 or is_list(X) -> ... The `is_list/1` part of the guard could never succeed since the `map_get/2` guard would fail the whole guard expression. In this situation, this could be solved by using `;` instead of `or` to separate the guards, but it is not possible in every case. To solve this situation, this PR proposes a `is_map_key/2` guard that allows to check if a map has key inside a guard before trying to access that key. When combined with `is_map/1` this allows to construct a purely boolean guard expression testing a value of a key in a map. Implementation. Given the use case motivating the introduction of this function, the PR contains compiler optimisations that produce optimial code for the following guard expression: foo(X) when is_map(X) and is_map_key(a, X) and map_get(a, X) =:= 1 -> ok; foo(_) -> error. Given all three tests share the failure label, the `is_map_key/2` and `is_map/2` tests are optimised away. As with `map_get/2` the `is_map_key/2` BIF is allowed in match specs.
2018-04-27beam_validator: Verify Y registers in exception-causing instructionsBjörn Gustavsson
When an exception is handled, the stack will be scanned. Therefore all Y registers must be initialized.
2018-04-27Correct beam_utils:is_killed/3 (again)Björn Gustavsson
beam_utils:is_killed/3 could incorrectly indicate that a register was killed. The previous fix is 5da6b91ecab6c.
2018-04-26Merge pull request #1797 from bjorng/bjorn/compiler/fold-apply/ERL-614Björn Gustavsson
Rewrite a call of a literal external fun to a direct call OTP-15044
2018-04-25Rewrite a call of a literal external fun to a direct callBjörn Gustavsson
Rewrite calls such as: (fun erlang:abs/1)(-42) to: erlang:abs(-42) While we are at it, also add rewriting of apply/2 with a fixed number of arguments to a direct call of the fun. For example: apply(F, [A,B]) would be rewritten to: F(A, B) https://bugs.erlang.org/browse/ERL-614
2018-04-25beam_validator: Clear X registers in wait_timeoutBjörn Gustavsson
Help us find more compiler bugs.
2018-04-25sys_core_fold: Eliminate crash for map update in guardBjörn Gustavsson
sys_core_fold would crash when attempting to optimize this code: t() when (#{})#{}-> c.
2018-04-25Merge branch 'map-get-bif' of git://github.com/michalmuskala/otpBjörn Gustavsson
* 'map-get-bif' of git://github.com/michalmuskala/otp: Introduce map_get guard-safe function OTP-15037
2018-04-24Introduce map_get guard-safe functionMichał Muskała
Rationale Today all compound data types except for maps can be deconstructed in guards. For tuples we have `element/2` and for lists `hd/1` and `tl/1`. Maps are completely opaque to guards. This means matching on maps can't be abstracted into macros, which is often done with repetitive guards. It also means that maps have to be always selected whole from ETS tables, even when only one field would be enough, which creates a potential efficiency issue. This PR introduces an `erlang:map_get/2` guard-safe function that allows extracting a map field in guard. An alternative to this function would be to introduce the syntax for extracting a value from a map that was planned in the original EEP: `Map#{Key}`. Even outside of guards, since this function is a guard-BIF it is more efficient than using `maps:get/2` (since it does not need to set up the stack), and more convenient from pattern matching on the map (compare: `#{key := Value} = Map, Value` to `map_get(key, Map)`). Performance considerations A common concern against adding this function is the notion that "guards have to be fast" and ideally execute in constant time. While there are some counterexamples (`length/1`), what is more important is the fact that adding those functions does not change in any way the time complexity of pattern matching - it's already possible to match on map fields today directly in patterns - adding this ability to guards will niether slow down or speed up the execution, it will only make certain programs more convenient to write. This first version is very naive and does not perform any optimizations.
2018-04-18core_lint: Handle repeated variables in map patterns correctlyBjörn Gustavsson
Keys in map patterns are input variables, not pattern variables.
2018-04-11beam_validator: Remove repeated "this"Björn Gustavsson
2018-04-11beam_validator: Remove unnecessary inclusion of beam_disasm.hrlBjörn Gustavsson
2018-04-11beam_validator: Strengthen validation of remaining GC instructionsBjörn Gustavsson
1ee21858db7e strengenthed validatation of GC instructions, but forgot the following instructions: bs_start_match2/5 bs_get_binary2/7 bs_get_float2/7 bs_get_integer2/7 bs_get_utf8/5 bs_get_utf16/5 bs_get_utf32/5 bs_skip_utf8/4 bs_skip_utf16/4 bs_skip_utf32/4
2018-04-06Check that messages outside of the heap are not corruptedBjörn Gustavsson
Waiting messages for a process may be stored in a queue outside of any heap or heap fragment belonging to the process. This is an optimization added in a recent major release to avoid garbage collection messages again and again if there is a long message queue. Until such message has been matched and accepted by the remove_message/0 instruction, the message must not be included in the root set for a garbage collection, as that would corrupt the message. The loop_rec/2 instruction explicitly turns off garbage collection of the process as long messages are being matched. However, if the compiler were to put references to a message outside of the heap in an Y register (on the stack) and there happened to be a GC when the process had been scheduled out, the message would be corrupted and the runtime system would crash sooner or later. To ensure that doesn't happen, teach beam_validator to check for references on the stack to messages outside of the heap.
2018-04-05Merge pull request #1769 from bjorng/bjorn/compiler/beam_utilsBjörn Gustavsson
Fix unsafe optimization of record test
2018-04-04Fix unsafe optimization of record testBjörn Gustavsson
beam_record would make an unsafe optimization for the not_used_p/4 function added to beam_utils_SUITE in this commit. The bug is in beam_utils, which would falsely report that {x,4} was unused when it in fact was used. The bug was in the function not_used/1. The purpose of not_used/1 is to return a 'not_used' result unless the actual result is 'used'. Unfortunately it was not implemented in that way. It would let a 'transparent' result slip through, which the caller in this case would convert to 'killed' (because the register was killed on all other paths). Reported-by: Richard Carlsson
2018-04-04Merge pull request #1725 from michalmuskala/fun-literalsBjörn Gustavsson
Compile external fun expressions to literals OTP-15003
2018-03-26Merge pull request #1761 from ↵Björn Gustavsson
bjorng/bjorn/compiler/fix-atom-leak/ERL-563/OTP-14968 Stop the compiler from overflowing the atom table
2018-03-26Compile external fun expressions to literalsMichał Muskała
The expressions fun M:F/A, when all elements are literals are also treated as a literal. Since they have consistent representation and don't depend on the code currently loaded in the VM, this is safe. This can provide significant performance improvements in code using such functions extensively - a full function call to erlang:make_fun/3 is replaced by a single move instruction and no register shuffling or saving registers to stack is necessary. Additionally, compound data types that contain such external functions as elements can be treated as literals too. The commit also changes the representation of external funs to be a valid Erlang syntax and adds support for literal external funs to core Erlang.
2018-03-24Avoid overflowing the atom tableBjörn Gustavsson
Use integer variable names instead of atoms in v3_core, sys_core_fold, and v3_kernel to avoid overflowing the atom table. It is a deliberate design decision to calculate the first free integer variable name (in sys_core_fold and v3_kernel) instead of somehow passing it from one pass to another. I don't want that kind of dependency between compiler passes. Also note that the next free variable name is not easily available after running the inliner.
2018-03-23Add cerl_trees:next_free_variable_name/1Björn Gustavsson
2018-03-23cerl_inline: Fix a name capture bugBjörn Gustavsson
The way variables created by make_template() are used, it is necessary that the names are unique in the entire function. This has not happened to cause any problems in the past because all other compiler passes created atom variable names, not integer variable names. If other passes start to create integer variable names, this bug is exposed.
2018-03-23Allow the match context identifier to be any termBjörn Gustavsson
During compilation, the bs_save2 and bs_restore2 instructions contain a match context reference. That reference is the variable name that holds the match context. beam_clean assumes that the reference always is an atom, which is not a safe assumption since integers are legal variable names in Core Erlang.
2018-03-21Point out the correct line in an exception for a bad generatorBjörn Gustavsson
When a generator in a list comprehension was given some other term than a list, the wrong line could be pointed out in the exception. Here is an example: bad_generator() -> [I || %%This line would be pointed out. I <- not_a_list]. https://bugs.erlang.org/browse/ERL-572
2018-03-19core_parse: Fix handling of negative sizes in binariesBjörn Gustavsson
A literal negative size in binary construction would cause a crash.
2018-03-14Teach beam_utils:replace_labels/4 to handle recv_{mark,set}Björn Gustavsson
The missing support for renumbering labels in recv_mark and recv_set did not seem to cause any problems, probably because the insructions are introduced late and their labels would keep their numbers. But it there will definitely be a problem if the recv_mark and recv_set instructions would be introduced much earlier.
2018-03-14v3_kernel: Stop ensuring one return value in #k_try{}Björn Gustavsson
For unclear reasons, v3_kernel attempts to guarantee that #k_try{} always has at least one return value, even if it will never be used. I said "attempts", because the handler block that is executed when an exception is caught does not have the same guarantee. That means that if an exception is thrown, the return value will not actually be set. In practice, however, this is not a problem for the existing code generator (v3_codegen). The generated code will still be safe. If we are to rewrite the code generator to generate an SSA-based intermediate format, this inconsistency *will* cause problems when creating phi nodes. While at it, also remove an unecessary creation of new variables in generation of #k_try_enter{}.
2018-03-14v3_kernel_pp: Print return variables for #k_try{}Björn Gustavsson
2018-03-13Merge branch 'hasse/dialyzer/extra-range/OTP-14970'Hans Bolinder
* hasse/dialyzer/extra-range/OTP-14970: ssl: Correct some specs os_mon: Correct a spec Fix broken spec in beam_asm Dialyzer should not throw away spec information because of overspec