diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-03-11 09:15:20 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-03-11 09:15:20 +0000 |
commit | 5922c954614e5947a548780bb3b894626affe6dd (patch) | |
tree | c7de7025f8d3dbeb816aa99cd197e5adba33815e /gc.c | |
parent | 5a62fdee4d166fe0eff14bc616e1befa8ad54cd2 (diff) | |
download | ruby-5922c954614e5947a548780bb3b894626affe6dd.tar.gz |
* 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.c | 28 |
1 files changed, 20 insertions, 8 deletions
@@ -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); |