diff options
author | Björn Gustavsson <[email protected]> | 2016-10-07 14:19:29 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-10-07 14:19:29 +0200 |
commit | 16f2daa48333cced93f4f31d9a57e5d2e3a8f9e8 (patch) | |
tree | 4ddef6b09c76b957fdd83a44e6844379f0cb64dd /lib/compiler/src/beam_bsm.erl | |
parent | 1f0ce3e83982c80a84e31ab16a89dd65b45157f8 (diff) | |
parent | c8fb8c177b9f74ddea36d9c002df4f9c1bf4fb27 (diff) | |
download | otp-16f2daa48333cced93f4f31d9a57e5d2e3a8f9e8.tar.gz otp-16f2daa48333cced93f4f31d9a57e5d2e3a8f9e8.tar.bz2 otp-16f2daa48333cced93f4f31d9a57e5d2e3a8f9e8.zip |
Merge branch 'maint'
* maint:
beam_bsm: Eliminate unsafe optimization
Diffstat (limited to 'lib/compiler/src/beam_bsm.erl')
-rw-r--r-- | lib/compiler/src/beam_bsm.erl | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl index 286307a4be..ae1b34ba49 100644 --- a/lib/compiler/src/beam_bsm.erl +++ b/lib/compiler/src/beam_bsm.erl @@ -205,8 +205,15 @@ 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,Arity,{f,Lbl}}|Is], Regs, D) -> - btb_call(Arity, Lbl, Regs, Is, D); +btb_reaches_match_2([{call,Arity,{f,Lbl}}|Is], Regs0, D) -> + case is_tail_call(Is) of + true -> + Regs1 = btb_kill_not_live(Arity, Regs0), + Regs = btb_kill_yregs(Regs1), + btb_tail_call(Lbl, Regs, D); + false -> + btb_call(Arity, Lbl, Regs0, Is, D) + end; btb_reaches_match_2([{apply,Arity}|Is], Regs, D) -> btb_call(Arity+2, apply, Regs, Is, D); btb_reaches_match_2([{call_fun,Live}=I|Is], Regs, D) -> @@ -360,6 +367,10 @@ btb_reaches_match_2([{line,_}|Is], Regs, D) -> btb_reaches_match_2([I|_], Regs, _) -> btb_error({btb_context_regs(Regs),I,not_handled}). +is_tail_call([{deallocate,_}|_]) -> true; +is_tail_call([return|_]) -> true; +is_tail_call(_) -> false. + btb_call(Arity, Lbl, Regs0, Is, D0) -> Regs = btb_kill_not_live(Arity, Regs0), case btb_are_x_registers_empty(Regs) of @@ -369,15 +380,15 @@ btb_call(Arity, Lbl, Regs0, Is, D0) -> D = btb_tail_call(Lbl, Regs, D0), %% 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. + %% match context). Now we must make sure that we don't + %% have any copies of the match context tucked away in an + %% y register. RegList = btb_context_regs(Regs), - YRegs = [R || {y,_}=R <- RegList], - case btb_are_all_unused(YRegs, Is, D) of - true -> D; - false -> btb_error({multiple_uses,RegList}) + case [R || {y,_}=R <- RegList] of + [] -> + D; + [_|_] -> + btb_error({multiple_uses,RegList}) end; true -> %% No match context in any x register. It could have been |