void gc_mark_object(Object* object) { ObjectHeader* head = &((ObjectHeader*)object)[-1]; debug("mark %p\n",head); long size; if (!heap_find(vm, head)) { debug2("******** unfind in heap %p\n", &head[1]); return; } debug2("find\n"); if (head->marked) return; long* bitmap; head->marked = 1; switch(head->type) { case OBJ_BOXED_ARRAY: debug("BOXED_ARRAY\n"); size = ((int)head->size) / sizeof(long); debug2("size=%ld\n",size); for(int i = 0; i < size; i++) gc_mark_object(object->field[i]); debug2("END\n"); break; case OBJ_PAIR: debug("PAIR\n"); gc_mark_object(object->fst); gc_mark_object(object->snd); break; case OBJ_UNBOXED_ARRAY: debug("UNBOXED ARRAY\n"); break; case OBJ_VM: debug("VM\n"); break; case OBJ_RECORD: size = ((int)head->size) / sizeof(long); debug("RECORD size=%ld\n", size); bitmap = &object->longs[size]; debug2("size=%ld\n",size); for(int i = 0; i < size; i++) { if(bitmap[i/sizeof(long)] & (1 << (i % sizeof(long)))) gc_mark_object(object->field[i]); else { debug2("skip %d\n", i); } } break; } }
void _VMArray_mark_references(void* _self) { pVMArray self = (pVMArray)_self; int size_of_indexable_fields = SEND(self, get_number_of_indexable_fields); for(int i=0;i<size_of_indexable_fields;i++) { gc_mark_object(SEND(self, get_indexable_field, i)); } SUPER(VMObject, self, mark_references); }
static void gc_mark(pic_state *pic, pic_value v) { if (! obj_p(pic, v)) return; gc_mark_object(pic, obj_ptr(pic, v)); }
void gc_collect_pipe(Object* data) { long prev_num = vm->heap_num; gc_mark_object(data); gc_sweep(NULL); vm->heap_max = prev_num * 2; debug("Collected %ld objects, %ld remaining.\n", prev_num - vm->heap_num, vm->heap_num); }
static void gc_mark() { int i; num_live_objects = 0; for (i = 0; i < num_roots; i++) { if (DEBUG) printf("root[%d]=%p\n", i, _roots[i]); Object *p = *_roots[i]; if (p != NULL) { if (gc_in_heap(p)) { gc_mark_object(p); } } } }
void gc_mark_frame(Frame *frame, Object** objects) { for(int i = 0; i < frame->bitmap_size; i++) { unsigned int bitmap = frame->bitmap[i]; int n = i * 32; while (bitmap) { if(bitmap & 1) { gc_mark_object(objects[n]); } bitmap = bitmap >> 1; n++; } } }
Object* gc_collect_end_vm(Object* data, VM* _vm) { long prev_num = vm->heap_num; debug2("gc mark\n"); gc_mark_object(data); debug2("gc sweep\n"); gc_sweep(_vm); vm->heap_max = prev_num * 2; debug("Collected %ld objects, %ld moving.\n", prev_num - vm->heap_num, vm->heap_num); return data; }
void gc_mark_object(Object* object) { ObjectHeader* head = &((ObjectHeader*)object)[-1]; debug("mark %p\n",head); long size; if (!heap_find(head)) return; if (head->marked) return; long* bitmap; head->marked = 1; switch(head->type) { case OBJ_BOXED_ARRAY: size = ((int)head->size) / sizeof(long); debug("size=%ld\n",size); for(int i = 0; i < size; i++) gc_mark_object(object->field[i]); break; case OBJ_PAIR: debug("PAIR\n"); gc_mark_object(object->pair.fst); gc_mark_object(object->pair.snd); break; case OBJ_UNBOXED_ARRAY: break; case OBJ_RECORD: size = ((int)head->size) / sizeof(long); debug("RECORD size=%ld\n", size); bitmap = &object->longs[size]; debug("size=%ld\n",size); for(int i = 0; i < size; i++) { if(bitmap[i/sizeof(long)] & (1 << (i % sizeof(long)))) gc_mark_object(object->field[i]); else debug("skip %d\n", i); } break; } }
void gc_mark() { Frame* frame = frame_list; while(frame != frame_bottom) { debug2("gc mark %p size %ld\n", frame, frame->frame_size); int pos = frame->frame_size; if(pos > frame->frame_pos) pos = frame->frame_pos; for(int i = 0; i < pos; i++) { gc_mark_object(frame->frame_data[i]); debug2("done\n"); } debug2("next %p\n", frame); debug2("next prev %p %p\n", frame->frame_prev, frame_bottom); frame = frame->frame_prev; } debug2("gc mark done\n"); }
void gc_mark_stack_map(int size, Object** objects) { for(int i = 0; i < size; i++) gc_mark_object(objects[i]); }
void _VMMethod_mark_references(void* _self) { pVMMethod self = (pVMMethod) _self; gc_mark_object(self->signature); gc_mark_object(self->holder); SUPER(VMArray, self, mark_references); }
static void gc_mark_phase(pic_state *pic) { struct context *cxt; size_t j; assert(pic->heap->weaks == NULL); /* context */ for (cxt = pic->cxt; cxt != NULL; cxt = cxt->prev) { if (cxt->fp) gc_mark_object(pic, (struct object *)cxt->fp); if (cxt->sp) gc_mark_object(pic, (struct object *)cxt->sp); if (cxt->irep) gc_mark_object(pic, (struct object *)cxt->irep); } /* arena */ for (j = 0; j < pic->ai; ++j) { gc_mark_object(pic, (struct object *)pic->arena[j]); } /* global variables */ gc_mark(pic, pic->globals); /* dynamic environment */ gc_mark(pic, pic->dyn_env); /* top continuation */ gc_mark(pic, pic->halt); /* features */ gc_mark(pic, pic->features); /* 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_alive(key)) { if (obj_p(pic, val) && ! is_alive(obj_ptr(pic, val))) { gc_mark(pic, val); ++j; } } } weak = weak->prev; } } while (j > 0); }
static void gc_mark_object(pic_state *pic, struct object *obj) { loop: if (is_alive(obj)) return; mark(obj); #define LOOP(o) obj = (struct object *)(o); goto loop switch (obj_type(pic, obj)) { case PIC_TYPE_PAIR: { gc_mark(pic, obj->u.pair.car); if (obj_p(pic, obj->u.pair.cdr)) { LOOP(obj_ptr(pic, obj->u.pair.cdr)); } break; } case PIC_TYPE_FRAME: { int i; for (i = 0; i < obj->u.frame.regc; ++i) { gc_mark(pic, obj->u.frame.regs[i]); } if (obj->u.frame.up) { LOOP(obj->u.frame.up); } break; } case PIC_TYPE_PROC_FUNC: { if (obj->u.proc.env) { LOOP(obj->u.proc.env); } break; } case PIC_TYPE_PROC_IREP: { if (obj->u.proc.env) { gc_mark_object(pic, (struct object *)obj->u.proc.env); } LOOP(obj->u.proc.u.irep); break; } case PIC_TYPE_IREP: { size_t i; for (i = 0; i < obj->u.irep.objc; ++i) { gc_mark(pic, obj->u.irep.obj[i]); } for (i = 0; i < obj->u.irep.irepc; ++i) { gc_mark_object(pic, (struct object *)obj->u.irep.irep[i]); } break; } case PIC_TYPE_PORT: { break; } case PIC_TYPE_ERROR: { gc_mark_object(pic, (struct object *)obj->u.err.type); gc_mark(pic, obj->u.err.irrs); LOOP(obj->u.err.msg); 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_DATA: { break; } case PIC_TYPE_DICT: { pic_value key, val; int it = 0; while (pic_dict_next(pic, obj_value(pic, &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.datum); LOOP(obj->u.rec.type); break; } case PIC_TYPE_SYMBOL: { LOOP(obj->u.sym.str); break; } case PIC_TYPE_WEAK: { struct weak *weak = (struct weak *)obj; weak->prev = pic->heap->weaks; pic->heap->weaks = weak; break; } default: PIC_UNREACHABLE(); } }
void pic_gc(pic_state *pic) { struct context *cxt; size_t j; khash_t(oblist) *s = &pic->oblist; struct symbol *sym; int it; struct object *obj, *prev, *next; assert(pic->gc_attrs == NULL); if (! pic->gc_enable) { return; } /* scan objects */ for (cxt = pic->cxt; cxt != NULL; cxt = cxt->prev) { if (cxt->fp) gc_mark_object(pic, (struct object *)cxt->fp); if (cxt->sp) gc_mark_object(pic, (struct object *)cxt->sp); if (cxt->irep) gc_mark_object(pic, (struct object *)cxt->irep); gc_mark(pic, cxt->conts); } for (j = 0; j < pic->ai; ++j) { gc_mark_object(pic, (struct object *)pic->arena[j]); } gc_mark(pic, pic->globals); gc_mark(pic, pic->halt); /* scan weak references */ do { struct object *key; pic_value val; int it; khash_t(attr) *h; struct attr *attr; j = 0; attr = pic->gc_attrs; while (attr != NULL) { h = &attr->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_alive(key)) { if (pic_obj_p(pic, val) && ! is_alive((struct object *) pic_ptr(pic, val))) { gc_mark(pic, val); ++j; } } } attr = attr->prev; } } while (j > 0); /* reclaim dead weak references */ while (pic->gc_attrs != NULL) { khash_t(attr) *h = &pic->gc_attrs->hash; for (it = kh_begin(h); it != kh_end(h); ++it) { if (! kh_exist(h, it)) continue; obj = kh_key(h, it); if (! is_alive(obj)) { kh_del(attr, h, it); } } pic->gc_attrs = pic->gc_attrs->prev; } for (it = kh_begin(s); it != kh_end(s); ++it) { if (! kh_exist(s, it)) continue; sym = kh_val(s, it); if (sym && ! is_alive((struct object *)sym)) { kh_del(oblist, s, it); } } /* reclaim dead objects */ for (prev = &pic->gc_head, obj = prev->next; obj != &pic->gc_head; prev = obj, obj = next) { next = obj->next; if (is_alive(obj)) { unmark(obj); } else { gc_finalize_object(pic, obj); pic_free(pic, obj); prev->next = next; obj = prev; } } }
static void gc_mark_object(pic_state *pic, struct object *obj) { loop: if (is_alive(obj)) return; mark(obj); #define LOOP(o) obj = (struct object *)(o); goto loop switch (obj_type(obj)) { case PIC_TYPE_PAIR: { struct pair *pair = (struct pair *) obj; gc_mark(pic, pair->car); if (pic_obj_p(pic, pair->cdr)) { LOOP(pic_ptr(pic, pair->cdr)); } break; } case PIC_TYPE_FRAME: { struct frame *frame = (struct frame *) obj; int i; for (i = 0; i < frame->regc; ++i) { gc_mark(pic, frame->regs[i]); } if (frame->up) { LOOP(frame->up); } break; } case PIC_TYPE_PROC_FUNC: { struct proc *proc = (struct proc *) obj; if (proc->env) { LOOP(proc->env); } break; } case PIC_TYPE_PROC_IREP: { struct proc *proc = (struct proc *) obj; if (proc->env) { gc_mark_object(pic, (struct object *) proc->env); } LOOP(proc->u.irep); break; } case PIC_TYPE_IREP: { struct irep *irep = (struct irep *) obj; size_t i; for (i = 0; i < irep->objc; ++i) { gc_mark(pic, irep->obj[i]); } for (i = 0; i < irep->irepc; ++i) { gc_mark_object(pic, (struct object *) irep->irep[i]); } break; } case PIC_TYPE_VECTOR: { struct vector *vec = (struct vector *) obj; int i; for (i = 0; i < vec->len; ++i) { gc_mark(pic, vec->data[i]); } break; } case PIC_TYPE_DICT: { struct dict *dict = (struct dict *) obj; khash_t(dict) *h = &dict->hash; int it; for (it = 0; it != kh_end(h); ++it) { if (kh_exist(h, it)) { gc_mark_object(pic, (struct object *) kh_key(h, it)); gc_mark(pic, kh_val(h, it)); } } break; } case PIC_TYPE_RECORD: { struct record *rec = (struct record *) obj; gc_mark(pic, rec->datum); LOOP(rec->type); break; } case PIC_TYPE_SYMBOL: { struct symbol *sym = (struct symbol *) obj; LOOP(sym->str); break; } case PIC_TYPE_ATTR: { struct attr *attr = (struct attr *) obj; attr->prev = pic->gc_attrs; pic->gc_attrs = attr; break; } case PIC_TYPE_STRING: { struct string *str = (struct string *) obj; LOOP(str->rope); break; } case PIC_TYPE_ROPE_NODE: { struct rope_node *node = (struct rope_node *) obj; gc_mark_object(pic, (struct object *) node->s1); LOOP(node->s2); break; } case PIC_TYPE_ROPE_LEAF: case PIC_TYPE_BLOB: case PIC_TYPE_DATA: break; default: PIC_UNREACHABLE(); } }