summaryrefslogtreecommitdiff
path: root/rts/sm/Storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/sm/Storage.c')
-rw-r--r--rts/sm/Storage.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index 541da5df1c..e5258c2517 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -78,6 +78,7 @@ initGeneration (generation *gen, int g)
gen->n_old_blocks = 0;
gen->large_objects = NULL;
gen->n_large_blocks = 0;
+ gen->n_large_words = 0;
gen->n_new_large_words = 0;
gen->scavenged_large_objects = NULL;
gen->n_scavenged_large_blocks = 0;
@@ -437,16 +438,12 @@ allocNursery (bdescr *tail, W_ blocks)
// tiny optimisation (~0.5%), but it's free.
while (blocks > 0) {
- if (blocks >= BLOCKS_PER_MBLOCK / 4) {
- n = stg_min(BLOCKS_PER_MBLOCK, blocks);
- bd = allocLargeChunk(16, n); // see comment with allocLargeChunk()
- // NB. we want a nice power of 2 for the minimum here
- n = bd->blocks;
- } else {
- bd = allocGroup(blocks);
- n = blocks;
- }
-
+ n = stg_min(BLOCKS_PER_MBLOCK, blocks);
+ // allocLargeChunk will prefer large chunks, but will pick up
+ // small chunks if there are any available. We must allow
+ // single blocks here to avoid fragmentation (#7257)
+ bd = allocLargeChunk(1, n);
+ n = bd->blocks;
blocks -= n;
for (i = 0; i < n; i++) {
@@ -767,6 +764,7 @@ allocatePinned (Capability *cap, W_ n)
// g0->large_objects.
if (bd != NULL) {
dbl_link_onto(bd, &cap->pinned_object_blocks);
+ cap->total_allocated += bd->free - bd->start;
}
// We need to find another block. We could just allocate one,
@@ -955,7 +953,7 @@ W_ countOccupied (bdescr *bd)
W_ genLiveWords (generation *gen)
{
- return gen->n_words + countOccupied(gen->large_objects);
+ return gen->n_words + gen->n_large_words;
}
W_ genLiveBlocks (generation *gen)