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 /compiler/main/BreakArray.hs | |
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 'compiler/main/BreakArray.hs')
-rw-r--r-- | compiler/main/BreakArray.hs | 132 |
1 files changed, 0 insertions, 132 deletions
diff --git a/compiler/main/BreakArray.hs b/compiler/main/BreakArray.hs deleted file mode 100644 index 447490266c..0000000000 --- a/compiler/main/BreakArray.hs +++ /dev/null @@ -1,132 +0,0 @@ -{-# LANGUAGE CPP, MagicHash, UnboxedTuples #-} - -------------------------------------------------------------------------------- --- --- (c) The University of Glasgow 2007 --- --- | Break Arrays --- --- An array of bytes, indexed by a breakpoint number (breakpointId in Tickish) --- There is one of these arrays per module. --- --- Each byte is --- 1 if the corresponding breakpoint is enabled --- 0 otherwise --- -------------------------------------------------------------------------------- - -module BreakArray - ( - BreakArray -#ifdef GHCI - (BA) -- constructor is exported only for ByteCodeGen -#endif - , newBreakArray -#ifdef GHCI - , getBreak - , setBreakOn - , setBreakOff - , showBreakArray -#endif - ) where - -#ifdef GHCI -import Control.Monad -import Data.Word -import GHC.Word - -import GHC.Exts -import GHC.IO ( IO(..) ) -import System.IO.Unsafe ( unsafeDupablePerformIO ) - -data BreakArray = BA (MutableByteArray# RealWorld) - -breakOff, breakOn :: Word8 -breakOn = 1 -breakOff = 0 - -showBreakArray :: BreakArray -> IO () -showBreakArray array = do - forM_ [0 .. (size array - 1)] $ \i -> do - val <- readBreakArray array i - putStr $ ' ' : show val - putStr "\n" - -setBreakOn :: BreakArray -> Int -> IO Bool -setBreakOn array index - | safeIndex array index = do - writeBreakArray array index breakOn - return True - | otherwise = return False - -setBreakOff :: BreakArray -> Int -> IO Bool -setBreakOff array index - | safeIndex array index = do - writeBreakArray array index breakOff - return True - | otherwise = return False - -getBreak :: BreakArray -> Int -> IO (Maybe Word8) -getBreak array index - | safeIndex array index = do - val <- readBreakArray array index - return $ Just val - | otherwise = return Nothing - -safeIndex :: BreakArray -> Int -> Bool -safeIndex array index = index < size array && index >= 0 - -size :: BreakArray -> Int -size (BA array) = size - where - -- We want to keep this operation pure. The mutable byte array - -- is never resized so this is safe. - size = unsafeDupablePerformIO $ sizeofMutableByteArray array - - sizeofMutableByteArray :: MutableByteArray# RealWorld -> IO Int - sizeofMutableByteArray arr = - IO $ \s -> case getSizeofMutableByteArray# arr s of - (# s', n# #) -> (# s', I# n# #) - -allocBA :: Int -> IO BreakArray -allocBA (I# sz) = IO $ \s1 -> - case newByteArray# sz s1 of { (# s2, array #) -> (# s2, BA array #) } - --- create a new break array and initialise elements to zero -newBreakArray :: Int -> IO BreakArray -newBreakArray entries@(I# sz) = do - BA array <- allocBA entries - case breakOff of - W8# off -> do - let loop n | isTrue# (n ==# sz) = return () - | otherwise = do writeBA# array n off; loop (n +# 1#) - loop 0# - return $ BA array - -writeBA# :: MutableByteArray# RealWorld -> Int# -> Word# -> IO () -writeBA# array i word = IO $ \s -> - case writeWord8Array# array i word s of { s -> (# s, () #) } - -writeBreakArray :: BreakArray -> Int -> Word8 -> IO () -writeBreakArray (BA array) (I# i) (W8# word) = writeBA# array i word - -readBA# :: MutableByteArray# RealWorld -> Int# -> IO Word8 -readBA# array i = IO $ \s -> - case readWord8Array# array i s of { (# s, c #) -> (# s, W8# c #) } - -readBreakArray :: BreakArray -> Int -> IO Word8 -readBreakArray (BA array) (I# i) = readBA# array i - -#else /* !GHCI */ - --- stub implementation to make main/, etc., code happier. --- IOArray and IOUArray are increasingly non-portable, --- still don't have quite the same interface, and (for GHCI) --- presumably have a different representation. -data BreakArray = Unspecified - -newBreakArray :: Int -> IO BreakArray -newBreakArray _ = return Unspecified - -#endif /* GHCI */ - |