File 3739-sys_core_fold-Rewrite-maps-get-2-and-friends-to-guar.patch of Package erlang

From 19eaa12154ff20b531ed96d5249998c762b1a139 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Thu, 28 Nov 2019 14:49:49 +0100
Subject: [PATCH 9/9] sys_core_fold: Rewrite maps:get/2 and friends to guard
 BIFs

---
 erts/emulator/test/map_SUITE.erl   | 16 +++++++----
 lib/compiler/src/sys_core_fold.erl | 56 ++++++++++++++++++++++++++------------
 lib/stdlib/test/maps_SUITE.erl     |  7 +++--
 3 files changed, 54 insertions(+), 25 deletions(-)

diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl
index 4b638b9082..dbf6fa58ed 100644
--- a/erts/emulator/test/map_SUITE.erl
+++ b/erts/emulator/test/map_SUITE.erl
@@ -1872,15 +1872,18 @@ t_bif_map_get(Config) when is_list(Config) ->
     "v3" = maps:get(<<"k2">>, M1),
 
     %% error cases
+    %%
+    %% Note that the stack trace is ignored because the compiler may have
+    %% rewritten maps:get/2 to map_get.
     do_badmap(fun(T) ->
-		      {'EXIT',{{badmap,T},[{maps,get,_,_}|_]}} =
+		      {'EXIT',{{badmap,T},_}} =
 			  (catch maps:get(a, T))
 	      end),
 
-    {'EXIT',{{badkey,{1,1}},[{maps,get,_,_}|_]}} =
+    {'EXIT',{{badkey,{1,1}},_}} =
 	(catch maps:get({1,1}, #{{1,1.0} => "tuple"})),
-    {'EXIT',{{badkey,a},[{maps,get,_,_}|_]}} = (catch maps:get(a, #{})),
-    {'EXIT',{{badkey,a},[{maps,get,_,_}|_]}} =
+    {'EXIT',{{badkey,a},_}} = (catch maps:get(a, #{})),
+    {'EXIT',{{badkey,a},_}} =
 	(catch maps:get(a, #{b=>1, c=>2})),
     ok.
 
@@ -1942,8 +1945,11 @@ t_bif_map_is_key(Config) when is_list(Config) ->
     false = maps:is_key(1.0, maps:put(1, "number", M1)),
 
     %% error case
+    %%
+    %% Note that the stack trace is ignored because the compiler may have
+    %% rewritten maps:is_key/2 to is_map_key.
     do_badmap(fun(T) ->
-		      {'EXIT',{{badmap,T},[{maps,is_key,_,_}|_]}} =
+		      {'EXIT',{{badmap,T},_}} =
 			  (catch maps:is_key(a, T))
 	      end),
     ok.
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index a16a030f9d..93136f74cd 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -876,25 +876,45 @@ fold_apply(Apply, _, _) -> Apply.
 
 %% Handling remote calls. The module/name fields have been processed.
 
-call(#c_call{args=As}=Call, #c_literal{val=M}=M0, #c_literal{val=N}=N0, Sub) ->
-    case get(no_inline_list_funcs) of
-  	true ->
-	    call_1(Call, M0, N0, As, Sub);
-  	false ->
-	    case sys_core_fold_lists:call(Call, M, N, As) of
-		none ->
-		    call_1(Call, M0, N0, As, Sub);
-		Core ->
-		    expr(Core, Sub)
-	    end
-
-      end;
-call(#c_call{args=As}=Call, M, N, Sub) ->
-    call_1(Call, M, N, As, Sub).
-
-call_1(Call, M, N, As0, Sub) ->
+call(#c_call{args=As0}=Call0, #c_literal{val=M}=M0, #c_literal{val=N}=N0, Sub) ->
     As1 = expr_list(As0, value, Sub),
-    fold_call(Call#c_call{args=As1}, M, N, As1, Sub).
+    case simplify_call(Call0, M, N, As1) of
+        #c_literal{}=Lit ->
+            Lit;
+        #c_call{args=As}=Call ->
+            case get(no_inline_list_funcs) of
+                true ->
+                    fold_call(Call, M0, N0, As, Sub);
+                false ->
+                    case sys_core_fold_lists:call(Call, M, N, As) of
+                        none -> fold_call(Call, M0, N0, As, Sub);
+                        Core -> expr(Core, Sub)
+                    end
+            end
+    end;
+call(#c_call{args=As0}=Call, M, N, Sub) ->
+    As = expr_list(As0, value, Sub),
+    fold_call(Call#c_call{args=As}, M, N, As, Sub).
+
+%% Rewrite certain known functions to BIFs, improving performance
+%% slightly at the cost of making tracing and stack traces incorrect.
+simplify_call(Call, maps, get, [Key, Map]) ->
+    rewrite_call(Call, erlang, map_get, [Key, Map]);
+simplify_call(Call, maps, is_key, [Key, Map]) ->
+    rewrite_call(Call, erlang, is_map_key, [Key, Map]);
+simplify_call(_Call, maps, new, []) ->
+    #c_literal{val=#{}};
+simplify_call(Call, maps, size, [Map]) ->
+    rewrite_call(Call, erlang, map_size, [Map]);
+simplify_call(Call, _, _, Args) ->
+    Call#c_call{args=Args}.
+
+%% rewrite_call(Call0, Mod, Func, Args, Sub) -> Call
+%%  Rewrites a call to the given MFA.
+rewrite_call(Call, Mod, Func, Args) ->
+    ModLit = #c_literal{val=Mod},
+    FuncLit = #c_literal{val=Func},
+    Call#c_call{module=ModLit,name=FuncLit,args=Args}.
 
 %% fold_call(Call, Mod, Name, Args, Sub) -> Expr.
 %%  Try to safely evaluate the call.  Just try to evaluate arguments,
diff --git a/lib/stdlib/test/maps_SUITE.erl b/lib/stdlib/test/maps_SUITE.erl
index 9853068478..0ad6989cbb 100644
--- a/lib/stdlib/test/maps_SUITE.erl
+++ b/lib/stdlib/test/maps_SUITE.erl
@@ -237,8 +237,11 @@ t_size_1(Config) when is_list(Config) ->
     600 = maps:size(maps:from_list([{{"k",I},I}||I<-lists:seq(1,600)])),
 
     %% error case
-    ?badmap(a,size,[a]) = (catch maps:size(id(a))),
-    ?badmap(<<>>,size,[<<>>]) = (catch maps:size(id(<<>>))),
+    %%
+    %% Note that the stack trace is ignored because the compiler may have
+    %% rewritten maps:size/2 to map_size.
+    {'EXIT', {{badmap,a}, _}} = (catch maps:size(id(a))),
+    {'EXIT', {{badmap,<<>>}, _}} = (catch maps:size(id(<<>>))),
     ok.
 
 id(I) -> I.
-- 
2.16.4

openSUSE Build Service is sponsored by