diff options
author | Björn Gustavsson <[email protected]> | 2016-05-23 20:13:48 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2016-05-30 13:19:20 +0200 |
commit | b1b27719d713c0e62d3242bbf1da0600ea0a651f (patch) | |
tree | 7376b00ada2e29bae532bd997a2a02fecec1faf6 /lib/compiler/src | |
parent | 88632d70cc866b5e54589ccb9311c7c5a88ecb46 (diff) | |
download | otp-b1b27719d713c0e62d3242bbf1da0600ea0a651f.tar.gz otp-b1b27719d713c0e62d3242bbf1da0600ea0a651f.tar.bz2 otp-b1b27719d713c0e62d3242bbf1da0600ea0a651f.zip |
Eliminate unsafe use of Y registers
If the Core Erlang optimization were turned off (using no_copt),
the optimization passes for Beam assembly could generate unsafe
code that did not initialize all Y registers before (for example)
a call instruction.
To fix this, beam_dead should not attempt to remove stores to Y
registers. That is not safe if there is an exception-generating
instruction inside a try...catch block.
Diffstat (limited to 'lib/compiler/src')
-rw-r--r-- | lib/compiler/src/beam_dead.erl | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl index dd42add433..b01f58f683 100644 --- a/lib/compiler/src/beam_dead.erl +++ b/lib/compiler/src/beam_dead.erl @@ -262,7 +262,7 @@ backward([{select,select_val,Reg,{f,Fail0},List0}|Is], D, Acc) -> backward([{jump,{f,To0}},{move,Src,Reg}=Move|Is], D, Acc) -> To = shortcut_select_label(To0, Reg, Src, D), Jump = {jump,{f,To}}, - case beam_utils:is_killed_at(Reg, To, D) of + case is_killed_at(Reg, To, D) of false -> backward([Move|Is], D, [Jump|Acc]); true -> backward([Jump|Is], D, Acc) end; @@ -420,7 +420,7 @@ comp_op_find_shortcut(To0, Reg, Val, D) -> To0 -> not_possible(); To -> - case beam_utils:is_killed_at(Reg, To, D) of + case is_killed_at(Reg, To, D) of false -> not_possible(); true -> To end @@ -863,3 +863,17 @@ get_literal(nil) -> get_literal({literal,_}=Lit) -> Lit; get_literal({_,_}) -> error. + + +%%% +%%% Removing stores to Y registers is not always safe +%%% if there is an instruction that causes an exception +%%% within a catch. In practice, there are few or no +%%% opportunities for removing stores to Y registers anyway +%%% if sys_core_fold has been run. +%%% + +is_killed_at({x,_}=Reg, Lbl, D) -> + beam_utils:is_killed_at(Reg, Lbl, D); +is_killed_at({y,_}, _, _) -> + false. |