mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-14 09:40:20 +02:00
More efficient sweep
This commit is contained in:
parent
5c8a8a2d3e
commit
5edc4fa81a
1 changed files with 33 additions and 17 deletions
50
mark-sweep.h
50
mark-sweep.h
|
@ -312,6 +312,21 @@ static size_t live_object_granules(struct gcobj *obj) {
|
||||||
return small_object_granule_sizes[granules_to_small_object_size(granules)];
|
return small_object_granule_sizes[granules_to_small_object_size(granules)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t next_mark(const uint8_t *mark, size_t limit) {
|
||||||
|
size_t n = 0;
|
||||||
|
for (; (((uintptr_t)mark) & 7) && n < limit; n++)
|
||||||
|
if (mark[n])
|
||||||
|
return n;
|
||||||
|
uintptr_t *word_mark = (uintptr_t *)(mark + n);
|
||||||
|
for (; n < limit; n += sizeof(uintptr_t), word_mark++)
|
||||||
|
if (word_mark)
|
||||||
|
break;
|
||||||
|
for (; n < limit; n++)
|
||||||
|
if (mark[n])
|
||||||
|
return n;
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
// Sweep some heap to reclaim free space. Return 1 if there is more
|
// Sweep some heap to reclaim free space. Return 1 if there is more
|
||||||
// heap to sweep, or 0 if we reached the end.
|
// heap to sweep, or 0 if we reached the end.
|
||||||
static int sweep(struct context *cx) {
|
static int sweep(struct context *cx) {
|
||||||
|
@ -322,25 +337,26 @@ static int sweep(struct context *cx) {
|
||||||
uintptr_t limit = cx->base + cx->size;
|
uintptr_t limit = cx->base + cx->size;
|
||||||
|
|
||||||
while (to_reclaim > 0 && sweep < limit) {
|
while (to_reclaim > 0 && sweep < limit) {
|
||||||
uintptr_t sweep_base = sweep;
|
uint8_t* mark = mark_byte(cx, (struct gcobj*)sweep);
|
||||||
struct gcobj *obj = (struct gcobj*)sweep_base;
|
size_t free_granules = next_mark(mark,
|
||||||
uint8_t* mark = mark_byte(cx, obj);
|
(limit - sweep) >> GRANULE_SIZE_LOG_2);
|
||||||
if (*mark) {
|
if (free_granules) {
|
||||||
// Object survived collection; clear mark and continue sweeping.
|
size_t free_bytes = free_granules * GRANULE_SIZE;
|
||||||
ASSERT(*mark == 1);
|
memset((void*)(sweep + GRANULE_SIZE),
|
||||||
*mark = 0;
|
|
||||||
sweep += live_object_granules(obj) * GRANULE_SIZE;
|
|
||||||
} else {
|
|
||||||
// Found a free object. Combine with any following free space.
|
|
||||||
// To avoid fragmentation, don't limit the amount to reclaim.
|
|
||||||
do {
|
|
||||||
sweep += GRANULE_SIZE, to_reclaim--, mark++;
|
|
||||||
} while (sweep < limit && !*mark);
|
|
||||||
memset((void*)(sweep_base + GRANULE_SIZE),
|
|
||||||
0,
|
0,
|
||||||
sweep - sweep_base - GRANULE_SIZE);
|
free_bytes - GRANULE_SIZE);
|
||||||
reclaim(cx, obj, (sweep - sweep_base) >> GRANULE_SIZE_LOG_2);
|
reclaim(cx, (void*)sweep, free_granules);
|
||||||
|
sweep += free_bytes;
|
||||||
|
to_reclaim -= free_granules;
|
||||||
|
|
||||||
|
mark += free_granules;
|
||||||
|
if (sweep == limit)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
// Object survived collection; clear mark and continue sweeping.
|
||||||
|
ASSERT(*mark == 1);
|
||||||
|
*mark = 0;
|
||||||
|
sweep += live_object_granules((struct gcobj *)sweep) * GRANULE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx->sweep = sweep;
|
cx->sweep = sweep;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue