aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2019-05-27 14:24:47 +0200
committerBjörn Gustavsson <[email protected]>2019-05-27 14:24:47 +0200
commit01851fed835d1b60edabc192672140402ed02474 (patch)
treefd2b91d10d0b9a0e53e353a6b5fd6a935a63351c /lib/compiler
parenta65825e8f14f8e2c9aa9d5f95971199b98eee9ee (diff)
parenta52b0126c19ab7d49126c82183a0477e25373bfe (diff)
downloadotp-01851fed835d1b60edabc192672140402ed02474.tar.gz
otp-01851fed835d1b60edabc192672140402ed02474.tar.bz2
otp-01851fed835d1b60edabc192672140402ed02474.zip
Merge branch 'maint'
* maint: Fix loading of Core Erlang code for extracting a map element Fix unsafe optimizations where guard tests could be removed
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/src/beam_ssa_codegen.erl15
-rw-r--r--lib/compiler/src/beam_ssa_dead.erl12
-rw-r--r--lib/compiler/test/core_SUITE.erl7
-rw-r--r--lib/compiler/test/core_SUITE_data/get_map_element.core18
-rw-r--r--lib/compiler/test/guard_SUITE.erl25
5 files changed, 61 insertions, 16 deletions
diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl
index 02b644f41a..7248aca5f3 100644
--- a/lib/compiler/src/beam_ssa_codegen.erl
+++ b/lib/compiler/src/beam_ssa_codegen.erl
@@ -1018,6 +1018,14 @@ bif_fail({catch_tag,_}) -> {f,0}.
next_block([]) -> none;
next_block([{Next,_}|_]) -> Next.
+%% Certain instructions (such as get_map_element or is_nonempty_list)
+%% are only used in guards and **must** have a non-zero label;
+%% otherwise, the loader will refuse to load the
+%% module. ensure_label/2 replaces a zero label with the "ultimate
+%% failure" label to make the module loadable. The instruction that
+%% have had the zero label replaced is **not** supposed to ever fail
+%% and actually jump to the label.
+
ensure_label(Fail0, #cg{ultimate_fail=Lbl}) ->
case bif_fail(Fail0) of
{f,0} -> {f,Lbl};
@@ -1166,6 +1174,11 @@ cg_block([#cg_set{op=match_fail}=I,
#cg_set{op=succeeded,dst=Bool}], {Bool,_Fail}, St) ->
%% A match_fail instruction in a try/catch block.
cg_block([I], none, St);
+cg_block([#cg_set{op=get_map_element,dst=Dst0,args=Args0},
+ #cg_set{op=succeeded,dst=Bool}], {Bool,Fail0}, St) ->
+ [Dst,Map,Key] = beam_args([Dst0|Args0], St),
+ Fail = ensure_label(Fail0, St),
+ {[{get_map_elements,Fail,Map,{list,[Key,Dst]}}],St};
cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=I,
#cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
[Dst|Args] = beam_args([Dst0|Args0], St),
@@ -1669,8 +1682,6 @@ cg_test({float,Op0}, Fail, Args, Dst, #cg_set{anno=Anno}) ->
'/' -> fdiv
end,
[line(Anno),{bif,Op,Fail,Args,Dst}];
-cg_test(get_map_element, Fail, [Map,Key], Dst, _I) ->
- [{get_map_elements,Fail,Map,{list,[Key,Dst]}}];
cg_test(peek_message, Fail, [], Dst, _I) ->
[{loop_rec,Fail,{x,0}}|copy({x,0}, Dst)];
cg_test(put_map, Fail, [{atom,exact},SrcMap|Ss], Dst, Set) ->
diff --git a/lib/compiler/src/beam_ssa_dead.erl b/lib/compiler/src/beam_ssa_dead.erl
index 423bc88c3b..b25685d20b 100644
--- a/lib/compiler/src/beam_ssa_dead.erl
+++ b/lib/compiler/src/beam_ssa_dead.erl
@@ -680,11 +680,8 @@ will_succeed_test(is_list, is_nonempty_list) ->
maybe;
will_succeed_test(is_nonempty_list, is_list) ->
yes;
-will_succeed_test(T1, T2) ->
- case is_numeric_test(T1) andalso is_numeric_test(T2) of
- true -> maybe;
- false -> no
- end.
+will_succeed_test(_T1, _T2) ->
+ maybe.
will_succeed_1('=:=', A, '<', B) ->
if
@@ -769,11 +766,6 @@ will_succeed_vars('==', Val1, '/=', Val2) when Val1 == Val2 -> no;
will_succeed_vars(_, _, _, _) -> maybe.
-is_numeric_test(is_float) -> true;
-is_numeric_test(is_integer) -> true;
-is_numeric_test(is_number) -> true;
-is_numeric_test(_) -> false.
-
eval_type_test(Test, Arg) ->
case eval_type_test_1(Test, Arg) of
true -> yes;
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
index e5611e99d1..72016c6d76 100644
--- a/lib/compiler/test/core_SUITE.erl
+++ b/lib/compiler/test/core_SUITE.erl
@@ -29,7 +29,8 @@
bs_shadowed_size_var/1,
cover_v3_kernel_1/1,cover_v3_kernel_2/1,cover_v3_kernel_3/1,
cover_v3_kernel_4/1,cover_v3_kernel_5/1,
- non_variable_apply/1,name_capture/1,fun_letrec_effect/1]).
+ non_variable_apply/1,name_capture/1,fun_letrec_effect/1,
+ get_map_element/1]).
-include_lib("common_test/include/ct.hrl").
@@ -57,7 +58,8 @@ groups() ->
bs_shadowed_size_var,
cover_v3_kernel_1,cover_v3_kernel_2,cover_v3_kernel_3,
cover_v3_kernel_4,cover_v3_kernel_5,
- non_variable_apply,name_capture,fun_letrec_effect
+ non_variable_apply,name_capture,fun_letrec_effect,
+ get_map_element
]}].
@@ -95,6 +97,7 @@ end_per_group(_GroupName, Config) ->
?comp(non_variable_apply).
?comp(name_capture).
?comp(fun_letrec_effect).
+?comp(get_map_element).
try_it(Mod, Conf) ->
Src = filename:join(proplists:get_value(data_dir, Conf),
diff --git a/lib/compiler/test/core_SUITE_data/get_map_element.core b/lib/compiler/test/core_SUITE_data/get_map_element.core
new file mode 100644
index 0000000000..092b5e71eb
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/get_map_element.core
@@ -0,0 +1,18 @@
+module 'get_map_element' ['get_map_element'/0]
+attributes []
+
+'get_map_element'/0 =
+ fun () ->
+ apply 'match_map'/1(~{'foo'=>'bar'}~)
+
+'match_map'/1 =
+ fun (_0) ->
+ case _0 of
+ <~{'foo':='bar'}~> when 'true' ->
+ 'ok'
+ %% It will be undefined behaviour at runtime if no
+ %% clause of the case can be selected. That can't
+ %% happen for this module, because match_map/1 is
+ %% always called with a matching map argument.
+ end
+end
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index f25d8a1a46..d3d62b53f5 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -36,7 +36,8 @@
basic_andalso_orelse/1,traverse_dcd/1,
check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
bad_constants/1,bad_guards/1,
- guard_in_catch/1,beam_bool_SUITE/1]).
+ guard_in_catch/1,beam_bool_SUITE/1,
+ repeated_type_tests/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -54,7 +55,8 @@ groups() ->
rel_ops,rel_op_combinations,generated_combinations,
literal_type_tests,basic_andalso_orelse,traverse_dcd,
check_qlc_hrl,andalso_semi,t_tuple_size,binary_part,
- bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE]}].
+ bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE,
+ repeated_type_tests]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -2378,6 +2380,25 @@ maps() ->
evidence(#{0 := Charge}) when 0; #{[] => Charge} == #{[] => 42} ->
ok.
+repeated_type_tests(_Config) ->
+ binary = repeated_type_test(<<42>>),
+ bitstring = repeated_type_test(<<1:1>>),
+ other = repeated_type_test(atom),
+ ok.
+
+repeated_type_test(T) ->
+ %% Test for a bug in beam_ssa_dead.
+ if is_bitstring(T) ->
+ if is_binary(T) -> %This test would be optimized away.
+ binary;
+ true ->
+ bitstring
+ end;
+ true ->
+ other
+ end.
+
+
%% Call this function to turn off constant propagation.
id(I) -> I.