1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-09 07:00:23 +02:00
guile/gc-stack.c
Andy Wingo d2bde8319f Add conservative stack capture
This isn't really wired up yet anywhere, but add a precursor to
conservative stack scanning.
2022-10-03 16:09:21 +02:00

90 lines
2.7 KiB
C

// For pthread_getattr_np.
#define _GNU_SOURCE
#include <pthread.h>
#include <setjmp.h>
#include <stdio.h>
#include <unistd.h>
#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);
}
}