X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=rts%2Fsm%2FStorage.c;h=02344003b89b1849bd9a63c7d774343b691c0110;hp=d9c7f8627829f79927fe9c4eeed8b88584083cf5;hb=5d52d9b64c21dcf77849866584744722f8121389;hpb=214b3663d5d7598c13643f9221e43d5a7735b47f diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c index d9c7f86..0234400 100644 --- a/rts/sm/Storage.c +++ b/rts/sm/Storage.c @@ -49,8 +49,6 @@ generation *generations = NULL; /* all the generations */ generation *g0 = NULL; /* generation 0, for convenience */ generation *oldest_gen = NULL; /* oldest generation, for convenience */ -ullong total_allocated = 0; /* total memory allocated during run */ - nursery *nurseries = NULL; /* array of nurseries, size == n_capabilities */ #ifdef THREADED_RTS @@ -79,6 +77,7 @@ initGeneration (generation *gen, int g) gen->n_old_blocks = 0; gen->large_objects = NULL; gen->n_large_blocks = 0; + gen->n_new_large_blocks = 0; gen->mut_list = allocBlock(); gen->scavenged_large_objects = NULL; gen->n_scavenged_large_blocks = 0; @@ -95,7 +94,7 @@ initGeneration (generation *gen, int g) void initStorage( void ) { - nat g; + nat g, n; if (generations != NULL) { // multi-init protection @@ -108,7 +107,7 @@ initStorage( void ) * doing something reasonable. */ /* We use the NOT_NULL variant or gcc warns that the test is always true */ - ASSERT(LOOKS_LIKE_INFO_PTR_NOT_NULL((StgWord)&stg_BLACKHOLE_info)); + ASSERT(LOOKS_LIKE_INFO_PTR_NOT_NULL((StgWord)&stg_BLOCKING_QUEUE_CLEAN_info)); ASSERT(LOOKS_LIKE_CLOSURE_PTR(&stg_dummy_ret_closure)); ASSERT(!HEAP_ALLOCED(&stg_dummy_ret_closure)); @@ -193,6 +192,13 @@ initStorage( void ) N = 0; + // allocate a block for each mut list + for (n = 0; n < n_capabilities; n++) { + for (g = 1; g < RtsFlags.GcFlags.generations; g++) { + capabilities[n].mut_lists[g] = allocBlock(); + } + } + initGcThreads(); IF_DEBUG(gc, statDescribeGens()); @@ -223,20 +229,20 @@ freeStorage (void) The entry code for every CAF does the following: - - builds a CAF_BLACKHOLE in the heap - - pushes an update frame pointing to the CAF_BLACKHOLE + - builds a BLACKHOLE in the heap + - pushes an update frame pointing to the BLACKHOLE - invokes UPD_CAF(), which: - calls newCaf, below - - updates the CAF with a static indirection to the CAF_BLACKHOLE + - updates the CAF with a static indirection to the BLACKHOLE - Why do we build a BLACKHOLE in the heap rather than just updating + Why do we build an BLACKHOLE in the heap rather than just updating the thunk directly? It's so that we only need one kind of update frame - otherwise we'd need a static version of the update frame too. newCaf() does the following: - - it puts the CAF on the oldest generation's mut-once list. - This is so that we can treat the CAF as a root when collecting + - it puts the CAF on the oldest generation's mutable list. + This is so that we treat the CAF as a root when collecting younger generations. For GHCI, we have additional requirements when dealing with CAFs: @@ -260,11 +266,8 @@ freeStorage (void) -------------------------------------------------------------------------- */ void -newCAF(StgClosure* caf) +newCAF(StgRegTable *reg, StgClosure* caf) { - ACQUIRE_SM_LOCK; - -#ifdef DYNAMIC if(keepCAFs) { // HACK: @@ -278,24 +281,25 @@ newCAF(StgClosure* caf) // do another hack here and do an address range test on caf to figure // out whether it is from a dynamic library. ((StgIndStatic *)caf)->saved_info = (StgInfoTable *)caf->header.info; + + ACQUIRE_SM_LOCK; // caf_list is global, locked by sm_mutex ((StgIndStatic *)caf)->static_link = caf_list; caf_list = caf; + RELEASE_SM_LOCK; } else -#endif { - /* Put this CAF on the mutable list for the old generation. - * This is a HACK - the IND_STATIC closure doesn't really have - * a mut_link field, but we pretend it has - in fact we re-use - * the STATIC_LINK field for the time being, because when we - * come to do a major GC we won't need the mut_link field - * any more and can use it as a STATIC_LINK. - */ + // Put this CAF on the mutable list for the old generation. ((StgIndStatic *)caf)->saved_info = NULL; - recordMutableGen(caf, oldest_gen->no); + recordMutableCap(caf, regTableToCapability(reg), oldest_gen->no); } - - RELEASE_SM_LOCK; +} + +// External API for setting the keepCAFs flag. see #3900. +void +setKeepCAFs (void) +{ + keepCAFs = 1; } // An alternate version of newCaf which is used for dynamically loaded @@ -308,7 +312,7 @@ newCAF(StgClosure* caf) // The linker hackily arranges that references to newCaf from dynamic // code end up pointing to newDynCAF. void -newDynCAF(StgClosure *caf) +newDynCAF (StgRegTable *reg STG_UNUSED, StgClosure *caf) { ACQUIRE_SM_LOCK; @@ -567,6 +571,7 @@ allocate (Capability *cap, lnat n) bd = allocGroup(req_blocks); dbl_link_onto(bd, &g0->large_objects); g0->n_large_blocks += bd->blocks; // might be larger than req_blocks + g0->n_new_large_blocks += bd->blocks; RELEASE_SM_LOCK; initBdescr(bd, g0, g0); bd->flags = BF_LARGE; @@ -614,6 +619,8 @@ allocate (Capability *cap, lnat n) } p = bd->free; bd->free += n; + + IF_DEBUG(sanity, ASSERT(*((StgWord8*)p) == 0xaa)); return p; } @@ -666,6 +673,7 @@ allocatePinned (Capability *cap, lnat n) cap->pinned_object_block = bd = allocBlock(); dbl_link_onto(bd, &g0->large_objects); g0->n_large_blocks++; + g0->n_new_large_blocks++; RELEASE_SM_LOCK; initBdescr(bd, g0, g0); bd->flags = BF_PINNED | BF_LARGE; @@ -691,11 +699,9 @@ void dirty_MUT_VAR(StgRegTable *reg, StgClosure *p) { Capability *cap = regTableToCapability(reg); - bdescr *bd; if (p->header.info == &stg_MUT_VAR_CLEAN_info) { p->header.info = &stg_MUT_VAR_DIRTY_info; - bd = Bdescr((StgPtr)p); - if (bd->gen_no > 0) recordMutableCap(p,cap,bd->gen_no); + recordClosureMutated(cap,p); } } @@ -708,11 +714,9 @@ dirty_MUT_VAR(StgRegTable *reg, StgClosure *p) void setTSOLink (Capability *cap, StgTSO *tso, StgTSO *target) { - bdescr *bd; if (tso->dirty == 0 && (tso->flags & TSO_LINK_DIRTY) == 0) { tso->flags |= TSO_LINK_DIRTY; - bd = Bdescr((StgPtr)tso); - if (bd->gen_no > 0) recordMutableCap((StgClosure*)tso,cap,bd->gen_no); + recordClosureMutated(cap,(StgClosure*)tso); } tso->_link = target; } @@ -720,10 +724,8 @@ setTSOLink (Capability *cap, StgTSO *tso, StgTSO *target) void dirty_TSO (Capability *cap, StgTSO *tso) { - bdescr *bd; if (tso->dirty == 0 && (tso->flags & TSO_LINK_DIRTY) == 0) { - bd = Bdescr((StgPtr)tso); - if (bd->gen_no > 0) recordMutableCap((StgClosure*)tso,cap,bd->gen_no); + recordClosureMutated(cap,(StgClosure*)tso); } tso->dirty = 1; } @@ -739,10 +741,7 @@ dirty_TSO (Capability *cap, StgTSO *tso) void dirty_MVAR(StgRegTable *reg, StgClosure *p) { - Capability *cap = regTableToCapability(reg); - bdescr *bd; - bd = Bdescr((StgPtr)p); - if (bd->gen_no > 0) recordMutableCap(p,cap,bd->gen_no); + recordClosureMutated(regTableToCapability(reg),p); } /* ----------------------------------------------------------------------------- @@ -784,7 +783,8 @@ calcAllocated( void ) } } - total_allocated += allocated; + allocated += g0->n_new_large_blocks * BLOCK_SIZE_W; + return allocated; }