From 924f1573adb661f5f15123b0e7af80bb233418be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
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?= <bjorn@erlang.org>
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?= <bjorn@erlang.org>
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