bitmap marking
This commit is contained in:
parent
3b333c2b47
commit
34d93682a9
|
@ -11,8 +11,12 @@ union header {
|
||||||
} s;
|
} s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define BITMAP_SIZE \
|
||||||
|
(PIC_HEAP_PAGE_SIZE / sizeof(union header)) / (sizeof(uint32_t) * CHAR_BIT)
|
||||||
|
|
||||||
struct heap_page {
|
struct heap_page {
|
||||||
union header *basep, *endp;
|
union header *basep, *endp;
|
||||||
|
uint32_t bitmap[BITMAP_SIZE];
|
||||||
struct heap_page *next;
|
struct heap_page *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -254,6 +258,50 @@ heap_morecore(pic_state *pic)
|
||||||
pic->heap->pages = page;
|
pic->heap->pages = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bitmap */
|
||||||
|
|
||||||
|
static struct heap_page *
|
||||||
|
obj2page(pic_state *pic, union header *h)
|
||||||
|
{
|
||||||
|
struct heap_page *page;
|
||||||
|
|
||||||
|
page = pic->heap->pages;
|
||||||
|
while (page) {
|
||||||
|
if (page->basep <= h && h < page->endp)
|
||||||
|
return page;
|
||||||
|
page = page->next;
|
||||||
|
}
|
||||||
|
PIC_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_marked(pic_state *pic, struct pic_object *obj)
|
||||||
|
{
|
||||||
|
union header *h = ((union header *)obj) - 1;
|
||||||
|
struct heap_page *page;
|
||||||
|
size_t i, unit_size = sizeof(uint32_t) * CHAR_BIT;
|
||||||
|
|
||||||
|
page = obj2page(pic, h);
|
||||||
|
|
||||||
|
i = h - page->basep;
|
||||||
|
|
||||||
|
return page->bitmap[i / unit_size] & (1 << (i % unit_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mark(pic_state *pic, struct pic_object *obj)
|
||||||
|
{
|
||||||
|
union header *h = ((union header *)obj) - 1;
|
||||||
|
struct heap_page *page;
|
||||||
|
size_t i, unit_size = sizeof(uint32_t) * CHAR_BIT;
|
||||||
|
|
||||||
|
page = obj2page(pic, h);
|
||||||
|
|
||||||
|
i = h - page->basep;
|
||||||
|
|
||||||
|
page->bitmap[i / unit_size] |= (1 << (i % unit_size));
|
||||||
|
}
|
||||||
|
|
||||||
/* MARK */
|
/* MARK */
|
||||||
|
|
||||||
static void gc_mark_object(pic_state *, union object *);
|
static void gc_mark_object(pic_state *, union object *);
|
||||||
|
@ -272,10 +320,10 @@ gc_mark_object(pic_state *pic, union object *obj)
|
||||||
{
|
{
|
||||||
loop:
|
loop:
|
||||||
|
|
||||||
if (obj->obj.gc_mark == PIC_GC_MARK)
|
if (is_marked(pic, &obj->obj))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
obj->obj.gc_mark = PIC_GC_MARK;
|
mark(pic, &obj->obj);
|
||||||
|
|
||||||
#define LOOP(o) obj = (union object *)(o); goto loop
|
#define LOOP(o) obj = (union object *)(o); goto loop
|
||||||
|
|
||||||
|
@ -528,8 +576,8 @@ gc_mark_phase(pic_state *pic)
|
||||||
continue;
|
continue;
|
||||||
key = kh_key(h, it);
|
key = kh_key(h, it);
|
||||||
val = kh_val(h, it);
|
val = kh_val(h, it);
|
||||||
if (key->gc_mark == PIC_GC_MARK) {
|
if (is_marked(pic, key)) {
|
||||||
if (pic_obj_p(val) && pic_obj_ptr(val)->gc_mark == PIC_GC_UNMARK) {
|
if (pic_obj_p(val) && ! is_marked(pic, pic_obj_ptr(val))) {
|
||||||
gc_mark(pic, val);
|
gc_mark(pic, val);
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
|
@ -624,8 +672,7 @@ gc_sweep_page(pic_state *pic, struct heap_page *page)
|
||||||
goto escape;
|
goto escape;
|
||||||
}
|
}
|
||||||
obj = (union object *)(p + 1);
|
obj = (union object *)(p + 1);
|
||||||
if (obj->obj.gc_mark == PIC_GC_MARK) {
|
if (is_marked(pic, &obj->obj)) {
|
||||||
obj->obj.gc_mark = PIC_GC_UNMARK;
|
|
||||||
alive += p->s.size;
|
alive += p->s.size;
|
||||||
} else {
|
} else {
|
||||||
if (head == NULL) {
|
if (head == NULL) {
|
||||||
|
@ -670,7 +717,7 @@ gc_sweep_phase(pic_state *pic)
|
||||||
if (! kh_exist(h, it))
|
if (! kh_exist(h, it))
|
||||||
continue;
|
continue;
|
||||||
obj = kh_key(h, it);
|
obj = kh_key(h, it);
|
||||||
if (obj->gc_mark == PIC_GC_UNMARK) {
|
if (! is_marked(pic, obj)) {
|
||||||
kh_del(reg, h, it);
|
kh_del(reg, h, it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -682,7 +729,7 @@ gc_sweep_phase(pic_state *pic)
|
||||||
if (! kh_exist(s, it))
|
if (! kh_exist(s, it))
|
||||||
continue;
|
continue;
|
||||||
sym = kh_val(s, it);
|
sym = kh_val(s, it);
|
||||||
if (sym->gc_mark == PIC_GC_UNMARK) {
|
if (! is_marked(pic, (struct pic_object *)sym)) {
|
||||||
kh_del(s, s, it);
|
kh_del(s, s, it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -699,6 +746,19 @@ gc_sweep_phase(pic_state *pic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gc_init(pic_state *pic)
|
||||||
|
{
|
||||||
|
struct heap_page *page;
|
||||||
|
|
||||||
|
page = pic->heap->pages;
|
||||||
|
while (page) {
|
||||||
|
/* clear mark bits */
|
||||||
|
memset(page->bitmap, 0, sizeof(page->bitmap));
|
||||||
|
page = page->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pic_gc_run(pic_state *pic)
|
pic_gc_run(pic_state *pic)
|
||||||
{
|
{
|
||||||
|
@ -706,6 +766,8 @@ pic_gc_run(pic_state *pic)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gc_init(pic);
|
||||||
|
|
||||||
gc_mark_phase(pic);
|
gc_mark_phase(pic);
|
||||||
gc_sweep_phase(pic);
|
gc_sweep_phase(pic);
|
||||||
}
|
}
|
||||||
|
@ -730,7 +792,6 @@ pic_obj_alloc_unsafe(pic_state *pic, size_t size, enum pic_tt tt)
|
||||||
pic_panic(pic, "GC memory exhausted");
|
pic_panic(pic, "GC memory exhausted");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
obj->gc_mark = PIC_GC_UNMARK;
|
|
||||||
obj->tt = tt;
|
obj->tt = tt;
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
|
|
@ -162,8 +162,7 @@ enum pic_tt {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PIC_OBJECT_HEADER \
|
#define PIC_OBJECT_HEADER \
|
||||||
enum pic_tt tt; \
|
enum pic_tt tt;
|
||||||
char gc_mark;
|
|
||||||
|
|
||||||
struct pic_object {
|
struct pic_object {
|
||||||
PIC_OBJECT_HEADER
|
PIC_OBJECT_HEADER
|
||||||
|
|
Loading…
Reference in New Issue