#include #include "picrin.h" #include "picrin/gc.h" void init_heap_page(struct heap_page *heap) { union header *base, *freep; void *p; p = (union header *)malloc(PIC_HEAP_SIZE); heap->base = base = (union header *) (((unsigned long)p + sizeof(union header) -1) & ~(sizeof(union header) - 1)); base->s.ptr = base + 1; base->s.size = 0; heap->freep = freep = base->s.ptr; freep->s.ptr = base; freep->s.size = ((char *)p + PIC_HEAP_SIZE - (char *)freep) / sizeof(union header); } void * pic_alloc(pic_state *pic, size_t size) { void *ptr; ptr = malloc(size); if (ptr == NULL) { pic_raise(pic, "memory exhausted"); } return ptr; } void pic_free(pic_state *pic, void *ptr) { free(ptr); } static void gc_protect(pic_state *pic, struct pic_object *obj) { if (pic->arena_idx >= PIC_ARENA_SIZE) { pic_raise(pic, "arena overflow"); } pic->arena[pic->arena_idx++] = obj; } void pic_gc_protect(pic_state *pic, pic_value v) { struct pic_object *obj; if (v.type != PIC_VTYPE_HEAP) { return; } obj = pic_object_ptr(v); gc_protect(pic, obj); } int pic_gc_arena_preserve(pic_state *pic) { return pic->arena_idx; } void pic_gc_arena_restore(pic_state *pic, int state) { pic->arena_idx = state; } static void * pic_gc_alloc(pic_state *pic, size_t size) { union header *freep, *p, *prevp; size_t nunits; nunits = (size + sizeof(union header) - 1) / sizeof(union header) + 1; freep = pic->heap->freep; prevp = freep; for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr) { if (p->s.size >= nunits) break; if (p == freep) { return 0; } } if (p->s.size == nunits) { prevp->s.ptr = p->s.ptr; } else { p->s.size -= nunits; p += p->s.size; p->s.size = nunits; } pic->heap->freep = prevp; return (void *)(p + 1); } static void pic_gc_free(pic_state *pic, void *ptr) { union header *bp, *p; bp = (union header *)ptr - 1; for (p = pic->heap->freep; !(p < bp && bp < p->s.ptr); p = p->s.ptr) { if (p >= p->s.ptr && (bp > p || bp < p->s.ptr)) break; } if (bp + bp->s.size == p->s.ptr) { bp->s.size += p->s.ptr->s.size; bp->s.ptr = p->s.ptr->s.ptr; } else { bp->s.ptr = p->s.ptr; } if (p + p->s.size == bp) { p->s.size += bp->s.size; p->s.ptr = bp->s.ptr; } else { p->s.ptr = bp; } pic->heap->freep = p; } struct pic_object * pic_obj_alloc(pic_state *pic, size_t size, enum pic_tt tt) { struct pic_object *obj; obj = (struct pic_object *)malloc(size); obj->tt = tt; gc_protect(pic, obj); return obj; }