Implement pin-based gc
This will allow for cleanup to occur mid-calculation when used throughout
This commit is contained in:
@@ -38,8 +38,8 @@ void ucl_add_special(struct ucl *state, const char *name, ucl_lisp fun);
|
|||||||
if (len != 2) { \
|
if (len != 2) { \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
struct ucl_object *arg0 = ucl_list_nth(args, 0); \
|
struct ucl_object *arg0 = ucl_list_nth(args, 0); \
|
||||||
struct ucl_object *arg1 = ucl_list_nth(args, 1); \
|
struct ucl_object *arg1 = ucl_list_nth(args, 1); \
|
||||||
return func_name##_impl(ucl, scope, arg0, arg1); \
|
return func_name##_impl(ucl, scope, arg0, arg1); \
|
||||||
} \
|
} \
|
||||||
static struct ucl_object *func_name##_impl(UNUSED struct ucl *ucl_name, UNUSED struct ucl_scope *scope, struct ucl_object *arg0_name, struct ucl_object *arg1_name)
|
static struct ucl_object *func_name##_impl(UNUSED struct ucl *ucl_name, UNUSED struct ucl_scope *scope, struct ucl_object *arg0_name, struct ucl_object *arg1_name)
|
||||||
|
|||||||
35
src/memory.c
35
src/memory.c
@@ -83,7 +83,7 @@ void ucl_object_pin(struct ucl_object *obj) {
|
|||||||
obj->flags |= UCL_OBJ_FLAG_PINNED;
|
obj->flags |= UCL_OBJ_FLAG_PINNED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ucl_object_unpinned(struct ucl_object *obj) {
|
void ucl_object_unpin(struct ucl_object *obj) {
|
||||||
obj->flags &= ~UCL_OBJ_FLAG_PINNED;
|
obj->flags &= ~UCL_OBJ_FLAG_PINNED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,52 +131,43 @@ void ucl_object_delete(struct ucl* state, struct ucl_object *obj) {
|
|||||||
ucl_object_delete_internal(state->obj_arena, obj);
|
ucl_object_delete_internal(state->obj_arena, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ucl_object_mark(struct ucl_object *obj) {
|
static void ucl_object_mark_recursive(struct ucl_object *obj) {
|
||||||
if (obj == NULL || obj->flags & UCL_OBJ_FLAG_REACHABLE) {
|
if (obj == NULL || obj->flags & UCL_OBJ_FLAG_REACHABLE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj->flags |= 1;
|
obj->flags |= UCL_OBJ_FLAG_REACHABLE;
|
||||||
if (obj->type == UCL_TYPE_CELL) {
|
if (obj->type == UCL_TYPE_CELL) {
|
||||||
ucl_object_mark(obj->cell.car);
|
ucl_object_mark_recursive(obj->cell.car);
|
||||||
ucl_object_mark(obj->cell.cdr);
|
ucl_object_mark_recursive(obj->cell.cdr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ucl_scope_mark(struct ucl_arena * arena, void *obj) {
|
static void ucl_gc_mark_pinned(struct ucl_arena * arena, void *obj) {
|
||||||
(void) arena;
|
(void) arena;
|
||||||
struct ucl_scope *scope = (struct ucl_scope *) obj;
|
struct ucl_object *object = (struct ucl_object *) obj;
|
||||||
|
|
||||||
ucl_object_mark(scope->list);
|
if (object->flags & UCL_OBJ_FLAG_PINNED) {
|
||||||
|
ucl_object_mark_recursive(object);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ucl_gc_unmark(struct ucl_arena * arena, void *obj) {
|
static void ucl_gc_unmark_all(struct ucl_arena * arena, void *obj) {
|
||||||
(void) arena;
|
(void) arena;
|
||||||
struct ucl_object *object = (struct ucl_object *) obj;
|
struct ucl_object *object = (struct ucl_object *) obj;
|
||||||
object->flags &= ~UCL_OBJ_FLAG_REACHABLE;
|
object->flags &= ~UCL_OBJ_FLAG_REACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ucl_gc_sweep(struct ucl_arena * arena, void *obj) {
|
static void ucl_gc_sweep(struct ucl_arena * arena, void *obj) {
|
||||||
(void) arena;
|
|
||||||
struct ucl_object *object = (struct ucl_object *) obj;
|
struct ucl_object *object = (struct ucl_object *) obj;
|
||||||
if (!(object->flags &UCL_OBJ_FLAG_REACHABLE)) {
|
if (!(object->flags &UCL_OBJ_FLAG_REACHABLE)) {
|
||||||
ucl_object_delete_internal(arena, object);
|
ucl_object_delete_internal(arena, object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement full cleanup
|
|
||||||
/* static void ucl_gc_deleteall(struct ucl_arena * arena, void *obj) { */
|
|
||||||
/* (void) arena; */
|
|
||||||
/* struct ucl_object *object = (struct ucl_object *) obj; */
|
|
||||||
/* ucl_object_delete_internal(arena, object); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
|
|
||||||
void ucl_gc(struct ucl* ucl) {
|
void ucl_gc(struct ucl* ucl) {
|
||||||
// TODO: Implement scope cleanup
|
ucl_arena_map(ucl->obj_arena, ucl_gc_unmark_all);
|
||||||
|
ucl_arena_map(ucl->obj_arena, ucl_gc_mark_pinned);
|
||||||
ucl_arena_map(ucl->obj_arena, ucl_gc_unmark);
|
|
||||||
ucl_arena_map(ucl->scope_arena, ucl_scope_mark);
|
|
||||||
ucl_arena_map(ucl->obj_arena, ucl_gc_sweep);
|
ucl_arena_map(ucl->obj_arena, ucl_gc_sweep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,12 +60,14 @@ struct ucl_scope *ucl_scope_create(struct ucl *state) {
|
|||||||
struct ucl_scope *scope = ucl_arena_get(state->scope_arena);
|
struct ucl_scope *scope = ucl_arena_get(state->scope_arena);
|
||||||
scope->list = ucl_nil_create(state);
|
scope->list = ucl_nil_create(state);
|
||||||
scope->parent = NULL;
|
scope->parent = NULL;
|
||||||
|
ucl_object_pin(scope->list);
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ucl_scope *ucl_scope_create_child(struct ucl *state, struct ucl_scope *parent) {
|
struct ucl_scope *ucl_scope_create_child(struct ucl *state, struct ucl_scope *parent) {
|
||||||
struct ucl_scope *scope = ucl_scope_create(state);
|
struct ucl_scope *scope = ucl_scope_create(state);
|
||||||
scope->parent = parent;
|
scope->parent = parent;
|
||||||
|
ucl_object_pin(scope->list);
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +80,6 @@ struct ucl_scope *ucl_scope_get_root(struct ucl_scope *scope) {
|
|||||||
|
|
||||||
void ucl_scope_delete(struct ucl *ucl, struct ucl_scope *scope) {
|
void ucl_scope_delete(struct ucl *ucl, struct ucl_scope *scope) {
|
||||||
assert(ucl->scope_arena != NULL);
|
assert(ucl->scope_arena != NULL);
|
||||||
|
ucl_object_unpin(scope->list);
|
||||||
ucl_arena_put(ucl->scope_arena, scope);
|
ucl_arena_put(ucl->scope_arena, scope);
|
||||||
// Garbage collection will handle the objects, they are shared
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user