Compare commits
2 commits
f1d54f301c
...
45a8df7443
| Author | SHA1 | Date | |
|---|---|---|---|
| 45a8df7443 | |||
| 3f9eb90187 |
1 changed files with 109 additions and 1 deletions
|
|
@ -60,7 +60,9 @@ void gc_remove_root(void **slot) {
|
|||
void gc_write_barrier(void *owner, void *value) {
|
||||
if (is_old(owner) && is_young(value)) {
|
||||
size_t idx = card_index(owner);
|
||||
gc.card_table[idx] = 1;
|
||||
if (idx < gc.card_count){
|
||||
gc.card_table[idx] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -93,6 +95,7 @@ static Obj *forward(Obj *obj) {
|
|||
if (obj->header.age >= PROMOTION_AGE) {
|
||||
Obj *p = promote(obj);
|
||||
obj->header.forwarding = p;
|
||||
scan_object_fields(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
@ -166,9 +169,13 @@ static void gc_minor_collect(void) {
|
|||
|
||||
void *gc_alloc(const TypeInfo *type, size_t payload_size) {
|
||||
size_t size = sizeof(ObjHeader) + payload_size;
|
||||
size = (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
|
||||
|
||||
if (gc.from_ptr + size > gc.from_space + gc.young_size) {
|
||||
gc_minor_collect();
|
||||
if ((gc.old_ptr - gc.old) > (gc.old_size * 7 / 10)) {
|
||||
gc_collect_old();
|
||||
}
|
||||
}
|
||||
|
||||
Obj *obj = (Obj*)gc.from_ptr;
|
||||
|
|
@ -210,6 +217,107 @@ void gc_init(void) {
|
|||
gc.root_count = 0;
|
||||
}
|
||||
|
||||
static void mark_object_fields(Obj *obj) {
|
||||
const TypeInfo *t = obj->header.type;
|
||||
for (uint16_t i = 0; i < t->field_count; i++) {
|
||||
if (t->pointer_bitmap[i]) {
|
||||
Obj *child = (Obj*)obj->fields[i];
|
||||
if (child && is_old(child)) {
|
||||
mark_obj(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_obj(Obj *obj) {
|
||||
if (!obj) return;
|
||||
if (!(obj->header.flags & MARKED)) {
|
||||
obj->header.flags |= MARKED;
|
||||
mark_object_fields(obj);
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_roots(void) {
|
||||
for (size_t i = 0; i < gc.root_count; i++) {
|
||||
Obj *obj = (Obj*)*gc.roots[i];
|
||||
if (obj && is_old(obj)) {
|
||||
mark_obj(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void compute_forwarding(void) {
|
||||
uint8_t *dest = gc.old;
|
||||
uint8_t *scan = gc.old;
|
||||
|
||||
while (scan < gc.old_ptr) {
|
||||
Obj *obj = (Obj*)scan;
|
||||
if (obj->header.flags & MARKED) {
|
||||
obj->header.forwarding = (Obj*)dest;
|
||||
dest += obj->header.size;
|
||||
}
|
||||
scan += obj->header.size;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_old_pointers(void) {
|
||||
uint8_t *scan = gc.old;
|
||||
|
||||
while (scan < gc.old_ptr) {
|
||||
Obj *obj = (Obj*)scan;
|
||||
if (obj->header.flags & MARKED) {
|
||||
const TypeInfo *t = obj->header.type;
|
||||
for (uint16_t i = 0; i < t->field_count; i++) {
|
||||
if (t->pointer_bitmap[i]) {
|
||||
Obj *child = (Obj*)obj->fields[i];
|
||||
if (child && is_old(child)) {
|
||||
obj->fields[i] = child->header.forwarding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scan += obj->header.size;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_root_pointers(void) {
|
||||
for (size_t i = 0; i < gc.root_count; i++) {
|
||||
Obj *obj = (Obj*)*gc.roots[i];
|
||||
if (obj && is_old(obj)) {
|
||||
*gc.roots[i] = obj->header.forwarding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void compact_old(void) {
|
||||
uint8_t *scan = gc.old;
|
||||
uint8_t *dest = gc.old;
|
||||
|
||||
while (scan < gc.old_ptr) {
|
||||
Obj *obj = (Obj*)scan;
|
||||
if (obj->header.flags & MARKED) {
|
||||
Obj *new_loc = obj->header.forwarding;
|
||||
memmove(new_loc, obj, obj->header.size);
|
||||
|
||||
Obj *moved = new_loc;
|
||||
moved->header.flags &= ~MARKED;
|
||||
moved->header.forwarding = NULL;
|
||||
|
||||
dest += moved->header.size;
|
||||
}
|
||||
scan += obj->header.size;
|
||||
}
|
||||
|
||||
gc.old_ptr = dest;
|
||||
}
|
||||
|
||||
void gc_collect_old(void) {
|
||||
mark_roots();
|
||||
compute_forwarding();
|
||||
update_root_pointers();
|
||||
update_old_pointers();
|
||||
compact_old();
|
||||
}
|
||||
|
||||
void gc_shutdown(void) {
|
||||
free(gc.from_space);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue