// allocate() - this includes many of the primops.
#define MAYBE_GC(liveness,reentry) \
if (bdescr_link(CurrentNursery) == NULL || \
- generation_n_new_large_blocks(W_[g0]) >= CInt[alloc_blocks_lim]) { \
+ generation_n_new_large_words(W_[g0]) >= CLong[large_alloc_lim]) { \
R9 = liveness; \
R10 = reentry; \
HpAlloc = 0; \
struct_size(generation);
struct_field(generation, mut_list);
- struct_field(generation, n_new_large_blocks);
+ struct_field(generation, n_new_large_words);
struct_size(CostCentreStack);
struct_field(CostCentreStack, ccsID);
bdescr * large_objects; // large objects (doubly linked)
unsigned int n_large_blocks; // no. of blocks used by large objs
- unsigned int n_new_large_blocks; // count freshly allocated large objects
+ unsigned long n_new_large_words; // words of new large objects
+ // (for allocation stats)
unsigned int max_blocks; // max blocks
bdescr *mut_list; // mut objects in this gen (not G0)
void freeExec (void *p);
// Used by GC checks in external .cmm code:
-extern nat alloc_blocks_lim;
+extern nat large_alloc_lim;
/* -----------------------------------------------------------------------------
Performing Garbage Collection
// Storage.c
extern unsigned int RTS_VAR(g0);
-extern unsigned int RTS_VAR(alloc_blocks_lim);
+extern unsigned int RTS_VAR(large_alloc_lim);
extern StgWord RTS_VAR(weak_ptr_list);
extern StgWord RTS_VAR(atomic_modify_mutvar_mutex);
SymI_HasProto(stg_yieldzh) \
SymI_NeedsProto(stg_interp_constr_entry) \
SymI_HasProto(stg_arg_bitmaps) \
- SymI_HasProto(alloc_blocks_lim) \
+ SymI_HasProto(large_alloc_lim) \
SymI_HasProto(g0) \
SymI_HasProto(allocate) \
SymI_HasProto(allocateExec) \
/* Approximate how much we allocated.
* Todo: only when generating stats?
*/
- allocated = calcAllocated();
+ allocated = calcAllocated(rtsFalse/* don't count the nursery yet */);
/* Figure out which generation to collect
*/
freeChain(gen->large_objects);
gen->large_objects = gen->scavenged_large_objects;
gen->n_large_blocks = gen->n_scavenged_large_blocks;
- gen->n_new_large_blocks = 0;
+ gen->n_new_large_words = 0;
ASSERT(countBlocks(gen->large_objects) == gen->n_large_blocks);
}
else // for generations > N
// Calculate the amount of live data for stats.
live = calcLiveWords();
- // Free the small objects allocated via allocate(), since this will
- // all have been copied into G0S1 now.
- alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize;
-
// Start a new pinned_object_block
for (n = 0; n < n_capabilities; n++) {
capabilities[n].pinned_object_block = NULL;
}
}
+ // Reset the nursery: make the blocks empty
+ allocated += clearNurseries();
+
resize_nursery();
- // mark the garbage collected CAFs as dead
+ resetNurseries();
+
+ // mark the garbage collected CAFs as dead
#if 0 && defined(DEBUG) // doesn't work at the moment
if (major_gc) { gcCAFs(); }
#endif
}
}
- // Reset the nursery
- resetNurseries();
-
- // send exceptions to any threads which were about to die
+ // send exceptions to any threads which were about to die
RELEASE_SM_LOCK;
resurrectThreads(resurrected_threads);
ACQUIRE_SM_LOCK;
StgClosure *revertible_caf_list = NULL;
rtsBool keepCAFs;
-nat alloc_blocks_lim; /* GC if n_large_blocks in any nursery
- * reaches this. */
+nat large_alloc_lim; /* GC if n_large_blocks in any nursery
+ * reaches this. */
bdescr *exec_block;
gen->n_old_blocks = 0;
gen->large_objects = NULL;
gen->n_large_blocks = 0;
- gen->n_new_large_blocks = 0;
+ gen->n_new_large_words = 0;
gen->mut_list = allocBlock();
gen->scavenged_large_objects = NULL;
gen->n_scavenged_large_blocks = 0;
revertible_caf_list = END_OF_STATIC_LIST;
/* initialise the allocate() interface */
- alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize;
+ large_alloc_lim = RtsFlags.GcFlags.minAllocAreaSize * BLOCK_SIZE_W;
exec_block = NULL;
void
exitStorage (void)
{
- stat_exit(calcAllocated());
+ stat_exit(calcAllocated(rtsTrue));
}
void
assignNurseriesToCapabilities();
}
-void
-resetNurseries( void )
+lnat // words allocated
+clearNurseries (void)
{
+ lnat allocated = 0;
nat i;
bdescr *bd;
for (i = 0; i < n_capabilities; i++) {
for (bd = nurseries[i].blocks; bd; bd = bd->link) {
- bd->free = bd->start;
+ allocated += (lnat)(bd->free - bd->start);
+ bd->free = bd->start;
ASSERT(bd->gen_no == 0);
ASSERT(bd->gen == g0);
IF_DEBUG(sanity,memset(bd->start, 0xaa, BLOCK_SIZE));
}
}
+
+ return allocated;
+}
+
+void
+resetNurseries (void)
+{
assignNurseriesToCapabilities();
+
}
lnat
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;
+ g0->n_new_large_words += n;
RELEASE_SM_LOCK;
initBdescr(bd, g0, g0);
bd->flags = BF_LARGE;
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;
bd->free = bd->start;
}
+ g0->n_new_large_words += n;
p = bd->free;
bd->free += n;
return p;
* -------------------------------------------------------------------------- */
lnat
-calcAllocated( void )
+calcAllocated (rtsBool include_nurseries)
{
- nat allocated;
+ nat allocated = 0;
bdescr *bd;
nat i;
- allocated = countNurseryBlocks() * BLOCK_SIZE_W;
-
- for (i = 0; i < n_capabilities; i++) {
- Capability *cap;
- for ( bd = capabilities[i].r.rCurrentNursery->link;
- bd != NULL; bd = bd->link ) {
- allocated -= BLOCK_SIZE_W;
- }
- cap = &capabilities[i];
- if (cap->r.rCurrentNursery->free <
- cap->r.rCurrentNursery->start + BLOCK_SIZE_W) {
- allocated -= (cap->r.rCurrentNursery->start + BLOCK_SIZE_W)
- - cap->r.rCurrentNursery->free;
- }
- if (cap->pinned_object_block != NULL) {
- allocated -= (cap->pinned_object_block->start + BLOCK_SIZE_W) -
- cap->pinned_object_block->free;
+ // When called from GC.c, we already have the allocation count for
+ // the nursery from resetNurseries(), so we don't need to walk
+ // through these block lists again.
+ if (include_nurseries)
+ {
+ for (i = 0; i < n_capabilities; i++) {
+ for (bd = nurseries[i].blocks; bd; bd = bd->link) {
+ allocated += (lnat)(bd->free - bd->start);
+ }
}
}
- allocated += g0->n_new_large_blocks * BLOCK_SIZE_W;
+ // add in sizes of new large and pinned objects
+ allocated += g0->n_new_large_words;
return allocated;
}
doYouWantToGC( Capability *cap )
{
return (cap->r.rCurrentNursery->link == NULL ||
- g0->n_large_blocks >= alloc_blocks_lim);
+ g0->n_new_large_words >= large_alloc_lim);
}
/* for splitting blocks groups in two */
extern nursery *nurseries;
void resetNurseries ( void );
+lnat clearNurseries ( void );
void resizeNurseries ( nat blocks );
void resizeNurseriesFixed ( nat blocks );
lnat countNurseryBlocks ( void );
Stats 'n' DEBUG stuff
-------------------------------------------------------------------------- */
-lnat calcAllocated (void);
+lnat calcAllocated (rtsBool count_nurseries);
lnat calcLiveBlocks (void);
lnat calcLiveWords (void);
lnat countOccupied (bdescr *bd);