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

Separate compilation!!!!!

This commit is contained in:
Andy Wingo 2022-08-16 17:54:15 +02:00
parent fe9bdf6397
commit b082f5f50d
28 changed files with 344 additions and 189 deletions

View file

@ -2,32 +2,49 @@ TESTS=quads mt-gcbench # MT_GCBench MT_GCBench2
COLLECTORS=bdw semi whippet parallel-whippet generational-whippet parallel-generational-whippet
CC=gcc
CFLAGS=-Wall -O2 -g -fno-strict-aliasing -fvisibility=hidden -Wno-unused -DNDEBUG
CFLAGS=-Wall -O2 -g -flto -fno-strict-aliasing -fvisibility=hidden -Wno-unused -DNDEBUG
INCLUDES=-I.
LDFLAGS=-lpthread
COMPILE=$(CC) $(CFLAGS) $(INCLUDES) $(LDFLAGS)
LDFLAGS=-lpthread -flto
COMPILE=$(CC) $(CFLAGS) $(INCLUDES)
ALL_TESTS=$(foreach COLLECTOR,$(COLLECTORS),$(addprefix $(COLLECTOR)-,$(TESTS)))
all: $(ALL_TESTS)
bdw-%: bdw.h conservative-roots.h %-types.h %.c
$(COMPILE) `pkg-config --libs --cflags bdw-gc` -DGC_BDW -o $@ $*.c
bdw-%-gc.o: semi.c %-embedder.h %.c
$(COMPILE) `pkg-config --cflags bdw-gc` -include $*-embedder.h -o $@ -c bdw.c
bdw-%.o: semi.c %.c
$(COMPILE) -include bdw-attrs.h -o $@ -c $*.c
bdw-%: bdw-%.o bdw-%-gc.o
$(CC) $(LDFLAGS) `pkg-config --libs bdw-gc` -o $@ $^
semi-%: semi.h precise-roots.h large-object-space.h %-types.h heap-objects.h %.c
$(COMPILE) -DGC_SEMI -o $@ $*.c
semi-%-gc.o: semi.c %-embedder.h large-object-space.h assert.h debug.h %.c
$(COMPILE) -DGC_PRECISE=1 -include $*-embedder.h -o $@ -c semi.c
semi-%.o: semi.c %.c
$(COMPILE) -DGC_PRECISE=1 -include semi-attrs.h -o $@ -c $*.c
whippet-%: whippet.h precise-roots.h large-object-space.h serial-tracer.h assert.h debug.h %-types.h heap-objects.h %.c
$(COMPILE) -DGC_WHIPPET -o $@ $*.c
whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c
$(COMPILE) -DGC_PRECISE=1 -include $*-embedder.h -o $@ -c whippet.c
whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_PRECISE=1 -include whippet-attrs.h -o $@ -c $*.c
parallel-whippet-%: whippet.h precise-roots.h large-object-space.h parallel-tracer.h assert.h debug.h %-types.h heap-objects.h %.c
$(COMPILE) -DGC_PARALLEL_WHIPPET -o $@ $*.c
parallel-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h parallel-tracer.h assert.h debug.h heap-objects.h %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_PRECISE=1 -include $*-embedder.h -o $@ -c whippet.c
parallel-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_PRECISE=1 -include whippet-attrs.h -o $@ -c $*.c
generational-whippet-%: whippet.h precise-roots.h large-object-space.h serial-tracer.h assert.h debug.h %-types.h heap-objects.h %.c
$(COMPILE) -DGC_GENERATIONAL_WHIPPET -o $@ $*.c
generational-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c
$(COMPILE) -DGC_GENERATIONAL=1 -DGC_PRECISE=1 -include $*-embedder.h -o $@ -c whippet.c
generational-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_GENERATIONAL=1 -DGC_PRECISE=1 -include whippet-attrs.h -o $@ -c $*.c
parallel-generational-whippet-%: whippet.h precise-roots.h large-object-space.h parallel-tracer.h assert.h debug.h %-types.h heap-objects.h %.c
$(COMPILE) -DGC_PARALLEL_GENERATIONAL_WHIPPET -o $@ $*.c
parallel-generational-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h parallel-tracer.h assert.h debug.h heap-objects.h %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_PRECISE=1 -include $*-embedder.h -o $@ -c whippet.c
parallel-generational-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_PRECISE=1 -include whippet-attrs.h -o $@ -c $*.c
%: %.o %-gc.o
$(CC) $(LDFLAGS) $($*_LDFLAGS) -o $@ $^
check: $(addprefix test-$(TARGET),$(TARGETS))

View file

