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
rts: Case continuation BCOs
This commit introduces the `stg_CASE_CONT_BCO` info table, which is
identical to `stg_BCO` and shares the same closure type (== BCO).
It changes the bytecode generator to always use `stg_CASE_CONT_BCO_info`
when constructing case continuation BCOs, and remain using `stg_BCO`
otherwise.
This allows us to distinguish at runtime case continuation BCOs from
other BCOs. In particular, this is relevant because, unlike other BCOs,
the code of a case continuation BCO may refer to variables in its
parent's stack frame (ie non-local variables), and therefore its frame
position on the stack cannot be changed in isolation.
The full motivation and details are in Note [Case continuation BCOs].
Towards #26042
- - - - -
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:
=====================================
compiler/GHC/Builtin/primops.txt.pp
=====================================
@@ -3872,12 +3872,13 @@ primop MkApUpd0_Op "mkApUpd0#" GenPrimOp
with
out_of_line = True
-primop NewBCOOp "newBCO#" GenPrimOp
- ByteArray# -> ByteArray# -> Array# a -> Int# -> ByteArray# -> State# s -> (# State# s, BCO #)
- { @'newBCO#' instrs lits ptrs arity bitmap@ creates a new bytecode object. The
+primop NewBCOOp "newBCO2#" GenPrimOp
+ Int8# -> ByteArray# -> ByteArray# -> Array# a -> Int# -> ByteArray# -> State# s -> (# State# s, BCO #)
+ { @'newBCO2#' is_case_cont instrs lits ptrs arity bitmap@ creates a new bytecode object. The
resulting object encodes a function of the given arity with the instructions
encoded in @instrs@, and a static reference table usage bitmap given by
- @bitmap@. }
+ @bitmap@. The @is_case_cont@ boolean indicates whether the BCO is a case
+ continuation (see Note [Case continuation BCOs]) }
with
effect = ReadWriteEffect
out_of_line = True
=====================================
compiler/GHC/ByteCode/Asm.hs
=====================================
@@ -85,7 +85,7 @@ bcoFreeNames :: UnlinkedBCO -> UniqDSet Name
bcoFreeNames bco
= bco_refs bco `uniqDSetMinusUniqSet` mkNameSet [unlinkedBCOName bco]
where
- bco_refs (UnlinkedBCO _ _ _ _ nonptrs ptrs)
+ bco_refs (UnlinkedBCO _ _ _ _ nonptrs ptrs _)
= unionManyUniqDSets (
mkUniqDSet [ n | BCOPtrName n <- elemsFlatBag ptrs ] :
mkUniqDSet [ n | BCONPtrItbl n <- elemsFlatBag nonptrs ] :
@@ -236,7 +236,8 @@ assembleBCO platform
, protoBCOInstrs = instrs
, protoBCOBitmap = bitmap
, protoBCOBitmapSize = bsize
- , protoBCOArity = arity }) = do
+ , protoBCOArity = arity
+ , protoBCOIsCaseCont = isCC }) = do
-- pass 1: collect up the offsets of the local labels.
let initial_offset = 0
@@ -266,7 +267,7 @@ assembleBCO platform
let !insns_arr = mkBCOByteArray $ final_isn_array
!bitmap_arr = mkBCOByteArray $ mkBitmapArray bsize bitmap
- ul_bco = UnlinkedBCO nm arity insns_arr bitmap_arr (fromSmallArray final_lit_array) (fromSmallArray final_ptr_array)
+ ul_bco = UnlinkedBCO nm arity insns_arr bitmap_arr (fromSmallArray final_lit_array) (fromSmallArray final_ptr_array) isCC
-- 8 Aug 01: Finalisers aren't safe when attached to non-primitive
-- objects, since they might get run too early. Disable this until
=====================================
compiler/GHC/ByteCode/Instr.hs
=====================================
@@ -53,7 +53,8 @@ data ProtoBCO a
-- what the BCO came from, for debugging only
protoBCOExpr :: Either [CgStgAlt] CgStgRhs,
-- malloc'd pointers
- protoBCOFFIs :: [FFIInfo]
+ protoBCOFFIs :: [FFIInfo],
+ protoBCOIsCaseCont :: !Bool -- See Note [Case continuation BCOs]
}
-- | A local block label (e.g. identifying a case alternative).
=====================================
compiler/GHC/ByteCode/Linker.hs
=====================================
@@ -59,7 +59,7 @@ linkBCO
-> UnlinkedBCO
-> IO ResolvedBCO
linkBCO interp pkgs_loaded le bco_ix
- (UnlinkedBCO _ arity insns bitmap lits0 ptrs0) = do
+ (UnlinkedBCO _ arity insns bitmap lits0 ptrs0 isCC) = do
-- fromIntegral Word -> Word64 should be a no op if Word is Word64
-- otherwise it will result in a cast to longlong on 32bit systems.
(lits :: [Word]) <- mapM (fmap fromIntegral . lookupLiteral interp pkgs_loaded le) (elemsFlatBag lits0)
@@ -69,7 +69,7 @@ linkBCO interp pkgs_loaded le bco_ix
insns
bitmap
(mkBCOByteArray lits')
- (addListToSS emptySS ptrs))
+ (addListToSS emptySS ptrs) isCC)
lookupLiteral :: Interp -> PkgsLoaded -> LinkerEnv -> BCONPtr -> IO Word
lookupLiteral interp pkgs_loaded le ptr = case ptr of
=====================================
compiler/GHC/ByteCode/Types.hs
=====================================
@@ -167,14 +167,109 @@ newtype ItblPtr = ItblPtr (RemotePtr Heap.StgInfoTable)
newtype AddrPtr = AddrPtr (RemotePtr ())
deriving (NFData)
+{-
+--------------------------------------------------------------------------------
+-- * Byte Code Objects (BCOs)
+--------------------------------------------------------------------------------
+
+Note [Case continuation BCOs]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A stack with a BCO stack frame at the top looks like:
+
+ (an StgBCO)
+ | ... | +---> +---------[1]--+
+ +------------------+ | | info_tbl_ptr | ------+
+ | OTHER FRAME | | +--------------+ |
+ +------------------+ | | StgArrBytes* | <--- the byte code
+ | ... | | +--------------+ |
+ +------------------+ | | ... | |
+ | fvs1 | | |
+ +------------------+ | |
+ | ... | | (StgInfoTable) |
+ +------------------+ | +----------+ <---+
+ | args1 | | | ... |
+ +------------------+ | +----------+
+ | some StgBCO* | -----+ | type=BCO |
+ +------------------+ +----------+
+ Sp | stg_apply_interp | -----+ | ... |
+ +------------------+ |
+ |
+ | (StgInfoTable)
+ +----> +--------------+
+ | ... |
+ +--------------+
+ | type=RET_BCO |
+ +--------------+
+ | ... |
+
+
+The byte code for a BCO heap object makes use of arguments and free variables
+which can typically be found within the BCO stack frame. In the code, these
+variables are referenced via a statically known stack offset (tracked using
+`BCEnv` in `StgToByteCode`).
+
+However, in /case continuation/ BCOs, the code may additionally refer to free
+variables that are outside of that BCO's stack frame -- some free variables of a
+case continuation BCO may only be found in the stack frame of a parent BCO.
+
+Yet, references to these out-of-frame variables are also done in terms of stack
+offsets. Thus, they rely on the position of /another frame/ to be fixed. (See
+Note [PUSH_L underflow] for more information about references to previous
+frames and nested BCOs)
+
+This makes case continuation BCOs special: unlike normal BCOs, case cont BCO
+frames cannot be moved on the stack independently from their parent BCOs.
+
+In order to be able to distinguish them at runtime, the code generator will use
+distinct info table pointers for their closures, even though they will have the
+same structure on the heap (StgBCO). Specifically:
+
+ - Normal BCOs are always headed by the `stg_BCO_info` pointer.
+ - Case continuation BCOs are always headed by the `stg_CASE_CONT_BCO_info` pointer.
+
+A primary reason why we need to distinguish these two cases is to know where we
+can insert a debugger step-out frame (`stg_stop_after_ret_frame`). In
+particular, because case cont BCOs may refer to the parent frame, we must not
+insert step-out frames between a case cont BCO and its parent.
+See Note [Debugger: Step-out] for further details.
+
+As an example, consider the following, where `y` is free in the case alternatives:
+
+ f x y = case x of
+ True -> y - 1
+ False -> y + 1 :: Int
+
+While interpreting f, the args x and y will be on the stack as part of f's frame.
+In its body, a case continuation BCO is pushed (PUSH_ALTS) and then `x` is
+entered to be evaluated. Upon entering `x`, the stack would look something like:
+
+
+
+ ...
+ <Case continuation BCO Frame>
+
+We cannot insert a step out frame in between:
+
+
+
+
+ ...
+ <inserted step-out frame> <--- BAD! Breaks stack offsets in the case cont.
+ <Case continuation BCO Frame>
+
+Instead, we must traverse until the parent BCO and insert the step-out frame before it instead.
+-}
+
data UnlinkedBCO
= UnlinkedBCO {
unlinkedBCOName :: !Name,
unlinkedBCOArity :: {-# UNPACK #-} !Int,
- unlinkedBCOInstrs :: !(BCOByteArray Word16), -- insns
- unlinkedBCOBitmap :: !(BCOByteArray Word), -- bitmap
+ unlinkedBCOInstrs :: !(BCOByteArray Word16), -- insns
+ unlinkedBCOBitmap :: !(BCOByteArray Word), -- bitmap
unlinkedBCOLits :: !(FlatBag BCONPtr), -- non-ptrs
- unlinkedBCOPtrs :: !(FlatBag BCOPtr) -- ptrs
+ unlinkedBCOPtrs :: !(FlatBag BCOPtr), -- ptrs
+ unlinkedBCOIsCaseCont :: !Bool -- See Note [Case continuation BCOs]
}
instance NFData UnlinkedBCO where
@@ -227,10 +322,11 @@ seqCgBreakInfo CgBreakInfo{..} =
rnf cgb_resty
instance Outputable UnlinkedBCO where
- ppr (UnlinkedBCO nm _arity _insns _bitmap lits ptrs)
+ ppr (UnlinkedBCO nm _arity _insns _bitmap lits ptrs pi)
= sep [text "BCO", ppr nm, text "with",
ppr (sizeFlatBag lits), text "lits",
- ppr (sizeFlatBag ptrs), text "ptrs" ]
+ ppr (sizeFlatBag ptrs), text "ptrs",
+ ppr pi, text "is_pos_indep"]
instance Outputable CgBreakInfo where
ppr info = text "CgBreakInfo" <+>
=====================================
compiler/GHC/StgToByteCode.hs
=====================================
@@ -253,7 +253,11 @@ mkProtoBCO
-> Int -- ^ arity
-> WordOff -- ^ bitmap size
-> [StgWord] -- ^ bitmap
- -> Bool -- ^ True <=> is a return point, rather than a function
+ -> Bool -- ^ True <=> it's a case continuation, rather than a function
+ -- Used for
+ -- (A) Stack check collision and
+ -- (B) Mark the BCO wrt whether it contains non-local stack
+ -- references. See Note [Case continuation BCOs].
-> [FFIInfo]
-> ProtoBCO Name
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
protoBCOBitmapSize = fromIntegral bitmap_size,
protoBCOArity = arity,
protoBCOExpr = origin,
- protoBCOFFIs = ffis
+ protoBCOFFIs = ffis,
+ protoBCOIsCaseCont = is_ret
}
where
#if MIN_VERSION_rts(1,0,3)
@@ -353,6 +358,9 @@ schemeTopBind (id, rhs)
-- Park the resulting BCO in the monad. Also requires the
-- name of the variable to which this value was bound,
-- so as to give the resulting BCO a name.
+--
+-- The resulting ProtoBCO expects the free variables and the function arguments
+-- to be in the stack directly before it.
schemeR :: [Id] -- Free vars of the RHS, ordered as they
-- will appear in the thunk. Empty for
-- top-level things, which have no free vars.
@@ -391,6 +399,8 @@ schemeR_wrk fvs nm original_body (args, body)
-- them unlike constructor fields.
szsb_args = map (wordsToBytes platform . idSizeW platform) all_args
sum_szsb_args = sum szsb_args
+ -- Make a stack offset for each argument or free var -- they should
+ -- appear contiguous in the stack, in order.
p_init = Map.fromList (zip all_args (mkStackOffsets 0 szsb_args))
-- make the arg bitmap
@@ -1401,7 +1411,7 @@ Note [unboxed tuple bytecodes and tuple_BCO]
tupleBCO :: Platform -> NativeCallInfo -> [(PrimRep, ByteOff)] -> [FFIInfo] -> ProtoBCO Name
tupleBCO platform args_info args =
mkProtoBCO platform Nothing invented_name body_code (Left [])
- 0{-no arity-} bitmap_size bitmap False{-is alts-}
+ 0{-no arity-} bitmap_size bitmap False{-not alts-}
where
{-
The tuple BCO is never referred to by name, so we can get away
@@ -1422,7 +1432,7 @@ tupleBCO platform args_info args =
primCallBCO :: Platform -> NativeCallInfo -> [(PrimRep, ByteOff)] -> [FFIInfo] -> ProtoBCO Name
primCallBCO platform args_info args =
mkProtoBCO platform Nothing invented_name body_code (Left [])
- 0{-no arity-} bitmap_size bitmap False{-is alts-}
+ 0{-no arity-} bitmap_size bitmap False{-not alts-}
where
{-
The primcall BCO is never referred to by name, so we can get away
=====================================
libraries/base/src/GHC/Exts.hs
=====================================
@@ -26,12 +26,12 @@ module GHC.Exts
-- ** Legacy interface for arrays of arrays
module GHC.Internal.ArrayArray,
-- * Primitive operations
- {-# 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."] #-}
+ {-# 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."] #-}
Prim.BCO,
{-# 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."] #-}
Prim.mkApUpd0#,
{-# 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."] #-}
- Prim.newBCO#,
+ IExts.newBCO#,
module GHC.Prim,
module GHC.Prim.Ext,
-- ** Running 'RealWorld' state thread
@@ -119,7 +119,7 @@ module GHC.Exts
maxTupleSize
) where
-import GHC.Internal.Exts
+import GHC.Internal.Exts hiding ( newBCO# )
import GHC.Internal.ArrayArray
import GHC.Prim hiding
( coerce
@@ -132,7 +132,7 @@ import GHC.Prim hiding
, isByteArrayWeaklyPinned#, isMutableByteArrayWeaklyPinned#
-- deprecated
- , BCO, mkApUpd0#, newBCO#
+ , BCO, mkApUpd0#
-- Don't re-export vector FMA instructions
, fmaddFloatX4#
@@ -256,8 +256,10 @@ import GHC.Prim hiding
, minWord8X32#
, minWord8X64#
)
+import qualified GHC.Internal.Exts as IExts
+ ( newBCO# )
import qualified GHC.Prim as Prim
- ( BCO, mkApUpd0#, newBCO# )
+ ( BCO, mkApUpd0# )
import GHC.Prim.Ext
=====================================
libraries/ghc-internal/src/GHC/Internal/Exts.hs
=====================================
@@ -163,6 +163,9 @@ module GHC.Internal.Exts
-- * The maximum tuple size
maxTupleSize,
+
+ -- * Interpreter
+ newBCO#
) where
import GHC.Internal.Prim hiding ( coerce, dataToTagSmall#, dataToTagLarge#, whereFrom# )
@@ -469,3 +472,18 @@ resizeSmallMutableArray# arr0 szNew a s0 =
-- accessible\" by word.
considerAccessible :: Bool
considerAccessible = True
+
+--------------------------------------------------------------------------------
+-- Interpreter
+
+{-|
+@'newBCO#' instrs lits ptrs arity bitmap@ creates a new bytecode object. The
+resulting object encodes a function of the given arity with the instructions
+encoded in @instrs@, and a static reference table usage bitmap given by
+@bitmap@.
+
+Note: Case continuation BCOs, with non-local stack references, must be
+constructed using @'newBCO2#' 1@ instead. See Note [Case continuation BCOs].
+-}
+newBCO# :: ByteArray# -> ByteArray# -> Array# a -> Int# -> ByteArray# -> State# s -> (# State# s, BCO #)
+newBCO# b1 b2 a1 i1 b3 s = newBCO2# (intToInt8# 0#) b1 b2 a1 i1 b3 s
=====================================
libraries/ghci/GHCi/CreateBCO.hs
=====================================
@@ -87,11 +87,11 @@ linkBCO' arr ResolvedBCO{..} = do
literals_barr = barr (getBCOByteArray resolvedBCOLits)
PtrsArr marr <- mkPtrsArray arr n_ptrs ptrs
+ let is_case_cont | resolvedBCOIsCaseCont = intToInt8# 1#
+ | otherwise = intToInt8# 0#
IO $ \s ->
case unsafeFreezeArray# marr s of { (# s, arr #) ->
- case newBCO insns_barr literals_barr arr arity# bitmap_barr of { IO io ->
- io s
- }}
+ newBCO2# is_case_cont insns_barr literals_barr arr arity# bitmap_barr s }
-- we recursively link any sub-BCOs while making the ptrs array
=====================================
libraries/ghci/GHCi/ResolvedBCO.hs
=====================================
@@ -45,7 +45,8 @@ data ResolvedBCO
resolvedBCOBitmap :: BCOByteArray Word, -- ^ bitmap
resolvedBCOLits :: BCOByteArray Word,
-- ^ non-ptrs - subword sized entries still take up a full (host) word
- resolvedBCOPtrs :: (SizedSeq ResolvedBCOPtr) -- ^ ptrs
+ resolvedBCOPtrs :: (SizedSeq ResolvedBCOPtr), -- ^ ptrs
+ resolvedBCOIsCaseCont :: !Bool -- ^ See Note [Case continuation BCOs]
}
deriving (Generic, Show)
@@ -86,7 +87,8 @@ instance Binary ResolvedBCO where
put resolvedBCOBitmap
put resolvedBCOLits
put resolvedBCOPtrs
- get = ResolvedBCO <$> get <*> get <*> get <*> get <*> get <*> get
+ put resolvedBCOIsCaseCont
+ get = ResolvedBCO <$> get <*> get <*> get <*> get <*> get <*> get <*> get
-- See Note [BCOByteArray serialization]
instance (Binary a, Storable a, IArray UArray a) => Binary (BCOByteArray a) where
=====================================
rts/Interpreter.c
=====================================
@@ -203,14 +203,14 @@ PUSH_L instruction.
|---------|
| BCO_1 | -<-┐
-|---------|
+|---------| |
......... |
|---------| | PUSH_L <n>
| BCO_N | ->-┘
|---------|
Here BCO_N is syntactically nested within the code for BCO_1 and will result
-in code that references the prior stack frame of BCO_1 for some of it's local
+in code that references the prior stack frame of BCO_1 for some of its local
variables. If a stack overflow happens between the creation of the stack frame
for BCO_1 and BCO_N the RTS might move BCO_N to a new stack chunk while leaving
BCO_1 in place, invalidating a simple offset based reference to the outer stack
@@ -524,14 +524,35 @@ interpretBCO (Capability* cap)
//
// We have a BCO application to perform. Stack looks like:
//
- // | .... |
- // +---------------+
- // | arg1 |
- // +---------------+
- // | BCO |
- // +---------------+
- // Sp | RET_BCO |
- // +---------------+
+ //
+ // (an StgBCO)
+ // +---> +---------[1]--+
+ // | | stg_BCO_info | ------+
+ // | +--------------+ |
+ // | | StgArrBytes* | <--- the byte code
+ // | ... | | +--------------+ |
+ // +------------------+ | | ... | |
+ // | fvs1 | | |
+ // +------------------+ | |
+ // | ... | | (StgInfoTable) |
+ // +------------------+ | +----------+ <---+
+ // | args1 | | | ... |
+ // +------------------+ | +----------+
+ // | some StgBCO* | -----+ | type=BCO |
+ // +------------------+ +----------+
+ // Sp | stg_apply_interp | -----+ | ... |
+ // +------------------+ |
+ // |
+ // | (StgInfoTable)
+ // +----> +--------------+
+ // | ... |
+ // +--------------+
+ // | type=RET_BCO |
+ // +--------------+
+ // | ... |
+ //
+ // [1] An StgBCO's info table pointer may also be stg_CASE_CONT_BCO_info.
+ // See Note [Case continuation BCOs].
//
else if (SpW(0) == (W_)&stg_apply_interp_info) {
obj = UNTAG_CLOSURE((StgClosure *)ReadSpW(1));
@@ -1500,7 +1521,7 @@ run_BCO:
// Here we make sure references we push are tagged.
// See Note [CBV Functions and the interpreter] in Info.hs
- //Safe some memory reads if we already have a tag.
+ //Save some memory reads if we already have a tag.
if(GET_CLOSURE_TAG(tagged_obj) == 0) {
StgClosure *obj = UNTAG_CLOSURE(tagged_obj);
switch ( get_itbl(obj)->type ) {
=====================================
rts/PrimOps.cmm
=====================================
@@ -55,6 +55,7 @@ import CLOSURE stg_AP_STACK_info;
import CLOSURE stg_AP_info;
import CLOSURE stg_ARR_WORDS_info;
import CLOSURE stg_BCO_info;
+import CLOSURE stg_CASE_CONT_BCO_info;
import CLOSURE stg_C_FINALIZER_LIST_info;
import CLOSURE stg_DEAD_WEAK_info;
import CLOSURE stg_END_STM_WATCH_QUEUE_closure;
@@ -2434,7 +2435,8 @@ stg_deRefStablePtrzh ( P_ sp )
Bytecode object primitives
------------------------------------------------------------------------- */
-stg_newBCOzh ( P_ instrs,
+stg_newBCO2zh ( CBool is_case_cont,
+ P_ instrs,
P_ literals,
P_ ptrs,
W_ arity,
@@ -2449,7 +2451,16 @@ stg_newBCOzh ( P_ instrs,
bco = Hp - bytes + WDS(1);
// No memory barrier necessary as this is a new allocation.
- SET_HDR(bco, stg_BCO_info, CCS_MAIN);
+ if (is_case_cont > 0) {
+ /* Uses stg_CASE_CONT_BCO_info to construct the BCO frame (rather than stg_BCO_info).
+ * Case continuations may contain non-local references to parent frames. The distinct info table
+ * tag allows the RTS to identify such non-local frames.
+ * See Note [Case continuation BCOs]
+ */
+ SET_HDR(bco, stg_CASE_CONT_BCO_info, CCS_MAIN);
+ } else {
+ SET_HDR(bco, stg_BCO_info, CCS_MAIN);
+ }
StgBCO_instrs(bco) = instrs;
StgBCO_literals(bco) = literals;
=====================================
rts/Printer.c
=====================================
@@ -690,6 +690,8 @@ printStackChunk( StgPtr sp, StgPtr spBottom )
debugBelch("stg_ctoi_V_info" );
} else if (c == (StgWord)&stg_BCO_info) {
debugBelch("stg_BCO_info" );
+ } else if (c == (StgWord)&stg_CASE_CONT_BCO_info) {
+ debugBelch("stg_CASE_CONT_BCO_info" );
} else if (c == (StgWord)&stg_apply_interp_info) {
debugBelch("stg_apply_interp_info" );
} else if (c == (StgWord)&stg_ret_t_info) {
=====================================
rts/RtsSymbols.c
=====================================
@@ -639,7 +639,7 @@ extern char **environ;
SymI_HasDataProto(stg_copySmallMutableArrayzh) \
SymI_HasDataProto(stg_casSmallArrayzh) \
SymI_HasDataProto(stg_copyArray_barrier) \
- SymI_HasDataProto(stg_newBCOzh) \
+ SymI_HasDataProto(stg_newBCO2zh) \
SymI_HasDataProto(stg_newByteArrayzh) \
SymI_HasDataProto(stg_casIntArrayzh) \
SymI_HasDataProto(stg_casInt8Arrayzh) \
=====================================
rts/StgMiscClosures.cmm
=====================================
@@ -464,6 +464,12 @@ INFO_TABLE_RET( stg_dead_thread, RET_SMALL,
/* ----------------------------------------------------------------------------
Entry code for a BCO
+
+ `stg_BCO` and `stg_CASE_CONT_BCO` distinguish between a BCO that refers to
+ non-local variables in its code (using a stack offset) and those that do not.
+ Only case-continuation BCOs should use non-local variables.
+ Otherwise, `stg_BCO` and `stg_CASE_CONT_BCO` behave the same.
+ See Note [Case continuation BCOs].
------------------------------------------------------------------------- */
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 )
jump stg_yield_to_interpreter [];
}
+INFO_TABLE_FUN( stg_CASE_CONT_BCO, 3, 0, BCO, "BCO", "BCO", 0, ARG_BCO )
+{
+ /* Exactly as for stg_BCO */
+ Sp_adj(-2);
+ Sp(1) = R1;
+ Sp(0) = stg_apply_interp_info;
+ jump stg_yield_to_interpreter [];
+}
+
/* ----------------------------------------------------------------------------
Info tables for indirections.
=====================================
rts/include/stg/MiscClosures.h
=====================================
@@ -180,6 +180,7 @@ RTS_ENTRY(stg_BLOCKING_QUEUE_CLEAN);
RTS_ENTRY(stg_BLOCKING_QUEUE_DIRTY);
RTS_FUN(stg_BCO);
+RTS_FUN(stg_CASE_CONT_BCO);
RTS_ENTRY(stg_EVACUATED);
RTS_ENTRY(stg_WEAK);
RTS_ENTRY(stg_DEAD_WEAK);
@@ -577,7 +578,7 @@ RTS_FUN_DECL(stg_deRefWeakzh);
RTS_FUN_DECL(stg_runRWzh);
-RTS_FUN_DECL(stg_newBCOzh);
+RTS_FUN_DECL(stg_newBCO2zh);
RTS_FUN_DECL(stg_mkApUpd0zh);
RTS_FUN_DECL(stg_retryzh);
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5cb4a42f690d13d3f1424913691be558...
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5cb4a42f690d13d3f1424913691be558...
You're receiving this email because of your account on gitlab.haskell.org.