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

nofl: Refactor to trace visitor

This commit is contained in:
Andy Wingo 2024-08-24 16:38:11 +02:00
parent 7db72e7f80
commit 010185f729

View file

@ -1187,20 +1187,27 @@ nofl_space_sweep_until_memory_released(struct nofl_space *space,
} }
static inline int static inline int
nofl_space_evacuate_or_mark_object(struct nofl_space *space, nofl_space_should_evacuate(struct nofl_space *space, struct gc_ref obj) {
if (!space->evacuating)
return 0;
struct nofl_block_summary *summary =
nofl_block_summary_for_addr(gc_ref_value(obj));
return nofl_block_summary_has_flag(summary, NOFL_BLOCK_EVACUATE);
}
static inline int
nofl_space_set_mark(struct nofl_space *space, uint8_t *metadata, uint8_t byte) {
uint8_t mask = NOFL_METADATA_BYTE_YOUNG | NOFL_METADATA_BYTE_MARK_0
| NOFL_METADATA_BYTE_MARK_1 | NOFL_METADATA_BYTE_MARK_2;
*metadata = (byte & ~mask) | space->marked_mask;
return 1;
}
static inline int
nofl_space_evacuate(struct nofl_space *space, uint8_t *metadata, uint8_t byte,
struct gc_edge edge, struct gc_edge edge,
struct gc_ref old_ref, struct gc_ref old_ref,
struct nofl_allocator *evacuate) { struct nofl_allocator *evacuate) {
uint8_t *metadata = nofl_metadata_byte_for_object(old_ref);
uint8_t byte = *metadata;
if (byte & space->marked_mask)
return 0;
if (space->evacuating &&
nofl_block_summary_has_flag(nofl_block_summary_for_addr(gc_ref_value(old_ref)),
NOFL_BLOCK_EVACUATE)) {
// This is an evacuating collection, and we are attempting to
// evacuate this block, and we are tracing this particular object
// for what appears to be the first time.
struct gc_atomic_forward fwd = gc_atomic_forward_begin(old_ref); struct gc_atomic_forward fwd = gc_atomic_forward_begin(old_ref);
if (fwd.state == GC_FORWARDING_STATE_NOT_FORWARDED) if (fwd.state == GC_FORWARDING_STATE_NOT_FORWARDED)
@ -1209,6 +1216,7 @@ nofl_space_evacuate_or_mark_object(struct nofl_space *space,
switch (fwd.state) { switch (fwd.state) {
case GC_FORWARDING_STATE_NOT_FORWARDED: case GC_FORWARDING_STATE_NOT_FORWARDED:
case GC_FORWARDING_STATE_ABORTED: case GC_FORWARDING_STATE_ABORTED:
default:
// Impossible. // Impossible.
GC_CRASH(); GC_CRASH();
case GC_FORWARDING_STATE_ACQUIRED: { case GC_FORWARDING_STATE_ACQUIRED: {
@ -1228,13 +1236,13 @@ nofl_space_evacuate_or_mark_object(struct nofl_space *space,
uint8_t *new_metadata = nofl_metadata_byte_for_object(new_ref); uint8_t *new_metadata = nofl_metadata_byte_for_object(new_ref);
memcpy(new_metadata + 1, metadata + 1, object_granules - 1); memcpy(new_metadata + 1, metadata + 1, object_granules - 1);
gc_edge_update(edge, new_ref); gc_edge_update(edge, new_ref);
metadata = new_metadata; return nofl_space_set_mark(space, new_metadata, byte);
// Fall through to set mark bits.
} else { } else {
// Well shucks; allocation failed, marking the end of // Well shucks; allocation failed, marking the end of
// opportunistic evacuation. No future evacuation of this // opportunistic evacuation. No future evacuation of this
// object will succeed. Mark in place instead. // object will succeed. Mark in place instead.
gc_atomic_forward_abort(&fwd); gc_atomic_forward_abort(&fwd);
return nofl_space_set_mark(space, metadata, byte);
} }
break; break;
} }
@ -1258,12 +1266,23 @@ nofl_space_evacuate_or_mark_object(struct nofl_space *space,
gc_edge_update(edge, gc_ref(gc_atomic_forward_address(&fwd))); gc_edge_update(edge, gc_ref(gc_atomic_forward_address(&fwd)));
return 0; return 0;
} }
} }
uint8_t mask = NOFL_METADATA_BYTE_YOUNG | NOFL_METADATA_BYTE_MARK_0 static inline int
| NOFL_METADATA_BYTE_MARK_1 | NOFL_METADATA_BYTE_MARK_2; nofl_space_evacuate_or_mark_object(struct nofl_space *space,
*metadata = (byte & ~mask) | space->marked_mask; struct gc_edge edge,
return 1; struct gc_ref old_ref,
struct nofl_allocator *evacuate) {
uint8_t *metadata = nofl_metadata_byte_for_object(old_ref);
uint8_t byte = *metadata;
if (byte & space->marked_mask)
return 0;
if (nofl_space_should_evacuate(space, old_ref))
return nofl_space_evacuate(space, metadata, byte, edge, old_ref,
evacuate);
return nofl_space_set_mark(space, metadata, byte);
} }
static inline int static inline int
@ -1282,21 +1301,10 @@ nofl_space_contains(struct nofl_space *space, struct gc_ref ref) {
return nofl_space_contains_address(space, gc_ref_value(ref)); return nofl_space_contains_address(space, gc_ref_value(ref));
} }
static int static inline int
nofl_space_forward_or_mark_if_traced(struct nofl_space *space, nofl_space_forward_if_evacuated(struct nofl_space *space,
struct gc_edge edge, struct gc_edge edge,
struct gc_ref ref) { struct gc_ref ref) {
uint8_t *metadata = nofl_metadata_byte_for_object(ref);
uint8_t byte = *metadata;
if (byte & space->marked_mask)
return 1;
if (!space->evacuating)
return 0;
if (!nofl_block_summary_has_flag(nofl_block_summary_for_addr(gc_ref_value(ref)),
NOFL_BLOCK_EVACUATE))
return 0;
struct gc_atomic_forward fwd = gc_atomic_forward_begin(ref); struct gc_atomic_forward fwd = gc_atomic_forward_begin(ref);
switch (fwd.state) { switch (fwd.state) {
case GC_FORWARDING_STATE_NOT_FORWARDED: case GC_FORWARDING_STATE_NOT_FORWARDED:
@ -1322,6 +1330,21 @@ nofl_space_forward_or_mark_if_traced(struct nofl_space *space,
} }
} }
static int
nofl_space_forward_or_mark_if_traced(struct nofl_space *space,
struct gc_edge edge,
struct gc_ref ref) {
uint8_t *metadata = nofl_metadata_byte_for_object(ref);
uint8_t byte = *metadata;
if (byte & space->marked_mask)
return 1;
if (!nofl_space_should_evacuate(space, ref))
return 0;
return nofl_space_forward_if_evacuated(space, edge, ref);
}
static inline struct gc_ref static inline struct gc_ref
nofl_space_mark_conservative_ref(struct nofl_space *space, nofl_space_mark_conservative_ref(struct nofl_space *space,
struct gc_conservative_ref ref, struct gc_conservative_ref ref,