bitmap marking

This commit is contained in:
Yuichi Nishiwaki 2015-07-24 15:42:30 +09:00
parent 3b333c2b47
commit 34d93682a9
2 changed files with 71 additions and 11 deletions

View File

@ -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;

View File

@ -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