Rodrigo Mesquita pushed to branch wip/romes/step-out-10 at Glasgow Haskell Compiler / GHC
Commits:
-
058ddc61
by Rodrigo Mesquita at 2025-07-02T14:56:10+01:00
-
8837b6ba
by Rodrigo Mesquita at 2025-07-02T15:00:16+01:00
-
9a35db92
by Rodrigo Mesquita at 2025-07-02T15:00:21+01:00
-
71819682
by Rodrigo Mesquita at 2025-07-02T16:48:57+01:00
13 changed files:
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Breakpoints.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/HsToCore/Breakpoints.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/StgToByteCode.hs
- libraries/ghci/GHCi/Debugger.hs
- libraries/ghci/GHCi/Message.hs
- libraries/ghci/GHCi/Run.hs
- rts/Disassembler.c
- rts/Exception.cmm
- rts/Interpreter.c
Changes:
| ... | ... | @@ -841,24 +841,19 @@ assembleI platform i = case i of |
| 841 | 841 | W8 -> emit_ bci_OP_INDEX_ADDR_08 []
|
| 842 | 842 | _ -> unsupported_width
|
| 843 | 843 | |
| 844 | - BRK_FUN (InternalBreakpointId tick_mod tickx info_mod infox) -> do
|
|
| 844 | + BRK_FUN ibi@(InternalBreakpointId info_mod infox) -> do
|
|
| 845 | + p1 <- ptr $ BCOPtrBreakArray info_mod
|
|
| 845 | 846 | let -- cast that checks that round-tripping through Word16 doesn't change the value
|
| 846 | 847 | toW16 x = let r = fromIntegral x :: Word16
|
| 847 | 848 | in if fromIntegral r == x
|
| 848 | 849 | then r
|
| 849 | 850 | else pprPanic "schemeER_wrk: breakpoint tick/info index too large!" (ppr x)
|
| 850 | - p1 <- ptr $ BCOPtrBreakArray tick_mod
|
|
| 851 | 851 | tick_addr <- lit1 $ BCONPtrFS $ moduleNameFS $ moduleName tick_mod
|
| 852 | 852 | info_addr <- lit1 $ BCONPtrFS $ moduleNameFS $ moduleName info_mod
|
| 853 | - tick_unitid_addr <- lit1 $ BCONPtrFS $ unitIdFS $ moduleUnitId $ tick_mod
|
|
| 854 | - info_unitid_addr <- lit1 $ BCONPtrFS $ unitIdFS $ moduleUnitId $ info_mod
|
|
| 855 | - np <- lit1 $ BCONPtrCostCentre (BreakpointId tick_mod tickx)
|
|
| 856 | - emit_ bci_BRK_FUN [ Op p1
|
|
| 857 | - , Op tick_addr, Op info_addr
|
|
| 858 | - , Op tick_unitid_addr, Op info_unitid_addr
|
|
| 859 | - , SmallOp (toW16 tickx), SmallOp (toW16 infox)
|
|
| 860 | - , Op np
|
|
| 861 | - ]
|
|
| 853 | + info_unitid_addr <- lit1 $ BCONPtrFS $ unitIdFS $ moduleUnitId info_mod
|
|
| 854 | + np <- lit1 $ BCONPtrCostCentre ibi
|
|
| 855 | + emit_ bci_BRK_FUN [ Op p1, Op info_addr, Op info_unitid_addr
|
|
| 856 | + , SmallOp infox, Op np ]
|
|
| 862 | 857 | |
| 863 | 858 | BRK_ALTS active -> emit_ bci_BRK_ALTS [SmallOp (if active then 1 else 0)]
|
| 864 | 859 |
| ... | ... | @@ -7,20 +7,19 @@ |
| 7 | 7 | -- 'InternalModBreaks', and is uniquely identified at runtime by an
|
| 8 | 8 | -- 'InternalBreakpointId'.
|
| 9 | 9 | --
|
| 10 | --- See Note [Breakpoint identifiers]
|
|
| 10 | +-- See Note [ModBreaks vs InternalModBreaks] and Note [Breakpoint identifiers]
|
|
| 11 | 11 | module GHC.ByteCode.Breakpoints
|
| 12 | 12 | ( -- * Internal Mod Breaks
|
| 13 | 13 | InternalModBreaks(..), CgBreakInfo(..)
|
| 14 | - , mkInternalModBreaks
|
|
| 14 | + , mkInternalModBreaks, imodBreaks_module
|
|
| 15 | 15 | |
| 16 | 16 | -- ** Internal breakpoint identifier
|
| 17 | 17 | , InternalBreakpointId(..), BreakInfoIndex
|
| 18 | 18 | |
| 19 | 19 | -- * Operations
|
| 20 | - , toBreakpointId
|
|
| 21 | 20 | |
| 22 | 21 | -- ** Internal-level operations
|
| 23 | - , getInternalBreak, addInternalBreak
|
|
| 22 | + , getInternalBreak
|
|
| 24 | 23 | |
| 25 | 24 | -- ** Source-level information operations
|
| 26 | 25 | , getBreakLoc, getBreakVars, getBreakDecls, getBreakCCS
|
| ... | ... | @@ -47,6 +46,31 @@ import GHC.Utils.Panic |
| 47 | 46 | import Data.Array
|
| 48 | 47 | |
| 49 | 48 | {-
|
| 49 | +Note [ModBreaks vs InternalModBreaks]
|
|
| 50 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 51 | +'ModBreaks' and 'BreakpointId's must not to be confused with
|
|
| 52 | +'InternalModBreaks' and 'InternalBreakId's.
|
|
| 53 | + |
|
| 54 | +'ModBreaks' is constructed once during HsToCore from the information attached
|
|
| 55 | +to source-level breakpoint ticks and is never changed afterwards. A 'ModBreaks'
|
|
| 56 | +can be queried using 'BreakpointId's, which uniquely identifies a breakpoint
|
|
| 57 | +within the list of breakpoint information for a given module's 'ModBreaks'.
|
|
| 58 | + |
|
| 59 | +'InternalModBreaks' are constructed during bytecode generation and are indexed
|
|
| 60 | +by a 'InternalBreakpointId'. They contain all the information relevant to a
|
|
| 61 | +breakpoint for code generation that can be accessed during runtime execution
|
|
| 62 | +(such as a 'BreakArray' for triggering breakpoints). 'InternalBreakpointId's
|
|
| 63 | +are used at runtime to trigger and inspect breakpoints -- a 'BRK_FUN'
|
|
| 64 | +instruction receives 'InternalBreakpointId' as an argument.
|
|
| 65 | + |
|
| 66 | +We keep a mapping from 'InternalModBreaks' to a 'BreakpointId', which can then be used
|
|
| 67 | +to get source-level information about a breakpoint via the corresponding 'ModBreaks'.
|
|
| 68 | + |
|
| 69 | +Notably, 'InternalModBreaks' can contain entries for so-called internal
|
|
| 70 | +breakpoints, which do not necessarily have a source-level location attached to
|
|
| 71 | +it (i.e. do not have a matching entry in 'ModBreaks'). We may leverage this to
|
|
| 72 | +introduce breakpoints during code generation for features such as stepping-out.
|
|
| 73 | + |
|
| 50 | 74 | Note [Breakpoint identifiers]
|
| 51 | 75 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 52 | 76 | Before optimization a breakpoint is identified uniquely with a tick module
|
| ... | ... | @@ -64,6 +88,10 @@ So every breakpoint occurrence gets assigned a module-unique *info index* and |
| 64 | 88 | we store it alongside the occurrence module (*info module*) in the
|
| 65 | 89 | 'InternalBreakpointId' datatype. This is the index that we use at runtime to
|
| 66 | 90 | identify a breakpoint.
|
| 91 | + |
|
| 92 | +When the internal breakpoint has a matching tick-level breakpoint we can fetch
|
|
| 93 | +the related tick-level information by first looking up a mapping
|
|
| 94 | +@'InternalBreakpointId' -> 'BreakpointId'@ in @'CgBreakInfo'@.
|
|
| 67 | 95 | -}
|
| 68 | 96 | |
| 69 | 97 | --------------------------------------------------------------------------------
|
| ... | ... | @@ -78,19 +106,11 @@ type BreakInfoIndex = Int |
| 78 | 106 | -- Indexes into the structures in the @'InternalModBreaks'@ produced during ByteCode generation.
|
| 79 | 107 | -- See Note [Breakpoint identifiers]
|
| 80 | 108 | data InternalBreakpointId = InternalBreakpointId
|
| 81 | - { ibi_tick_mod :: !Module -- ^ Breakpoint tick module
|
|
| 82 | - , ibi_tick_index :: !Int -- ^ Breakpoint tick index
|
|
| 83 | - , ibi_info_mod :: !Module -- ^ Breakpoint tick module
|
|
| 109 | + { ibi_info_mod :: !Module -- ^ Breakpoint tick module
|
|
| 84 | 110 | , ibi_info_index :: !BreakInfoIndex -- ^ Breakpoint tick index
|
| 85 | 111 | }
|
| 86 | 112 | deriving (Eq, Ord)
|
| 87 | 113 | |
| 88 | -toBreakpointId :: InternalBreakpointId -> BreakpointId
|
|
| 89 | -toBreakpointId ibi = BreakpointId
|
|
| 90 | - { bi_tick_mod = ibi_tick_mod ibi
|
|
| 91 | - , bi_tick_index = ibi_tick_index ibi
|
|
| 92 | - }
|
|
| 93 | - |
|
| 94 | 114 | --------------------------------------------------------------------------------
|
| 95 | 115 | -- * Internal Mod Breaks
|
| 96 | 116 | --------------------------------------------------------------------------------
|
| ... | ... | @@ -107,18 +127,34 @@ data InternalModBreaks = InternalModBreaks |
| 107 | 127 | -- 'InternalBreakpointId'.
|
| 108 | 128 | |
| 109 | 129 | , imodBreaks_modBreaks :: !ModBreaks
|
| 110 | - -- ^ Store the original ModBreaks for this module, unchanged.
|
|
| 111 | - -- Allows us to query about source-level breakpoint information using
|
|
| 112 | - -- an internal breakpoint id.
|
|
| 130 | + -- ^ Store the ModBreaks for this module
|
|
| 131 | + --
|
|
| 132 | + -- Recall Note [Breakpoint identifiers]: for some module A, an
|
|
| 133 | + -- *occurrence* of a breakpoint in A may have been inlined from some
|
|
| 134 | + -- breakpoint *defined* in module B.
|
|
| 135 | + --
|
|
| 136 | + -- This 'ModBreaks' contains information regarding all the breakpoints
|
|
| 137 | + -- defined in the module this 'InternalModBreaks' corresponds to. It
|
|
| 138 | + -- /does not/ necessarily have information regarding all the breakpoint
|
|
| 139 | + -- occurrences registered in 'imodBreaks_breakInfo'. Some of those
|
|
| 140 | + -- occurrences may refer breakpoints inlined from other modules.
|
|
| 113 | 141 | }
|
| 114 | 142 | |
| 115 | --- | Construct an 'InternalModBreaks'
|
|
| 143 | +-- | Construct an 'InternalModBreaks'.
|
|
| 144 | +--
|
|
| 145 | +-- INVARIANT: The given 'ModBreaks' correspond to the same module as this
|
|
| 146 | +-- 'InternalModBreaks' module (the first argument) and its breakpoint infos
|
|
| 147 | +-- (the @IntMap CgBreakInfo@ argument)
|
|
| 116 | 148 | mkInternalModBreaks :: Module -> IntMap CgBreakInfo -> ModBreaks -> InternalModBreaks
|
| 117 | 149 | mkInternalModBreaks mod im mbs =
|
| 118 | 150 | assertPpr (mod == modBreaks_module mbs)
|
| 119 | 151 | (text "Constructing InternalModBreaks with the ModBreaks of a different module!") $
|
| 120 | 152 | InternalModBreaks im mbs
|
| 121 | 153 | |
| 154 | +-- | Get the module to which these 'InternalModBreaks' correspond
|
|
| 155 | +imodBreaks_module :: InternalModBreaks -> Module
|
|
| 156 | +imodBreaks_module = modBreaks_module . imodBreaks_modBreaks
|
|
| 157 | + |
|
| 122 | 158 | -- | Information about a breakpoint that we know at code-generation time
|
| 123 | 159 | -- In order to be used, this needs to be hydrated relative to the current HscEnv by
|
| 124 | 160 | -- 'hydrateCgBreakInfo'. Everything here can be fully forced and that's critical for
|
| ... | ... | @@ -128,20 +164,22 @@ data CgBreakInfo |
| 128 | 164 | { cgb_tyvars :: ![IfaceTvBndr] -- ^ Type variables in scope at the breakpoint
|
| 129 | 165 | , cgb_vars :: ![Maybe (IfaceIdBndr, Word)]
|
| 130 | 166 | , cgb_resty :: !IfaceType
|
| 167 | + , cgb_tick_id :: !BreakpointId
|
|
| 168 | + -- ^ This field records the original breakpoint tick identifier for this
|
|
| 169 | + -- internal breakpoint info. It is used to convert a breakpoint
|
|
| 170 | + -- *occurrence* index ('InternalBreakpointId') into a *definition* index
|
|
| 171 | + -- ('BreakpointId').
|
|
| 172 | + --
|
|
| 173 | + -- The modules of breakpoint occurrence and breakpoint definition are not
|
|
| 174 | + -- necessarily the same: See Note [Breakpoint identifiers].
|
|
| 131 | 175 | }
|
| 132 | 176 | -- See Note [Syncing breakpoint info] in GHC.Runtime.Eval
|
| 133 | 177 | |
| 134 | 178 | -- | Get an internal breakpoint info by 'InternalBreakpointId'
|
| 135 | 179 | getInternalBreak :: InternalBreakpointId -> InternalModBreaks -> CgBreakInfo
|
| 136 | -getInternalBreak (InternalBreakpointId _ _ info_mod info_ix) imbs =
|
|
| 137 | - assert_modules_match info_mod (modBreaks_module $ imodBreaks_modBreaks imbs) $
|
|
| 138 | - imodBreaks_breakInfo imbs IM.! info_ix
|
|
| 139 | - |
|
| 140 | --- | Add a CgBreakInfo to an 'InternalModBreaks' at 'InternalBreakpointId'
|
|
| 141 | -addInternalBreak :: InternalBreakpointId -> CgBreakInfo -> InternalModBreaks -> InternalModBreaks
|
|
| 142 | -addInternalBreak (InternalBreakpointId _ _ info_mod info_ix) info imbs =
|
|
| 143 | - assert_modules_match info_mod (modBreaks_module $ imodBreaks_modBreaks imbs) $
|
|
| 144 | - imbs{imodBreaks_breakInfo = IM.insert info_ix info (imodBreaks_breakInfo imbs)}
|
|
| 180 | +getInternalBreak (InternalBreakpointId mod ix) imbs =
|
|
| 181 | + assert_modules_match mod (imodBreaks_module imbs) $
|
|
| 182 | + imodBreaks_breakInfo imbs IM.! ix
|
|
| 145 | 183 | |
| 146 | 184 | -- | Assert that the module in the 'InternalBreakpointId' and in
|
| 147 | 185 | -- 'InternalModBreaks' match.
|
| ... | ... | @@ -156,26 +194,47 @@ assert_modules_match ibi_mod imbs_mod = |
| 156 | 194 | --------------------------------------------------------------------------------
|
| 157 | 195 | |
| 158 | 196 | -- | Get the source span for this breakpoint
|
| 159 | -getBreakLoc :: InternalBreakpointId -> InternalModBreaks -> SrcSpan
|
|
| 197 | +getBreakLoc :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO SrcSpan
|
|
| 160 | 198 | getBreakLoc = getBreakXXX modBreaks_locs
|
| 161 | 199 | |
| 162 | 200 | -- | Get the vars for this breakpoint
|
| 163 | -getBreakVars :: InternalBreakpointId -> InternalModBreaks -> [OccName]
|
|
| 201 | +getBreakVars :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO [OccName]
|
|
| 164 | 202 | getBreakVars = getBreakXXX modBreaks_vars
|
| 165 | 203 | |
| 166 | 204 | -- | Get the decls for this breakpoint
|
| 167 | -getBreakDecls :: InternalBreakpointId -> InternalModBreaks -> [String]
|
|
| 205 | +getBreakDecls :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO [String]
|
|
| 168 | 206 | getBreakDecls = getBreakXXX modBreaks_decls
|
| 169 | 207 | |
| 170 | 208 | -- | Get the decls for this breakpoint
|
| 171 | -getBreakCCS :: InternalBreakpointId -> InternalModBreaks -> (String, String)
|
|
| 209 | +getBreakCCS :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO (String, String)
|
|
| 172 | 210 | getBreakCCS = getBreakXXX modBreaks_ccs
|
| 173 | 211 | |
| 174 | 212 | -- | Internal utility to access a ModBreaks field at a particular breakpoint index
|
| 175 | -getBreakXXX :: (ModBreaks -> Array BreakTickIndex a) -> InternalBreakpointId -> InternalModBreaks -> a
|
|
| 176 | -getBreakXXX view (InternalBreakpointId tick_mod tick_id _ _) imbs =
|
|
| 177 | - assert_modules_match tick_mod (modBreaks_module $ imodBreaks_modBreaks imbs) $ do
|
|
| 178 | - view (imodBreaks_modBreaks imbs) ! tick_id
|
|
| 213 | +--
|
|
| 214 | +-- Recall Note [Breakpoint identifiers]: the internal breakpoint module (the
|
|
| 215 | +-- *occurrence* module) doesn't necessarily match the module where the
|
|
| 216 | +-- tick breakpoint was defined with the relevant 'ModBreaks'.
|
|
| 217 | +--
|
|
| 218 | +-- When the tick module is the same as the internal module, we use the stored
|
|
| 219 | +-- 'ModBreaks'. When the tick module is different, we need to look up the
|
|
| 220 | +-- 'ModBreaks' in the HUG for that other module.
|
|
| 221 | +--
|
|
| 222 | +-- To avoid cyclic dependencies, we instead receive a function that looks up
|
|
| 223 | +-- the 'ModBreaks' given a 'Module'
|
|
| 224 | +getBreakXXX :: (ModBreaks -> Array BreakTickIndex a) -> (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO a
|
|
| 225 | +getBreakXXX view lookupModule (InternalBreakpointId ibi_mod ibi_ix) imbs =
|
|
| 226 | + assert_modules_match ibi_mod (imodBreaks_module imbs) $ do
|
|
| 227 | + let cgb = imodBreaks_breakInfo imbs IM.! ibi_ix
|
|
| 228 | + case cgb_tick_id cgb of
|
|
| 229 | + BreakpointId{bi_tick_mod, bi_tick_index}
|
|
| 230 | + | bi_tick_mod == ibi_mod
|
|
| 231 | + -> do
|
|
| 232 | + let these_mbs = imodBreaks_modBreaks imbs
|
|
| 233 | + return $ view these_mbs ! bi_tick_index
|
|
| 234 | + | otherwise
|
|
| 235 | + -> do
|
|
| 236 | + other_mbs <- lookupModule bi_tick_mod
|
|
| 237 | + return $ view other_mbs ! bi_tick_index
|
|
| 179 | 238 | |
| 180 | 239 | --------------------------------------------------------------------------------
|
| 181 | 240 | -- Instances
|
| ... | ... | @@ -190,7 +249,8 @@ seqInternalModBreaks InternalModBreaks{..} = |
| 190 | 249 | seqCgBreakInfo CgBreakInfo{..} =
|
| 191 | 250 | rnf cgb_tyvars `seq`
|
| 192 | 251 | rnf cgb_vars `seq`
|
| 193 | - rnf cgb_resty
|
|
| 252 | + rnf cgb_resty `seq`
|
|
| 253 | + rnf cgb_tick_id
|
|
| 194 | 254 | |
| 195 | 255 | instance Outputable InternalBreakpointId where
|
| 196 | 256 | ppr InternalBreakpointId{..} =
|
| ... | ... | @@ -203,4 +263,5 @@ instance NFData InternalBreakpointId where |
| 203 | 263 | instance Outputable CgBreakInfo where
|
| 204 | 264 | ppr info = text "CgBreakInfo" <+>
|
| 205 | 265 | parens (ppr (cgb_vars info) <+>
|
| 206 | - ppr (cgb_resty info)) |
|
| 266 | + ppr (cgb_resty info) <+>
|
|
| 267 | + ppr (cgb_tick_id info)) |
| ... | ... | @@ -454,9 +454,8 @@ instance Outputable BCInstr where |
| 454 | 454 | ppr ENTER = text "ENTER"
|
| 455 | 455 | ppr (RETURN pk) = text "RETURN " <+> ppr pk
|
| 456 | 456 | ppr (RETURN_TUPLE) = text "RETURN_TUPLE"
|
| 457 | - ppr (BRK_FUN (InternalBreakpointId tick_mod tickx info_mod infox))
|
|
| 457 | + ppr (BRK_FUN (InternalBreakpointId info_mod infox))
|
|
| 458 | 458 | = text "BRK_FUN" <+> text "<breakarray>"
|
| 459 | - <+> ppr tick_mod <+> ppr tickx
|
|
| 460 | 459 | <+> ppr info_mod <+> ppr infox
|
| 461 | 460 | <+> text "<cc>"
|
| 462 | 461 | ppr (BRK_ALTS active) = text "BRK_ALTS" <+> ppr active
|
| ... | ... | @@ -704,12 +704,13 @@ toIfaceLFInfo nm lfi = case lfi of |
| 704 | 704 | |
| 705 | 705 | -- Dehydrating CgBreakInfo
|
| 706 | 706 | |
| 707 | -dehydrateCgBreakInfo :: [TyVar] -> [Maybe (Id, Word)] -> Type -> CgBreakInfo
|
|
| 708 | -dehydrateCgBreakInfo ty_vars idOffSets tick_ty =
|
|
| 707 | +dehydrateCgBreakInfo :: [TyVar] -> [Maybe (Id, Word)] -> Type -> BreakpointId -> CgBreakInfo
|
|
| 708 | +dehydrateCgBreakInfo ty_vars idOffSets tick_ty bid =
|
|
| 709 | 709 | CgBreakInfo
|
| 710 | 710 | { cgb_tyvars = map toIfaceTvBndr ty_vars
|
| 711 | 711 | , cgb_vars = map (fmap (\(i, offset) -> (toIfaceIdBndr i, offset))) idOffSets
|
| 712 | 712 | , cgb_resty = toIfaceType tick_ty
|
| 713 | + , cgb_tick_id = bid
|
|
| 713 | 714 | }
|
| 714 | 715 | |
| 715 | 716 | {- Note [Inlining and hs-boot files]
|
| ... | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | -- 'InternalModBreaks' and 'InternalBreakId's. The latter are constructed
|
| 13 | 13 | -- during bytecode generation and can be found in 'GHC.ByteCode.Breakpoints'.
|
| 14 | 14 | --
|
| 15 | --- See Note [Breakpoint identifiers]
|
|
| 15 | +-- See Note [ModBreaks vs InternalModBreaks] and Note [Breakpoint identifiers]
|
|
| 16 | 16 | module GHC.HsToCore.Breakpoints
|
| 17 | 17 | ( -- * ModBreaks
|
| 18 | 18 | mkModBreaks, ModBreaks(..)
|
| ... | ... | @@ -28,6 +28,7 @@ module GHC.Runtime.Interpreter |
| 28 | 28 | , whereFrom
|
| 29 | 29 | , getModBreaks
|
| 30 | 30 | , readModBreaks
|
| 31 | + , readModBreaksMaybe
|
|
| 31 | 32 | , seqHValue
|
| 32 | 33 | , evalBreakpointToId
|
| 33 | 34 | |
| ... | ... | @@ -411,15 +412,10 @@ evalBreakpointToId :: EvalBreakpoint -> InternalBreakpointId |
| 411 | 412 | evalBreakpointToId eval_break =
|
| 412 | 413 | let
|
| 413 | 414 | mkUnitId u = fsToUnit $ mkFastStringShortByteString u
|
| 414 | - |
|
| 415 | 415 | toModule u n = mkModule (mkUnitId u) (mkModuleName n)
|
| 416 | - tickl = toModule (eb_tick_mod_unit eval_break) (eb_tick_mod eval_break)
|
|
| 417 | - infol = toModule (eb_info_mod_unit eval_break) (eb_info_mod eval_break)
|
|
| 418 | 416 | in
|
| 419 | 417 | InternalBreakpointId
|
| 420 | - { ibi_tick_mod = tickl
|
|
| 421 | - , ibi_tick_index = eb_tick_index eval_break
|
|
| 422 | - , ibi_info_mod = infol
|
|
| 418 | + { ibi_info_mod = toModule (eb_info_mod_unit eval_break) (eb_info_mod eval_break)
|
|
| 423 | 419 | , ibi_info_index = eb_info_index eval_break
|
| 424 | 420 | }
|
| 425 | 421 | |
| ... | ... | @@ -440,17 +436,18 @@ handleSeqHValueStatus interp unit_env eval_status = |
| 440 | 436 | -- Reason: Setting of flags in libraries/ghci/GHCi/Run.hs:evalOptsSeq
|
| 441 | 437 | |
| 442 | 438 | Just break -> do
|
| 443 | - let bi = evalBreakpointToId break
|
|
| 439 | + let ibi = evalBreakpointToId break
|
|
| 440 | + hug = ue_home_unit_graph unit_env
|
|
| 444 | 441 | |
| 445 | 442 | -- Just case: Stopped at a breakpoint, extract SrcSpan information
|
| 446 | 443 | -- from the breakpoint.
|
| 447 | - mb_modbreaks <- getModBreaks . expectJust <$>
|
|
| 448 | - lookupHugByModule (ibi_tick_mod bi) (ue_home_unit_graph unit_env)
|
|
| 444 | + mb_modbreaks <- readModBreaksMaybe hug (ibi_info_mod ibi)
|
|
| 449 | 445 | case mb_modbreaks of
|
| 450 | 446 | -- Nothing case - should not occur! We should have the appropriate
|
| 451 | 447 | -- breakpoint information
|
| 452 | 448 | Nothing -> nothing_case
|
| 453 | - Just modbreaks -> put $ brackets . ppr $ getBreakLoc bi modbreaks
|
|
| 449 | + Just modbreaks -> put . brackets . ppr =<<
|
|
| 450 | + getBreakLoc (fmap imodBreaks_modBreaks . readModBreaks hug) ibi modbreaks
|
|
| 454 | 451 | |
| 455 | 452 | -- resume the seq (:force) processing in the iserv process
|
| 456 | 453 | withForeignRef resume_ctxt_fhv $ \hval -> do
|
| ... | ... | @@ -745,10 +742,13 @@ getModBreaks hmi |
| 745 | 742 | | otherwise
|
| 746 | 743 | = Nothing -- probably object code
|
| 747 | 744 | |
| 748 | --- | Read the 'InternalModBreaks' and 'ModBreaks' of the given home 'Module'
|
|
| 749 | --- from the 'HomeUnitGraph'.
|
|
| 745 | +-- | Read the 'InternalModBreaks' of the given home 'Module' from the 'HomeUnitGraph'.
|
|
| 750 | 746 | readModBreaks :: HomeUnitGraph -> Module -> IO InternalModBreaks
|
| 751 | -readModBreaks hug modl = expectJust . getModBreaks . expectJust <$> HUG.lookupHugByModule modl hug
|
|
| 747 | +readModBreaks hug modl = expectJust <$> readModBreaksMaybe hug modl
|
|
| 748 | + |
|
| 749 | +-- | Read the 'InternalModBreaks' of the given home 'Module' from the 'HomeUnitGraph'.
|
|
| 750 | +readModBreaksMaybe :: HomeUnitGraph -> Module -> IO (Maybe InternalModBreaks)
|
|
| 751 | +readModBreaksMaybe hug modl = getModBreaks . expectJust <$> HUG.lookupHugByModule modl hug
|
|
| 752 | 752 | |
| 753 | 753 | -- -----------------------------------------------------------------------------
|
| 754 | 754 | -- Misc utils
|
| ... | ... | @@ -31,7 +31,6 @@ import GHC.Cmm.Utils |
| 31 | 31 | import GHC.Platform
|
| 32 | 32 | import GHC.Platform.Profile
|
| 33 | 33 | |
| 34 | -import GHC.Runtime.Interpreter
|
|
| 35 | 34 | import GHCi.FFI
|
| 36 | 35 | import GHC.Types.Basic
|
| 37 | 36 | import GHC.Utils.Outputable
|
| ... | ... | @@ -64,6 +63,7 @@ import GHC.StgToCmm.Closure ( NonVoid(..), fromNonVoid, idPrimRepU, |
| 64 | 63 | assertNonVoidIds, assertNonVoidStgArgs )
|
| 65 | 64 | import GHC.StgToCmm.Layout
|
| 66 | 65 | import GHC.Runtime.Heap.Layout hiding (WordOff, ByteOff, wordsToBytes)
|
| 66 | +import GHC.Runtime.Interpreter ( interpreterProfiled )
|
|
| 67 | 67 | import GHC.Data.Bitmap
|
| 68 | 68 | import GHC.Data.FlatBag as FlatBag
|
| 69 | 69 | import GHC.Data.OrdList
|
| ... | ... | @@ -79,7 +79,6 @@ import Control.Monad |
| 79 | 79 | import Data.Char
|
| 80 | 80 | |
| 81 | 81 | import GHC.Unit.Module
|
| 82 | -import qualified GHC.Unit.Home.Graph as HUG
|
|
| 83 | 82 | |
| 84 | 83 | import Data.Coerce (coerce)
|
| 85 | 84 | #if MIN_VERSION_rts(1,0,3)
|
| ... | ... | @@ -394,65 +393,28 @@ schemeR_wrk fvs nm original_body (args, body) |
| 394 | 393 | -- | Introduce break instructions for ticked expressions.
|
| 395 | 394 | -- If no breakpoint information is available, the instruction is omitted.
|
| 396 | 395 | schemeER_wrk :: StackDepth -> BCEnv -> CgStgExpr -> BcM BCInstrList
|
| 397 | -schemeER_wrk d p (StgTick (Breakpoint tick_ty (BreakpointId tick_mod tick_no) fvs) rhs) = do
|
|
| 396 | +schemeER_wrk d p (StgTick (Breakpoint tick_ty tick_id fvs) rhs) = do
|
|
| 398 | 397 | code <- schemeE d 0 p rhs
|
| 399 | - hsc_env <- getHscEnv
|
|
| 400 | - current_mod <- getCurrentModule
|
|
| 401 | 398 | mb_current_mod_breaks <- getCurrentModBreaks
|
| 402 | 399 | case mb_current_mod_breaks of
|
| 403 | 400 | -- if we're not generating ModBreaks for this module for some reason, we
|
| 404 | 401 | -- can't store breakpoint occurrence information.
|
| 405 | 402 | Nothing -> pure code
|
| 406 | - Just current_mod_breaks -> break_info hsc_env tick_mod current_mod mb_current_mod_breaks >>= \case
|
|
| 407 | - Nothing -> pure code
|
|
| 408 | - Just ModBreaks{modBreaks_module = tick_mod} -> do
|
|
| 409 | - platform <- profilePlatform <$> getProfile
|
|
| 410 | - let idOffSets = getVarOffSets platform d p fvs
|
|
| 411 | - ty_vars = tyCoVarsOfTypesWellScoped (tick_ty:map idType fvs)
|
|
| 412 | - toWord :: Maybe (Id, WordOff) -> Maybe (Id, Word)
|
|
| 413 | - toWord = fmap (\(i, wo) -> (i, fromIntegral wo))
|
|
| 414 | - breakInfo = dehydrateCgBreakInfo ty_vars (map toWord idOffSets) tick_ty
|
|
| 403 | + Just current_mod_breaks -> do
|
|
| 404 | + platform <- profilePlatform <$> getProfile
|
|
| 405 | + let idOffSets = getVarOffSets platform d p fvs
|
|
| 406 | + ty_vars = tyCoVarsOfTypesWellScoped (tick_ty:map idType fvs)
|
|
| 407 | + toWord :: Maybe (Id, WordOff) -> Maybe (Id, Word)
|
|
| 408 | + toWord = fmap (\(i, wo) -> (i, fromIntegral wo))
|
|
| 409 | + breakInfo = dehydrateCgBreakInfo ty_vars (map toWord idOffSets) tick_ty tick_id
|
|
| 415 | 410 | |
| 416 | - let info_mod = modBreaks_module current_mod_breaks
|
|
| 417 | - infox <- newBreakInfo breakInfo
|
|
| 411 | + let info_mod = modBreaks_module current_mod_breaks
|
|
| 412 | + infox <- newBreakInfo breakInfo
|
|
| 418 | 413 | |
| 419 | - let breakInstr = BRK_FUN (InternalBreakpointId tick_mod tick_no info_mod infox)
|
|
| 420 | - return $ breakInstr `consOL` code
|
|
| 414 | + let breakInstr = BRK_FUN (InternalBreakpointId info_mod infox)
|
|
| 415 | + return $ breakInstr `consOL` code
|
|
| 421 | 416 | schemeER_wrk d p rhs = schemeE d 0 p rhs
|
| 422 | 417 | |
| 423 | --- | Determine the GHCi-allocated 'BreakArray' and module pointer for the module
|
|
| 424 | --- from which the breakpoint originates.
|
|
| 425 | --- These are stored in 'ModBreaks' as remote pointers in order to allow the BCOs
|
|
| 426 | --- to refer to pointers in GHCi's address space.
|
|
| 427 | --- They are initialized in 'GHC.HsToCore.Breakpoints.mkModBreaks', called by
|
|
| 428 | --- 'GHC.HsToCore.deSugar'.
|
|
| 429 | ---
|
|
| 430 | --- Breakpoints might be disabled because we're in TH, because
|
|
| 431 | --- @-fno-break-points@ was specified, or because a module was reloaded without
|
|
| 432 | --- reinitializing 'ModBreaks'.
|
|
| 433 | ---
|
|
| 434 | --- If the module stored in the breakpoint is the currently processed module, use
|
|
| 435 | --- the 'ModBreaks' from the state.
|
|
| 436 | --- If that is 'Nothing', consider breakpoints to be disabled and skip the
|
|
| 437 | --- instruction.
|
|
| 438 | ---
|
|
| 439 | --- If the breakpoint is inlined from another module, look it up in the HUG (home unit graph).
|
|
| 440 | --- If the module doesn't exist there, or if the 'ModBreaks' value is
|
|
| 441 | --- uninitialized, skip the instruction (i.e. return Nothing).
|
|
| 442 | -break_info ::
|
|
| 443 | - HscEnv ->
|
|
| 444 | - Module ->
|
|
| 445 | - Module ->
|
|
| 446 | - Maybe ModBreaks ->
|
|
| 447 | - BcM (Maybe ModBreaks)
|
|
| 448 | -break_info hsc_env mod current_mod current_mod_breaks
|
|
| 449 | - | mod == current_mod
|
|
| 450 | - = pure current_mod_breaks
|
|
| 451 | - | otherwise
|
|
| 452 | - = liftIO (HUG.lookupHugByModule mod (hsc_HUG hsc_env)) >>= \case
|
|
| 453 | - Just hp -> pure $ imodBreaks_modBreaks <$> getModBreaks hp
|
|
| 454 | - Nothing -> pure Nothing
|
|
| 455 | - |
|
| 456 | 418 | getVarOffSets :: Platform -> StackDepth -> BCEnv -> [Id] -> [Maybe (Id, WordOff)]
|
| 457 | 419 | getVarOffSets platform depth env = map getOffSet
|
| 458 | 420 | where
|
| ... | ... | @@ -65,10 +65,7 @@ foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt |
| 65 | 65 | --------------------------------------------------------------------------------
|
| 66 | 66 | |
| 67 | 67 | type BreakpointCallback
|
| 68 | - = Addr# -- pointer to the breakpoint tick module name
|
|
| 69 | - -> Addr# -- pointer to the breakpoint tick module unit id
|
|
| 70 | - -> Int# -- breakpoint tick index
|
|
| 71 | - -> Addr# -- pointer to the breakpoint info module name
|
|
| 68 | + = Addr# -- pointer to the breakpoint info module name
|
|
| 72 | 69 | -> Addr# -- pointer to the breakpoint info module unit id
|
| 73 | 70 | -> Int# -- breakpoint info index
|
| 74 | 71 | -> Bool -- exception?
|
| ... | ... | @@ -418,10 +418,7 @@ data EvalStatus_ a b |
| 418 | 418 | instance Binary a => Binary (EvalStatus_ a b)
|
| 419 | 419 | |
| 420 | 420 | data EvalBreakpoint = EvalBreakpoint
|
| 421 | - { eb_tick_mod :: String -- ^ Breakpoint tick module
|
|
| 422 | - , eb_tick_mod_unit :: BS.ShortByteString -- ^ Breakpoint tick module unit id
|
|
| 423 | - , eb_tick_index :: Int -- ^ Breakpoint tick index
|
|
| 424 | - , eb_info_mod :: String -- ^ Breakpoint info module
|
|
| 421 | + { eb_info_mod :: String -- ^ Breakpoint info module
|
|
| 425 | 422 | , eb_info_mod_unit :: BS.ShortByteString -- ^ Breakpoint tick module unit id
|
| 426 | 423 | , eb_info_index :: Int -- ^ Breakpoint info index
|
| 427 | 424 | }
|
| ... | ... | @@ -345,7 +345,7 @@ withBreakAction opts breakMVar statusMVar mtid act |
| 345 | 345 | -- as soon as it is hit, or in resetBreakAction below.
|
| 346 | 346 | |
| 347 | 347 | onBreak :: BreakpointCallback
|
| 348 | - onBreak tick_mod# tick_mod_uid# tickx# info_mod# info_mod_uid# infox# is_exception apStack = do
|
|
| 348 | + onBreak info_mod# info_mod_uid# infox# is_exception apStack = do
|
|
| 349 | 349 | tid <- myThreadId
|
| 350 | 350 | let resume = ResumeContext
|
| 351 | 351 | { resumeBreakMVar = breakMVar
|
| ... | ... | @@ -358,11 +358,9 @@ withBreakAction opts breakMVar statusMVar mtid act |
| 358 | 358 | if is_exception
|
| 359 | 359 | then pure Nothing
|
| 360 | 360 | else do
|
| 361 | - tick_mod <- peekCString (Ptr tick_mod#)
|
|
| 362 | - tick_mod_uid <- BS.packCString (Ptr tick_mod_uid#)
|
|
| 363 | 361 | info_mod <- peekCString (Ptr info_mod#)
|
| 364 | 362 | info_mod_uid <- BS.packCString (Ptr info_mod_uid#)
|
| 365 | - pure (Just (EvalBreakpoint tick_mod tick_mod_uid (I# tickx#) info_mod info_mod_uid (I# infox#)))
|
|
| 363 | + pure (Just (EvalBreakpoint info_mod info_mod_uid (I# infox#)))
|
|
| 366 | 364 | putMVar statusMVar $ EvalBreak apStack_r breakpoint resume_r ccs
|
| 367 | 365 | takeMVar breakMVar
|
| 368 | 366 | |
| ... | ... | @@ -409,8 +407,8 @@ noBreakStablePtr :: StablePtr BreakpointCallback |
| 409 | 407 | noBreakStablePtr = unsafePerformIO $ newStablePtr noBreakAction
|
| 410 | 408 | |
| 411 | 409 | noBreakAction :: BreakpointCallback
|
| 412 | -noBreakAction _ _ _ _ _ _ False _ = putStrLn "*** Ignoring breakpoint"
|
|
| 413 | -noBreakAction _ _ _ _ _ _ True _ = return () -- exception: just continue
|
|
| 410 | +noBreakAction _ _ _ False _ = putStrLn "*** Ignoring breakpoint"
|
|
| 411 | +noBreakAction _ _ _ True _ = return () -- exception: just continue
|
|
| 414 | 412 | |
| 415 | 413 | -- Malloc and copy the bytes. We don't have any way to monitor the
|
| 416 | 414 | -- lifetime of this memory, so it just leaks.
|
| ... | ... | @@ -84,16 +84,23 @@ disInstr ( StgBCO *bco, int pc ) |
| 84 | 84 | |
| 85 | 85 | |
| 86 | 86 | switch (instr & 0xff) {
|
| 87 | - case bci_BRK_FUN:
|
|
| 88 | - debugBelch ("BRK_FUN " ); printPtr( ptrs[instrs[pc]] );
|
|
| 89 | - debugBelch (" %d ", instrs[pc+1]); printPtr( ptrs[instrs[pc+2]] );
|
|
| 90 | - CostCentre* cc = (CostCentre*)literals[instrs[pc+5]];
|
|
| 87 | + case bci_BRK_FUN: {
|
|
| 88 | + W_ p1, info_mod, info_unit_id, info_wix, np;
|
|
| 89 | + p1 = BCO_GET_LARGE_ARG;
|
|
| 90 | + info_mod = BCO_GET_LARGE_ARG;
|
|
| 91 | + info_unit_id = BCO_GET_LARGE_ARG;
|
|
| 92 | + info_wix = BCO_NEXT;
|
|
| 93 | + np = BCO_GET_LARGE_ARG;
|
|
| 94 | + debugBelch ("BRK_FUN " ); printPtr( ptrs[p1] );
|
|
| 95 | + debugBelch("%" FMT_Word, literals[info_mod] );
|
|
| 96 | + debugBelch("%" FMT_Word, literals[info_unit_id] );
|
|
| 97 | + debugBelch("%" FMT_Word, info_wix );
|
|
| 98 | + CostCentre* cc = (CostCentre*)literals[np];
|
|
| 91 | 99 | if (cc) {
|
| 92 | 100 | debugBelch(" %s", cc->label);
|
| 93 | 101 | }
|
| 94 | 102 | debugBelch("\n");
|
| 95 | - pc += 6;
|
|
| 96 | - break;
|
|
| 103 | + break; }
|
|
| 97 | 104 | case bci_BRK_ALTS:
|
| 98 | 105 | debugBelch ("BRK_ALTS %d\n", BCO_NEXT);
|
| 99 | 106 | break;
|
| ... | ... | @@ -535,23 +535,17 @@ retry_pop_stack: |
| 535 | 535 | // be per-thread.
|
| 536 | 536 | CInt[rts_stop_on_exception] = 0;
|
| 537 | 537 | ("ptr" ioAction) = ccall deRefStablePtr (W_[rts_breakpoint_io_action] "ptr");
|
| 538 | - Sp = Sp - WDS(17);
|
|
| 539 | - Sp(16) = exception;
|
|
| 540 | - Sp(15) = stg_raise_ret_info;
|
|
| 541 | - Sp(14) = exception;
|
|
| 542 | - Sp(13) = ghczminternal_GHCziInternalziTypes_True_closure; // True <=> an exception
|
|
| 543 | - Sp(12) = stg_ap_ppv_info;
|
|
| 544 | - Sp(11) = 0;
|
|
| 545 | - Sp(10) = stg_ap_n_info;
|
|
| 546 | - Sp(9) = 0;
|
|
| 547 | - Sp(8) = stg_ap_n_info;
|
|
| 548 | - Sp(7) = 0;
|
|
| 549 | - Sp(6) = stg_ap_n_info;
|
|
| 550 | - Sp(5) = 0;
|
|
| 551 | - Sp(4) = stg_ap_n_info;
|
|
| 552 | - Sp(3) = 0;
|
|
| 553 | - Sp(2) = stg_ap_n_info;
|
|
| 554 | - Sp(1) = 0;
|
|
| 538 | + Sp = Sp - WDS(11);
|
|
| 539 | + Sp(10) = exception;
|
|
| 540 | + Sp(9) = stg_raise_ret_info;
|
|
| 541 | + Sp(8) = exception;
|
|
| 542 | + Sp(7) = ghczminternal_GHCziInternalziTypes_True_closure; // True <=> an exception
|
|
| 543 | + Sp(6) = stg_ap_ppv_info;
|
|
| 544 | + Sp(5) = 0;
|
|
| 545 | + Sp(4) = stg_ap_n_info;
|
|
| 546 | + Sp(3) = 0;
|
|
| 547 | + Sp(2) = stg_ap_n_info;
|
|
| 548 | + Sp(1) = 0;
|
|
| 555 | 549 | R1 = ioAction;
|
| 556 | 550 | jump RET_LBL(stg_ap_n) [R1];
|
| 557 | 551 | }
|
| ... | ... | @@ -1454,9 +1454,9 @@ run_BCO: |
| 1454 | 1454 | /* check for a breakpoint on the beginning of a let binding */
|
| 1455 | 1455 | case bci_BRK_FUN:
|
| 1456 | 1456 | {
|
| 1457 | - int arg1_brk_array, arg2_tick_mod, arg3_info_mod, arg4_tick_mod_id, arg5_info_mod_id, arg6_tick_index, arg7_info_index;
|
|
| 1457 | + W_ arg1_brk_array, arg2_info_mod_name, arg3_info_mod_id, arg4_info_index;
|
|
| 1458 | 1458 | #if defined(PROFILING)
|
| 1459 | - int arg8_cc;
|
|
| 1459 | + W_ arg5_cc;
|
|
| 1460 | 1460 | #endif
|
| 1461 | 1461 | StgArrBytes *breakPoints;
|
| 1462 | 1462 | int returning_from_break, stop_next_breakpoint;
|
| ... | ... | @@ -1471,14 +1471,11 @@ run_BCO: |
| 1471 | 1471 | int size_words;
|
| 1472 | 1472 | |
| 1473 | 1473 | arg1_brk_array = BCO_GET_LARGE_ARG;
|
| 1474 | - arg2_tick_mod = BCO_GET_LARGE_ARG;
|
|
| 1475 | - arg3_info_mod = BCO_GET_LARGE_ARG;
|
|
| 1476 | - arg4_tick_mod_id = BCO_GET_LARGE_ARG;
|
|
| 1477 | - arg5_info_mod_id = BCO_GET_LARGE_ARG;
|
|
| 1478 | - arg6_tick_index = BCO_NEXT;
|
|
| 1479 | - arg7_info_index = BCO_NEXT;
|
|
| 1474 | + arg2_info_mod_name = BCO_GET_LARGE_ARG;
|
|
| 1475 | + arg3_info_mod_id = BCO_GET_LARGE_ARG;
|
|
| 1476 | + arg4_info_index = BCO_NEXT;
|
|
| 1480 | 1477 | #if defined(PROFILING)
|
| 1481 | - arg8_cc = BCO_GET_LARGE_ARG;
|
|
| 1478 | + arg5_cc = BCO_GET_LARGE_ARG;
|
|
| 1482 | 1479 | #else
|
| 1483 | 1480 | BCO_GET_LARGE_ARG;
|
| 1484 | 1481 | #endif
|
| ... | ... | @@ -1498,7 +1495,7 @@ run_BCO: |
| 1498 | 1495 | |
| 1499 | 1496 | #if defined(PROFILING)
|
| 1500 | 1497 | cap->r.rCCCS = pushCostCentre(cap->r.rCCCS,
|
| 1501 | - (CostCentre*)BCO_LIT(arg8_cc));
|
|
| 1498 | + (CostCentre*)BCO_LIT(arg5_cc));
|
|
| 1502 | 1499 | #endif
|
| 1503 | 1500 | |
| 1504 | 1501 | // if we are returning from a break then skip this section
|
| ... | ... | @@ -1509,11 +1506,11 @@ run_BCO: |
| 1509 | 1506 | |
| 1510 | 1507 | // stop the current thread if either `stop_next_breakpoint` is
|
| 1511 | 1508 | // true OR if the ignore count for this particular breakpoint is zero
|
| 1512 | - StgInt ignore_count = ((StgInt*)breakPoints->payload)[arg6_tick_index];
|
|
| 1509 | + StgInt ignore_count = ((StgInt*)breakPoints->payload)[arg4_info_index];
|
|
| 1513 | 1510 | if (stop_next_breakpoint == false && ignore_count > 0)
|
| 1514 | 1511 | {
|
| 1515 | 1512 | // decrement and write back ignore count
|
| 1516 | - ((StgInt*)breakPoints->payload)[arg6_tick_index] = --ignore_count;
|
|
| 1513 | + ((StgInt*)breakPoints->payload)[arg4_info_index] = --ignore_count;
|
|
| 1517 | 1514 | }
|
| 1518 | 1515 | else if (stop_next_breakpoint == true || ignore_count == 0)
|
| 1519 | 1516 | {
|
| ... | ... | @@ -1547,10 +1544,7 @@ run_BCO: |
| 1547 | 1544 | // Arrange the stack to call the breakpoint IO action, and
|
| 1548 | 1545 | // continue execution of this BCO when the IO action returns.
|
| 1549 | 1546 | //
|
| 1550 | - // ioAction :: Addr# -- the breakpoint tick module
|
|
| 1551 | - // -> Addr# -- the breakpoint tick module unit id
|
|
| 1552 | - // -> Int# -- the breakpoint tick index
|
|
| 1553 | - // -> Addr# -- the breakpoint info module
|
|
| 1547 | + // ioAction :: Addr# -- the breakpoint info module
|
|
| 1554 | 1548 | // -> Addr# -- the breakpoint info module unit id
|
| 1555 | 1549 | // -> Int# -- the breakpoint info index
|
| 1556 | 1550 | // -> Bool -- exception?
|
| ... | ... | @@ -1560,23 +1554,17 @@ run_BCO: |
| 1560 | 1554 | ioAction = (StgClosure *) deRefStablePtr (
|
| 1561 | 1555 | rts_breakpoint_io_action);
|
| 1562 | 1556 | |
| 1563 | - Sp_subW(19);
|
|
| 1564 | - SpW(18) = (W_)obj;
|
|
| 1565 | - SpW(17) = (W_)&stg_apply_interp_info;
|
|
| 1566 | - SpW(16) = (W_)new_aps;
|
|
| 1567 | - SpW(15) = (W_)False_closure; // True <=> an exception
|
|
| 1568 | - SpW(14) = (W_)&stg_ap_ppv_info;
|
|
| 1569 | - SpW(13) = (W_)arg7_info_index;
|
|
| 1570 | - SpW(12) = (W_)&stg_ap_n_info;
|
|
| 1571 | - SpW(11) = (W_)BCO_LIT(arg5_info_mod_id);
|
|
| 1572 | - SpW(10) = (W_)&stg_ap_n_info;
|
|
| 1573 | - SpW(9) = (W_)BCO_LIT(arg3_info_mod);
|
|
| 1574 | - SpW(8) = (W_)&stg_ap_n_info;
|
|
| 1575 | - SpW(7) = (W_)arg6_tick_index;
|
|
| 1557 | + Sp_subW(13);
|
|
| 1558 | + SpW(12) = (W_)obj;
|
|
| 1559 | + SpW(11) = (W_)&stg_apply_interp_info;
|
|
| 1560 | + SpW(10) = (W_)new_aps;
|
|
| 1561 | + SpW(9) = (W_)False_closure; // True <=> an exception
|
|
| 1562 | + SpW(8) = (W_)&stg_ap_ppv_info;
|
|
| 1563 | + SpW(7) = (W_)arg4_info_index;
|
|
| 1576 | 1564 | SpW(6) = (W_)&stg_ap_n_info;
|
| 1577 | - SpW(5) = (W_)BCO_LIT(arg4_tick_mod_id);
|
|
| 1565 | + SpW(5) = (W_)BCO_LIT(arg3_info_mod_id);
|
|
| 1578 | 1566 | SpW(4) = (W_)&stg_ap_n_info;
|
| 1579 | - SpW(3) = (W_)BCO_LIT(arg2_tick_mod);
|
|
| 1567 | + SpW(3) = (W_)BCO_LIT(arg2_info_mod_name);
|
|
| 1580 | 1568 | SpW(2) = (W_)&stg_ap_n_info;
|
| 1581 | 1569 | SpW(1) = (W_)ioAction;
|
| 1582 | 1570 | SpW(0) = (W_)&stg_enter_info;
|