@ -2,6 +2,7 @@
#define BDW_ATTRS_H
#include "gc-attrs.h"
#include "gc-assert.h"
static inline enum gc_allocator_kind gc_allocator_kind(void) {
return GC_ALLOCATOR_INLINE_FREELIST;
@ -14,10 +15,10 @@ static inline size_t gc_allocator_large_threshold(void) {
}
static inline size_t gc_allocator_allocation_pointer_offset(void) {
abort();
GC_CRASH();
}
static inline size_t gc_allocator_allocation_limit_offset(void) {
abort();
GC_CRASH();
}
static inline size_t gc_allocator_freelist_offset(size_t size) {
@ -29,10 +30,10 @@ static inline size_t gc_allocator_alloc_table_alignment(void) {
return 0;
}
static inline uint8_t gc_allocator_alloc_table_begin_pattern(void) {
abort();
GC_CRASH();
}
static inline uint8_t gc_allocator_alloc_table_end_pattern(void) {
abort();
GC_CRASH();
}
static inline int gc_allocator_needs_clear(void) {
@ -43,10 +44,10 @@ static inline enum gc_write_barrier_kind gc_small_write_barrier_kind(void) {
return GC_WRITE_BARRIER_NONE;
}
static inline size_t gc_small_write_barrier_card_table_alignment(void) {
abort();
GC_CRASH();
}
static inline size_t gc_small_write_barrier_card_size(void) {
abort();
GC_CRASH();
}
#endif // BDW_ATTRS_H

View file

@ -1,8 +1,18 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GC_API_
#include "gc-api.h"
#include "bdw-attrs.h"
#include "conservative-roots.h"
#if GC_PRECISE
#error bdw-gc is a conservative collector
#else
#include "conservative-roots-embedder.h"
#endif
// When pthreads are used, let `libgc' know about it and redirect
// allocation calls such as `GC_MALLOC ()' to (contention-free, faster)
@ -61,10 +71,10 @@ static void* allocate_small_slow(void **freelist, size_t idx,
size_t bytes = gc_inline_freelist_object_size(idx);
GC_generic_malloc_many(bytes, kind, freelist);
void *head = *freelist;
if (UNLIKELY (!head)) {
if (GC_UNLIKELY (!head)) {
fprintf(stderr, "ran out of space, heap size %zu\n",
GC_get_heap_size());
abort();
GC_CRASH();
}
*freelist = *(void **)(head);
return head;
@ -74,25 +84,25 @@ static inline void *
allocate_small(void **freelist, size_t idx, enum gc_inline_kind kind) {
void *head = *freelist;
if (UNLIKELY (!head))
if (GC_UNLIKELY (!head))
return allocate_small_slow(freelist, idx, kind);
*freelist = *(void **)(head);
return head;
}
static void* gc_allocate_large(struct mutator *mut, size_t size) {
void* gc_allocate_large(struct mutator *mut, size_t size) {
return GC_malloc(size);
}
static void* gc_allocate_small(struct mutator *mut, size_t size) {
void* gc_allocate_small(struct mutator *mut, size_t size) {
GC_ASSERT(size != 0);
GC_ASSERT(size <= gc_allocator_large_threshold());
size_t idx = gc_inline_bytes_to_freelist_index(size);
return allocate_small(&mut->freelists[idx], idx, GC_INLINE_KIND_NORMAL);
}
static inline void* gc_allocate_pointerless(struct mutator *mut,
void* gc_allocate_pointerless(struct mutator *mut,
size_t size) {
// Because the BDW API requires us to implement a custom marker so
// that the pointerless freelist gets traced, even though it's in a
@ -126,7 +136,7 @@ static void dump_available_gc_options(void) {
fprintf(stderr, "\n");
}
static int gc_option_from_string(const char *str) {
int gc_option_from_string(const char *str) {
#define PARSE_OPTION(option, name) if (strcmp(str, name) == 0) return option;
FOR_EACH_GC_OPTION(PARSE_OPTION)
#undef PARSE_OPTION
@ -145,8 +155,8 @@ struct options {
};
static size_t parse_size_t(double value) {
ASSERT(value >= 0);
ASSERT(value <= (size_t) -1);
GC_ASSERT(value >= 0);
GC_ASSERT(value <= (size_t) -1);
return value;
}
@ -163,7 +173,7 @@ static int parse_options(int argc, struct gc_option argv[],
options->parallelism = parse_size_t(argv[i].value);
break;
default:
abort();
GC_CRASH();
}
}
@ -177,7 +187,7 @@ static int parse_options(int argc, struct gc_option argv[],
return 1;
}
static int gc_init(int argc, struct gc_option argv[],
int gc_init(int argc, struct gc_option argv[],
struct heap **heap, struct mutator **mutator) {
GC_ASSERT_EQ(gc_allocator_small_granule_size(), GC_INLINE_GRANULE_BYTES);
GC_ASSERT_EQ(gc_allocator_large_threshold(),
@ -208,7 +218,7 @@ static int gc_init(int argc, struct gc_option argv[],
return 1;
}
static struct mutator* gc_init_for_thread(uintptr_t *stack_base,
struct mutator* gc_init_for_thread(uintptr_t *stack_base,
struct heap *heap) {
pthread_mutex_lock(&heap->lock);
if (!heap->multithreaded) {
@ -221,23 +231,23 @@ static struct mutator* gc_init_for_thread(uintptr_t *stack_base,
GC_register_my_thread(&base);
return add_mutator(heap);
}
static void gc_finish_for_thread(struct mutator *mut) {
void gc_finish_for_thread(struct mutator *mut) {
GC_unregister_my_thread();
}
static void* gc_call_without_gc(struct mutator *mut,
void* gc_call_without_gc(struct mutator *mut,
void* (*f)(void*),
void *data) {
return GC_do_blocking(f, data);
}
static void gc_mutator_set_roots(struct mutator *mut,
void gc_mutator_set_roots(struct mutator *mut,
struct gc_mutator_roots *roots) {
}
static void gc_heap_set_roots(struct heap *heap, struct gc_heap_roots *roots) {
void gc_heap_set_roots(struct heap *heap, struct gc_heap_roots *roots) {
}
static void gc_print_stats(struct heap *heap) {
void gc_print_stats(struct heap *heap) {
printf("Completed %ld collections\n", (long)GC_get_gc_no());
printf("Heap size is %ld\n", (long)GC_get_heap_size());
}

12
conservative-roots-api.h Normal file
View file

@ -0,0 +1,12 @@
#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

@ -0,0 +1,21 @@
#ifndef CONSERVATIVE_ROOTS_EMBEDDER_H
#define CONSERVATIVE_ROOTS_EMBEDDER_H
#include "gc-assert.h"
#include "conservative-roots-types.h"
static inline void gc_trace_mutator_roots(struct gc_mutator_roots *roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data) {
GC_CRASH();
}
static inline void gc_trace_heap_roots(struct gc_heap_roots *roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data) {
GC_CRASH();
}
#endif // CONSERVATIVE_ROOTS_EMBEDDER_H

View file

@ -0,0 +1,8 @@
#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,21 +0,0 @@
struct handle { void *unused; };
#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)
static inline void visit_thread_roots(void *thread_roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data) {
abort();
}
static inline void visit_roots(struct handle *roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data) {
GC_ASSERT(!roots);
}

View file

@ -32,7 +32,7 @@ struct gc_mutator {
// FIXME: Conflict with bdw-gc GC_API. Switch prefix?
#ifndef GC_API_
#define GC_API_ static
#define GC_API_ __attribute__((visibility("hidden")))
#endif
GC_API_ int gc_option_from_string(const char *str);
@ -159,12 +159,12 @@ static inline void* gc_allocate(struct mutator *mut, size_t size) {
case GC_ALLOCATOR_INLINE_NONE:
return gc_allocate_small(mut, size);
default:
abort();
GC_CRASH();
}
}
// FIXME: remove :P
static inline void* gc_allocate_pointerless(struct mutator *mut, size_t bytes);
GC_API_ void* gc_allocate_pointerless(struct mutator *mut, size_t bytes);
static inline void gc_small_write_barrier(struct gc_ref obj, struct gc_edge edge,
struct gc_ref new_val) GC_ALWAYS_INLINE;
@ -183,7 +183,7 @@ static inline void gc_small_write_barrier(struct gc_ref obj, struct gc_edge edge
return;
}
default:
abort();
GC_CRASH();
}
}

View file

@ -6,10 +6,14 @@
#define GC_UNLIKELY(e) __builtin_expect(e, 0)
#define GC_LIKELY(e) __builtin_expect(e, 1)
#define GC_CRASH() __builtin_trap()
#if GC_DEBUG
#define GC_ASSERT(x) do { if (GC_UNLIKELY(!(x))) __builtin_trap(); } while (0)
#define GC_ASSERT(x) do { if (GC_UNLIKELY(!(x))) GC_CRASH(); } while (0)
#define GC_UNREACHABLE() GC_CRASH()
#else
#define GC_ASSERT(x) do { } while (0)
#define GC_UNREACHABLE() __builtin_unreachable()
#endif
#define GC_ASSERT_EQ(a, b) GC_ASSERT((a) == (b))

39
gc-attrs.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef GC_ATTRS_H
#define GC_ATTRS_H
#include "gc-inline.h"
#include <stddef.h>
#include <stdint.h>
enum gc_allocator_kind {
GC_ALLOCATOR_INLINE_BUMP_POINTER,
GC_ALLOCATOR_INLINE_FREELIST,
GC_ALLOCATOR_INLINE_NONE
};
static inline enum gc_allocator_kind gc_allocator_kind(void) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_large_threshold(void) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_small_granule_size(void) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_allocation_pointer_offset(void) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_allocation_limit_offset(void) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_freelist_offset(size_t size) GC_ALWAYS_INLINE;
static inline size_t gc_allocator_alloc_table_alignment(void) GC_ALWAYS_INLINE;
static inline uint8_t gc_allocator_alloc_table_begin_pattern(void) GC_ALWAYS_INLINE;
static inline uint8_t gc_allocator_alloc_table_end_pattern(void) GC_ALWAYS_INLINE;
static inline int gc_allocator_needs_clear(void) GC_ALWAYS_INLINE;
enum gc_write_barrier_kind {
GC_WRITE_BARRIER_NONE,
GC_WRITE_BARRIER_CARD
};
static inline enum gc_write_barrier_kind gc_small_write_barrier_kind(void) GC_ALWAYS_INLINE;
static inline size_t gc_small_write_barrier_card_table_alignment(void) GC_ALWAYS_INLINE;
static inline size_t gc_small_write_barrier_card_size(void) GC_ALWAYS_INLINE;
#endif // GC_ATTRS_H

View file

@ -5,4 +5,16 @@
#define GC_DEBUG 0
#endif
#ifndef GC_PARALLEL
#define GC_PARALLEL 0
#endif
#ifndef GC_GENERATIONAL
#define GC_GENERATIONAL 0
#endif
#ifndef GC_PRECISE
#define GC_PRECISE 0
#endif
#endif // GC_CONFIG_H

View file

@ -8,6 +8,10 @@
#define GC_EMBEDDER_API static
#endif
struct gc_mutator_roots;
struct gc_heap_roots;
struct gc_atomic_forward;
GC_EMBEDDER_API inline void gc_trace_object(void *object,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),

7
gc-visibility.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef GC_VISIBILITY_H_
#define GC_VISIBILITY_H_
#define GC_INTERNAL __attribute__((visibility("hidden")))
#define GC_PUBLIC __attribute__((visibility("default")))
#endif // GC_VISIBILITY_H

View file

@ -36,7 +36,7 @@ static inline void
visit_hole_fields(Hole *obj,
void (*visit)(struct gc_edge edge, void *visit_data),
void *visit_data) {
abort();
GC_CRASH();
}
#include "simple-gc-embedder.h"

View file

@ -1,6 +1,9 @@
#ifndef GCBENCH_TYPES_H
#define GCBENCH_TYPES_H
#include <stddef.h>
#include <stdint.h>
#define FOR_EACH_HEAP_OBJECT_KIND(M) \
M(node, Node, NODE) \
M(double_array, DoubleArray, DOUBLE_ARRAY) \

View file

@ -44,16 +44,16 @@
#include <stdlib.h>
#include <sys/time.h>
#include "mt-gcbench-types.h"
#include "assert.h"
#include "simple-allocator.h"
#include "gc-api.h"
#include "mt-gcbench-embedder.h"
#include "gc.h"
#include "gc-inline.h"
#include "mt-gcbench-types.h"
#if GC_PRECISE
#include "precise-roots-api.h"
#else
#include "conservative-roots-api.h"
#endif
#include "mt-gcbench-types.h"
#include "simple-allocator.h"
#define MAX_THREAD_COUNT 256

View file

@ -149,7 +149,7 @@ static int
trace_deque_grow(struct trace_deque *q, int cur, size_t b, size_t t) {
if (!trace_buf_grow(&q->bufs[cur], &q->bufs[cur + 1], b, t)) {
fprintf(stderr, "failed to grow deque!!\n");
abort();
GC_CRASH();
}
cur++;
@ -359,7 +359,7 @@ trace_worker_thread(void *data) {
pthread_mutex_unlock(&worker->lock);
return NULL;
default:
abort();
GC_CRASH();
}
}
}

View file

@ -1,7 +1,7 @@
struct handle {
void *v;
struct handle *next;
};
#ifndef PRECISE_ROOTS_API_H
#define PRECISE_ROOTS_API_H
#include "precise-roots-types.h"
#define HANDLE_TO(T) union { T* v; struct handle handle; }
#define HANDLE_REF(h) h.v
@ -18,10 +18,4 @@ static inline void pop_handle(struct handle **roots) {
*roots = (*roots)->next;
}
static inline void visit_roots(struct handle *roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data) {
for (struct handle *h = roots; h; h = h->next)
trace_edge(gc_edge(&h->v), trace_data);
}
#endif // PRECISE_ROOTS_API_H

31
precise-roots-embedder.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef PRECISE_ROOTS_EMBEDDER_H
#define PRECISE_ROOTS_EMBEDDER_H
#include "gc-edge.h"
#include "precise-roots-types.h"
static inline void visit_roots(struct handle *roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data) {
for (struct handle *h = roots; h; h = h->next)
trace_edge(gc_edge(&h->v), trace_data);
}
static inline void gc_trace_mutator_roots(struct gc_mutator_roots *roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data) {
if (roots)
visit_roots(roots->roots, trace_edge, trace_data);
}
static inline void gc_trace_heap_roots(struct gc_heap_roots *roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data) {
if (roots)
visit_roots(roots->roots, trace_edge, trace_data);
}
#endif // PRECISE_ROOTS_EMBEDDER_H

17
precise-roots-types.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef PRECISE_ROOTS_TYPES_H
#define PRECISE_ROOTS_TYPES_H
struct handle {
void *v;
struct handle *next;
};
struct gc_heap_roots {
struct handle *roots;
};
struct gc_mutator_roots {
struct handle *roots;
};
#endif // PRECISE_ROOTS_TYPES_H

View file

@ -1,6 +1,8 @@
#ifndef QUADS_EMBEDDER_H
#define QUADS_EMBEDDER_H
#include <stddef.h>
#include "quads-types.h"
#define DEFINE_METHODS(name, Name, NAME) \

11
quads.c
View file

@ -1,14 +1,17 @@
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <sys/time.h>
#include "assert.h"
#include "gc-api.h"
#if GC_PRECISE
#include "precise-roots-api.h"
#else
#include "conservative-roots-api.h"
#endif
#include "quads-types.h"
#include "simple-allocator.h"
#include "gc-api.h"
#include "quads-embedder.h"
#include "gc.h"
typedef HANDLE_TO(Quad) QuadHandle;

View file

@ -2,6 +2,7 @@
#define SEMI_ATTRS_H
#include "gc-attrs.h"
#include "gc-assert.h"
static const uintptr_t GC_ALIGNMENT = 8;
static const size_t GC_LARGE_OBJECT_THRESHOLD = 8192;
@ -24,7 +25,7 @@ static inline size_t gc_allocator_allocation_limit_offset(void) {
}
static inline size_t gc_allocator_freelist_offset(size_t size) {
abort();
GC_CRASH();
}
static inline int gc_allocator_needs_clear(void) {
@ -35,20 +36,20 @@ static inline size_t gc_allocator_alloc_table_alignment(void) {
return 0;
}
static inline uint8_t gc_allocator_alloc_table_begin_pattern(void) {
abort();
GC_CRASH();
}
static inline uint8_t gc_allocator_alloc_table_end_pattern(void) {
abort();
GC_CRASH();
}
static inline enum gc_write_barrier_kind gc_small_write_barrier_kind(void) {
return GC_WRITE_BARRIER_NONE;
}
static inline size_t gc_small_write_barrier_card_table_alignment(void) {
abort();
GC_CRASH();
}
static inline size_t gc_small_write_barrier_card_size(void) {
abort();
GC_CRASH();
}
#endif // SEMI_ATTRS_H

View file

@ -5,9 +5,17 @@
#include <sys/mman.h>
#include <unistd.h>
#define GC_API_
#include "gc-api.h"
#include "semi-attrs.h"
#include "large-object-space.h"
#include "precise-roots.h"
#if GC_PRECISE
#include "precise-roots-embedder.h"
#else
#error semi is a precise collector
#endif
struct semi_space {
uintptr_t hp;
@ -141,7 +149,7 @@ static void visit(struct gc_edge edge, void *visit_data) {
else if (large_object_space_contains(heap_large_object_space(heap), obj))
visit_large_object_space(heap, heap_large_object_space(heap), obj);
else
abort();
GC_CRASH();
}
static void collect(struct mutator *mut) {
@ -167,11 +175,11 @@ static void collect_for_alloc(struct mutator *mut, size_t bytes) {
struct semi_space *space = mutator_semi_space(mut);
if (space->limit - space->hp < bytes) {
fprintf(stderr, "ran out of space, heap size %zu\n", space->size);
abort();
GC_CRASH();
}
}
static void* gc_allocate_large(struct mutator *mut, size_t size) {
void* gc_allocate_large(struct mutator *mut, size_t size) {
struct heap *heap = mutator_heap(mut);
struct large_object_space *space = heap_large_object_space(heap);
struct semi_space *semi_space = heap_semi_space(heap);
@ -181,7 +189,7 @@ static void* gc_allocate_large(struct mutator *mut, size_t size) {
collect(mut);
if (!semi_space_steal_pages(semi_space, npages)) {
fprintf(stderr, "ran out of space, heap size %zu\n", semi_space->size);
abort();
GC_CRASH();
}
}
@ -191,13 +199,13 @@ static void* gc_allocate_large(struct mutator *mut, size_t size) {
if (!ret) {
perror("weird: we have the space but mmap didn't work");
abort();
GC_CRASH();
}
return ret;
}
static void* gc_allocate_small(struct mutator *mut, size_t size) {
void* gc_allocate_small(struct mutator *mut, size_t size) {
struct semi_space *space = mutator_semi_space(mut);
while (1) {
uintptr_t addr = space->hp;
@ -212,7 +220,7 @@ static void* gc_allocate_small(struct mutator *mut, size_t size) {
return (void *)addr;
}
}
static inline void* gc_allocate_pointerless(struct mutator *mut, size_t size) {
void* gc_allocate_pointerless(struct mutator *mut, size_t size) {
return gc_allocate(mut, size);
}
@ -250,7 +258,7 @@ static void dump_available_gc_options(void) {
fprintf(stderr, "\n");
}
static int gc_option_from_string(const char *str) {
int gc_option_from_string(const char *str) {
#define PARSE_OPTION(option, name) if (strcmp(str, name) == 0) return option;
FOR_EACH_GC_OPTION(PARSE_OPTION)
#undef PARSE_OPTION
@ -269,8 +277,8 @@ struct options {
};
static size_t parse_size_t(double value) {
ASSERT(value >= 0);
ASSERT(value <= (size_t) -1);
GC_ASSERT(value >= 0);
GC_ASSERT(value <= (size_t) -1);
return value;
}
@ -286,7 +294,7 @@ static int parse_options(int argc, struct gc_option argv[],
options->parallelism = parse_size_t(argv[i].value);
break;
default:
abort();
GC_CRASH();
}
}
@ -302,7 +310,7 @@ static int parse_options(int argc, struct gc_option argv[],
return 1;
}
static int gc_init(int argc, struct gc_option argv[],
int gc_init(int argc, struct gc_option argv[],
struct heap **heap, struct mutator **mut) {
GC_ASSERT_EQ(gc_allocator_allocation_pointer_offset(),
offsetof(struct semi_space, hp));
@ -314,7 +322,7 @@ static int gc_init(int argc, struct gc_option argv[],
return 0;
*mut = calloc(1, sizeof(struct mutator));
if (!*mut) abort();
if (!*mut) GC_CRASH();
*heap = mutator_heap(*mut);
struct semi_space *space = mutator_semi_space(*mut);
@ -328,30 +336,30 @@ static int gc_init(int argc, struct gc_option argv[],
return 1;
}
static void gc_mutator_set_roots(struct mutator *mut,
void gc_mutator_set_roots(struct mutator *mut,
struct gc_mutator_roots *roots) {
mut->roots = roots;
}
static void gc_heap_set_roots(struct heap *heap, struct gc_heap_roots *roots) {
abort();
void gc_heap_set_roots(struct heap *heap, struct gc_heap_roots *roots) {
GC_CRASH();
}
static struct mutator* gc_init_for_thread(uintptr_t *stack_base,
struct mutator* gc_init_for_thread(uintptr_t *stack_base,
struct heap *heap) {
fprintf(stderr,
"Semispace copying collector not appropriate for multithreaded use.\n");
exit(1);
GC_CRASH();
}
static void gc_finish_for_thread(struct mutator *space) {
void gc_finish_for_thread(struct mutator *space) {
}
static void* gc_call_without_gc(struct mutator *mut, void* (*f)(void*),
void* gc_call_without_gc(struct mutator *mut, void* (*f)(void*),
void *data) {
// Can't be threads, then there won't be collection.
return f(data);
}
static void gc_print_stats(struct heap *heap) {
void gc_print_stats(struct heap *heap) {
struct semi_space *space = heap_semi_space(heap);
printf("Completed %ld collections\n", space->count);
printf("Heap size is %zd\n", space->size);

View file

@ -85,7 +85,7 @@ static inline void
trace_queue_push(struct trace_queue *q, struct gcobj *p) {
if (UNLIKELY(q->write - q->read == q->size)) {
if (!trace_queue_grow(q))
abort();
GC_CRASH();
}
trace_queue_put(q, q->write++, p);
}
@ -94,7 +94,7 @@ static inline void
trace_queue_push_many(struct trace_queue *q, struct gcobj **pv, size_t count) {
while (q->size - (q->write - q->read) < count) {
if (!trace_queue_grow(q))
abort();
GC_CRASH();
}
for (size_t i = 0; i < count; i++)
trace_queue_put(q, q->write++, pv[i]);

View file

@ -19,34 +19,15 @@ static inline void gc_trace_object(void *object,
FOR_EACH_HEAP_OBJECT_KIND(SCAN_OBJECT)
#undef SCAN_OBJECT
default:
abort ();
GC_CRASH();
}
}
struct handle;
struct gc_heap_roots { struct handle *roots; };
struct gc_mutator_roots { struct handle *roots; };
static inline void visit_roots(struct handle *roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data);
static inline void gc_trace_mutator_roots(struct gc_mutator_roots *roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data) {
if (roots)
visit_roots(roots->roots, trace_edge, trace_data);
}
static inline void gc_trace_heap_roots(struct gc_heap_roots *roots,
void (*trace_edge)(struct gc_edge edge,
void *trace_data),
void *trace_data) {
if (roots)
visit_roots(roots->roots, trace_edge, trace_data);
}
#if GC_PRECISE
#include "precise-roots-embedder.h"
#else
#include "conservative-roots-embedder.h"
#endif
static inline uintptr_t gc_object_forwarded_nonatomic(void *object) {
uintptr_t tag = *tag_word(object);

View file

@ -2,6 +2,7 @@
#define WHIPPET_ATTRS_H
#include "gc-config.h"
#include "gc-assert.h"
#include "gc-attrs.h"
static inline enum gc_allocator_kind gc_allocator_kind(void) {
@ -22,7 +23,7 @@ static inline size_t gc_allocator_allocation_limit_offset(void) {
}
static inline size_t gc_allocator_freelist_offset(size_t size) {
abort();
GC_CRASH();
}
static inline size_t gc_allocator_alloc_table_alignment(void) {

View file

@ -1,11 +1,3 @@
#ifndef GC_PARALLEL_TRACE
#error define GC_PARALLEL_TRACE to 1 or 0
#endif
#ifndef GC_GENERATIONAL
#error define GC_GENERATIONAL to 1 or 0
#endif
#include <pthread.h>
#include <stdatomic.h>
#include <stdint.h>
@ -15,11 +7,13 @@
#include <string.h>
#include <unistd.h>
#define GC_API_
#include "gc-api.h"
#include "debug.h"
#include "gc-inline.h"
#include "large-object-space.h"
#include "precise-roots.h"
#if GC_PARALLEL_TRACE
#if GC_PARALLEL
#include "parallel-tracer.h"
#else
#include "serial-tracer.h"
@ -27,6 +21,12 @@
#include "spin.h"
#include "whippet-attrs.h"
#if GC_PRECISE
#include "precise-roots-embedder.h"
#else
#error whippet only currently implements precise collection
#endif
#define GRANULE_SIZE 16
#define GRANULE_SIZE_LOG_2 4
#define MEDIUM_OBJECT_THRESHOLD 256
@ -560,7 +560,7 @@ static inline int mark_space_evacuate_or_mark_object(struct mark_space *space,
case GC_FORWARDING_STATE_NOT_FORWARDED:
case GC_FORWARDING_STATE_ABORTED:
// Impossible.
abort();
GC_CRASH();
case GC_FORWARDING_STATE_ACQUIRED: {
// We claimed the object successfully; evacuating is up to us.
size_t object_granules = mark_space_live_object_granules(metadata);
@ -641,7 +641,7 @@ static inline int trace_edge(struct heap *heap, struct gc_edge edge) {
return large_object_space_mark_object(heap_large_object_space(heap),
obj);
else
abort();
GC_CRASH();
}
static inline void trace_one(struct gcobj *obj, void *mark_data) {
@ -836,7 +836,7 @@ static void mutator_mark_buf_grow(struct mutator_mark_buf *buf) {
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (mem == MAP_FAILED) {
perror("allocating mutator mark buffer failed");
abort();
GC_CRASH();
}
if (old_bytes) {
memcpy(mem, buf->objects, old_bytes);
@ -905,11 +905,11 @@ static int mutator_should_mark_while_stopping(struct mutator *mut) {
return heap_should_mark_while_stopping(mutator_heap(mut));
}
static void gc_mutator_set_roots(struct mutator *mut,
void gc_mutator_set_roots(struct mutator *mut,
struct gc_mutator_roots *roots) {
mut->roots = roots;
}
static void gc_heap_set_roots(struct heap *heap, struct gc_heap_roots *roots) {
void gc_heap_set_roots(struct heap *heap, struct gc_heap_roots *roots) {
heap->roots = roots;
}
@ -1213,7 +1213,7 @@ static void detect_out_of_memory(struct heap *heap) {
// be able to yield more space: out of memory.
fprintf(stderr, "ran out of space, heap size %zu (%zu slabs)\n",
heap->size, mark_space->nslabs);
abort();
GC_CRASH();
}
static double clamp_major_gc_yield_threshold(struct heap *heap,
@ -1762,7 +1762,7 @@ static void trigger_collection(struct mutator *mut) {
heap_unlock(heap);
}
static void* gc_allocate_large(struct mutator *mut, size_t size) {
void* gc_allocate_large(struct mutator *mut, size_t size) {
struct heap *heap = mutator_heap(mut);
struct large_object_space *space = heap_large_object_space(heap);
@ -1781,13 +1781,13 @@ static void* gc_allocate_large(struct mutator *mut, size_t size) {
if (!ret) {
perror("weird: we have the space but mmap didn't work");
abort();
GC_CRASH();
}
return ret;
}
static void* gc_allocate_small(struct mutator *mut, size_t size) {
void* gc_allocate_small(struct mutator *mut, size_t size) {
GC_ASSERT(size > 0); // allocating 0 bytes would be silly
GC_ASSERT(size <= gc_allocator_large_threshold());
size = align_up(size, GRANULE_SIZE);
@ -1816,7 +1816,7 @@ static void* gc_allocate_small(struct mutator *mut, size_t size) {
return obj;
}
static inline void* gc_allocate_pointerless(struct mutator *mut, size_t size) {
void* gc_allocate_pointerless(struct mutator *mut, size_t size) {
return gc_allocate(mut, size);
}
@ -1832,7 +1832,7 @@ static void dump_available_gc_options(void) {
fprintf(stderr, "\n");
}
static int gc_option_from_string(const char *str) {
int gc_option_from_string(const char *str) {
#define PARSE_OPTION(option, name) if (strcmp(str, name) == 0) return option;
FOR_EACH_GC_OPTION(PARSE_OPTION)
#undef PARSE_OPTION
@ -1869,7 +1869,7 @@ static int parse_options(int argc, struct gc_option argv[],
options->parallelism = parse_size_t(argv[i].value);
break;
default:
abort();
GC_CRASH();
}
}
@ -1916,7 +1916,7 @@ static int heap_init(struct heap *heap, struct options *options) {
heap->size = options->fixed_heap_size;
if (!tracer_init(heap, options->parallelism))
abort();
GC_CRASH();
heap->fragmentation_low_threshold = 0.05;
heap->fragmentation_high_threshold = 0.10;
@ -1960,7 +1960,7 @@ static int mark_space_init(struct mark_space *space, struct heap *heap) {
return 1;
}
static int gc_init(int argc, struct gc_option argv[],
int gc_init(int argc, struct gc_option argv[],
struct heap **heap, struct mutator **mut) {
GC_ASSERT_EQ(gc_allocator_small_granule_size(), GRANULE_SIZE);
GC_ASSERT_EQ(gc_allocator_large_threshold(), LARGE_OBJECT_THRESHOLD);
@ -1982,10 +1982,10 @@ static int gc_init(int argc, struct gc_option argv[],
return 0;
*heap = calloc(1, sizeof(struct heap));
if (!*heap) abort();
if (!*heap) GC_CRASH();
if (!heap_init(*heap, &options))
abort();
GC_CRASH();
struct mark_space *space = heap_mark_space(*heap);
if (!mark_space_init(space, *heap)) {
@ -1995,24 +1995,24 @@ static int gc_init(int argc, struct gc_option argv[],
}
if (!large_object_space_init(heap_large_object_space(*heap), *heap))
abort();
GC_CRASH();
*mut = calloc(1, sizeof(struct mutator));
if (!*mut) abort();
if (!*mut) GC_CRASH();
add_mutator(*heap, *mut);
return 1;
}
static struct mutator* gc_init_for_thread(uintptr_t *stack_base,
struct mutator* gc_init_for_thread(uintptr_t *stack_base,
struct heap *heap) {
struct mutator *ret = calloc(1, sizeof(struct mutator));
if (!ret)
abort();
GC_CRASH();
add_mutator(heap, ret);
return ret;
}
static void gc_finish_for_thread(struct mutator *mut) {
void gc_finish_for_thread(struct mutator *mut) {
remove_mutator(mutator_heap(mut), mut);
mutator_mark_buf_destroy(&mut->mark_buf);
free(mut);
@ -2042,7 +2042,7 @@ static void reactivate_mutator(struct heap *heap, struct mutator *mut) {
heap_unlock(heap);
}
static void* gc_call_without_gc(struct mutator *mut,
void* gc_call_without_gc(struct mutator *mut,
void* (*f)(void*),
void *data) {
struct heap *heap = mutator_heap(mut);
@ -2052,7 +2052,7 @@ static void* gc_call_without_gc(struct mutator *mut,
return ret;
}
static void gc_print_stats(struct heap *heap) {
void gc_print_stats(struct heap *heap) {
printf("Completed %ld collections (%ld major)\n",
heap->count, heap->count - heap->minor_count);
printf("Heap size with overhead is %zd (%zu slabs)\n",