diff options
author | Björn Gustavsson <[email protected]> | 2017-10-13 10:40:30 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2017-10-13 10:40:30 +0200 |
commit | 094e0a91fc1046462c4dd5accd48b8e2eb7a4c9c (patch) | |
tree | dc305b713f0ba3f3c615b1b39c4b345db6649831 /lib/compiler | |
parent | 805c5b9b4627eacc2fb13d234c553ae476a2c3dd (diff) | |
parent | 119713b4d9ad6649aa5f1d0bf492e2f35a0ced01 (diff) | |
download | otp-094e0a91fc1046462c4dd5accd48b8e2eb7a4c9c.tar.gz otp-094e0a91fc1046462c4dd5accd48b8e2eb7a4c9c.tar.bz2 otp-094e0a91fc1046462c4dd5accd48b8e2eb7a4c9c.zip |
Merge pull request #1596 from bjorng/bjorn/enhance-try-catch
(Slightly) optimize catch and try/catch
OTP-14683
Diffstat (limited to 'lib/compiler')
-rw-r--r-- | lib/compiler/src/beam_receive.erl | 2 | ||||
-rw-r--r-- | lib/compiler/src/beam_utils.erl | 10 | ||||
-rw-r--r-- | lib/compiler/src/sys_core_fold.erl | 9 |
3 files changed, 19 insertions, 2 deletions
diff --git a/lib/compiler/src/beam_receive.erl b/lib/compiler/src/beam_receive.erl index 1403e1e05e..468460eedf 100644 --- a/lib/compiler/src/beam_receive.erl +++ b/lib/compiler/src/beam_receive.erl @@ -207,6 +207,8 @@ opt_update_regs({label,Lbl}, R, L) -> %% A catch label for a previously seen catch instruction is OK. {R,L} end; +opt_update_regs({'try',_,{f,Lbl}}, R, L) -> + {R,gb_sets:add(Lbl, L)}; opt_update_regs({try_end,_}, R, L) -> {R,L}; opt_update_regs({line,_}, R, L) -> diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl index a4c65397df..00f396c246 100644 --- a/lib/compiler/src/beam_utils.erl +++ b/lib/compiler/src/beam_utils.erl @@ -825,8 +825,14 @@ live_opt([{select,_,Src,Fail,List}=I|Is], Regs0, D, Acc) -> Regs1 = x_live([Src], Regs0), Regs = live_join_labels([Fail|List], D, Regs1), live_opt(Is, Regs, D, [I|Acc]); -live_opt([{try_case,_}=I|Is], _, D, Acc) -> - live_opt(Is, live_call(1), D, [I|Acc]); +live_opt([{try_case,Y}=I|Is], Regs0, D, Acc) -> + Regs = live_call(1), + case Regs0 of + 0 -> + live_opt(Is, Regs, D, [{try_end,Y}|Acc]); + _ -> + live_opt(Is, live_call(1), D, [I|Acc]) + end; live_opt([{loop_rec,_Fail,_Dst}=I|Is], _, D, Acc) -> live_opt(Is, 0, D, [I|Acc]); live_opt([timeout=I|Is], _, D, Acc) -> diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index f3f315935a..df880ff784 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -418,6 +418,15 @@ expr(#c_call{module=M0,name=N0}=Call0, Ctxt, Sub) -> expr(#c_primop{args=As0}=Prim, _, Sub) -> As1 = expr_list(As0, value, Sub), Prim#c_primop{args=As1}; +expr(#c_catch{anno=Anno,body=B}, effect, Sub) -> + %% When the return value of the 'catch' is ignored, we can replace it + %% with a try/catch to avoid building a stack trace when an exception + %% occurs. + Var = #c_var{name='catch_value'}, + Evs = [#c_var{name='Class'},#c_var{name='Reason'},#c_var{name='Stk'}], + Try = #c_try{anno=Anno,arg=B,vars=[Var],body=Var, + evars=Evs,handler=void()}, + expr(Try, effect, Sub); expr(#c_catch{body=B0}=Catch, _, Sub) -> %% We can remove catch if the value is simple B1 = body(B0, value, Sub), |