summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2013-11-08 20:39:50 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2013-11-08 20:39:50 +0900
commitde790bdc2785ee36730563982afc45480f6c0f42 (patch)
treeefc81547c8a6190a00bbd0fce704a02c8e373c3a /src
parentcba07b02755711630e418fcf361d94cf47bb6730 (diff)
downloadmruby-de790bdc2785ee36730563982afc45480f6c0f42.tar.gz
mruby-de790bdc2785ee36730563982afc45480f6c0f42.zip
allow irep to be GCed
Diffstat (limited to 'src')
-rw-r--r--src/gc.c10
-rw-r--r--src/proc.c6
-rw-r--r--src/state.c19
3 files changed, 34 insertions, 1 deletions
diff --git a/src/gc.c b/src/gc.c
index 866d5bdc8..a1ff4d32b 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -640,6 +640,16 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
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;
diff --git a/src/proc.c b/src/proc.c
index a7e4192aa..cfb677f0a 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -22,6 +22,7 @@ mrb_proc_new(mrb_state *mrb, mrb_irep *irep)
p->target_class = (mrb->c->ci) ? mrb->c->ci->target_class : 0;
p->body.irep = irep;
p->env = 0;
+ mrb_irep_incref(mrb, irep);
return p;
}
@@ -80,6 +81,9 @@ mrb_proc_copy(struct RProc *a, struct RProc *b)
{
a->flags = b->flags;
a->body = b->body;
+ if (!MRB_PROC_CFUNC_P(a)) {
+ a->body.irep->refcnt++;
+ };
a->target_class = b->target_class;
a->env = b->env;
}
@@ -181,7 +185,7 @@ void
mrb_init_proc(mrb_state *mrb)
{
struct RProc *m;
- mrb_irep *call_irep = (mrb_irep *)mrb_alloca(mrb, sizeof(mrb_irep));
+ mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
static const mrb_irep mrb_irep_zero = { 0 };
if (call_irep == NULL)
diff --git a/src/state.c b/src/state.c
index 6e6394c9c..0012bc189 100644
--- a/src/state.c
+++ b/src/state.c
@@ -107,6 +107,21 @@ void mrb_free_symtbl(mrb_state *mrb);
void mrb_free_heap(mrb_state *mrb);
void
+mrb_irep_incref(mrb_state *mrb, mrb_irep *irep)
+{
+ irep->refcnt++;
+}
+
+void
+mrb_irep_decref(mrb_state *mrb, mrb_irep *irep)
+{
+ irep->refcnt--;
+ if (irep->refcnt == 0) {
+ mrb_irep_free(mrb, irep);
+ }
+}
+
+void
mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
{
size_t i;
@@ -119,6 +134,9 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
}
mrb_free(mrb, irep->pool);
mrb_free(mrb, irep->syms);
+ for (i=0; i<irep->rlen; i++) {
+ mrb_irep_decref(mrb, irep->reps[i]);
+ }
mrb_free(mrb, irep->reps);
mrb_free(mrb, (void *)irep->filename);
mrb_free(mrb, irep->lines);
@@ -163,6 +181,7 @@ mrb_add_irep(mrb_state *mrb)
irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
*irep = mrb_irep_zero;
+ irep->refcnt = 1;
return irep;
}