summaryrefslogtreecommitdiff
path: root/ghc
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 /ghc
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 'ghc')
-rw-r--r--ghc/GHCi/UI.hs52
-rw-r--r--ghc/GHCi/UI/Monad.hs2
2 files changed, 25 insertions, 29 deletions
diff --git a/ghc/GHCi/UI.hs b/ghc/GHCi/UI.hs
index 4fcbe6d7fe..7bd9bbeb77 100644
--- a/ghc/GHCi/UI.hs
+++ b/ghc/GHCi/UI.hs
@@ -39,6 +39,8 @@ import Debugger
-- The GHC interface
import GHCi
+import GHCi.RemoteTypes
+import GHCi.BreakArray
import DynFlags
import ErrUtils
import GhcMonad ( modifySession )
@@ -58,7 +60,6 @@ import PrelNames
import RdrName ( RdrName, getGRE_NameQualifier_maybes, getRdrName )
import SrcLoc
import qualified Lexer
-import ByteCodeTypes (BreakInfo(..))
import StringBuffer
import Outputable hiding ( printForUser, printForUserPartWay, bold )
@@ -2651,7 +2652,7 @@ pprStopped res =
<> text (GHC.resumeDecl res))
<> char ',' <+> ppr (GHC.resumeSpan res)
where
- mb_mod_name = moduleName <$> breakInfo_module <$> GHC.resumeBreakInfo res
+ mb_mod_name = moduleName <$> GHC.breakInfo_module <$> GHC.resumeBreakInfo res
showPackages :: GHCi ()
showPackages = do
@@ -3094,24 +3095,19 @@ findBreakAndSet md lookupTickTree = do
some -> mapM_ (breakAt breakArray) some
where
breakAt breakArray (tick, pan) = do
- success <- liftIO $ setBreakFlag True breakArray tick
- if success
- then do
- (alreadySet, nm) <-
- recordBreak $ BreakLocation
- { breakModule = md
- , breakLoc = RealSrcSpan pan
- , breakTick = tick
- , onBreakCmd = ""
- }
- printForUser $
- text "Breakpoint " <> ppr nm <>
- if alreadySet
- then text " was already set at " <> ppr pan
- else text " activated at " <> ppr pan
- else do
- printForUser $ text "Breakpoint could not be activated at"
- <+> ppr pan
+ setBreakFlag True breakArray tick
+ (alreadySet, nm) <-
+ recordBreak $ BreakLocation
+ { breakModule = md
+ , breakLoc = RealSrcSpan pan
+ , breakTick = tick
+ , onBreakCmd = ""
+ }
+ printForUser $
+ text "Breakpoint " <> ppr nm <>
+ if alreadySet
+ then text " was already set at " <> ppr pan
+ else text " activated at " <> ppr pan
-- When a line number is specified, the current policy for choosing
-- the best breakpoint is this:
@@ -3390,12 +3386,13 @@ deleteBreak identity = do
mapM_ (turnOffBreak.snd) this
setGHCiState $ st { breaks = rest }
-turnOffBreak :: BreakLocation -> GHCi Bool
+turnOffBreak :: BreakLocation -> GHCi ()
turnOffBreak loc = do
(arr, _) <- getModBreak (breakModule loc)
- liftIO $ setBreakFlag False arr (breakTick loc)
+ hsc_env <- GHC.getSession
+ liftIO $ enableBreakpoint hsc_env arr (breakTick loc) False
-getModBreak :: Module -> GHCi (GHC.BreakArray, Array Int SrcSpan)
+getModBreak :: Module -> GHCi (ForeignRef BreakArray, Array Int SrcSpan)
getModBreak m = do
Just mod_info <- GHC.getModuleInfo m
let modBreaks = GHC.modInfoModBreaks mod_info
@@ -3403,11 +3400,10 @@ getModBreak m = do
let ticks = GHC.modBreaks_locs modBreaks
return (arr, ticks)
-setBreakFlag :: Bool -> GHC.BreakArray -> Int -> IO Bool
-setBreakFlag toggle arr i
- | toggle = GHC.setBreakOn arr i
- | otherwise = GHC.setBreakOff arr i
-
+setBreakFlag :: Bool -> ForeignRef BreakArray -> Int -> GHCi ()
+setBreakFlag toggle arr i = do
+ hsc_env <- GHC.getSession
+ liftIO $ enableBreakpoint hsc_env arr i toggle
-- ---------------------------------------------------------------------------
-- User code exception handling
diff --git a/ghc/GHCi/UI/Monad.hs b/ghc/GHCi/UI/Monad.hs
index 2a2372d5f9..87b6d27c5d 100644
--- a/ghc/GHCi/UI/Monad.hs
+++ b/ghc/GHCi/UI/Monad.hs
@@ -118,7 +118,7 @@ data GHCiState = GHCiState
noBuffering :: ForeignHValue
}
-type TickArray = Array Int [(BreakIndex,RealSrcSpan)]
+type TickArray = Array Int [(GHC.BreakIndex,RealSrcSpan)]
-- | A GHCi command
data Command