summaryrefslogtreecommitdiff
path: root/rts/Interpreter.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2016-01-07 11:36:41 +0000
committerSimon Marlow <marlowsd@gmail.com>2016-01-08 08:49:26 +0000
commit6be09e884730f19da6c24fc565980f515300e53c (patch)
treeb7e0e13c4b4acd138d4da91013562cd5637db865 /rts/Interpreter.c
parentc78fedde7055490ca6f6210ada797190f3c35d87 (diff)
downloadhaskell-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/Interpreter.c')
-rw-r--r--rts/Interpreter.c43
1 files changed, 27 insertions, 16 deletions
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