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 COLLECTORS=bdw semi whippet parallel-whippet generational-whippet parallel-generational-whippet
CC=gcc 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. INCLUDES=-I.
LDFLAGS=-lpthread LDFLAGS=-lpthread -flto
COMPILE=$(CC) $(CFLAGS) $(INCLUDES) $(LDFLAGS) COMPILE=$(CC) $(CFLAGS) $(INCLUDES)
ALL_TESTS=$(foreach COLLECTOR,$(COLLECTORS),$(addprefix $(COLLECTOR)-,$(TESTS))) ALL_TESTS=$(foreach COLLECTOR,$(COLLECTORS),$(addprefix $(COLLECTOR)-,$(TESTS)))
all: $(ALL_TESTS) all: $(ALL_TESTS)
bdw-%: bdw.h conservative-roots.h %-types.h %.c bdw-%-gc.o: semi.c %-embedder.h %.c
$(COMPILE) `pkg-config --libs --cflags bdw-gc` -DGC_BDW -o $@ $*.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 semi-%-gc.o: semi.c %-embedder.h large-object-space.h assert.h debug.h %.c
$(COMPILE) -DGC_SEMI -o $@ $*.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 whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c
$(COMPILE) -DGC_WHIPPET -o $@ $*.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 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_WHIPPET -o $@ $*.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 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_WHIPPET -o $@ $*.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 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_GENERATIONAL_WHIPPET -o $@ $*.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)) check: $(addprefix test-$(TARGET),$(TARGETS))

View file

@ -2,6 +2,7 @@
#define BDW_ATTRS_H #define BDW_ATTRS_H
#include "gc-attrs.h" #include "gc-attrs.h"
#include "gc-assert.h"
static inline enum gc_allocator_kind gc_allocator_kind(void) { static inline enum gc_allocator_kind gc_allocator_kind(void) {
return GC_ALLOCATOR_INLINE_FREELIST; 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) { static inline size_t gc_allocator_allocation_pointer_offset(void) {
abort(); GC_CRASH();
} }
static inline size_t gc_allocator_allocation_limit_offset(void) { static inline size_t gc_allocator_allocation_limit_offset(void) {
abort(); GC_CRASH();
} }
static inline size_t gc_allocator_freelist_offset(size_t size) { 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; return 0;
} }
static inline uint8_t gc_allocator_alloc_table_begin_pattern(void) { 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) { static inline uint8_t gc_allocator_alloc_table_end_pattern(void) {
abort(); GC_CRASH();
} }
static inline int gc_allocator_needs_clear(void) { 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; return GC_WRITE_BARRIER_NONE;
} }
static inline size_t gc_small_write_barrier_card_table_alignment(void) { 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) { static inline size_t gc_small_write_barrier_card_size(void) {
abort(); GC_CRASH();
} }
#endif // BDW_ATTRS_H #endif // BDW_ATTRS_H

View file

@ -1,8 +1,18 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#define GC_API_
#include "gc-api.h"
#include "bdw-attrs.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 // When pthreads are used, let `libgc' know about it and redirect
// allocation calls such as `GC_MALLOC ()' to (contention-free, faster) // 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); size_t bytes = gc_inline_freelist_object_size(idx);
GC_generic_malloc_many(bytes, kind, freelist); GC_generic_malloc_many(bytes, kind, freelist);
void *head = *freelist; void *head = *freelist;
if (UNLIKELY (!head)) { if (GC_UNLIKELY (!head)) {
fprintf(stderr, "ran out of space, heap size %zu\n", fprintf(stderr, "ran out of space, heap size %zu\n",
GC_get_heap_size()); GC_get_heap_size());
abort(); GC_CRASH();
} }
*freelist = *(void **)(head); *freelist = *(void **)(head);
return head; return head;
@ -74,25 +84,25 @@ static inline void *
allocate_small(void **freelist, size_t idx, enum gc_inline_kind kind) { allocate_small(void **freelist, size_t idx, enum gc_inline_kind kind) {
void *head = *freelist; void *head = *freelist;
if (UNLIKELY (!head)) if (GC_UNLIKELY (!head))
return allocate_small_slow(freelist, idx, kind); return allocate_small_slow(freelist, idx, kind);
*freelist = *(void **)(head); *freelist = *(void **)(head);
return 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); 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 != 0);
GC_ASSERT(size <= gc_allocator_large_threshold()); GC_ASSERT(size <= gc_allocator_large_threshold());
size_t idx = gc_inline_bytes_to_freelist_index(size); size_t idx = gc_inline_bytes_to_freelist_index(size);
return allocate_small(&mut->freelists[idx], idx, GC_INLINE_KIND_NORMAL); 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) { size_t size) {
// Because the BDW API requires us to implement a custom marker so // Because the BDW API requires us to implement a custom marker so
// that the pointerless freelist gets traced, even though it's in a // 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"); 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; #define PARSE_OPTION(option, name) if (strcmp(str, name) == 0) return option;
FOR_EACH_GC_OPTION(PARSE_OPTION) FOR_EACH_GC_OPTION(PARSE_OPTION)
#undef PARSE_OPTION #undef PARSE_OPTION
@ -145,8 +155,8 @@ struct options {
}; };
static size_t parse_size_t(double value) { static size_t parse_size_t(double value) {
ASSERT(value >= 0); GC_ASSERT(value >= 0);
ASSERT(value <= (size_t) -1); GC_ASSERT(value <= (size_t) -1);
return value; return value;
} }
@ -163,7 +173,7 @@ static int parse_options(int argc, struct gc_option argv[],
options->parallelism = parse_size_t(argv[i].value); options->parallelism = parse_size_t(argv[i].value);
break; break;
default: default:
abort(); GC_CRASH();
} }
} }
@ -177,8 +187,8 @@ static int parse_options(int argc, struct gc_option argv[],
return 1; 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) { struct heap **heap, struct mutator **mutator) {
GC_ASSERT_EQ(gc_allocator_small_granule_size(), GC_INLINE_GRANULE_BYTES); GC_ASSERT_EQ(gc_allocator_small_granule_size(), GC_INLINE_GRANULE_BYTES);
GC_ASSERT_EQ(gc_allocator_large_threshold(), GC_ASSERT_EQ(gc_allocator_large_threshold(),
GC_INLINE_FREELIST_COUNT * GC_INLINE_GRANULE_BYTES); GC_INLINE_FREELIST_COUNT * GC_INLINE_GRANULE_BYTES);
@ -208,8 +218,8 @@ static int gc_init(int argc, struct gc_option argv[],
return 1; 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 heap *heap) {
pthread_mutex_lock(&heap->lock); pthread_mutex_lock(&heap->lock);
if (!heap->multithreaded) { if (!heap->multithreaded) {
GC_allow_register_threads(); GC_allow_register_threads();
@ -221,23 +231,23 @@ static struct mutator* gc_init_for_thread(uintptr_t *stack_base,
GC_register_my_thread(&base); GC_register_my_thread(&base);
return add_mutator(heap); 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(); 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* (*f)(void*),
void *data) { void *data) {
return GC_do_blocking(f, 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) { 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("Completed %ld collections\n", (long)GC_get_gc_no());
printf("Heap size is %ld\n", (long)GC_get_heap_size()); 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? // FIXME: Conflict with bdw-gc GC_API. Switch prefix?
#ifndef GC_API_ #ifndef GC_API_
#define GC_API_ static #define GC_API_ __attribute__((visibility("hidden")))
#endif #endif
GC_API_ int gc_option_from_string(const char *str); 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: case GC_ALLOCATOR_INLINE_NONE:
return gc_allocate_small(mut, size); return gc_allocate_small(mut, size);
default: default:
abort(); GC_CRASH();
} }
} }
// FIXME: remove :P // 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, static inline void gc_small_write_barrier(struct gc_ref obj, struct gc_edge edge,
struct gc_ref new_val) GC_ALWAYS_INLINE; 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; return;
} }
default: default:
abort(); GC_CRASH();
} }
} }

View file

@ -6,10 +6,14 @@
#define GC_UNLIKELY(e) __builtin_expect(e, 0) #define GC_UNLIKELY(e) __builtin_expect(e, 0)
#define GC_LIKELY(e) __builtin_expect(e, 1) #define GC_LIKELY(e) __builtin_expect(e, 1)
#define GC_CRASH() __builtin_trap()
#if GC_DEBUG #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 #else
#define GC_ASSERT(x) do { } while (0) #define GC_ASSERT(x) do { } while (0)
#define GC_UNREACHABLE() __builtin_unreachable()
#endif #endif
#define GC_ASSERT_EQ(a, b) GC_ASSERT((a) == (b)) #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 #define GC_DEBUG 0
#endif #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 #endif // GC_CONFIG_H

View file

@ -8,6 +8,10 @@
#define GC_EMBEDDER_API static #define GC_EMBEDDER_API static
#endif #endif
struct gc_mutator_roots;
struct gc_heap_roots;
struct gc_atomic_forward;
GC_EMBEDDER_API inline void gc_trace_object(void *object, GC_EMBEDDER_API inline void gc_trace_object(void *object,
void (*trace_edge)(struct gc_edge edge, void (*trace_edge)(struct gc_edge edge,
void *trace_data), 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, visit_hole_fields(Hole *obj,
void (*visit)(struct gc_edge edge, void *visit_data), void (*visit)(struct gc_edge edge, void *visit_data),
void *visit_data) { void *visit_data) {
abort(); GC_CRASH();
} }
#include "simple-gc-embedder.h" #include "simple-gc-embedder.h"

View file

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

View file

@ -44,16 +44,16 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/time.h> #include <sys/time.h>
#include "mt-gcbench-types.h"
#include "assert.h" #include "assert.h"
#include "simple-allocator.h"
#include "gc-api.h" #include "gc-api.h"
#include "mt-gcbench-types.h"
#include "mt-gcbench-embedder.h" #if GC_PRECISE
#include "gc.h" #include "precise-roots-api.h"
#else
#include "gc-inline.h" #include "conservative-roots-api.h"
#endif
#include "mt-gcbench-types.h"
#include "simple-allocator.h"
#define MAX_THREAD_COUNT 256 #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) { 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)) { if (!trace_buf_grow(&q->bufs[cur], &q->bufs[cur + 1], b, t)) {
fprintf(stderr, "failed to grow deque!!\n"); fprintf(stderr, "failed to grow deque!!\n");
abort(); GC_CRASH();
} }
cur++; cur++;
@ -359,7 +359,7 @@ trace_worker_thread(void *data) {
pthread_mutex_unlock(&worker->lock); pthread_mutex_unlock(&worker->lock);
return NULL; return NULL;
default: default:
abort(); GC_CRASH();
} }
} }
} }

View file

@ -1,7 +1,7 @@
struct handle { #ifndef PRECISE_ROOTS_API_H
void *v; #define PRECISE_ROOTS_API_H
struct handle *next;
}; #include "precise-roots-types.h"
#define HANDLE_TO(T) union { T* v; struct handle handle; } #define HANDLE_TO(T) union { T* v; struct handle handle; }
#define HANDLE_REF(h) h.v #define HANDLE_REF(h) h.v
@ -18,10 +18,4 @@ static inline void pop_handle(struct handle **roots) {
*roots = (*roots)->next; *roots = (*roots)->next;
} }
static inline void visit_roots(struct handle *roots, #endif // PRECISE_ROOTS_API_H
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);
}

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 #ifndef QUADS_EMBEDDER_H
#define QUADS_EMBEDDER_H #define QUADS_EMBEDDER_H
#include <stddef.h>
#include "quads-types.h" #include "quads-types.h"
#define DEFINE_METHODS(name, Name, NAME) \ #define DEFINE_METHODS(name, Name, NAME) \

11
quads.c
View file

@ -1,14 +1,17 @@
#include <stdio.h> #include <stdio.h>
#include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/time.h> #include <sys/time.h>
#include "assert.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 "quads-types.h"
#include "simple-allocator.h" #include "simple-allocator.h"
#include "gc-api.h"
#include "quads-embedder.h"
#include "gc.h"
typedef HANDLE_TO(Quad) QuadHandle; typedef HANDLE_TO(Quad) QuadHandle;

View file

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

View file

