[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 4 commits: rts: handle large CONSTR closures in compacting GC
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: f422f793 by Luite Stegeman at 2026-09-15T07:26:15-04:00 rts: handle large CONSTR closures in compacting GC The function update_fwd_large in the compacting GC could run into an unexpected object with the following error: internal error: update_fwd_large: unknown/strange object 1 Closure type 1 is CONSTR. This patch adds cases for CONSTR and CONSTR_NOCAF. This is the same problem as #27434 (large AP closures, fixed by cca0d58963), which missed this case. Fixes #27649 - - - - - fc0ef58a by Luite Stegeman at 2026-09-15T07:26:15-04:00 testsuite: fix T27434 test with compacting GC Ensure that the interpreter is actually run with the compacting GC - - - - - 9c5fac53 by Luite Stegeman at 2026-09-15T07:26:19-04:00 rts: initialise the stack frame header for mask_frame and apply_mask_frame We must leave the stack in consistent state before jumping to mask_frame or apply_mask_frame because they may result. Failing to do so could lead to a crash if there were waiting exceptions. Fixes #27651 - - - - - b1e7f826 by Simon Peyton Jones at 2026-09-15T07:26:27-04:00 Re-introduce the "weird SpecDict" case In this commit commit f80375dd4945350a1d784e436975b48b9c736eaf Author: Simon Peyton Jones <simon.peytonjones@gmail.com> Date: Sun Jun 29 15:26:58 2025 +0100 Refactor of Specialise.hs I removed a test for a dictionary with unbound type variables. This turned out to be wrong; see #27629. So this MR re-introduces it. - - - - - 17 changed files: - + changelog.d/T27629 - + changelog.d/fix-compacting-gc-constr-27649 - + changelog.d/fix-control0-mask-trampoline - compiler/GHC/Core/Opt/Specialise.hs - rts/ContinuationOps.cmm - rts/sm/Compact.c - + testsuite/tests/rts/T27649.hs - + testsuite/tests/rts/T27649.stdout - testsuite/tests/rts/all.T - + testsuite/tests/rts/continuations/T27651.hs - + testsuite/tests/rts/continuations/T27651.stdout - testsuite/tests/rts/continuations/all.T - testsuite/tests/simplCore/should_compile/Makefile - + testsuite/tests/simplCore/should_compile/T27629.hs - + testsuite/tests/simplCore/should_compile/T27629.stderr - + testsuite/tests/simplCore/should_compile/T27629Plugin.hs - testsuite/tests/simplCore/should_compile/all.T Changes: ===================================== changelog.d/T27629 ===================================== @@ -0,0 +1,6 @@ +section: compiler +synopsis: Fix a scoping bug in the type-class specialiser +description: We don't know of any user programs that can trigger this bug + (the repro involves a plugin), so there is no user-visible effect. +mrs: !16603 +issues: #27629 ===================================== changelog.d/fix-compacting-gc-constr-27649 ===================================== @@ -0,0 +1,14 @@ +section: rts +synopsis: Fix "unknown/strange object 1" crash in compacting GC +issues: #27649 +mrs: !16482 + +description { +Fix a crash in the compacting garbage collector when collecting large +data constructor closures, as allocated by the bytecode interpreter for +constructors with several hundred fields. Affected programs (run in GHCi, +or via ``ghc -e`` or ``runghc``) crashed with an internal error of the +form "update_fwd_large: unknown/strange object 1" when run with the +compacting GC (``+RTS -c``, or compaction enabled automatically by a +``-M`` heap limit). +} ===================================== changelog.d/fix-control0-mask-trampoline ===================================== @@ -0,0 +1,13 @@ +section: rts +synopsis: Fix a crash when capturing or resuming a delimited continuation that adjusts the async exception masking state +issues: #27651 +mrs: !16484 + +description: { +Capturing a continuation with ``control0#`` from inside ``mask`` or +``uninterruptibleMask`` left an uninitialised word on the stack while +restoring the masking state. When the thread had a pending asynchronous +exception (e.g. from ``throwTo``), raising it walked over that word and +crashed with a segmentation fault. Resuming such a continuation had the +same defect. +} ===================================== compiler/GHC/Core/Opt/Specialise.hs ===================================== @@ -1713,9 +1713,7 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs ; let spec_rhs_bndrs = spec_bndrs ++ inner_rhs_bndrs' (rhs_uds2, inner_dumped_dbs) = dumpUDs spec_rhs_bndrs $ dx_binds `consDictBinds` rhs_uds - -- dx_binds comes from the arguments to the call, - -- and so can mention poly_qvars but no other local binders - spec_rhs = mkLams spec_rhs_bndrs $ + spec_rhs = mkLams spec_rhs_bndrs $ wrapDictBindsE inner_dumped_dbs rhs_body' rule_rhs_args = spec_bndrs @@ -1784,8 +1782,7 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs , text "rule_act" <+> ppr rule_act ] --- ; pprTrace "spec_call: rule" (vcat [ -- text "poly_qvars" <+> ppr poly_qvars --- text "rule_bndrs" <+> ppr rule_bndrs +-- ; pprTrace "spec_call: rule" (vcat [ text "rule_bndrs" <+> ppr rule_bndrs -- , text "rule_lhs_args" <+> ppr rule_lhs_args -- , text "all_call_args" <+> ppr all_call_args -- , ppr spec_rule ]) $ @@ -2611,6 +2608,17 @@ specHeader subst (bndr:bndrs) (UnspecType : args) -- a wildcard binder to match the dictionary (See Note [Specialising Calls] for -- the nitty-gritty), as a LHS rule and unfolding details. specHeader subst (bndr:bndrs) (SpecDict dict_arg : args) + | let in_scope = getInScopeVars (substInScopeSet subst) + bad_dict_fv v = isLocalVar v && not (v `elemVarSet` in_scope) + , not $ isEmptyVarSet $ exprSomeFreeVars bad_dict_fv dict_arg + = -- Do not specialise if `dict_arg` has any free vars that are /not/ in scope + -- See Note [Weird special case for SpecDict] + -- We add a warnPprTrace because this should be super-rare, + -- so if it starts happening we'd like to know. + warnPprTrace True "Specialise: weird dictionary with free type variable" (ppr dict_arg) $ + specHeader subst (bndr:bndrs) (UnspecArg : args) + + | otherwise = do { -- Make up a fresh binder to use in the RULE -- It might turn into a dict binding (via bindAuxiliaryDict) which we -- then float, so we use cloneIdBndr to get a completely fresh binder @@ -2886,13 +2894,15 @@ We could zap `k` to (Any @Type) and `a` to (Any @(Any @Type)), but that is a lot of hard work for a very strange case. So we simply refrain from specialising in this case; hence the guard - allVarSet (`elemInScopeSet` in_scope) (exprFreeVars d) -in the SpecDict cased of specHeader. - -How did this strange polymorphic mkD arise in the first place? -From GHC.Core.Opt.Utils.abstractFloats, which was abstracting -over too many type variables. But that too is now fixed; -see Note [Which type variables to abstract over] in that module. + not $ isEmptyVarSet $ exprSomeFreeVars bad_dict_fv dict_arg +in the SpecDict case of `specHeader`. + +How did this strange polymorphic mkD arise in the first place? From +GHC.Core.Opt.Simplify.Utils.abstractFloats, which was abstracting over too many type +variables. But that too is now fixed; see Note [Which type variables to abstract +over] in that module. So we don't actually have a Haskell source program that +triggers it (see #27629) -- only test T27629 that uses a plugin to inject a strange +definition. -} instance Outputable DictBind where ===================================== rts/ContinuationOps.cmm ===================================== @@ -148,6 +148,7 @@ stg_control0zh_ll // explicit stack // and jump to the frame’s entry code. Sp_adj(-3); // Note -3, not -2, because `mask_frame` will // try to pop itself off the stack when it returns! + Sp(0) = mask_frame; // Can't be omitted, see #27651 Sp(1) = stg_ap_pv_info; Sp(2) = cont; R1 = f; @@ -230,6 +231,7 @@ stg_CONTINUATION_apply // explicit stack // Now we just set up the stack so that `apply_mask_frame` will apply `io` // when it returns and jump to it. Sp_adj(-2); + Sp(0) = apply_mask_frame; // Can't be omitted, see #27651 Sp(1) = stg_ap_v_info; R1 = io; jump %ENTRY_CODE(apply_mask_frame) [R1]; ===================================== rts/sm/Compact.c ===================================== @@ -573,6 +573,13 @@ update_fwd_large( bdescr *bd ) continue; } + case CONSTR: + case CONSTR_NOCAF: + { + thread_obj(info, p); + continue; + } + case MUT_ARR_PTRS_CLEAN: case MUT_ARR_PTRS_DIRTY: case MUT_ARR_PTRS_FROZEN_CLEAN: ===================================== testsuite/tests/rts/T27649.hs ===================================== @@ -0,0 +1,27 @@ +-- Test that the compacting GC can handle large CONSTR closures. +-- +-- The bytecode interpreter allocates data constructors with allocate(), +-- so a constructor with enough fields becomes a large object (BF_LARGE). +-- update_fwd_large in rts/sm/Compact.c must therefore handle CONSTR. +-- This test only exercises the interpreter (ghci way): compiled code +-- bump-allocates constructors in the nursery and never hits this path. +module Main where + +import System.Mem (performMajorGC) +import Control.Monad (forM, forM_) + +data Big = Big Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int + +{-# NOINLINE mkBig #-} +mkBig :: Int -> Big +mkBig seed = Big (seed + 0) (seed + 1) (seed + 2) (seed + 3) (seed + 4) (seed + 5) (seed + 6) (seed + 7) (seed + 8) (seed + 9) (seed + 10) (seed + 11) (seed + 12) (seed + 13) (seed + 14) (seed + 15) (seed + 16) (seed + 17) (seed + 18) (seed + 19) (seed + 20) (seed + 21) (seed + 22) (seed + 23) (seed + 24) (seed + 25) (seed + 26) (seed + 27) (seed + 28) (seed + 29) (seed + 30) (seed + 31) (seed + 32) (seed + 33) (seed + 34) (seed + 35) (seed + 36) (seed + 37) (seed + 38) (seed + 39) (seed + 40) (seed + 41) (seed + 42) (seed + 43) (seed + 44) (seed + 45) (seed + 46) (seed + 47) (seed + 48) (seed + 49) (seed + 50) (seed + 51) (seed + 52) (seed + 53) (seed + 54) (seed + 55) (seed + 56) (seed + 57) (seed + 58) (seed + 59) (seed + 60) (seed + 61) (seed + 62) (seed + 63) (seed + 64) (seed + 65) (seed + 66) (seed + 67) (seed + 68) (seed + 69) (seed + 70) (seed + 71) (seed + 72) (seed + 73) (seed + 74) (seed + 75) (seed + 76) (seed + 77) (seed + 78) (seed + 79) (seed + 80) (seed + 81) (seed + 82) (seed + 83) (seed + 84) (seed + 85) (seed + 86) (seed + 87) (seed + 88) (seed + 89) (seed + 90) (seed + 91) (seed + 92) (seed + 93) (seed + 94) (seed + 95) (seed + 96) (seed + 97) (seed + 98) (seed + 99) (seed + 100) (seed + 101) (seed + 102) (seed + 103) (seed + 104) (seed + 105) (seed + 106) (seed + 107) (seed + 108) (seed + 109) (seed + 110) (seed + 111) (seed + 112) (seed + 113) (seed + 114) (seed + 115) (seed + 116) (seed + 117) (seed + 118) (seed + 119) (seed + 120) (seed + 121) (seed + 122) (seed + 123) (seed + 124) (seed + 125) (seed + 126) (seed + 127) (seed + 128) (seed + 129) (seed + 130) (seed + 131) (seed + 132) (seed + 133) (seed + 134) (seed + 135) (seed + 136) (seed + 137) (seed + 138) (seed + 139) (seed + 140) (seed + 141) (seed + 142) (seed + 143) (seed + 144) (seed + 145) (seed + 146) (seed + 147) (seed + 148) (seed + 149) (seed + 150) (seed + 151) (seed + 152) (seed + 153) (seed + 154) (seed + 155) (seed + 156) (seed + 157) (seed + 158) (seed + 159) (seed + 160) (seed + 161) (seed + 162) (seed + 163) (seed + 164) (seed + 165) (seed + 166) (seed + 167) (seed + 168) (seed + 169) (seed + 170) (seed + 171) (seed + 172) (seed + 173) (seed + 174) (seed + 175) (seed + 176) (seed + 177) (seed + 178) (seed + 179) (seed + 180) (seed + 181) (seed + 182) (seed + 183) (seed + 184) (seed + 185) (seed + 186) (seed + 187) (seed + 188) (seed + 189) (seed + 190) (seed + 191) (seed + 192) (seed + 193) (seed + 194) (seed + 195) (seed + 196) (seed + 197) (seed + 198) (seed + 199) (seed + 200) (seed + 201) (seed + 202) (seed + 203) (seed + 204) (seed + 205) (seed + 206) (seed + 207) (seed + 208) (seed + 209) (seed + 210) (seed + 211) (seed + 212) (seed + 213) (seed + 214) (seed + 215) (seed + 216) (seed + 217) (seed + 218) (seed + 219) (seed + 220) (seed + 221) (seed + 222) (seed + 223) (seed + 224) (seed + 225) (seed + 226) (seed + 227) (seed + 228) (seed + 229) (seed + 230) (seed + 231) (seed + 232) (seed + 233) (seed + 234) (seed + 235) (seed + 236) (seed + 237) (seed + 238) (seed + 239) (seed + 240) (seed + 241) (seed + 242) (seed + 243) (seed + 244) (seed + 245) (seed + 246) (seed + 247) (seed + 248) (seed + 249) (seed + 250) (seed + 251) (seed + 252) (seed + 253) (seed + 254) (seed + 255) (seed + 256) (seed + 257) (seed + 258) (seed + 259) (seed + 260) (seed + 261) (seed + 262) (seed + 263) (seed + 264) (seed + 265) (seed + 266) (seed + 267) (seed + 268) (seed + 269) (seed + 270) (seed + 271) (seed + 272) (seed + 273) (seed + 274) (seed + 275) (seed + 276) (seed + 277) (seed + 278) (seed + 279) (seed + 280) (seed + 281) (seed + 282) (seed + 283) (seed + 284) (seed + 285) (seed + 286) (seed + 287) (seed + 288) (seed + 289) (seed + 290) (seed + 291) (seed + 292) (seed + 293) (seed + 294) (seed + 295) (seed + 296) (seed + 297) (seed + 298) (seed + 299) (seed + 300) (seed + 301) (seed + 302) (seed + 303) (seed + 304) (seed + 305) (seed + 306) (seed + 307) (seed + 308) (seed + 309) (seed + 310) (seed + 311) (seed + 312) (seed + 313) (seed + 314) (seed + 315) (seed + 316) (seed + 317) (seed + 318) (seed + 319) (seed + 320) (seed + 321) (seed + 322) (seed + 323) (seed + 324) (seed + 325) (seed + 326) (seed + 327) (seed + 328) (seed + 329) (seed + 330) (seed + 331) (seed + 332) (seed + 333) (seed + 334) (seed + 335) (seed + 336) (seed + 337) (seed + 338) (seed + 339) (seed + 340) (seed + 341) (seed + 342) (seed + 343) (seed + 344) (seed + 345) (seed + 346) (seed + 347) (seed + 348) (seed + 349) (seed + 350) (seed + 351) (seed + 352) (seed + 353) (seed + 354) (seed + 355) (seed + 356) (seed + 357) (seed + 358) (seed + 359) (seed + 360) (seed + 361) (seed + 362) (seed + 363) (seed + 364) (seed + 365) (seed + 366) (seed + 367) (seed + 368) (seed + 369) (seed + 370) (seed + 371) (seed + 372) (seed + 373) (seed + 374) (seed + 375) (seed + 376) (seed + 377) (seed + 378) (seed + 379) (seed + 380) (seed + 381) (seed + 382) (seed + 383) (seed + 384) (seed + 385) (seed + 386) (seed + 387) (seed + 388) (seed + 389) (seed + 390) (seed + 391) (seed + 392) (seed + 393) (seed + 394) (seed + 395) (seed + 396) (seed + 397) (seed + 398) (seed + 399) (seed + 400) (seed + 401) (seed + 402) (seed + 403) (seed + 404) (seed + 405) (seed + 406) (seed + 407) (seed + 408) (seed + 409) (seed + 410) (seed + 411) (seed + 412) (seed + 413) (seed + 414) (seed + 415) (seed + 416) (seed + 417) (seed + 418) (seed + 419) (seed + 420) (seed + 421) (seed + 422) (seed + 423) (seed + 424) (seed + 425) (seed + 426) (seed + 427) (seed + 428) (seed + 429) (seed + 430) (seed + 431) (seed + 432) (seed + 433) (seed + 434) (seed + 435) (seed + 436) (seed + 437) (seed + 438) (seed + 439) (seed + 440) (seed + 441) (seed + 442) (seed + 443) (seed + 444) (seed + 445) (seed + 446) (seed + 447) (seed + 448) (seed + 449) (seed + 450) (seed + 451) (seed + 452) (seed + 453) (seed + 454) (seed + 455) (seed + 456) (seed + 457) (seed + 458) (seed + 459) (seed + 460) (seed + 461) (seed + 462) (seed + 463) (seed + 464) (seed + 465) (seed + 466) (seed + 467) (seed + 468) (seed + 469) (seed + 470) (seed + 471) (seed + 472) (seed + 473) (seed + 474) (seed + 475) (seed + 476) (seed + 477) (seed + 478) (seed + 479) (seed + 480) (seed + 481) (seed + 482) (seed + 483) (seed + 484) (seed + 485) (seed + 486) (seed + 487) (seed + 488) (seed + 489) (seed + 490) (seed + 491) (seed + 492) (seed + 493) (seed + 494) (seed + 495) (seed + 496) (seed + 497) (seed + 498) (seed + 499) + +sumBig :: Big -> Int +sumBig (Big a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22 a23 a24 a25 a26 a27 a28 a29 a30 a31 a32 a33 a34 a35 a36 a37 a38 a39 a40 a41 a42 a43 a44 a45 a46 a47 a48 a49 a50 a51 a52 a53 a54 a55 a56 a57 a58 a59 a60 a61 a62 a63 a64 a65 a66 a67 a68 a69 a70 a71 a72 a73 a74 a75 a76 a77 a78 a79 a80 a81 a82 a83 a84 a85 a86 a87 a88 a89 a90 a91 a92 a93 a94 a95 a96 a97 a98 a99 a100 a101 a102 a103 a104 a105 a106 a107 a108 a109 a110 a111 a112 a113 a114 a115 a116 a117 a118 a119 a120 a121 a122 a123 a124 a125 a126 a127 a128 a129 a130 a131 a132 a133 a134 a135 a136 a137 a138 a139 a140 a141 a142 a143 a144 a145 a146 a147 a148 a149 a150 a151 a152 a153 a154 a155 a156 a157 a158 a159 a160 a161 a162 a163 a164 a165 a166 a167 a168 a169 a170 a171 a172 a173 a174 a175 a176 a177 a178 a179 a180 a181 a182 a183 a184 a185 a186 a187 a188 a189 a190 a191 a192 a193 a194 a195 a196 a197 a198 a199 a200 a201 a202 a203 a204 a205 a206 a207 a208 a209 a210 a211 a212 a213 a214 a215 a216 a217 a218 a219 a220 a221 a222 a223 a224 a225 a226 a227 a228 a229 a230 a231 a232 a233 a234 a235 a236 a237 a238 a239 a240 a241 a242 a243 a244 a245 a246 a247 a248 a249 a250 a251 a252 a253 a254 a255 a256 a257 a258 a259 a260 a261 a262 a263 a264 a265 a266 a267 a268 a269 a270 a271 a272 a273 a274 a275 a276 a277 a278 a279 a280 a281 a282 a283 a284 a285 a286 a287 a288 a289 a290 a291 a292 a293 a294 a295 a296 a297 a298 a299 a300 a301 a302 a303 a304 a305 a306 a307 a308 a309 a310 a311 a312 a313 a314 a315 a316 a317 a318 a319 a320 a321 a322 a323 a324 a325 a326 a327 a328 a329 a330 a331 a332 a333 a334 a335 a336 a337 a338 a339 a340 a341 a342 a343 a344 a345 a346 a347 a348 a349 a350 a351 a352 a353 a354 a355 a356 a357 a358 a359 a360 a361 a362 a363 a364 a365 a366 a367 a368 a369 a370 a371 a372 a373 a374 a375 a376 a377 a378 a379 a380 a381 a382 a383 a384 a385 a386 a387 a388 a389 a390 a391 a392 a393 a394 a395 a396 a397 a398 a399 a400 a401 a402 a403 a404 a405 a406 a407 a408 a409 a410 a411 a412 a413 a414 a415 a416 a417 a418 a419 a420 a421 a422 a423 a424 a425 a426 a427 a428 a429 a430 a431 a432 a433 a434 a435 a436 a437 a438 a439 a440 a441 a442 a443 a444 a445 a446 a447 a448 a449 a450 a451 a452 a453 a454 a455 a456 a457 a458 a459 a460 a461 a462 a463 a464 a465 a466 a467 a468 a469 a470 a471 a472 a473 a474 a475 a476 a477 a478 a479 a480 a481 a482 a483 a484 a485 a486 a487 a488 a489 a490 a491 a492 a493 a494 a495 a496 a497 a498 a499) = a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20 + a21 + a22 + a23 + a24 + a25 + a26 + a27 + a28 + a29 + a30 + a31 + a32 + a33 + a34 + a35 + a36 + a37 + a38 + a39 + a40 + a41 + a42 + a43 + a44 + a45 + a46 + a47 + a48 + a49 + a50 + a51 + a52 + a53 + a54 + a55 + a56 + a57 + a58 + a59 + a60 + a61 + a62 + a63 + a64 + a65 + a66 + a67 + a68 + a69 + a70 + a71 + a72 + a73 + a74 + a75 + a76 + a77 + a78 + a79 + a80 + a81 + a82 + a83 + a84 + a85 + a86 + a87 + a88 + a89 + a90 + a91 + a92 + a93 + a94 + a95 + a96 + a97 + a98 + a99 + a100 + a101 + a102 + a103 + a104 + a105 + a106 + a107 + a108 + a109 + a110 + a111 + a112 + a113 + a114 + a115 + a116 + a117 + a118 + a119 + a120 + a121 + a122 + a123 + a124 + a125 + a126 + a127 + a128 + a129 + a130 + a131 + a132 + a133 + a134 + a135 + a136 + a137 + a138 + a139 + a140 + a141 + a142 + a143 + a144 + a145 + a146 + a147 + a148 + a149 + a150 + a151 + a152 + a153 + a154 + a155 + a156 + a157 + a158 + a159 + a160 + a161 + a162 + a163 + a164 + a165 + a166 + a167 + a168 + a169 + a170 + a171 + a172 + a173 + a174 + a175 + a176 + a177 + a178 + a179 + a180 + a181 + a182 + a183 + a184 + a185 + a186 + a187 + a188 + a189 + a190 + a191 + a192 + a193 + a194 + a195 + a196 + a197 + a198 + a199 + a200 + a201 + a202 + a203 + a204 + a205 + a206 + a207 + a208 + a209 + a210 + a211 + a212 + a213 + a214 + a215 + a216 + a217 + a218 + a219 + a220 + a221 + a222 + a223 + a224 + a225 + a226 + a227 + a228 + a229 + a230 + a231 + a232 + a233 + a234 + a235 + a236 + a237 + a238 + a239 + a240 + a241 + a242 + a243 + a244 + a245 + a246 + a247 + a248 + a249 + a250 + a251 + a252 + a253 + a254 + a255 + a256 + a257 + a258 + a259 + a260 + a261 + a262 + a263 + a264 + a265 + a266 + a267 + a268 + a269 + a270 + a271 + a272 + a273 + a274 + a275 + a276 + a277 + a278 + a279 + a280 + a281 + a282 + a283 + a284 + a285 + a286 + a287 + a288 + a289 + a290 + a291 + a292 + a293 + a294 + a295 + a296 + a297 + a298 + a299 + a300 + a301 + a302 + a303 + a304 + a305 + a306 + a307 + a308 + a309 + a310 + a311 + a312 + a313 + a314 + a315 + a316 + a317 + a318 + a319 + a320 + a321 + a322 + a323 + a324 + a325 + a326 + a327 + a328 + a329 + a330 + a331 + a332 + a333 + a334 + a335 + a336 + a337 + a338 + a339 + a340 + a341 + a342 + a343 + a344 + a345 + a346 + a347 + a348 + a349 + a350 + a351 + a352 + a353 + a354 + a355 + a356 + a357 + a358 + a359 + a360 + a361 + a362 + a363 + a364 + a365 + a366 + a367 + a368 + a369 + a370 + a371 + a372 + a373 + a374 + a375 + a376 + a377 + a378 + a379 + a380 + a381 + a382 + a383 + a384 + a385 + a386 + a387 + a388 + a389 + a390 + a391 + a392 + a393 + a394 + a395 + a396 + a397 + a398 + a399 + a400 + a401 + a402 + a403 + a404 + a405 + a406 + a407 + a408 + a409 + a410 + a411 + a412 + a413 + a414 + a415 + a416 + a417 + a418 + a419 + a420 + a421 + a422 + a423 + a424 + a425 + a426 + a427 + a428 + a429 + a430 + a431 + a432 + a433 + a434 + a435 + a436 + a437 + a438 + a439 + a440 + a441 + a442 + a443 + a444 + a445 + a446 + a447 + a448 + a449 + a450 + a451 + a452 + a453 + a454 + a455 + a456 + a457 + a458 + a459 + a460 + a461 + a462 + a463 + a464 + a465 + a466 + a467 + a468 + a469 + a470 + a471 + a472 + a473 + a474 + a475 + a476 + a477 + a478 + a479 + a480 + a481 + a482 + a483 + a484 + a485 + a486 + a487 + a488 + a489 + a490 + a491 + a492 + a493 + a494 + a495 + a496 + a497 + a498 + a499 + +main :: IO () +main = do + bigs <- forM [1..100] (return . mkBig) + performMajorGC + forM_ [1..3] (const performMajorGC) + print (sum (map sumBig bigs)) ===================================== testsuite/tests/rts/T27649.stdout ===================================== @@ -0,0 +1 @@ +15000000 ===================================== testsuite/tests/rts/all.T ===================================== @@ -699,8 +699,20 @@ test('resizeMutableByteArrayInPlace', [req_cmm, extra_ways(['optasm', 'sanity']) test('T27123', [when(have_profiling(), extra_ways(['prof']))], compile_and_run, ['-O']) +# T27434 and T27649 test the compacting GC on large closures (AP and +# CONSTR respectively) that only the bytecode interpreter allocates, so +# they must run in the ghci way. In the ghci way extra_run_opts only +# sets the interpreted program's argv (via :set args), so enable +# compaction with GHCRTS to make it reach the RTS of the GHCi process +# itself (#27615). test('T27434', - extra_ways(['compacting_gc']), + [only_ways(['ghci']), + cmd_prefix('GHCRTS=-c ')], + compile_and_run, ['']) + +test('T27649', + [only_ways(['ghci']), + cmd_prefix('GHCRTS=-c ')], compile_and_run, ['']) test('T19048', ===================================== testsuite/tests/rts/continuations/T27651.hs ===================================== @@ -0,0 +1,91 @@ +-- When capturing or resuming a continuation adjusts the async exception +-- masking state, the RTS trampolines through a mask/unmask frame, and the +-- stack must be well-formed at that point: with a blocked exception +-- pending, the eager raise in stg_unmaskAsyncExceptionszh_ret walks the +-- whole stack. +-- +-- Phase 1 exercises the capture side (stg_control0zh_ll): control0# runs +-- inside uninterruptibleMask_ while another thread has queued an +-- exception via throwTo, so the capture unmasks with the exception +-- pending. The frame evaluated between the unmask frame and the prompt +-- keeps raw Int# payload live so that a stale word on the stack cannot +-- masquerade as a valid frame by accident. +-- +-- Phase 2 exercises the resume side (stg_CONTINUATION_apply): the +-- continuation is captured while unmasked (inside mask/restore), so +-- resuming it unmasks, and it is applied from a thread that is masked +-- with an exception pending. +import Control.Concurrent +import Control.Exception +import Control.Monad + +import ContIO + +data Boom = Boom deriving Show +instance Exception Boom + +{-# NOINLINE useInts #-} +useInts :: Int -> Int -> Int -> Int -> Int -> Int +useInts a b c d e = a + b * c + d * e + +rounds :: Int +rounds = 150 + +phase1 :: Int -> IO () +phase1 i = do + mv <- newEmptyMVar + done <- newEmptyMVar + let !p = i * 7919 + 3 -- raw ints to live in the continuation frame + !q = i * 104729 + 7 + !u = i * 1299709 + 11 + !v = i * 15485863 + 13 + a <- forkIO $ + handle (\Boom -> void (tryPutMVar done (Left Boom))) $ do + tag <- newPromptTag + r <- prompt tag $ do + x <- uninterruptibleMask_ $ do + putMVar mv () + threadDelay 2000 -- let the thrower queue its exception + control0 tag (\_k -> pure (42 :: Int)) + -- continuation frame between the unmask frame and the + -- prompt frame, carrying raw Int# payload: + pure (useInts x p q u v) + void (tryPutMVar done (Right r)) + takeMVar mv + _ <- forkIO $ throwTo a Boom + void (takeMVar done) + +phase2 :: Int -> IO () +phase2 i = do + mv <- newEmptyMVar + done <- newEmptyMVar + kvar <- newEmptyMVar + let !p = i * 7919 + 3 + !q = i * 104729 + 7 + !u = i * 1299709 + 11 + !v = i * 15485863 + 13 + -- Capture a continuation whose resumption unmasks: the capture happens + -- inside restore, so its apply_mask_frame is the unmask frame. + _ <- forkIO $ do + tag <- newPromptTag + _ <- prompt tag $ mask $ \restore -> do + x <- restore (control0 tag (\k -> putMVar kvar k >> pure 0)) + pure (useInts x p q u v) + pure () + k <- takeMVar kvar + a <- forkIO $ + handle (\Boom -> void (tryPutMVar done (Left Boom))) $ do + r <- uninterruptibleMask_ $ do + putMVar mv () + threadDelay 2000 -- let the thrower queue its exception + k (pure 42) -- resuming unmasks with the exception pending + void (tryPutMVar done (Right r)) + takeMVar mv + _ <- forkIO $ throwTo a Boom + void (takeMVar done) + +main :: IO () +main = do + forM_ [1 .. rounds] phase1 + forM_ [1 .. rounds] phase2 + putStrLn "ok" ===================================== testsuite/tests/rts/continuations/T27651.stdout ===================================== @@ -0,0 +1 @@ +ok ===================================== testsuite/tests/rts/continuations/all.T ===================================== @@ -9,3 +9,4 @@ test('cont_nondet_handler', [extra_files(['ContIO.hs'])], multimod_compile_and_r test('cont_stack_overflow', [extra_files(['ContIO.hs'])], multimod_compile_and_run, ['cont_stack_overflow', '-with-rtsopts "-ki1k -kc2k -kb256"']) test('T23513', [extra_files(['ContIO.hs'])], multimod_compile_and_run, ['T23513', '']) +test('T27651', [extra_files(['ContIO.hs'])], multimod_compile_and_run, ['T27651', '']) ===================================== testsuite/tests/simplCore/should_compile/Makefile ===================================== @@ -3,6 +3,12 @@ include $(TOP)/mk/boilerplate.mk include $(TOP)/mk/test.mk +# T27629 runs a plugin that injects a Core binding +# that made the specialiser crash +T27629: + '$(TEST_HC)' $(TEST_HC_OPTS) $(ghcPluginWayFlags) --make -package ghc -c T27629Plugin.hs -v0 + '$(TEST_HC)' $(TEST_HC_OPTS) $(ghcPluginWayFlags) -c -O -fpolymorphic-specialisation -dcore-lint T27629.hs + # T18815 should not have a non-recursive join-point for 'go' # Previously we ended up with # join {go_sPI w_sQ3 = case w_sQ3 of { GHC.Types.I# ww1_sQ6 -> ===================================== testsuite/tests/simplCore/should_compile/T27629.hs ===================================== @@ -0,0 +1,29 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# OPTIONS_GHC -fplugin=T27629Plugin #-} + +-- The plugin rewrites 'poly' to the example of +-- Note [Weird special case for SpecDict]: +-- +-- poly = /\x. \t. split @T (mkD @x MkT) [t] +-- +-- where mkD :: forall a. T -> C T is a new top-level binding +-- (mkD = /\a. \_. $fCT), so the tyvar x is free in the dictionary +-- *expression* but not in its *type* (C T). +module T27629 (poly, split, T (..), C (..)) where + +import Data.Kind (Type) + +data T = MkT + +class C b where + meth :: b -> b + +instance C T where + meth x = x + +split :: C b => [b] -> [b] +split [] = [] +split (x : xs) = meth x : split xs + +poly :: forall (x :: Type). T -> [T] +poly t = [t] ===================================== testsuite/tests/simplCore/should_compile/T27629.stderr ===================================== @@ -0,0 +1 @@ +ReproPlugin: injected weird SpecDict call into poly ===================================== testsuite/tests/simplCore/should_compile/T27629Plugin.hs ===================================== @@ -0,0 +1,89 @@ +-- Injects the example of Note [Weird special case for SpecDict] in +-- GHC.Core.Opt.Specialise, which cannot be written in source Haskell: +-- a call whose dictionary argument mentions a type variable that is +-- free in the dictionary expression but not in its type. +-- +-- Runs before the main Core pipeline (in particular before the +-- Specialiser). It adds +-- +-- mkD :: forall a. T -> C T {-# NOINLINE mkD #-} +-- mkD = /\a. \_. $fCT +-- +-- and rewrites poly = /\x. \t. [t] +-- to poly = /\x. \t. split @T (mkD @x MkT) [t] +module T27629Plugin (plugin) where + +import GHC.Core.Make (mkCoreApps, mkListExpr) +import GHC.Core.Predicate (getClassPredTys_maybe) +import GHC.Plugins +import GHC.Types.InlinePragma (neverInlinePragma) + +plugin :: Plugin +plugin = + defaultPlugin + { installCoreToDos = \_ todos -> + return (CoreDoPluginPass "inject-weird-specdict" pass : todos) + , pluginRecompile = purePlugin + } + +pass :: ModGuts -> CoreM ModGuts +pass guts = do + let binds = mg_binds guts + + dfun = case [b | b <- bindersOfBinds binds, isDFunId b] of + (b : _) -> b + [] -> panic "ReproPlugin: no dfun binding in module" + + dictTy = idType dfun -- C T + tyT = case getClassPredTys_maybe dictTy of + Just (_cls, [t]) -> t + _ -> panic "ReproPlugin: dfun type is not C T" + + mkTCon = case tyConDataCons (tyConAppTyCon tyT) of + (dc : _) -> dataConWorkId dc + [] -> panic "ReproPlugin: T has no data constructors" + + findTopId nm = + case [b | b <- bindersOfBinds binds, occNameString (getOccName b) == nm] of + (b : _) -> b + [] -> panic ("ReproPlugin: no top-level binding " ++ nm) + + splitId = findTopId "split" + polyId = findTopId "poly" + + uMkD <- getUniqueM + uTv <- getUniqueM + uWild <- getUniqueM + + let aTv = mkTyVar (mkSystemName uTv (mkTyVarOcc "a")) liftedTypeKind + mkDTy = mkSpecForAllTys [aTv] (mkFunctionType ManyTy tyT dictTy) + mkDId = + setInlinePragma + (mkExportedVanillaId (mkSystemName uMkD (mkVarOcc "mkD")) mkDTy) + neverInlinePragma + wild = mkSysLocal (fsLit "eta") uWild ManyTy tyT + mkDBind = NonRec mkDId (mkLams [aTv, wild] (Var dfun)) + + rewritePoly rhs + | (bndrs, _body) <- collectBinders rhs + , (x : _) <- reverse (filter isTyVar bndrs) + , (t : _) <- filter isId bndrs + = mkLams bndrs $ + mkCoreApps + (Var splitId) + [ Type tyT + , mkCoreApps (Var mkDId) [Type (mkTyVarTy x), Var mkTCon] + , mkListExpr tyT [Var t] + ] + | otherwise = + pprPanic "ReproPlugin: unexpected shape of poly" (ppr rhs) + + go (b, rhs) + | b == polyId = (b, rewritePoly rhs) + | otherwise = (b, rhs) + + -- One top-level Rec, so bind order is irrelevant. + binds' = [Rec (map go (flattenBinds binds) ++ flattenBinds [mkDBind])] + + putMsgS "ReproPlugin: injected weird SpecDict call into poly" + return guts {mg_binds = binds'} ===================================== testsuite/tests/simplCore/should_compile/all.T ===================================== @@ -618,3 +618,5 @@ test('T27556', [only_ways('ghci'), extra_hc_opts('-O -fno-unoptimized-core-for-i test('T27749', multiline_grep_errmsg(r'ordering\n.*\n(\s+src<[^>]*>\n)+'), compile, ['-O -g3 -ddump-simpl -dsuppress-uniques']) + +test('T27629', only_ways(['optasm']), makefile_test, ['T27629']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7113ad52a62ac825310bcba0693d4c4... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7113ad52a62ac825310bcba0693d4c4... You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
participants (1)
-
Marge Bot (@marge-bot)