Rodrigo Mesquita pushed to branch wip/romes/top-level-bcos-tag at Glasgow Haskell Compiler / GHC
Commits:
-
5cb4a42f
by Rodrigo Mesquita at 2025-05-22T14:35:38+01:00
16 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-internal/src/GHC/Internal/Exts.hs
- libraries/ghci/GHCi/CreateBCO.hs
- libraries/ghci/GHCi/ResolvedBCO.hs
- rts/Interpreter.c
- rts/PrimOps.cmm
- rts/Printer.c
- rts/RtsSymbols.c
- rts/StgMiscClosures.cmm
- 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,109 @@ 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 | +See Note [Debugger: Step-out] for further details.
|
|
| 236 | + |
|
| 237 | +As an example, consider the following, where `y` is free in the case alternatives:
|
|
| 238 | + |
|
| 239 | + f x y = case x of
|
|
| 240 | + True -> y - 1
|
|
| 241 | + False -> y + 1 :: Int
|
|
| 242 | + |
|
| 243 | +While interpreting f, the args x and y will be on the stack as part of f's frame.
|
|
| 244 | +In its body, a case continuation BCO is pushed (PUSH_ALTS) and then `x` is
|
|
| 245 | +entered to be evaluated. Upon entering `x`, the stack would look something like:
|
|
| 246 | + |
|
| 247 | + <f arg 2>
|
|
| 248 | + <f arg 1>
|
|
| 249 | + ...
|
|
| 250 | + <Case continuation BCO Frame>
|
|
| 251 | + |
|
| 252 | +We cannot insert a step out frame in between:
|
|
| 253 | + |
|
| 254 | + |
|
| 255 | + <f arg 2>
|
|
| 256 | + <f arg 1>
|
|
| 257 | + ...
|
|
| 258 | + <inserted step-out frame> <--- BAD! Breaks stack offsets in the case cont.
|
|
| 259 | + <Case continuation BCO Frame>
|
|
| 260 | + |
|
| 261 | +Instead, we must traverse until the parent BCO and insert the step-out frame before it instead.
|
|
| 262 | +-}
|
|
| 263 | + |
|
| 170 | 264 | data UnlinkedBCO
|
| 171 | 265 | = UnlinkedBCO {
|
| 172 | 266 | unlinkedBCOName :: !Name,
|
| 173 | 267 | unlinkedBCOArity :: {-# UNPACK #-} !Int,
|
| 174 | - unlinkedBCOInstrs :: !(BCOByteArray Word16), -- insns
|
|
| 175 | - unlinkedBCOBitmap :: !(BCOByteArray Word), -- bitmap
|
|
| 268 | + unlinkedBCOInstrs :: !(BCOByteArray Word16), -- insns
|
|
| 269 | + unlinkedBCOBitmap :: !(BCOByteArray Word), -- bitmap
|
|
| 176 | 270 | unlinkedBCOLits :: !(FlatBag BCONPtr), -- non-ptrs
|
| 177 | - unlinkedBCOPtrs :: !(FlatBag BCOPtr) -- ptrs
|
|
| 271 | + unlinkedBCOPtrs :: !(FlatBag BCOPtr), -- ptrs
|
|
| 272 | + unlinkedBCOIsCaseCont :: !Bool -- See Note [Case continuation BCOs]
|
|
| 178 | 273 | }
|
| 179 | 274 | |
| 180 | 275 | instance NFData UnlinkedBCO where
|
| ... | ... | @@ -227,10 +322,11 @@ seqCgBreakInfo CgBreakInfo{..} = |
| 227 | 322 | rnf cgb_resty
|
| 228 | 323 | |
| 229 | 324 | instance Outputable UnlinkedBCO where
|
| 230 | - ppr (UnlinkedBCO nm _arity _insns _bitmap lits ptrs)
|
|
| 325 | + ppr (UnlinkedBCO nm _arity _insns _bitmap lits ptrs pi)
|
|
| 231 | 326 | = sep [text "BCO", ppr nm, text "with",
|
| 232 | 327 | ppr (sizeFlatBag lits), text "lits",
|
| 233 | - ppr (sizeFlatBag ptrs), text "ptrs" ]
|
|
| 328 | + ppr (sizeFlatBag ptrs), text "ptrs",
|
|
| 329 | + ppr pi, text "is_pos_indep"]
|
|
| 234 | 330 | |
| 235 | 331 | instance Outputable CgBreakInfo where
|
| 236 | 332 | 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 |
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -524,14 +524,35 @@ interpretBCO (Capability* cap) |
| 524 | 524 | //
|
| 525 | 525 | // We have a BCO application to perform. Stack looks like:
|
| 526 | 526 | //
|
| 527 | - // | .... |
|
|
| 528 | - // +---------------+
|
|
| 529 | - // | arg1 |
|
|
| 530 | - // +---------------+
|
|
| 531 | - // | BCO |
|
|
| 532 | - // +---------------+
|
|
| 533 | - // Sp | RET_BCO |
|
|
| 534 | - // +---------------+
|
|
| 527 | + //
|
|
| 528 | + // (an StgBCO)
|
|
| 529 | + // +---> +---------[1]--+
|
|
| 530 | + // | | stg_BCO_info | ------+
|
|
| 531 | + // | +--------------+ |
|
|
| 532 | + // | | StgArrBytes* | <--- the byte code
|
|
| 533 | + // | ... | | +--------------+ |
|
|
| 534 | + // +------------------+ | | ... | |
|
|
| 535 | + // | fvs1 | | |
|
|
| 536 | + // +------------------+ | |
|
|
| 537 | + // | ... | | (StgInfoTable) |
|
|
| 538 | + // +------------------+ | +----------+ <---+
|
|
| 539 | + // | args1 | | | ... |
|
|
| 540 | + // +------------------+ | +----------+
|
|
| 541 | + // | some StgBCO* | -----+ | type=BCO |
|
|
| 542 | + // +------------------+ +----------+
|
|
| 543 | + // Sp | stg_apply_interp | -----+ | ... |
|
|
| 544 | + // +------------------+ |
|
|
| 545 | + // |
|
|
| 546 | + // | (StgInfoTable)
|
|
| 547 | + // +----> +--------------+
|
|
| 548 | + // | ... |
|
|
| 549 | + // +--------------+
|
|
| 550 | + // | type=RET_BCO |
|
|
| 551 | + // +--------------+
|
|
| 552 | + // | ... |
|
|
| 553 | + //
|
|
| 554 | + // [1] An StgBCO's info table pointer may also be stg_CASE_CONT_BCO_info.
|
|
| 555 | + // See Note [Case continuation BCOs].
|
|
| 535 | 556 | //
|
| 536 | 557 | else if (SpW(0) == (W_)&stg_apply_interp_info) {
|
| 537 | 558 | obj = UNTAG_CLOSURE((StgClosure *)ReadSpW(1));
|
| ... | ... | @@ -1500,7 +1521,7 @@ run_BCO: |
| 1500 | 1521 | // Here we make sure references we push are tagged.
|
| 1501 | 1522 | // See Note [CBV Functions and the interpreter] in Info.hs
|
| 1502 | 1523 | |
| 1503 | - //Safe some memory reads if we already have a tag.
|
|
| 1524 | + //Save some memory reads if we already have a tag.
|
|
| 1504 | 1525 | if(GET_CLOSURE_TAG(tagged_obj) == 0) {
|
| 1505 | 1526 | StgClosure *obj = UNTAG_CLOSURE(tagged_obj);
|
| 1506 | 1527 | switch ( get_itbl(obj)->type ) {
|
| ... | ... | @@ -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) \
|
| ... | ... | @@ -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 |
| ... | ... | @@ -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);
|