diff options
Diffstat (limited to 'lib/compiler/src/beam_jump.erl')
-rw-r--r-- | lib/compiler/src/beam_jump.erl | 58 |
1 files changed, 44 insertions, 14 deletions
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl index 555af00ccc..9ae5a33d74 100644 --- a/lib/compiler/src/beam_jump.erl +++ b/lib/compiler/src/beam_jump.erl @@ -407,30 +407,43 @@ share_1([I|Is], Safe, Dict, Lbls, Seq, Acc) -> share_1(Is, Safe, Dict, Lbls, [I], Acc) end. -unambigous_deallocation([{call_ext,_,_}|Is]) -> +unambigous_deallocation([{bs_init,_,bs_init_writable,_,_,_}|Is]) -> %% beam_validator requires that the size of the stack frame is - %% unambigously known when a function is called. + %% unambigously known when certain instructions are used. %% - %% That means that we must be careful when sharing function calls. + %% That means that we must be careful when sharing them. %% %% To ensure that the frame size is unambigous, only allow sharing %% of calls if the call is followed by instructions that %% indicates the size of the stack frame. find_deallocation(Is); +unambigous_deallocation([{call_ext,_,_}|Is]) -> + find_deallocation(Is); unambigous_deallocation([{call,_,_}|Is]) -> find_deallocation(Is); unambigous_deallocation([_|Is]) -> unambigous_deallocation(Is); -unambigous_deallocation([]) -> true. +unambigous_deallocation([]) -> + true. -find_deallocation([{line,_}|Is]) -> find_deallocation(Is); -find_deallocation([{call,_,_}|Is]) -> find_deallocation(Is); -find_deallocation([{call_ext,_,_}|Is]) -> find_deallocation(Is); -find_deallocation([{init_yregs,_}|Is]) -> find_deallocation(Is); -find_deallocation([{block,_}|Is]) -> find_deallocation(Is); -find_deallocation([{deallocate,_}|_]) -> true; -find_deallocation([return]) -> true; -find_deallocation(_) -> false. +find_deallocation([{block,_}|Is]) -> + find_deallocation(Is); +find_deallocation([{bs_init,_,bs_init_writable,_,_,_}|Is]) -> + find_deallocation(Is); +find_deallocation([{call,_,_}|Is]) -> + find_deallocation(Is); +find_deallocation([{call_ext,_,_}|Is]) -> + find_deallocation(Is); +find_deallocation([{deallocate,_}|_]) -> + true; +find_deallocation([{init_yregs,_}|Is]) -> + find_deallocation(Is); +find_deallocation([{line,_}|Is]) -> + find_deallocation(Is); +find_deallocation([return]) -> + true; +find_deallocation(_) -> + false. %% If the label has a scope set, assign it to any line instruction %% in the sequence. @@ -451,6 +464,7 @@ add_scope([I|Is], Scope) -> [I|add_scope(Is, Scope)]; add_scope([], _Scope) -> []. +is_shareable([{badmatch,_}|_]) -> false; is_shareable([build_stacktrace|_]) -> false; is_shareable([{case_end,_}|_]) -> false; is_shareable([{'catch',_,_}|_]) -> false; @@ -599,20 +613,23 @@ find_fixpoint(OptFun, Is0) -> opt([{test,is_eq_exact,{f,L},_}|[{jump,{f,L}}|_]=Is], Acc, St) -> %% The is_eq_exact test is not needed. opt(Is, Acc, St); -opt([{test,Test0,{f,L}=Lbl,Ops}=I|[{jump,To}|Is]=Is0], Acc, St) -> +opt([{test,Test0,{f,L}=Lbl,Ops}=I0|[{jump,To}|Is]=Is0], Acc, St) -> case is_label_defined(Is, L) of false -> + I = is_lt_to_is_ge(I0), opt(Is0, [I|Acc], label_used(Lbl, St)); true -> case invert_test(Test0) of not_possible -> + I = is_lt_to_is_ge(I0), opt(Is0, [I|Acc], label_used(Lbl, St)); Test -> %% Invert the test and remove the jump. opt([{test,Test,To,Ops}|Is], Acc, St) end end; -opt([{test,_,{f,_}=Lbl,_}=I|Is], Acc, St) -> +opt([{test,_,{f,_}=Lbl,_}=I0|Is], Acc, St) -> + I = is_lt_to_is_ge(I0), opt(Is, [I|Acc], label_used(Lbl, St)); opt([{test,_,{f,_}=Lbl,_,_,_}=I|Is], Acc, St) -> opt(Is, [I|Acc], label_used(Lbl, St)); @@ -673,6 +690,17 @@ opt([], Acc, #st{replace=Replace0}) when Replace0 =/= #{} -> opt([], Acc, #st{replace=Replace}) when Replace =:= #{} -> reverse(Acc). +is_lt_to_is_ge({test,is_lt,Lbl,Args}=I) -> + case Args of + [{integer,N},{tr,_,#t_integer{}}=Src] -> + {test,is_ge,Lbl,[Src,{integer,N+1}]}; + [{tr,_,#t_integer{}}=Src,{integer,N}] -> + {test,is_ge,Lbl,[{integer,N-1},Src]}; + [_,_] -> + I + end; +is_lt_to_is_ge(I) -> I. + prune_redundant_values([_Val,F|Vls], F) -> prune_redundant_values(Vls, F); prune_redundant_values([Val,Lbl|Vls], F) -> @@ -911,6 +939,8 @@ instr_labels({bs_start_match4,Fail,_,_,_}) -> {f,L} -> [L]; {atom,_} -> [] end; +instr_labels({bs_match,{f,Fail},_Ctx,_List}) -> + [Fail]; instr_labels(_) -> []. |