summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-08 14:50:55 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-08 14:50:55 +0000
commit2c3f0749c56a1a094ca7be12e669f0d1545bb756 (patch)
treec7a71723ebc04dca49bddaec2fe51129a8b99ee3
parentc01f1655be6aa6dfd4de838bcf7af6400684533a (diff)
free ibf_dump at exception
* compile.c (iseq_ibf_dump): wrap ibf_dump to free tables at exception. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52960 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--compile.c97
1 files changed, 74 insertions, 23 deletions
diff --git a/compile.c b/compile.c
index 3dbed3829c5..bbdfcf8e49a 100644
--- a/compile.c
+++ b/compile.c
@@ -8026,19 +8026,66 @@ ibf_dump_object_list(struct ibf_dump *dump, struct ibf_header *header)
header->object_list_size = size;
}
-VALUE
-iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
+static void
+ibf_dump_mark(void *ptr)
{
- struct ibf_dump dump;
- struct ibf_header header;
+ struct ibf_dump *dump = (struct ibf_dump *)ptr;
+ rb_gc_mark(dump->str);
+ rb_gc_mark(dump->iseq_list);
+ rb_gc_mark(dump->obj_list);
+}
- dump.str = rb_str_new(0, 0);
- dump.iseq_list = rb_ary_tmp_new(0);
- dump.obj_list = rb_ary_tmp_new(1); rb_ary_push(dump.obj_list, Qnil); /* 0th is nil */
- dump.iseq_table = st_init_numtable(); /* need free */
- dump.id_table = st_init_numtable(); /* need free */
+static void
+ibf_dump_free(void *ptr)
+{
+ struct ibf_dump *dump = (struct ibf_dump *)ptr;
+ if (dump->iseq_table) {
+ st_free_table(dump->iseq_table);
+ dump->iseq_table = 0;
+ }
+ if (dump->id_table) {
+ st_free_table(dump->id_table);
+ dump->id_table = 0;
+ }
+ ruby_xfree(dump);
+}
- ibf_table_index(dump.id_table, 0); /* id_index:0 is 0 */
+static size_t
+ibf_dump_memsize(const void *ptr)
+{
+ struct ibf_dump *dump = (struct ibf_dump *)ptr;
+ size_t size = sizeof(*dump);
+ if (dump->iseq_table) size += st_memsize(dump->iseq_table);
+ if (dump->id_table) size += st_memsize(dump->id_table);
+ return size;
+}
+
+static const rb_data_type_t ibf_dump_type = {
+ "ibf_dump",
+ {ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,},
+ 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static void
+ibf_dump_setup(struct ibf_dump *dump, VALUE dumper_obj)
+{
+ RB_OBJ_WRITE(dumper_obj, &dump->str, rb_str_new(0, 0));
+ RB_OBJ_WRITE(dumper_obj, &dump->iseq_list, rb_ary_tmp_new(0));
+ RB_OBJ_WRITE(dumper_obj, &dump->obj_list, rb_ary_tmp_new(1));
+ rb_ary_push(dump->obj_list, Qnil); /* 0th is nil */
+ dump->iseq_table = st_init_numtable(); /* need free */
+ dump->id_table = st_init_numtable(); /* need free */
+
+ ibf_table_index(dump->id_table, 0); /* id_index:0 is 0 */
+}
+
+VALUE
+iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
+{
+ struct ibf_dump *dump;
+ struct ibf_header header = {{0}};
+ VALUE dump_obj;
+ VALUE str;
if (iseq->body->parent_iseq != NULL ||
iseq->body->local_iseq != iseq) {
@@ -8048,9 +8095,12 @@ iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
rb_raise(rb_eRuntimeError, "should not compile with coverage");
}
- ibf_dump_write(&dump, &header, sizeof(header));
- ibf_dump_write(&dump, RUBY_PLATFORM, strlen(RUBY_PLATFORM) + 1);
- ibf_dump_iseq(&dump, iseq);
+ dump_obj = TypedData_Make_Struct(0, struct ibf_dump, &ibf_dump_type, dump);
+ ibf_dump_setup(dump, dump_obj);
+
+ ibf_dump_write(dump, &header, sizeof(header));
+ ibf_dump_write(dump, RUBY_PLATFORM, strlen(RUBY_PLATFORM) + 1);
+ ibf_dump_iseq(dump, iseq);
header.magic[0] = 'Y'; /* YARB */
header.magic[1] = 'A';
@@ -8058,27 +8108,28 @@ iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt)
header.magic[3] = 'B';
header.major_version = ISEQ_MAJOR_VERSION;
header.minor_version = ISEQ_MINOR_VERSION;
- ibf_dump_iseq_list(&dump, &header);
- ibf_dump_id_list(&dump, &header);
- ibf_dump_object_list(&dump, &header);
- header.size = ibf_dump_pos(&dump);
+ ibf_dump_iseq_list(dump, &header);
+ ibf_dump_id_list(dump, &header);
+ ibf_dump_object_list(dump, &header);
+ header.size = ibf_dump_pos(dump);
if (RTEST(opt)) {
VALUE opt_str = opt;
const char *ptr = StringValuePtr(opt_str);
header.extra_size = RSTRING_LENINT(opt_str) + 1;
- ibf_dump_write(&dump, ptr, header.extra_size);
+ ibf_dump_write(dump, ptr, header.extra_size);
}
else {
header.extra_size = 0;
}
- ibf_dump_overwrite(&dump, &header, sizeof(header), 0);
+ ibf_dump_overwrite(dump, &header, sizeof(header), 0);
- /* release. TODO: no need to care exceptions? */
- st_free_table(dump.iseq_table);
- st_free_table(dump.id_table);
- return dump.str;
+ str = dump->str;
+ ibf_dump_free(dump);
+ DATA_PTR(dump_obj) = NULL;
+ RB_GC_GUARD(dump_obj);
+ return str;
}
static const ibf_offset_t *