diff options
author | Simon Marlow <marlowsd@gmail.com> | 2016-01-07 11:36:41 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2016-01-08 08:49:26 +0000 |
commit | 6be09e884730f19da6c24fc565980f515300e53c (patch) | |
tree | b7e0e13c4b4acd138d4da91013562cd5637db865 /rts | |
parent | c78fedde7055490ca6f6210ada797190f3c35d87 (diff) | |
download | haskell-6be09e884730f19da6c24fc565980f515300e53c.tar.gz |
Enable stack traces with ghci -fexternal-interpreter -prof
Summary:
The main goal here is enable stack traces in GHCi. After this change,
if you start GHCi like this:
ghci -fexternal-interpreter -prof
(which requires packages to be built for profiling, but not GHC
itself) then the interpreter manages cost-centre stacks during
execution and can produce a stack trace on request. Call locations
are available for all interpreted code, and any compiled code that was
built with the `-fprof-auto` familiy of flags.
There are a couple of ways to get a stack trace:
* `error`/`undefined` automatically get one attached
* `Debug.Trace.traceStack` can be used anywhere, and prints the current
stack
Because the interpreter is running in a separate process, only the
interpreted code is running in profiled mode and the compiler itself
isn't slowed down by profiling.
The GHCi debugger still doesn't work with -fexternal-interpreter,
although this patch gets it a step closer. Most of the functionality
of breakpoints is implemented, but the runtime value introspection is
still not supported.
Along the way I also did some refactoring and added type arguments to
the various remote pointer types in `GHCi.RemotePtr`, so there's
better type safety and documentation in the bridge code between GHC
and ghc-iserv.
Test Plan: validate
Reviewers: bgamari, ezyang, austin, hvr, goldfire, erikd
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D1747
GHC Trac Issues: #11047, #11100
Diffstat (limited to 'rts')
-rw-r--r-- | rts/Exception.cmm | 17 | ||||
-rw-r--r-- | rts/Interpreter.c | 43 |
2 files changed, 37 insertions, 23 deletions
diff --git a/rts/Exception.cmm b/rts/Exception.cmm index 8d19c143ee..a89bd19eb3 100644 --- a/rts/Exception.cmm +++ b/rts/Exception.cmm @@ -524,14 +524,17 @@ retry_pop_stack: // be per-thread. CInt[rts_stop_on_exception] = 0; ("ptr" ioAction) = ccall deRefStablePtr (W_[rts_breakpoint_io_action] "ptr"); - Sp = Sp - WDS(6); - Sp(5) = exception; - Sp(4) = stg_raise_ret_info; - Sp(3) = exception; // the AP_STACK - Sp(2) = ghczmprim_GHCziTypes_True_closure; // dummy breakpoint info - Sp(1) = ghczmprim_GHCziTypes_True_closure; // True <=> a breakpoint + Sp = Sp - WDS(9); + Sp(8) = exception; + Sp(7) = stg_raise_ret_info; + Sp(6) = exception; + Sp(5) = ghczmprim_GHCziTypes_True_closure; // True <=> a breakpoint + Sp(4) = stg_ap_ppv_info; + Sp(3) = 0; + Sp(2) = stg_ap_n_info; + Sp(1) = 0; R1 = ioAction; - jump RET_LBL(stg_ap_pppv) [R1]; + jump RET_LBL(stg_ap_n) [R1]; } } diff --git a/rts/Interpreter.c b/rts/Interpreter.c index 37fef9c65e..21d7527541 100644 --- a/rts/Interpreter.c +++ b/rts/Interpreter.c @@ -928,7 +928,7 @@ run_BCO: /* check for a breakpoint on the beginning of a let binding */ case bci_BRK_FUN: { - int arg1_brk_array, arg2_array_index, arg3_freeVars; + int arg1_brk_array, arg2_array_index, arg3_module_uniq; #ifdef PROFILING int arg4_cc; #endif @@ -946,7 +946,7 @@ run_BCO: arg1_brk_array = BCO_GET_LARGE_ARG; arg2_array_index = BCO_NEXT; - arg3_freeVars = BCO_GET_LARGE_ARG; + arg3_module_uniq = BCO_GET_LARGE_ARG; #ifdef PROFILING arg4_cc = BCO_GET_LARGE_ARG; #else @@ -1002,20 +1002,31 @@ run_BCO: new_aps->payload[i] = (StgClosure *)Sp[i-2]; } - // prepare the stack so that we can call the - // rts_breakpoint_io_action and ensure that the stack is - // in a reasonable state for the GC and so that - // execution of this BCO can continue when we resume - ioAction = (StgClosure *) deRefStablePtr (rts_breakpoint_io_action); - Sp -= 8; - Sp[7] = (W_)obj; - Sp[6] = (W_)&stg_apply_interp_info; - Sp[5] = (W_)new_aps; // the AP_STACK - Sp[4] = (W_)BCO_PTR(arg3_freeVars); // the info about local vars of the breakpoint - Sp[3] = (W_)False_closure; // True <=> a breakpoint - Sp[2] = (W_)&stg_ap_pppv_info; - Sp[1] = (W_)ioAction; // apply the IO action to its two arguments above - Sp[0] = (W_)&stg_enter_info; // get ready to run the IO action + // Arrange the stack to call the breakpoint IO action, and + // continue execution of this BCO when the IO action returns. + // + // ioAction :: Bool -- exception? + // -> HValue -- the AP_STACK, or exception + // -> Int -- the breakpoint index (arg2) + // -> Int -- the module uniq (arg3) + // -> IO () + // + ioAction = (StgClosure *) deRefStablePtr ( + rts_breakpoint_io_action); + + Sp -= 11; + Sp[10] = (W_)obj; + Sp[9] = (W_)&stg_apply_interp_info; + Sp[8] = (W_)new_aps; + Sp[7] = (W_)False_closure; // True <=> a breakpoint + Sp[6] = (W_)&stg_ap_ppv_info; + Sp[5] = (W_)BCO_LIT(arg3_module_uniq); + Sp[4] = (W_)&stg_ap_n_info; + Sp[3] = (W_)arg2_array_index; + Sp[2] = (W_)&stg_ap_n_info; + Sp[1] = (W_)ioAction; + Sp[0] = (W_)&stg_enter_info; + // set the flag in the TSO to say that we are now // stopping at a breakpoint so that when we resume // we don't stop on the same breakpoint that we |