Simon Jakobi pushed to branch wip/sjakobi/mr16259 at Glasgow Haskell Compiler / GHC

Commits:

8 changed files:

Changes:

  • compiler/GHC/StgToCmm.hs
    ... ... @@ -382,9 +382,11 @@ cgDataCon mn data_con
    382 382
                    ; tickyReturnOldCon (length arg_reps)
    
    383 383
                    -- A taggable (small-family) normal form should never be entered:
    
    384 384
                    -- every reference to it carries the constructor's pointer tag, so
    
    385
    -               -- reaching this entry code is an invariant violation. We report it
    
    386
    -               -- (aborting under +RTS --fatal-enter-taggable, otherwise warning once)
    
    387
    -               -- and then self-return the value tagged with the constructor tag.
    
    385
    +               -- reaching this entry code is an invariant violation. We jump to
    
    386
    +               -- a shared RTS stub that reports it (aborting under +RTS
    
    387
    +               -- --fatal-enter-taggable, otherwise warning once) and self-returns
    
    388
    +               -- the value tagged with the constructor tag; sharing the stub keeps
    
    389
    +               -- the per-constructor entry code to a single tail-jump.
    
    388 390
                    -- Larger families have no spare tag, so their values are entered
    
    389 391
                    -- as normal and the entry returns them tagged with the
    
    390 392
                    -- family-saturating tag.
    
    ... ... @@ -392,9 +394,9 @@ cgDataCon mn data_con
    392 394
                    -- LDV profiling relies on it to mark closures as used (ENTER()
    
    393 395
                    -- in rts/include/Cmm.h does not shortcut on the tag), so the
    
    394 396
                    -- check would fire on every constructor use.
    
    395
    -               ; when (taggable && not (profileIsProfiling profile)) $
    
    396
    -                   emitCheckEnteredTaggable (showPprUnsafe data_con)
    
    397
    -               ; void $ emitReturn
    
    398
    -                   [cmmOffsetB platform node (fromDynTag (tagForCon platform data_con))]
    
    397
    +               ; if taggable && not (profileIsProfiling profile)
    
    398
    +                   then emitJumpEnteredTaggable node
    
    399
    +                   else void $ emitReturn
    
    400
    +                     [cmmOffsetB platform node (fromDynTag (tagForCon platform data_con))]
    
    399 401
                    }
    
    400 402
             }

  • compiler/GHC/StgToCmm/Utils.hs
    ... ... @@ -10,7 +10,7 @@
    10 10
     module GHC.StgToCmm.Utils (
    
    11 11
             emitDataLits, emitRODataLits,
    
    12 12
             emitDataCon,
    
    13
    -        emitRtsCall, emitRtsCallWithResult, emitRtsCallGen, emitCheckEnteredTaggable,
    
    13
    +        emitRtsCall, emitRtsCallWithResult, emitRtsCallGen, emitJumpEnteredTaggable,
    
    14 14
             emitBarf,
    
    15 15
             assignTemp, newTemp,
    
    16 16
     
    
    ... ... @@ -193,11 +193,16 @@ emitBarf msg = do
    193 193
     -- Call from a taggable normal form's entry code (which the pointer-tagging
    
    194 194
     -- invariant makes unreachable). It aborts under +RTS --fatal-enter-taggable and
    
    195 195
     -- otherwise warns once; the entry then self-returns the tagged value.
    
    196
    -emitCheckEnteredTaggable :: String -> FCode ()
    
    197
    -emitCheckEnteredTaggable con = do
    
    198
    -  strLbl <- newStringCLit con
    
    199
    -  emitRtsCall rtsUnitId (fsLit "checkEnteredTaggable")
    
    200
    -    [(CmmLit strLbl, AddrHint)] False
    
    196
    +-- Tail-jump to the RTS's shared entry code for taggable normal forms
    
    197
    +-- (stg_enteredTaggable in rts/StgMiscClosures.cmm), which reports the
    
    198
    +-- invariant violation and self-returns the value tagged with its
    
    199
    +-- constructor tag (both derived from the info table).
    
    200
    +emitJumpEnteredTaggable :: CmmExpr -> FCode ()
    
    201
    +emitJumpEnteredTaggable node = do
    
    202
    +  profile   <- getProfile
    
    203
    +  updfr_off <- getUpdFrameOff
    
    204
    +  let lbl = mkCmmCodeLabel rtsUnitId (fsLit "stg_enteredTaggable")
    
    205
    +  emit (mkJump profile NativeNodeCall (CmmLit (CmmLabel lbl)) [node] updfr_off)
    
    201 206
     
    
    202 207
     emitRtsCall :: UnitId -> FastString -> [(CmmExpr,ForeignHint)] -> Bool -> FCode ()
    
    203 208
     emitRtsCall pkg fun = emitRtsCallGen [] (mkCmmCodeLabel pkg fun) CmmMayReturn
    

  • rts/RtsMessages.c
    ... ... @@ -98,6 +98,16 @@ checkEnteredTaggable(const char *con)
    98 98
       }
    
    99 99
     }
    
    100 100
     
    
    101
    +// Backing for stg_enteredTaggable (StgMiscClosures.cmm), the shared entry
    
    102
    +// code of taggable normal forms: report the violation and hand back the
    
    103
    +// pointer retagged with its constructor tag so the entry can self-return.
    
    104
    +StgClosure *
    
    105
    +enteredTaggableClosure(StgClosure *p)
    
    106
    +{
    
    107
    +  checkEnteredTaggable(GET_CON_DESC(get_con_itbl(p)));
    
    108
    +  return tagConstr(p);
    
    109
    +}
    
    110
    +
    
    101 111
     void
    
    102 112
     _assertFail(const char*filename, unsigned int linenum)
    
    103 113
     {
    

  • rts/RtsSymbols.c
    ... ... @@ -542,7 +542,7 @@ extern char **environ;
    542 542
           SymI_HasProto(barf)                                               \
    
    543 543
           SymI_HasProto(sbarf)                                              \
    
    544 544
           SymI_HasProto(ssbarf)                                             \
    
    545
    -      SymI_HasProto(checkEnteredTaggable)                               \
    
    545
    +      SymI_HasProto(stg_enteredTaggable)                                \
    
    546 546
           SymI_HasProto(tagClosureIfConstr)                                 \
    
    547 547
           SymI_HasProto(startEventLogging)                                  \
    
    548 548
           SymI_HasProto(endEventLogging)                                    \
    

  • rts/StgMiscClosures.cmm
    ... ... @@ -103,6 +103,19 @@ INFO_TABLE_RET (stg_restore_cccs_eval, RET_SMALL, W_ info_ptr, W_ cccs)
    103 103
         jump stg_ap_0_fast(ret);
    
    104 104
     }
    
    105 105
     
    
    106
    +/* Shared entry code for taggable normal forms, which the pointer-tagging
    
    107
    +   invariant makes unreachable: every taggable data constructor's entry code
    
    108
    +   tail-jumps here (see cgDataCon in GHC.StgToCmm) instead of carrying its own
    
    109
    +   report call. Reports the violation (aborting under +RTS
    
    110
    +   --fatal-enter-taggable, otherwise warning once) and self-returns the value
    
    111
    +   tagged with its constructor tag; name and tag come from the info table. */
    
    112
    +stg_enteredTaggable (P_ node)
    
    113
    +{
    
    114
    +    P_ tagged;
    
    115
    +    (tagged) = ccall enteredTaggableClosure(node "ptr");
    
    116
    +    return (tagged);
    
    117
    +}
    
    118
    +
    
    106 119
     /* ----------------------------------------------------------------------------
    
    107 120
        Support for the bytecode interpreter.
    
    108 121
        ------------------------------------------------------------------------- */
    

  • rts/include/rts/Messages.h
    ... ... @@ -49,11 +49,15 @@ void pbarf(const char *fmt, void *p)
    49 49
     void ssbarf(const char *fmt, const char *s)
    
    50 50
        STG_NORETURN;
    
    51 51
     
    
    52
    -/* Called from a taggable normal form's entry code (which the pointer-tagging
    
    53
    -   invariant makes unreachable). Aborts under +RTS --fatal-enter-taggable, otherwise
    
    54
    -   warns once and lets the entry self-return the tagged value. */
    
    52
    +/* Report that a taggable normal form was entered (its entry code is
    
    53
    +   unreachable under the pointer-tagging invariant). Aborts under +RTS
    
    54
    +   --fatal-enter-taggable, otherwise warns once. */
    
    55 55
     void checkEnteredTaggable(const char *con);
    
    56 56
     
    
    57
    +/* Backing for stg_enteredTaggable: report the violation and return the
    
    58
    +   closure pointer retagged with its constructor tag. */
    
    59
    +StgClosure *enteredTaggableClosure(StgClosure *p);
    
    60
    +
    
    57 61
     // declared in Rts.h:
    
    58 62
     // extern void _assertFail(const char *filename, unsigned int linenum)
    
    59 63
     //    STG_NORETURN;
    

  • rts/include/stg/MiscClosures.h
    ... ... @@ -477,6 +477,7 @@ RTS_FUN_DECL(stg_raiseIOzh);
    477 477
     RTS_FUN_DECL(stg_paniczh);
    
    478 478
     RTS_FUN_DECL(stg_keepAlivezh);
    
    479 479
     RTS_FUN_DECL(stg_absentErrorzh);
    
    480
    +RTS_FUN_DECL(stg_enteredTaggable);
    
    480 481
     
    
    481 482
     RTS_FUN_DECL(stg_newPromptTagzh);
    
    482 483
     RTS_FUN_DECL(stg_promptzh);
    

  • rts/sm/NonMovingShortcut.c
    ... ... @@ -225,6 +225,15 @@ selectee_changed:
    225 225
                 default:
    
    226 226
                     // Found a value, add the current selector to the chain and
    
    227 227
                     // update it.
    
    228
    +                // Re-establish the pointer tag for an evaluated constructor,
    
    229
    +                // as in eval_thunk_selector (rts/sm/Evac.c): the indirectees
    
    230
    +                // and the origin field installed by update_selector_chain
    
    231
    +                // must carry the tag.
    
    232
    +                ;
    
    233
    +                const StgInfoTable *val_info = get_itbl(val);
    
    234
    +                if (val_info->type >= CONSTR && val_info->type <= CONSTR_NOCAF) {
    
    235
    +                    val = TAG_CLOSURE(stg_min(TAG_MASK, 1 + val_info->srt), val);
    
    236
    +                }
    
    228 237
                     p->payload[0] = chain;
    
    229 238
                     chain = p;
    
    230 239
                     update_selector_chain(chain, origin, p0, val);