1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

Add finalizers

This commit is contained in:
Andy Wingo 2024-07-23 22:32:57 +02:00
parent 9167dbb5f6
commit f6057184e1
18 changed files with 756 additions and 28 deletions

View file

@ -301,6 +301,7 @@ struct gc_heap {
int mark_while_stopping;
int check_pending_ephemerons;
struct gc_pending_ephemerons *pending_ephemerons;
struct gc_finalizer_state *finalizer_state;
enum gc_collection_kind gc_kind;
int multithreaded;
size_t mutator_count;
@ -1231,8 +1232,28 @@ static inline void trace_one(struct gc_ref ref, struct gc_heap *heap,
static inline void trace_root(struct gc_root root,
struct gc_heap *heap,
struct gc_trace_worker *worker) {
// We don't use parallel root tracing yet.
GC_CRASH();
switch (root.kind) {
case GC_ROOT_KIND_HEAP:
gc_trace_heap_roots(root.heap->roots, tracer_visit, heap, worker);
break;
case GC_ROOT_KIND_MUTATOR:
gc_trace_mutator_roots(root.mutator->roots, tracer_visit, heap, worker);
break;
case GC_ROOT_KIND_RESOLVED_EPHEMERONS:
gc_trace_resolved_ephemerons(root.resolved_ephemerons, tracer_visit,
heap, worker);
break;
case GC_ROOT_KIND_EDGE:
tracer_visit(root.edge, heap, worker);
break;
default:
GC_CRASH();
}
}
static void visit_root_edge(struct gc_edge edge, struct gc_heap *heap,
void *unused) {
gc_tracer_add_root(&heap->tracer, gc_root_edge(edge));
}
static void
@ -1823,6 +1844,7 @@ static void trace_pinned_roots_after_stop(struct gc_heap *heap) {
static void trace_roots_after_stop(struct gc_heap *heap) {
trace_mutator_roots_after_stop(heap);
gc_trace_heap_roots(heap->roots, trace_and_enqueue_globally, heap, NULL);
gc_visit_finalizer_roots(heap->finalizer_state, visit_root_edge, heap, NULL);
trace_generational_roots(heap);
}
@ -1890,6 +1912,28 @@ static int enqueue_resolved_ephemerons(struct gc_heap *heap) {
return 1;
}
static void trace_resolved_ephemerons(struct gc_heap *heap) {
for (struct gc_ephemeron *resolved = gc_pop_resolved_ephemerons(heap);
resolved;
resolved = gc_pop_resolved_ephemerons(heap)) {
gc_tracer_add_root(&heap->tracer, gc_root_resolved_ephemerons(resolved));
gc_tracer_trace(&heap->tracer);
}
}
static void resolve_finalizers(struct gc_heap *heap) {
for (size_t priority = 0;
priority < gc_finalizer_priority_count();
priority++) {
if (gc_resolve_finalizers(heap->finalizer_state, priority,
visit_root_edge, heap, NULL)) {
gc_tracer_trace(&heap->tracer);
trace_resolved_ephemerons(heap);
}
}
gc_notify_finalizers(heap->finalizer_state, heap);
}
static void sweep_ephemerons(struct gc_heap *heap) {
return gc_sweep_pending_ephemerons(heap->pending_ephemerons, 0, 1);
}
@ -1934,9 +1978,10 @@ static void collect(struct gc_mutator *mut,
gc_tracer_trace(&heap->tracer);
HEAP_EVENT(heap, heap_traced);
resolve_ephemerons_eagerly(heap);
while (enqueue_resolved_ephemerons(heap))
gc_tracer_trace(&heap->tracer);
trace_resolved_ephemerons(heap);
HEAP_EVENT(heap, ephemerons_traced);
resolve_finalizers(heap);
HEAP_EVENT(heap, finalizers_traced);
sweep_ephemerons(heap);
gc_tracer_release(&heap->tracer);
mark_space_finish_gc(space, gc_kind);
@ -2322,6 +2367,28 @@ unsigned gc_heap_ephemeron_trace_epoch(struct gc_heap *heap) {
return heap->count;
}
struct gc_finalizer* gc_allocate_finalizer(struct gc_mutator *mut) {
return gc_allocate(mut, gc_finalizer_size());
}
void gc_finalizer_attach(struct gc_mutator *mut, struct gc_finalizer *finalizer,
unsigned priority, struct gc_ref object,
struct gc_ref closure) {
gc_finalizer_init_internal(finalizer, object, closure);
gc_finalizer_attach_internal(mutator_heap(mut)->finalizer_state,
finalizer, priority);
// No write barrier.
}
struct gc_finalizer* gc_finalizer_pop(struct gc_mutator *mut) {
return gc_finalizer_state_pop(mutator_heap(mut)->finalizer_state);
}
void gc_set_finalizer_callback(struct gc_heap *heap,
gc_finalizer_callback callback) {
gc_finalizer_state_set_callback(heap->finalizer_state, callback);
}
static struct slab* allocate_slabs(size_t nslabs) {
size_t size = nslabs * SLAB_SIZE;
size_t extent = size + SLAB_SIZE;
@ -2406,6 +2473,10 @@ static int heap_init(struct gc_heap *heap, const struct gc_options *options) {
if (!heap_prepare_pending_ephemerons(heap))
GC_CRASH();
heap->finalizer_state = gc_make_finalizer_state();
if (!heap->finalizer_state)
GC_CRASH();
return 1;
}