aboutsummaryrefslogtreecommitdiffstats
path: root/lib/debugger/src/dbg_ieval.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <bjorn@erlang.org>2011-03-31 07:31:14 +0200
committerBjörn Gustavsson <bjorn@erlang.org>2011-08-16 08:58:47 +0200
commite0fe23461cc94a80e02a9542ab2182f62badd5de (patch)
tree2ec0499d0b23c64d88880eb1c8e8c8830dfce8ea /lib/debugger/src/dbg_ieval.erl
parent3ccc4730e54f0f9e86bf96360b7600ab8c9e1d47 (diff)
downloadotp-e0fe23461cc94a80e02a9542ab2182f62badd5de.tar.gz
otp-e0fe23461cc94a80e02a9542ab2182f62badd5de.tar.bz2
otp-e0fe23461cc94a80e02a9542ab2182f62badd5de.zip
Don't build stacktrace until erlang:get_stacktrace() is called
Currently, dbg_istk:exception_stacktrace/2 does not do a very good job imitating BEAM's stacktrace. The reason is that it need to be relatively fast since a simulated stacktrace is constructed not only when an exception oocurs, but also before every call to non-interpreted code. To prepare for a future more thorough (and slower) stacktrace construction, refactor the building of the stacktrace so that it only is done when erlang:get_stacktrace/0 is called.
Diffstat (limited to 'lib/debugger/src/dbg_ieval.erl')
-rw-r--r--lib/debugger/src/dbg_ieval.erl38
1 files changed, 29 insertions, 9 deletions
diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl
index 445eba3346..fe7f9af1a9 100644
--- a/lib/debugger/src/dbg_ieval.erl
+++ b/lib/debugger/src/dbg_ieval.erl
@@ -168,7 +168,7 @@ check_exit_msg(_Msg, _Bs, _Ieval) ->
%% and then raise the exception.
%%--------------------------------------------------------------------
exception(Class, Reason, Bs, Ieval) ->
- exception(Class, Reason, dbg_istk:exception_stacktrace(complete, Ieval),
+ exception(Class, Reason, dbg_istk:delayed_stacktrace(Ieval),
Bs, Ieval).
exception(Class, Reason, Stacktrace, Bs, #ieval{module=M, line=Line}) ->
@@ -226,8 +226,7 @@ meta(Int, Debugged, M, F, As) ->
debugged_cmd(Cmd, Bs, Ieval) ->
Debugged = get(self),
- Stacktrace = dbg_istk:exception_stacktrace(no_current, Ieval),
- Debugged ! {sys, self(), {command,Cmd,Stacktrace}},
+ Debugged ! {sys, self(), {command,Cmd}},
meta_loop(Debugged, Bs, Ieval).
meta_loop(Debugged, Bs, #ieval{level=Le} = Ieval) ->
@@ -240,12 +239,17 @@ meta_loop(Debugged, Bs, #ieval{level=Le} = Ieval) ->
{value, Val, Bs};
{sys, Debugged, {value,Val,Bs2}} ->
{value, Val, Bs2};
- {sys, Debugged, {exception,{Class,Reason,Stacktrace}}} ->
+ {sys, Debugged, {exception,{Class,Reason,Stk}}} ->
case get(exit_info) of
- %% Error occured outside interpreted code
+ %% Error occurred outside of interpreted code.
undefined ->
- exception(Class,Reason,Stacktrace,Bs,Ieval);
+ MakeStk0 = dbg_istk:delayed_stacktrace(),
+ MakeStk = fun(Depth0) ->
+ Depth = max(0, Depth0 - length(Stk)),
+ Stk ++ MakeStk0(Depth)
+ end,
+ exception(Class, Reason, MakeStk, Bs, Ieval);
%% Error must have occured within a re-entry to
%% interpreted code, simply raise the exception
@@ -370,7 +374,7 @@ format_args1([]) ->
%% Mimic catch behaviour
catch_value(error, Reason) ->
- {'EXIT',{Reason,get(stacktrace)}};
+ {'EXIT',{Reason,get_stacktrace()}};
catch_value(exit, Reason) ->
{'EXIT',Reason};
catch_value(throw, Reason) ->
@@ -395,7 +399,7 @@ eval_mfa(Debugged, M, F, As, #ieval{level=Le}=Ieval0) ->
exit:{Int, Reason} ->
exit(Reason);
Class:Reason ->
- {exception, {Class, Reason, get(stacktrace)}}
+ {exception, {Class, Reason, get_stacktrace()}}
end.
eval_function(Mod, Name, As, Bs, Called, Ieval0) ->
@@ -782,7 +786,7 @@ expr({dbg,Line,self,[]}, Bs, #ieval{level=Le}) ->
{value,Self,Bs};
expr({dbg,Line,get_stacktrace,[]}, Bs, #ieval{level=Le}) ->
trace(bif, {Le,Line,erlang,get_stacktrace,[]}),
- Stacktrace = get(stacktrace),
+ Stacktrace = get_stacktrace(),
trace(return, {Le,Stacktrace}),
{value,Stacktrace,Bs};
expr({dbg,Line,throw,As0}, Bs0, #ieval{level=Le}=Ieval0) ->
@@ -1501,3 +1505,19 @@ add_binding(N,Val,[B1|Bs]) ->
[B1|add_binding(N,Val,Bs)];
add_binding(N,Val,[]) ->
[{N,Val}].
+
+%% get_stacktrace() -> Stacktrace
+%% Return the latest stacktrace for the process.
+get_stacktrace() ->
+ case get(stacktrace) of
+ MakeStk when is_function(MakeStk, 1) ->
+ %% The stacktrace has not been constructed before.
+ %% Construct it and remember the result.
+ Depth = erlang:system_flag(backtrace_depth, 8),
+ erlang:system_flag(backtrace_depth, Depth),
+ Stk = MakeStk(Depth),
+ put(stacktrace, Stk),
+ Stk;
+ Stk when is_list(Stk) ->
+ Stk
+ end.