Ticket #8590: 0001-Move-the-allocation-of-CAF-blackholes-into-newCAF.patch

File 0001-Move-the-allocation-of-CAF-blackholes-into-newCAF.patch, 8.0 KB (added by parcs, 21 months ago)
  • compiler/codeGen/StgCmmBind.hs

    From 9a15fb7c8bd4fb225ed3198e41f86028d364dfec Mon Sep 17 00:00:00 2001
    From: Patrick Palka <[email protected]>
    Date: Sun, 1 Dec 2013 21:17:43 -0500
    Subject: [PATCH] Move the allocation of CAF blackholes into 'newCAF'
    
    We now do the allocation of the blackhole indirection closure inside the
    RTS procedure 'newCAF' instead of generating the allocation code inline
    in the closure body of each CAF.  This slightly decreases code size in
    modules with a lot of CAFs.
    
    As a result of this change, for example, the size of DynFlags.o drops by
    ~60KB and HsExpr.o by ~100KB.
    ---
     compiler/codeGen/StgCmmBind.hs | 40 ++++++++++------------------------------
     includes/rts/storage/GC.h      |  4 ++--
     rts/sm/Storage.c               | 40 +++++++++++++++++++++++++++-------------
     3 files changed, 39 insertions(+), 45 deletions(-)
    
    diff --git a/compiler/codeGen/StgCmmBind.hs b/compiler/codeGen/StgCmmBind.hs
    index 64772c6..05aae0a 100644
    a b import StgCmmEnv 
    2121import StgCmmCon
    2222import StgCmmHeap
    2323import StgCmmProf (curCCS, ldvEnterClosure, enterCostCentreFun, enterCostCentreThunk,
    24                    initUpdFrameProf, costCentreFrom)
     24                   initUpdFrameProf)
    2525import StgCmmTicky
    2626import StgCmmLayout
    2727import StgCmmUtils
    emitUpdateFrame dflags frame lbl updatee = do 
    718718-- (which Hugs needs to do in order that combined mode works right.)
    719719--
    720720
    721 -- ToDo [Feb 04]  This entire link_caf nonsense could all be moved
    722 -- into the "newCAF" RTS procedure, which we call anyway, including
    723 -- the allocation of the black-hole indirection closure.
    724 -- That way, code size would fall, the CAF-handling code would
    725 -- be closer together, and the compiler wouldn't need to know
    726 -- about off_indirectee etc.
    727 
    728721link_caf :: LocalReg           -- pointer to the closure
    729722         -> Bool               -- True <=> updatable, False <=> single-entry
    730723         -> FCode CmmExpr      -- Returns amode for closure to be updated
    link_caf :: LocalReg -- pointer to the closure 
    736729-- so that generational GC is easier.
    737730link_caf node _is_upd = do
    738731  { dflags <- getDynFlags
    739     -- Alloc black hole specifying CC_HDR(Node) as the cost centre
    740   ; let use_cc   = costCentreFrom dflags (CmmReg nodeReg)
    741         blame_cc = use_cc
    742         tso      = CmmReg (CmmGlobal CurrentTSO)
    743 
    744   ; hp_rel <- allocDynClosureCmm Nothing cafBlackHoleInfoTable mkLFBlackHole
    745                                          use_cc blame_cc [(tso,fixedHdrSize dflags)]
    746         -- small optimisation: we duplicate the hp_rel expression in
    747         -- both the newCAF call and the value returned below.
    748         -- If we instead used allocDynClosureReg which assigns it to a reg,
    749         -- then the reg is live across the newCAF call and gets spilled,
    750         -- which is stupid.  Really we should have an optimisation pass to
    751         -- fix this, but we don't yet. --SDM
    752 
    753732        -- Call the RTS function newCAF to add the CAF to the CafList
    754733        -- so that the garbage collector can find them
    755734        -- This must be done *before* the info table pointer is overwritten,
    756735        -- because the old info table ptr is needed for reversion
    757   ; ret <- newTemp (bWord dflags)
    758   ; emitRtsCallGen [(ret,NoHint)] (mkForeignLabel (fsLit "newCAF") Nothing ForeignLabelInExternalPackage IsFunction)
     736  ; let newCAF_lbl = mkForeignLabel (fsLit "newCAF") Nothing
     737                                    ForeignLabelInExternalPackage IsFunction
     738  ; bh <- newTemp (bWord dflags)
     739  ; emitRtsCallGen [(bh,AddrHint)] newCAF_lbl
    759740      [ (CmmReg (CmmGlobal BaseReg),  AddrHint),
    760         (CmmReg (CmmLocal node), AddrHint),
    761         (hp_rel, AddrHint) ]
     741        (CmmReg (CmmLocal node), AddrHint) ]
    762742      False
    763743
    764744  -- see Note [atomic CAF entry] in rts/sm/Storage.c
    765745  ; updfr  <- getUpdFrameOff
     746  ; let target = entryCode dflags (closureInfoPtr dflags (CmmReg (CmmLocal node)))
    766747  ; emit =<< mkCmmIfThen
    767       (CmmMachOp (mo_wordEq dflags) [ CmmReg (CmmLocal ret), CmmLit (zeroCLit dflags)])
     748      (cmmEqWord dflags (CmmReg (CmmLocal bh)) (zeroExpr dflags))
    768749        -- re-enter the CAF
    769        (let target = entryCode dflags (closureInfoPtr dflags (CmmReg (CmmLocal node))) in
    770         mkJump dflags NativeNodeCall target [] updfr)
     750       (mkJump dflags NativeNodeCall target [] updfr)
    771751
    772   ; return hp_rel }
     752  ; return (CmmReg (CmmLocal bh)) }
    773753
    774754------------------------------------------------------------------------
    775755--              Profiling
  • includes/rts/storage/GC.h

    diff --git a/includes/rts/storage/GC.h b/includes/rts/storage/GC.h
    index f8b8afe..63a9594 100644
    a b void performMajorGC(void); 
    181181   The CAF table - used to let us revert CAFs in GHCi
    182182   -------------------------------------------------------------------------- */
    183183
    184 StgWord newCAF    (StgRegTable *reg, StgIndStatic *caf, StgClosure *bh);
    185 StgWord newDynCAF (StgRegTable *reg, StgIndStatic *caf, StgClosure *bh);
     184StgInd *newCAF    (StgRegTable *reg, StgIndStatic *caf);
     185StgInd *newDynCAF (StgRegTable *reg, StgIndStatic *caf);
    186186void revertCAFs (void);
    187187
    188188// Request that all CAFs are retained indefinitely.
  • rts/sm/Storage.c

    diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
    index b5f3202..68d2c70 100644
    a b freeStorage (rtsBool free_heap) 
    333333
    334334   -------------------------------------------------------------------------- */
    335335
    336 STATIC_INLINE StgWord lockCAF (StgIndStatic *caf, StgClosure *bh)
     336STATIC_INLINE StgInd *
     337lockCAF (StgRegTable *reg, StgIndStatic *caf)
    337338{
    338339    const StgInfoTable *orig_info;
     340    Capability *cap = regTableToCapability(reg);
     341    StgInd *bh;
    339342
    340343    orig_info = caf->header.info;
    341344
    STATIC_INLINE StgWord lockCAF (StgIndStatic *caf, StgClosure *bh) 
    345348    if (orig_info == &stg_IND_STATIC_info ||
    346349        orig_info == &stg_WHITEHOLE_info) {
    347350        // already claimed by another thread; re-enter the CAF
    348         return 0;
     351        return NULL;
    349352    }
    350353
    351354    cur_info = (const StgInfoTable *)
    STATIC_INLINE StgWord lockCAF (StgIndStatic *caf, StgClosure *bh) 
    355358
    356359    if (cur_info != orig_info) {
    357360        // already claimed by another thread; re-enter the CAF
    358         return 0;
     361        return NULL;
    359362    }
    360363
    361364    // successfully claimed by us; overwrite with IND_STATIC
    STATIC_INLINE StgWord lockCAF (StgIndStatic *caf, StgClosure *bh) 
    364367    // For the benefit of revertCAFs(), save the original info pointer
    365368    caf->saved_info = orig_info;
    366369
    367     caf->indirectee = bh;
     370    // Allocate the blackhole indirection closure
     371    bh = (StgInd *)allocate(cap, sizeofW(*bh));
     372    bh->header.info = &stg_CAF_BLACKHOLE_info;
     373    bh->indirectee = (StgClosure *)cap->r.rCurrentTSO;
     374
     375    caf->indirectee = (StgClosure *)bh;
    368376    write_barrier();
    369377    SET_INFO((StgClosure*)caf,&stg_IND_STATIC_info);
    370378
    371     return 1;
     379    return bh;
    372380}
    373381
    374 StgWord
    375 newCAF(StgRegTable *reg, StgIndStatic *caf, StgClosure *bh)
     382StgInd *
     383newCAF(StgRegTable *reg, StgIndStatic *caf)
    376384{
    377     if (lockCAF(caf,bh) == 0) return 0;
     385    StgInd *bh;
     386
     387    bh = lockCAF(reg, caf);
     388    if (!bh) return NULL;
    378389
    379390    if(keepCAFs)
    380391    {
    newCAF(StgRegTable *reg, StgIndStatic *caf, StgClosure *bh) 
    418429#endif
    419430    }
    420431
    421     return 1;
     432    return bh;
    422433}
    423434
    424435// External API for setting the keepCAFs flag. see #3900.
    setKeepCAFs (void) 
    437448//
    438449// The linker hackily arranges that references to newCaf from dynamic
    439450// code end up pointing to newDynCAF.
    440 StgWord
    441 newDynCAF (StgRegTable *reg STG_UNUSED, StgIndStatic *caf, StgClosure *bh)
     451StgInd *
     452newDynCAF (StgRegTable *reg, StgIndStatic *caf)
    442453{
    443     if (lockCAF(caf,bh) == 0) return 0;
     454    StgInd *bh;
     455
     456    bh = lockCAF(reg, caf);
     457    if (!bh) return NULL;
    444458
    445459    ACQUIRE_SM_LOCK;
    446460
    newDynCAF (StgRegTable *reg STG_UNUSED, StgIndStatic *caf, StgClosure *bh) 
    449463
    450464    RELEASE_SM_LOCK;
    451465
    452     return 1;
     466    return bh;
    453467}
    454468
    455469/* -----------------------------------------------------------------------------