mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
Expose definition of gc_stack_addr, rework API
This commit is contained in:
parent
d3df1a632a
commit
2dab407ec1
13 changed files with 82 additions and 48 deletions
10
api/gc-api.h
10
api/gc-api.h
|
@ -11,6 +11,7 @@
|
||||||
#include "gc-inline.h"
|
#include "gc-inline.h"
|
||||||
#include "gc-options.h"
|
#include "gc-options.h"
|
||||||
#include "gc-ref.h"
|
#include "gc-ref.h"
|
||||||
|
#include "gc-stack-addr.h"
|
||||||
#include "gc-visibility.h"
|
#include "gc-visibility.h"
|
||||||
|
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
@ -20,13 +21,8 @@
|
||||||
struct gc_heap;
|
struct gc_heap;
|
||||||
struct gc_mutator;
|
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,
|
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_mutator **mutator,
|
||||||
struct gc_event_listener event_listener,
|
struct gc_event_listener event_listener,
|
||||||
void *event_listener_data);
|
void *event_listener_data);
|
||||||
|
@ -50,7 +46,7 @@ struct gc_extern_space;
|
||||||
GC_API_ void gc_heap_set_extern_space(struct gc_heap *heap,
|
GC_API_ void gc_heap_set_extern_space(struct gc_heap *heap,
|
||||||
struct gc_extern_space *space);
|
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);
|
struct gc_heap *heap);
|
||||||
GC_API_ void gc_finish_for_thread(struct gc_mutator *mut);
|
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*),
|
GC_API_ void* gc_call_without_gc(struct gc_mutator *mut, void* (*f)(void*),
|
||||||
|
|
36
api/gc-stack-addr.h
Normal file
36
api/gc-stack-addr.h
Normal file
|
@ -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
|
|
@ -56,7 +56,7 @@ struct call_with_gc_data {
|
||||||
void* (*f)(struct thread *);
|
void* (*f)(struct thread *);
|
||||||
struct gc_heap *heap;
|
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 call_with_gc_data *data = arg;
|
||||||
struct gc_mutator *mut = gc_init_for_thread(addr, data->heap);
|
struct gc_mutator *mut = gc_init_for_thread(addr, data->heap);
|
||||||
struct thread t = { mut, };
|
struct thread t = { mut, };
|
||||||
|
@ -234,7 +234,8 @@ int main(int argc, char *argv[]) {
|
||||||
struct gc_heap *heap;
|
struct gc_heap *heap;
|
||||||
struct gc_mutator *mut;
|
struct gc_mutator *mut;
|
||||||
struct gc_basic_stats stats;
|
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",
|
fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
|
||||||
(size_t)heap_size);
|
(size_t)heap_size);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -56,7 +56,7 @@ struct call_with_gc_data {
|
||||||
void* (*f)(struct thread *);
|
void* (*f)(struct thread *);
|
||||||
struct gc_heap *heap;
|
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 call_with_gc_data *data = arg;
|
||||||
struct gc_mutator *mut = gc_init_for_thread(addr, data->heap);
|
struct gc_mutator *mut = gc_init_for_thread(addr, data->heap);
|
||||||
struct thread t = { mut, };
|
struct thread t = { mut, };
|
||||||
|
@ -241,7 +241,8 @@ int main(int argc, char *argv[]) {
|
||||||
struct gc_heap *heap;
|
struct gc_heap *heap;
|
||||||
struct gc_mutator *mut;
|
struct gc_mutator *mut;
|
||||||
struct gc_basic_stats stats;
|
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",
|
fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
|
||||||
(size_t)heap_size);
|
(size_t)heap_size);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -258,7 +258,7 @@ struct call_with_gc_data {
|
||||||
void* (*f)(struct thread *);
|
void* (*f)(struct thread *);
|
||||||
struct gc_heap *heap;
|
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 call_with_gc_data *data = arg;
|
||||||
struct gc_mutator *mut = gc_init_for_thread(addr, data->heap);
|
struct gc_mutator *mut = gc_init_for_thread(addr, data->heap);
|
||||||
struct thread t = { mut, };
|
struct thread t = { mut, };
|
||||||
|
@ -364,7 +364,8 @@ int main(int argc, char *argv[]) {
|
||||||
struct gc_heap *heap;
|
struct gc_heap *heap;
|
||||||
struct gc_mutator *mut;
|
struct gc_mutator *mut;
|
||||||
struct gc_basic_stats stats;
|
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",
|
fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
|
||||||
heap_size);
|
heap_size);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -135,7 +135,8 @@ int main(int argc, char *argv[]) {
|
||||||
struct gc_heap *heap;
|
struct gc_heap *heap;
|
||||||
struct gc_mutator *mut;
|
struct gc_mutator *mut;
|
||||||
struct gc_basic_stats stats;
|
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",
|
fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
|
||||||
heap_size);
|
heap_size);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
1
embed.am
1
embed.am
|
@ -67,6 +67,7 @@ libwhippet_la_SOURCES = \
|
||||||
%D%/api/gc-null-event-listener.h \
|
%D%/api/gc-null-event-listener.h \
|
||||||
%D%/api/gc-options.h \
|
%D%/api/gc-options.h \
|
||||||
%D%/api/gc-ref.h \
|
%D%/api/gc-ref.h \
|
||||||
|
%D%/api/gc-stack-addr.h \
|
||||||
%D%/api/gc-tracepoint.h \
|
%D%/api/gc-tracepoint.h \
|
||||||
%D%/api/gc-visibility.h \
|
%D%/api/gc-visibility.h \
|
||||||
%D%/api/mmc-attrs.h \
|
%D%/api/mmc-attrs.h \
|
||||||
|
|
10
src/bdw.c
10
src/bdw.c
|
@ -490,6 +490,10 @@ static void on_collection_event(GC_EventType event) {
|
||||||
// Sloppily attribute finalizers and eager reclamation to
|
// Sloppily attribute finalizers and eager reclamation to
|
||||||
// ephemerons.
|
// ephemerons.
|
||||||
HEAP_EVENT(ephemerons_traced);
|
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());
|
HEAP_EVENT(live_data_size, GC_get_heap_size() - GC_get_free_bytes());
|
||||||
break;
|
break;
|
||||||
case GC_EVENT_END:
|
case GC_EVENT_END:
|
||||||
|
@ -517,7 +521,7 @@ uint64_t gc_allocation_counter(struct gc_heap *heap) {
|
||||||
return GC_get_total_bytes();
|
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_heap **heap, struct gc_mutator **mutator,
|
||||||
struct gc_event_listener event_listener,
|
struct gc_event_listener event_listener,
|
||||||
void *event_listener_data) {
|
void *event_listener_data) {
|
||||||
|
@ -613,9 +617,9 @@ int gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base,
|
||||||
return 1;
|
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_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);
|
GC_register_my_thread(&base);
|
||||||
return add_mutator(heap);
|
return add_mutator(heap);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,40 +26,37 @@ static uintptr_t current_thread_hot_stack_addr(void) {
|
||||||
// FIXME: check platform stack growth direction.
|
// FIXME: check platform stack growth direction.
|
||||||
#define HOTTER_THAN <=
|
#define HOTTER_THAN <=
|
||||||
|
|
||||||
static void capture_current_thread_hot_stack_addr(struct gc_stack_addr *addr) {
|
static struct gc_stack_addr capture_current_thread_hot_stack_addr(void) {
|
||||||
addr->addr = current_thread_hot_stack_addr();
|
return gc_stack_addr(current_thread_hot_stack_addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void capture_current_thread_cold_stack_addr(struct gc_stack_addr *addr) {
|
static struct gc_stack_addr capture_current_thread_cold_stack_addr(void) {
|
||||||
addr->addr = gc_platform_current_thread_stack_base();
|
return gc_stack_addr(gc_platform_current_thread_stack_base());
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc_stack_init(struct gc_stack *stack, struct gc_stack_addr *base) {
|
void gc_stack_init(struct gc_stack *stack, struct gc_stack_addr base) {
|
||||||
if (base)
|
if (gc_stack_addr_is_empty (base))
|
||||||
stack->cold = *base;
|
base = capture_current_thread_cold_stack_addr();
|
||||||
else
|
stack->cold = stack->hot = base;
|
||||||
capture_current_thread_cold_stack_addr(&stack->cold);
|
|
||||||
stack->hot = stack->cold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc_stack_capture_hot(struct gc_stack *stack) {
|
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);
|
setjmp(stack->registers);
|
||||||
GC_ASSERT(stack->hot.addr HOTTER_THAN stack->cold.addr);
|
GC_ASSERT(stack->hot.addr HOTTER_THAN stack->cold.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* call_with_stack(void* (*)(struct gc_stack_addr*, void*),
|
static void* call_with_stack(void* (*)(struct gc_stack_addr, void*),
|
||||||
struct gc_stack_addr*, void*) GC_NEVER_INLINE;
|
struct gc_stack_addr, void*) GC_NEVER_INLINE;
|
||||||
static void* call_with_stack(void* (*f)(struct gc_stack_addr *, void *),
|
static void* call_with_stack(void* (*f)(struct gc_stack_addr, void *),
|
||||||
struct gc_stack_addr *addr, void *arg) {
|
struct gc_stack_addr addr, void *arg) {
|
||||||
return f(addr, 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),
|
||||||
void *arg) {
|
void *arg) {
|
||||||
struct gc_stack_addr base;
|
struct gc_stack_addr base = capture_current_thread_hot_stack_addr();
|
||||||
capture_current_thread_hot_stack_addr(&base);
|
return call_with_stack(f, base, arg);
|
||||||
return call_with_stack(f, &base, arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc_stack_visit(struct gc_stack *stack,
|
void gc_stack_visit(struct gc_stack *stack,
|
||||||
|
|
|
@ -6,12 +6,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "gc-inline.h"
|
#include "gc-inline.h"
|
||||||
|
#include "gc-stack-addr.h"
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
struct gc_stack_addr {
|
|
||||||
uintptr_t addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gc_stack {
|
struct gc_stack {
|
||||||
struct gc_stack_addr cold;
|
struct gc_stack_addr cold;
|
||||||
struct gc_stack_addr hot;
|
struct gc_stack_addr hot;
|
||||||
|
@ -21,7 +18,7 @@ struct gc_stack {
|
||||||
struct gc_heap;
|
struct gc_heap;
|
||||||
|
|
||||||
GC_INTERNAL void gc_stack_init(struct gc_stack *stack,
|
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_capture_hot(struct gc_stack *stack);
|
||||||
GC_INTERNAL void gc_stack_visit(struct gc_stack *stack,
|
GC_INTERNAL void gc_stack_visit(struct gc_stack *stack,
|
||||||
void (*visit)(uintptr_t low, uintptr_t high,
|
void (*visit)(uintptr_t low, uintptr_t high,
|
||||||
|
|
|
@ -1148,7 +1148,7 @@ heap_init(struct gc_heap *heap, const struct gc_options *options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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_heap **heap, struct gc_mutator **mut,
|
||||||
struct gc_event_listener event_listener,
|
struct gc_event_listener event_listener,
|
||||||
void *event_listener_data) {
|
void *event_listener_data) {
|
||||||
|
@ -1217,8 +1217,7 @@ gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gc_mutator*
|
struct gc_mutator*
|
||||||
gc_init_for_thread(struct gc_stack_addr *stack_base,
|
gc_init_for_thread(struct gc_stack_addr stack_base, struct gc_heap *heap) {
|
||||||
struct gc_heap *heap) {
|
|
||||||
struct gc_mutator *ret = calloc(1, sizeof(struct gc_mutator));
|
struct gc_mutator *ret = calloc(1, sizeof(struct gc_mutator));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
GC_CRASH();
|
GC_CRASH();
|
||||||
|
|
|
@ -1218,7 +1218,7 @@ static int heap_init(struct gc_heap *heap, const struct gc_options *options) {
|
||||||
return 1;
|
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_heap **heap, struct gc_mutator **mut,
|
||||||
struct gc_event_listener event_listener,
|
struct gc_event_listener event_listener,
|
||||||
void *event_listener_data) {
|
void *event_listener_data) {
|
||||||
|
@ -1294,7 +1294,7 @@ int gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base,
|
||||||
return 1;
|
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_heap *heap) {
|
||||||
struct gc_mutator *ret = calloc(1, sizeof(struct gc_mutator));
|
struct gc_mutator *ret = calloc(1, sizeof(struct gc_mutator));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
|
@ -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);
|
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_heap **heap, struct gc_mutator **mut,
|
||||||
struct gc_event_listener event_listener,
|
struct gc_event_listener event_listener,
|
||||||
void *event_listener_data) {
|
void *event_listener_data) {
|
||||||
|
@ -722,7 +722,7 @@ void gc_heap_set_extern_space(struct gc_heap *heap,
|
||||||
heap->extern_space = space;
|
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) {
|
struct gc_heap *heap) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Semispace copying collector not appropriate for multithreaded use.\n");
|
"Semispace copying collector not appropriate for multithreaded use.\n");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue