Rodrigo Mesquita pushed to branch wip/romes/top-level-bcos-tag at Glasgow Haskell Compiler / GHC
Commits:
-
0784224f
by Rodrigo Mesquita at 2025-05-21T18:56:32+01:00
3 changed files:
Changes:
| ... | ... | @@ -173,11 +173,80 @@ newtype AddrPtr = AddrPtr (RemotePtr ()) |
| 173 | 173 | --------------------------------------------------------------------------------
|
| 174 | 174 | |
| 175 | 175 | Note [Case continuation BCOs]
|
| 176 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 177 | - |
|
| 176 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 177 | + |
|
| 178 | +Consider the following stack with a BCO stack frame at the top:
|
|
| 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 code for a BCO heap object makes use of arguments and free variables which
|
|
| 208 | +can typically be found within the BCO stack frame. In the code, these variables
|
|
| 209 | +are referenced via a statically known stack offset (tracked using `BCEnv` in
|
|
| 210 | +`StgToByteCode`).
|
|
| 211 | + |
|
| 212 | +However, in /case continuation/ BCOs, the code may additionally refer to free
|
|
| 213 | +variables that are outside of the BCO's stack frame. Instead, some free
|
|
| 214 | +variables of a case continuation BCO may only be found in the stack frame of a
|
|
| 215 | +parent BCO:
|
|
| 216 | + |
|
| 217 | + f x y = case x of ... -> ... y ...
|
|
| 218 | + |
|
| 219 | + ==>
|
|
| 220 | + |
|
| 221 | + <ParentBCOFrame>
|
|
| 222 | + ...
|
|
| 223 | + <CaseContinuationBCOFrame>
|
|
| 224 | + |
|
| 225 | +Similarly, references to these non-local/out-of-frame variables are done in
|
|
| 226 | +terms of stack offsets, but they rely on the position of another frame to be fixed.
|
|
| 227 | +(See Note [PUSH_L underflow] for more information about references to previous frames and nested BCOs)
|
|
| 228 | + |
|
| 229 | +TODO
|
|
| 230 | + |
|
| 231 | +to arguments or free variables in
|
|
| 232 | +the stack using a stack pointer offset .
|
|
| 233 | + |
|
| 234 | +A BCO closure is typically headed by the stg_BCO info table pointer.
|
|
| 235 | +...
|
|
| 236 | + |
|
| 237 | +A BCO can be constructed using the stg_BCO info table, OR using the stg
|
|
| 178 | 238 | Does the BCO code depend on stack-pointer-relative offsets?
|
| 179 | 239 | ... why
|
| 180 | 240 | ... example
|
| 241 | + |
|
| 242 | +...
|
|
| 243 | + |
|
| 244 | + <parentBCOFrame>
|
|
| 245 | + ...
|
|
| 246 | + <inserted>
|
|
| 247 | + ...
|
|
| 248 | + <childBCOFrame>
|
|
| 249 | + |
|
| 181 | 250 | -}
|
| 182 | 251 | |
| 183 | 252 | data UnlinkedBCO
|
| ... | ... | @@ -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));
|
| ... | ... | @@ -469,6 +469,7 @@ INFO_TABLE_RET( stg_dead_thread, RET_SMALL, |
| 469 | 469 | non-local variables in its code (using a stack offset) and those that do not.
|
| 470 | 470 | Only case-continuation BCOs should use non-local variables.
|
| 471 | 471 | Otherwise, `stg_BCO` and `stg_CASE_CONT_BCO` behave the same.
|
| 472 | + See Note [Case continuation BCOs].
|
|
| 472 | 473 | ------------------------------------------------------------------------- */
|
| 473 | 474 | |
| 474 | 475 | INFO_TABLE_FUN( stg_BCO, 3, 0, BCO, "BCO", "BCO", 0, ARG_BCO )
|