swissChili | 6d6525e | 2021-06-15 21:20:53 -0700 | [diff] [blame] | 1 | #pragma once |
| 2 | |
swissChili | 9e57da4 | 2021-06-15 22:22:46 -0700 | [diff] [blame] | 3 | #include "lisp.h" |
| 4 | |
| 5 | // I hate this |
| 6 | extern value_t *gc_base; |
swissChili | 8056031 | 2022-07-31 21:05:47 -0700 | [diff] [blame] | 7 | extern struct gc_segment *gc_last_segment; |
| 8 | |
| 9 | struct gc_segment |
| 10 | { |
| 11 | struct gc_segment *prev; |
| 12 | |
| 13 | // The address of the first dword on the stack below the return |
| 14 | // pointer for this function (i.e. when the procedure is first |
| 15 | // `call`'d, this is esp+4) |
| 16 | void *seg_start; |
| 17 | |
| 18 | // The address of the return pointer for the subsequently called |
| 19 | // function on the stack. When the lisp function is called, |
| 20 | // seg_end=esp. |
| 21 | void *seg_end; |
| 22 | |
| 23 | // The number of arguments passed to the lisp function. These are |
| 24 | // stored in order on the stack, starting at seg_end+4, each |
| 25 | // taking 1 dword of memory. |
| 26 | int nargs; |
| 27 | |
| 28 | // The value of ebp as it was when the function was first |
| 29 | // invoked. This denotes the caller's stack frame. |
| 30 | void *old_ebp; |
| 31 | |
| 32 | // The number of lisp values which are retained by this C |
| 33 | // function. |
| 34 | int nretained; |
| 35 | value_t retained[]; |
| 36 | }; |
| 37 | |
| 38 | #define gc_prepare_call(nargs) \ |
| 39 | { \ |
| 40 | void *__gc_segment_base; \ |
| 41 | asm("movl %%esp, %0" : "=g"(__gc_segment_base)); \ |
| 42 | gc_prepare_call_(__gc_segment_base, nargs); \ |
| 43 | } |
| 44 | void gc_push_segment(void *last_arg_addr, int nretained); |
| 45 | void gc_pop_segment(); |
| 46 | void gc_prepare_call_(void *esp, int nargs); |
| 47 | void gc_set_retained(int index, value_t retained); |
swissChili | 9e57da4 | 2021-06-15 22:22:46 -0700 | [diff] [blame] | 48 | |
swissChili | a890aed | 2022-07-30 17:13:07 -0700 | [diff] [blame] | 49 | struct gc_stats |
| 50 | { |
| 51 | // bytes currently used |
| 52 | unsigned long bytes_used; |
| 53 | // bytes ever freed by the GC |
| 54 | unsigned long bytes_freed; |
| 55 | // how many total allocations are currently alive |
| 56 | unsigned long total_allocs; |
| 57 | // how many times has the GC ever been run |
| 58 | unsigned long gc_runs; |
| 59 | }; |
| 60 | |
swissChili | 9e57da4 | 2021-06-15 22:22:46 -0700 | [diff] [blame] | 61 | void gc_set_base_here(); |
| 62 | |
swissChili | e9fec8b | 2021-06-22 13:59:33 -0700 | [diff] [blame] | 63 | value_t alloc_to_value(struct alloc *a); |
swissChili | 6d6525e | 2021-06-15 21:20:53 -0700 | [diff] [blame] | 64 | void _do_gc(unsigned int esp, unsigned int ebp); |
swissChili | e9fec8b | 2021-06-22 13:59:33 -0700 | [diff] [blame] | 65 | void _mark(value_t value, unsigned int *marked); |
swissChili | 6d6525e | 2021-06-15 21:20:53 -0700 | [diff] [blame] | 66 | void _sweep(); |
swissChili | b8fd471 | 2021-06-23 15:32:04 -0700 | [diff] [blame] | 67 | void free_all(); |
swissChili | a890aed | 2022-07-30 17:13:07 -0700 | [diff] [blame] | 68 | struct gc_stats gc_get_stats(); |