ruby-changes:39466
From: normal <ko1@a...>
Date: Wed, 12 Aug 2015 21:19:07 +0900 (JST)
Subject: [ruby-changes:39466] normal:r51547 (trunk): iseq.c (iseq_memsize): reimplement for wrapper
normal 2015-08-12 21:18:51 +0900 (Wed, 12 Aug 2015) New Revision: 51547 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=51547 Log: iseq.c (iseq_memsize): reimplement for wrapper * iseq.c (iseq_memsize): reimplement for wrapper (param_keyword_size): extracted from iseq_memsize (iseqw_mark): new mark function (iseqw_data_type): new data type (iseqw_new): wrap as iseqw_data_type (iseqw_check): adjust for wrapper (Init_ISeq): remove iseqw_iseq_key initialization * test/objspace/test_objspace.rb: new test [ruby-core:70344] [Feature #11435] v2 changes: - added RUBY_TYPED_WB_PROTECTED and write barrier - account for rb_call_info_kw_arg_t entries Modified files: trunk/ChangeLog trunk/iseq.c trunk/test/objspace/test_objspace.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 51546) +++ ChangeLog (revision 51547) @@ -1,3 +1,15 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Wed Aug 12 21:17:38 2015 Eric Wong <e@8...> + + * iseq.c (iseq_memsize): reimplement for wrapper + (param_keyword_size): extracted from iseq_memsize + (iseqw_mark): new mark function + (iseqw_data_type): new data type + (iseqw_new): wrap as iseqw_data_type + (iseqw_check): adjust for wrapper + (Init_ISeq): remove iseqw_iseq_key initialization + * test/objspace/test_objspace.rb: new test + [ruby-core:70344] [Feature #11435] + Wed Aug 12 21:15:27 2015 Eric Wong <e@8...> * vm_core.h (rb_call_info_kw_arg_bytes): extract from compile.c Index: iseq.c =================================================================== --- iseq.c (revision 51546) +++ iseq.c (revision 51547) @@ -29,7 +29,6 @@ https://github.com/ruby/ruby/blob/trunk/iseq.c#L29 #define ISEQ_MINOR_VERSION 2 VALUE rb_cISeq; -ID iseqw_iseq_key; #define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass) @@ -130,47 +129,81 @@ rb_iseq_mark(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L129 RUBY_MARK_LEAVE("iseq"); } -#if 0 /* TODO */ static size_t -iseq_memsize(const void *ptr) +param_keyword_size(const struct rb_iseq_param_keyword *pkw) { - size_t size = sizeof(rb_iseq_t); + size_t size = 0; - if (ptr) { - const rb_iseq_t *iseq = ptr; + if (!pkw) return size; - size += iseq->body->iseq_size * sizeof(VALUE); - size += iseq->body->line_info_size * sizeof(struct iseq_line_info_entry); - size += iseq->body->local_table_size * sizeof(ID); - if (iseq->body->catch_table) { - size += iseq_catch_table_bytes(iseq->body->catch_table->size); - } - size += (iseq->body->param.opt_num + 1) * sizeof(VALUE); - if (iseq->body->param.keyword != NULL) { - size += sizeof(struct rb_iseq_param_keyword); - size += sizeof(VALUE) * (iseq->body->param.keyword->num - iseq->body->param.keyword->required_num); + size += sizeof(struct rb_iseq_param_keyword); + size += sizeof(VALUE) * (pkw->num - pkw->required_num); + + return size; +} + +static size_t +iseq_memsize(const void *ptr) +{ + const rb_iseq_t *iseq = ptr; + size_t size = 0; /* struct already counted as RVALUE size */ + const struct rb_iseq_variable_body *variable_body; + const struct rb_iseq_constant_body *body; + const struct iseq_compile_data *compile_data; + + variable_body = iseq->variable_body; + body = iseq->body; + + if (variable_body) { + size += sizeof(struct rb_iseq_variable_body); + if (variable_body->iseq && body) { + size += body->iseq_size * sizeof(VALUE); } - size += iseq->body->is_size * sizeof(union iseq_inline_storage_entry); - size += iseq->body->callinfo_size * sizeof(rb_call_info_t); + } + + if (body) { + rb_call_info_t *ci_entries = body->callinfo_entries; + + size += sizeof(struct rb_iseq_constant_body); + size += body->iseq_size * sizeof(VALUE); + size += body->line_info_size * sizeof(struct iseq_line_info_entry); + size += body->local_table_size * sizeof(ID); + if (body->catch_table) { + size += iseq_catch_table_bytes(body->catch_table->size); + } + size += (body->param.opt_num + 1) * sizeof(VALUE); + size += param_keyword_size(body->param.keyword); + size += body->is_size * sizeof(union iseq_inline_storage_entry); + size += body->callinfo_size * sizeof(rb_call_info_t); + + if (ci_entries) { + unsigned int i; - if (iseq->compile_data) { - struct iseq_compile_data_storage *cur; + for (i = 0; i < body->callinfo_size; i++) { + const rb_call_info_kw_arg_t *kw_arg = ci_entries[i].kw_arg; - cur = iseq->compile_data->storage_head; - while (cur) { - size += cur->size + SIZEOF_ISEQ_COMPILE_DATA_STORAGE; - cur = cur->next; + if (kw_arg) { + size += rb_call_info_kw_arg_bytes(kw_arg->keyword_len); + } } - size += sizeof(struct iseq_compile_data); } - if (iseq->body->iseq) { - size += iseq->body->iseq_size * sizeof(VALUE); + } + + compile_data = iseq->compile_data; + if (compile_data) { + struct iseq_compile_data_storage *cur; + + size += sizeof(struct iseq_compile_data); + + cur = compile_data->storage_head; + while (cur) { + size += cur->size + SIZEOF_ISEQ_COMPILE_DATA_STORAGE; + cur = cur->next; } } return size; } -#endif static rb_iseq_t * iseq_alloc(void) @@ -639,12 +672,29 @@ rb_iseq_method_name(const rb_iseq_t *ise https://github.com/ruby/ruby/blob/trunk/iseq.c#L672 /* define wrapper class methods (RubyVM::InstructionSequence) */ +static void +iseqw_mark(void *ptr) +{ + rb_gc_mark((VALUE)ptr); +} + +static const rb_data_type_t iseqw_data_type = { + "T_IMEMO/iseq", + {iseqw_mark, NULL, iseq_memsize,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED +}; + static VALUE iseqw_new(const rb_iseq_t *iseq) { - VALUE iseqw = rb_obj_alloc(rb_cISeq); - rb_ivar_set(iseqw, iseqw_iseq_key, (VALUE)iseq); - return iseqw; + union { const rb_iseq_t *in; void *out; } deconst; + VALUE obj; + + deconst.in = iseq; + obj = TypedData_Wrap_Struct(rb_cISeq, &iseqw_data_type, deconst.out); + RB_OBJ_WRITTEN(obj, Qundef, iseq); + + return obj; } VALUE @@ -795,7 +845,7 @@ iseqw_s_compile_option_get(VALUE self) https://github.com/ruby/ruby/blob/trunk/iseq.c#L845 static const rb_iseq_t * iseqw_check(VALUE iseqw) { - const rb_iseq_t *iseq = (rb_iseq_t *)rb_ivar_get(iseqw, iseqw_iseq_key); + const rb_iseq_t *iseq = DATA_PTR(iseqw); if (!iseq->body->location.label) { rb_raise(rb_eTypeError, "uninitialized InstructionSequence"); @@ -2282,6 +2332,4 @@ Init_ISeq(void) https://github.com/ruby/ruby/blob/trunk/iseq.c#L2332 rb_define_singleton_method(rb_cISeq, "disasm", iseqw_s_disasm, 1); rb_define_singleton_method(rb_cISeq, "disassemble", iseqw_s_disasm, 1); rb_define_singleton_method(rb_cISeq, "of", iseqw_s_of, 1); - - iseqw_iseq_key = rb_intern("T_IMEMO/iseq"); } Index: test/objspace/test_objspace.rb =================================================================== --- test/objspace/test_objspace.rb (revision 51546) +++ test/objspace/test_objspace.rb (revision 51547) @@ -88,6 +88,12 @@ class TestObjSpace < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/objspace/test_objspace.rb#L88 assert_not_empty(res) end + def test_memsize_of_iseq + iseqw = RubyVM::InstructionSequence.compile('def a; a = :b; end') + base_obj_size = ObjectSpace.memsize_of(Object.new) + assert_operator(ObjectSpace.memsize_of(iseqw), :>, base_obj_size) + end + def test_reachable_objects_from assert_separately %w[--disable-gem -robjspace], __FILE__, __LINE__, <<-'eom' assert_equal(nil, ObjectSpace.reachable_objects_from(nil)) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/