summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-03-11 09:15:20 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-03-11 09:15:20 +0000
commit5922c954614e5947a548780bb3b894626affe6dd (patch)
treec7de7025f8d3dbeb816aa99cd197e5adba33815e /gc.c
parent5a62fdee4d166fe0eff14bc616e1befa8ad54cd2 (diff)
* gc.c: fix memory leak by prepend method.
It is easy to reproduce with such script: module M; def bar; end; end loop{ Class.new do def foo; end prepend M end } * gc.c (obj_free): free T_ICLASS::m_tbl if it is created by prepend. To recognize it, check RICLASS_IS_ORIGIN flag. * gc.c (gc_mark_children): T_ICLASS objects only need to mark T_ICLASS::m_tbl if RICLASS_IS_ORIGIN is set. * gc.c (obj_memsize_of): count T_ICLASS if RICLASS_IS_ORIGIN is set. * internal.h (RCLASS_SET_ORIGIN): add to set RCLASS_SET_ORIGIN. TODO: The word `origin' seems not good name. We need to invent another good name. * class.c: use RCLASS_SET_ORIGIN(). * class.c (class_alloc): zero clear rb_classext_t. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49931 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/gc.c b/gc.c
index 10b74b0cae..12721df6ae 100644
--- a/gc.c
+++ b/gc.c
@@ -1882,7 +1882,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case T_MODULE:
case T_CLASS:
rb_free_m_tbl(RCLASS_M_TBL(obj));
-
if (RCLASS_IV_TBL(obj)) {
st_free_table(RCLASS_IV_TBL(obj));
}
@@ -1974,7 +1973,10 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case T_COMPLEX:
break;
case T_ICLASS:
- /* iClass shares table with the module */
+ /* Basically , T_ICLASS shares table with the module */
+ if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
+ rb_free_m_tbl(RCLASS_M_TBL(obj));
+ }
if (RCLASS_EXT(obj)->subclasses) {
rb_class_detach_subclasses(obj);
RCLASS_EXT(obj)->subclasses = NULL;
@@ -2874,6 +2876,13 @@ obj_memsize_of(VALUE obj, int use_all_types)
size += sizeof(rb_classext_t);
}
break;
+ case T_ICLASS:
+ if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
+ if (RCLASS_M_TBL(obj)) {
+ size += st_memsize(RCLASS_M_TBL(obj));
+ }
+ }
+ break;
case T_STRING:
size += rb_str_memsize(obj);
break;
@@ -2909,9 +2918,6 @@ obj_memsize_of(VALUE obj, int use_all_types)
case T_RATIONAL:
case T_COMPLEX:
break;
- case T_ICLASS:
- /* iClass shares table with the module */
- break;
case T_FLOAT:
case T_SYMBOL:
@@ -4135,15 +4141,21 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
switch (BUILTIN_TYPE(obj)) {
case T_CLASS:
case T_MODULE:
- if (!RCLASS_EXT(obj)) break;
- mark_m_tbl(objspace, RCLASS_M_TBL(RCLASS_ORIGIN(obj)));
- case T_ICLASS:
+ mark_m_tbl(objspace, RCLASS_M_TBL(obj));
if (!RCLASS_EXT(obj)) break;
mark_tbl(objspace, RCLASS_IV_TBL(obj));
mark_const_tbl(objspace, RCLASS_CONST_TBL(obj));
gc_mark(objspace, RCLASS_SUPER((VALUE)obj));
break;
+ case T_ICLASS:
+ if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
+ mark_m_tbl(objspace, RCLASS_M_TBL(obj));
+ }
+ if (!RCLASS_EXT(obj)) break;
+ gc_mark(objspace, RCLASS_SUPER((VALUE)obj));
+ break;
+
case T_ARRAY:
if (FL_TEST(obj, ELTS_SHARED)) {
gc_mark(objspace, any->as.array.as.heap.aux.shared);