mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-16 18:50:23 +02:00
Add conservative stack capture
This isn't really wired up yet anywhere, but add a precursor to conservative stack scanning.
This commit is contained in:
parent
a5b1a66d21
commit
d2bde8319f
10 changed files with 200 additions and 58 deletions
90
gc-stack.c
Normal file
90
gc-stack.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue