diff options
author | Björn Gustavsson <[email protected]> | 2010-11-26 11:47:50 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2010-12-02 17:12:24 +0100 |
commit | 2b03fbacf1ac0c06a84439baac90d418916a1778 (patch) | |
tree | a42ca97705f775998d0bc779db20b47b4e752816 /lib | |
parent | 8836ebccae92886decf5645944ae4ce8a2f99947 (diff) | |
download | otp-2b03fbacf1ac0c06a84439baac90d418916a1778.tar.gz otp-2b03fbacf1ac0c06a84439baac90d418916a1778.tar.bz2 otp-2b03fbacf1ac0c06a84439baac90d418916a1778.zip |
beam_utils: Fix check_liveness/3 for receive loops
Sometimes the beam_bool pass wants to know whether an
y register will be killed by the code that follows and
will do (effectively):
beam_utils:is_killed({y,Y}, Code, L)
When asked to calculate the liveness for an y register,
beam_utils:is_killed/3 will loop forever if the code
includes a receive loop.
Since this rarely occurs, fix the problem in the simplest
and most conservative way.
Reported-by: Christopher Williams
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compiler/src/beam_utils.erl | 9 | ||||
-rw-r--r-- | lib/compiler/test/compilation_SUITE.erl | 20 |
2 files changed, 25 insertions, 4 deletions
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index dc8079d0b7..45cdf8a659 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -489,10 +489,13 @@ check_liveness(R, [{bs_context_to_binary,S}|Is], St) -> S -> {used,St}; _ -> check_liveness(R, Is, St) end; -check_liveness(R, [{loop_rec,{f,_},{x,0}}|Is], St) -> +check_liveness(R, [{loop_rec,{f,_},{x,0}}|_], St) -> case R of - {x,_} -> {killed,St}; - _ -> check_liveness(R, Is, St) + {x,_} -> + {killed,St}; + _ -> + %% y register. Rarely happens. Be very conversative. + {unknown,St} end; check_liveness(R, [{loop_rec_end,{f,Fail}}|_], St) -> check_liveness_at(R, Fail, St); diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl index 7b6975f912..935e384d2d 100644 --- a/lib/compiler/test/compilation_SUITE.erl +++ b/lib/compiler/test/compilation_SUITE.erl @@ -46,7 +46,7 @@ all(suite) -> trycatch_4, opt_crash, otp_5404,otp_5436,otp_5481,otp_5553,otp_5632, otp_5714,otp_5872,otp_6121,otp_6121a,otp_6121b, - otp_7202,otp_7345,on_load,string_table,otp_8949_a + otp_7202,otp_7345,on_load,string_table,otp_8949_a,otp_8949_a ]. -define(comp(N), @@ -628,5 +628,23 @@ otp_8949_a() -> end end. +otp_8949_b(Config) when is_list(Config) -> + self() ! something, + ?line value = otp_8949_b([], false), + ?line {'EXIT',_} = (catch otp_8949_b([], true)), + ok. + +%% Would cause an endless loop in beam_utils. +otp_8949_b(A, B) -> + Var = id(value), + if + A == [], B == false -> + ok + end, + receive + something -> + id(Var) + end. + id(I) -> I. |