diff options
author | Björn Gustavsson <[email protected]> | 2015-02-23 10:04:35 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2015-02-23 10:04:35 +0100 |
commit | ae19533a826c211d8ac1c06f59c62c2f3b7a3804 (patch) | |
tree | 161504962e4388f26590441eec65bbfdf7eed794 /lib/compiler/src | |
parent | 79736ff7d2e3916356fddda3a03fed8c9d292bdb (diff) | |
parent | 1899aa487d898078e6e7b1c6b7ea3aa5ea31c7e5 (diff) | |
download | otp-ae19533a826c211d8ac1c06f59c62c2f3b7a3804.tar.gz otp-ae19533a826c211d8ac1c06f59c62c2f3b7a3804.tar.bz2 otp-ae19533a826c211d8ac1c06f59c62c2f3b7a3804.zip |
Merge branch 'bjorn/compiler/beam_jump-share'
* bjorn/compiler/beam_jump-share:
beam_jump: Don't jump into the middle of a 'try'
Diffstat (limited to 'lib/compiler/src')
-rw-r--r-- | lib/compiler/src/beam_jump.erl | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl index 52fe0e90ce..ba71d4efae 100644 --- a/lib/compiler/src/beam_jump.erl +++ b/lib/compiler/src/beam_jump.erl @@ -166,6 +166,12 @@ share_1([{label,L}=Lbl|Is], Dict0, Seq, Acc) -> end; share_1([{func_info,_,_,_}=I|Is], _, [], Acc) -> reverse(Is, [I|Acc]); +share_1([{'try',_,_}=I|Is], Dict0, Seq, Acc) -> + Dict = clean_non_sharable(Dict0), + share_1(Is, Dict, [I|Seq], Acc); +share_1([{try_case,_}=I|Is], Dict0, Seq, Acc) -> + Dict = clean_non_sharable(Dict0), + share_1(Is, Dict, [I|Seq], Acc); share_1([I|Is], Dict, Seq, Acc) -> case is_unreachable_after(I) of false -> @@ -174,6 +180,24 @@ share_1([I|Is], Dict, Seq, Acc) -> share_1(Is, Dict, [I], Acc) end. +clean_non_sharable(Dict) -> + %% We are passing in or out of a 'try' block. Remove + %% sequences that should not shared over the boundaries + %% of a 'try' block. Since the end of the sequence must match, + %% the only possible match between a sequence outside and + %% a sequence inside the 'try' block is a sequence that ends + %% with an instruction that causes an exception. Any sequence + %% that causes an exception must contain a line/1 instruction. + dict:filter(fun(K, _V) -> sharable_with_try(K) end, Dict). + +sharable_with_try([{line,_}|_]) -> + %% This sequence may cause an exception and may potentially + %% match a sequence on the other side of the 'try' block + %% boundary. + false; +sharable_with_try([_|Is]) -> + sharable_with_try(Is); +sharable_with_try([]) -> true. %% Eliminate all fallthroughs. Return the result reversed. |