[GHC] #11047: Provide call stacks in GHCi

GHC ghc-devs at haskell.org
Sun Nov 1 21:43:25 UTC 2015


#11047: Provide call stacks in GHCi
-------------------------------------+-------------------------------------
        Reporter:  simonmar          |                Owner:  simonmar
            Type:  task              |               Status:  new
        Priority:  high              |            Milestone:  8.0.1
       Component:  GHCi              |              Version:  7.11
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #545, #4837       |  Differential Rev(s):  Phab:D1407
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Description changed by simonmar:

Old description:

> I want call stacks to be available in GHCi with no effort on the part of
> the user, or changes to the source code.  The call stack will be
> available both programatically and via GHCi commands:
>
> * `GHC.Stack.currentCallStack` returns the current call stack as
> `[String]`. This can be used from `error` and copied into the exception
> string.
> * `Debug.Trace.traceStack` prints out the stack anywhere.
> * GHCi will have a new command `:where` to print out the stack when
> stopped at a breakpoint
>
> The stack trace will be the accurate (i.e. not exposing details of lazy
> evaluation or tail calls) and detailed (including locations of calls, not
> just the enclosing function definition).
>
> = Implmeentation =
>
> Here's how it's going to work:
>
> * We make GHCi work with profiling (done: Phab:D1407)
> * We make breakpoint ticks behave like SCC annotations, and update the
> interpreter to implement the cost-centre-stack semantics.
>
> = Exmaple =
>
> Here's an example from my prototype:
>
> {{{
> g :: Int -> [Int]
> g n = traceStack "g" [n]
>
> h :: Int -> Bool
> h n = case g n of
>          [] -> True
>          (x:xs) -> False
>
> map :: (a -> b) -> [a] -> [b]
> map f [] = []
> map f (x:xs) = f x : map f xs
>
> k n = map h [n]
> }}}
>
> {{{
> [1 of 1] Compiling Main             ( /home/smarlow/scratch/dbg1.hs,
> interpreted )
> Ok, modules loaded: Main.
> *Main> k 1
> [g
> Stack trace:
>   Main.g (/home/smarlow/scratch/dbg1.hs:13:7-24)
>   Main.g (/home/smarlow/scratch/dbg1.hs:13:1-24)
>   Main.h (/home/smarlow/scratch/dbg1.hs:16:12-14)
>   Main.h (/home/smarlow/scratch/dbg1.hs:(16,7)-(18,24))
>   Main.h (/home/smarlow/scratch/dbg1.hs:(16,1)-(18,24))
>   Main.map (/home/smarlow/scratch/dbg1.hs:22:16-18)
>   Main.map (/home/smarlow/scratch/dbg1.hs:22:16-29)
>   Main.map (/home/smarlow/scratch/dbg1.hs:(21,1)-(22,29))
>   Main.k (/home/smarlow/scratch/dbg1.hs:24:7-15)
>   Main.k (/home/smarlow/scratch/dbg1.hs:24:1-15)
> False]
> *Main>
> }}}
>
> We could trim some of the extra detail from the stack trace so that each
> function appears once; there are several choices here, currently I'm
> collecting and displaying the most detail.
>
> = Deployment =
>
> One disadvantage of this is that it requires GHCi to be built with
> profiling, and all the libraries have to be built with profiling too.
> There are two options for deployment:
>
> 1. We deploy two versions of GHCi (profiled and non-profiled), or
> 2. We expand on what GHCJS did, and make the interpreted code run in a
> separate process, thus separating the GHCi binary itself from the code
> being interpreted.  This would allow the interpreted code to be run with
> the profiled RTS while GHCi itself is unprofiled.

New description:

 I want call stacks to be available in GHCi with no effort on the part of
 the user, or changes to the source code.  The call stack will be available
 both programatically and via GHCi commands:

 * `GHC.Stack.currentCallStack` returns the current call stack as
 `[String]`. This can be used from `error` and copied into the exception
 string.
 * `Debug.Trace.traceStack` prints out the stack anywhere.
 * GHCi will have a new command `:where` to print out the stack when
 stopped at a breakpoint

 The stack trace will be the accurate (i.e. not exposing details of lazy
 evaluation or tail calls) and detailed (including locations of calls, not
 just the enclosing function definition).

 = Implementation =

 Here's how it's going to work:

 * We make GHCi work with profiling (done: Phab:D1407)
 * We make breakpoint ticks behave like SCC annotations, and update the
 interpreter to implement the cost-centre-stack semantics.

 = Example =

 Here's an example from my prototype:

 {{{
 g :: Int -> [Int]
 g n = traceStack "g" [n]

 h :: Int -> Bool
 h n = case g n of
          [] -> True
          (x:xs) -> False

 map :: (a -> b) -> [a] -> [b]
 map f [] = []
 map f (x:xs) = f x : map f xs

 k n = map h [n]
 }}}

 {{{
 [1 of 1] Compiling Main             ( /home/smarlow/scratch/dbg1.hs,
 interpreted )
 Ok, modules loaded: Main.
 *Main> k 1
 [g
 Stack trace:
   Main.g (/home/smarlow/scratch/dbg1.hs:13:7-24)
   Main.g (/home/smarlow/scratch/dbg1.hs:13:1-24)
   Main.h (/home/smarlow/scratch/dbg1.hs:16:12-14)
   Main.h (/home/smarlow/scratch/dbg1.hs:(16,7)-(18,24))
   Main.h (/home/smarlow/scratch/dbg1.hs:(16,1)-(18,24))
   Main.map (/home/smarlow/scratch/dbg1.hs:22:16-18)
   Main.map (/home/smarlow/scratch/dbg1.hs:22:16-29)
   Main.map (/home/smarlow/scratch/dbg1.hs:(21,1)-(22,29))
   Main.k (/home/smarlow/scratch/dbg1.hs:24:7-15)
   Main.k (/home/smarlow/scratch/dbg1.hs:24:1-15)
 False]
 *Main>
 }}}

 We could trim some of the extra detail from the stack trace so that each
 function appears once; there are several choices here, currently I'm
 collecting and displaying the most detail.

 = Deployment =

 One disadvantage of this is that it requires GHCi to be built with
 profiling, and all the libraries have to be built with profiling too.
 There are two options for deployment:

 1. We deploy two versions of GHCi (profiled and non-profiled), or
 2. We expand on what GHCJS did, and make the interpreted code run in a
 separate process, thus separating the GHCi binary itself from the code
 being interpreted.  This would allow the interpreted code to be run with
 the profiled RTS while GHCi itself is unprofiled.

--

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11047#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list