Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
1017-Enhance-creation-of-maps-with-literal-keys...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 1017-Enhance-creation-of-maps-with-literal-keys.patch of Package erlang
From 68e89fb4f10696b8ec41b82cb962f4b285fffe99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Tue, 26 Jul 2022 16:23:11 +0200 Subject: [PATCH 1/2] Enhance creation of maps with literal keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An optimization in the loader was added in: https://github.com/erlang/otp/pull/1498 When a small map is created where all keys are literals, the key tuple is created as a literal. That means that the key tuple can be shared for all instances of the map created by the same code. However, that does not always work, for example for code such as: decimal(Int) -> #{type => decimal, int => Int, exp => 0}. The compiler would try to be smart and rewrite the code to: decimal(Int) -> (#{type => decimal, exp => 0})#{int => Int}. Expressed in that way, the loader optimization cannot be applied and a new key tuple will be created every time `decimal/1` is called. This commit removes that problematic transformation. The implementation is based on José Valim's suggested implementation. Fixes #6139 --- lib/compiler/src/cerl.erl | 41 +++++++++++++++++++-------------- lib/compiler/test/map_SUITE.erl | 25 ++++++++++++++++++-- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl index bc28f58712..99651ebc2f 100644 --- a/lib/compiler/src/cerl.erl +++ b/lib/compiler/src/cerl.erl @@ -1647,34 +1647,41 @@ ann_c_map(As, Es) -> -spec ann_c_map([term()], c_map() | c_literal(), [c_map_pair()]) -> c_map() | c_literal(). -ann_c_map(As,#c_literal{val=M},Es) when is_map(M) -> - fold_map_pairs(As,Es,M); -ann_c_map(As,M,Es) -> - #c_map{arg=M, es=Es, anno=As }. - -fold_map_pairs(As,[],M) -> #c_literal{anno=As,val=M}; -%% M#{ K => V} -fold_map_pairs(As,[#c_map_pair{op=#c_literal{val=assoc},key=Ck,val=Cv}=E|Es],M) -> +ann_c_map(As, #c_literal{val=M0}=Lit, Es) when is_map(M0) -> + case update_map_literal(Es, M0) of + none -> + #c_map{arg=Lit, es=Es, anno=As}; + M1 -> + #c_literal{anno=As, val=M1} + end; +ann_c_map(As, M, Es) -> + #c_map{arg=M, es=Es, anno=As}. + +update_map_literal([#c_map_pair{op=#c_literal{val=assoc},key=Ck,val=Cv}|Es], M) -> + %% M#{K => V} case is_lit_list([Ck,Cv]) of true -> [K,V] = lit_list_vals([Ck,Cv]), - fold_map_pairs(As,Es,maps:put(K,V,M)); + update_map_literal(Es, M#{K => V}); false -> - #c_map{arg=#c_literal{val=M,anno=As}, es=[E|Es], anno=As } + none end; -%% M#{ K := V} -fold_map_pairs(As,[#c_map_pair{op=#c_literal{val=exact},key=Ck,val=Cv}=E|Es],M) -> +update_map_literal([#c_map_pair{op=#c_literal{val=exact},key=Ck,val=Cv}|Es], M) -> + %% M#{K := V} case is_lit_list([Ck,Cv]) of true -> [K,V] = lit_list_vals([Ck,Cv]), - case maps:is_key(K,M) of - true -> fold_map_pairs(As,Es,maps:put(K,V,M)); + case is_map_key(K, M) of + true -> + update_map_literal(Es, M#{K => V}); false -> - #c_map{arg=#c_literal{val=M,anno=As}, es=[E|Es], anno=As } + none end; false -> - #c_map{arg=#c_literal{val=M,anno=As}, es=[E|Es], anno=As } - end. + none + end; +update_map_literal([], M) -> + M. -spec update_c_map(c_map(), cerl(), [cerl()]) -> c_map() | c_literal(). diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index 4db5b01109..8716d85477 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -77,7 +77,10 @@ t_duplicate_keys/1, %% new in OTP 23 - t_key_expressions/1 + t_key_expressions/1, + + %% miscellaneous + shared_key_tuples/1 ]). suite() -> []. @@ -138,7 +141,10 @@ all() -> t_duplicate_keys, %% new in OTP 23 - t_key_expressions + t_key_expressions, + + %% miscellaneous + shared_key_tuples ]. groups() -> []. @@ -2337,6 +2343,25 @@ do_cse_assoc(M, V) -> O2 end. +shared_key_tuples(_Config) -> + A = decimal(0), + B = decimal(1), + + case ?MODULE of + map_inline_SUITE -> + %% With inlining, two separate map literals will be created. They + %% will not share keys. + ok; + _ -> + %% The two instances should share the key tuple. + true = erts_debug:same(erts_internal:map_to_tuple_keys(A), + erts_internal:map_to_tuple_keys(B)) + end, + ok. + +decimal(Int) -> + #{type => decimal, int => Int, exp => 0}. + %% aux rand_terms(0) -> []; -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor