diff options
Diffstat (limited to 'lib/compiler/src/v3_codegen.erl')
-rw-r--r-- | lib/compiler/src/v3_codegen.erl | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl index 4d155c0fd0..47a357c23d 100644 --- a/lib/compiler/src/v3_codegen.erl +++ b/lib/compiler/src/v3_codegen.erl @@ -938,22 +938,38 @@ select_map_val(V, Es, B, Fail, I, Vdb, Bef, St0) -> {Bis,Aft,St2} = match_cg(B, Fail, Int, St1), {Eis++Bis,Aft,St2}. +select_extract_map(_, [], _, _, _, Bef, St) -> {[],Bef,St}; select_extract_map(Src, Vs, Fail, I, Vdb, Bef, St) -> - F = fun ({map_pair,Key,{var,V}}, Int0) -> - Rsrc = fetch_var(Src, Int0), + %% First split the instruction flow + %% We want one set of each + %% 1) has_map_fields (no target registers) + %% 2) get_map_elements (with target registers) + %% Assume keys are term-sorted + Rsrc = fetch_var(Src, Bef), + + {{HasKs,GetVs},Aft} = lists:foldr(fun + ({map_pair,Key,{var,V}},{{HasKsi,GetVsi},Int0}) -> case vdb_find(V, Vdb) of {V,_,L} when L =< I -> - {[{test,has_map_field,{f,Fail},[Rsrc,Key]}],Int0}; + {{[Key|HasKsi],GetVsi},Int0}; _Other -> Reg1 = put_reg(V, Int0#sr.reg), Int1 = Int0#sr{reg=Reg1}, - {[{get_map_element,{f,Fail}, - Rsrc,Key,fetch_reg(V, Reg1)}], - Int1} + {{HasKsi,[Key,fetch_reg(V, Reg1)|GetVsi]},Int1} end - end, - {Es,Aft} = flatmapfoldl(F, Bef, Vs), - {Es,Aft,St}. + end, {{[],[]},Bef}, Vs), + + Code = case {HasKs,GetVs} of + {HasKs,[]} -> + [{test,has_map_fields,{f,Fail},Rsrc,{list,HasKs}}]; + {[],GetVs} -> + [{get_map_elements, {f,Fail},Rsrc,{list,GetVs}}]; + {HasKs,GetVs} -> + [{test,has_map_fields,{f,Fail},Rsrc,{list,HasKs}}, + {get_map_elements, {f,Fail},Rsrc,{list,GetVs}}] + end, + {Code, Aft, St}. + select_extract_cons(Src, [{var,Hd}, {var,Tl}], I, Vdb, Bef, St) -> {Es,Aft} = case {vdb_find(Hd, Vdb), vdb_find(Tl, Vdb)} of @@ -1534,7 +1550,10 @@ map_pair_strip_and_termsort(Es) -> %% [{map_pair,K,V}] %% where K is for example {integer, 1} and we want to sort on 1. Ls = [{K,V}||{_,K,V}<-Es], - lists:sort(fun({{_,A},_},{{_,B},_}) -> erts_internal:cmp_term(A,B) < 0 end, Ls). + lists:sort(fun ({{_,A},_}, {{_,B},_}) -> erts_internal:cmp_term(A,B) =< 0; + ({nil,_}, {{_,B},_}) -> [] =< B; + ({{_,A},_}, {nil,_}) -> A =< [] + end, Ls). %%% %%% Code generation for constructing binaries. |