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);
|