Rodrigo Mesquita pushed to branch wip/romes/top-level-bcos-tag at Glasgow Haskell Compiler / GHC
Commits:
-
ac7b34fd
by Rodrigo Mesquita at 2025-05-23T15:54:43+01:00
-
186b2582
by Rodrigo Mesquita at 2025-05-23T15:55:01+01:00
25 changed files:
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/ByteCode/Linker.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/StgToByteCode.hs
- libraries/base/src/GHC/Exts.hs
- libraries/ghc-heap/GHC/Exts/Heap/Closures.hs
- libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc
- libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc
- libraries/ghc-heap/tests/parse_tso_flags.hs
- libraries/ghc-internal/src/GHC/Internal/Exts.hs
- libraries/ghci/GHCi/CreateBCO.hs
- + libraries/ghci/GHCi/Debugger.hs
- libraries/ghci/GHCi/ResolvedBCO.hs
- libraries/ghci/GHCi/Run.hs
- libraries/ghci/ghci.cabal.in
- rts/Interpreter.c
- rts/Interpreter.h
- rts/PrimOps.cmm
- rts/Printer.c
- rts/RtsSymbols.c
- rts/StgMiscClosures.cmm
- rts/include/rts/Constants.h
- rts/include/stg/MiscClosures.h
Changes:
| ... | ... | @@ -3872,12 +3872,13 @@ primop MkApUpd0_Op "mkApUpd0#" GenPrimOp |
| 3872 | 3872 | with
|
| 3873 | 3873 | out_of_line = True
|
| 3874 | 3874 | |
| 3875 | -primop NewBCOOp "newBCO#" GenPrimOp
|
|
| 3876 | - ByteArray# -> ByteArray# -> Array# a -> Int# -> ByteArray# -> State# s -> (# State# s, BCO #)
|
|
| 3877 | - { @'newBCO#' instrs lits ptrs arity bitmap@ creates a new bytecode object. The
|
|
| 3875 | +primop NewBCOOp "newBCO2#" GenPrimOp
|
|
| 3876 | + Int8# -> ByteArray# -> ByteArray# -> Array# a -> Int# -> ByteArray# -> State# s -> (# State# s, BCO #)
|
|
| 3877 | + { @'newBCO2#' is_case_cont instrs lits ptrs arity bitmap@ creates a new bytecode object. The
|
|
| 3878 | 3878 | resulting object encodes a function of the given arity with the instructions
|
| 3879 | 3879 | encoded in @instrs@, and a static reference table usage bitmap given by
|
| 3880 | - @bitmap@. }
|
|
| 3880 | + @bitmap@. The @is_case_cont@ boolean indicates whether the BCO is a case
|
|
| 3881 | + continuation (see Note [Case continuation BCOs]) }
|
|
| 3881 | 3882 | with
|
| 3882 | 3883 | effect = ReadWriteEffect
|
| 3883 | 3884 | out_of_line = True
|
| ... | ... | @@ -85,7 +85,7 @@ bcoFreeNames :: UnlinkedBCO -> UniqDSet Name |
| 85 | 85 | bcoFreeNames bco
|
| 86 | 86 | = bco_refs bco `uniqDSetMinusUniqSet` mkNameSet [unlinkedBCOName bco]
|
| 87 | 87 | where
|
| 88 | - bco_refs (UnlinkedBCO _ _ _ _ nonptrs ptrs)
|
|
| 88 | + bco_refs (UnlinkedBCO _ _ _ _ nonptrs ptrs _)
|
|
| 89 | 89 | = unionManyUniqDSets (
|
| 90 | 90 | mkUniqDSet [ n | BCOPtrName n <- elemsFlatBag ptrs ] :
|
| 91 | 91 | mkUniqDSet [ n | BCONPtrItbl n <- elemsFlatBag nonptrs ] :
|
| ... | ... | @@ -236,7 +236,8 @@ assembleBCO platform |
| 236 | 236 | , protoBCOInstrs = instrs
|
| 237 | 237 | , protoBCOBitmap = bitmap
|
| 238 | 238 | , protoBCOBitmapSize = bsize
|
| 239 | - , protoBCOArity = arity }) = do
|
|
| 239 | + , protoBCOArity = arity
|
|
| 240 | + , protoBCOIsCaseCont = isCC }) = do
|
|
| 240 | 241 | -- pass 1: collect up the offsets of the local labels.
|
| 241 | 242 | let initial_offset = 0
|
| 242 | 243 | |
| ... | ... | @@ -266,7 +267,7 @@ assembleBCO platform |
| 266 | 267 | |
| 267 | 268 | let !insns_arr = mkBCOByteArray $ final_isn_array
|
| 268 | 269 | !bitmap_arr = mkBCOByteArray $ mkBitmapArray bsize bitmap
|
| 269 | - ul_bco = UnlinkedBCO nm arity insns_arr bitmap_arr (fromSmallArray final_lit_array) (fromSmallArray final_ptr_array)
|
|
| 270 | + ul_bco = UnlinkedBCO nm arity insns_arr bitmap_arr (fromSmallArray final_lit_array) (fromSmallArray final_ptr_array) isCC
|
|
| 270 | 271 | |
| 271 | 272 | -- 8 Aug 01: Finalisers aren't safe when attached to non-primitive
|
| 272 | 273 | -- objects, since they might get run too early. Disable this until
|
| ... | ... | @@ -53,7 +53,8 @@ data ProtoBCO a |
| 53 | 53 | -- what the BCO came from, for debugging only
|
| 54 | 54 | protoBCOExpr :: Either [CgStgAlt] CgStgRhs,
|
| 55 | 55 | -- malloc'd pointers
|
| 56 | - protoBCOFFIs :: [FFIInfo]
|
|
| 56 | + protoBCOFFIs :: [FFIInfo],
|
|
| 57 | + protoBCOIsCaseCont :: !Bool -- See Note [Case continuation BCOs]
|
|
| 57 | 58 | }
|
| 58 | 59 | |
| 59 | 60 | -- | A local block label (e.g. identifying a case alternative).
|
| ... | ... | @@ -59,7 +59,7 @@ linkBCO |
| 59 | 59 | -> UnlinkedBCO
|
| 60 | 60 | -> IO ResolvedBCO
|
| 61 | 61 | linkBCO interp pkgs_loaded le bco_ix
|
| 62 | - (UnlinkedBCO _ arity insns bitmap lits0 ptrs0) = do
|
|
| 62 | + (UnlinkedBCO _ arity insns bitmap lits0 ptrs0 isCC) = do
|
|
| 63 | 63 | -- fromIntegral Word -> Word64 should be a no op if Word is Word64
|
| 64 | 64 | -- otherwise it will result in a cast to longlong on 32bit systems.
|
| 65 | 65 | (lits :: [Word]) <- mapM (fmap fromIntegral . lookupLiteral interp pkgs_loaded le) (elemsFlatBag lits0)
|
| ... | ... | @@ -69,7 +69,7 @@ linkBCO interp pkgs_loaded le bco_ix |
| 69 | 69 | insns
|
| 70 | 70 | bitmap
|
| 71 | 71 | (mkBCOByteArray lits')
|
| 72 | - (addListToSS emptySS ptrs))
|
|
| 72 | + (addListToSS emptySS ptrs) isCC)
|
|
| 73 | 73 | |
| 74 | 74 | lookupLiteral :: Interp -> PkgsLoaded -> LinkerEnv -> BCONPtr -> IO Word
|
| 75 | 75 | lookupLiteral interp pkgs_loaded le ptr = case ptr of
|
| ... | ... | @@ -167,14 +167,108 @@ newtype ItblPtr = ItblPtr (RemotePtr Heap.StgInfoTable) |
| 167 | 167 | newtype AddrPtr = AddrPtr (RemotePtr ())
|
| 168 | 168 | deriving (NFData)
|
| 169 | 169 | |
| 170 | +{-
|
|
| 171 | +--------------------------------------------------------------------------------
|
|
| 172 | +-- * Byte Code Objects (BCOs)
|
|
| 173 | +--------------------------------------------------------------------------------
|
|
| 174 | + |
|
| 175 | +Note [Case continuation BCOs]
|
|
| 176 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 177 | + |
|
| 178 | +A stack with a BCO stack frame at the top looks like:
|
|
| 179 | + |
|
| 180 | + (an StgBCO)
|
|
| 181 | + | ... | +---> +---------[1]--+
|
|
| 182 | + +------------------+ | | info_tbl_ptr | ------+
|
|
| 183 | + | OTHER FRAME | | +--------------+ |
|
|
| 184 | + +------------------+ | | StgArrBytes* | <--- the byte code
|
|
| 185 | + | ... | | +--------------+ |
|
|
| 186 | + +------------------+ | | ... | |
|
|
| 187 | + | fvs1 | | |
|
|
| 188 | + +------------------+ | |
|
|
| 189 | + | ... | | (StgInfoTable) |
|
|
| 190 | + +------------------+ | +----------+ <---+
|
|
| 191 | + | args1 | | | ... |
|
|
| 192 | + +------------------+ | +----------+
|
|
| 193 | + | some StgBCO* | -----+ | type=BCO |
|
|
| 194 | + +------------------+ +----------+
|
|
| 195 | + Sp | stg_apply_interp | -----+ | ... |
|
|
| 196 | + +------------------+ |
|
|
| 197 | + |
|
|
| 198 | + | (StgInfoTable)
|
|
| 199 | + +----> +--------------+
|
|
| 200 | + | ... |
|
|
| 201 | + +--------------+
|
|
| 202 | + | type=RET_BCO |
|
|
| 203 | + +--------------+
|
|
| 204 | + | ... |
|
|
| 205 | + |
|
| 206 | + |
|
| 207 | +The byte code for a BCO heap object makes use of arguments and free variables
|
|
| 208 | +which can typically be found within the BCO stack frame. In the code, these
|
|
| 209 | +variables are referenced via a statically known stack offset (tracked using
|
|
| 210 | +`BCEnv` in `StgToByteCode`).
|
|
| 211 | + |
|
| 212 | +However, in /case continuation/ BCOs, the code may additionally refer to free
|
|
| 213 | +variables that are outside of that BCO's stack frame -- some free variables of a
|
|
| 214 | +case continuation BCO may only be found in the stack frame of a parent BCO.
|
|
| 215 | + |
|
| 216 | +Yet, references to these out-of-frame variables are also done in terms of stack
|
|
| 217 | +offsets. Thus, they rely on the position of /another frame/ to be fixed. (See
|
|
| 218 | +Note [PUSH_L underflow] for more information about references to previous
|
|
| 219 | +frames and nested BCOs)
|
|
| 220 | + |
|
| 221 | +This makes case continuation BCOs special: unlike normal BCOs, case cont BCO
|
|
| 222 | +frames cannot be moved on the stack independently from their parent BCOs.
|
|
| 223 | + |
|
| 224 | +In order to be able to distinguish them at runtime, the code generator will use
|
|
| 225 | +distinct info table pointers for their closures, even though they will have the
|
|
| 226 | +same structure on the heap (StgBCO). Specifically:
|
|
| 227 | + |
|
| 228 | + - Normal BCOs are always headed by the `stg_BCO_info` pointer.
|
|
| 229 | + - Case continuation BCOs are always headed by the `stg_CASE_CONT_BCO_info` pointer.
|
|
| 230 | + |
|
| 231 | +A primary reason why we need to distinguish these two cases is to know where we
|
|
| 232 | +can insert a debugger step-out frame (`stg_stop_after_ret_frame`). In
|
|
| 233 | +particular, because case cont BCOs may refer to the parent frame, we must not
|
|
| 234 | +insert step-out frames between a case cont BCO and its parent.
|
|
| 235 | + |
|
| 236 | +As an example, consider the following, where `y` is free in the case alternatives:
|
|
| 237 | + |
|
| 238 | + f x y = case x of
|
|
| 239 | + True -> y - 1
|
|
| 240 | + False -> y + 1 :: Int
|
|
| 241 | + |
|
| 242 | +While interpreting f, the args x and y will be on the stack as part of f's frame.
|
|
| 243 | +In its body, a case continuation BCO is pushed (PUSH_ALTS) and then `x` is
|
|
| 244 | +entered to be evaluated. Upon entering `x`, the stack would look something like:
|
|
| 245 | + |
|
| 246 | + <f arg 2>
|
|
| 247 | + <f arg 1>
|
|
| 248 | + ...
|
|
| 249 | + <Case continuation BCO Frame>
|
|
| 250 | + |
|
| 251 | +We cannot insert a step out frame in between:
|
|
| 252 | + |
|
| 253 | + |
|
| 254 | + <f arg 2>
|
|
| 255 | + <f arg 1>
|
|
| 256 | + ...
|
|
| 257 | + <inserted step-out frame> <--- BAD! Breaks stack offsets in the case cont.
|
|
| 258 | + <Case continuation BCO Frame>
|
|
| 259 | + |
|
| 260 | +Instead, we must traverse until the parent BCO and insert the step-out frame before it instead.
|
|
| 261 | +-}
|
|
| 262 | + |
|
| 170 | 263 | data UnlinkedBCO
|
| 171 | 264 | = UnlinkedBCO {
|
| 172 | 265 | unlinkedBCOName :: !Name,
|
| 173 | 266 | unlinkedBCOArity :: {-# UNPACK #-} !Int,
|
| 174 | - unlinkedBCOInstrs :: !(BCOByteArray Word16), -- insns
|
|
| 175 | - unlinkedBCOBitmap :: !(BCOByteArray Word), -- bitmap
|
|
| 267 | + unlinkedBCOInstrs :: !(BCOByteArray Word16), -- insns
|
|
| 268 | + unlinkedBCOBitmap :: !(BCOByteArray Word), -- bitmap
|
|
| 176 | 269 | unlinkedBCOLits :: !(FlatBag BCONPtr), -- non-ptrs
|
| 177 | - unlinkedBCOPtrs :: !(FlatBag BCOPtr) -- ptrs
|
|
| 270 | + unlinkedBCOPtrs :: !(FlatBag BCOPtr), -- ptrs
|
|
| 271 | + unlinkedBCOIsCaseCont :: !Bool -- See Note [Case continuation BCOs]
|
|
| 178 | 272 | }
|
| 179 | 273 | |
| 180 | 274 | instance NFData UnlinkedBCO where
|
| ... | ... | @@ -227,10 +321,11 @@ seqCgBreakInfo CgBreakInfo{..} = |
| 227 | 321 | rnf cgb_resty
|
| 228 | 322 | |
| 229 | 323 | instance Outputable UnlinkedBCO where
|
| 230 | - ppr (UnlinkedBCO nm _arity _insns _bitmap lits ptrs)
|
|
| 324 | + ppr (UnlinkedBCO nm _arity _insns _bitmap lits ptrs pi)
|
|
| 231 | 325 | = sep [text "BCO", ppr nm, text "with",
|
| 232 | 326 | ppr (sizeFlatBag lits), text "lits",
|
| 233 | - ppr (sizeFlatBag ptrs), text "ptrs" ]
|
|
| 327 | + ppr (sizeFlatBag ptrs), text "ptrs",
|
|
| 328 | + ppr pi, text "is_pos_indep"]
|
|
| 234 | 329 | |
| 235 | 330 | instance Outputable CgBreakInfo where
|
| 236 | 331 | ppr info = text "CgBreakInfo" <+>
|
| ... | ... | @@ -253,7 +253,11 @@ mkProtoBCO |
| 253 | 253 | -> Int -- ^ arity
|
| 254 | 254 | -> WordOff -- ^ bitmap size
|
| 255 | 255 | -> [StgWord] -- ^ bitmap
|
| 256 | - -> Bool -- ^ True <=> is a return point, rather than a function
|
|
| 256 | + -> Bool -- ^ True <=> it's a case continuation, rather than a function
|
|
| 257 | + -- Used for
|
|
| 258 | + -- (A) Stack check collision and
|
|
| 259 | + -- (B) Mark the BCO wrt whether it contains non-local stack
|
|
| 260 | + -- references. See Note [Case continuation BCOs].
|
|
| 257 | 261 | -> [FFIInfo]
|
| 258 | 262 | -> ProtoBCO Name
|
| 259 | 263 | mkProtoBCO platform _add_bco_name nm instrs_ordlist origin arity bitmap_size bitmap is_ret ffis
|
| ... | ... | @@ -264,7 +268,8 @@ mkProtoBCO platform _add_bco_name nm instrs_ordlist origin arity bitmap_size bit |
| 264 | 268 | protoBCOBitmapSize = fromIntegral bitmap_size,
|
| 265 | 269 | protoBCOArity = arity,
|
| 266 | 270 | protoBCOExpr = origin,
|
| 267 | - protoBCOFFIs = ffis
|
|
| 271 | + protoBCOFFIs = ffis,
|
|
| 272 | + protoBCOIsCaseCont = is_ret
|
|
| 268 | 273 | }
|
| 269 | 274 | where
|
| 270 | 275 | #if MIN_VERSION_rts(1,0,3)
|
| ... | ... | @@ -353,6 +358,9 @@ schemeTopBind (id, rhs) |
| 353 | 358 | -- Park the resulting BCO in the monad. Also requires the
|
| 354 | 359 | -- name of the variable to which this value was bound,
|
| 355 | 360 | -- so as to give the resulting BCO a name.
|
| 361 | +--
|
|
| 362 | +-- The resulting ProtoBCO expects the free variables and the function arguments
|
|
| 363 | +-- to be in the stack directly before it.
|
|
| 356 | 364 | schemeR :: [Id] -- Free vars of the RHS, ordered as they
|
| 357 | 365 | -- will appear in the thunk. Empty for
|
| 358 | 366 | -- top-level things, which have no free vars.
|
| ... | ... | @@ -391,6 +399,8 @@ schemeR_wrk fvs nm original_body (args, body) |
| 391 | 399 | -- them unlike constructor fields.
|
| 392 | 400 | szsb_args = map (wordsToBytes platform . idSizeW platform) all_args
|
| 393 | 401 | sum_szsb_args = sum szsb_args
|
| 402 | + -- Make a stack offset for each argument or free var -- they should
|
|
| 403 | + -- appear contiguous in the stack, in order.
|
|
| 394 | 404 | p_init = Map.fromList (zip all_args (mkStackOffsets 0 szsb_args))
|
| 395 | 405 | |
| 396 | 406 | -- make the arg bitmap
|
| ... | ... | @@ -1401,7 +1411,7 @@ Note [unboxed tuple bytecodes and tuple_BCO] |
| 1401 | 1411 | tupleBCO :: Platform -> NativeCallInfo -> [(PrimRep, ByteOff)] -> [FFIInfo] -> ProtoBCO Name
|
| 1402 | 1412 | tupleBCO platform args_info args =
|
| 1403 | 1413 | mkProtoBCO platform Nothing invented_name body_code (Left [])
|
| 1404 | - 0{-no arity-} bitmap_size bitmap False{-is alts-}
|
|
| 1414 | + 0{-no arity-} bitmap_size bitmap False{-not alts-}
|
|
| 1405 | 1415 | where
|
| 1406 | 1416 | {-
|
| 1407 | 1417 | The tuple BCO is never referred to by name, so we can get away
|
| ... | ... | @@ -1422,7 +1432,7 @@ tupleBCO platform args_info args = |
| 1422 | 1432 | primCallBCO :: Platform -> NativeCallInfo -> [(PrimRep, ByteOff)] -> [FFIInfo] -> ProtoBCO Name
|
| 1423 | 1433 | primCallBCO platform args_info args =
|
| 1424 | 1434 | mkProtoBCO platform Nothing invented_name body_code (Left [])
|
| 1425 | - 0{-no arity-} bitmap_size bitmap False{-is alts-}
|
|
| 1435 | + 0{-no arity-} bitmap_size bitmap False{-not alts-}
|
|
| 1426 | 1436 | where
|
| 1427 | 1437 | {-
|
| 1428 | 1438 | The primcall BCO is never referred to by name, so we can get away
|
| ... | ... | @@ -26,12 +26,12 @@ module GHC.Exts |
| 26 | 26 | -- ** Legacy interface for arrays of arrays
|
| 27 | 27 | module GHC.Internal.ArrayArray,
|
| 28 | 28 | -- * Primitive operations
|
| 29 | - {-# DEPRECATED ["The BCO, mkApUpd0#, and newBCO# re-exports from GHC.Exts have been deprecated and will be removed in 9.14", "These symbols should be imported from ghc-internal instead if needed."] #-}
|
|
| 29 | + {-# DEPRECATED ["The BCO, mkApUpd0#, and newBCO# re-exports from GHC.Exts have been deprecated and will be removed in 10.14", "These symbols should be imported from ghc-internal instead if needed."] #-}
|
|
| 30 | 30 | Prim.BCO,
|
| 31 | 31 | {-# DEPRECATED ["The BCO, mkApUpd0#, and newBCO# re-exports from GHC.Exts have been deprecated and will be removed in 9.14", "These symbols should be imported from ghc-internal instead if needed."] #-}
|
| 32 | 32 | Prim.mkApUpd0#,
|
| 33 | 33 | {-# DEPRECATED ["The BCO, mkApUpd0#, and newBCO# re-exports from GHC.Exts have been deprecated and will be removed in 9.14", "These symbols should be imported from ghc-internal instead if needed."] #-}
|
| 34 | - Prim.newBCO#,
|
|
| 34 | + IExts.newBCO#,
|
|
| 35 | 35 | module GHC.Prim,
|
| 36 | 36 | module GHC.Prim.Ext,
|
| 37 | 37 | -- ** Running 'RealWorld' state thread
|
| ... | ... | @@ -119,7 +119,7 @@ module GHC.Exts |
| 119 | 119 | maxTupleSize
|
| 120 | 120 | ) where
|
| 121 | 121 | |
| 122 | -import GHC.Internal.Exts
|
|
| 122 | +import GHC.Internal.Exts hiding ( newBCO# )
|
|
| 123 | 123 | import GHC.Internal.ArrayArray
|
| 124 | 124 | import GHC.Prim hiding
|
| 125 | 125 | ( coerce
|
| ... | ... | @@ -132,7 +132,7 @@ import GHC.Prim hiding |
| 132 | 132 | , isByteArrayWeaklyPinned#, isMutableByteArrayWeaklyPinned#
|
| 133 | 133 | |
| 134 | 134 | -- deprecated
|
| 135 | - , BCO, mkApUpd0#, newBCO#
|
|
| 135 | + , BCO, mkApUpd0#
|
|
| 136 | 136 | |
| 137 | 137 | -- Don't re-export vector FMA instructions
|
| 138 | 138 | , fmaddFloatX4#
|
| ... | ... | @@ -256,8 +256,10 @@ import GHC.Prim hiding |
| 256 | 256 | , minWord8X32#
|
| 257 | 257 | , minWord8X64#
|
| 258 | 258 | )
|
| 259 | +import qualified GHC.Internal.Exts as IExts
|
|
| 260 | + ( newBCO# )
|
|
| 259 | 261 | import qualified GHC.Prim as Prim
|
| 260 | - ( BCO, mkApUpd0#, newBCO# )
|
|
| 262 | + ( BCO, mkApUpd0# )
|
|
| 261 | 263 | |
| 262 | 264 | import GHC.Prim.Ext
|
| 263 | 265 |
| ... | ... | @@ -624,6 +624,7 @@ data TsoFlags |
| 624 | 624 | | TsoMarked
|
| 625 | 625 | | TsoSqueezed
|
| 626 | 626 | | TsoAllocLimit
|
| 627 | + | TsoStopNextBreakpoint
|
|
| 627 | 628 | | TsoFlagsUnknownValue Word32 -- ^ Please report this as a bug
|
| 628 | 629 | deriving (Eq, Show, Generic, Ord)
|
| 629 | 630 |
| ... | ... | @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset |
| 87 | 87 | | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w)
|
| 88 | 88 | | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w)
|
| 89 | 89 | | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w)
|
| 90 | +#if __GLASGOW_HASKELL__ >= 913
|
|
| 91 | + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w)
|
|
| 92 | +#endif
|
|
| 90 | 93 | parseTsoFlags 0 = []
|
| 91 | 94 | parseTsoFlags w = [TsoFlagsUnknownValue w]
|
| 92 | 95 |
| ... | ... | @@ -87,6 +87,9 @@ parseTsoFlags w | isSet (#const TSO_LOCKED) w = TsoLocked : parseTsoFlags (unset |
| 87 | 87 | | isSet (#const TSO_MARKED) w = TsoMarked : parseTsoFlags (unset (#const TSO_MARKED) w)
|
| 88 | 88 | | isSet (#const TSO_SQUEEZED) w = TsoSqueezed : parseTsoFlags (unset (#const TSO_SQUEEZED) w)
|
| 89 | 89 | | isSet (#const TSO_ALLOC_LIMIT) w = TsoAllocLimit : parseTsoFlags (unset (#const TSO_ALLOC_LIMIT) w)
|
| 90 | +#if __GLASGOW_HASKELL__ >= 913
|
|
| 91 | + | isSet (#const TSO_STOP_NEXT_BREAKPOINT) w = TsoStopNextBreakpoint : parseTsoFlags (unset (#const TSO_STOP_NEXT_BREAKPOINT) w)
|
|
| 92 | +#endif
|
|
| 90 | 93 | parseTsoFlags 0 = []
|
| 91 | 94 | parseTsoFlags w = [TsoFlagsUnknownValue w]
|
| 92 | 95 |
| ... | ... | @@ -13,5 +13,6 @@ main = do |
| 13 | 13 | assertEqual (parseTsoFlags 64) [TsoMarked]
|
| 14 | 14 | assertEqual (parseTsoFlags 128) [TsoSqueezed]
|
| 15 | 15 | assertEqual (parseTsoFlags 256) [TsoAllocLimit]
|
| 16 | + assertEqual (parseTsoFlags 512) [TsoStopNextBreakpoint]
|
|
| 16 | 17 | |
| 17 | 18 | assertEqual (parseTsoFlags 6) [TsoLocked, TsoBlockx] |
| ... | ... | @@ -163,6 +163,9 @@ module GHC.Internal.Exts |
| 163 | 163 | |
| 164 | 164 | -- * The maximum tuple size
|
| 165 | 165 | maxTupleSize,
|
| 166 | + |
|
| 167 | + -- * Interpreter
|
|
| 168 | + newBCO#
|
|
| 166 | 169 | ) where
|
| 167 | 170 | |
| 168 | 171 | import GHC.Internal.Prim hiding ( coerce, dataToTagSmall#, dataToTagLarge#, whereFrom# )
|
| ... | ... | @@ -469,3 +472,18 @@ resizeSmallMutableArray# arr0 szNew a s0 = |
| 469 | 472 | -- accessible\" by word.
|
| 470 | 473 | considerAccessible :: Bool
|
| 471 | 474 | considerAccessible = True
|
| 475 | + |
|
| 476 | +--------------------------------------------------------------------------------
|
|
| 477 | +-- Interpreter
|
|
| 478 | + |
|
| 479 | +{-|
|
|
| 480 | +@'newBCO#' instrs lits ptrs arity bitmap@ creates a new bytecode object. The
|
|
| 481 | +resulting object encodes a function of the given arity with the instructions
|
|
| 482 | +encoded in @instrs@, and a static reference table usage bitmap given by
|
|
| 483 | +@bitmap@.
|
|
| 484 | + |
|
| 485 | +Note: Case continuation BCOs, with non-local stack references, must be
|
|
| 486 | +constructed using @'newBCO2#' 1@ instead. See Note [Case continuation BCOs].
|
|
| 487 | +-}
|
|
| 488 | +newBCO# :: ByteArray# -> ByteArray# -> Array# a -> Int# -> ByteArray# -> State# s -> (# State# s, BCO #)
|
|
| 489 | +newBCO# b1 b2 a1 i1 b3 s = newBCO2# (intToInt8# 0#) b1 b2 a1 i1 b3 s |
| ... | ... | @@ -87,11 +87,11 @@ linkBCO' arr ResolvedBCO{..} = do |
| 87 | 87 | literals_barr = barr (getBCOByteArray resolvedBCOLits)
|
| 88 | 88 | |
| 89 | 89 | PtrsArr marr <- mkPtrsArray arr n_ptrs ptrs
|
| 90 | + let is_case_cont | resolvedBCOIsCaseCont = intToInt8# 1#
|
|
| 91 | + | otherwise = intToInt8# 0#
|
|
| 90 | 92 | IO $ \s ->
|
| 91 | 93 | case unsafeFreezeArray# marr s of { (# s, arr #) ->
|
| 92 | - case newBCO insns_barr literals_barr arr arity# bitmap_barr of { IO io ->
|
|
| 93 | - io s
|
|
| 94 | - }}
|
|
| 94 | + newBCO2# is_case_cont insns_barr literals_barr arr arity# bitmap_barr s }
|
|
| 95 | 95 | |
| 96 | 96 | |
| 97 | 97 | -- we recursively link any sub-BCOs while making the ptrs array
|
| 1 | +{-# LANGUAGE MagicHash #-}
|
|
| 2 | +{-# LANGUAGE UnliftedFFITypes #-}
|
|
| 3 | +module GHCi.Debugger
|
|
| 4 | + (
|
|
| 5 | + -- * Single step mode
|
|
| 6 | + rts_enableStopNextBreakpoint
|
|
| 7 | + , rts_enableStopNextBreakpointAll
|
|
| 8 | + , rts_disableStopNextBreakpoint
|
|
| 9 | + , rts_disableStopNextBreakpointAll
|
|
| 10 | + |
|
| 11 | + -- * Stop on exception
|
|
| 12 | + , exceptionFlag
|
|
| 13 | + |
|
| 14 | + -- * Breakpoint Callback
|
|
| 15 | + , BreakpointCallback
|
|
| 16 | + , breakPointIOAction
|
|
| 17 | + ) where
|
|
| 18 | + |
|
| 19 | +import Prelude -- See note [Why do we import Prelude here?]
|
|
| 20 | + |
|
| 21 | +import GHC.Base (ThreadId#, Addr#, Int#)
|
|
| 22 | +import Foreign.C (CInt)
|
|
| 23 | +import Foreign (StablePtr, Ptr)
|
|
| 24 | +import GHCi.RemoteTypes (HValue)
|
|
| 25 | + |
|
| 26 | +--------------------------------------------------------------------------------
|
|
| 27 | +-- Single step mode
|
|
| 28 | + |
|
| 29 | +-- | Enables the single step mode for a specific thread, thus stopping only on
|
|
| 30 | +-- breakpoints in that thread.
|
|
| 31 | +foreign import ccall unsafe "rts_enableStopNextBreakpoint"
|
|
| 32 | + rts_enableStopNextBreakpoint :: ThreadId# -> IO ()
|
|
| 33 | + |
|
| 34 | +-- | Disables per-thread single-step mode. Note: if global single-step is
|
|
| 35 | +-- enabled we stop at all breakpoints regardless of the per-thread flag.
|
|
| 36 | +foreign import ccall unsafe "rts_disableStopNextBreakpoint"
|
|
| 37 | + rts_disableStopNextBreakpoint :: ThreadId# -> IO ()
|
|
| 38 | + |
|
| 39 | +-- | Enables the single step mode for all threads, thus stopping at any
|
|
| 40 | +-- existing breakpoint.
|
|
| 41 | +foreign import ccall unsafe "rts_enableStopNextBreakpointAll"
|
|
| 42 | + rts_enableStopNextBreakpointAll :: IO ()
|
|
| 43 | + |
|
| 44 | +-- | Disables the single step mode for all threads
|
|
| 45 | +foreign import ccall unsafe "rts_disableStopNextBreakpointAll"
|
|
| 46 | + rts_disableStopNextBreakpointAll :: IO ()
|
|
| 47 | + |
|
| 48 | +--------------------------------------------------------------------------------
|
|
| 49 | + |
|
| 50 | +foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt
|
|
| 51 | + |
|
| 52 | +--------------------------------------------------------------------------------
|
|
| 53 | + |
|
| 54 | +type BreakpointCallback
|
|
| 55 | + = Addr# -- pointer to the breakpoint tick module name
|
|
| 56 | + -> Addr# -- pointer to the breakpoint tick module unit id
|
|
| 57 | + -> Int# -- breakpoint tick index
|
|
| 58 | + -> Addr# -- pointer to the breakpoint info module name
|
|
| 59 | + -> Addr# -- pointer to the breakpoint info module unit id
|
|
| 60 | + -> Int# -- breakpoint info index
|
|
| 61 | + -> Bool -- exception?
|
|
| 62 | + -> HValue -- the AP_STACK, or exception
|
|
| 63 | + -> IO ()
|
|
| 64 | + |
|
| 65 | +foreign import ccall "&rts_breakpoint_io_action"
|
|
| 66 | + breakPointIOAction :: Ptr (StablePtr BreakpointCallback)
|
|
| 67 | + |
| ... | ... | @@ -45,7 +45,8 @@ data ResolvedBCO |
| 45 | 45 | resolvedBCOBitmap :: BCOByteArray Word, -- ^ bitmap
|
| 46 | 46 | resolvedBCOLits :: BCOByteArray Word,
|
| 47 | 47 | -- ^ non-ptrs - subword sized entries still take up a full (host) word
|
| 48 | - resolvedBCOPtrs :: (SizedSeq ResolvedBCOPtr) -- ^ ptrs
|
|
| 48 | + resolvedBCOPtrs :: (SizedSeq ResolvedBCOPtr), -- ^ ptrs
|
|
| 49 | + resolvedBCOIsCaseCont :: !Bool -- ^ See Note [Case continuation BCOs]
|
|
| 49 | 50 | }
|
| 50 | 51 | deriving (Generic, Show)
|
| 51 | 52 | |
| ... | ... | @@ -86,7 +87,8 @@ instance Binary ResolvedBCO where |
| 86 | 87 | put resolvedBCOBitmap
|
| 87 | 88 | put resolvedBCOLits
|
| 88 | 89 | put resolvedBCOPtrs
|
| 89 | - get = ResolvedBCO <$> get <*> get <*> get <*> get <*> get <*> get
|
|
| 90 | + put resolvedBCOIsCaseCont
|
|
| 91 | + get = ResolvedBCO <$> get <*> get <*> get <*> get <*> get <*> get <*> get
|
|
| 90 | 92 | |
| 91 | 93 | -- See Note [BCOByteArray serialization]
|
| 92 | 94 | instance (Binary a, Storable a, IArray UArray a) => Binary (BCOByteArray a) where
|
| 1 | 1 | {-# LANGUAGE GADTs, RecordWildCards, MagicHash, ScopedTypeVariables, CPP,
|
| 2 | - UnboxedTuples, LambdaCase #-}
|
|
| 2 | + UnboxedTuples, LambdaCase, UnliftedFFITypes #-}
|
|
| 3 | 3 | {-# OPTIONS_GHC -fno-warn-name-shadowing #-}
|
| 4 | 4 | |
| 5 | 5 | -- |
|
| ... | ... | @@ -20,6 +20,7 @@ import GHCi.InfoTable |
| 20 | 20 | #endif
|
| 21 | 21 | |
| 22 | 22 | import qualified GHC.InfoProv as InfoProv
|
| 23 | +import GHCi.Debugger
|
|
| 23 | 24 | import GHCi.FFI
|
| 24 | 25 | import GHCi.Message
|
| 25 | 26 | import GHCi.ObjLink
|
| ... | ... | @@ -332,7 +333,7 @@ withBreakAction opts breakMVar statusMVar act |
| 332 | 333 | stablePtr <- newStablePtr onBreak
|
| 333 | 334 | poke breakPointIOAction stablePtr
|
| 334 | 335 | when (breakOnException opts) $ poke exceptionFlag 1
|
| 335 | - when (singleStep opts) $ setStepFlag
|
|
| 336 | + when (singleStep opts) rts_enableStopNextBreakpointAll
|
|
| 336 | 337 | return stablePtr
|
| 337 | 338 | -- Breaking on exceptions is not enabled by default, since it
|
| 338 | 339 | -- might be a bit surprising. The exception flag is turned off
|
| ... | ... | @@ -363,7 +364,7 @@ withBreakAction opts breakMVar statusMVar act |
| 363 | 364 | resetBreakAction stablePtr = do
|
| 364 | 365 | poke breakPointIOAction noBreakStablePtr
|
| 365 | 366 | poke exceptionFlag 0
|
| 366 | - resetStepFlag
|
|
| 367 | + rts_disableStopNextBreakpointAll
|
|
| 367 | 368 | freeStablePtr stablePtr
|
| 368 | 369 | |
| 369 | 370 | resumeStmt
|
| ... | ... | @@ -396,28 +397,6 @@ abandonStmt hvref = do |
| 396 | 397 | _ <- takeMVar resumeStatusMVar
|
| 397 | 398 | return ()
|
| 398 | 399 | |
| 399 | -foreign import ccall "&rts_stop_next_breakpoint" stepFlag :: Ptr CInt
|
|
| 400 | -foreign import ccall "&rts_stop_on_exception" exceptionFlag :: Ptr CInt
|
|
| 401 | - |
|
| 402 | -setStepFlag :: IO ()
|
|
| 403 | -setStepFlag = poke stepFlag 1
|
|
| 404 | -resetStepFlag :: IO ()
|
|
| 405 | -resetStepFlag = poke stepFlag 0
|
|
| 406 | - |
|
| 407 | -type BreakpointCallback
|
|
| 408 | - = Addr# -- pointer to the breakpoint tick module name
|
|
| 409 | - -> Addr# -- pointer to the breakpoint tick module unit id
|
|
| 410 | - -> Int# -- breakpoint tick index
|
|
| 411 | - -> Addr# -- pointer to the breakpoint info module name
|
|
| 412 | - -> Addr# -- pointer to the breakpoint info module unit id
|
|
| 413 | - -> Int# -- breakpoint info index
|
|
| 414 | - -> Bool -- exception?
|
|
| 415 | - -> HValue -- the AP_STACK, or exception
|
|
| 416 | - -> IO ()
|
|
| 417 | - |
|
| 418 | -foreign import ccall "&rts_breakpoint_io_action"
|
|
| 419 | - breakPointIOAction :: Ptr (StablePtr BreakpointCallback)
|
|
| 420 | - |
|
| 421 | 400 | noBreakStablePtr :: StablePtr BreakpointCallback
|
| 422 | 401 | noBreakStablePtr = unsafePerformIO $ newStablePtr noBreakAction
|
| 423 | 402 |
| ... | ... | @@ -60,6 +60,7 @@ library |
| 60 | 60 | CPP-Options: -DHAVE_INTERNAL_INTERPRETER
|
| 61 | 61 | exposed-modules:
|
| 62 | 62 | GHCi.Run
|
| 63 | + GHCi.Debugger
|
|
| 63 | 64 | GHCi.CreateBCO
|
| 64 | 65 | GHCi.ObjLink
|
| 65 | 66 | GHCi.Signals
|
| ... | ... | @@ -203,14 +203,14 @@ PUSH_L instruction. |
| 203 | 203 | |
| 204 | 204 | |---------|
|
| 205 | 205 | | BCO_1 | -<-┐
|
| 206 | -|---------|
|
|
| 206 | +|---------| |
|
|
| 207 | 207 | ......... |
|
| 208 | 208 | |---------| | PUSH_L <n>
|
| 209 | 209 | | BCO_N | ->-┘
|
| 210 | 210 | |---------|
|
| 211 | 211 | |
| 212 | 212 | Here BCO_N is syntactically nested within the code for BCO_1 and will result
|
| 213 | -in code that references the prior stack frame of BCO_1 for some of it's local
|
|
| 213 | +in code that references the prior stack frame of BCO_1 for some of its local
|
|
| 214 | 214 | variables. If a stack overflow happens between the creation of the stack frame
|
| 215 | 215 | for BCO_1 and BCO_N the RTS might move BCO_N to a new stack chunk while leaving
|
| 216 | 216 | BCO_1 in place, invalidating a simple offset based reference to the outer stack
|
| ... | ... | @@ -243,9 +243,44 @@ allocate_NONUPD (Capability *cap, int n_words) |
| 243 | 243 | return allocate(cap, stg_max(sizeofW(StgHeader)+MIN_PAYLOAD_SIZE, n_words));
|
| 244 | 244 | }
|
| 245 | 245 | |
| 246 | -int rts_stop_next_breakpoint = 0;
|
|
| 247 | 246 | int rts_stop_on_exception = 0;
|
| 248 | 247 | |
| 248 | +/* ---------------------------------------------------------------------------
|
|
| 249 | + * Enabling and disabling global single step mode
|
|
| 250 | + * ------------------------------------------------------------------------ */
|
|
| 251 | + |
|
| 252 | +/* A global toggle for single-step mode.
|
|
| 253 | + * Unlike `TSO_STOP_NEXT_BREAKPOINT`, which sets single-step mode per-thread,
|
|
| 254 | + * `rts_stop_next_breakpoint` globally enables single-step mode. If enabled, we
|
|
| 255 | + * will stop at the immediate next breakpoint regardless of what thread it is in. */
|
|
| 256 | +int rts_stop_next_breakpoint = 0;
|
|
| 257 | + |
|
| 258 | +void rts_enableStopNextBreakpointAll(void)
|
|
| 259 | +{
|
|
| 260 | + rts_stop_next_breakpoint = 1;
|
|
| 261 | +}
|
|
| 262 | + |
|
| 263 | +void rts_disableStopNextBreakpointAll(void)
|
|
| 264 | +{
|
|
| 265 | + rts_stop_next_breakpoint = 0;
|
|
| 266 | +}
|
|
| 267 | + |
|
| 268 | +/* ---------------------------------------------------------------------------
|
|
| 269 | + * Enabling and disabling per-thread single step mode
|
|
| 270 | + * ------------------------------------------------------------------------ */
|
|
| 271 | + |
|
| 272 | +void rts_enableStopNextBreakpoint(StgPtr tso)
|
|
| 273 | +{
|
|
| 274 | + ((StgTSO *)tso)->flags |= TSO_STOP_NEXT_BREAKPOINT;
|
|
| 275 | +}
|
|
| 276 | + |
|
| 277 | +void rts_disableStopNextBreakpoint(StgPtr tso)
|
|
| 278 | +{
|
|
| 279 | + ((StgTSO *)tso)->flags &= ~TSO_STOP_NEXT_BREAKPOINT;
|
|
| 280 | +}
|
|
| 281 | + |
|
| 282 | +/* -------------------------------------------------------------------------- */
|
|
| 283 | + |
|
| 249 | 284 | #if defined(INTERP_STATS)
|
| 250 | 285 | |
| 251 | 286 | #define N_CODES 128
|
| ... | ... | @@ -508,14 +543,35 @@ interpretBCO (Capability* cap) |
| 508 | 543 | //
|
| 509 | 544 | // We have a BCO application to perform. Stack looks like:
|
| 510 | 545 | //
|
| 511 | - // | .... |
|
|
| 512 | - // +---------------+
|
|
| 513 | - // | arg1 |
|
|
| 514 | - // +---------------+
|
|
| 515 | - // | BCO |
|
|
| 516 | - // +---------------+
|
|
| 517 | - // Sp | RET_BCO |
|
|
| 518 | - // +---------------+
|
|
| 546 | + //
|
|
| 547 | + // (an StgBCO)
|
|
| 548 | + // +---> +---------[1]--+
|
|
| 549 | + // | | stg_BCO_info | ------+
|
|
| 550 | + // | +--------------+ |
|
|
| 551 | + // | | StgArrBytes* | <--- the byte code
|
|
| 552 | + // | ... | | +--------------+ |
|
|
| 553 | + // +------------------+ | | ... | |
|
|
| 554 | + // | fvs1 | | |
|
|
| 555 | + // +------------------+ | |
|
|
| 556 | + // | ... | | (StgInfoTable) |
|
|
| 557 | + // +------------------+ | +----------+ <---+
|
|
| 558 | + // | args1 | | | ... |
|
|
| 559 | + // +------------------+ | +----------+
|
|
| 560 | + // | some StgBCO* | -----+ | type=BCO |
|
|
| 561 | + // +------------------+ +----------+
|
|
| 562 | + // Sp | stg_apply_interp | -----+ | ... |
|
|
| 563 | + // +------------------+ |
|
|
| 564 | + // |
|
|
| 565 | + // | (StgInfoTable)
|
|
| 566 | + // +----> +--------------+
|
|
| 567 | + // | ... |
|
|
| 568 | + // +--------------+
|
|
| 569 | + // | type=RET_BCO |
|
|
| 570 | + // +--------------+
|
|
| 571 | + // | ... |
|
|
| 572 | + //
|
|
| 573 | + // [1] An StgBCO's info table pointer may also be stg_CASE_CONT_BCO_info.
|
|
| 574 | + // See Note [Case continuation BCOs].
|
|
| 519 | 575 | //
|
| 520 | 576 | else if (SpW(0) == (W_)&stg_apply_interp_info) {
|
| 521 | 577 | obj = UNTAG_CLOSURE((StgClosure *)ReadSpW(1));
|
| ... | ... | @@ -1250,7 +1306,7 @@ run_BCO: |
| 1250 | 1306 | int arg8_cc;
|
| 1251 | 1307 | #endif
|
| 1252 | 1308 | StgArrBytes *breakPoints;
|
| 1253 | - int returning_from_break;
|
|
| 1309 | + int returning_from_break, stop_next_breakpoint;
|
|
| 1254 | 1310 | |
| 1255 | 1311 | // the io action to run at a breakpoint
|
| 1256 | 1312 | StgClosure *ioAction;
|
| ... | ... | @@ -1280,6 +1336,13 @@ run_BCO: |
| 1280 | 1336 | returning_from_break =
|
| 1281 | 1337 | cap->r.rCurrentTSO->flags & TSO_STOPPED_ON_BREAKPOINT;
|
| 1282 | 1338 | |
| 1339 | + // check whether this thread is set to stop at the immediate next
|
|
| 1340 | + // breakpoint -- either by the global `rts_stop_next_breakpoint`
|
|
| 1341 | + // flag, or by the local `TSO_STOP_NEXT_BREAKPOINT`
|
|
| 1342 | + stop_next_breakpoint =
|
|
| 1343 | + rts_stop_next_breakpoint ||
|
|
| 1344 | + cap->r.rCurrentTSO->flags & TSO_STOP_NEXT_BREAKPOINT;
|
|
| 1345 | + |
|
| 1283 | 1346 | #if defined(PROFILING)
|
| 1284 | 1347 | cap->r.rCCCS = pushCostCentre(cap->r.rCCCS,
|
| 1285 | 1348 | (CostCentre*)BCO_LIT(arg8_cc));
|
| ... | ... | @@ -1291,20 +1354,20 @@ run_BCO: |
| 1291 | 1354 | {
|
| 1292 | 1355 | breakPoints = (StgArrBytes *) BCO_PTR(arg1_brk_array);
|
| 1293 | 1356 | |
| 1294 | - // stop the current thread if either the
|
|
| 1295 | - // "rts_stop_next_breakpoint" flag is true OR if the
|
|
| 1296 | - // ignore count for this particular breakpoint is zero
|
|
| 1357 | + // stop the current thread if either `stop_next_breakpoint` is
|
|
| 1358 | + // true OR if the ignore count for this particular breakpoint is zero
|
|
| 1297 | 1359 | StgInt ignore_count = ((StgInt*)breakPoints->payload)[arg6_tick_index];
|
| 1298 | - if (rts_stop_next_breakpoint == false && ignore_count > 0)
|
|
| 1360 | + if (stop_next_breakpoint == false && ignore_count > 0)
|
|
| 1299 | 1361 | {
|
| 1300 | 1362 | // decrement and write back ignore count
|
| 1301 | 1363 | ((StgInt*)breakPoints->payload)[arg6_tick_index] = --ignore_count;
|
| 1302 | 1364 | }
|
| 1303 | - else if (rts_stop_next_breakpoint == true || ignore_count == 0)
|
|
| 1365 | + else if (stop_next_breakpoint == true || ignore_count == 0)
|
|
| 1304 | 1366 | {
|
| 1305 | 1367 | // make sure we don't automatically stop at the
|
| 1306 | 1368 | // next breakpoint
|
| 1307 | - rts_stop_next_breakpoint = false;
|
|
| 1369 | + rts_stop_next_breakpoint = 0;
|
|
| 1370 | + cap->r.rCurrentTSO->flags &= ~TSO_STOP_NEXT_BREAKPOINT;
|
|
| 1308 | 1371 | |
| 1309 | 1372 | // allocate memory for a new AP_STACK, enough to
|
| 1310 | 1373 | // store the top stack frame plus an
|
| ... | ... | @@ -1477,7 +1540,7 @@ run_BCO: |
| 1477 | 1540 | // Here we make sure references we push are tagged.
|
| 1478 | 1541 | // See Note [CBV Functions and the interpreter] in Info.hs
|
| 1479 | 1542 | |
| 1480 | - //Safe some memory reads if we already have a tag.
|
|
| 1543 | + //Save some memory reads if we already have a tag.
|
|
| 1481 | 1544 | if(GET_CLOSURE_TAG(tagged_obj) == 0) {
|
| 1482 | 1545 | StgClosure *obj = UNTAG_CLOSURE(tagged_obj);
|
| 1483 | 1546 | switch ( get_itbl(obj)->type ) {
|
| ... | ... | @@ -11,3 +11,8 @@ |
| 11 | 11 | RTS_PRIVATE Capability *interpretBCO (Capability* cap);
|
| 12 | 12 | void interp_startup ( void );
|
| 13 | 13 | void interp_shutdown ( void );
|
| 14 | + |
|
| 15 | +void rts_enableStopNextBreakpointAll ( void );
|
|
| 16 | +void rts_disableStopNextBreakpointAll ( void );
|
|
| 17 | +void rts_enableStopNextBreakpoint ( StgPtr );
|
|
| 18 | +void rts_disableStopNextBreakpoint ( StgPtr ); |
| ... | ... | @@ -55,6 +55,7 @@ import CLOSURE stg_AP_STACK_info; |
| 55 | 55 | import CLOSURE stg_AP_info;
|
| 56 | 56 | import CLOSURE stg_ARR_WORDS_info;
|
| 57 | 57 | import CLOSURE stg_BCO_info;
|
| 58 | +import CLOSURE stg_CASE_CONT_BCO_info;
|
|
| 58 | 59 | import CLOSURE stg_C_FINALIZER_LIST_info;
|
| 59 | 60 | import CLOSURE stg_DEAD_WEAK_info;
|
| 60 | 61 | import CLOSURE stg_END_STM_WATCH_QUEUE_closure;
|
| ... | ... | @@ -2434,7 +2435,8 @@ stg_deRefStablePtrzh ( P_ sp ) |
| 2434 | 2435 | Bytecode object primitives
|
| 2435 | 2436 | ------------------------------------------------------------------------- */
|
| 2436 | 2437 | |
| 2437 | -stg_newBCOzh ( P_ instrs,
|
|
| 2438 | +stg_newBCO2zh ( CBool is_case_cont,
|
|
| 2439 | + P_ instrs,
|
|
| 2438 | 2440 | P_ literals,
|
| 2439 | 2441 | P_ ptrs,
|
| 2440 | 2442 | W_ arity,
|
| ... | ... | @@ -2449,7 +2451,16 @@ stg_newBCOzh ( P_ instrs, |
| 2449 | 2451 | |
| 2450 | 2452 | bco = Hp - bytes + WDS(1);
|
| 2451 | 2453 | // No memory barrier necessary as this is a new allocation.
|
| 2452 | - SET_HDR(bco, stg_BCO_info, CCS_MAIN);
|
|
| 2454 | + if (is_case_cont > 0) {
|
|
| 2455 | + /* Uses stg_CASE_CONT_BCO_info to construct the BCO frame (rather than stg_BCO_info).
|
|
| 2456 | + * Case continuations may contain non-local references to parent frames. The distinct info table
|
|
| 2457 | + * tag allows the RTS to identify such non-local frames.
|
|
| 2458 | + * See Note [Case continuation BCOs]
|
|
| 2459 | + */
|
|
| 2460 | + SET_HDR(bco, stg_CASE_CONT_BCO_info, CCS_MAIN);
|
|
| 2461 | + } else {
|
|
| 2462 | + SET_HDR(bco, stg_BCO_info, CCS_MAIN);
|
|
| 2463 | + }
|
|
| 2453 | 2464 | |
| 2454 | 2465 | StgBCO_instrs(bco) = instrs;
|
| 2455 | 2466 | StgBCO_literals(bco) = literals;
|
| ... | ... | @@ -690,6 +690,8 @@ printStackChunk( StgPtr sp, StgPtr spBottom ) |
| 690 | 690 | debugBelch("stg_ctoi_V_info" );
|
| 691 | 691 | } else if (c == (StgWord)&stg_BCO_info) {
|
| 692 | 692 | debugBelch("stg_BCO_info" );
|
| 693 | + } else if (c == (StgWord)&stg_CASE_CONT_BCO_info) {
|
|
| 694 | + debugBelch("stg_CASE_CONT_BCO_info" );
|
|
| 693 | 695 | } else if (c == (StgWord)&stg_apply_interp_info) {
|
| 694 | 696 | debugBelch("stg_apply_interp_info" );
|
| 695 | 697 | } else if (c == (StgWord)&stg_ret_t_info) {
|
| ... | ... | @@ -639,7 +639,7 @@ extern char **environ; |
| 639 | 639 | SymI_HasDataProto(stg_copySmallMutableArrayzh) \
|
| 640 | 640 | SymI_HasDataProto(stg_casSmallArrayzh) \
|
| 641 | 641 | SymI_HasDataProto(stg_copyArray_barrier) \
|
| 642 | - SymI_HasDataProto(stg_newBCOzh) \
|
|
| 642 | + SymI_HasDataProto(stg_newBCO2zh) \
|
|
| 643 | 643 | SymI_HasDataProto(stg_newByteArrayzh) \
|
| 644 | 644 | SymI_HasDataProto(stg_casIntArrayzh) \
|
| 645 | 645 | SymI_HasDataProto(stg_casInt8Arrayzh) \
|
| ... | ... | @@ -906,7 +906,10 @@ extern char **environ; |
| 906 | 906 | SymI_HasProto(revertCAFs) \
|
| 907 | 907 | SymI_HasProto(RtsFlags) \
|
| 908 | 908 | SymI_NeedsDataProto(rts_breakpoint_io_action) \
|
| 909 | - SymI_NeedsDataProto(rts_stop_next_breakpoint) \
|
|
| 909 | + SymI_NeedsDataProto(rts_enableStopNextBreakpointAll) \
|
|
| 910 | + SymI_NeedsDataProto(rts_disableStopNextBreakpointAll) \
|
|
| 911 | + SymI_NeedsDataProto(rts_enableStopNextBreakpoint) \
|
|
| 912 | + SymI_NeedsDataProto(rts_disableStopNextBreakpoint) \
|
|
| 910 | 913 | SymI_NeedsDataProto(rts_stop_on_exception) \
|
| 911 | 914 | SymI_HasProto(stopTimer) \
|
| 912 | 915 | SymI_HasProto(n_capabilities) \
|
| ... | ... | @@ -464,6 +464,12 @@ INFO_TABLE_RET( stg_dead_thread, RET_SMALL, |
| 464 | 464 | |
| 465 | 465 | /* ----------------------------------------------------------------------------
|
| 466 | 466 | Entry code for a BCO
|
| 467 | + |
|
| 468 | + `stg_BCO` and `stg_CASE_CONT_BCO` distinguish between a BCO that refers to
|
|
| 469 | + non-local variables in its code (using a stack offset) and those that do not.
|
|
| 470 | + Only case-continuation BCOs should use non-local variables.
|
|
| 471 | + Otherwise, `stg_BCO` and `stg_CASE_CONT_BCO` behave the same.
|
|
| 472 | + See Note [Case continuation BCOs].
|
|
| 467 | 473 | ------------------------------------------------------------------------- */
|
| 468 | 474 | |
| 469 | 475 | INFO_TABLE_FUN( stg_BCO, 3, 0, BCO, "BCO", "BCO", 0, ARG_BCO )
|
| ... | ... | @@ -478,6 +484,15 @@ INFO_TABLE_FUN( stg_BCO, 3, 0, BCO, "BCO", "BCO", 0, ARG_BCO ) |
| 478 | 484 | jump stg_yield_to_interpreter [];
|
| 479 | 485 | }
|
| 480 | 486 | |
| 487 | +INFO_TABLE_FUN( stg_CASE_CONT_BCO, 3, 0, BCO, "BCO", "BCO", 0, ARG_BCO )
|
|
| 488 | +{
|
|
| 489 | + /* Exactly as for stg_BCO */
|
|
| 490 | + Sp_adj(-2);
|
|
| 491 | + Sp(1) = R1;
|
|
| 492 | + Sp(0) = stg_apply_interp_info;
|
|
| 493 | + jump stg_yield_to_interpreter [];
|
|
| 494 | +}
|
|
| 495 | + |
|
| 481 | 496 | /* ----------------------------------------------------------------------------
|
| 482 | 497 | Info tables for indirections.
|
| 483 | 498 |
| ... | ... | @@ -328,6 +328,12 @@ |
| 328 | 328 | */
|
| 329 | 329 | #define TSO_ALLOC_LIMIT 256
|
| 330 | 330 | |
| 331 | +/*
|
|
| 332 | + * Enables step-in mode for this thread -- it will stop at the immediate next
|
|
| 333 | + * breakpoint found in this thread.
|
|
| 334 | + */
|
|
| 335 | +#define TSO_STOP_NEXT_BREAKPOINT 512
|
|
| 336 | + |
|
| 331 | 337 | /*
|
| 332 | 338 | * The number of times we spin in a spin lock before yielding (see
|
| 333 | 339 | * #3758). To tune this value, use the benchmark in #3758: run the
|
| ... | ... | @@ -180,6 +180,7 @@ RTS_ENTRY(stg_BLOCKING_QUEUE_CLEAN); |
| 180 | 180 | RTS_ENTRY(stg_BLOCKING_QUEUE_DIRTY);
|
| 181 | 181 | |
| 182 | 182 | RTS_FUN(stg_BCO);
|
| 183 | +RTS_FUN(stg_CASE_CONT_BCO);
|
|
| 183 | 184 | RTS_ENTRY(stg_EVACUATED);
|
| 184 | 185 | RTS_ENTRY(stg_WEAK);
|
| 185 | 186 | RTS_ENTRY(stg_DEAD_WEAK);
|
| ... | ... | @@ -577,7 +578,7 @@ RTS_FUN_DECL(stg_deRefWeakzh); |
| 577 | 578 | |
| 578 | 579 | RTS_FUN_DECL(stg_runRWzh);
|
| 579 | 580 | |
| 580 | -RTS_FUN_DECL(stg_newBCOzh);
|
|
| 581 | +RTS_FUN_DECL(stg_newBCO2zh);
|
|
| 581 | 582 | RTS_FUN_DECL(stg_mkApUpd0zh);
|
| 582 | 583 | |
| 583 | 584 | RTS_FUN_DECL(stg_retryzh);
|