summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-07-13 09:30:23 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-07-13 09:30:23 +0000
commit321a2a0920a349bdccac0bb31e3f1ca0126acdd3 (patch)
tree4a46ed32d9918e8fdbf3d63cdda79a6526032b5b
parent2b1ca5addb362954f5009995b37147e95d5a328f (diff)
downloadruby-321a2a0920a349bdccac0bb31e3f1ca0126acdd3.tar.gz
ruby-321a2a0920a349bdccac0bb31e3f1ca0126acdd3.tar.xz
ruby-321a2a0920a349bdccac0bb31e3f1ca0126acdd3.zip
* vm_core.h, compile.c: declare struct iseq_inline_cache_entry.
Inline cache (IC) entries are no longer GC managed object. IC entries are freed when ISeq is freed. * iseq.c: fix mark, free, memsize functions for above change. * insns.def: remove rb_gc_write_barrier(). * vm_insnhelper.c (vm_method_search): ditto. * tool/instruction.rb, template/insns_info.inc.tmpl (insn_iclen): added. git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@24085 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog15
-rw-r--r--compile.c27
-rw-r--r--insns.def2
-rw-r--r--iseq.c12
-rw-r--r--template/insns_info.inc.tmpl12
-rw-r--r--tool/instruction.rb8
-rw-r--r--vm_core.h24
-rw-r--r--vm_insnhelper.c10
8 files changed, 83 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 2e4ca09db..b40e7e135 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Mon Jul 13 17:49:11 2009 Koichi Sasada <ko1@atdot.net>
+
+ * vm_core.h, compile.c: declare struct iseq_inline_cache_entry.
+ Inline cache (IC) entries are no longer GC managed object.
+ IC entries are freed when ISeq is freed.
+
+ * iseq.c: fix mark, free, memsize functions for above change.
+
+ * insns.def: remove rb_gc_write_barrier().
+
+ * vm_insnhelper.c (vm_method_search): ditto.
+
+ * tool/instruction.rb, template/insns_info.inc.tmpl (insn_iclen):
+ added.
+
Mon Jul 13 13:35:08 2009 Koichi Sasada <ko1@atdot.net>
* insns.def, vm_insnhelper.c (getinstancevariable):
diff --git a/compile.c b/compile.c
index 57d58d2d6..6198f077b 100644
--- a/compile.c
+++ b/compile.c
@@ -12,6 +12,7 @@
#include "ruby/ruby.h"
#define USE_INSN_STACK_INCREASE 1
+#define USE_INSN_ICLEN 1
#include "vm_core.h"
#include "iseq.h"
#include "insns.inc"
@@ -1260,6 +1261,8 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
struct iseq_insn_info_entry *insn_info_table;
LINK_ELEMENT *list;
VALUE *generated_iseq;
+ int ic_size = 0;
+ int ic_index = 0;
int k, pos, sp, stack_max = 0, line = 0;
@@ -1273,6 +1276,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
iobj = (INSN *)list;
line = iobj->line_no;
pos += insn_data_length(iobj);
+ ic_size += insn_iclen(iobj->insn_id);
k++;
break;
}
@@ -1310,6 +1314,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
/* make instruction sequence */
generated_iseq = ALLOC_N(VALUE, pos);
insn_info_table = ALLOC_N(struct iseq_insn_info_entry, k);
+ iseq->ic_entries = ALLOC_N(struct iseq_inline_cache_entry, ic_size);
+ MEMZERO(iseq->ic_entries, struct iseq_inline_cache_entry, ic_size);
+ iseq->ic_size = ic_size;
list = FIRST_ELEMENT(anchor);
k = pos = sp = 0;
@@ -1318,7 +1325,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
switch (list->type) {
case ISEQ_ELEMENT_INSN:
{
- int j, len, insn, iclen = 0, i;
+ int j, len, insn, iclen = 0;
const char *types;
VALUE *operands;
@@ -1337,12 +1344,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
generated_iseq[pos] = insn;
types = insn_op_types(insn);
len = insn_len(insn);
-
- for (i=0; i<len; i++) {
- if (types[i] == TS_IC) {
- iclen++;
- }
- }
+ iclen = insn_iclen(insn);
/* operand check */
if (iobj->operand_size + iclen != len - 1) {
@@ -1432,9 +1434,12 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
}
case TS_IC: /* inline cache */
{
- VALUE v = (VALUE)NEW_INLINE_CACHE_ENTRY();
- generated_iseq[pos + 1 + j] = v;
- iseq_add_mark_object(iseq, v);
+ IC ic = &iseq->ic_entries[ic_index++];
+ if (UNLIKELY(ic_index > ic_size)) {
+ rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d",
+ ic_index, ic_size);
+ }
+ generated_iseq[pos + 1 + j] = (VALUE)ic;
break;
}
case TS_ID: /* ID */
@@ -5241,8 +5246,6 @@ iseq_build_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor,
argv[j] = (VALUE)rb_global_entry(SYM2ID(op));
break;
case TS_IC:
- argv[j] = (VALUE)NEW_INLINE_CACHE_ENTRY();
- iseq_add_mark_object(iseq, argv[j]);
break;
case TS_ID:
argv[j] = rb_convert_type(op, T_SYMBOL,
diff --git a/insns.def b/insns.def
index d7a06f6a1..7ce5b920a 100644
--- a/insns.def
+++ b/insns.def
@@ -1223,7 +1223,7 @@ setinlinecache
{
IC ic = GET_CONST_INLINE_CACHE(dst);
- ic->ic_value = rb_gc_write_barrier(val);
+ ic->ic_value = val;
ic->ic_vmstat = GET_VM_STATE_VERSION() - ruby_vm_const_missing_count;
ruby_vm_const_missing_count = 0;
}
diff --git a/iseq.c b/iseq.c
index b01874b98..711712a4d 100644
--- a/iseq.c
+++ b/iseq.c
@@ -74,6 +74,7 @@ iseq_free(void *ptr)
RUBY_FREE_UNLESS_NULL(iseq->iseq);
RUBY_FREE_UNLESS_NULL(iseq->insn_info_table);
RUBY_FREE_UNLESS_NULL(iseq->local_table);
+ RUBY_FREE_UNLESS_NULL(iseq->ic_entries);
RUBY_FREE_UNLESS_NULL(iseq->catch_table);
RUBY_FREE_UNLESS_NULL(iseq->arg_opt_table);
compile_data_free(iseq->compile_data);
@@ -86,11 +87,12 @@ iseq_free(void *ptr)
static void
iseq_mark(void *ptr)
{
- rb_iseq_t *iseq;
RUBY_MARK_ENTER("iseq");
if (ptr) {
- iseq = ptr;
+ int i;
+ rb_iseq_t *iseq = ptr;
+
RUBY_GC_INFO("%s @ %s\n", RSTRING_PTR(iseq->name), RSTRING_PTR(iseq->filename));
RUBY_MARK_UNLESS_NULL(iseq->mark_ary);
RUBY_MARK_UNLESS_NULL(iseq->name);
@@ -102,6 +104,11 @@ iseq_mark(void *ptr)
/* RUBY_MARK_UNLESS_NULL(iseq->cached_special_block); */
RUBY_MARK_UNLESS_NULL(iseq->orig);
+ for (i=0; i<iseq->ic_size; i++) {
+ RUBY_MARK_UNLESS_NULL(iseq->ic_entries[i].ic_class);
+ RUBY_MARK_UNLESS_NULL(iseq->ic_entries[i].ic_value);
+ }
+
if (iseq->compile_data != 0) {
RUBY_MARK_UNLESS_NULL(iseq->compile_data->mark_ary);
RUBY_MARK_UNLESS_NULL(iseq->compile_data->err_info);
@@ -129,6 +136,7 @@ iseq_memsize(void *ptr)
size += iseq->local_table_size * sizeof(ID);
size += iseq->catch_table_size * sizeof(struct iseq_catch_table_entry);
size += iseq->arg_opts * sizeof(VALUE);
+ size += iseq->ic_size * sizeof(struct iseq_inline_cache_entry);
if (iseq->compile_data) {
struct iseq_compile_data_storage *cur;
diff --git a/template/insns_info.inc.tmpl b/template/insns_info.inc.tmpl
index d901c6825..1093e10d0 100644
--- a/template/insns_info.inc.tmpl
+++ b/template/insns_info.inc.tmpl
@@ -23,6 +23,10 @@ static const int insn_len_info[] = {
<%= operands_num_info %>
};
+static const int insn_iclen_info[] = {
+<%= icoperands_num_info %>
+};
+
#ifdef USE_INSN_RET_NUM
static const int insn_stack_push_num_info[] = {
<%= stack_num_info %>
@@ -81,3 +85,11 @@ insn_ret_num(int insn)
return insn_stack_push_num_info[insn];
}
#endif
+
+#ifdef USE_INSN_ICLEN
+static int
+insn_iclen(int insn)
+{
+ return insn_iclen_info[insn];
+}
+#endif
diff --git a/tool/instruction.rb b/tool/instruction.rb
index 4e60f04f6..8d55683da 100644
--- a/tool/instruction.rb
+++ b/tool/instruction.rb
@@ -977,6 +977,8 @@ class RubyVM
# operands info
operands_info = ''
operands_num_info = ''
+ icoperands_num_info = ''
+
@insns.each{|insn|
opes = insn.opes
operands_info << ' '
@@ -987,6 +989,12 @@ class RubyVM
num = opes.size + 1
operands_num_info << " #{num},\n"
+
+ icnum = 0
+ opes.each{|e|
+ icnum += 1 if e[0] == 'IC'
+ }
+ icoperands_num_info << " #{icnum},\n"
}
# stack num
diff --git a/vm_core.h b/vm_core.h
index 8019e63a2..799ac52b8 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -106,6 +106,18 @@ typedef struct rb_compile_option_struct {
int debug_level;
} rb_compile_option_t;
+struct iseq_inline_cache_entry {
+ long ic_vmstat;
+ VALUE ic_class;
+ union {
+ NODE *method;
+ VALUE value;
+ } value;
+#define ic_value value.value
+#define ic_method value.method
+#define ic_index ic_vmstat
+};
+
#if 1
#define GetCoreDataFromValue(obj, type, ptr) do { \
ptr = (type*)DATA_PTR(obj); \
@@ -143,6 +155,9 @@ struct rb_iseq_struct {
/* method, class frame: sizeof(vars) + 1, block frame: sizeof(vars) */
int local_size;
+ struct iseq_inline_cache_entry *ic_entries;
+ int ic_size;
+
/**
* argument information
*
@@ -522,13 +537,8 @@ typedef struct {
(VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
-/* inline (method|const) cache */
-#define NEW_INLINE_CACHE_ENTRY() NEW_NODE_LONGLIFE(NODE_WHILE, Qundef, 0, 0)
-#define ic_class u1.value
-#define ic_method u2.node
-#define ic_value u2.value
-#define ic_vmstat u3.value
-typedef NODE *IC;
+/* inline cache */
+typedef struct iseq_inline_cache_entry *IC;
void rb_vm_change_state(void);
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index de53d533b..ac2405442 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1180,7 +1180,7 @@ vm_getivar(VALUE obj, ID id, IC ic)
VALUE klass = RBASIC(obj)->klass;
if (ic->ic_class == klass) {
- long index = ic->ic_vmstat;
+ long index = ic->ic_index;
long len = ROBJECT_NUMIV(obj);
VALUE *ptr = ROBJECT_IVPTR(obj);
@@ -1199,8 +1199,8 @@ vm_getivar(VALUE obj, ID id, IC ic)
if (index < len) {
val = ptr[index];
}
- ic->ic_class = CLASS_OF(obj);
- ic->ic_vmstat = index;
+ ic->ic_class = RBASIC(obj)->klass;
+ ic->ic_index = index;
}
}
}
@@ -1231,8 +1231,8 @@ vm_method_search(VALUE id, VALUE klass, IC ic)
}
else {
mn = rb_method_node(klass, id);
- ic->ic_class = rb_gc_write_barrier(klass);
- ic->ic_method = (NODE *)rb_gc_write_barrier((VALUE)mn);
+ ic->ic_class = klass;
+ ic->ic_method = mn;
ic->ic_vmstat = GET_VM_STATE_VERSION();
}
}