mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-09 07:00:23 +02:00
This isn't really wired up yet anywhere, but add a precursor to conservative stack scanning.
90 lines
2.7 KiB
C
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);
|
|
}
|
|
}
|