static void os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud) { struct os_each_object_data *d = (struct os_each_object_data*)ud; /* filter dead objects */ if (mrb_object_dead_p(mrb, obj)) { return; } /* filter internal objects */ switch (obj->tt) { case MRB_TT_ENV: case MRB_TT_ICLASS: return; default: break; } /* filter half baked (or internal) objects */ if (!obj->c) return; /* filter class kind if target module defined */ if (d->target_module && !mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), d->target_module)) { return; } mrb_yield(mrb, d->block, mrb_obj_value(obj)); ++d->count; }
static void os_count_object_type(mrb_state *mrb, struct RBasic *obj, void *data) { struct os_count_struct *obj_count; obj_count = (struct os_count_struct*)data; obj_count->total++; if (mrb_object_dead_p(mrb, obj)) { obj_count->freed++; } else { obj_count->counts[obj->tt]++; } }
static void obj_free(mrb_state *mrb, struct RBasic *obj, int end) { DEBUG(fprintf(stderr, "obj_free(%p,tt=%d)\n",obj,obj->tt)); switch (obj->tt) { /* immediate - no mark */ case MRB_TT_TRUE: case MRB_TT_FIXNUM: case MRB_TT_SYMBOL: /* cannot happen */ return; #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: #ifdef MRB_WORD_BOXING break; #else return; #endif #endif case MRB_TT_OBJECT: mrb_gc_free_iv(mrb, (struct RObject*)obj); break; case MRB_TT_EXCEPTION: mrb_gc_free_iv(mrb, (struct RObject*)obj); break; case MRB_TT_CLASS: case MRB_TT_MODULE: case MRB_TT_SCLASS: mrb_gc_free_mt(mrb, (struct RClass*)obj); mrb_gc_free_iv(mrb, (struct RObject*)obj); break; case MRB_TT_ICLASS: if (MRB_FLAG_TEST(obj, MRB_FL_CLASS_IS_ORIGIN)) mrb_gc_free_mt(mrb, (struct RClass*)obj); break; case MRB_TT_ENV: { struct REnv *e = (struct REnv*)obj; if (MRB_ENV_STACK_SHARED_P(e)) { /* cannot be freed */ e->stack = NULL; break; } mrb_free(mrb, e->stack); e->stack = NULL; } break; case MRB_TT_FIBER: { struct mrb_context *c = ((struct RFiber*)obj)->cxt; if (c && c != mrb->root_c) { if (!end && c->status != MRB_FIBER_TERMINATED) { mrb_callinfo *ci = c->ci; mrb_callinfo *ce = c->cibase; while (ce <= ci) { struct REnv *e = ci->env; if (e && !mrb_object_dead_p(mrb, (struct RBasic*)e) && e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) { mrb_env_unshare(mrb, e); } ci--; } } mrb_free_context(mrb, c); } } break; case MRB_TT_ARRAY: if (ARY_SHARED_P(obj)) mrb_ary_decref(mrb, ((struct RArray*)obj)->as.heap.aux.shared); else if (!ARY_EMBED_P(obj)) mrb_free(mrb, ((struct RArray*)obj)->as.heap.ptr); break; case MRB_TT_HASH: mrb_gc_free_iv(mrb, (struct RObject*)obj); mrb_gc_free_hash(mrb, (struct RHash*)obj); break; case MRB_TT_STRING: mrb_gc_free_str(mrb, (struct RString*)obj); break; case MRB_TT_PROC: { struct RProc *p = (struct RProc*)obj; if (!MRB_PROC_CFUNC_P(p) && p->body.irep) { mrb_irep *irep = p->body.irep; if (end) { mrb_irep_cutref(mrb, irep); } mrb_irep_decref(mrb, irep); } } break; case MRB_TT_RANGE: mrb_free(mrb, ((struct RRange*)obj)->edges); break; case MRB_TT_DATA: { struct RData *d = (struct RData*)obj; if (d->type && d->type->dfree) { d->type->dfree(mrb, d->data); } mrb_gc_free_iv(mrb, (struct RObject*)obj); } break; default: break; } obj->tt = MRB_TT_FREE; }