dumping ground for random patches and texts
 help / color / mirror / Atom feed
* [PATCH 1/2] hoist out rb_call_info_kw_arg_bytes to inline function
@ 2015-08-12 12:14 Eric Wong
  2015-08-12 12:14 ` [PATCH 2/2] iseq.c (iseq_memsize): reimplement for wrapper Eric Wong
  0 siblings, 1 reply; 2+ messages in thread
From: Eric Wong @ 2015-08-12 12:14 UTC (permalink / raw)
  To: spew

* vm_core.h (rb_call_info_kw_arg_bytes): extract from below
* compile.c (iseq_build_callinfo_from_hash): use above

This will be use for implementing iseq_memsize
---
 compile.c | 2 +-
 vm_core.h | 6 ++++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/compile.c b/compile.c
index 637f56f..26ee3b2 100644
--- a/compile.c
+++ b/compile.c
@@ -5917,7 +5917,7 @@ iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op)
 	if (!NIL_P(vkw_arg)) {
 	    int i;
 	    int len = RARRAY_LENINT(vkw_arg);
-	    size_t n = sizeof(rb_call_info_kw_arg_t) + sizeof(VALUE) * (len - 1);
+	    size_t n = rb_call_info_kw_arg_bytes(len);
 
 	    kw_arg = xmalloc(n);
 	    kw_arg->keyword_len = len;
diff --git a/vm_core.h b/vm_core.h
index a032daa..6745837 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -180,6 +180,12 @@ typedef struct rb_call_info_kw_arg_struct {
     VALUE keywords[1];
 } rb_call_info_kw_arg_t;
 
+static inline size_t
+rb_call_info_kw_arg_bytes(int keyword_len)
+{
+    return sizeof(rb_call_info_kw_arg_t) + sizeof(VALUE) * (keyword_len - 1);
+}
+
 enum method_missing_reason {
     MISSING_NOENTRY   = 0x00,
     MISSING_PRIVATE   = 0x01,
-- 
EW


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH 2/2] iseq.c (iseq_memsize): reimplement for wrapper
  2015-08-12 12:14 [PATCH 1/2] hoist out rb_call_info_kw_arg_bytes to inline function Eric Wong
@ 2015-08-12 12:14 ` Eric Wong
  0 siblings, 0 replies; 2+ messages in thread
From: Eric Wong @ 2015-08-12 12:14 UTC (permalink / raw)
  To: spew

* 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
---
 iseq.c                         | 112 +++++++++++++++++++++++++++++------------
 test/objspace/test_objspace.rb |   6 +++
 2 files changed, 86 insertions(+), 32 deletions(-)

diff --git a/iseq.c b/iseq.c
index bc1d60b..e9b84a1 100644
--- a/iseq.c
+++ b/iseq.c
@@ -29,7 +29,6 @@
 #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)
     RUBY_MARK_LEAVE("iseq");
 }
 
-#if 0 /* TODO */
+static size_t
+param_keyword_size(const struct rb_iseq_param_keyword *pkw)
+{
+    size_t size = 0;
+
+    if (!pkw) return size;
+
+    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)
 {
-    size_t size = sizeof(rb_iseq_t);
+    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;
 
-    if (ptr) {
-	const rb_iseq_t *iseq = ptr;
+    variable_body = iseq->variable_body;
+    body = iseq->body;
 
-	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);
+    if (variable_body) {
+	size += sizeof(struct rb_iseq_variable_body);
+	if (variable_body->iseq && body) {
+	    size += body->iseq_size * sizeof(VALUE);
 	}
-	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);
+    }
+
+    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 += iseq->body->is_size * sizeof(union iseq_inline_storage_entry);
-	size += iseq->body->callinfo_size * sizeof(rb_call_info_t);
+	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 *iseq)
 
 /* 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)
 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)
     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");
 }
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 01f31cc..3036b87 100644
--- a/test/objspace/test_objspace.rb
+++ b/test/objspace/test_objspace.rb
@@ -88,6 +88,12 @@ class TestObjSpace < Test::Unit::TestCase
     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))
-- 
EW


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-08-12 12:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-12 12:14 [PATCH 1/2] hoist out rb_call_info_kw_arg_bytes to inline function Eric Wong
2015-08-12 12:14 ` [PATCH 2/2] iseq.c (iseq_memsize): reimplement for wrapper Eric Wong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).