From 5d7138e7d316edf4ce5ec6d7d4bbde5c79d4743d Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sun, 19 Jun 2016 20:53:46 +0900 Subject: [PATCH] remove duplicate definitions --- extlib/benz/gc.c | 466 ++++++++++++++++++++++++++++++++ extlib/benz/gc/bitmap.c | 492 ++-------------------------------- extlib/benz/gc/markandsweep.c | 454 +------------------------------ 3 files changed, 491 insertions(+), 921 deletions(-) diff --git a/extlib/benz/gc.c b/extlib/benz/gc.c index b19e21e1..56d504a4 100644 --- a/extlib/benz/gc.c +++ b/extlib/benz/gc.c @@ -1,7 +1,473 @@ +/** + * See Copyright Notice in picrin.h + */ + #include "picrin.h" +#include "picrin/private/object.h" +#include "picrin/private/state.h" + +union header { + struct { + union header *ptr; + size_t size; + } s; +}; + +struct object { + union { + struct basic basic; + struct identifier id; + struct string str; + struct blob blob; + struct pair pair; + struct vector vec; + struct dict dict; + struct weak weak; + struct data data; + struct record rec; + struct env env; + struct proc proc; + struct context cxt; + struct port port; + struct error err; + struct checkpoint cp; + } u; +}; + +struct heap { + union header base, *freep; /* unused if PIC_USE_BITMAP */ + struct heap_page *pages; + struct weak *weaks; /* weak map chain */ +}; + +#if PIC_USE_LIBC +void * +pic_default_allocf(void *PIC_UNUSED(userdata), void *ptr, size_t size) +{ + if (size != 0) { + return realloc(ptr, size); + } + free(ptr); + return NULL; +} +#endif + +void * +pic_malloc(pic_state *pic, size_t size) +{ + void *ptr; + + ptr = pic->allocf(pic->userdata, NULL, size); + if (ptr == NULL && size > 0) { + pic_panic(pic, "memory exhausted"); + } + return ptr; +} + +void * +pic_realloc(pic_state *pic, void *ptr, size_t size) +{ + ptr = pic->allocf(pic->userdata, ptr, size); + if (ptr == NULL && size > 0) { + pic_panic(pic, "memory exhausted"); + } + return ptr; +} + +void * +pic_calloc(pic_state *pic, size_t count, size_t size) +{ + void *ptr; + + size *= count; + ptr = pic->allocf(pic->userdata, NULL, size); + if (ptr == NULL && size > 0) { + pic_panic(pic, "memory exhausted"); + } + memset(ptr, 0, size); + return ptr; +} + +void +pic_free(pic_state *pic, void *ptr) +{ + pic->allocf(pic->userdata, ptr, 0); +} + +static void +gc_protect(pic_state *pic, struct object *obj) +{ + if (pic->arena_idx >= pic->arena_size) { + pic->arena_size = pic->arena_size * 2 + 1; + pic->arena = pic_realloc(pic, pic->arena, sizeof(struct object *) * pic->arena_size); + } + pic->arena[pic->arena_idx++] = obj; +} + +pic_value +pic_protect(pic_state *pic, pic_value v) +{ + if (! pic_obj_p(pic, v)) + return v; + + gc_protect(pic, pic_obj_ptr(v)); + + return v; +} + +size_t +pic_enter(pic_state *pic) +{ + return pic->arena_idx; +} + +void +pic_leave(pic_state *pic, size_t state) +{ + pic->arena_idx = state; +} + +void * +pic_alloca(pic_state *pic, size_t n) +{ + static const pic_data_type t = { "pic_alloca", pic_free, 0 }; + + return pic_data(pic, pic_data_value(pic, pic_malloc(pic, n), &t)); /* TODO optimize */ +} + +static bool is_marked(pic_state *pic, struct object *obj); +static void mark(pic_state *pic, struct object *obj); + +/* MARK */ + +static void gc_mark_object(pic_state *, struct object *); + +static void +gc_mark(pic_state *pic, pic_value v) +{ + if (! pic_obj_p(pic, v)) + return; + + gc_mark_object(pic, pic_obj_ptr(v)); +} + +static void +gc_mark_object(pic_state *pic, struct object *obj) +{ + loop: + + if (is_marked(pic, obj)) + return; + + mark(pic, obj); + +#define LOOP(o) obj = (struct object *)(o); goto loop + + switch (obj->u.basic.tt) { + case PIC_TYPE_PAIR: { + gc_mark(pic, obj->u.pair.car); + if (pic_obj_p(pic, obj->u.pair.cdr)) { + LOOP(pic_obj_ptr(obj->u.pair.cdr)); + } + break; + } + case PIC_TYPE_CXT: { + int i; + + for (i = 0; i < obj->u.cxt.regc; ++i) { + gc_mark(pic, obj->u.cxt.regs[i]); + } + if (obj->u.cxt.up) { + LOOP(obj->u.cxt.up); + } + break; + } + case PIC_TYPE_FUNC: { + int i; + for (i = 0; i < obj->u.proc.u.f.localc; ++i) { + gc_mark(pic, obj->u.proc.locals[i]); + } + break; + } + case PIC_TYPE_IREP: { + if (obj->u.proc.u.i.cxt) { + LOOP(obj->u.proc.u.i.cxt); + } + break; + } + case PIC_TYPE_PORT: { + break; + } + case PIC_TYPE_ERROR: { + gc_mark_object(pic, (struct object *)obj->u.err.type); + gc_mark_object(pic, (struct object *)obj->u.err.msg); + gc_mark(pic, obj->u.err.irrs); + LOOP(obj->u.err.stack); + break; + } + case PIC_TYPE_STRING: { + break; + } + case PIC_TYPE_VECTOR: { + int i; + for (i = 0; i < obj->u.vec.len; ++i) { + gc_mark(pic, obj->u.vec.data[i]); + } + break; + } + case PIC_TYPE_BLOB: { + break; + } + case PIC_TYPE_ID: { + gc_mark_object(pic, (struct object *)obj->u.id.u.id); + LOOP(obj->u.id.env); + break; + } + case PIC_TYPE_ENV: { + khash_t(env) *h = &obj->u.env.map; + int it; + + for (it = kh_begin(h); it != kh_end(h); ++it) { + if (kh_exist(h, it)) { + gc_mark_object(pic, (struct object *)kh_key(h, it)); + gc_mark_object(pic, (struct object *)kh_val(h, it)); + } + } + if (obj->u.env.up) { + LOOP(obj->u.env.up); + } + break; + } + case PIC_TYPE_DATA: { + if (obj->u.data.type->mark) { + obj->u.data.type->mark(pic, obj->u.data.data, gc_mark); + } + break; + } + case PIC_TYPE_DICT: { + pic_value key, val; + int it = 0; + + while (pic_dict_next(pic, pic_obj_value(&obj->u.dict), &it, &key, &val)) { + gc_mark(pic, key); + gc_mark(pic, val); + } + break; + } + case PIC_TYPE_RECORD: { + gc_mark(pic, obj->u.rec.type); + if (pic_obj_p(pic, obj->u.rec.datum)) { + LOOP(pic_obj_ptr(obj->u.rec.datum)); + } + break; + } + case PIC_TYPE_SYMBOL: { + LOOP(obj->u.id.u.str); + break; + } + case PIC_TYPE_WEAK: { + struct weak *weak = (struct weak *)obj; + + weak->prev = pic->heap->weaks; + pic->heap->weaks = weak; + break; + } + case PIC_TYPE_CP: { + if (obj->u.cp.prev) { + gc_mark_object(pic, (struct object *)obj->u.cp.prev); + } + if (obj->u.cp.in) { + gc_mark_object(pic, (struct object *)obj->u.cp.in); + } + if (obj->u.cp.out) { + LOOP((struct object *)obj->u.cp.out); + } + break; + } + default: + PIC_UNREACHABLE(); + } +} + +static void +gc_mark_phase(pic_state *pic) +{ + pic_value *stack; + struct callinfo *ci; + struct list_head *list; + int it; + size_t j; + + assert(pic->heap->weaks == NULL); + + /* checkpoint */ + if (pic->cp) { + gc_mark_object(pic, (struct object *)pic->cp); + } + + /* stack */ + for (stack = pic->stbase; stack != pic->sp; ++stack) { + gc_mark(pic, *stack); + } + + /* callinfo */ + for (ci = pic->ci; ci != pic->cibase; --ci) { + if (ci->cxt) { + gc_mark_object(pic, (struct object *)ci->cxt); + } + } + + /* arena */ + for (j = 0; j < pic->arena_idx; ++j) { + gc_mark_object(pic, (struct object *)pic->arena[j]); + } + + /* ireps */ + for (list = pic->ireps.next; list != &pic->ireps; list = list->next) { + struct irep *irep = (struct irep *)list; + for (j = 0; j < irep->npool; ++j) { + gc_mark_object(pic, irep->pool[j]); + } + } + + /* global variables */ + gc_mark(pic, pic->globals); + + /* macro objects */ + gc_mark(pic, pic->macros); + + /* error object */ + gc_mark(pic, pic->err); + + /* features */ + gc_mark(pic, pic->features); + + /* library table */ + for (it = kh_begin(&pic->ltable); it != kh_end(&pic->ltable); ++it) { + if (! kh_exist(&pic->ltable, it)) { + continue; + } + gc_mark_object(pic, (struct object *)kh_val(&pic->ltable, it).name); + gc_mark_object(pic, (struct object *)kh_val(&pic->ltable, it).env); + gc_mark_object(pic, (struct object *)kh_val(&pic->ltable, it).exports); + } + + /* weak maps */ + do { + struct object *key; + pic_value val; + int it; + khash_t(weak) *h; + struct weak *weak; + + j = 0; + weak = pic->heap->weaks; + + while (weak != NULL) { + h = &weak->hash; + for (it = kh_begin(h); it != kh_end(h); ++it) { + if (! kh_exist(h, it)) + continue; + key = kh_key(h, it); + val = kh_val(h, it); + if (is_marked(pic, key)) { + if (pic_obj_p(pic, val) && ! is_marked(pic, pic_obj_ptr(val))) { + gc_mark(pic, val); + ++j; + } + } + } + weak = weak->prev; + } + } while (j > 0); +} + +/* SWEEP */ + +static void +gc_finalize_object(pic_state *pic, struct object *obj) +{ + switch (obj->u.basic.tt) { + case PIC_TYPE_VECTOR: { + pic_free(pic, obj->u.vec.data); + break; + } + case PIC_TYPE_BLOB: { + pic_free(pic, obj->u.blob.data); + break; + } + case PIC_TYPE_STRING: { + pic_rope_decref(pic, obj->u.str.rope); + break; + } + case PIC_TYPE_ENV: { + kh_destroy(env, &obj->u.env.map); + break; + } + case PIC_TYPE_DATA: { + if (obj->u.data.type->dtor) { + obj->u.data.type->dtor(pic, obj->u.data.data); + } + break; + } + case PIC_TYPE_DICT: { + kh_destroy(dict, &obj->u.dict.hash); + break; + } + case PIC_TYPE_SYMBOL: { + /* TODO: remove this symbol's entry from pic->syms immediately */ + break; + } + case PIC_TYPE_WEAK: { + kh_destroy(weak, &obj->u.weak.hash); + break; + } + case PIC_TYPE_IREP: { + pic_irep_decref(pic, obj->u.proc.u.i.irep); + break; + } + + case PIC_TYPE_PAIR: + case PIC_TYPE_CXT: + case PIC_TYPE_PORT: + case PIC_TYPE_ERROR: + case PIC_TYPE_ID: + case PIC_TYPE_RECORD: + case PIC_TYPE_CP: + case PIC_TYPE_FUNC: + break; + + default: + PIC_UNREACHABLE(); + } +} #ifdef PIC_USE_BITMAPGC # include "./gc/bitmap.c" #else # include "./gc/markandsweep.c" #endif + +void +pic_gc(pic_state *pic) +{ + if (! pic->gc_enable) { + return; + } + + gc_init(pic); + + gc_mark_phase(pic); + gc_sweep_phase(pic); +} + +struct object * +pic_obj_alloc(pic_state *pic, size_t size, int type) +{ + struct object *obj; + + obj = pic_obj_alloc_unsafe(pic, size, type); + + gc_protect(pic, obj); + return obj; +} diff --git a/extlib/benz/gc/bitmap.c b/extlib/benz/gc/bitmap.c index ac387296..f43d6fe3 100644 --- a/extlib/benz/gc/bitmap.c +++ b/extlib/benz/gc/bitmap.c @@ -4,22 +4,12 @@ #include "picrin.h" #include "picrin/private/object.h" -#include "picrin/private/khash.h" #include "picrin/private/state.h" -union header { - struct { - union header *ptr; - size_t size; - } s; -}; - #define UNIT_SIZE (sizeof(uint32_t) * CHAR_BIT) -#define BITMAP_SIZE \ - (PIC_HEAP_PAGE_SIZE / sizeof(union header) / UNIT_SIZE) +#define BITMAP_SIZE (PIC_HEAP_PAGE_SIZE / sizeof(union header) / UNIT_SIZE) #define HEADER_SIZE ((PIC_HEAP_PAGE_SIZE - sizeof(struct heap_page)) / sizeof(union header)) - struct heap_page { struct heap_page *next; size_t current; @@ -28,32 +18,6 @@ struct heap_page { uint32_t index[BITMAP_SIZE / UNIT_SIZE]; }; -struct object { - union { - struct basic basic; - struct identifier id; - struct string str; - struct blob blob; - struct pair pair; - struct vector vec; - struct dict dict; - struct weak weak; - struct data data; - struct record rec; - struct env env; - struct proc proc; - struct context cxt; - struct port port; - struct error err; - struct checkpoint cp; - } u; -}; - -struct heap { - struct heap_page *pages; - struct weak *weaks; /* weak map chain */ -}; - struct heap * pic_heap_open(pic_state *pic) { @@ -80,93 +44,6 @@ pic_heap_close(pic_state *pic, struct heap *heap) pic_free(pic, heap); } -#if PIC_USE_LIBC -void * -pic_default_allocf(void *PIC_UNUSED(userdata), void *ptr, size_t size) -{ - if (size != 0) { - return realloc(ptr, size); - } - free(ptr); - return NULL; -} -#endif - -void * -pic_malloc(pic_state *pic, size_t size) -{ - void *ptr; - - ptr = pic->allocf(pic->userdata, NULL, size); - if (ptr == NULL && size > 0) { - pic_panic(pic, "memory exhausted"); - } - return ptr; -} - -void * -pic_realloc(pic_state *pic, void *ptr, size_t size) -{ - ptr = pic->allocf(pic->userdata, ptr, size); - if (ptr == NULL && size > 0) { - pic_panic(pic, "memory exhausted"); - } - return ptr; -} - -void * -pic_calloc(pic_state *pic, size_t count, size_t size) -{ - void *ptr; - - size *= count; - ptr = pic->allocf(pic->userdata, NULL, size); - if (ptr == NULL && size > 0) { - pic_panic(pic, "memory exhausted"); - } - memset(ptr, 0, size); - return ptr; -} - -void -pic_free(pic_state *pic, void *ptr) -{ - pic->allocf(pic->userdata, ptr, 0); -} - -static void -gc_protect(pic_state *pic, struct object *obj) -{ - if (pic->arena_idx >= pic->arena_size) { - pic->arena_size = pic->arena_size * 2 + 1; - pic->arena = pic_realloc(pic, pic->arena, sizeof(struct object *) * pic->arena_size); - } - pic->arena[pic->arena_idx++] = obj; -} - -pic_value -pic_protect(pic_state *pic, pic_value v) -{ - if (! pic_obj_p(pic, v)) - return v; - - gc_protect(pic, pic_obj_ptr(v)); - - return v; -} - -size_t -pic_enter(pic_state *pic) -{ - return pic->arena_idx; -} - -void -pic_leave(pic_state *pic, size_t state) -{ - pic->arena_idx = state; -} - /* bitmap */ static union header * @@ -183,7 +60,6 @@ obj2page(pic_state *PIC_UNUSED(pic), union header *h) return (struct heap_page *)(((unsigned long int) h) & mask); } - static int numofbits(unsigned long bits) { @@ -195,11 +71,9 @@ numofbits(unsigned long bits) return bits >> 24; } - static void mark_at(struct heap_page *page, size_t index, size_t size) { - size_t mask = ~(-1 << size); size_t mark_size; while (0 < size) { @@ -234,7 +108,6 @@ is_marked_at(uint32_t *bitmap, size_t index, size_t size) } - static void * heap_alloc_heap_page(struct heap_page *page, size_t nunits) { @@ -282,7 +155,6 @@ heap_alloc(pic_state *pic, size_t size) return NULL; } - static void heap_morecore(pic_state *pic) { @@ -330,308 +202,25 @@ mark(pic_state *pic, struct object *obj) mark_at(page, i, h->s.size + 1); } -/* MARK */ - -static void gc_mark_object(pic_state *, struct object *); - -static void -gc_mark(pic_state *pic, pic_value v) +static size_t +gc_sweep_page(pic_state *pic, struct heap_page *page) { - if (! pic_obj_p(pic, v)) - return; + size_t index, i, inuse = 0; + union header *h; - gc_mark_object(pic, pic_obj_ptr(v)); -} - -static void -gc_mark_object(pic_state *pic, struct object *obj) -{ - loop: - - if (is_marked(pic, obj)) - return; - - mark(pic, obj); - -#define LOOP(o) obj = (struct object *)(o); goto loop - - switch (obj->u.basic.tt) { - case PIC_TYPE_PAIR: { - gc_mark(pic, obj->u.pair.car); - if (pic_obj_p(pic, obj->u.pair.cdr)) { - LOOP(pic_obj_ptr(obj->u.pair.cdr)); - } - break; - } - case PIC_TYPE_CXT: { - int i; - - for (i = 0; i < obj->u.cxt.regc; ++i) { - gc_mark(pic, obj->u.cxt.regs[i]); - } - if (obj->u.cxt.up) { - LOOP(obj->u.cxt.up); - } - break; - } - case PIC_TYPE_FUNC: { - int i; - for (i = 0; i < obj->u.proc.u.f.localc; ++i) { - gc_mark(pic, obj->u.proc.locals[i]); - } - break; - } - case PIC_TYPE_IREP: { - if (obj->u.proc.u.i.cxt) { - LOOP(obj->u.proc.u.i.cxt); - } - break; - } - case PIC_TYPE_PORT: { - break; - } - case PIC_TYPE_ERROR: { - gc_mark_object(pic, (struct object *)obj->u.err.type); - gc_mark_object(pic, (struct object *)obj->u.err.msg); - gc_mark(pic, obj->u.err.irrs); - LOOP(obj->u.err.stack); - break; - } - case PIC_TYPE_STRING: { - break; - } - case PIC_TYPE_VECTOR: { - int i; - for (i = 0; i < obj->u.vec.len; ++i) { - gc_mark(pic, obj->u.vec.data[i]); - } - break; - } - case PIC_TYPE_BLOB: { - break; - } - case PIC_TYPE_ID: { - gc_mark_object(pic, (struct object *)obj->u.id.u.id); - LOOP(obj->u.id.env); - break; - } - case PIC_TYPE_ENV: { - khash_t(env) *h = &obj->u.env.map; - int it; - - for (it = kh_begin(h); it != kh_end(h); ++it) { - if (kh_exist(h, it)) { - gc_mark_object(pic, (struct object *)kh_key(h, it)); - gc_mark_object(pic, (struct object *)kh_val(h, it)); - } - } - if (obj->u.env.up) { - LOOP(obj->u.env.up); - } - break; - } - case PIC_TYPE_DATA: { - if (obj->u.data.type->mark) { - obj->u.data.type->mark(pic, obj->u.data.data, gc_mark); - } - break; - } - case PIC_TYPE_DICT: { - pic_value key, val; - int it = 0; - - while (pic_dict_next(pic, pic_obj_value(&obj->u.dict), &it, &key, &val)) { - gc_mark(pic, key); - gc_mark(pic, val); - } - break; - } - case PIC_TYPE_RECORD: { - gc_mark(pic, obj->u.rec.type); - if (pic_obj_p(pic, obj->u.rec.datum)) { - LOOP(pic_obj_ptr(obj->u.rec.datum)); - } - break; - } - case PIC_TYPE_SYMBOL: { - LOOP(obj->u.id.u.str); - break; - } - case PIC_TYPE_WEAK: { - struct weak *weak = (struct weak *)obj; - - weak->prev = pic->heap->weaks; - pic->heap->weaks = weak; - break; - } - case PIC_TYPE_CP: { - if (obj->u.cp.prev) { - gc_mark_object(pic, (struct object *)obj->u.cp.prev); - } - if (obj->u.cp.in) { - gc_mark_object(pic, (struct object *)obj->u.cp.in); - } - if (obj->u.cp.out) { - LOOP((struct object *)obj->u.cp.out); - } - break; - } - default: - PIC_UNREACHABLE(); - } -} - -static void -gc_mark_phase(pic_state *pic) -{ - pic_value *stack; - struct callinfo *ci; - struct list_head *list; - int it; - size_t j; - - assert(pic->heap->weaks == NULL); - - /* checkpoint */ - if (pic->cp) { - gc_mark_object(pic, (struct object *)pic->cp); + for (i = 0; i < BITMAP_SIZE; ++i) { + page->shadow[i] &= ~page->bitmap[i]; + inuse += numofbits(page->bitmap[i]); } - /* stack */ - for (stack = pic->stbase; stack != pic->sp; ++stack) { - gc_mark(pic, *stack); - } - - /* callinfo */ - for (ci = pic->ci; ci != pic->cibase; --ci) { - if (ci->cxt) { - gc_mark_object(pic, (struct object *)ci->cxt); + for (index = 0; index < HEADER_SIZE; ++index) { + if (page->shadow[index / UNIT_SIZE] & (1 << (index % UNIT_SIZE))) { + h = index2header(page, index); + index += h->s.size; + gc_finalize_object(pic, (struct object *) (h + 1)); } } - - /* arena */ - for (j = 0; j < pic->arena_idx; ++j) { - gc_mark_object(pic, (struct object *)pic->arena[j]); - } - - /* ireps */ - for (list = pic->ireps.next; list != &pic->ireps; list = list->next) { - struct irep *irep = (struct irep *)list; - for (j = 0; j < irep->npool; ++j) { - gc_mark_object(pic, irep->pool[j]); - } - } - - /* global variables */ - gc_mark(pic, pic->globals); - - /* macro objects */ - gc_mark(pic, pic->macros); - - /* error object */ - gc_mark(pic, pic->err); - - /* features */ - gc_mark(pic, pic->features); - - /* library table */ - for (it = kh_begin(&pic->ltable); it != kh_end(&pic->ltable); ++it) { - if (! kh_exist(&pic->ltable, it)) { - continue; - } - gc_mark_object(pic, (struct object *)kh_val(&pic->ltable, it).name); - gc_mark_object(pic, (struct object *)kh_val(&pic->ltable, it).env); - gc_mark_object(pic, (struct object *)kh_val(&pic->ltable, it).exports); - } - - /* weak maps */ - do { - struct object *key; - pic_value val; - int it; - khash_t(weak) *h; - struct weak *weak; - - j = 0; - weak = pic->heap->weaks; - - while (weak != NULL) { - h = &weak->hash; - for (it = kh_begin(h); it != kh_end(h); ++it) { - if (! kh_exist(h, it)) - continue; - key = kh_key(h, it); - val = kh_val(h, it); - if (is_marked(pic, key)) { - if (pic_obj_p(pic, val) && ! is_marked(pic, pic_obj_ptr(val))) { - gc_mark(pic, val); - ++j; - } - } - } - weak = weak->prev; - } - } while (j > 0); -} - -/* SWEEP */ - -static void -gc_finalize_object(pic_state *pic, struct object *obj) -{ - switch (obj->u.basic.tt) { - case PIC_TYPE_VECTOR: { - pic_free(pic, obj->u.vec.data); - break; - } - case PIC_TYPE_BLOB: { - pic_free(pic, obj->u.blob.data); - break; - } - case PIC_TYPE_STRING: { - pic_rope_decref(pic, obj->u.str.rope); - break; - } - case PIC_TYPE_ENV: { - kh_destroy(env, &obj->u.env.map); - break; - } - case PIC_TYPE_DATA: { - if (obj->u.data.type->dtor) { - obj->u.data.type->dtor(pic, obj->u.data.data); - } - break; - } - case PIC_TYPE_DICT: { - kh_destroy(dict, &obj->u.dict.hash); - break; - } - case PIC_TYPE_SYMBOL: { - /* TODO: remove this symbol's entry from pic->syms immediately */ - break; - } - case PIC_TYPE_WEAK: { - kh_destroy(weak, &obj->u.weak.hash); - break; - } - case PIC_TYPE_IREP: { - pic_irep_decref(pic, obj->u.proc.u.i.irep); - break; - } - - case PIC_TYPE_PAIR: - case PIC_TYPE_CXT: - case PIC_TYPE_PORT: - case PIC_TYPE_ERROR: - case PIC_TYPE_ID: - case PIC_TYPE_RECORD: - case PIC_TYPE_CP: - case PIC_TYPE_FUNC: - break; - - default: - PIC_UNREACHABLE(); - } + return inuse; } static void @@ -664,29 +253,15 @@ gc_sweep_phase(pic_state *pic) if (! kh_exist(s, it)) continue; sym = kh_val(s, it); - if (! is_marked(pic, (struct object *)sym)) { + if (sym && ! is_marked(pic, (struct object *)sym)) { kh_del(oblist, s, it); } } page = pic->heap->pages; - while(page) { - size_t index, i; - union header *h; - + while (page) { + inuse += gc_sweep_page(pic, page); total += HEADER_SIZE; - for (i = 0; i < BITMAP_SIZE; ++i) { - page->shadow[i] &= ~page->bitmap[i]; - inuse += numofbits(page->bitmap[i]); - } - - for (index = 0; index < HEADER_SIZE; ++index) { - if (page->shadow[index / UNIT_SIZE] & (1 << (index % UNIT_SIZE))) { - h = index2header(page, index); - index += h->s.size; - gc_finalize_object(pic, (struct object *) (h + 1)); - } - } page = page->next; } @@ -711,28 +286,6 @@ gc_init(pic_state *pic) } } -void -pic_gc(pic_state *pic) -{ - if (! pic->gc_enable) { - return; - } - - gc_init(pic); - - gc_mark_phase(pic); - gc_sweep_phase(pic); -} - -void * -pic_alloca(pic_state *pic, size_t n) -{ - static const pic_data_type t = { "pic_alloca", pic_free, 0 }; - - /* TODO: optimize */ - return pic_data(pic, pic_data_value(pic, pic_malloc(pic, n), &t)); -} - struct object * pic_obj_alloc_unsafe(pic_state *pic, size_t size, int type) { @@ -757,14 +310,3 @@ pic_obj_alloc_unsafe(pic_state *pic, size_t size, int type) return obj; } - -struct object * -pic_obj_alloc(pic_state *pic, size_t size, int type) -{ - struct object *obj; - - obj = pic_obj_alloc_unsafe(pic, size, type); - - gc_protect(pic, obj); - return obj; -} diff --git a/extlib/benz/gc/markandsweep.c b/extlib/benz/gc/markandsweep.c index 0f0bc6f2..fbcfc904 100644 --- a/extlib/benz/gc/markandsweep.c +++ b/extlib/benz/gc/markandsweep.c @@ -11,45 +11,11 @@ enum { BLACK = 1 }; -union header { - struct { - union header *ptr; - size_t size; - } s; -}; - struct heap_page { union header *basep, *endp; struct heap_page *next; }; -struct object { - union { - struct basic basic; - struct identifier id; - struct string str; - struct blob blob; - struct pair pair; - struct vector vec; - struct dict dict; - struct weak weak; - struct data data; - struct record rec; - struct env env; - struct proc proc; - struct context cxt; - struct port port; - struct error err; - struct checkpoint cp; - } u; -}; - -struct heap { - union header base, *freep; - struct heap_page *pages; - struct weak *weaks; /* weak map chain */ -}; - struct heap * pic_heap_open(pic_state *pic) { @@ -82,93 +48,6 @@ pic_heap_close(pic_state *pic, struct heap *heap) pic_free(pic, heap); } -#if PIC_USE_LIBC -void * -pic_default_allocf(void *PIC_UNUSED(userdata), void *ptr, size_t size) -{ - if (size != 0) { - return realloc(ptr, size); - } - free(ptr); - return NULL; -} -#endif - -void * -pic_malloc(pic_state *pic, size_t size) -{ - void *ptr; - - ptr = pic->allocf(pic->userdata, NULL, size); - if (ptr == NULL && size > 0) { - pic_panic(pic, "memory exhausted"); - } - return ptr; -} - -void * -pic_realloc(pic_state *pic, void *ptr, size_t size) -{ - ptr = pic->allocf(pic->userdata, ptr, size); - if (ptr == NULL && size > 0) { - pic_panic(pic, "memory exhausted"); - } - return ptr; -} - -void * -pic_calloc(pic_state *pic, size_t count, size_t size) -{ - void *ptr; - - size *= count; - ptr = pic->allocf(pic->userdata, NULL, size); - if (ptr == NULL && size > 0) { - pic_panic(pic, "memory exhausted"); - } - memset(ptr, 0, size); - return ptr; -} - -void -pic_free(pic_state *pic, void *ptr) -{ - pic->allocf(pic->userdata, ptr, 0); -} - -static void -gc_protect(pic_state *pic, struct object *obj) -{ - if (pic->arena_idx >= pic->arena_size) { - pic->arena_size = pic->arena_size * 2 + 1; - pic->arena = pic_realloc(pic, pic->arena, sizeof(struct object *) * pic->arena_size); - } - pic->arena[pic->arena_idx++] = obj; -} - -pic_value -pic_protect(pic_state *pic, pic_value v) -{ - if (! pic_obj_p(pic, v)) - return v; - - gc_protect(pic, pic_obj_ptr(v)); - - return v; -} - -size_t -pic_enter(pic_state *pic) -{ - return pic->arena_idx; -} - -void -pic_leave(pic_state *pic, size_t state) -{ - pic->arena_idx = state; -} - static void * heap_alloc(pic_state *pic, size_t size) { @@ -257,308 +136,16 @@ heap_morecore(pic_state *pic) pic->heap->pages = page; } -/* MARK */ - -static void gc_mark_object(pic_state *, struct object *); - -static void -gc_mark(pic_state *pic, pic_value v) +static bool +is_marked(pic_state *PIC_UNUSED(pic), struct object *obj) { - if (! pic_obj_p(pic, v)) - return; - - gc_mark_object(pic, pic_obj_ptr(v)); + return obj->u.basic.gc_mark == BLACK; } static void -gc_mark_object(pic_state *pic, struct object *obj) +mark(pic_state *PIC_UNUSED(pic), struct object *obj) { - loop: - - if (obj->u.basic.gc_mark == BLACK) - return; - obj->u.basic.gc_mark = BLACK; - -#define LOOP(o) obj = (struct object *)(o); goto loop - - switch (obj->u.basic.tt) { - case PIC_TYPE_PAIR: { - gc_mark(pic, obj->u.pair.car); - if (pic_obj_p(pic, obj->u.pair.cdr)) { - LOOP(pic_obj_ptr(obj->u.pair.cdr)); - } - break; - } - case PIC_TYPE_CXT: { - int i; - - for (i = 0; i < obj->u.cxt.regc; ++i) { - gc_mark(pic, obj->u.cxt.regs[i]); - } - if (obj->u.cxt.up) { - LOOP(obj->u.cxt.up); - } - break; - } - case PIC_TYPE_FUNC: { - int i; - for (i = 0; i < obj->u.proc.u.f.localc; ++i) { - gc_mark(pic, obj->u.proc.locals[i]); - } - break; - } - case PIC_TYPE_IREP: { - if (obj->u.proc.u.i.cxt) { - LOOP(obj->u.proc.u.i.cxt); - } - break; - } - case PIC_TYPE_PORT: { - break; - } - case PIC_TYPE_ERROR: { - gc_mark_object(pic, (struct object *)obj->u.err.type); - gc_mark_object(pic, (struct object *)obj->u.err.msg); - gc_mark(pic, obj->u.err.irrs); - LOOP(obj->u.err.stack); - break; - } - case PIC_TYPE_STRING: { - break; - } - case PIC_TYPE_VECTOR: { - int i; - for (i = 0; i < obj->u.vec.len; ++i) { - gc_mark(pic, obj->u.vec.data[i]); - } - break; - } - case PIC_TYPE_BLOB: { - break; - } - case PIC_TYPE_ID: { - gc_mark_object(pic, (struct object *)obj->u.id.u.id); - LOOP(obj->u.id.env); - break; - } - case PIC_TYPE_ENV: { - khash_t(env) *h = &obj->u.env.map; - int it; - - for (it = kh_begin(h); it != kh_end(h); ++it) { - if (kh_exist(h, it)) { - gc_mark_object(pic, (struct object *)kh_key(h, it)); - gc_mark_object(pic, (struct object *)kh_val(h, it)); - } - } - if (obj->u.env.up) { - LOOP(obj->u.env.up); - } - break; - } - case PIC_TYPE_DATA: { - if (obj->u.data.type->mark) { - obj->u.data.type->mark(pic, obj->u.data.data, gc_mark); - } - break; - } - case PIC_TYPE_DICT: { - pic_value key, val; - int it = 0; - - while (pic_dict_next(pic, pic_obj_value(&obj->u.dict), &it, &key, &val)) { - gc_mark(pic, key); - gc_mark(pic, val); - } - break; - } - case PIC_TYPE_RECORD: { - gc_mark(pic, obj->u.rec.type); - if (pic_obj_p(pic, obj->u.rec.datum)) { - LOOP(pic_obj_ptr(obj->u.rec.datum)); - } - break; - } - case PIC_TYPE_SYMBOL: { - LOOP(obj->u.id.u.str); - break; - } - case PIC_TYPE_WEAK: { - struct weak *weak = (struct weak *)obj; - - weak->prev = pic->heap->weaks; - pic->heap->weaks = weak; - break; - } - case PIC_TYPE_CP: { - if (obj->u.cp.prev) { - gc_mark_object(pic, (struct object *)obj->u.cp.prev); - } - if (obj->u.cp.in) { - gc_mark_object(pic, (struct object *)obj->u.cp.in); - } - if (obj->u.cp.out) { - LOOP((struct object *)obj->u.cp.out); - } - break; - } - default: - PIC_UNREACHABLE(); - } -} - -static void -gc_mark_phase(pic_state *pic) -{ - pic_value *stack; - struct callinfo *ci; - struct list_head *list; - int it; - size_t j; - - assert(pic->heap->weaks == NULL); - - /* checkpoint */ - if (pic->cp) { - gc_mark_object(pic, (struct object *)pic->cp); - } - - /* stack */ - for (stack = pic->stbase; stack != pic->sp; ++stack) { - gc_mark(pic, *stack); - } - - /* callinfo */ - for (ci = pic->ci; ci != pic->cibase; --ci) { - if (ci->cxt) { - gc_mark_object(pic, (struct object *)ci->cxt); - } - } - - /* arena */ - for (j = 0; j < pic->arena_idx; ++j) { - gc_mark_object(pic, (struct object *)pic->arena[j]); - } - - /* ireps */ - for (list = pic->ireps.next; list != &pic->ireps; list = list->next) { - struct irep *irep = (struct irep *)list; - for (j = 0; j < irep->npool; ++j) { - gc_mark_object(pic, irep->pool[j]); - } - } - - /* global variables */ - gc_mark(pic, pic->globals); - - /* macro objects */ - gc_mark(pic, pic->macros); - - /* error object */ - gc_mark(pic, pic->err); - - /* features */ - gc_mark(pic, pic->features); - - /* library table */ - for (it = kh_begin(&pic->ltable); it != kh_end(&pic->ltable); ++it) { - if (! kh_exist(&pic->ltable, it)) { - continue; - } - gc_mark_object(pic, (struct object *)kh_val(&pic->ltable, it).name); - gc_mark_object(pic, (struct object *)kh_val(&pic->ltable, it).env); - gc_mark_object(pic, (struct object *)kh_val(&pic->ltable, it).exports); - } - - /* weak maps */ - do { - struct object *key; - pic_value val; - int it; - khash_t(weak) *h; - struct weak *weak; - - j = 0; - weak = pic->heap->weaks; - - while (weak != NULL) { - h = &weak->hash; - for (it = kh_begin(h); it != kh_end(h); ++it) { - if (! kh_exist(h, it)) - continue; - key = kh_key(h, it); - val = kh_val(h, it); - if (key->u.basic.gc_mark == BLACK) { - if (pic_obj_p(pic, val) && pic_obj_ptr(val)->u.basic.gc_mark == WHITE) { - gc_mark(pic, val); - ++j; - } - } - } - weak = weak->prev; - } - } while (j > 0); -} - -/* SWEEP */ - -static void -gc_finalize_object(pic_state *pic, struct object *obj) -{ - switch (obj->u.basic.tt) { - case PIC_TYPE_VECTOR: { - pic_free(pic, obj->u.vec.data); - break; - } - case PIC_TYPE_BLOB: { - pic_free(pic, obj->u.blob.data); - break; - } - case PIC_TYPE_STRING: { - pic_rope_decref(pic, obj->u.str.rope); - break; - } - case PIC_TYPE_ENV: { - kh_destroy(env, &obj->u.env.map); - break; - } - case PIC_TYPE_DATA: { - if (obj->u.data.type->dtor) { - obj->u.data.type->dtor(pic, obj->u.data.data); - } - break; - } - case PIC_TYPE_DICT: { - kh_destroy(dict, &obj->u.dict.hash); - break; - } - case PIC_TYPE_SYMBOL: { - /* TODO: remove this symbol's entry from pic->syms immediately */ - break; - } - case PIC_TYPE_WEAK: { - kh_destroy(weak, &obj->u.weak.hash); - break; - } - case PIC_TYPE_IREP: { - pic_irep_decref(pic, obj->u.proc.u.i.irep); - break; - } - - case PIC_TYPE_PAIR: - case PIC_TYPE_CXT: - case PIC_TYPE_PORT: - case PIC_TYPE_ERROR: - case PIC_TYPE_ID: - case PIC_TYPE_RECORD: - case PIC_TYPE_CP: - case PIC_TYPE_FUNC: - break; - - default: - PIC_UNREACHABLE(); - } } static size_t @@ -633,7 +220,7 @@ gc_sweep_phase(pic_state *pic) if (! kh_exist(s, it)) continue; sym = kh_val(s, it); - if (sym && sym->gc_mark == WHITE) { + if (sym && ! is_marked(pic, (struct object *)sym)) { kh_del(oblist, s, it); } } @@ -650,24 +237,10 @@ gc_sweep_phase(pic_state *pic) } } -void -pic_gc(pic_state *pic) +static void +gc_init(pic_state *PIC_UNUSED(pic)) { - if (! pic->gc_enable) { - return; - } - - gc_mark_phase(pic); - gc_sweep_phase(pic); -} - -void * -pic_alloca(pic_state *pic, size_t n) -{ - static const pic_data_type t = { "pic_alloca", pic_free, 0 }; - - /* TODO: optimize */ - return pic_data(pic, pic_data_value(pic, pic_malloc(pic, n), &t)); + return; } struct object * @@ -695,14 +268,3 @@ pic_obj_alloc_unsafe(pic_state *pic, size_t size, int type) return obj; } - -struct object * -pic_obj_alloc(pic_state *pic, size_t size, int type) -{ - struct object *obj; - - obj = pic_obj_alloc_unsafe(pic, size, type); - - gc_protect(pic, obj); - return obj; -}