1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-09 07:00:23 +02:00

Refactor embedder interface for conservative GC

Now users don't have to #ifdef on conservative vs precise tracing; it's
just a generic embedder concern.
This commit is contained in:
Andy Wingo 2022-10-26 11:59:56 +02:00
parent 910b62af8f
commit c614c2e40b
14 changed files with 109 additions and 198 deletions

2
bdw.c
View file

@ -20,8 +20,6 @@
#error bdw-gc is a conservative collector
#endif
#include "conservative-roots-embedder.h"
// When pthreads are used, let `libgc' know about it and redirect
// allocation calls such as `GC_MALLOC ()' to (contention-free, faster)
// thread-local allocation.

View file

@ -1,12 +0,0 @@
#ifndef CONSERVATIVE_ROOTS_API_H
#define CONSERVATIVE_ROOTS_API_H
#include "conservative-roots-types.h"
#define HANDLE_TO(T) union { T* v; struct handle handle; }
#define HANDLE_REF(h) h.v
#define HANDLE_SET(h,val) do { h.v = val; } while (0)
#define PUSH_HANDLE(cx, h) do { (void) &h; } while (0)
#define POP_HANDLE(cx) do { } while (0)
#endif // CONSERVATIVE_ROOTS_API_H

View file

@ -1,54 +0,0 @@
#ifndef CONSERVATIVE_ROOTS_EMBEDDER_H
#define CONSERVATIVE_ROOTS_EMBEDDER_H
#include "gc-config.h"
#include "gc-embedder-api.h"
static inline int gc_has_mutator_conservative_roots(void) {
return 1;
}
static inline int gc_mutator_conservative_roots_may_be_interior(void) {
return 1;
}
static inline int gc_has_global_conservative_roots(void) {
return 1;
}
static inline int gc_has_conservative_intraheap_edges(void) {
return GC_CONSERVATIVE_TRACE;
}
static inline int
gc_is_valid_conservative_ref_displacement(uintptr_t displacement) {
// Here is where you would allow tagged heap object references.
return displacement == 0;
}
static inline int
gc_conservative_ref_might_be_a_heap_object(struct gc_conservative_ref ref,
int possibly_interior) {
// Assume that the minimum page size is 4096, and that the first page
// will contain no heap objects.
if (gc_conservative_ref_value(ref) < 4096)
return 0;
if (possibly_interior)
return 1;
return gc_is_valid_conservative_ref_displacement
(gc_conservative_ref_value(ref) & (sizeof(uintptr_t) - 1));
}
static inline void gc_trace_mutator_roots(struct gc_mutator_roots *roots,
void (*trace_edge)(struct gc_edge edge,
struct gc_heap *heap,
void *trace_data),
struct gc_heap *heap,
void *trace_data) {
}
static inline void gc_trace_heap_roots(struct gc_heap_roots *roots,
void (*trace_edge)(struct gc_edge edge,
struct gc_heap *heap,
void *trace_data),
struct gc_heap *heap,
void *trace_data) {
}
#endif // CONSERVATIVE_ROOTS_EMBEDDER_H

View file

@ -1,8 +0,0 @@
#ifndef CONSERVATIVE_ROOTS_TYPES_H
#define CONSERVATIVE_ROOTS_TYPES_H
struct handle { void *unused; };
struct gc_heap_roots { void *unused; };
struct gc_mutator_roots { void *unused; };
#endif // CONSERVATIVE_ROOTS_TYPES_H

View file

