aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-08-05 19:12:15 +0200
committerBjörn Gustavsson <[email protected]>2015-08-21 15:56:14 +0200
commit3640e5c89bda0ca45b3320e8a00efb48b9d9f531 (patch)
tree24d721f71f1879a6d1cf7b46002c14ab97ba4155
parentc288ab87fd6cafe22ce46be551baa2e815b495b0 (diff)
downloadotp-3640e5c89bda0ca45b3320e8a00efb48b9d9f531.tar.gz
otp-3640e5c89bda0ca45b3320e8a00efb48b9d9f531.tar.bz2
otp-3640e5c89bda0ca45b3320e8a00efb48b9d9f531.zip
Reorder instructions across try/catch
Simplify further optimizations by moving safe instructions to before the 'try' or 'catch' instruction.
-rw-r--r--lib/compiler/src/beam_reorder.erl21
1 files changed, 21 insertions, 0 deletions
diff --git a/lib/compiler/src/beam_reorder.erl b/lib/compiler/src/beam_reorder.erl
index 3230e33dbd..70adca6b04 100644
--- a/lib/compiler/src/beam_reorder.erl
+++ b/lib/compiler/src/beam_reorder.erl
@@ -64,6 +64,16 @@ reorder(Is) ->
D = beam_utils:index_labels(Is),
reorder_1(Is, D, []).
+reorder_1([{Op,_,_}=TryCatch|[I|Is]=Is0], D, Acc)
+ when Op =:= 'catch'; Op =:= 'try' ->
+ %% Don't allow 'try' or 'catch' instructions to split blocks if
+ %% it can be avoided.
+ case is_safe(I) of
+ false ->
+ reorder_1(Is0, D, [TryCatch|Acc]);
+ true ->
+ reorder_1([TryCatch|Is], D, [I|Acc])
+ end;
reorder_1([{label,L}=I|_], D, Acc) ->
Is = beam_utils:code_at(L, D),
reorder_1(Is, D, [I|Acc]);
@@ -111,3 +121,14 @@ reorder_1([{allocate_zero,N,Live}|Is], D,
reorder_1([I|Is], D, Acc) ->
reorder_1(Is, D, [I|Acc]);
reorder_1([], _, Acc) -> reverse(Acc).
+
+%% is_safe(Instruction) -> true|false
+%% Test whether an instruction is safe (cannot cause an exception).
+
+is_safe({kill,_}) -> true;
+is_safe({move,_,_}) -> true;
+is_safe({put,_}) -> true;
+is_safe({put_list,_,_,_}) -> true;
+is_safe({put_tuple,_,_}) -> true;
+is_safe({test_heap,_,_}) -> true;
+is_safe(_) -> false.