aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-02-23 10:04:35 +0100
committerBjörn Gustavsson <[email protected]>2015-02-23 10:04:35 +0100
commitae19533a826c211d8ac1c06f59c62c2f3b7a3804 (patch)
tree161504962e4388f26590441eec65bbfdf7eed794 /lib/compiler/src
parent79736ff7d2e3916356fddda3a03fed8c9d292bdb (diff)
parent1899aa487d898078e6e7b1c6b7ea3aa5ea31c7e5 (diff)
downloadotp-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.erl24
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.