1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-12 14:50:19 +02:00

Merge remote-tracking branch 'whippet/main' into wip-whippet

This commit is contained in:
Andy Wingo 2025-05-21 14:28:34 +02:00
commit fb5a99c752
10 changed files with 145 additions and 71 deletions

View file

@ -88,8 +88,6 @@ static inline void gc_update_alloc_table(struct gc_ref obj, size_t size,
alloc[0] = begin_pattern | end_pattern; alloc[0] = begin_pattern | end_pattern;
} else { } else {
alloc[0] = begin_pattern; alloc[0] = begin_pattern;
if (granules > 2)
memset(alloc + 1, 0, granules - 2);
alloc[granules - 1] = end_pattern; alloc[granules - 1] = end_pattern;
} }
} else { } else {

View file

@ -22,7 +22,6 @@ GC_EMBEDDER_API inline int gc_is_valid_conservative_ref_displacement(uintptr_t d
GC_EMBEDDER_API inline size_t gc_finalizer_priority_count(void); GC_EMBEDDER_API inline size_t gc_finalizer_priority_count(void);
GC_EMBEDDER_API inline int gc_extern_space_visit(struct gc_extern_space *space, GC_EMBEDDER_API inline int gc_extern_space_visit(struct gc_extern_space *space,
struct gc_edge edge,
struct gc_ref ref) GC_ALWAYS_INLINE; struct gc_ref ref) GC_ALWAYS_INLINE;
GC_EMBEDDER_API inline void gc_extern_space_start_gc(struct gc_extern_space *space, GC_EMBEDDER_API inline void gc_extern_space_start_gc(struct gc_extern_space *space,
int is_minor_gc); int is_minor_gc);
@ -51,23 +50,29 @@ GC_EMBEDDER_API inline void gc_trace_heap_roots(struct gc_heap_roots *roots,
void *trace_data); void *trace_data);
GC_EMBEDDER_API inline void GC_EMBEDDER_API inline void
gc_trace_mutator_conservative_roots(struct gc_mutator_roots *roots, gc_trace_mutator_pinned_roots(struct gc_mutator_roots *roots,
void (*trace_range)(uintptr_t start, void (*trace_pinned)(struct gc_ref ref,
uintptr_t end, struct gc_heap *heap,
int possibly_interior, void *data),
struct gc_heap *heap, void (*trace_ambiguous)(uintptr_t start,
void *data), uintptr_t end,
struct gc_heap *heap, int possibly_interior,
void *data); struct gc_heap *heap,
void *data),
struct gc_heap *heap,
void *data);
GC_EMBEDDER_API inline void GC_EMBEDDER_API inline void
gc_trace_heap_conservative_roots(struct gc_heap_roots *roots, gc_trace_heap_pinned_roots(struct gc_heap_roots *roots,
void (*trace_range)(uintptr_t start, void (*trace_pinned)(struct gc_ref ref,
uintptr_t end, struct gc_heap *heap,
int possibly_interior, void *data),
struct gc_heap *heap, void (*trace_ambiguous)(uintptr_t start,
void *data), uintptr_t end,
struct gc_heap *heap, int possibly_interior,
void *data); struct gc_heap *heap,
void *data),
struct gc_heap *heap,
void *data);
GC_EMBEDDER_API inline uintptr_t gc_object_forwarded_nonatomic(struct gc_ref ref); GC_EMBEDDER_API inline uintptr_t gc_object_forwarded_nonatomic(struct gc_ref ref);
GC_EMBEDDER_API inline void gc_object_forward_nonatomic(struct gc_ref ref, GC_EMBEDDER_API inline void gc_object_forward_nonatomic(struct gc_ref ref,

View file

@ -23,7 +23,6 @@ gc_is_valid_conservative_ref_displacement(uintptr_t displacement) {
// No external objects in simple benchmarks. // No external objects in simple benchmarks.
static inline int gc_extern_space_visit(struct gc_extern_space *space, static inline int gc_extern_space_visit(struct gc_extern_space *space,
struct gc_edge edge,
struct gc_ref ref) { struct gc_ref ref) {
GC_CRASH(); GC_CRASH();
} }
@ -93,24 +92,30 @@ static inline void gc_trace_heap_roots(struct gc_heap_roots *roots,
} }
static inline void static inline void
gc_trace_mutator_conservative_roots(struct gc_mutator_roots *roots, gc_trace_mutator_pinned_roots(struct gc_mutator_roots *roots,
void (*trace_range)(uintptr_t start, void (*trace_pinned)(struct gc_ref ref,
uintptr_t end, struct gc_heap *heap,
int possibly_interior, void *data),
struct gc_heap *heap, void (*trace_ambiguous)(uintptr_t start,
void *data), uintptr_t end,
struct gc_heap *heap, int possibly_interior,
void *data) {} struct gc_heap *heap,
void *data),
struct gc_heap *heap,
void *data) {}
static inline void static inline void
gc_trace_heap_conservative_roots(struct gc_heap_roots *roots, gc_trace_heap_pinned_roots(struct gc_heap_roots *roots,
void (*trace_range)(uintptr_t start, void (*trace_pinned)(struct gc_ref ref,
uintptr_t end, struct gc_heap *heap,
int possibly_interior, void *data),
struct gc_heap *heap, void (*trace_ambiguous)(uintptr_t start,
void *data), uintptr_t end,
struct gc_heap *heap, int possibly_interior,
void *data) {} struct gc_heap *heap,
void *data),
struct gc_heap *heap,
void *data) {}
static inline uintptr_t gc_object_forwarded_nonatomic(struct gc_ref ref) { static inline uintptr_t gc_object_forwarded_nonatomic(struct gc_ref ref) {
uintptr_t tag = *tag_word(ref); uintptr_t tag = *tag_word(ref);

View file

@ -5,6 +5,7 @@
#define GC_IMPL 1 #define GC_IMPL 1
#include "gc-align.h"
#include "gc-api.h" #include "gc-api.h"
#include "gc-ephemeron.h" #include "gc-ephemeron.h"
#include "gc-tracepoint.h" #include "gc-tracepoint.h"
@ -218,16 +219,20 @@ struct bdw_mark_state {
struct GC_ms_entry *mark_stack_limit; struct GC_ms_entry *mark_stack_limit;
}; };
static void bdw_mark_edge(struct gc_edge edge, struct gc_heap *heap, static void bdw_mark(struct gc_ref ref, struct gc_heap *heap,
void *visit_data) { void *visit_data) {
struct bdw_mark_state *state = visit_data; struct bdw_mark_state *state = visit_data;
uintptr_t addr = gc_ref_value(gc_edge_ref(edge)); state->mark_stack_ptr = GC_MARK_AND_PUSH ((void *) gc_ref_value(ref),
state->mark_stack_ptr = GC_MARK_AND_PUSH ((void *) addr,
state->mark_stack_ptr, state->mark_stack_ptr,
state->mark_stack_limit, state->mark_stack_limit,
NULL); NULL);
} }
static void bdw_mark_edge(struct gc_edge edge, struct gc_heap *heap,
void *visit_data) {
bdw_mark(gc_edge_ref(edge), heap, visit_data);
}
static void bdw_mark_range(uintptr_t lo, uintptr_t hi, int possibly_interior, static void bdw_mark_range(uintptr_t lo, uintptr_t hi, int possibly_interior,
struct gc_heap *heap, void *visit_data) { struct gc_heap *heap, void *visit_data) {
struct bdw_mark_state *state = visit_data; struct bdw_mark_state *state = visit_data;
@ -395,7 +400,8 @@ mark_heap(GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
return state.mark_stack_ptr; return state.mark_stack_ptr;
if (heap->roots) { if (heap->roots) {
gc_trace_heap_conservative_roots(heap->roots, bdw_mark_range, heap, &state); gc_trace_heap_pinned_roots(heap->roots, bdw_mark, bdw_mark_range,
heap, &state);
gc_trace_heap_roots(heap->roots, bdw_mark_edge, heap, &state); gc_trace_heap_roots(heap->roots, bdw_mark_edge, heap, &state);
} }
@ -432,8 +438,8 @@ mark_mutator(GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
memset(mut->freelists, 0, sizeof(void*) * GC_INLINE_FREELIST_COUNT); memset(mut->freelists, 0, sizeof(void*) * GC_INLINE_FREELIST_COUNT);
if (mut->roots) { if (mut->roots) {
gc_trace_mutator_conservative_roots(mut->roots, bdw_mark_range, gc_trace_mutator_pinned_roots(mut->roots, bdw_mark, bdw_mark_range,
mut->heap, &state); mut->heap, &state);
gc_trace_mutator_roots(mut->roots, bdw_mark_edge, mut->heap, &state); gc_trace_mutator_roots(mut->roots, bdw_mark_edge, mut->heap, &state);
} }

View file

@ -88,6 +88,8 @@ static int visit_roots(struct dl_phdr_info *info, size_t size, void *data) {
if (p->p_type == PT_LOAD && (p->p_flags & PF_W)) { if (p->p_type == PT_LOAD && (p->p_flags & PF_W)) {
uintptr_t start = p->p_vaddr + object_addr; uintptr_t start = p->p_vaddr + object_addr;
uintptr_t end = start + p->p_memsz; uintptr_t end = start + p->p_memsz;
start = align_up(start, sizeof(void*));
end = align_down(end, sizeof(void*));
DEBUG("found roots for '%s': [%p,%p)\n", object_name, DEBUG("found roots for '%s': [%p,%p)\n", object_name,
(void*)start, (void*)end); (void*)start, (void*)end);
visit_data->f(start, end, visit_data->heap, visit_data->data); visit_data->f(start, end, visit_data->heap, visit_data->data);

View file

@ -146,7 +146,7 @@ do_trace(struct gc_heap *heap, struct gc_edge edge, struct gc_ref ref,
else if (large_object_space_contains_with_lock(heap_large_object_space(heap), ref)) else if (large_object_space_contains_with_lock(heap_large_object_space(heap), ref))
return large_object_space_mark(heap_large_object_space(heap), ref); return large_object_space_mark(heap_large_object_space(heap), ref);
else else
return gc_extern_space_visit(heap_extern_space(heap), edge, ref); return gc_extern_space_visit(heap_extern_space(heap), ref);
} }
static inline int static inline int
@ -166,6 +166,34 @@ trace_edge(struct gc_heap *heap, struct gc_edge edge,
return is_new; return is_new;
} }
static inline int
do_trace_pinned(struct gc_heap *heap, struct gc_ref ref,
struct gc_trace_worker_data *data) {
if (GC_LIKELY(nofl_space_contains(heap_nofl_space(heap), ref)))
return nofl_space_mark_object(heap_nofl_space(heap), ref, &data->allocator);
else if (large_object_space_contains_with_lock(heap_large_object_space(heap),
ref))
return large_object_space_mark(heap_large_object_space(heap), ref);
else
return gc_extern_space_visit(heap_extern_space(heap), ref);
}
static inline int
trace_pinned_edge(struct gc_heap *heap, struct gc_ref ref,
struct gc_trace_worker_data *data) {
if (gc_ref_is_null(ref) || gc_ref_is_immediate(ref))
return 0;
int is_new = do_trace_pinned(heap, ref, data);
if (is_new &&
GC_UNLIKELY(atomic_load_explicit(&heap->check_pending_ephemerons,
memory_order_relaxed)))
gc_resolve_pending_ephemerons(ref, heap);
return is_new;
}
int int
gc_visit_ephemeron_key(struct gc_edge edge, struct gc_heap *heap) { gc_visit_ephemeron_key(struct gc_edge edge, struct gc_heap *heap) {
struct gc_ref ref = gc_edge_ref(edge); struct gc_ref ref = gc_edge_ref(edge);
@ -274,6 +302,17 @@ tracer_visit(struct gc_edge edge, struct gc_heap *heap, void *trace_data) {
gc_trace_worker_enqueue(worker, gc_edge_ref(edge)); gc_trace_worker_enqueue(worker, gc_edge_ref(edge));
} }
static inline void
tracer_visit_pinned_root(struct gc_ref ref, struct gc_heap *heap,
void *trace_data) GC_ALWAYS_INLINE;
static inline void
tracer_visit_pinned_root(struct gc_ref ref, struct gc_heap *heap,
void *trace_data) {
struct gc_trace_worker *worker = trace_data;
if (trace_pinned_edge(heap, ref, gc_trace_worker_data(worker)))
gc_trace_worker_enqueue(worker, ref);
}
static inline int static inline int
trace_remembered_edge(struct gc_edge edge, struct gc_heap *heap, void *trace_data) { trace_remembered_edge(struct gc_edge edge, struct gc_heap *heap, void *trace_data) {
tracer_visit(edge, heap, trace_data); tracer_visit(edge, heap, trace_data);
@ -331,8 +370,8 @@ static inline void
trace_conservative_edges(uintptr_t low, uintptr_t high, int possibly_interior, trace_conservative_edges(uintptr_t low, uintptr_t high, int possibly_interior,
struct gc_heap *heap, void *data) { struct gc_heap *heap, void *data) {
struct gc_trace_worker *worker = data; struct gc_trace_worker *worker = data;
GC_ASSERT(low == align_down(low, sizeof(uintptr_t))); GC_ASSERT_EQ(low, align_down(low, sizeof(uintptr_t)));
GC_ASSERT(high == align_down(high, sizeof(uintptr_t))); GC_ASSERT_EQ(high, align_down(high, sizeof(uintptr_t)));
for (uintptr_t addr = low; addr < high; addr += sizeof(uintptr_t)) for (uintptr_t addr = low; addr < high; addr += sizeof(uintptr_t))
tracer_trace_conservative_ref(load_conservative_ref(addr), heap, worker, tracer_trace_conservative_ref(load_conservative_ref(addr), heap, worker,
possibly_interior); possibly_interior);
@ -404,13 +443,17 @@ trace_root(struct gc_root root, struct gc_heap *heap,
gc_field_set_visit_edge_buffer(&heap->remembered_set, root.edge_buffer, gc_field_set_visit_edge_buffer(&heap->remembered_set, root.edge_buffer,
trace_remembered_edge, heap, worker); trace_remembered_edge, heap, worker);
break; break;
case GC_ROOT_KIND_HEAP_CONSERVATIVE_ROOTS: case GC_ROOT_KIND_HEAP_PINNED_ROOTS:
gc_trace_heap_conservative_roots(root.heap->roots, trace_conservative_edges, gc_trace_heap_pinned_roots(root.heap->roots,
heap, worker); tracer_visit_pinned_root,
trace_conservative_edges,
heap, worker);
break; break;
case GC_ROOT_KIND_MUTATOR_CONSERVATIVE_ROOTS: case GC_ROOT_KIND_MUTATOR_PINNED_ROOTS:
gc_trace_mutator_conservative_roots(root.mutator->roots, gc_trace_mutator_pinned_roots(root.mutator->roots,
trace_conservative_edges, heap, worker); tracer_visit_pinned_root,
trace_conservative_edges,
heap, worker);
break; break;
default: default:
GC_CRASH(); GC_CRASH();
@ -671,7 +714,7 @@ enqueue_mutator_conservative_roots(struct gc_heap *heap) {
&possibly_interior); &possibly_interior);
if (mut->roots) if (mut->roots)
gc_tracer_add_root(&heap->tracer, gc_tracer_add_root(&heap->tracer,
gc_root_mutator_conservative_roots(mut)); gc_root_mutator_pinned_roots(mut));
} }
return 1; return 1;
} }
@ -685,7 +728,7 @@ enqueue_global_conservative_roots(struct gc_heap *heap) {
gc_platform_visit_global_conservative_roots gc_platform_visit_global_conservative_roots
(enqueue_conservative_roots, heap, &possibly_interior); (enqueue_conservative_roots, heap, &possibly_interior);
if (heap->roots) if (heap->roots)
gc_tracer_add_root(&heap->tracer, gc_root_heap_conservative_roots(heap)); gc_tracer_add_root(&heap->tracer, gc_root_heap_pinned_roots(heap));
return 1; return 1;
} }
return 0; return 0;

View file

@ -298,7 +298,9 @@ nofl_metadata_byte_for_addr(uintptr_t addr) {
static uint8_t* static uint8_t*
nofl_metadata_byte_for_object(struct gc_ref ref) { nofl_metadata_byte_for_object(struct gc_ref ref) {
return nofl_metadata_byte_for_addr(gc_ref_value(ref)); uint8_t *ret = nofl_metadata_byte_for_addr(gc_ref_value(ref));
GC_ASSERT(*ret & NOFL_METADATA_BYTE_MARK_MASK);
return ret;
} }
static uint8_t* static uint8_t*
@ -932,7 +934,7 @@ nofl_finish_sweeping(struct nofl_allocator *alloc,
static inline int static inline int
nofl_is_ephemeron(struct gc_ref ref) { nofl_is_ephemeron(struct gc_ref ref) {
uint8_t meta = *nofl_metadata_byte_for_addr(gc_ref_value(ref)); uint8_t meta = *nofl_metadata_byte_for_object(ref);
uint8_t kind = meta & NOFL_METADATA_BYTE_TRACE_KIND_MASK; uint8_t kind = meta & NOFL_METADATA_BYTE_TRACE_KIND_MASK;
return kind == NOFL_METADATA_BYTE_TRACE_EPHEMERON; return kind == NOFL_METADATA_BYTE_TRACE_EPHEMERON;
} }
@ -940,7 +942,7 @@ nofl_is_ephemeron(struct gc_ref ref) {
static void static void
nofl_space_set_ephemeron_flag(struct gc_ref ref) { nofl_space_set_ephemeron_flag(struct gc_ref ref) {
if (gc_has_conservative_intraheap_edges()) { if (gc_has_conservative_intraheap_edges()) {
uint8_t *metadata = nofl_metadata_byte_for_addr(gc_ref_value(ref)); uint8_t *metadata = nofl_metadata_byte_for_object(ref);
uint8_t byte = *metadata & ~NOFL_METADATA_BYTE_TRACE_KIND_MASK; uint8_t byte = *metadata & ~NOFL_METADATA_BYTE_TRACE_KIND_MASK;
*metadata = byte | NOFL_METADATA_BYTE_TRACE_EPHEMERON; *metadata = byte | NOFL_METADATA_BYTE_TRACE_EPHEMERON;
} }
@ -1558,7 +1560,7 @@ nofl_space_evacuate(struct nofl_space *space, uint8_t *metadata, uint8_t byte,
gc_atomic_forward_commit(&fwd, new_ref); gc_atomic_forward_commit(&fwd, new_ref);
// Now update extent metadata, and indicate to the caller that // Now update extent metadata, and indicate to the caller that
// the object's fields need to be traced. // the object's fields need to be traced.
uint8_t *new_metadata = nofl_metadata_byte_for_object(new_ref); uint8_t *new_metadata = nofl_metadata_byte_for_addr(gc_ref_value(new_ref));
memcpy(new_metadata + 1, metadata + 1, object_granules - 1); memcpy(new_metadata + 1, metadata + 1, object_granules - 1);
if (GC_GENERATIONAL) if (GC_GENERATIONAL)
byte = clear_logged_bits_in_evacuated_object(byte, new_metadata, byte = clear_logged_bits_in_evacuated_object(byte, new_metadata,
@ -1615,6 +1617,19 @@ nofl_space_evacuate_or_mark_object(struct nofl_space *space,
return nofl_space_set_nonempty_mark(space, metadata, byte, old_ref); return nofl_space_set_nonempty_mark(space, metadata, byte, old_ref);
} }
static inline int
nofl_space_mark_object(struct nofl_space *space, struct gc_ref ref,
struct nofl_allocator *evacuate) {
uint8_t *metadata = nofl_metadata_byte_for_object(ref);
uint8_t byte = *metadata;
if (nofl_metadata_byte_has_mark(byte, space->current_mark))
return 0;
GC_ASSERT(!nofl_space_should_evacuate(space, byte, ref));
return nofl_space_set_nonempty_mark(space, metadata, byte, ref);
}
static inline int static inline int
nofl_space_forward_if_evacuated(struct nofl_space *space, nofl_space_forward_if_evacuated(struct nofl_space *space,
struct gc_edge edge, struct gc_edge edge,
@ -1719,6 +1734,7 @@ nofl_space_mark_conservative_ref(struct nofl_space *space,
addr = block_base + (loc - loc_base) * NOFL_GRANULE_SIZE; addr = block_base + (loc - loc_base) * NOFL_GRANULE_SIZE;
} }
GC_ASSERT(*loc & NOFL_METADATA_BYTE_MARK_MASK);
nofl_space_set_nonempty_mark(space, loc, byte, gc_ref(addr)); nofl_space_set_nonempty_mark(space, loc, byte, gc_ref(addr));
return gc_ref(addr); return gc_ref(addr);

View file

@ -422,7 +422,7 @@ static inline int do_trace(struct gc_heap *heap, struct gc_edge edge,
if (large_object_space_contains_with_lock(heap_large_object_space(heap), ref)) if (large_object_space_contains_with_lock(heap_large_object_space(heap), ref))
return large_object_space_mark(heap_large_object_space(heap), ref); return large_object_space_mark(heap_large_object_space(heap), ref);
else else
return gc_extern_space_visit(heap_extern_space(heap), edge, ref); return gc_extern_space_visit(heap_extern_space(heap), ref);
} }
static inline int trace_edge(struct gc_heap *heap, struct gc_edge edge, static inline int trace_edge(struct gc_heap *heap, struct gc_edge edge,

View file

@ -18,8 +18,8 @@ enum gc_root_kind {
GC_ROOT_KIND_RESOLVED_EPHEMERONS, GC_ROOT_KIND_RESOLVED_EPHEMERONS,
GC_ROOT_KIND_EDGE, GC_ROOT_KIND_EDGE,
GC_ROOT_KIND_EDGE_BUFFER, GC_ROOT_KIND_EDGE_BUFFER,
GC_ROOT_KIND_HEAP_CONSERVATIVE_ROOTS, GC_ROOT_KIND_HEAP_PINNED_ROOTS,
GC_ROOT_KIND_MUTATOR_CONSERVATIVE_ROOTS, GC_ROOT_KIND_MUTATOR_PINNED_ROOTS,
}; };
struct gc_root { struct gc_root {
@ -81,15 +81,15 @@ gc_root_edge_buffer(struct gc_edge_buffer *buf) {
} }
static inline struct gc_root static inline struct gc_root
gc_root_heap_conservative_roots(struct gc_heap* heap) { gc_root_heap_pinned_roots(struct gc_heap* heap) {
struct gc_root ret = { GC_ROOT_KIND_HEAP_CONSERVATIVE_ROOTS }; struct gc_root ret = { GC_ROOT_KIND_HEAP_PINNED_ROOTS };
ret.heap = heap; ret.heap = heap;
return ret; return ret;
} }
static inline struct gc_root static inline struct gc_root
gc_root_mutator_conservative_roots(struct gc_mutator* mutator) { gc_root_mutator_pinned_roots(struct gc_mutator* mutator) {
struct gc_root ret = { GC_ROOT_KIND_MUTATOR_CONSERVATIVE_ROOTS }; struct gc_root ret = { GC_ROOT_KIND_MUTATOR_PINNED_ROOTS };
ret.mutator = mutator; ret.mutator = mutator;
return ret; return ret;
} }

View file

@ -236,13 +236,12 @@ static int semi_space_contains(struct semi_space *space, struct gc_ref ref) {
static void visit_external_object(struct gc_heap *heap, static void visit_external_object(struct gc_heap *heap,
struct gc_extern_space *space, struct gc_extern_space *space,
struct gc_edge edge, struct gc_ref ref) {
struct gc_ref old_ref) { if (gc_extern_space_visit(space, ref)) {
if (gc_extern_space_visit(space, edge, old_ref)) {
if (GC_UNLIKELY(heap->check_pending_ephemerons)) if (GC_UNLIKELY(heap->check_pending_ephemerons))
gc_resolve_pending_ephemerons(old_ref, heap); gc_resolve_pending_ephemerons(ref, heap);
gc_trace_object(gc_edge_ref(edge), trace, heap, NULL, NULL); gc_trace_object(ref, trace, heap, NULL, NULL);
} }
} }
@ -256,7 +255,7 @@ static void visit(struct gc_edge edge, struct gc_heap *heap) {
ref)) ref))
visit_large_object_space(heap, heap_large_object_space(heap), ref); visit_large_object_space(heap, heap_large_object_space(heap), ref);
else else
visit_external_object(heap, heap->extern_space, edge, ref); visit_external_object(heap, heap->extern_space, ref);
} }
struct gc_pending_ephemerons * struct gc_pending_ephemerons *