[前][次][番号順一覧][スレッド一覧]

ruby-changes:40881

From: nobu <ko1@a...>
Date: Tue, 8 Dec 2015 23:51:02 +0900 (JST)
Subject: [ruby-changes:40881] nobu:r52960 (trunk): free ibf_dump at exception

nobu	2015-12-08 23:50:55 +0900 (Tue, 08 Dec 2015)

  New Revision: 52960

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=52960

  Log:
    free ibf_dump at exception
    
    * compile.c (iseq_ibf_dump): wrap ibf_dump to free tables at
      exception.

  Modified files:
    trunk/compile.c
Index: compile.c
===================================================================
--- compile.c	(revision 52959)
+++ compile.c	(revision 52960)
@@ -8026,19 +8026,66 @@ ibf_dump_object_list(struct ibf_dump *du https://github.com/ruby/ruby/blob/trunk/compile.c#L8026
     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_dump *)ptr;
+    rb_gc_mark(dump->str);
+    rb_gc_mark(dump->iseq_list);
+    rb_gc_mark(dump->obj_list);
+}
+
+static void
+ibf_dump_free(void *ptr)
 {
-    struct ibf_dump dump;
-    struct ibf_header header;
+    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);
+}
 
-    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 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;
+}
 
-    ibf_table_index(dump.id_table, 0); /* id_index:0 is 0 */
+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, VAL https://github.com/ruby/ruby/blob/trunk/compile.c#L8095
 	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, VAL https://github.com/ruby/ruby/blob/trunk/compile.c#L8108
     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 *

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]