@ -1,7 +1,7 @@
#ifndef GC_EMBEDDER_API_H
#define GC_EMBEDDER_API_H
#include "gc-conservative-ref.h"
#include "gc-config.h"
#include "gc-edge.h"
#include "gc-forwarding.h"
@ -14,14 +14,7 @@ struct gc_heap_roots;
struct gc_atomic_forward;
struct gc_heap;
GC_EMBEDDER_API inline int gc_has_mutator_conservative_roots(void);
GC_EMBEDDER_API inline int gc_has_global_conservative_roots(void);
GC_EMBEDDER_API inline int gc_has_conservative_intraheap_edges(void);
GC_EMBEDDER_API inline int gc_mutator_conservative_roots_may_be_interior(void);
GC_EMBEDDER_API inline int gc_is_valid_conservative_ref_displacement(uintptr_t displacement);
GC_EMBEDDER_API inline int gc_conservative_ref_might_be_a_heap_object(struct gc_conservative_ref,
int possibly_interior);
GC_EMBEDDER_API inline void gc_trace_object(struct gc_ref ref,
void (*visit)(struct gc_edge edge,

44
gc-trace.h Normal file
View file

@ -0,0 +1,44 @@
#ifndef GC_TRACE_H
#define GC_TRACE_H
#ifndef GC_IMPL
#error internal header file, not part of API
#endif
#include "gc-config.h"
#include "gc-assert.h"
#include "gc-conservative-ref.h"
#include "gc-embedder-api.h"
static inline int gc_has_mutator_conservative_roots(void) {
return GC_CONSERVATIVE_ROOTS;
}
static inline int gc_mutator_conservative_roots_may_be_interior(void) {
return 1;
}
static inline int gc_has_global_conservative_roots(void) {
return GC_CONSERVATIVE_ROOTS;
}
static inline int gc_has_conservative_intraheap_edges(void) {
return GC_CONSERVATIVE_TRACE;
}
static inline int gc_has_conservative_roots(void) {
return gc_has_mutator_conservative_roots() ||
gc_has_global_conservative_roots();
}
static inline int
gc_conservative_ref_might_be_a_heap_object(struct gc_conservative_ref ref,
int possibly_interior) {
// Assume that the minimum page size is 4096, and that the first page
// will contain no heap objects.
if (gc_conservative_ref_value(ref) < 4096)
return 0;
if (possibly_interior)
return 1;
return gc_is_valid_conservative_ref_displacement
(gc_conservative_ref_value(ref) & (sizeof(uintptr_t) - 1));
}
#endif // GC_TRACE_H

View file

@ -47,13 +47,7 @@
#include "assert.h"
#include "gc-api.h"
#include "mt-gcbench-types.h"
#if GC_PRECISE_ROOTS
#include "precise-roots-api.h"
#endif
#if GC_CONSERVATIVE_ROOTS
#include "conservative-roots-api.h"
#endif
#include "mt-gcbench-types.h"
#include "simple-roots-api.h"
#include "simple-allocator.h"
#define MAX_THREAD_COUNT 256

View file

@ -1,61 +0,0 @@
#ifndef PRECISE_ROOTS_EMBEDDER_H
#define PRECISE_ROOTS_EMBEDDER_H
#include "gc-edge.h"
#include "gc-embedder-api.h"
#include "precise-roots-types.h"
static inline int gc_has_mutator_conservative_roots(void) {
return 0;
}
static inline int gc_mutator_conservative_roots_may_be_interior(void) {
return 0;
}
static inline int gc_has_global_conservative_roots(void) {
return 0;
}
static inline int gc_has_conservative_intraheap_edges(void) {
return 0;
}
static inline int
gc_is_valid_conservative_ref_displacement(uintptr_t displacement) {
GC_CRASH();
}
static inline int
gc_conservative_ref_might_be_a_heap_object(struct gc_conservative_ref ref,
int possibly_interior) {
GC_CRASH();
}
static inline void visit_roots(struct handle *roots,
void (*trace_edge)(struct gc_edge edge,
struct gc_heap *heap,
void *trace_data),
struct gc_heap *heap,
void *trace_data) {
for (struct handle *h = roots; h; h = h->next)
trace_edge(gc_edge(&h->v), heap, trace_data);
}
static inline void gc_trace_mutator_roots(struct gc_mutator_roots *roots,
void (*trace_edge)(struct gc_edge edge,
struct gc_heap *heap,
void *trace_data),
struct gc_heap *heap,
void *trace_data) {
if (roots)
visit_roots(roots->roots, trace_edge, heap, trace_data);
}
static inline void gc_trace_heap_roots(struct gc_heap_roots *roots,
void (*trace_edge)(struct gc_edge edge,
struct gc_heap *heap,
void *trace_data),
struct gc_heap *heap,
void *trace_data) {
if (roots)
visit_roots(roots->roots, trace_edge, heap, trace_data);
}
#endif // PRECISE_ROOTS_EMBEDDER_H

View file

@ -5,12 +5,7 @@
#include "assert.h"
#include "gc-api.h"
#if GC_PRECISE_ROOTS
#include "precise-roots-api.h"
#endif
#if GC_CONSERVATIVE_ROOTS
#include "conservative-roots-api.h"
#endif
#include "simple-roots-api.h"
#include "quads-types.h"
#include "simple-allocator.h"

4
semi.c
View file

@ -11,10 +11,6 @@
#include "semi-attrs.h"
#include "large-object-space.h"
#if GC_PRECISE_ROOTS
#include "precise-roots-embedder.h"
#endif
#if GC_CONSERVATIVE_ROOTS
#error semi is a precise collector
#endif

View file

@ -1,8 +1,21 @@
#include <stdatomic.h>
#include "simple-tagging-scheme.h"
#include "simple-roots-types.h"
#include "gc-config.h"
#include "gc-embedder-api.h"
static inline int
gc_is_valid_conservative_ref_displacement(uintptr_t displacement) {
#if GC_CONSERVATIVE_ROOTS || GC_CONSERVATIVE_TRACE
// Here is where you would allow tagged heap object references.
return displacement == 0;
#else
// Shouldn't get here.
GC_CRASH();
#endif
}
static inline void gc_trace_object(struct gc_ref ref,
void (*trace_edge)(struct gc_edge edge,
struct gc_heap *heap,
@ -10,6 +23,10 @@ static inline void gc_trace_object(struct gc_ref ref,
struct gc_heap *heap,
void *trace_data,
size_t *size) {
#if GC_CONSERVATIVE_TRACE
// Shouldn't get here.
GC_CRASH();
#else
switch (tag_live_alloc_kind(*tag_word(ref))) {
#define SCAN_OBJECT(name, Name, NAME) \
case ALLOC_KIND_##NAME: \
@ -24,15 +41,38 @@ static inline void gc_trace_object(struct gc_ref ref,
default:
GC_CRASH();
}
#endif
}
#if GC_PRECISE_ROOTS
#include "precise-roots-embedder.h"
#endif
static inline void visit_roots(struct handle *roots,
void (*trace_edge)(struct gc_edge edge,
struct gc_heap *heap,
void *trace_data),
struct gc_heap *heap,
void *trace_data) {
for (struct handle *h = roots; h; h = h->next)
trace_edge(gc_edge(&h->v), heap, trace_data);
}
#if GC_CONSERVATIVE_ROOTS
#include "conservative-roots-embedder.h"
#endif
static inline void gc_trace_mutator_roots(struct gc_mutator_roots *roots,
void (*trace_edge)(struct gc_edge edge,
struct gc_heap *heap,
void *trace_data),
struct gc_heap *heap,
void *trace_data) {
if (roots)
visit_roots(roots->roots, trace_edge, heap, trace_data);
}
static inline void gc_trace_heap_roots(struct gc_heap_roots *roots,
void (*trace_edge)(struct gc_edge edge,
struct gc_heap *heap,
void *trace_data),
struct gc_heap *heap,
void *trace_data) {
if (roots)
visit_roots(roots->roots, trace_edge, heap, trace_data);
}
static inline uintptr_t gc_object_forwarded_nonatomic(struct gc_ref ref) {
uintptr_t tag = *tag_word(ref);
@ -108,9 +148,3 @@ gc_atomic_forward_address(struct gc_atomic_forward *fwd) {
GC_ASSERT(fwd->state == GC_FORWARDING_STATE_FORWARDED);
return fwd->data;
}
static inline uintptr_t
gc_conservative_ref_heap_address(struct gc_conservative_ref ref) {
// The specific spaces are responsible for checking alignment.
return gc_conservative_ref_value(ref);
}

View file

@ -1,7 +1,8 @@
#ifndef PRECISE_ROOTS_API_H
#define PRECISE_ROOTS_API_H
#ifndef SIMPLE_ROOTS_API_H
#define SIMPLE_ROOTS_API_H
#include "precise-roots-types.h"
#include "gc-config.h"
#include "simple-roots-types.h"
#define HANDLE_TO(T) union { T* v; struct handle handle; }
#define HANDLE_REF(h) h.v
@ -10,12 +11,15 @@
#define POP_HANDLE(cx) pop_handle(&(cx)->roots.roots)
static inline void push_handle(struct handle **roots, struct handle *handle) {
handle->next = *roots;
*roots = handle;
if (GC_PRECISE_ROOTS) {
handle->next = *roots;
*roots = handle;
}
}
static inline void pop_handle(struct handle **roots) {
*roots = (*roots)->next;
if (GC_PRECISE_ROOTS)
*roots = (*roots)->next;
}
#endif // PRECISE_ROOTS_API_H
#endif // SIMPLE_ROOTS_API_H

View file

@ -1,5 +1,5 @@
#ifndef PRECISE_ROOTS_TYPES_H
#define PRECISE_ROOTS_TYPES_H
#ifndef SIMPLE_ROOTS_TYPES_H
#define SIMPLE_ROOTS_TYPES_H
struct handle {
void *v;
@ -14,4 +14,4 @@ struct gc_mutator_roots {
struct handle *roots;
};
#endif // PRECISE_ROOTS_TYPES_H
#endif // SIMPLE_ROOTS_TYPES_H

View file

@ -17,6 +17,7 @@
#include "gc-inline.h"
#include "gc-platform.h"
#include "gc-stack.h"
#include "gc-trace.h"
#include "large-object-space.h"
#if GC_PARALLEL
#include "parallel-tracer.h"
@ -26,14 +27,6 @@
#include "spin.h"
#include "whippet-attrs.h"
#if GC_PRECISE_ROOTS
#include "precise-roots-embedder.h"
#endif
#if GC_CONSERVATIVE_ROOTS
#include "conservative-roots-embedder.h"
#endif
#define GRANULE_SIZE 16
#define GRANULE_SIZE_LOG_2 4
#define MEDIUM_OBJECT_THRESHOLD 256
@ -1455,11 +1448,6 @@ static double clamp_major_gc_yield_threshold(struct gc_heap *heap,
return threshold;
}
static inline int has_conservative_roots(void) {
return gc_has_mutator_conservative_roots() ||
gc_has_global_conservative_roots();
}
static enum gc_kind determine_collection_kind(struct gc_heap *heap) {
struct mark_space *mark_space = heap_mark_space(heap);
enum gc_kind previous_gc_kind = atomic_load(&heap->gc_kind);
@ -1489,7 +1477,7 @@ static enum gc_kind determine_collection_kind(struct gc_heap *heap) {
// blocks, try to avoid any pinning caused by the ragged-stop
// marking. Of course if the mutator has conservative roots we will
// have pinning anyway and might as well allow ragged stops.
mark_while_stopping = has_conservative_roots();
mark_while_stopping = gc_has_conservative_roots();
} else if (previous_gc_kind == GC_KIND_MAJOR_EVACUATING
&& fragmentation >= heap->fragmentation_low_threshold) {
DEBUG("continuing evacuation due to fragmentation %.2f%% > %.2f%%\n",