From 924f1573adb661f5f15123b0e7af80bb233418be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 20 Aug 2018 15:44:05 +0200 Subject: map_SUITE: Cover map_get optimizations in beam_dead --- lib/compiler/test/map_SUITE.erl | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'lib') diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index c004dca834..f1b09869f2 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -1258,6 +1258,31 @@ t_guard_bifs(Config) when is_list(Config) -> {'EXIT',{{badkey,k},_}} = (catch erl_699(#{})), {'EXIT',{{badmap,not_a_map},_}} = (catch erl_699(not_a_map)), + %% Cover optimizations in beam_dead. + + ok = beam_dead_1(#{a=>any,k=>true}), + error = beam_dead_1(#{a=>any,k=>false}), + error = beam_dead_1(#{a=>any}), + error = beam_dead_1(#{}), + + ok = beam_dead_2(#{a=>any,k=>true}), + error = beam_dead_2(#{a=>any,k=>false}), + error = beam_dead_2(#{a=>any}), + error = beam_dead_2(#{}), + + ok = beam_dead_3(#{k=>true}), + error = beam_dead_3(#{k=>false}), + error = beam_dead_3(#{}), + + ok = beam_dead_4(#{k=>true}), + error = beam_dead_4(#{k=>false}), + error = beam_dead_4(#{}), + error = beam_dead_4(not_a_map), + + ok = beam_dead_5(#{k=>true}), + error = beam_dead_5(#{k=>false}), + error = beam_dead_3(#{}), + ok. map_guard_empty() when is_map(#{}); false -> true. @@ -1298,6 +1323,40 @@ erl_699(M) -> %% Used to cause an internal consistency failure. {is_map_key(k, M),maps:get(k, M)}. +beam_dead_1(#{a:=_,k:=_}=M) when map_get(k, M) -> + ok; +beam_dead_1(#{}) -> + error. + +beam_dead_2(M) -> + case M of + #{a:=_,k:=_} when map_get(k, M) -> + ok; + #{} -> + error + end. + +beam_dead_3(M) -> + case M of + #{k:=_} when map_get(k, M) -> + ok; + #{} -> + error + end. + +beam_dead_4(M) -> + case M of + #{} when map_get(k, M) -> + ok; + _ -> + error + end. + +beam_dead_5(#{}=M) when map_get(k, M) -> + ok; +beam_dead_5(#{}) -> + error. + t_guard_sequence(Config) when is_list(Config) -> {1, "a"} = map_guard_sequence_1(#{seq=>1,val=>id("a")}), {2, "b"} = map_guard_sequence_1(#{seq=>2,val=>id("b")}), -- cgit v1.2.3 From e8deb9f8ff3cb32286ca9b87a36b23aadffd1a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 22 Aug 2018 10:17:50 +0200 Subject: beam_validator: Infer the type of the map argument for is_map_key/2 Make sure that beam_validator considers a call to is_map_key/2 followed by an update of the same map without an is_map/1 test safe. (This situation will probably not be encountered when using the compiler in OTP 21, but better safe than sorry.) --- lib/compiler/src/beam_validator.erl | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index a0eef826ce..fb2e7df65c 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -565,6 +565,12 @@ valfun_4({bif,map_get,{f,Fail},[_Key,Map]=Src,Dst}, Vst0) -> Vst = set_type(map, Map, Vst1), Type = propagate_fragility(term, Src, Vst), set_type_reg(Type, Dst, Vst); +valfun_4({bif,is_map_key,{f,Fail},[_Key,Map]=Src,Dst}, Vst0) -> + validate_src(Src, Vst0), + Vst1 = branch_state(Fail, Vst0), + Vst = set_type(map, Map, Vst1), + Type = propagate_fragility(bool, Src, Vst), + set_type_reg(Type, Dst, Vst); valfun_4({bif,Op,{f,Fail},Src,Dst}, Vst0) -> validate_src(Src, Vst0), Vst = branch_state(Fail, Vst0), -- cgit v1.2.3 From 840b04bbd9359375a7491f5555bf84363cd08d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 22 Aug 2018 10:17:00 +0200 Subject: map_SUITE: Test is_map_key/2 followed by a map update --- lib/compiler/test/map_SUITE.erl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'lib') diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index f1b09869f2..3e0ab78390 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -1283,6 +1283,13 @@ t_guard_bifs(Config) when is_list(Config) -> error = beam_dead_5(#{k=>false}), error = beam_dead_3(#{}), + %% Test is_map_key/2 followed by map update. + + Used0 = map_usage(var, #{other=>value}), + Used0 = #{other=>value,var=>dead}, + Used1 = map_usage(var, #{var=>live}), + Used1 = #{var=>live}, + ok. map_guard_empty() when is_map(#{}); false -> true. @@ -1357,6 +1364,14 @@ beam_dead_5(#{}=M) when map_get(k, M) -> beam_dead_5(#{}) -> error. +%% Test is_map_key/2, followed by an update of the map. +map_usage(Def, Used) -> + case is_map_key(Def, Used) of + true -> Used; + false -> Used#{Def=>dead} + end. + + t_guard_sequence(Config) when is_list(Config) -> {1, "a"} = map_guard_sequence_1(#{seq=>1,val=>id("a")}), {2, "b"} = map_guard_sequence_1(#{seq=>2,val=>id("b")}), -- cgit v1.2.3