diff --git a/ChangeLog b/ChangeLog index 2e4ca09db4..b40e7e135e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +Mon Jul 13 17:49:11 2009 Koichi Sasada + + * 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 * insns.def, vm_insnhelper.c (getinstancevariable): diff --git a/compile.c b/compile.c index 57d58d2d63..6198f077b6 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; ioperand_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 d7a06f6a12..7ce5b920a4 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 b01874b98f..711712a4db 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; iic_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 d901c68257..1093e10d0a 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 4e60f04f62..8d55683da3 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 8019e63a27..799ac52b89 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 de53d533b8..ac2405442b 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(); } }