1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-12 16:50:22 +02:00

Rework options interface

Users will want to set options from an environment variable or something
like that.  Particular GC implementations will want to expose an
expanded set of options.  For these reasons we make the options
interface a bit more generalized and include parsing.
This commit is contained in:
Andy Wingo 2023-02-15 10:50:17 +01:00
parent 499ff1fe76
commit 4cb26e0144
14 changed files with 411 additions and 257 deletions

View file

@ -44,6 +44,9 @@ gc-platform.o: gc-platform.h gc-platform-$(PLATFORM).c gc-visibility.h
gc-stack.o: gc-stack.c gc-stack.o: gc-stack.c
$(COMPILE) -o $@ -c $< $(COMPILE) -o $@ -c $<
gc-options.o: gc-options.c gc-options.h gc-options-internal.h
$(COMPILE) -o $@ -c $<
gc-ephemeron-%.o: gc-ephemeron.c gc-ephemeron.h gc-ephemeron-internal.h %-embedder.h gc-ephemeron-%.o: gc-ephemeron.c gc-ephemeron.h gc-ephemeron-internal.h %-embedder.h
$(COMPILE) -include $*-embedder.h -o $@ -c $< $(COMPILE) -include $*-embedder.h -o $@ -c $<
@ -51,98 +54,98 @@ bdw-%-gc.o: bdw.c %-embedder.h %.c
$(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 `pkg-config --cflags bdw-gc` -include $*-embedder.h -o $@ -c bdw.c $(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 `pkg-config --cflags bdw-gc` -include $*-embedder.h -o $@ -c bdw.c
bdw-%.o: bdw.c %.c bdw-%.o: bdw.c %.c
$(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include bdw-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include bdw-attrs.h -o $@ -c $*.c
bdw-%: bdw-%.o bdw-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o bdw-%: bdw-%.o bdw-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) `pkg-config --libs bdw-gc` -o $@ $^ $(CC) $(LDFLAGS) `pkg-config --libs bdw-gc` -o $@ $^
semi-%-gc.o: semi.c %-embedder.h large-object-space.h assert.h debug.h %.c semi-%-gc.o: semi.c %-embedder.h large-object-space.h assert.h debug.h %.c
$(COMPILE) -DGC_PRECISE_ROOTS=1 -include $*-embedder.h -o $@ -c semi.c $(COMPILE) -DGC_PRECISE_ROOTS=1 -include $*-embedder.h -o $@ -c semi.c
semi-%.o: semi.c %.c semi-%.o: semi.c %.c
$(COMPILE) -DGC_PRECISE_ROOTS=1 -include semi-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_PRECISE_ROOTS=1 -include semi-attrs.h -o $@ -c $*.c
semi-%: semi-%.o semi-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o semi-%: semi-%.o semi-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.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_PRECISE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_PRECISE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c
whippet-%.o: whippet.c %.c whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_PRECISE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_PRECISE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c
whippet-%: whippet-%.o whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o whippet-%: whippet-%.o whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
stack-conservative-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c stack-conservative-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c
$(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c
stack-conservative-whippet-%.o: whippet.c %.c stack-conservative-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c
stack-conservative-whippet-%: stack-conservative-whippet-%.o stack-conservative-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o stack-conservative-whippet-%: stack-conservative-whippet-%.o stack-conservative-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
heap-conservative-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c heap-conservative-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c
$(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include $*-embedder.h -o $@ -c whippet.c
heap-conservative-whippet-%.o: whippet.c %.c heap-conservative-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include whippet-attrs.h -o $@ -c $*.c
heap-conservative-whippet-%: heap-conservative-whippet-%.o heap-conservative-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o heap-conservative-whippet-%: heap-conservative-whippet-%.o heap-conservative-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
parallel-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h parallel-tracer.h assert.h debug.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=1 -DGC_PRECISE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_PARALLEL=1 -DGC_PRECISE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c
parallel-whippet-%.o: whippet.c %.c parallel-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_PRECISE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_PARALLEL=1 -DGC_PRECISE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c
parallel-whippet-%: parallel-whippet-%.o parallel-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o parallel-whippet-%: parallel-whippet-%.o parallel-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
stack-conservative-parallel-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c stack-conservative-parallel-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_CONSERVATIVE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_PARALLEL=1 -DGC_CONSERVATIVE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c
stack-conservative-parallel-whippet-%.o: whippet.c %.c stack-conservative-parallel-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_CONSERVATIVE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_PARALLEL=1 -DGC_CONSERVATIVE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c
stack-conservative-parallel-whippet-%: stack-conservative-parallel-whippet-%.o stack-conservative-parallel-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o stack-conservative-parallel-whippet-%: stack-conservative-parallel-whippet-%.o stack-conservative-parallel-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
heap-conservative-parallel-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c heap-conservative-parallel-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_PARALLEL=1 -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include $*-embedder.h -o $@ -c whippet.c
heap-conservative-parallel-whippet-%.o: whippet.c %.c heap-conservative-parallel-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -DGC_FULLY_CONSERVATIVE=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_PARALLEL=1 -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -DGC_FULLY_CONSERVATIVE=1 -include whippet-attrs.h -o $@ -c $*.c
heap-conservative-parallel-whippet-%: heap-conservative-parallel-whippet-%.o heap-conservative-parallel-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o heap-conservative-parallel-whippet-%: heap-conservative-parallel-whippet-%.o heap-conservative-parallel-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
generational-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.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=1 -DGC_PRECISE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_GENERATIONAL=1 -DGC_PRECISE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c
generational-whippet-%.o: whippet.c %.c generational-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_GENERATIONAL=1 -DGC_PRECISE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_GENERATIONAL=1 -DGC_PRECISE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c
generational-whippet-%: generational-whippet-%.o generational-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o generational-whippet-%: generational-whippet-%.o generational-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
stack-conservative-generational-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c stack-conservative-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_CONSERVATIVE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c
stack-conservative-generational-whippet-%.o: whippet.c %.c stack-conservative-generational-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c
stack-conservative-generational-whippet-%: stack-conservative-generational-whippet-%.o stack-conservative-generational-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o stack-conservative-generational-whippet-%: stack-conservative-generational-whippet-%.o stack-conservative-generational-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
heap-conservative-generational-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h serial-tracer.h assert.h debug.h heap-objects.h %.c heap-conservative-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_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include $*-embedder.h -o $@ -c whippet.c
heap-conservative-generational-whippet-%.o: whippet.c %.c heap-conservative-generational-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include whippet-attrs.h -o $@ -c $*.c
heap-conservative-generational-whippet-%: heap-conservative-generational-whippet-%.o heap-conservative-generational-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o heap-conservative-generational-whippet-%: heap-conservative-generational-whippet-%.o heap-conservative-generational-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
parallel-generational-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h parallel-tracer.h assert.h debug.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=1 -DGC_GENERATIONAL=1 -DGC_PRECISE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_PRECISE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c
parallel-generational-whippet-%.o: whippet.c %.c parallel-generational-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_PRECISE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_PRECISE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c
parallel-generational-whippet-%: parallel-generational-whippet-%.o parallel-generational-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o parallel-generational-whippet-%: parallel-generational-whippet-%.o parallel-generational-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
stack-conservative-parallel-generational-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h parallel-tracer.h assert.h debug.h heap-objects.h %.c stack-conservative-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_CONSERVATIVE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -include $*-embedder.h -o $@ -c whippet.c
stack-conservative-parallel-generational-whippet-%.o: whippet.c %.c stack-conservative-parallel-generational-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -include whippet-attrs.h -o $@ -c $*.c
stack-conservative-parallel-generational-whippet-%: stack-conservative-parallel-generational-whippet-%.o stack-conservative-parallel-generational-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o stack-conservative-parallel-generational-whippet-%: stack-conservative-parallel-generational-whippet-%.o stack-conservative-parallel-generational-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
heap-conservative-parallel-generational-whippet-%-gc.o: whippet.c %-embedder.h large-object-space.h parallel-tracer.h assert.h debug.h heap-objects.h %.c heap-conservative-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_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include $*-embedder.h -o $@ -c whippet.c $(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include $*-embedder.h -o $@ -c whippet.c
heap-conservative-parallel-generational-whippet-%.o: whippet.c %.c heap-conservative-parallel-generational-whippet-%.o: whippet.c %.c
$(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include whippet-attrs.h -o $@ -c $*.c $(COMPILE) -DGC_PARALLEL=1 -DGC_GENERATIONAL=1 -DGC_CONSERVATIVE_ROOTS=1 -DGC_CONSERVATIVE_TRACE=1 -include whippet-attrs.h -o $@ -c $*.c
heap-conservative-parallel-generational-whippet-%: heap-conservative-parallel-generational-whippet-%.o heap-conservative-parallel-generational-whippet-%-gc.o gc-stack.o gc-platform.o gc-ephemeron-%.o heap-conservative-parallel-generational-whippet-%: heap-conservative-parallel-generational-whippet-%.o heap-conservative-parallel-generational-whippet-%-gc.o gc-stack.o gc-options.o gc-platform.o gc-ephemeron-%.o
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $^
.PRECIOUS: $(ALL_TESTS) .PRECIOUS: $(ALL_TESTS)

103
bdw.c
View file

@ -213,79 +213,40 @@ static inline struct gc_heap *mutator_heap(struct gc_mutator *mutator) {
return mutator->heap; return mutator->heap;
} }
#define FOR_EACH_GC_OPTION(M) \ struct gc_options {
M(GC_OPTION_FIXED_HEAP_SIZE, "fixed-heap-size") \ struct gc_common_options common;
M(GC_OPTION_PARALLELISM, "parallelism")
static void dump_available_gc_options(void) {
fprintf(stderr, "available gc options:");
#define PRINT_OPTION(option, name) fprintf(stderr, " %s", name);
FOR_EACH_GC_OPTION(PRINT_OPTION)
#undef PRINT_OPTION
fprintf(stderr, "\n");
}
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
if (strcmp(str, "fixed-heap-size") == 0)
return GC_OPTION_FIXED_HEAP_SIZE;
if (strcmp(str, "parallelism") == 0)
return GC_OPTION_PARALLELISM;
fprintf(stderr, "bad gc option: '%s'\n", str);
dump_available_gc_options();
return -1;
}
struct options {
size_t fixed_heap_size;
size_t parallelism;
}; };
int gc_option_from_string(const char *str) {
static size_t parse_size_t(double value) { return gc_common_option_from_string(str);
GC_ASSERT(value >= 0); }
GC_ASSERT(value <= (size_t) -1); struct gc_options* gc_allocate_options(void) {
return value; struct gc_options *ret = malloc(sizeof(struct gc_options));
gc_init_common_options(&ret->common);
return ret;
}
int gc_options_set_int(struct gc_options *options, int option, int value) {
return gc_common_options_set_int(&options->common, option, value);
}
int gc_options_set_size(struct gc_options *options, int option,
size_t value) {
return gc_common_options_set_size(&options->common, option, value);
}
int gc_options_set_double(struct gc_options *options, int option,
double value) {
return gc_common_options_set_double(&options->common, option, value);
}
int gc_options_parse_and_set(struct gc_options *options, int option,
const char *value) {
return gc_common_options_parse_and_set(&options->common, option, value);
} }
static size_t number_of_current_processors(void) { return 1; } int gc_init(struct gc_options *options, struct gc_stack_addr *stack_base,
struct gc_heap **heap, struct gc_mutator **mutator) {
static int parse_options(int argc, struct gc_option argv[],
struct options *options) {
for (int i = 0; i < argc; i++) {
switch (argv[i].option) {
case GC_OPTION_FIXED_HEAP_SIZE:
options->fixed_heap_size = parse_size_t(argv[i].value);
break;
case GC_OPTION_PARALLELISM:
options->parallelism = parse_size_t(argv[i].value);
break;
default:
GC_CRASH();
}
}
if (!options->fixed_heap_size) {
fprintf(stderr, "fixed heap size is currently required\n");
return 0;
}
if (!options->parallelism)
options->parallelism = number_of_current_processors();
return 1;
}
int gc_init(int argc, struct gc_option argv[],
struct gc_stack_addr *stack_base, struct gc_heap **heap,
struct gc_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);
struct options options = { 0, }; if (!options) options = gc_allocate_options();
if (!parse_options(argc, argv, &options))
return 0;
// GC_full_freq = 30; // GC_full_freq = 30;
// GC_free_space_divisor = 16; // GC_free_space_divisor = 16;
@ -293,16 +254,16 @@ int gc_init(int argc, struct gc_option argv[],
// Ignore stack base for main thread. // Ignore stack base for main thread.
GC_set_max_heap_size(options.fixed_heap_size); GC_set_max_heap_size(options->common.heap_size);
// Not part of 7.3, sigh. Have to set an env var. // Not part of 7.3, sigh. Have to set an env var.
// GC_set_markers_count(options.parallelism); // GC_set_markers_count(options->common.parallelism);
char markers[21] = {0,}; // 21 bytes enough for 2**64 in decimal + NUL. char markers[21] = {0,}; // 21 bytes enough for 2**64 in decimal + NUL.
snprintf(markers, sizeof(markers), "%zu", options.parallelism); snprintf(markers, sizeof(markers), "%d", options->common.parallelism);
setenv("GC_MARKERS", markers, 1); setenv("GC_MARKERS", markers, 1);
GC_init(); GC_init();
size_t current_heap_size = GC_get_heap_size(); size_t current_heap_size = GC_get_heap_size();
if (options.fixed_heap_size > current_heap_size) if (options->common.heap_size > current_heap_size)
GC_expand_hp(options.fixed_heap_size - current_heap_size); GC_expand_hp(options->common.heap_size - current_heap_size);
GC_allow_register_threads(); GC_allow_register_threads();
*heap = GC_malloc(sizeof(struct gc_heap)); *heap = GC_malloc(sizeof(struct gc_heap));
pthread_mutex_init(&(*heap)->lock, NULL); pthread_mutex_init(&(*heap)->lock, NULL);

View file

@ -225,12 +225,14 @@ int main(int argc, char *argv[]) {
printf("Allocating heap of %.3fGB (%.2f multiplier of live data).\n", printf("Allocating heap of %.3fGB (%.2f multiplier of live data).\n",
heap_size / 1e9, heap_multiplier); heap_size / 1e9, heap_multiplier);
struct gc_option options[] = { { GC_OPTION_FIXED_HEAP_SIZE, (size_t) heap_size }, struct gc_options *options = gc_allocate_options();
{ GC_OPTION_PARALLELISM, parallelism } }; gc_options_set_int(options, GC_OPTION_HEAP_SIZE_POLICY, GC_HEAP_SIZE_FIXED);
gc_options_set_size(options, GC_OPTION_HEAP_SIZE, heap_size);
gc_options_set_int(options, GC_OPTION_PARALLELISM, parallelism);
struct gc_heap *heap; struct gc_heap *heap;
struct gc_mutator *mut; struct gc_mutator *mut;
if (!gc_init(sizeof options / sizeof options[0], options, NULL, &heap, if (!gc_init(options, NULL, &heap, &mut)) {
&mut)) {
fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n", fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
(size_t)heap_size); (size_t)heap_size);
return 1; return 1;

View file

@ -4,9 +4,10 @@
#include "gc-config.h" #include "gc-config.h"
#include "gc-assert.h" #include "gc-assert.h"
#include "gc-attrs.h" #include "gc-attrs.h"
#include "gc-inline.h"
#include "gc-ref.h"
#include "gc-edge.h" #include "gc-edge.h"
#include "gc-inline.h"
#include "gc-options.h"
#include "gc-ref.h"
#include "gc-visibility.h" #include "gc-visibility.h"
#include <stdatomic.h> #include <stdatomic.h>
@ -16,26 +17,13 @@
struct gc_heap; struct gc_heap;
struct gc_mutator; struct gc_mutator;
enum {
GC_OPTION_FIXED_HEAP_SIZE,
GC_OPTION_PARALLELISM
};
struct gc_option {
int option;
double value;
};
GC_API_ int gc_option_from_string(const char *str);
struct gc_stack_addr; struct gc_stack_addr;
GC_API_ void* gc_call_with_stack_addr(void* (*f)(struct gc_stack_addr *, GC_API_ void* gc_call_with_stack_addr(void* (*f)(struct gc_stack_addr *,
void *), void *),
void *data) GC_NEVER_INLINE; void *data) GC_NEVER_INLINE;
GC_API_ int gc_init(int argc, struct gc_option argv[], GC_API_ int gc_init(struct gc_options *options, struct gc_stack_addr *base,
struct gc_stack_addr *base, struct gc_heap **heap, struct gc_heap **heap, struct gc_mutator **mutator);
struct gc_mutator **mutator);
struct gc_mutator_roots; struct gc_mutator_roots;
GC_API_ void gc_mutator_set_roots(struct gc_mutator *mut, GC_API_ void gc_mutator_set_roots(struct gc_mutator *mut,

View file

@ -6,5 +6,6 @@
#endif #endif
#include "gc-ephemeron-internal.h" #include "gc-ephemeron-internal.h"
#include "gc-options-internal.h"
#endif // GC_INTERNAL_H #endif // GC_INTERNAL_H

32
gc-options-internal.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef GC_OPTIONS_INTERNAL_H
#define GC_OPTIONS_INTERNAL_H
#ifndef GC_IMPL
#error internal header file, not part of API
#endif
#include "gc-options.h"
struct gc_common_options {
enum gc_heap_size_policy heap_size_policy;
size_t heap_size;
size_t maximum_heap_size;
double heap_size_multiplier;
double heap_frugality;
int parallelism;
};
GC_INTERNAL void gc_init_common_options(struct gc_common_options *options);
GC_INTERNAL int gc_common_option_from_string(const char *str);
GC_INTERNAL int gc_common_options_set_int(struct gc_common_options *options,
int option, int value);
GC_INTERNAL int gc_common_options_set_size(struct gc_common_options *options,
int option, size_t value);
GC_INTERNAL int gc_common_options_set_double(struct gc_common_options *options,
int option, double value);
GC_INTERNAL int gc_common_options_parse_and_set(struct gc_common_options *options,
int option, const char *value);
#endif // GC_OPTIONS_INTERNAL_H

181
gc-options.c Normal file
View file

@ -0,0 +1,181 @@
#include <limits.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#define GC_IMPL 1
#include "gc-options-internal.h"
#include "gc-platform.h"
// M(UPPER, lower, repr, parser, default, min, max)
#define FOR_EACH_INT_GC_OPTION(M) \
M(HEAP_SIZE_POLICY, heap_size_policy, "heap-size-policy", \
int, GC_HEAP_SIZE_FIXED, GC_HEAP_SIZE_FIXED, GC_HEAP_SIZE_ADAPTIVE) \
M(PARALLELISM, parallelism, "parallelism", \
int, default_parallelism(), 1, 64)
#define FOR_EACH_SIZE_GC_OPTION(M) \
M(HEAP_SIZE, heap_size, "heap-size", \
size, 6 * 1024 * 1024, 0, -1) \
M(MAXIMUM_HEAP_SIZE, maximum_heap_size, "maximum-heap-size", \
size, 0, 0, -1)
#define FOR_EACH_DOUBLE_GC_OPTION(M) \
M(HEAP_SIZE_MULTIPLIER, heap_size_multiplier, "heap-size-multiplier", \
double, 1.75, 1.0, 1e6) \
M(HEAP_FRUGALITY, heap_frugality, "heap-frugality", \
double, 1e-1, 1e-6, 1e6)
typedef int gc_option_int;
typedef size_t gc_option_size;
typedef double gc_option_double;
#define FOR_EACH_COMMON_GC_OPTION(M) \
FOR_EACH_INT_GC_OPTION(M) \
FOR_EACH_SIZE_GC_OPTION(M) \
FOR_EACH_DOUBLE_GC_OPTION(M)
static int clamp_int(int n, int lo, int hi) {
return n < lo ? lo : n > hi ? hi : n;
}
static size_t clamp_size(size_t n, size_t lo, size_t hi) {
return n < lo ? lo : n > hi ? hi : n;
}
static double clamp_double(double n, double lo, double hi) {
return n < lo ? lo : n > hi ? hi : n;
}
static int default_parallelism(void) {
return clamp_int(gc_platform_processor_count(), 1, 8);
}
void gc_init_common_options(struct gc_common_options *options) {
#define INIT(UPPER, lower, repr, parser, default, min, max) \
options->lower = default;
FOR_EACH_COMMON_GC_OPTION(INIT)
#undef INIT
}
int gc_common_option_from_string(const char *str) {
#define GET_OPTION(UPPER, lower, repr, parser, default, min, max) \
if (strcmp(str, repr) == 0) return GC_OPTION_##UPPER;
FOR_EACH_COMMON_GC_OPTION(GET_OPTION)
#undef GET_OPTION
return -1;
}
#define SET_OPTION(UPPER, lower, repr, parser, default, min, max) \
case GC_OPTION_##UPPER: \
if (value != clamp_##parser(value, min, max)) return 0; \
options->lower = value; \
return 1;
#define DEFINE_SETTER(STEM, stem, type) \
int gc_common_options_set_##stem(struct gc_common_options *options, \
int option, type value) { \
switch (option) { \
FOR_EACH_##STEM##_GC_OPTION(SET_OPTION) \
default: return 0; \
} \
}
DEFINE_SETTER(INT, int, int)
DEFINE_SETTER(SIZE, size, size_t)
DEFINE_SETTER(DOUBLE, double, double)
#undef SET_OPTION
#undef DEFINE_SETTER
static int parse_size(const char *arg, size_t *val) {
char *end;
long i = strtol(arg, &end, 0);
if (i < 0 || i == LONG_MAX) return 0;
if (end == arg) return 0;
char delim = *end;
if (delim == 'k' || delim == 'K')
++end, i *= 1024L;
else if (delim == 'm' || delim == 'M')
++end, i *= 1024L * 1024L;
else if (delim == 'g' || delim == 'G')
++end, i *= 1024L * 1024L * 1024L;
else if (delim == 't' || delim == 'T')
++end, i *= 1024L * 1024L * 1024L * 1024L;
if (*end != '\0') return 0;
*val = i;
return 1;
}
static int parse_int(const char *arg, int *val) {
char *end;
long i = strtol(arg, &end, 0);
if (i == LONG_MIN || i == LONG_MAX || end == arg || *end)
return 0;
*val = i;
return 1;
}
static int parse_double(const char *arg, double *val) {
char *end;
double d = strtod(arg, &end);
if (end == arg || *end)
return 0;
*val = d;
return 1;
}
int gc_common_options_parse_and_set(struct gc_common_options *options,
int option, const char *value) {
switch (option) {
#define SET_OPTION(UPPER, lower, repr, parser, default, min, max) \
case GC_OPTION_##UPPER: { \
gc_option_##parser v; \
if (!parse_##parser(value, &v)) return 0; \
return gc_common_options_set_##parser(options, option, v); \
}
FOR_EACH_COMMON_GC_OPTION(SET_OPTION)
default: return 0;
}
}
static int is_lower(char c) { return 'a' <= c && c <= 'z'; }
static int is_digit(char c) { return '0' <= c && c <= '9'; }
static int is_option(char c) { return is_lower(c) || c == '-'; }
static int is_option_end(char c) { return c == '='; }
static int is_value(char c) {
return is_lower(c) || is_digit(c) || c == '-' || c == '+' || c == '.';
}
static int is_value_end(char c) { return c == '\0' || c == ','; }
static char* read_token(char *p, int (*is_tok)(char c), int (*is_end)(char c),
char *delim) {
char c;
for (c = *p; is_tok(c); p++);
if (!is_end(c)) return NULL;
*delim = c;
*p = '\0';
return p + 1;
}
int gc_options_parse_and_set_many(struct gc_options *options,
const char *str) {
if (!*str) return 1;
char *copy = strdup(str);
char *cur = copy;
int ret = 0;
while (1) {
char delim;
char *next = read_token(cur, is_option, is_option_end, &delim);
if (!next) break;
int option = gc_option_from_string(cur);
if (option < 0) break;
cur = next;
next = read_token(cur, is_value, is_value_end, &delim);
if (!next) break;
if (!gc_options_parse_and_set(options, option, cur)) break;
cur = next;
if (delim == '\0') {
ret = 1;
break;
}
}
free(copy);
return ret;
}

39
gc-options.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef GC_OPTIONS_H
#define GC_OPTIONS_H
#include "gc-visibility.h"
enum gc_heap_size_policy {
GC_HEAP_SIZE_FIXED,
GC_HEAP_SIZE_GROWABLE,
GC_HEAP_SIZE_ADAPTIVE,
};
enum {
GC_OPTION_HEAP_SIZE_POLICY,
GC_OPTION_HEAP_SIZE,
GC_OPTION_MAXIMUM_HEAP_SIZE,
GC_OPTION_HEAP_SIZE_MULTIPLIER,
GC_OPTION_HEAP_FRUGALITY,
GC_OPTION_PARALLELISM
};
struct gc_options;
GC_API_ int gc_option_from_string(const char *str);
GC_API_ struct gc_options* gc_allocate_options(void);
GC_API_ int gc_options_set_int(struct gc_options *options, int option,
int value);
GC_API_ int gc_options_set_size(struct gc_options *options, int option,
size_t value);
GC_API_ int gc_options_set_double(struct gc_options *options, int option,
double value);
GC_API_ int gc_options_parse_and_set(struct gc_options *options,
int option, const char *value);
GC_API_ int gc_options_parse_and_set_many(struct gc_options *options,
const char *str);
#endif // GC_OPTIONS_H

View file

@ -3,6 +3,7 @@
#include <errno.h> #include <errno.h>
#include <link.h> #include <link.h>
#include <pthread.h> #include <pthread.h>
#include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
@ -102,3 +103,10 @@ void gc_platform_visit_global_conservative_roots(void (*f)(uintptr_t start,
struct visit_data visit_data = { f, heap, data }; struct visit_data visit_data = { f, heap, data };
dl_iterate_phdr(visit_roots, &visit_data); dl_iterate_phdr(visit_roots, &visit_data);
} }
int gc_platform_processor_count(void) {
cpu_set_t set;
if (sched_getaffinity(0, sizeof (set), &set) != 0)
return 1;
return CPU_COUNT(&set);
}

View file

@ -20,5 +20,6 @@ void gc_platform_visit_global_conservative_roots(void (*f)(uintptr_t start,
void *data), void *data),
struct gc_heap *heap, struct gc_heap *heap,
void *data); void *data);
GC_INTERNAL int gc_platform_processor_count(void);
#endif // GC_PLATFORM_H #endif // GC_PLATFORM_H

View file

@ -355,12 +355,15 @@ int main(int argc, char *argv[]) {
} }
size_t heap_size = heap_max_live * multiplier * nthreads; size_t heap_size = heap_max_live * multiplier * nthreads;
struct gc_option options[] = { { GC_OPTION_FIXED_HEAP_SIZE, heap_size },
{ GC_OPTION_PARALLELISM, parallelism } }; struct gc_options *options = gc_allocate_options();
gc_options_set_int(options, GC_OPTION_HEAP_SIZE_POLICY, GC_HEAP_SIZE_FIXED);
gc_options_set_size(options, GC_OPTION_HEAP_SIZE, heap_size);
gc_options_set_int(options, GC_OPTION_PARALLELISM, parallelism);
struct gc_heap *heap; struct gc_heap *heap;
struct gc_mutator *mut; struct gc_mutator *mut;
if (!gc_init(sizeof options / sizeof options[0], options, NULL, &heap, if (!gc_init(options, NULL, &heap, &mut)) {
&mut)) {
fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n", fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
heap_size); heap_size);
return 1; return 1;

10
quads.c
View file

@ -128,12 +128,14 @@ int main(int argc, char *argv[]) {
printf("Allocating heap of %.3fGB (%.2f multiplier of live data).\n", printf("Allocating heap of %.3fGB (%.2f multiplier of live data).\n",
heap_size / 1e9, multiplier); heap_size / 1e9, multiplier);
struct gc_option options[] = { { GC_OPTION_FIXED_HEAP_SIZE, heap_size }, struct gc_options *options = gc_allocate_options();
{ GC_OPTION_PARALLELISM, parallelism } }; gc_options_set_int(options, GC_OPTION_HEAP_SIZE_POLICY, GC_HEAP_SIZE_FIXED);
gc_options_set_size(options, GC_OPTION_HEAP_SIZE, heap_size);
gc_options_set_int(options, GC_OPTION_PARALLELISM, 1);
struct gc_heap *heap; struct gc_heap *heap;
struct gc_mutator *mut; struct gc_mutator *mut;
if (!gc_init(sizeof options / sizeof options[0], options, NULL, &heap, if (!gc_init(options, NULL, &heap, &mut)) {
&mut)) {
fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n", fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
heap_size); heap_size);
return 1; return 1;

111
semi.c
View file

@ -303,70 +303,6 @@ static int initialize_semi_space(struct semi_space *space, size_t size) {
return 1; return 1;
} }
#define FOR_EACH_GC_OPTION(M) \
M(GC_OPTION_FIXED_HEAP_SIZE, "fixed-heap-size") \
M(GC_OPTION_PARALLELISM, "parallelism")
static void dump_available_gc_options(void) {
fprintf(stderr, "available gc options:");
#define PRINT_OPTION(option, name) fprintf(stderr, " %s", name);
FOR_EACH_GC_OPTION(PRINT_OPTION)
#undef PRINT_OPTION
fprintf(stderr, "\n");
}
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
if (strcmp(str, "fixed-heap-size") == 0)
return GC_OPTION_FIXED_HEAP_SIZE;
if (strcmp(str, "parallelism") == 0)
return GC_OPTION_PARALLELISM;
fprintf(stderr, "bad gc option: '%s'\n", str);
dump_available_gc_options();
return -1;
}
struct options {
size_t fixed_heap_size;
size_t parallelism;
};
static size_t parse_size_t(double value) {
GC_ASSERT(value >= 0);
GC_ASSERT(value <= (size_t) -1);
return value;
}
static int parse_options(int argc, struct gc_option argv[],
struct options *options) {
options->parallelism = 1;
for (int i = 0; i < argc; i++) {
switch (argv[i].option) {
case GC_OPTION_FIXED_HEAP_SIZE:
options->fixed_heap_size = parse_size_t(argv[i].value);
break;
case GC_OPTION_PARALLELISM:
options->parallelism = parse_size_t(argv[i].value);
break;
default:
GC_CRASH();
}
}
if (!options->fixed_heap_size) {
fprintf(stderr, "fixed heap size is currently required\n");
return 0;
}
if (options->parallelism != 1) {
fprintf(stderr, "parallelism unimplemented in semispace copying collector\n");
return 0;
}
return 1;
}
static int heap_prepare_pending_ephemerons(struct gc_heap *heap) { static int heap_prepare_pending_ephemerons(struct gc_heap *heap) {
struct gc_pending_ephemerons *cur = heap->pending_ephemerons; struct gc_pending_ephemerons *cur = heap->pending_ephemerons;
size_t target = heap->size * heap->pending_ephemerons_size_factor; size_t target = heap->size * heap->pending_ephemerons_size_factor;
@ -390,27 +326,60 @@ static int heap_init(struct gc_heap *heap, size_t size) {
return heap_prepare_pending_ephemerons(heap); return heap_prepare_pending_ephemerons(heap);
} }
int gc_init(int argc, struct gc_option argv[], struct gc_options {
struct gc_stack_addr *stack_base, struct gc_heap **heap, struct gc_common_options common;
struct gc_mutator **mut) { };
int gc_option_from_string(const char *str) {
return gc_common_option_from_string(str);
}
struct gc_options* gc_allocate_options(void) {
struct gc_options *ret = malloc(sizeof(struct gc_options));
gc_init_common_options(&ret->common);
return ret;
}
int gc_options_set_int(struct gc_options *options, int option, int value) {
return gc_common_options_set_int(&options->common, option, value);
}
int gc_options_set_size(struct gc_options *options, int option,
size_t value) {
return gc_common_options_set_size(&options->common, option, value);
}
int gc_options_set_double(struct gc_options *options, int option,
double value) {
return gc_common_options_set_double(&options->common, option, value);
}
int gc_options_parse_and_set(struct gc_options *options, int option,
const char *value) {
return gc_common_options_parse_and_set(&options->common, option, value);
}
int gc_init(struct gc_options *options, struct gc_stack_addr *stack_base,
struct gc_heap **heap, struct gc_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(),
offsetof(struct semi_space, limit)); offsetof(struct semi_space, limit));
struct options options = { 0, }; if (!options) options = gc_allocate_options();
if (!parse_options(argc, argv, &options))
if (options->common.heap_size_policy != GC_HEAP_SIZE_FIXED) {
fprintf(stderr, "fixed heap size is currently required\n");
return 0; return 0;
}
if (options->common.parallelism != 1) {
fprintf(stderr, "parallelism unimplemented in semispace copying collector\n");
return 0;
}
*mut = calloc(1, sizeof(struct gc_mutator)); *mut = calloc(1, sizeof(struct gc_mutator));
if (!*mut) GC_CRASH(); if (!*mut) GC_CRASH();
*heap = mutator_heap(*mut); *heap = mutator_heap(*mut);
if (!heap_init(*heap, options.fixed_heap_size)) if (!heap_init(*heap, options->common.heap_size))
return 0; return 0;
struct semi_space *space = mutator_semi_space(*mut); struct semi_space *space = mutator_semi_space(*mut);
if (!initialize_semi_space(space, options.fixed_heap_size)) if (!initialize_semi_space(space, options->common.heap_size))
return 0; return 0;
if (!large_object_space_init(heap_large_object_space(*heap), *heap)) if (!large_object_space_init(heap_large_object_space(*heap), *heap))
return 0; return 0;

108
whippet.c
View file

@ -2197,69 +2197,6 @@ unsigned gc_heap_ephemeron_trace_epoch(struct gc_heap *heap) {
return heap->count; return heap->count;
} }
#define FOR_EACH_GC_OPTION(M) \
M(GC_OPTION_FIXED_HEAP_SIZE, "fixed-heap-size") \
M(GC_OPTION_PARALLELISM, "parallelism")
static void dump_available_gc_options(void) {
fprintf(stderr, "available gc options:");
#define PRINT_OPTION(option, name) fprintf(stderr, " %s", name);
FOR_EACH_GC_OPTION(PRINT_OPTION)
#undef PRINT_OPTION
fprintf(stderr, "\n");
}
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
if (strcmp(str, "fixed-heap-size") == 0)
return GC_OPTION_FIXED_HEAP_SIZE;
if (strcmp(str, "parallelism") == 0)
return GC_OPTION_PARALLELISM;
fprintf(stderr, "bad gc option: '%s'\n", str);
dump_available_gc_options();
return -1;
}
struct options {
size_t fixed_heap_size;
size_t parallelism;
};
static size_t parse_size_t(double value) {
GC_ASSERT(value >= 0);
GC_ASSERT(value <= (size_t) -1);
return value;
}
static size_t number_of_current_processors(void) { return 1; }
static int parse_options(int argc, struct gc_option argv[],
struct options *options) {
for (int i = 0; i < argc; i++) {
switch (argv[i].option) {
case GC_OPTION_FIXED_HEAP_SIZE:
options->fixed_heap_size = parse_size_t(argv[i].value);
break;
case GC_OPTION_PARALLELISM:
options->parallelism = parse_size_t(argv[i].value);
break;
default:
GC_CRASH();
}
}
if (!options->fixed_heap_size) {
fprintf(stderr, "fixed heap size is currently required\n");
return 0;
}
if (!options->parallelism)
options->parallelism = number_of_current_processors();
return 1;
}
static struct slab* allocate_slabs(size_t nslabs) { static struct slab* allocate_slabs(size_t nslabs) {
size_t size = nslabs * SLAB_SIZE; size_t size = nslabs * SLAB_SIZE;
size_t extent = size + SLAB_SIZE; size_t extent = size + SLAB_SIZE;
@ -2294,15 +2231,42 @@ static int heap_prepare_pending_ephemerons(struct gc_heap *heap) {
return !!heap->pending_ephemerons; return !!heap->pending_ephemerons;
} }
static int heap_init(struct gc_heap *heap, struct options *options) { struct gc_options {
struct gc_common_options common;
};
int gc_option_from_string(const char *str) {
return gc_common_option_from_string(str);
}
struct gc_options* gc_allocate_options(void) {
struct gc_options *ret = malloc(sizeof(struct gc_options));
gc_init_common_options(&ret->common);
return ret;
}
int gc_options_set_int(struct gc_options *options, int option, int value) {
return gc_common_options_set_int(&options->common, option, value);
}
int gc_options_set_size(struct gc_options *options, int option,
size_t value) {
return gc_common_options_set_size(&options->common, option, value);
}
int gc_options_set_double(struct gc_options *options, int option,
double value) {
return gc_common_options_set_double(&options->common, option, value);
}
int gc_options_parse_and_set(struct gc_options *options, int option,
const char *value) {
return gc_common_options_parse_and_set(&options->common, option, value);
}
static int heap_init(struct gc_heap *heap, struct gc_options *options) {
// *heap is already initialized to 0. // *heap is already initialized to 0.
pthread_mutex_init(&heap->lock, NULL); pthread_mutex_init(&heap->lock, NULL);
pthread_cond_init(&heap->mutator_cond, NULL); pthread_cond_init(&heap->mutator_cond, NULL);
pthread_cond_init(&heap->collector_cond, NULL); pthread_cond_init(&heap->collector_cond, NULL);
heap->size = options->fixed_heap_size; heap->size = options->common.heap_size;
if (!tracer_init(heap, options->parallelism)) if (!tracer_init(heap, options->common.parallelism))
GC_CRASH(); GC_CRASH();
heap->pending_ephemerons_size_factor = 0.005; heap->pending_ephemerons_size_factor = 0.005;
@ -2352,9 +2316,8 @@ static int mark_space_init(struct mark_space *space, struct gc_heap *heap) {
return 1; return 1;
} }
int gc_init(int argc, struct gc_option argv[], int gc_init(struct gc_options *options, struct gc_stack_addr *stack_base,
struct gc_stack_addr *stack_base, struct gc_heap **heap, struct gc_heap **heap, struct gc_mutator **mut) {
struct gc_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);
GC_ASSERT_EQ(gc_allocator_allocation_pointer_offset(), GC_ASSERT_EQ(gc_allocator_allocation_pointer_offset(),
@ -2370,14 +2333,15 @@ int gc_init(int argc, struct gc_option argv[],
BLOCK_SIZE / REMSET_BYTES_PER_BLOCK); BLOCK_SIZE / REMSET_BYTES_PER_BLOCK);
} }
struct options options = { 0, }; if (options->common.heap_size_policy != GC_HEAP_SIZE_FIXED) {
if (!parse_options(argc, argv, &options)) fprintf(stderr, "fixed heap size is currently required\n");
return 0; return 0;
}
*heap = calloc(1, sizeof(struct gc_heap)); *heap = calloc(1, sizeof(struct gc_heap));
if (!*heap) GC_CRASH(); if (!*heap) GC_CRASH();
if (!heap_init(*heap, &options)) if (!heap_init(*heap, options))
GC_CRASH(); GC_CRASH();
struct mark_space *space = heap_mark_space(*heap); struct mark_space *space = heap_mark_space(*heap);