// For pthread_getattr_np. #define _GNU_SOURCE #include #include #include #include #define GC_IMPL 1 #include "debug.h" #include "gc-align.h" #include "gc-assert.h" #include "gc-inline.h" #include "gc-platform.h" #include "gc-stack.h" static uintptr_t current_thread_hot_stack_addr(void) { #ifdef __GCC__ return (uintptr_t)__builtin_frame_address(0); #else uintptr_t local; return (uintptr_t)&local; #endif } // 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 void capture_current_thread_cold_stack_addr(struct gc_stack_addr *addr) { addr->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_capture_hot(struct gc_stack *stack) { capture_current_thread_hot_stack_addr(&stack->hot); 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) { return f(addr, arg); } 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); } void gc_stack_visit(struct gc_stack *stack, void (*visit)(uintptr_t low, uintptr_t high, void *data), void *data) { { uintptr_t low = (uintptr_t)stack->registers; GC_ASSERT(low == align_down(low, sizeof(uintptr_t))); uintptr_t high = low + sizeof(jmp_buf); DEBUG("found mutator register roots for %p: [%p,%p)\n", stack, (void*)low, (void*)high); visit(low, high, data); } if (0 HOTTER_THAN 1) { DEBUG("found mutator stack roots for %p: [%p,%p)\n", stack, (void*)stack->hot.addr, (void*)stack->cold.addr); visit(align_up(stack->hot.addr, sizeof(uintptr_t)), align_down(stack->cold.addr, sizeof(uintptr_t)), data); } else { DEBUG("found mutator stack roots for %p: [%p,%p)\n", stack, (void*)stack->cold.addr, (void*)stack->hot.addr); visit(align_up(stack->cold.addr, sizeof(uintptr_t)), align_down(stack->hot.addr, sizeof(uintptr_t)), data); } }