aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
AgeCommit message (Collapse)Author
2018-08-17beam_validator: Improve merge of cons and literal listBjörn Gustavsson
2018-08-17beam_validator: Strengthen validation of func_infoBjörn Gustavsson
The func_info instruction does not expect a stack frame. There will be an assertion failure in the debug-compiled runtime system.
2018-08-17beam_validator: Allow get_tuple_element before dsetelementBjörn Gustavsson
2018-08-17beam_validator: Don't transfer state to labels that can't be reachedBjörn Gustavsson
If we transfer state appropriately to labels that can't be reached, the state could taint other labels.
2018-08-17beam_validator: Improve type analysis for tuplesBjörn Gustavsson
Since the compiler will start optimizing more aggressively, beam_validator must keep up and improve the recognization of tuples and maps.
2018-08-17beam_validator: Be more careful when updating try/catch stateBjörn Gustavsson
The new code generator will more aggressively reuse registers, so we must be more careful about updating the state for try/catch. In particular, an "empty" try/catch that can't throw an exception must not update the try/catch state.
2018-08-17beam_trim: Handle an empty list of instructionsBjörn Gustavsson
2018-08-17v3_core: Number argument variables in ascending orderBjörn Gustavsson
Nicer to read and less confusion.
2018-08-15Merge branch 'maint'Björn Gustavsson
* maint: Fix compiler crash when compiling double receives erts: Delete fd from poll-set when closing fd_driver port
2018-08-14remove_message does not store any pointer to x0Davide Bettio
remove_message just remove messages without writing to any register. Compiler is already generating code like: {get_tuple_element,{x,0},1,{x,0}}. remove_message. {jump,{f,6}} That clearly uses x0 for other purposes.
2018-08-14Fix compiler crash when compiling double receivesBjörn Gustavsson
The compiler would crash when compiling a function with two receive statements. https://bugs.erlang.org/browse/ERL-703
2018-08-13Merge branch 'maint'Björn Gustavsson
* maint: Correct error behavior of is_map_key/2 in guards
2018-08-13Correct error behavior of is_map_key/2 in guardsBjörn Gustavsson
Consider the following functions: foo() -> bar(not_a_map). bar(M) when not is_map_key(a, M) -> ok; bar(_) -> error. What will `foo/0` return? It depends. If the module is compiled with the default compiler options, the return value will be `ok`. If the module is compiled with the `inline` option, the return value will be `error`. The correct value is `error`, because the call to `is_map_key/2` when the second argument is not a map should fail the entire guard. That is the way other failing guards BIFs are handled. For example: foo() -> bar(not_a_tuple). bar(T) when not element(1, T) -> ok; bar(_) -> error. `foo/0` always returns `error` (whether the code is inlined or not). This bug can be fixed by changing the classification of `is_map_key/2` in the `erl_internal` module. It is now classified as a type test, which is incorrect because type tests should not fail. Reclassifying it as a plain guard BIF corrects the bug. This correction also fixes the internal consistency check failure which was reported in: https://bugs.erlang.org/browse/ERL-699
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-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.)