struct RBasic* mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) { struct RBasic *p; static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } }; #ifdef MRB_GC_STRESS mrb_full_gc(mrb); #endif if (mrb->gc_threshold < mrb->live) { mrb_incremental_gc(mrb); } if (mrb->free_heaps == NULL) { add_heap(mrb); } p = mrb->free_heaps->freelist; mrb->free_heaps->freelist = ((struct free_obj*)p)->next; if (mrb->free_heaps->freelist == NULL) { unlink_free_heap_page(mrb, mrb->free_heaps); } mrb->live++; gc_protect(mrb, p); *(RVALUE *)p = RVALUE_zero; p->tt = ttype; p->c = cls; paint_partial_white(mrb, p); return p; }
struct RBasic* mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) { struct RBasic *p; #ifdef MRB_GC_STRESS mrb_garbage_collect(mrb); #endif if (mrb->gc_threshold < mrb->live) { mrb_incremental_gc(mrb); } if (mrb->free_heaps == NULL) { add_heap(mrb); } p = mrb->free_heaps->freelist; mrb->free_heaps->freelist = ((struct free_obj*)p)->next; if (mrb->free_heaps->freelist == NULL) { unlink_free_heap_page(mrb, mrb->free_heaps); } mrb->live++; gc_protect(mrb, p); memset(p, 0, sizeof(RVALUE)); p->tt = ttype; p->c = cls; paint_partial_white(mrb, p); return p; }
struct RBasic* mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) { struct RBasic *p; if (mrb->gc_threshold < mrb->live) { mrb_incremental_gc(mrb); } if (mrb->free_heaps == NULL) { add_heap(mrb); } p = mrb->free_heaps->freelist; mrb->free_heaps->freelist = ((struct free_obj*)p)->next; if (mrb->free_heaps->freelist == NULL) { unlink_free_heap_page(mrb, mrb->free_heaps); } mrb->live++; mrb->arena[mrb->arena_idx++] = p; memset(p, 0, sizeof(RVALUE)); if (mrb->arena_idx >= MRB_ARENA_SIZE) { /* arena overflow error */ mrb_raise(mrb, E_TYPE_ERROR, "arena overflow error"); } p->tt = ttype; p->c = cls; paint_partial_white(mrb, p); return p; }
MRB_API struct RBasic* mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) { struct RBasic *p; static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } }; mrb_gc *gc = &mrb->gc; if (cls) { enum mrb_vtype tt; switch (cls->tt) { case MRB_TT_CLASS: case MRB_TT_SCLASS: case MRB_TT_MODULE: case MRB_TT_ENV: break; default: mrb_raise(mrb, E_TYPE_ERROR, "allocation failure"); } tt = MRB_INSTANCE_TT(cls); if (tt != MRB_TT_FALSE && ttype != MRB_TT_SCLASS && ttype != MRB_TT_ICLASS && ttype != MRB_TT_ENV && ttype != tt) { mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %S", mrb_obj_value(cls)); } } #ifdef MRB_GC_STRESS mrb_full_gc(mrb); #endif if (gc->threshold < gc->live) { mrb_incremental_gc(mrb); } if (gc->free_heaps == NULL) { add_heap(mrb, gc); } p = gc->free_heaps->freelist; gc->free_heaps->freelist = ((struct free_obj*)p)->next; if (gc->free_heaps->freelist == NULL) { unlink_free_heap_page(gc, gc->free_heaps); } gc->live++; gc_protect(mrb, gc, p); *(RVALUE *)p = RVALUE_zero; p->tt = ttype; p->c = cls; paint_partial_white(gc, p); return p; }
static size_t incremental_sweep_phase(mrb_state *mrb, size_t limit) { struct heap_page *page = mrb->sweeps; size_t tried_sweep = 0; while (page && (tried_sweep < limit)) { RVALUE *p = page->objects; RVALUE *e = p + MRB_HEAP_PAGE_SIZE; size_t freed = 0; int dead_slot = 1; int full = (page->freelist == NULL); while (p<e) { if (is_dead(mrb, &p->as.basic)) { if (p->as.basic.tt != MRB_TT_FREE) { obj_free(mrb, &p->as.basic); p->as.free.next = page->freelist; page->freelist = (struct RBasic*)p; freed++; } } else { paint_partial_white(mrb, &p->as.basic); /* next gc target */ dead_slot = 0; } p++; } /* free dead slot */ if (dead_slot && freed < MRB_HEAP_PAGE_SIZE) { struct heap_page *next = page->next; unlink_heap_page(mrb, page); unlink_free_heap_page(mrb, page); mrb_free(mrb, page); page = next; } else { if (full && freed > 0) { link_free_heap_page(mrb, page); } page = page->next; } tried_sweep += MRB_HEAP_PAGE_SIZE; mrb->live -= freed; mrb->gc_live_after_mark -= freed; } mrb->sweeps = page; return tried_sweep; }
static size_t incremental_sweep_phase(mrb_state *mrb, size_t limit) { struct heap_page *page = mrb->sweeps; size_t tried_sweep = 0; while (page && (tried_sweep < limit)) { RVALUE *p = page->objects; RVALUE *e = p + MRB_HEAP_PAGE_SIZE; size_t freed = 0; mrb_bool dead_slot = TRUE; int full = (page->freelist == NULL); if (is_minor_gc(mrb) && page->old) { /* skip a slot which doesn't contain any young object */ p = e; dead_slot = FALSE; } while (p<e) { if (is_dead(mrb, &p->as.basic)) { if (p->as.basic.tt != MRB_TT_FREE) { obj_free(mrb, &p->as.basic); p->as.free.next = page->freelist; page->freelist = (struct RBasic*)p; freed++; } } else { if (!is_generational(mrb)) paint_partial_white(mrb, &p->as.basic); /* next gc target */ dead_slot = 0; } p++; } /* free dead slot */ if (dead_slot && freed < MRB_HEAP_PAGE_SIZE) { struct heap_page *next = page->next; unlink_heap_page(mrb, page); unlink_free_heap_page(mrb, page); mrb_free(mrb, page); page = next; } else { if (full && freed > 0) { link_free_heap_page(mrb, page); } if (page->freelist == NULL && is_minor_gc(mrb)) page->old = TRUE; else page->old = FALSE; page = page->next; } tried_sweep += MRB_HEAP_PAGE_SIZE; mrb->live -= freed; mrb->gc_live_after_mark -= freed; } mrb->sweeps = page; return tried_sweep; }