diff --git a/include/mruby/internal.h b/include/mruby/internal.h index 4b06dd522..0b5a88af8 100644 --- a/include/mruby/internal.h +++ b/include/mruby/internal.h @@ -279,4 +279,7 @@ mrb_value mrb_bint_abs(mrb_state *mrb, mrb_value x); void mrb_task_mark_all(mrb_state *mrb); #endif +/* Internal object allocation without type validation (gc.c) */ +struct RBasic* mrb_obj_alloc_core(mrb_state*, enum mrb_vtype, struct RClass*); + #endif /* MRUBY_INTERNAL_H */ diff --git a/src/gc.c b/src/gc.c index 283d1dcdb..4f203b92b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -563,38 +563,14 @@ mrb_gc_unregister(mrb_state *mrb, mrb_value obj) ARY_SET_LEN(a, w); } -MRB_API struct RBasic* -mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) +/* Core allocation without type validation. + Used internally by mrb_proc_new, mrb_env_new, etc. */ +struct RBasic* +mrb_obj_alloc_core(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) { static const RVALUE RVALUE_zero = { { { NULL, 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 (ttype != MRB_TT_SCLASS && - ttype != MRB_TT_ICLASS && - ttype != MRB_TT_ENV && - ttype != MRB_TT_BIGINT && - ttype != tt && - !(cls == mrb->object_class && (ttype == MRB_TT_CPTR || ttype == MRB_TT_CDATA || ttype == MRB_TT_ISTRUCT))) { - mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %C", cls); - } - } - if (ttype <= MRB_TT_FREE) { - mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %C (type %d)", cls, (int)ttype); - } - #ifdef MRB_GC_STRESS mrb_full_gc(mrb); #endif @@ -625,6 +601,37 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) return &p->as.basic; } +MRB_API struct RBasic* +mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) +{ + 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 (ttype != MRB_TT_SCLASS && + ttype != MRB_TT_ICLASS && + ttype != MRB_TT_ENV && + ttype != MRB_TT_BIGINT && + ttype != tt && + !(cls == mrb->object_class && (ttype == MRB_TT_CPTR || ttype == MRB_TT_CDATA || ttype == MRB_TT_ISTRUCT))) { + mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %C", cls); + } + } + if (ttype <= MRB_TT_FREE) { + mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %C (type %d)", cls, (int)ttype); + } + return mrb_obj_alloc_core(mrb, ttype, cls); +} + static inline void add_gray_list(mrb_gc *gc, struct RBasic *obj) { diff --git a/src/proc.c b/src/proc.c index 4864cadd1..963841689 100644 --- a/src/proc.c +++ b/src/proc.c @@ -47,7 +47,7 @@ mrb_proc_new(mrb_state *mrb, const mrb_irep *irep) struct RProc *p; mrb_callinfo *ci = mrb->c->ci; - p = MRB_OBJ_ALLOC(mrb, MRB_TT_PROC, mrb->proc_class); + p = (struct RProc*)mrb_obj_alloc_core(mrb, MRB_TT_PROC, mrb->proc_class); if (ci) { struct RClass *tc = NULL; @@ -76,7 +76,7 @@ mrb_env_new(mrb_state *mrb, struct mrb_context *c, mrb_callinfo *ci, int nstacks int n = ci->n; int nk = ci->nk; - e = MRB_OBJ_ALLOC(mrb, MRB_TT_ENV, NULL); + e = (struct REnv*)mrb_obj_alloc_core(mrb, MRB_TT_ENV, NULL); e->c = tc; MRB_ENV_SET_LEN(e, nstacks); bidx += (n == 15) ? 1 : n;