1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-13 01:00:21 +02:00

Record object sizes in metadata byte array

This will let us avoid paging in objects when sweeping.
This commit is contained in:
Andy Wingo 2022-05-01 15:19:13 +02:00
parent 3a04078044
commit ce69e9ed4c

View file

@ -646,19 +646,11 @@ static void unlink_medium_object(struct gcobj_free_medium **prev,
*prev = medium->next; *prev = medium->next;
} }
static size_t live_object_granules(struct gcobj *obj) { static size_t mark_space_live_object_granules(uint8_t *metadata) {
size_t bytes; size_t n = 0;
switch (tag_live_alloc_kind (obj->tag)) { while ((metadata[n] & METADATA_BYTE_END) == 0)
#define COMPUTE_SIZE(name, Name, NAME) \ n++;
case ALLOC_KIND_##NAME: \ return n + 1;
bytes = name##_size((Name*)obj); \
break;
FOR_EACH_HEAP_OBJECT_KIND(COMPUTE_SIZE)
#undef COMPUTE_SIZE
default:
abort ();
}
return size_to_granules(bytes);
} }
static size_t sweep_and_check_live(uint8_t *loc, uint8_t live_mask) { static size_t sweep_and_check_live(uint8_t *loc, uint8_t live_mask) {
@ -752,7 +744,7 @@ static int sweep(struct mutator *mut,
} }
// Object survived collection; skip over it and continue sweeping. // Object survived collection; skip over it and continue sweeping.
ASSERT((*mark) & live_mask); ASSERT((*mark) & live_mask);
sweep += live_object_granules((struct gcobj *)sweep) * GRANULE_SIZE; sweep += mark_space_live_object_granules(mark) * GRANULE_SIZE;
} }
mut->sweep = sweep; mut->sweep = sweep;
@ -772,8 +764,6 @@ static void finish_sweeping(struct mutator *mut) {
size_t free_granules = next_mark(mark, limit_granules, live_mask); size_t free_granules = next_mark(mark, limit_granules, live_mask);
if (free_granules) { if (free_granules) {
ASSERT(free_granules <= limit_granules); ASSERT(free_granules <= limit_granules);
size_t free_bytes = free_granules * GRANULE_SIZE;
sweep += free_bytes;
mark += free_granules; mark += free_granules;
limit_granules -= free_granules; limit_granules -= free_granules;
if (limit_granules == 0) if (limit_granules == 0)
@ -781,8 +771,7 @@ static void finish_sweeping(struct mutator *mut) {
} }
// Object survived collection; skip over it and continue sweeping. // Object survived collection; skip over it and continue sweeping.
ASSERT((*mark) & live_mask); ASSERT((*mark) & live_mask);
size_t live_granules = live_object_granules((struct gcobj *)sweep); size_t live_granules = mark_space_live_object_granules(mark);
sweep += live_granules * GRANULE_SIZE;
limit_granules -= live_granules; limit_granules -= live_granules;
mark += live_granules; mark += live_granules;
} }
@ -839,6 +828,9 @@ static void* allocate_medium(struct mutator *mut, enum alloc_kind kind,
split_medium_object(mut, medium, granules); split_medium_object(mut, medium, granules);
struct gcobj *obj = (struct gcobj *)medium; struct gcobj *obj = (struct gcobj *)medium;
obj->tag = tag_live(kind); obj->tag = tag_live(kind);
uint8_t *metadata = object_metadata_byte(obj);
metadata[0] = METADATA_BYTE_YOUNG;
metadata[granules - 1] = METADATA_BYTE_END;
return medium; return medium;
} }
} }
@ -933,6 +925,13 @@ static inline void* allocate_small(struct mutator *mut, enum alloc_kind kind,
if (!*loc) if (!*loc)
fill_small(mut, granules); fill_small(mut, granules);
struct gcobj_free *ret = *loc; struct gcobj_free *ret = *loc;
uint8_t *metadata = object_metadata_byte(ret);
if (granules == 1) {
metadata[0] = METADATA_BYTE_YOUNG | METADATA_BYTE_END;
} else {
metadata[0] = METADATA_BYTE_YOUNG;
metadata[granules - 1] = METADATA_BYTE_END;
}
*loc = ret->next; *loc = ret->next;
struct gcobj *obj = (struct gcobj *)ret; struct gcobj *obj = (struct gcobj *)ret;
obj->tag = tag_live(kind); obj->tag = tag_live(kind);