diff --git a/api/gc-api.h b/api/gc-api.h index 78d8b2bdb..603b38030 100644 --- a/api/gc-api.h +++ b/api/gc-api.h @@ -11,6 +11,7 @@ #include "gc-inline.h" #include "gc-options.h" #include "gc-ref.h" +#include "gc-stack-addr.h" #include "gc-visibility.h" #include @@ -20,13 +21,8 @@ struct gc_heap; struct gc_mutator; -struct gc_stack_addr; -GC_API_ void* gc_call_with_stack_addr(void* (*f)(struct gc_stack_addr *, - void *), - void *data) GC_NEVER_INLINE; - GC_API_ int gc_init(const struct gc_options *options, - struct gc_stack_addr *base, struct gc_heap **heap, + struct gc_stack_addr base, struct gc_heap **heap, struct gc_mutator **mutator, struct gc_event_listener event_listener, void *event_listener_data); @@ -50,7 +46,7 @@ struct gc_extern_space; GC_API_ void gc_heap_set_extern_space(struct gc_heap *heap, struct gc_extern_space *space); -GC_API_ struct gc_mutator* gc_init_for_thread(struct gc_stack_addr *base, +GC_API_ struct gc_mutator* gc_init_for_thread(struct gc_stack_addr base, struct gc_heap *heap); GC_API_ void gc_finish_for_thread(struct gc_mutator *mut); GC_API_ void* gc_call_without_gc(struct gc_mutator *mut, void* (*f)(void*), diff --git a/api/gc-stack-addr.h b/api/gc-stack-addr.h new file mode 100644 index 000000000..62c089432 --- /dev/null +++ b/api/gc-stack-addr.h @@ -0,0 +1,36 @@ +#ifndef GC_STACK_ADDR_H +#define GC_STACK_ADDR_H + +#include "gc-assert.h" +#include "gc-visibility.h" + +struct gc_stack_addr { + uintptr_t addr; +}; + +static inline struct gc_stack_addr gc_empty_stack_addr (void) { + return (struct gc_stack_addr){ 0 }; +}; + +static inline int gc_stack_addr_is_empty (struct gc_stack_addr addr) { + return addr.addr == 0; +}; + +static inline char* gc_stack_addr_as_pointer (struct gc_stack_addr addr) { + GC_ASSERT(!gc_stack_addr_is_empty(addr)); + return (char*)addr.addr; +}; + +static inline struct gc_stack_addr gc_stack_addr (uintptr_t addr) { + GC_ASSERT(addr); + return (struct gc_stack_addr){ addr }; +}; + +GC_API_ void* gc_call_with_stack_addr(void* (*f)(struct gc_stack_addr, + void *), + void *data) GC_NEVER_INLINE; + +GC_API_ int gc_stack_addr_is_colder(struct gc_stack_addr a, + struct gc_stack_addr b); + +#endif // GC_STACK_ADDR_H diff --git a/benchmarks/ephemerons.c b/benchmarks/ephemerons.c index 2262bd5c9..c74db9d43 100644 --- a/benchmarks/ephemerons.c +++ b/benchmarks/ephemerons.c @@ -56,7 +56,7 @@ struct call_with_gc_data { void* (*f)(struct thread *); struct gc_heap *heap; }; -static void* call_with_gc_inner(struct gc_stack_addr *addr, void *arg) { +static void* call_with_gc_inner(struct gc_stack_addr addr, void *arg) { struct call_with_gc_data *data = arg; struct gc_mutator *mut = gc_init_for_thread(addr, data->heap); struct thread t = { mut, }; @@ -234,7 +234,8 @@ int main(int argc, char *argv[]) { struct gc_heap *heap; struct gc_mutator *mut; struct gc_basic_stats stats; - if (!gc_init(options, NULL, &heap, &mut, GC_BASIC_STATS, &stats)) { + if (!gc_init(options, gc_empty_stack_addr(), &heap, &mut, + GC_BASIC_STATS, &stats)) { fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n", (size_t)heap_size); return 1; diff --git a/benchmarks/finalizers.c b/benchmarks/finalizers.c index 537307118..79a2660c3 100644 --- a/benchmarks/finalizers.c +++ b/benchmarks/finalizers.c @@ -56,7 +56,7 @@ struct call_with_gc_data { void* (*f)(struct thread *); struct gc_heap *heap; }; -static void* call_with_gc_inner(struct gc_stack_addr *addr, void *arg) { +static void* call_with_gc_inner(struct gc_stack_addr addr, void *arg) { struct call_with_gc_data *data = arg; struct gc_mutator *mut = gc_init_for_thread(addr, data->heap); struct thread t = { mut, }; @@ -241,7 +241,8 @@ int main(int argc, char *argv[]) { struct gc_heap *heap; struct gc_mutator *mut; struct gc_basic_stats stats; - if (!gc_init(options, NULL, &heap, &mut, GC_BASIC_STATS, &stats)) { + if (!gc_init(options, gc_empty_stack_addr(), &heap, &mut, + GC_BASIC_STATS, &stats)) { fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n", (size_t)heap_size); return 1; diff --git a/benchmarks/mt-gcbench.c b/benchmarks/mt-gcbench.c index 9b2521043..62fdc7154 100644 --- a/benchmarks/mt-gcbench.c +++ b/benchmarks/mt-gcbench.c @@ -258,7 +258,7 @@ struct call_with_gc_data { void* (*f)(struct thread *); struct gc_heap *heap; }; -static void* call_with_gc_inner(struct gc_stack_addr *addr, void *arg) { +static void* call_with_gc_inner(struct gc_stack_addr addr, void *arg) { struct call_with_gc_data *data = arg; struct gc_mutator *mut = gc_init_for_thread(addr, data->heap); struct thread t = { mut, }; @@ -364,7 +364,8 @@ int main(int argc, char *argv[]) { struct gc_heap *heap; struct gc_mutator *mut; struct gc_basic_stats stats; - if (!gc_init(options, NULL, &heap, &mut, GC_BASIC_STATS, &stats)) { + if (!gc_init(options, gc_empty_stack_addr(), &heap, &mut, + GC_BASIC_STATS, &stats)) { fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n", heap_size); return 1; diff --git a/benchmarks/quads.c b/benchmarks/quads.c index 6fa19f452..51bcca870 100644 --- a/benchmarks/quads.c +++ b/benchmarks/quads.c @@ -135,7 +135,8 @@ int main(int argc, char *argv[]) { struct gc_heap *heap; struct gc_mutator *mut; struct gc_basic_stats stats; - if (!gc_init(options, NULL, &heap, &mut, GC_BASIC_STATS, &stats)) { + if (!gc_init(options, gc_empty_stack_addr(), &heap, &mut, + GC_BASIC_STATS, &stats)) { fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n", heap_size); return 1; diff --git a/embed.am b/embed.am index d59dbd06f..57423b515 100644 --- a/embed.am +++ b/embed.am @@ -67,6 +67,7 @@ libwhippet_la_SOURCES = \ %D%/api/gc-null-event-listener.h \ %D%/api/gc-options.h \ %D%/api/gc-ref.h \ + %D%/api/gc-stack-addr.h \ %D%/api/gc-tracepoint.h \ %D%/api/gc-visibility.h \ %D%/api/mmc-attrs.h \ diff --git a/src/bdw.c b/src/bdw.c index 2fcc02e37..83a157d61 100644 --- a/src/bdw.c +++ b/src/bdw.c @@ -490,6 +490,10 @@ static void on_collection_event(GC_EventType event) { // Sloppily attribute finalizers and eager reclamation to // ephemerons. HEAP_EVENT(ephemerons_traced); + // FIXME: This overestimates the live data size, as blocks that have at + // least one live object will be lazily swept, and free space discovered in + // those objects will be added to GC_bytes_found, which would need to be + // subtracted from this value. HEAP_EVENT(live_data_size, GC_get_heap_size() - GC_get_free_bytes()); break; case GC_EVENT_END: @@ -517,7 +521,7 @@ uint64_t gc_allocation_counter(struct gc_heap *heap) { return GC_get_total_bytes(); } -int gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base, +int gc_init(const struct gc_options *options, struct gc_stack_addr stack_base, struct gc_heap **heap, struct gc_mutator **mutator, struct gc_event_listener event_listener, void *event_listener_data) { @@ -613,9 +617,9 @@ int gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base, return 1; } -struct gc_mutator* gc_init_for_thread(struct gc_stack_addr *stack_base, +struct gc_mutator* gc_init_for_thread(struct gc_stack_addr stack_base, struct gc_heap *heap) { - struct GC_stack_base base = { stack_base }; + struct GC_stack_base base = { gc_stack_addr_as_pointer (stack_base) }; GC_register_my_thread(&base); return add_mutator(heap); } diff --git a/src/gc-stack.c b/src/gc-stack.c index 318f5757f..e4e170505 100644 --- a/src/gc-stack.c +++ b/src/gc-stack.c @@ -26,40 +26,37 @@ static uintptr_t current_thread_hot_stack_addr(void) { // FIXME: check platform stack growth direction. #define HOTTER_THAN <= -static void capture_current_thread_hot_stack_addr(struct gc_stack_addr *addr) { - addr->addr = current_thread_hot_stack_addr(); +static struct gc_stack_addr capture_current_thread_hot_stack_addr(void) { + return gc_stack_addr(current_thread_hot_stack_addr()); } -static void capture_current_thread_cold_stack_addr(struct gc_stack_addr *addr) { - addr->addr = gc_platform_current_thread_stack_base(); +static struct gc_stack_addr capture_current_thread_cold_stack_addr(void) { + return gc_stack_addr(gc_platform_current_thread_stack_base()); } -void gc_stack_init(struct gc_stack *stack, struct gc_stack_addr *base) { - if (base) - stack->cold = *base; - else - capture_current_thread_cold_stack_addr(&stack->cold); - stack->hot = stack->cold; +void gc_stack_init(struct gc_stack *stack, struct gc_stack_addr base) { + if (gc_stack_addr_is_empty (base)) + base = capture_current_thread_cold_stack_addr(); + stack->cold = stack->hot = base; } void gc_stack_capture_hot(struct gc_stack *stack) { - capture_current_thread_hot_stack_addr(&stack->hot); + stack->hot = capture_current_thread_hot_stack_addr(); setjmp(stack->registers); GC_ASSERT(stack->hot.addr HOTTER_THAN stack->cold.addr); } -static void* call_with_stack(void* (*)(struct gc_stack_addr*, void*), - struct gc_stack_addr*, void*) GC_NEVER_INLINE; -static void* call_with_stack(void* (*f)(struct gc_stack_addr *, void *), - struct gc_stack_addr *addr, void *arg) { +static void* call_with_stack(void* (*)(struct gc_stack_addr, void*), + struct gc_stack_addr, void*) GC_NEVER_INLINE; +static void* call_with_stack(void* (*f)(struct gc_stack_addr, void *), + struct gc_stack_addr addr, void *arg) { return f(addr, arg); } -void* gc_call_with_stack_addr(void* (*f)(struct gc_stack_addr *base, +void* gc_call_with_stack_addr(void* (*f)(struct gc_stack_addr base, void *arg), void *arg) { - struct gc_stack_addr base; - capture_current_thread_hot_stack_addr(&base); - return call_with_stack(f, &base, arg); + struct gc_stack_addr base = capture_current_thread_hot_stack_addr(); + return call_with_stack(f, base, arg); } void gc_stack_visit(struct gc_stack *stack, diff --git a/src/gc-stack.h b/src/gc-stack.h index 15df9df6d..b075f5a57 100644 --- a/src/gc-stack.h +++ b/src/gc-stack.h @@ -6,12 +6,9 @@ #endif #include "gc-inline.h" +#include "gc-stack-addr.h" #include -struct gc_stack_addr { - uintptr_t addr; -}; - struct gc_stack { struct gc_stack_addr cold; struct gc_stack_addr hot; @@ -21,7 +18,7 @@ struct gc_stack { struct gc_heap; GC_INTERNAL void gc_stack_init(struct gc_stack *stack, - struct gc_stack_addr *base); + struct gc_stack_addr base); GC_INTERNAL void gc_stack_capture_hot(struct gc_stack *stack); GC_INTERNAL void gc_stack_visit(struct gc_stack *stack, void (*visit)(uintptr_t low, uintptr_t high, diff --git a/src/mmc.c b/src/mmc.c index 661b7084b..d2bc4df9d 100644 --- a/src/mmc.c +++ b/src/mmc.c @@ -1148,7 +1148,7 @@ heap_init(struct gc_heap *heap, const struct gc_options *options) { } int -gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base, +gc_init(const struct gc_options *options, struct gc_stack_addr stack_base, struct gc_heap **heap, struct gc_mutator **mut, struct gc_event_listener event_listener, void *event_listener_data) { @@ -1217,8 +1217,7 @@ gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base, } struct gc_mutator* -gc_init_for_thread(struct gc_stack_addr *stack_base, - struct gc_heap *heap) { +gc_init_for_thread(struct gc_stack_addr stack_base, struct gc_heap *heap) { struct gc_mutator *ret = calloc(1, sizeof(struct gc_mutator)); if (!ret) GC_CRASH(); diff --git a/src/pcc.c b/src/pcc.c index ca8be1c11..0b137f56b 100644 --- a/src/pcc.c +++ b/src/pcc.c @@ -1218,7 +1218,7 @@ static int heap_init(struct gc_heap *heap, const struct gc_options *options) { return 1; } -int gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base, +int gc_init(const struct gc_options *options, struct gc_stack_addr stack_base, struct gc_heap **heap, struct gc_mutator **mut, struct gc_event_listener event_listener, void *event_listener_data) { @@ -1294,7 +1294,7 @@ int gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base, return 1; } -struct gc_mutator* gc_init_for_thread(struct gc_stack_addr *stack_base, +struct gc_mutator* gc_init_for_thread(struct gc_stack_addr stack_base, struct gc_heap *heap) { struct gc_mutator *ret = calloc(1, sizeof(struct gc_mutator)); if (!ret) diff --git a/src/semi.c b/src/semi.c index 6f902534d..a4ee85f39 100644 --- a/src/semi.c +++ b/src/semi.c @@ -670,7 +670,7 @@ int gc_options_parse_and_set(struct gc_options *options, int option, return gc_common_options_parse_and_set(&options->common, option, value); } -int gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base, +int gc_init(const struct gc_options *options, struct gc_stack_addr stack_base, struct gc_heap **heap, struct gc_mutator **mut, struct gc_event_listener event_listener, void *event_listener_data) { @@ -722,7 +722,7 @@ void gc_heap_set_extern_space(struct gc_heap *heap, heap->extern_space = space; } -struct gc_mutator* gc_init_for_thread(struct gc_stack_addr *base, +struct gc_mutator* gc_init_for_thread(struct gc_stack_addr base, struct gc_heap *heap) { fprintf(stderr, "Semispace copying collector not appropriate for multithreaded use.\n");