aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
AgeCommit message (Collapse)Author
2018-08-10Merge branch 'maint'Björn Gustavsson
* maint: Fix bug in binary matching
2018-08-10Merge pull request #1911 from ↵Björn Gustavsson
bjorng/bjorn/compiler/binary-syntax/ERL-689/OTP-15219 Fix bug in binary matching
2018-08-09Merge branch 'maint'Rickard Green
* maint: Omit include path debug info for +deterministic builds
2018-08-09Merge branch ↵Rickard Green
'john/compiler/fix-deterministic-include-paths/OTP-15204/ERL-679' into maint * john/compiler/fix-deterministic-include-paths/OTP-15204/ERL-679: Omit include path debug info for +deterministic builds
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-08-09Merge branch 'maint'Björn Gustavsson
* maint: Fix side-effect optimization when compiling from Core Erlang Conflicts: lib/compiler/src/sys_core_fold.erl
2018-08-09Merge pull request #1910 from ↵Björn Gustavsson
bjorng/bjorn/compiler/letrec-side-effect-fix/ERL-658/OTP-15188 Fix side-effect optimization when compiling from Core Erlang
2018-08-08Fix bug in binary matchingBjörn Gustavsson
The compiler generates incorrect code for the following example: decode_binary(_, <<Length, Data/binary>>) -> case {Length, Data} of {0, _} -> %% When converting the match context back to a binary, %% Data will be set to the entire original binary, %% that is, to <<0>> instead of <<>>. {{0, 0, 0}, Data}; {4, <<Y:16/little, M, D, Rest/binary>>} -> {{Y, M, D}, Rest} end. The problem is the delayed sub binary creation optimization, which is not safe to do in this case. This commit introduces a heuristic that will disable the delayed sub binary creation optimization for this example. Unfortunately, the heuristic may turn off the optimization when it would actually be safe. In the OTP codebase, the optimization is turned off in two instances, once in string.erl and once in dets_v9.erl. https://bugs.erlang.org/browse/ERL-689
2018-08-08Merge pull request #1904 from michalmuskala/mm/get-stacktrace-to-buildBjörn Gustavsson
Rewrite erlang:get_stacktrace calls to primop when safe
2018-08-08Merge branch 'maint'Björn Gustavsson
* maint: Eliminate double computation of next var beam_validator: Fix false diagnostic for a receive nested in a try
2018-08-08Merge pull request #1903 from michalmuskala/mm/useless-callBjörn Gustavsson
Eliminate double computation of next var
2018-08-08Fix side-effect optimization when compiling from Core ErlangJohn Högberg
When an expression is only used for its side effects, we try to remove everything that doesn't tie into a side-effect, but we went a bit too far when we applied the optimization to funs defined in such a context. Consider the following: do letrec 'f'/0 = fun () -> ... whatever ... in call 'side':'effect'(apply 'f'/0()) 'ok' When f/0 is optimized under the assumption that its return value is unused, side:effect/1 will be fed the result of the last side-effecting expression in f/0 instead of its actual result. https://bugs.erlang.org/browse/ERL-658 Co-authored-by: Björn Gustavsson <[email protected]>
2018-08-07Eliminate double computation of next varMichał Muskała
My compiler benchmarks on modules with huge functions, show the next_free_variable_name call to be expensive. It turns out one of the 3 calls to the function was completely ignored.
2018-08-06beam_validator: Fix false diagnostic for a receive nested in a tryBjörn Gustavsson
When nesting a receive in a try/catch, there could be a false diagnostic that a fragile term is used. https://bugs.erlang.org/browse/ERL-684
2018-08-05Rewrite erlang:get_stacktrace calls to primop when safeMichał Muskała
This allows taking advantage of further optimisations, like the raw_raise instruction for code that can't upgrade (yet) to the new stacktrace syntax for compatibility reasons. The rewrite is only done when it is safe - when the get_stacktrace call is the very first thing the handler does.
2018-07-27Change "can not" into "cannot"Raimo Niskanen
I did not find any legitimate use of "can not", however skipped changing e.g RFCs archived in the source tree.
2018-07-18Merge branch 'maint'John Högberg
* maint: Abort size calculation when a matched-out variable is used
2018-07-16Abort size calculation when a matched-out variable is usedJohn Högberg
Referencing a matched-out variable in a size expression makes it impossible to calculate the size of the result based on the size of the matched binary. The compiler would still generate code to do this however, which would crash since the variable isn't defined at the size calculation.
2018-07-04Merge branch 'maint'John Högberg
* maint: Updated OTP version Update release notes Update version numbers Eliminate a crash in the beam_jump pass stdlib: Fix a 'chars_limit' bug Fix a race condition when generating async operation ids Fix internal compiler error for map_get/2 beam_type: Fix unsafe optimization public_key: Remove moduli 5121 and 7167 Thoose were added by 598629aeba9de98e8cdf5637043eb34e5d407751 but are not universaly supported.
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-27Merge pull request #1717 from michalmuskala/is-function-pureBjörn Gustavsson
Fold is_function/1,2 during compilation
2018-06-27Merge pull request #1833 from michalmuskala/mm/fix-beam-jumpBjörn Gustavsson
Optimise beam_jump
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-08Optimise beam_jumpMichał Muskała
This is an alternative to #1832. The optimisation relies on special-casing the common pattern of "renaming" a label by direct jump to another label. The change makes beam_jump recognise couple more opportunities for optimisation. The optimisation additionally avoids superfluous list concatenations by only flattening the accumulator at the very end.
2018-06-08Run the sharing optimisation in beam_jump until fixpointMichał Muskała
This is especially useful after inlining a function with a case. Today the compiler would most probably be able to unify all the leafs of the case during the sharing optimisation, but it would fail to unify the pattern matching itself. Naively running the optimisation multiple times wouldn't be able to find the common code either, because it would differ in jump/fail targets of various instructions. To remedy this, after doing each sharing pass we traverse the code backwards when reversing and update all the jump targets with the new targets that were discovered during the unification pass. This allows running the optimisation until fixpoint and makes sure all sharing opportunities will be discovered. This optimisation also helps with the Elixir's `with/else` construct.
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-06Fold is_function/1,2 during compilationMichał Muskała
This can often appear in code after inlining some higher-order functions. * mark is_function/2 as pure * track function types in sys_core_fold * use those types to eval is_function/1,2 at compile-time when possible
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.