Fix some memory leaks
This commit is contained in:
23
src/gc.c
23
src/gc.c
@ -307,3 +307,26 @@ void lisp_gc_now(struct timespec *restrict time_took) {
|
||||
++total_gc_count;
|
||||
lisp_doing_gc = false;
|
||||
}
|
||||
|
||||
void lisp_gc_teardown(void) {
|
||||
assert(the_stack.depth == 0);
|
||||
while (white_objects) {
|
||||
free_object(white_objects->obj);
|
||||
}
|
||||
while (grey_objects) {
|
||||
free_object(grey_objects->obj);
|
||||
}
|
||||
while (black_objects) {
|
||||
free_object(black_objects->obj);
|
||||
}
|
||||
while (static_objects) {
|
||||
struct GCObjectList *next = static_objects->next;
|
||||
free(static_objects);
|
||||
static_objects = next;
|
||||
}
|
||||
while (free_objects_list) {
|
||||
struct GCObjectList *next = free_objects_list->next;
|
||||
free(free_objects_list);
|
||||
free_objects_list = next;
|
||||
}
|
||||
}
|
||||
|
||||
4
src/gc.h
4
src/gc.h
@ -33,4 +33,8 @@ void gc_move_to_set(void *val, ObjectGCSet new_set);
|
||||
|
||||
void lisp_gc_now(struct timespec *restrict time_took);
|
||||
|
||||
// Unregister all static objects and prepare for shutdown
|
||||
// The stack MUST be empty when this is called
|
||||
void lisp_gc_teardown(void);
|
||||
|
||||
#endif
|
||||
|
||||
@ -92,6 +92,7 @@ static void rehash(LispHashTable *ht, size_t new_size) {
|
||||
nb->value = cob->value;
|
||||
}
|
||||
}
|
||||
lisp_free(old_data);
|
||||
}
|
||||
|
||||
static void maybe_rehash(LispHashTable *ht) {
|
||||
|
||||
@ -52,7 +52,10 @@ void lisp_init(void) {
|
||||
lisp_init_stack();
|
||||
}
|
||||
|
||||
void lisp_shutdown(void) {}
|
||||
void lisp_shutdown(void) {
|
||||
lisp_gc_teardown();
|
||||
lisp_teardown_stack();
|
||||
}
|
||||
|
||||
DEFUN(eval, "eval", (LispVal * form), "(form)", "") {
|
||||
if (!OBJECTP(form)) {
|
||||
|
||||
@ -31,6 +31,7 @@ DEFUN(cons, "cons", (LispVal * car, LispVal *cdr), "(car cdr)",
|
||||
|
||||
DEFUN(length, "length", (LispVal * list), "(list)", "") {
|
||||
// TODO type check
|
||||
// TODO list may be circular
|
||||
return MAKE_FIXNUM(list_length(list));
|
||||
}
|
||||
|
||||
|
||||
16
src/stack.c
16
src/stack.c
@ -26,6 +26,21 @@ void lisp_init_stack(void) {
|
||||
the_stack.nogc_retval = Qnil;
|
||||
}
|
||||
|
||||
static void teardown_stack_frame(struct StackFrame *restrict frame) {
|
||||
for (size_t i = 0; i < frame->local_refs.num_blocks; ++i) {
|
||||
lisp_free(frame->local_refs.blocks[i]);
|
||||
}
|
||||
lisp_free(frame->local_refs.blocks);
|
||||
}
|
||||
|
||||
void lisp_teardown_stack(void) {
|
||||
assert(the_stack.depth == 0);
|
||||
for (size_t i = 0; i < the_stack.max_depth; ++i) {
|
||||
teardown_stack_frame(&the_stack.frames[i]);
|
||||
}
|
||||
lisp_free(the_stack.frames);
|
||||
}
|
||||
|
||||
void push_stack_frame(LispVal *name, LispVal *fobj, LispVal *args) {
|
||||
assert(the_stack.depth < the_stack.max_depth);
|
||||
struct StackFrame *frame = &the_stack.frames[the_stack.depth++];
|
||||
@ -164,6 +179,7 @@ void add_local_reference(LispVal *obj) {
|
||||
while ((cur = next_local_reference(&i))) {
|
||||
add_local_refs_for_object_sub_vals(seen_objs, cur);
|
||||
}
|
||||
release_hash_table_no_gc(seen_objs);
|
||||
}
|
||||
|
||||
void compact_stack_frame(struct StackFrame *restrict frame) {
|
||||
|
||||
@ -41,6 +41,7 @@ static ALWAYS_INLINE struct StackFrame *LISP_STACK_TOP(void) {
|
||||
}
|
||||
|
||||
void lisp_init_stack(void);
|
||||
void lisp_teardown_stack(void);
|
||||
void push_stack_frame(LispVal *name, LispVal *fobj, LispVal *args);
|
||||
void pop_stack_frame(void);
|
||||
void add_local_reference_no_recurse(LispVal *obj);
|
||||
|
||||
Reference in New Issue
Block a user