static void ary_modify(mrb_state *mrb, struct RArray *a) { if (ARY_SHARED_P(a)) { mrb_shared_array *shared = a->aux.shared; if (shared->refcnt == 1 && a->ptr == shared->ptr) { a->ptr = shared->ptr; a->aux.capa = a->len; mrb_free(mrb, shared); } else { mrb_value *ptr, *p; mrb_int len; p = a->ptr; len = a->len * sizeof(mrb_value); ptr = (mrb_value *)mrb_malloc(mrb, len); if (p) { array_copy(ptr, p, a->len); } a->ptr = ptr; a->aux.capa = a->len; mrb_ary_decref(mrb, shared); } ARY_UNSET_SHARED_FLAG(a); } }
static void ary_modify(mrb_state *mrb, struct RArray *a) { if (a->flags & MRB_ARY_SHARED) { struct mrb_shared_array *shared = a->aux.shared; if (shared->refcnt == 1 && a->ptr == shared->ptr) { a->ptr = shared->ptr; a->aux.capa = a->len; mrb_free(mrb, shared); } else { mrb_value *ptr, *p; int len; p = a->ptr; len = a->len * sizeof(mrb_value); ptr = (mrb_value *)mrb_malloc(mrb, len); if (p) { memcpy(ptr, p, len); } a->ptr = ptr; a->aux.capa = a->len; mrb_ary_decref(mrb, shared); } a->flags &= ~MRB_ARY_SHARED; } }
MRB_API mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); ary_modify(mrb, a); if (ARY_SHARED_P(a)) { mrb_ary_decref(mrb, a->as.heap.aux.shared); ARY_UNSET_SHARED_FLAG(a); } else if (!ARY_EMBED_P(a)){ mrb_free(mrb, a->as.heap.ptr); } ARY_SET_EMBED_LEN(a, 0); return self; }
MRB_API mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); if (ARY_SHARED_P(a)) { mrb_ary_decref(mrb, a->aux.shared); ARY_UNSET_SHARED_FLAG(a); } else { mrb_free(mrb, a->ptr); } a->len = 0; a->aux.capa = 0; a->ptr = 0; return self; }
static void ary_replace(mrb_state *mrb, struct RArray *a, struct RArray *b) { mrb_int len = ARY_LEN(b); ary_modify_check(mrb, a); if (a == b) return; if (ARY_SHARED_P(a)) { mrb_ary_decref(mrb, a->as.heap.aux.shared); a->as.heap.aux.capa = 0; a->as.heap.len = 0; a->as.heap.ptr = NULL; ARY_UNSET_SHARED_FLAG(a); } if (ARY_SHARED_P(b)) { shared_b: if (ARY_EMBED_P(a)) { ARY_UNSET_EMBED_FLAG(a); } else { mrb_free(mrb, a->as.heap.ptr); } a->as.heap.ptr = b->as.heap.ptr; a->as.heap.len = len; a->as.heap.aux.shared = b->as.heap.aux.shared; a->as.heap.aux.shared->refcnt++; ARY_SET_SHARED_FLAG(a); mrb_write_barrier(mrb, (struct RBasic*)a); return; } if (!MRB_FROZEN_P(b) && len > ARY_REPLACE_SHARED_MIN) { ary_make_shared(mrb, b); goto shared_b; } if (ARY_CAPA(a) < len) ary_expand_capa(mrb, a, len); array_copy(ARY_PTR(a), ARY_PTR(b), len); mrb_write_barrier(mrb, (struct RBasic*)a); ARY_SET_LEN(a, len); }
static void obj_free(mrb_state *mrb, struct RBasic *obj) { DEBUG(printf("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; case MRB_TT_FLOAT: #ifdef MRB_WORD_BOXING break; #else return; #endif case MRB_TT_OBJECT: 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_ENV: { struct REnv *e = (struct REnv*)obj; if (!MRB_ENV_STACK_SHARED_P(e)) { mrb_free(mrb, e->stack); e->stack = NULL; } } break; case MRB_TT_FIBER: { struct mrb_context *c = ((struct RFiber*)obj)->cxt; if (c != mrb->root_c) mrb_free_context(mrb, c); } break; case MRB_TT_ARRAY: if (obj->flags & MRB_ARY_SHARED) mrb_ary_decref(mrb, ((struct RArray*)obj)->aux.shared); else mrb_free(mrb, ((struct RArray*)obj)->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_decref(mrb, p->body.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; }
static void obj_free(mrb_state *mrb, struct RBasic *obj) { DEBUG(printf("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: case MRB_TT_FLOAT: /* cannot happen */ return; case MRB_TT_OBJECT: 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_ENV: { struct REnv *e = (struct REnv*)obj; if (e->cioff < 0) { mrb_free(mrb, e->stack); e->stack = 0; } } break; case MRB_TT_ARRAY: if (obj->flags & MRB_ARY_SHARED) mrb_ary_decref(mrb, ((struct RArray*)obj)->aux.shared); else mrb_free(mrb, ((struct RArray*)obj)->ptr); break; case MRB_TT_HASH: mrb_gc_free_iv(mrb, (struct RObject*)obj); mrb_gc_free_ht(mrb, (struct RHash*)obj); break; case MRB_TT_STRING: if (obj->flags & MRB_STR_SHARED) mrb_str_decref(mrb, ((struct RString*)obj)->aux.shared); else mrb_free(mrb, ((struct RString*)obj)->ptr); break; case MRB_TT_RANGE: mrb_free(mrb, ((struct RRange*)obj)->edges); break; #ifdef ENABLE_STRUCT case MRB_TT_STRUCT: mrb_free(mrb, ((struct RStruct*)obj)->ptr); break; #endif case MRB_TT_DATA: { struct RData *d = (struct RData*)obj; if (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; }
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; case MRB_TT_FLOAT: #ifdef MRB_WORD_BOXING break; #else return; #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_FLAG_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 */ return; } mrb_free(mrb, e->stack); e->stack = NULL; } break; case MRB_TT_FIBER: { struct mrb_context *c = ((struct RFiber*)obj)->cxt; if (!end && c && c != mrb->root_c) { mrb_callinfo *ci = c->ci; mrb_callinfo *ce = c->cibase; while (ce <= ci) { struct REnv *e = ci->env; if (e && !is_dead(&mrb->gc, 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)->aux.shared); else mrb_free(mrb, ((struct RArray*)obj)->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_decref(mrb, p->body.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; }