Skip to content

Commit

Permalink
Add gc_cut
Browse files Browse the repository at this point in the history
  • Loading branch information
luboslenco committed Sep 23, 2024
1 parent af6408c commit 0bb1417
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 1 deletion.
7 changes: 7 additions & 0 deletions sources/iron_gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ void gc_root(void *ptr) {
void gc_unroot(void *ptr) {
}

void *gc_cut(void *ptr, size_t pos, size_t size) {
}

void *gc_realloc(void *ptr, size_t size) {
#ifdef HEAP_SIZE
// NOTE: gc_realloc is not implemented when HEAP_SIZE is defined
Expand Down Expand Up @@ -90,6 +93,10 @@ void gc_unroot(void *ptr) {
_gc_unroot(ptr);
}

void *gc_cut(void *ptr, size_t pos, size_t size) {
_gc_cut(ptr, pos, size);
}

void *gc_realloc(void *ptr, size_t size) {
return ptr == NULL ? gc_alloc(size) : _gc_realloc(ptr, size);
}
Expand Down
1 change: 1 addition & 0 deletions sources/iron_gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ void gc_array(void *ptr, int *length);
void gc_leaf(void *ptr);
void gc_root(void *ptr);
void gc_unroot(void *ptr);
void *gc_cut(void *ptr, size_t pos, size_t size);
void *gc_realloc(void *ptr, size_t size);
void gc_free(void *ptr);
void gc_pause();
Expand Down
48 changes: 47 additions & 1 deletion sources/libs/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#define GC_TAG_LEAF 0x1
#define GC_TAG_MARK 0x2
#define GC_TAG_ROOT 0x4
#define GC_TAG_CUT 0x8

#if defined(_MSC_VER) && !defined(__clang__)
#define __builtin_frame_address(x) ((void)(x), _AddressOfReturnAddress())
Expand All @@ -47,7 +48,8 @@ typedef struct gc_allocation {
int *array_length; // if this alloc is an array
char tag; // the tag for mark-and-sweep
char roots; // number of root users
struct gc_allocation_t *next; // separate chaining
struct gc_allocation *next; // separate chaining
struct gc_allocation *cut;
} gc_allocation_t;

typedef struct gc_allocation_map {
Expand Down Expand Up @@ -79,6 +81,7 @@ static gc_allocation_t *gc_allocation_new(void *ptr, size_t size) {
a->tag = GC_TAG_NONE;
a->roots = 0;
a->next = NULL;
a->cut = NULL;
return a;
}

Expand Down Expand Up @@ -309,6 +312,39 @@ void _gc_unroot(void *ptr) {
}
}

static inline uint64_t pad(int di, int n) {
return (n - (di % n)) % n;
}

// Cut out a leaf out of an existing allocation
void *_gc_cut(void *ptr, size_t pos, size_t size) {
size += pad(size, 8);

// Start
gc_allocation_t *start = gc_allocation_map_get(gc->allocs, ptr);
while (start->cut) {
start = start->cut;
}
size_t start_size = start->size;
pos -= start->ptr - ptr;
start->size = pos;

// Middle
gc_allocation_t *middle = gc_allocation_new(start->ptr + pos, size);
middle->tag |= GC_TAG_CUT;
middle->tag |= GC_TAG_LEAF;
start->cut = middle;
gc_allocation_map_put(gc->allocs, middle);

// End
gc_allocation_t *end = gc_allocation_new(start->ptr + pos + size, start_size - size - pos);
end->tag |= GC_TAG_CUT;
middle->cut = end;
gc_allocation_map_put(gc->allocs, end);

return middle->ptr;
}

static void gc_mark_alloc(void *ptr) {
gc_allocation_t *alloc = gc_allocation_map_get(gc->allocs, ptr);
/* Mark if alloc exists and is not tagged already, otherwise skip */
Expand All @@ -317,6 +353,7 @@ static void gc_mark_alloc(void *ptr) {
if (!(alloc->tag & GC_TAG_LEAF)) { // Skip contents
/* Iterate over allocation contents and mark them as well */
int size = alloc->array_length ? (*alloc->array_length) * PTRSIZE : alloc->size;

for (char *p = (char *)alloc->ptr; p <= (char *)alloc->ptr + size - PTRSIZE; ++p) {
gc_mark_alloc(*(void **)p);
}
Expand Down Expand Up @@ -370,13 +407,22 @@ static size_t gc_sweep() {
chunk->tag &= ~GC_TAG_MARK;
chunk = chunk->next;
}
else if (chunk->tag & GC_TAG_CUT) {
chunk = chunk->next;
}
else {
/* no reference to this chunk, hence delete it */
total += chunk->size;
free(chunk->ptr);
/* and remove it from the bookkeeping */
next = chunk->next;
gc_allocation_t *cut = chunk->cut;
gc_allocation_map_remove(gc->allocs, chunk->ptr, false);
while (cut) {
gc_allocation_t *next = cut->cut;
gc_allocation_map_remove(gc->allocs, cut->ptr, false);
cut = next;
}
chunk = next;
}
}
Expand Down
1 change: 1 addition & 0 deletions sources/libs/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ void _gc_array(void *ptr, int *length);
void _gc_leaf(void *ptr);
void _gc_root(void *ptr);
void _gc_unroot(void *ptr);
void *_gc_cut(void *ptr, size_t pos, size_t size);
void *_gc_realloc(void *ptr, size_t size);
void _gc_free(void *ptr);

0 comments on commit 0bb1417

Please sign in to comment.