summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/codeGen/StgCmmBind.hs40
-rw-r--r--includes/rts/storage/GC.h4
-rw-r--r--rts/sm/Storage.c40
3 files changed, 39 insertions, 45 deletions
diff --git a/compiler/codeGen/StgCmmBind.hs b/compiler/codeGen/StgCmmBind.hs
index 64772c66ce..05aae0aeeb 100644
--- a/compiler/codeGen/StgCmmBind.hs
+++ b/compiler/codeGen/StgCmmBind.hs
@@ -21,7 +21,7 @@ import StgCmmEnv
import StgCmmCon
import StgCmmHeap
import StgCmmProf (curCCS, ldvEnterClosure, enterCostCentreFun, enterCostCentreThunk,
- initUpdFrameProf, costCentreFrom)
+ initUpdFrameProf)
import StgCmmTicky
import StgCmmLayout
import StgCmmUtils
@@ -718,13 +718,6 @@ emitUpdateFrame dflags frame lbl updatee = do
-- (which Hugs needs to do in order that combined mode works right.)
--
--- ToDo [Feb 04] This entire link_caf nonsense could all be moved
--- into the "newCAF" RTS procedure, which we call anyway, including
--- the allocation of the black-hole indirection closure.
--- That way, code size would fall, the CAF-handling code would
--- be closer together, and the compiler wouldn't need to know
--- about off_indirectee etc.
-
link_caf :: LocalReg -- pointer to the closure
-> Bool -- True <=> updatable, False <=> single-entry
-> FCode CmmExpr -- Returns amode for closure to be updated
@@ -736,40 +729,27 @@ link_caf :: LocalReg -- pointer to the closure
-- so that generational GC is easier.
link_caf node _is_upd = do
{ dflags <- getDynFlags
- -- Alloc black hole specifying CC_HDR(Node) as the cost centre
- ; let use_cc = costCentreFrom dflags (CmmReg nodeReg)
- blame_cc = use_cc
- tso = CmmReg (CmmGlobal CurrentTSO)
-
- ; hp_rel <- allocDynClosureCmm Nothing cafBlackHoleInfoTable mkLFBlackHole
- use_cc blame_cc [(tso,fixedHdrSize dflags)]
- -- small optimisation: we duplicate the hp_rel expression in
- -- both the newCAF call and the value returned below.
- -- If we instead used allocDynClosureReg which assigns it to a reg,
- -- then the reg is live across the newCAF call and gets spilled,
- -- which is stupid. Really we should have an optimisation pass to
- -- fix this, but we don't yet. --SDM
-
-- Call the RTS function newCAF to add the CAF to the CafList
-- so that the garbage collector can find them
-- This must be done *before* the info table pointer is overwritten,
-- because the old info table ptr is needed for reversion
- ; ret <- newTemp (bWord dflags)
- ; emitRtsCallGen [(ret,NoHint)] (mkForeignLabel (fsLit "newCAF") Nothing ForeignLabelInExternalPackage IsFunction)
+ ; let newCAF_lbl = mkForeignLabel (fsLit "newCAF") Nothing
+ ForeignLabelInExternalPackage IsFunction
+ ; bh <- newTemp (bWord dflags)
+ ; emitRtsCallGen [(bh,AddrHint)] newCAF_lbl
[ (CmmReg (CmmGlobal BaseReg), AddrHint),
- (CmmReg (CmmLocal node), AddrHint),
- (hp_rel, AddrHint) ]
+ (CmmReg (CmmLocal node), AddrHint) ]
False
-- see Note [atomic CAF entry] in rts/sm/Storage.c
; updfr <- getUpdFrameOff
+ ; let target = entryCode dflags (closureInfoPtr dflags (CmmReg (CmmLocal node)))
; emit =<< mkCmmIfThen
- (CmmMachOp (mo_wordEq dflags) [ CmmReg (CmmLocal ret), CmmLit (zeroCLit dflags)])
+ (cmmEqWord dflags (CmmReg (CmmLocal bh)) (zeroExpr dflags))
-- re-enter the CAF
- (let target = entryCode dflags (closureInfoPtr dflags (CmmReg (CmmLocal node))) in
- mkJump dflags NativeNodeCall target [] updfr)
+ (mkJump dflags NativeNodeCall target [] updfr)
- ; return hp_rel }
+ ; return (CmmReg (CmmLocal bh)) }
------------------------------------------------------------------------
-- Profiling
diff --git a/includes/rts/storage/GC.h b/includes/rts/storage/GC.h
index f8b8afe328..63a9594da0 100644
--- a/includes/rts/storage/GC.h
+++ b/includes/rts/storage/GC.h
@@ -181,8 +181,8 @@ void performMajorGC(void);
The CAF table - used to let us revert CAFs in GHCi
-------------------------------------------------------------------------- */
-StgWord newCAF (StgRegTable *reg, StgIndStatic *caf, StgClosure *bh);
-StgWord newDynCAF (StgRegTable *reg, StgIndStatic *caf, StgClosure *bh);
+StgInd *newCAF (StgRegTable *reg, StgIndStatic *caf);
+StgInd *newDynCAF (StgRegTable *reg, StgIndStatic *caf);
void revertCAFs (void);
// Request that all CAFs are retained indefinitely.
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index b5f3202887..755b3d9f00 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -333,9 +333,12 @@ freeStorage (rtsBool free_heap)
-------------------------------------------------------------------------- */
-STATIC_INLINE StgWord lockCAF (StgIndStatic *caf, StgClosure *bh)
+STATIC_INLINE StgInd *
+lockCAF (StgRegTable *reg, StgIndStatic *caf)
{
const StgInfoTable *orig_info;
+ Capability *cap = regTableToCapability(reg);
+ StgInd *bh;
orig_info = caf->header.info;
@@ -345,7 +348,7 @@ STATIC_INLINE StgWord lockCAF (StgIndStatic *caf, StgClosure *bh)
if (orig_info == &stg_IND_STATIC_info ||
orig_info == &stg_WHITEHOLE_info) {
// already claimed by another thread; re-enter the CAF
- return 0;
+ return NULL;
}
cur_info = (const StgInfoTable *)
@@ -355,7 +358,7 @@ STATIC_INLINE StgWord lockCAF (StgIndStatic *caf, StgClosure *bh)
if (cur_info != orig_info) {
// already claimed by another thread; re-enter the CAF
- return 0;
+ return NULL;
}
// successfully claimed by us; overwrite with IND_STATIC
@@ -364,17 +367,25 @@ STATIC_INLINE StgWord lockCAF (StgIndStatic *caf, StgClosure *bh)
// For the benefit of revertCAFs(), save the original info pointer
caf->saved_info = orig_info;
- caf->indirectee = bh;
+ // Allocate the blackhole indirection closure
+ bh = (StgInd *)allocate(cap, sizeofW(*bh));
+ SET_HDR(bh, &stg_CAF_BLACKHOLE_info, caf->header.prof.ccs);
+ bh->indirectee = (StgClosure *)cap->r.rCurrentTSO;
+
+ caf->indirectee = (StgClosure *)bh;
write_barrier();
SET_INFO((StgClosure*)caf,&stg_IND_STATIC_info);
- return 1;
+ return bh;
}
-StgWord
-newCAF(StgRegTable *reg, StgIndStatic *caf, StgClosure *bh)
+StgInd *
+newCAF(StgRegTable *reg, StgIndStatic *caf)
{
- if (lockCAF(caf,bh) == 0) return 0;
+ StgInd *bh;
+
+ bh = lockCAF(reg, caf);
+ if (!bh) return NULL;
if(keepCAFs)
{
@@ -418,7 +429,7 @@ newCAF(StgRegTable *reg, StgIndStatic *caf, StgClosure *bh)
#endif
}
- return 1;
+ return bh;
}
// External API for setting the keepCAFs flag. see #3900.
@@ -437,10 +448,13 @@ setKeepCAFs (void)
//
// The linker hackily arranges that references to newCaf from dynamic
// code end up pointing to newDynCAF.
-StgWord
-newDynCAF (StgRegTable *reg STG_UNUSED, StgIndStatic *caf, StgClosure *bh)
+StgInd *
+newDynCAF (StgRegTable *reg, StgIndStatic *caf)
{
- if (lockCAF(caf,bh) == 0) return 0;
+ StgInd *bh;
+
+ bh = lockCAF(reg, caf);
+ if (!bh) return NULL;
ACQUIRE_SM_LOCK;
@@ -449,7 +463,7 @@ newDynCAF (StgRegTable *reg STG_UNUSED, StgIndStatic *caf, StgClosure *bh)
RELEASE_SM_LOCK;
- return 1;
+ return bh;
}
/* -----------------------------------------------------------------------------