diff options
author | Björn-Egil Dahlberg <[email protected]> | 2014-03-06 18:00:52 +0100 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2014-03-17 17:47:35 +0100 |
commit | 5d75a3b453b64ae1b10c8980ec5c146d7b2d5d1a (patch) | |
tree | 0a5601a0b059d1cb9f289f31169c77c574feddd9 /lib/compiler | |
parent | 90a948d7cf7f188b5461c2a7bb25a656ec681966 (diff) | |
download | otp-5d75a3b453b64ae1b10c8980ec5c146d7b2d5d1a.tar.gz otp-5d75a3b453b64ae1b10c8980ec5c146d7b2d5d1a.tar.bz2 otp-5d75a3b453b64ae1b10c8980ec5c146d7b2d5d1a.zip |
compiler: Constant fold Maps that are safe
For updates of Map literals which may cause an error will be
determined in runtime, i.e. instructions are emitted for those
updates.
The changes in cerl now requires compiler-5.0 to compile because of
is_map/1 guard.
Diffstat (limited to 'lib/compiler')
-rw-r--r-- | lib/compiler/src/cerl.erl | 32 | ||||
-rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 4 |
2 files changed, 33 insertions, 3 deletions
diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl index 9024999d7f..61b47ed468 100644 --- a/lib/compiler/src/cerl.erl +++ b/lib/compiler/src/cerl.erl @@ -1588,7 +1588,7 @@ ann_c_map(As,Es) -> ann_c_map(As, #c_literal{val=#{}}, Es). ann_c_map(As,#c_literal{val=Mval}=M,Es) when is_map(Mval), map_size(Mval) =:= 0 -> - Pairs = [[K,V]||#c_map_pair{key=K,val=V}<-Es], + Pairs = [[Ck,Cv]||#c_map_pair{key=Ck,val=Cv}<-Es], IsLit = lists:foldl(fun(Pair,Res) -> Res andalso is_lit_list(Pair) end, true, Pairs), @@ -1599,8 +1599,36 @@ ann_c_map(As,#c_literal{val=Mval}=M,Es) when is_map(Mval), map_size(Mval) =:= 0 true -> #c_literal{anno=As, val=maps:from_list(lists:map(Fun, Pairs))} end; +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{var=M, es = Es, anno = As }. + #c_map{var=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) -> + 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)); + false -> + #c_map{var=#c_literal{val=M,anno=As}, es=[E|Es], anno=As } + end; +%% M#{ K := V} +fold_map_pairs(As,[#c_map_pair{op=#c_literal{val=exact},key=Ck,val=Cv}=E|Es],M) -> + 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)); + false -> + #c_map{var=#c_literal{val=M,anno=As}, es=[E|Es], anno=As } + end; + false -> + #c_map{var=#c_literal{val=M,anno=As}, es=[E|Es], anno=As } + end; +fold_map_pairs(As,Es,M) -> + #c_map{var=#c_literal{val=M,anno=As}, es=Es, anno=As }. update_c_map(Old,M,Es) -> diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 90cc3b9051..bf1be6d773 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -72,7 +72,7 @@ -import(lists, [map/2,foldl/3,foldr/3,mapfoldl/3,all/2,any/2, reverse/1,reverse/2,member/2,nth/2,flatten/1,unzip/1]). --import(cerl, [ann_c_cons/3,ann_c_tuple/2,ann_c_map/3]). +-import(cerl, [ann_c_cons/3,ann_c_map/3,ann_c_tuple/2]). -include("core_parse.hrl"). @@ -1378,6 +1378,7 @@ eval_is_record(Call, _, _, _, _) -> Call. is_not_integer(#c_literal{val=Val}) when not is_integer(Val) -> true; is_not_integer(#c_tuple{}) -> true; is_not_integer(#c_cons{}) -> true; +is_not_integer(#c_map{}) -> true; is_not_integer(_) -> false. %% is_not_tuple(Core) -> true | false. @@ -1385,6 +1386,7 @@ is_not_integer(_) -> false. is_not_tuple(#c_literal{val=Val}) when not is_tuple(Val) -> true; is_not_tuple(#c_cons{}) -> true; +is_not_tuple(#c_map{}) -> true; is_not_tuple(_) -> false. %% eval_setelement(Call, Pos, Tuple, NewVal) -> Core. |