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
	
	 Yuichi Nishiwaki
						Yuichi Nishiwaki