From 44e3810be19f58f0348cd2c38de9bb1b2e9d4c6e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muska=C5=82a?= <michal@muskala.eu>
Date: Sun, 5 Aug 2018 00:15:33 +0200
Subject: Rewrite erlang:get_stacktrace calls to primop when safe

This allows taking advantage of further optimisations, like the
raw_raise instruction for code that can't upgrade (yet) to the
new stacktrace syntax for compatibility reasons.

The rewrite is only done when it is safe - when the get_stacktrace
call is the very first thing the handler does.
---
 lib/compiler/src/sys_core_fold.erl | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 0aa58a46e4..f5f652a954 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -480,9 +480,21 @@ expr(#c_try{anno=A,arg=E0,vars=Vs0,body=B0,evars=Evs0,handler=H0}=Try, _, Sub0)
 	false ->
 	    {Evs1,Sub2} = var_list(Evs0, Sub0),
 	    H1 = body(H0, value, Sub2),
-	    Try#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H1}
+	    H2 = opt_try_handler(H1, lists:last(Evs1)),
+	    Try#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H2}
     end.
 
+%% Attempts to convert old erlang:get_stacktrace/0 calls into the new
+%% three-argument catch, with possibility of further optimisations.
+opt_try_handler(#c_call{anno=A,module=#c_literal{val=erlang},name=#c_literal{val=get_stacktrace},args=[]}, Var) ->
+    #c_primop{anno=A,name=#c_literal{val=build_stacktrace},args=[Var]};
+opt_try_handler(#c_case{clauses=Cs0} = Case, Var) ->
+    Cs = [C#c_clause{body=opt_try_handler(B, Var)} || #c_clause{body=B} = C <- Cs0],
+    Case#c_case{clauses=Cs};
+opt_try_handler(#c_let{arg=Arg} = Let, Var) ->
+    Let#c_let{arg=opt_try_handler(Arg, Var)};
+opt_try_handler(X, _) -> X.
+
 expr_list(Es, Ctxt, Sub) ->
     [expr(E, Ctxt, Sub) || E <- Es].
 
-- 
cgit v1.2.3