diff options
Diffstat (limited to 'lib/compiler/src/beam_bsm.erl')
-rw-r--r-- | lib/compiler/src/beam_bsm.erl | 91 |
1 files changed, 16 insertions, 75 deletions
diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl index 1217f7f777..37053e1cc4 100644 --- a/lib/compiler/src/beam_bsm.erl +++ b/lib/compiler/src/beam_bsm.erl @@ -204,16 +204,6 @@ btb_reaches_match_1(Is, Regs, D) -> btb_reaches_match_2([{block,Bl}|Is], Regs0, D) -> Regs = btb_reaches_match_block(Bl, Regs0), btb_reaches_match_1(Is, Regs, D); -btb_reaches_match_2([{call_only,Arity,{f,Lbl}}|_], Regs0, D) -> - Regs = btb_kill_not_live(Arity, Regs0), - btb_tail_call(Lbl, Regs, D); -btb_reaches_match_2([{call_ext_only,Arity,Func}|_], Regs0, D) -> - Regs = btb_kill_not_live(Arity, Regs0), - btb_tail_call(Func, Regs, D); -btb_reaches_match_2([{call_last,Arity,{f,Lbl},_}|_], Regs0, D) -> - Regs1 = btb_kill_not_live(Arity, Regs0), - Regs = btb_kill_yregs(Regs1), - btb_tail_call(Lbl, Regs, D); btb_reaches_match_2([{call,Arity,{f,Lbl}}|Is], Regs, D) -> btb_call(Arity, Lbl, Regs, Is, D); btb_reaches_match_2([{apply,Arity}|Is], Regs, D) -> @@ -222,19 +212,16 @@ btb_reaches_match_2([{call_fun,Live}=I|Is], Regs, D) -> btb_call(Live, I, Regs, Is, D); btb_reaches_match_2([{make_fun2,_,_,_,Live}|Is], Regs, D) -> btb_call(Live, make_fun2, Regs, Is, D); -btb_reaches_match_2([{call_ext,Arity,{extfunc,Mod,Name,Arity}=Func}|Is], Regs0, D) -> +btb_reaches_match_2([{call_ext,Arity,Func}=I|Is], Regs0, D) -> %% Allow us scanning beyond the call in case the match %% context is saved on the stack. - case erl_bifs:is_exit_bif(Mod, Name, Arity) of + case beam_jump:is_exit_instruction(I) of false -> btb_call(Arity, Func, Regs0, Is, D); true -> Regs = btb_kill_not_live(Arity, Regs0), btb_tail_call(Func, Regs, D) end; -btb_reaches_match_2([{call_ext_last,Arity,_,_}=I|_], Regs, D) -> - btb_ensure_not_used(btb_regs_from_arity(Arity), I, Regs), - D; btb_reaches_match_2([{kill,Y}|Is], Regs, D) -> btb_reaches_match_1(Is, btb_kill([Y], Regs), D); btb_reaches_match_2([{deallocate,_}|Is], Regs0, D) -> @@ -278,12 +265,7 @@ btb_reaches_match_2([{test,_,{f,F},_,Ss,_}=I|Is], Regs, D0) -> btb_ensure_not_used(Ss, I, Regs), D = btb_follow_branch(F, Regs, D0), btb_reaches_match_1(Is, Regs, D); -btb_reaches_match_2([{select_val,Src,{f,F},{list,Conds}}=I|Is], Regs, D0) -> - btb_ensure_not_used([Src], I, Regs), - D1 = btb_follow_branch(F, Regs, D0), - D = btb_follow_branches(Conds, Regs, D1), - btb_reaches_match_1(Is, Regs, D); -btb_reaches_match_2([{select_tuple_arity,Src,{f,F},{list,Conds}}=I|Is], Regs, D0) -> +btb_reaches_match_2([{select,_,Src,{f,F},Conds}=I|Is], Regs, D0) -> btb_ensure_not_used([Src], I, Regs), D1 = btb_follow_branch(F, Regs, D0), D = btb_follow_branches(Conds, Regs, D1), @@ -293,46 +275,11 @@ btb_reaches_match_2([{jump,{f,Lbl}}|_], Regs, #btb{index=Li}=D) -> btb_reaches_match_2(Is, Regs, D); btb_reaches_match_2([{label,_}|Is], Regs, D) -> btb_reaches_match_2(Is, Regs, D); -btb_reaches_match_2([{bs_add,{f,0},_,Dst}|Is], Regs, D) -> - btb_reaches_match_1(Is, btb_kill([Dst], Regs), D); -btb_reaches_match_2([bs_init_writable|Is], Regs0, D) -> - Regs = btb_kill_not_live(0, Regs0), - btb_reaches_match_1(Is, Regs, D); -btb_reaches_match_2([{bs_init2,{f,0},_,_,_,_,Dst}|Is], Regs, D) -> - btb_reaches_match_1(Is, btb_kill([Dst], Regs), D); -btb_reaches_match_2([{bs_init_bits,{f,0},_,_,_,_,Dst}|Is], Regs, D) -> - btb_reaches_match_1(Is, btb_kill([Dst], Regs), D); -btb_reaches_match_2([{bs_append,{f,0},_,_,_,_,Src,_,Dst}=I|Is], Regs, D) -> - btb_ensure_not_used([Src], I, Regs), - btb_reaches_match_1(Is, btb_kill([Dst], Regs), D); -btb_reaches_match_2([{bs_private_append,{f,0},_,_,Src,_,Dst}=I|Is], Regs, D) -> - btb_ensure_not_used([Src], I, Regs), - btb_reaches_match_1(Is, btb_kill([Dst], Regs), D); -btb_reaches_match_2([{bs_put_integer,{f,0},_,_,_,Src}=I|Is], Regs, D) -> - btb_ensure_not_used([Src], I, Regs), - btb_reaches_match_1(Is, Regs, D); -btb_reaches_match_2([{bs_put_float,{f,0},_,_,_,Src}=I|Is], Regs, D) -> - btb_ensure_not_used([Src], I, Regs), - btb_reaches_match_1(Is, Regs, D); -btb_reaches_match_2([{bs_put_binary,{f,0},_,_,_,Src}=I|Is], Regs, D) -> - btb_ensure_not_used([Src], I, Regs), - btb_reaches_match_1(Is, Regs, D); -btb_reaches_match_2([{bs_put_string,_,_}|Is], Regs, D) -> - btb_reaches_match_1(Is, Regs, D); -btb_reaches_match_2([{bs_utf8_size,_,Src,Dst}=I|Is], Regs, D) -> - btb_ensure_not_used([Src], I, Regs), - btb_reaches_match_1(Is, btb_kill([Dst], Regs), D); -btb_reaches_match_2([{bs_utf16_size,_,Src,Dst}=I|Is], Regs, D) -> - btb_ensure_not_used([Src], I, Regs), +btb_reaches_match_2([{bs_init,{f,0},_,_,Ss,Dst}=I|Is], Regs, D) -> + btb_ensure_not_used(Ss, I, Regs), btb_reaches_match_1(Is, btb_kill([Dst], Regs), D); -btb_reaches_match_2([{bs_put_utf8,_,_,Src}=I|Is], Regs, D) -> - btb_ensure_not_used([Src], I, Regs), - btb_reaches_match_1(Is, Regs, D); -btb_reaches_match_2([{bs_put_utf16,_,_,Src}=I|Is], Regs, D) -> - btb_ensure_not_used([Src], I, Regs), - btb_reaches_match_1(Is, Regs, D); -btb_reaches_match_2([{bs_put_utf32,_,_,Src}=I|Is], Regs, D) -> - btb_ensure_not_used([Src], I, Regs), +btb_reaches_match_2([{bs_put,{f,0},_,Ss}=I|Is], Regs, D) -> + btb_ensure_not_used(Ss, I, Regs), btb_reaches_match_1(Is, Regs, D); btb_reaches_match_2([{bs_restore2,Src,_}=I|Is], Regs0, D) -> case btb_contains_context(Src, Regs0) of @@ -389,13 +336,16 @@ btb_call(Arity, Lbl, Regs0, Is, D0) -> %% First handle the call as if it were a tail call. D = btb_tail_call(Lbl, Regs, D0), - %% No problem so far, but now we must make sure that - %% we don't have any copies of the match context - %% tucked away in an y register. + %% No problem so far (the called function can handle a + %% match context). Now we must make sure that the rest + %% of this function following the call does not attempt + %% to use the match context in case there is a copy + %% tucked away in a y register. RegList = btb_context_regs(Regs), - case [R || {y,_}=R <- RegList] of - [] -> D; - [_|_] -> btb_error({multiple_uses,RegList}) + YRegs = [R || {y,_}=R <- RegList], + case btb_are_all_killed(YRegs, Is, D) of + true -> D; + false -> btb_error({multiple_uses,RegList}) end; true -> %% No match context in any x register. It could have been @@ -475,15 +425,6 @@ btb_reaches_match_block([{set,Ds,Ss,_}=I|Is], Regs0) -> btb_reaches_match_block([], Regs) -> Regs. -%% btb_regs_from_arity(Arity) -> [Register]) -%% Create a list of x registers from a function arity. - -btb_regs_from_arity(Arity) -> - btb_regs_from_arity_1(Arity, []). - -btb_regs_from_arity_1(0, Acc) -> Acc; -btb_regs_from_arity_1(N, Acc) -> btb_regs_from_arity_1(N-1, [{x,N-1}|Acc]). - %% btb_are_all_killed([Register], [Instruction], D) -> true|false %% Test whether all of the register are killed in the instruction stream. |