Fix gc with exceptions
This commit is contained in:
@@ -23,17 +23,16 @@ static size_t free_objects_list_count;
|
||||
static struct GCObjectList *free_objects_list;
|
||||
|
||||
static struct GCObjectList *black_objects;
|
||||
static struct GCObjectList *grey_objects;
|
||||
static struct GCObjectList *GRAY_objects;
|
||||
static struct GCObjectList *white_objects;
|
||||
static struct GCObjectList *static_objects;
|
||||
|
||||
ObjectGCSet GC_BLACK = 0;
|
||||
ObjectGCSet GC_GREY = 1;
|
||||
ObjectGCSet GC_GRAY = 1;
|
||||
ObjectGCSet GC_WHITE = 2;
|
||||
|
||||
enum IncrementalGCSetp {
|
||||
GC_STEP_STATICS,
|
||||
GC_STEP_UNWIND,
|
||||
GC_STEP_STACK,
|
||||
GC_STEP_HEAP,
|
||||
GC_STEP_FREE,
|
||||
@@ -52,8 +51,8 @@ static struct IncrementalGCState incremental_state = {
|
||||
static ALWAYS_INLINE struct GCObjectList **HEAD_FOR_SET(ObjectGCSet set) {
|
||||
if (set == GC_BLACK) {
|
||||
return &black_objects;
|
||||
} else if (set == GC_GREY) {
|
||||
return &grey_objects;
|
||||
} else if (set == GC_GRAY) {
|
||||
return &GRAY_objects;
|
||||
} else if (set == GC_WHITE) {
|
||||
return &white_objects;
|
||||
} else {
|
||||
@@ -188,9 +187,9 @@ static void free_object(LispVal *val) {
|
||||
lisp_release_object(val);
|
||||
}
|
||||
|
||||
static inline void make_grey_if_white(LispVal *val) {
|
||||
static inline void make_GRAY_if_white(LispVal *val) {
|
||||
if (OBJECTP(val) && OBJECT_GC_SET_P(val, GC_WHITE)) {
|
||||
gc_move_to_set(val, GC_GREY);
|
||||
gc_move_to_set(val, GC_GRAY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,39 +200,39 @@ static void mark_object(LispVal *val) {
|
||||
}
|
||||
switch (((LispObject *) val)->type) {
|
||||
case TYPE_CONS:
|
||||
make_grey_if_white(((LispCons *) val)->car);
|
||||
make_grey_if_white(((LispCons *) val)->cdr);
|
||||
make_GRAY_if_white(((LispCons *) val)->car);
|
||||
make_GRAY_if_white(((LispCons *) val)->cdr);
|
||||
break;
|
||||
case TYPE_SYMBOL: {
|
||||
LispSymbol *sym = val;
|
||||
make_grey_if_white(sym->name);
|
||||
make_grey_if_white(SYMBOL_VALUE(sym));
|
||||
make_grey_if_white(sym->function);
|
||||
make_grey_if_white(sym->plist);
|
||||
make_GRAY_if_white(sym->name);
|
||||
make_GRAY_if_white(SYMBOL_VALUE(sym));
|
||||
make_GRAY_if_white(sym->function);
|
||||
make_GRAY_if_white(sym->plist);
|
||||
break;
|
||||
}
|
||||
case TYPE_VECTOR: {
|
||||
LispVector *vec = val;
|
||||
for (size_t i = 0; i < vec->length; ++i) {
|
||||
make_grey_if_white(vec->data[i]);
|
||||
make_GRAY_if_white(vec->data[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TYPE_HASH_TABLE: {
|
||||
HT_FOREACH_INDEX(val, i) {
|
||||
make_grey_if_white(HASH_KEY(val, i));
|
||||
make_grey_if_white(HASH_VALUE(val, i));
|
||||
make_GRAY_if_white(HASH_KEY(val, i));
|
||||
make_GRAY_if_white(HASH_VALUE(val, i));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TYPE_FUNCTION: {
|
||||
LispFunction *fobj = val;
|
||||
make_grey_if_white(fobj->name);
|
||||
make_grey_if_white(fobj->docstr);
|
||||
make_grey_if_white(fobj->args.req);
|
||||
make_grey_if_white(fobj->args.opt);
|
||||
make_grey_if_white(fobj->args.kw);
|
||||
make_grey_if_white(fobj->args.rest);
|
||||
make_GRAY_if_white(fobj->name);
|
||||
make_GRAY_if_white(fobj->docstr);
|
||||
make_GRAY_if_white(fobj->args.req);
|
||||
make_GRAY_if_white(fobj->args.opt);
|
||||
make_GRAY_if_white(fobj->args.kw);
|
||||
make_GRAY_if_white(fobj->args.rest);
|
||||
break;
|
||||
}
|
||||
case TYPE_STRING:
|
||||
@@ -265,7 +264,7 @@ static void mark_statics(size_t *restrict limit) {
|
||||
// we processed the whole list, move to the next step
|
||||
if (!node) {
|
||||
incremental_state.next_static = static_objects;
|
||||
incremental_state.step = GC_STEP_UNWIND;
|
||||
incremental_state.step = GC_STEP_STACK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,26 +311,6 @@ static void mark_stack_frame(StackFrame *frame, size_t *restrict limit) {
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_unwind_info(size_t *restrict limit) {
|
||||
if (the_stack.unwind_info.set) {
|
||||
switch (the_stack.unwind_info.cause) {
|
||||
case UNWIND_NORMAL:
|
||||
mark_object(the_stack.unwind_info.target);
|
||||
saturating_dec(limit, 1);
|
||||
break;
|
||||
case UNWIND_EXCEPTION:
|
||||
mark_object(the_stack.unwind_info.exception.name);
|
||||
mark_object(the_stack.unwind_info.exception.data);
|
||||
saturating_dec(limit, 2);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
incremental_state.step = GC_STEP_STACK;
|
||||
}
|
||||
|
||||
static void mark_the_stack(size_t *restrict limit) {
|
||||
size_t i;
|
||||
for (i = 0; i < the_stack.depth && *limit; ++i) {
|
||||
@@ -351,11 +330,11 @@ static void unmark_the_stack(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_grey_objects(size_t *restrict limit) {
|
||||
while (grey_objects && saturating_dec(limit, 1)) {
|
||||
mark_object(grey_objects->obj);
|
||||
static void mark_GRAY_objects(size_t *restrict limit) {
|
||||
while (GRAY_objects && saturating_dec(limit, 1)) {
|
||||
mark_object(GRAY_objects->obj);
|
||||
}
|
||||
if (!grey_objects) {
|
||||
if (!GRAY_objects) {
|
||||
incremental_state.step = GC_STEP_FREE;
|
||||
}
|
||||
}
|
||||
@@ -398,22 +377,19 @@ void lisp_gc_yield(struct timespec *restrict time_took, bool full) {
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
|
||||
size_t limit = full ? SIZE_MAX : LISP_GC_INCREMENTAL_COUNT;
|
||||
while (limit) {
|
||||
// there are more grey objects, mark them before we sweep
|
||||
if (incremental_state.step == GC_STEP_FREE && grey_objects) {
|
||||
// there are more GRAY objects, mark them before we sweep
|
||||
if (incremental_state.step == GC_STEP_FREE && GRAY_objects) {
|
||||
incremental_state.step = GC_STEP_HEAP;
|
||||
}
|
||||
switch (incremental_state.step) {
|
||||
case GC_STEP_STATICS:
|
||||
mark_statics(&limit);
|
||||
break;
|
||||
case GC_STEP_UNWIND:
|
||||
mark_unwind_info(&limit);
|
||||
break;
|
||||
case GC_STEP_STACK:
|
||||
mark_the_stack(&limit);
|
||||
break;
|
||||
case GC_STEP_HEAP:
|
||||
mark_grey_objects(&limit);
|
||||
mark_GRAY_objects(&limit);
|
||||
break;
|
||||
case GC_STEP_FREE:
|
||||
gc_sweep_objects(&limit);
|
||||
@@ -438,8 +414,8 @@ void lisp_gc_teardown(void) {
|
||||
while (white_objects) {
|
||||
free_object(white_objects->obj);
|
||||
}
|
||||
while (grey_objects) {
|
||||
free_object(grey_objects->obj);
|
||||
while (GRAY_objects) {
|
||||
free_object(GRAY_objects->obj);
|
||||
}
|
||||
while (black_objects) {
|
||||
free_object(black_objects->obj);
|
||||
|
||||
Reference in New Issue
Block a user