@ -5,9 +5,17 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
#define GC_API_
#include "gc-api.h"
#include "semi-attrs.h" #include "semi-attrs.h"
#include "large-object-space.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 { struct semi_space {
uintptr_t hp; 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)) else if (large_object_space_contains(heap_large_object_space(heap), obj))
visit_large_object_space(heap, heap_large_object_space(heap), obj); visit_large_object_space(heap, heap_large_object_space(heap), obj);
else else
abort(); GC_CRASH();
} }
static void collect(struct mutator *mut) { 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); struct semi_space *space = mutator_semi_space(mut);
if (space->limit - space->hp < bytes) { if (space->limit - space->hp < bytes) {
fprintf(stderr, "ran out of space, heap size %zu\n", space->size); 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 heap *heap = mutator_heap(mut);
struct large_object_space *space = heap_large_object_space(heap); struct large_object_space *space = heap_large_object_space(heap);
struct semi_space *semi_space = heap_semi_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); collect(mut);
if (!semi_space_steal_pages(semi_space, npages)) { if (!semi_space_steal_pages(semi_space, npages)) {
fprintf(stderr, "ran out of space, heap size %zu\n", semi_space->size); 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) { if (!ret) {
perror("weird: we have the space but mmap didn't work"); perror("weird: we have the space but mmap didn't work");
abort(); GC_CRASH();
} }
return ret; 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); struct semi_space *space = mutator_semi_space(mut);
while (1) { while (1) {
uintptr_t addr = space->hp; uintptr_t addr = space->hp;
@ -212,7 +220,7 @@ static void* gc_allocate_small(struct mutator *mut, size_t size) {
return (void *)addr; 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); return gc_allocate(mut, size);
} }
@ -250,7 +258,7 @@ static void dump_available_gc_options(void) {
fprintf(stderr, "\n"); 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; #define PARSE_OPTION(option, name) if (strcmp(str, name) == 0) return option;
FOR_EACH_GC_OPTION(PARSE_OPTION) FOR_EACH_GC_OPTION(PARSE_OPTION)
#undef PARSE_OPTION #undef PARSE_OPTION
@ -269,8 +277,8 @@ struct options {
}; };
static size_t parse_size_t(double value) { static size_t parse_size_t(double value) {
ASSERT(value >= 0); GC_ASSERT(value >= 0);
ASSERT(value <= (size_t) -1); GC_ASSERT(value <= (size_t) -1);
return value; return value;
} }
@ -286,7 +294,7 @@ static int parse_options(int argc, struct gc_option argv[],
options->parallelism = parse_size_t(argv[i].value); options->parallelism = parse_size_t(argv[i].value);
break; break;
default: default:
abort(); GC_CRASH();
} }
} }
@ -302,8 +310,8 @@ static int parse_options(int argc, struct gc_option argv[],
return 1; 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) { struct heap **heap, struct mutator **mut) {
GC_ASSERT_EQ(gc_allocator_allocation_pointer_offset(), GC_ASSERT_EQ(gc_allocator_allocation_pointer_offset(),
offsetof(struct semi_space, hp)); offsetof(struct semi_space, hp));
GC_ASSERT_EQ(gc_allocator_allocation_limit_offset(), GC_ASSERT_EQ(gc_allocator_allocation_limit_offset(),
@ -314,7 +322,7 @@ static int gc_init(int argc, struct gc_option argv[],
return 0; return 0;
*mut = calloc(1, sizeof(struct mutator)); *mut = calloc(1, sizeof(struct mutator));
if (!*mut) abort(); if (!*mut) GC_CRASH();
*heap = mutator_heap(*mut); *heap = mutator_heap(*mut);
struct semi_space *space = mutator_semi_space(*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; return 1;
} }
static void gc_mutator_set_roots(struct mutator *mut, void gc_mutator_set_roots(struct mutator *mut,
struct gc_mutator_roots *roots) { struct gc_mutator_roots *roots) {
mut->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) {
abort(); 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) { struct heap *heap) {
fprintf(stderr, fprintf(stderr,
"Semispace copying collector not appropriate for multithreaded use.\n"); "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) { void *data) {
// Can't be threads, then there won't be collection. // Can't be threads, then there won't be collection.
return f(data); 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); struct semi_space *space = heap_semi_space(heap);
printf("Completed %ld collections\n", space->count); printf("Completed %ld collections\n", space->count);
printf("Heap size is %zd\n", space->size); 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) { trace_queue_push(struct trace_queue *q, struct gcobj *p) {
if (UNLIKELY(q->write - q->read == q->size)) { if (UNLIKELY(q->write - q->read == q->size)) {
if (!trace_queue_grow(q)) if (!trace_queue_grow(q))
abort(); GC_CRASH();
} }
trace_queue_put(q, q->write++, p); 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) { trace_queue_push_many(struct trace_queue *q, struct gcobj **pv, size_t count) {
while (q->size - (q->write - q->read) < count) { while (q->size - (q->write - q->read) < count) {
if (!trace_queue_grow(q)) if (!trace_queue_grow(q))
abort(); GC_CRASH();
} }
for (size_t i = 0; i < count; i++) for (size_t i = 0; i < count; i++)
trace_queue_put(q, q->write++, pv[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) FOR_EACH_HEAP_OBJECT_KIND(SCAN_OBJECT)
#undef SCAN_OBJECT #undef SCAN_OBJECT
default: default:
abort (); GC_CRASH();
} }
} }
struct handle; #if GC_PRECISE
struct gc_heap_roots { struct handle *roots; }; #include "precise-roots-embedder.h"
struct gc_mutator_roots { struct handle *roots; }; #else
#include "conservative-roots-embedder.h"
static inline void visit_roots(struct handle *roots, #endif
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);
}
static inline uintptr_t gc_object_forwarded_nonatomic(void *object) { static inline uintptr_t gc_object_forwarded_nonatomic(void *object) {
uintptr_t tag = *tag_word(object); uintptr_t tag = *tag_word(object);

View file

@ -2,6 +2,7 @@
#define WHIPPET_ATTRS_H #define WHIPPET_ATTRS_H
#include "gc-config.h" #include "gc-config.h"
#include "gc-assert.h"
#include "gc-attrs.h" #include "gc-attrs.h"
static inline enum gc_allocator_kind gc_allocator_kind(void) { 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) { static inline size_t gc_allocator_freelist_offset(size_t size) {
abort(); GC_CRASH();
} }
static inline size_t gc_allocator_alloc_table_alignment(void) { 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 <pthread.h>
#include <stdatomic.h> #include <stdatomic.h>
#include <stdint.h> #include <stdint.h>
@ -15,11 +7,13 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#define GC_API_
#include "gc-api.h"
#include "debug.h" #include "debug.h"
#include "gc-inline.h" #include "gc-inline.h"
#include "large-object-space.h" #include "large-object-space.h"
#include "precise-roots.h" #if GC_PARALLEL
#if GC_PARALLEL_TRACE
#include "parallel-tracer.h" #include "parallel-tracer.h"
#else #else
#include "serial-tracer.h" #include "serial-tracer.h"
@ -27,6 +21,12 @@
#include "spin.h" #include "spin.h"
#include "whippet-attrs.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 16
#define GRANULE_SIZE_LOG_2 4 #define GRANULE_SIZE_LOG_2 4
#define MEDIUM_OBJECT_THRESHOLD 256 #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_NOT_FORWARDED:
case GC_FORWARDING_STATE_ABORTED: case GC_FORWARDING_STATE_ABORTED:
// Impossible. // Impossible.
abort(); GC_CRASH();
case GC_FORWARDING_STATE_ACQUIRED: { case GC_FORWARDING_STATE_ACQUIRED: {
// We claimed the object successfully; evacuating is up to us. // We claimed the object successfully; evacuating is up to us.
size_t object_granules = mark_space_live_object_granules(metadata); 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), return large_object_space_mark_object(heap_large_object_space(heap),
obj); obj);
else else
abort(); GC_CRASH();
} }
static inline void trace_one(struct gcobj *obj, void *mark_data) { 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); MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (mem == MAP_FAILED) { if (mem == MAP_FAILED) {
perror("allocating mutator mark buffer failed"); perror("allocating mutator mark buffer failed");
abort(); GC_CRASH();
} }
if (old_bytes) { if (old_bytes) {
memcpy(mem, buf->objects, 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)); 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) { struct gc_mutator_roots *roots) {
mut->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; 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. // be able to yield more space: out of memory.
fprintf(stderr, "ran out of space, heap size %zu (%zu slabs)\n", fprintf(stderr, "ran out of space, heap size %zu (%zu slabs)\n",
heap->size, mark_space->nslabs); heap->size, mark_space->nslabs);
abort(); GC_CRASH();
} }
static double clamp_major_gc_yield_threshold(struct heap *heap, static double clamp_major_gc_yield_threshold(struct heap *heap,
@ -1762,7 +1762,7 @@ static void trigger_collection(struct mutator *mut) {
heap_unlock(heap); 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 heap *heap = mutator_heap(mut);
struct large_object_space *space = heap_large_object_space(heap); 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) { if (!ret) {
perror("weird: we have the space but mmap didn't work"); perror("weird: we have the space but mmap didn't work");
abort(); GC_CRASH();
} }
return ret; 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 > 0); // allocating 0 bytes would be silly
GC_ASSERT(size <= gc_allocator_large_threshold()); GC_ASSERT(size <= gc_allocator_large_threshold());
size = align_up(size, GRANULE_SIZE); size = align_up(size, GRANULE_SIZE);
@ -1816,7 +1816,7 @@ static void* gc_allocate_small(struct mutator *mut, size_t size) {
return obj; 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); return gc_allocate(mut, size);
} }
@ -1832,7 +1832,7 @@ static void dump_available_gc_options(void) {
fprintf(stderr, "\n"); 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; #define PARSE_OPTION(option, name) if (strcmp(str, name) == 0) return option;
FOR_EACH_GC_OPTION(PARSE_OPTION) FOR_EACH_GC_OPTION(PARSE_OPTION)
#undef 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); options->parallelism = parse_size_t(argv[i].value);
break; break;
default: default:
abort(); GC_CRASH();
} }
} }
@ -1916,7 +1916,7 @@ static int heap_init(struct heap *heap, struct options *options) {
heap->size = options->fixed_heap_size; heap->size = options->fixed_heap_size;
if (!tracer_init(heap, options->parallelism)) if (!tracer_init(heap, options->parallelism))
abort(); GC_CRASH();
heap->fragmentation_low_threshold = 0.05; heap->fragmentation_low_threshold = 0.05;
heap->fragmentation_high_threshold = 0.10; heap->fragmentation_high_threshold = 0.10;
@ -1960,7 +1960,7 @@ static int mark_space_init(struct mark_space *space, struct heap *heap) {
return 1; 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) { struct heap **heap, struct mutator **mut) {
GC_ASSERT_EQ(gc_allocator_small_granule_size(), GRANULE_SIZE); GC_ASSERT_EQ(gc_allocator_small_granule_size(), GRANULE_SIZE);
GC_ASSERT_EQ(gc_allocator_large_threshold(), LARGE_OBJECT_THRESHOLD); 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; return 0;
*heap = calloc(1, sizeof(struct heap)); *heap = calloc(1, sizeof(struct heap));
if (!*heap) abort(); if (!*heap) GC_CRASH();
if (!heap_init(*heap, &options)) if (!heap_init(*heap, &options))
abort(); GC_CRASH();
struct mark_space *space = heap_mark_space(*heap); struct mark_space *space = heap_mark_space(*heap);
if (!mark_space_init(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)) if (!large_object_space_init(heap_large_object_space(*heap), *heap))
abort(); GC_CRASH();
*mut = calloc(1, sizeof(struct mutator)); *mut = calloc(1, sizeof(struct mutator));
if (!*mut) abort(); if (!*mut) GC_CRASH();
add_mutator(*heap, *mut); add_mutator(*heap, *mut);
return 1; 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 heap *heap) {
struct mutator *ret = calloc(1, sizeof(struct mutator)); struct mutator *ret = calloc(1, sizeof(struct mutator));
if (!ret) if (!ret)
abort(); GC_CRASH();
add_mutator(heap, ret); add_mutator(heap, ret);
return 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); remove_mutator(mutator_heap(mut), mut);
mutator_mark_buf_destroy(&mut->mark_buf); mutator_mark_buf_destroy(&mut->mark_buf);
free(mut); free(mut);
@ -2042,7 +2042,7 @@ static void reactivate_mutator(struct heap *heap, struct mutator *mut) {
heap_unlock(heap); heap_unlock(heap);
} }
static void* gc_call_without_gc(struct mutator *mut, void* gc_call_without_gc(struct mutator *mut,
void* (*f)(void*), void* (*f)(void*),
void *data) { void *data) {
struct heap *heap = mutator_heap(mut); struct heap *heap = mutator_heap(mut);
@ -2052,7 +2052,7 @@ static void* gc_call_without_gc(struct mutator *mut,
return ret; return ret;
} }
static void gc_print_stats(struct heap *heap) { void gc_print_stats(struct heap *heap) {
printf("Completed %ld collections (%ld major)\n", printf("Completed %ld collections (%ld major)\n",
heap->count, heap->count - heap->minor_count); heap->count, heap->count - heap->minor_count);
printf("Heap size with overhead is %zd (%zu slabs)\n", printf("Heap size with overhead is %zd (%zu slabs)\n",