diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | compile.c | 32 | ||||
-rw-r--r-- | insns.def | 50 | ||||
-rwxr-xr-x | tool/instruction.rb | 10 | ||||
-rw-r--r-- | vm_core.h | 19 | ||||
-rw-r--r-- | vm_insnhelper.c | 28 | ||||
-rw-r--r-- | vm_insnhelper.h | 2 |
7 files changed, 107 insertions, 51 deletions
@@ -1,3 +1,20 @@ +Tue Oct 9 14:28:18 2012 Koichi Sasada <ko1@atdot.net> + + * vm_core.h (rb_call_info_t): add new type `rb_call_inf_t'. + This data structure contains information including inline method + cache. After that, `struct iseq_inline_cache_entry' does not + need to contain inline cache for method invocation. + Other information will be added to this data structure. + + * vm_core.h (rb_iseq_t): add `callinfo_entries' and `callinfo_size' + members to `rb_iseq_t'. + + * insns.def, compile.c: Use CALL_INFO instead of IC. + + * tool/instruction.rb: support CALL_INFO as operand type. + + * vm_insnhelper.c, vm_insnhelper.h: ditto. + Sun Oct 7 23:54:33 2012 CHIKANAGA Tomoyuki <nagachika@ruby-lang.org> * ext/zlib/zlib.c (zstream_run_func): don't call inflate() when @@ -946,7 +946,7 @@ new_insn_send(rb_iseq_t *iseq, int line_no, operands[1] = argc; operands[2] = block; operands[3] = flag; - operands[4] = INT2FIX(iseq->ic_size++); + operands[4] = INT2FIX(iseq->callinfo_size++); iobj = new_insn_core(iseq, line_no, BIN(send), 5, operands); return iobj; } @@ -1398,6 +1398,8 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) line_info_table = ALLOC_N(struct iseq_line_info_entry, k); iseq->ic_entries = ALLOC_N(struct iseq_inline_cache_entry, iseq->ic_size); MEMZERO(iseq->ic_entries, struct iseq_inline_cache_entry, iseq->ic_size); + iseq->callinfo_entries = ALLOC_N(rb_call_info_t, iseq->callinfo_size); + MEMZERO(iseq->callinfo_entries, rb_call_info_t, iseq->callinfo_size); list = FIRST_ELEMENT(anchor); k = pos = sp = 0; @@ -1495,12 +1497,21 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) int ic_index = FIX2INT(operands[j]); IC ic = &iseq->ic_entries[ic_index]; if (UNLIKELY(ic_index >= iseq->ic_size)) { - rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", - ic_index, iseq->ic_size); + rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->ic_size); } generated_iseq[pos + 1 + j] = (VALUE)ic; break; } + case TS_CALLINFO: /* call info */ + { + int ci_index = FIX2INT(operands[j]); + CALL_INFO ci = &iseq->callinfo_entries[ci_index]; + if (UNLIKELY(ci_index >= iseq->callinfo_size)) { + rb_bug("iseq_set_sequence: ci_index overflow: index: %d, size: %d", ci_index, iseq->callinfo_size); + } + generated_iseq[pos + 1 + j] = (VALUE)ci; + break; + } case TS_ID: /* ID */ generated_iseq[pos + 1 + j] = SYM2ID(operands[j]); break; @@ -1859,7 +1870,7 @@ insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id) } for (i=0; i<iobj->operand_size; i++) { - iobj->operands[i] = INT2FIX(iseq->ic_size++); + iobj->operands[i] = INT2FIX(iseq->callinfo_size++); } return COMPILE_OK; @@ -5234,9 +5245,12 @@ insn_data_to_s_detail(INSN *iobj) (OPERAND_AT(iobj, j) & (~1)); rb_str_cat2(str, rb_id2name(entry->id)); } - case TS_IC: /* method cache */ + case TS_IC: /* inline cache */ rb_str_catf(str, "<ic:%d>", FIX2INT(OPERAND_AT(iobj, j))); break; + case TS_CALLINFO: /* call info */ + rb_str_catf(str, "<callinfo:%d>", FIX2INT(OPERAND_AT(iobj, j))); + break; case TS_CDHASH: /* case/when condition cache */ rb_str_cat2(str, "<ch>"); break; @@ -5500,9 +5514,15 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, break; case TS_IC: argv[j] = op; - if (NUM2INT(op) >= iseq->ic_size) + if (NUM2INT(op) >= iseq->ic_size) { iseq->ic_size = NUM2INT(op) + 1; + } break; + case TS_CALLINFO: + argv[j] = op; + if (NUM2INT(op) >= iseq->callinfo_size) { + iseq->callinfo_size = NUM2INT(op) + 1; + } case TS_ID: argv[j] = rb_convert_type(op, T_SYMBOL, "Symbol", "to_sym"); @@ -963,7 +963,7 @@ defineclass */ DEFINE_INSN send -(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, IC ic) +(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, CALL_INFO ci) (...) (VALUE val) // inc += - (int)(op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0)); { @@ -978,7 +978,7 @@ send /* get receiver */ recv = TOPN(num); klass = CLASS_OF(recv); - me = vm_method_search(id, klass, ic, &defined_class); + me = vm_method_search(id, klass, ci, &defined_class); CALL_METHOD(num, blockptr, flag, id, me, recv, defined_class); } @@ -1286,7 +1286,7 @@ opt_case_dispatch */ DEFINE_INSN opt_plus -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1349,7 +1349,7 @@ opt_plus */ DEFINE_INSN opt_minus -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1397,7 +1397,7 @@ opt_minus */ DEFINE_INSN opt_mult -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1450,7 +1450,7 @@ opt_mult */ DEFINE_INSN opt_div -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1513,7 +1513,7 @@ opt_div */ DEFINE_INSN opt_mod -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1577,11 +1577,11 @@ opt_mod */ DEFINE_INSN opt_eq -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { - val = opt_eq_func(recv, obj, ic); + val = opt_eq_func(recv, obj, ci); if (val == Qundef) { /* other */ @@ -1598,16 +1598,16 @@ opt_eq */ DEFINE_INSN opt_neq -(IC ic, IC ic_eq) +(CALL_INFO ci, CALL_INFO ci_eq) (VALUE recv, VALUE obj) (VALUE val) { extern VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2); - const rb_method_entry_t *me = vm_method_search(idNeq, CLASS_OF(recv), ic, 0); + const rb_method_entry_t *me = vm_method_search(idNeq, CLASS_OF(recv), ci, 0); val = Qundef; if (check_cfunc(me, rb_obj_not_equal)) { - val = opt_eq_func(recv, obj, ic_eq); + val = opt_eq_func(recv, obj, ci_eq); if (val != Qundef) { val = RTEST(val) ? Qfalse : Qtrue; @@ -1629,7 +1629,7 @@ opt_neq */ DEFINE_INSN opt_lt -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1673,7 +1673,7 @@ opt_lt */ DEFINE_INSN opt_le -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1708,7 +1708,7 @@ opt_le */ DEFINE_INSN opt_gt -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1752,7 +1752,7 @@ opt_gt */ DEFINE_INSN opt_ge -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1786,7 +1786,7 @@ opt_ge */ DEFINE_INSN opt_ltlt -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1818,7 +1818,7 @@ opt_ltlt */ DEFINE_INSN opt_aref -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj) (VALUE val) { @@ -1848,7 +1848,7 @@ opt_aref */ DEFINE_INSN opt_aset -(IC ic) +(CALL_INFO ci) (VALUE recv, VALUE obj, VALUE set) (VALUE val) { @@ -1881,7 +1881,7 @@ opt_aset */ DEFINE_INSN opt_length -(IC ic) +(CALL_INFO ci) (VALUE recv) (VALUE val) { @@ -1916,7 +1916,7 @@ opt_length */ DEFINE_INSN opt_size -(IC ic) +(CALL_INFO ci) (VALUE recv) (VALUE val) { @@ -1951,7 +1951,7 @@ opt_size */ DEFINE_INSN opt_empty_p -(IC ic) +(CALL_INFO ci) (VALUE recv) (VALUE val) { @@ -1989,7 +1989,7 @@ opt_empty_p */ DEFINE_INSN opt_succ -(IC ic) +(CALL_INFO ci) (VALUE recv) (VALUE val) { @@ -2036,12 +2036,12 @@ opt_succ */ DEFINE_INSN opt_not -(IC ic) +(CALL_INFO ci) (VALUE recv) (VALUE val) { extern VALUE rb_obj_not(VALUE obj); - const rb_method_entry_t *me = vm_method_search(idNot, CLASS_OF(recv), ic, 0); + const rb_method_entry_t *me = vm_method_search(idNot, CLASS_OF(recv), ci, 0); if (check_cfunc(me, rb_obj_not)) { val = RTEST(recv) ? Qfalse : Qtrue; diff --git a/tool/instruction.rb b/tool/instruction.rb index 38318a435c..6934b33e80 100755 --- a/tool/instruction.rb +++ b/tool/instruction.rb @@ -706,10 +706,13 @@ class RubyVM break end + # skip make operands when body has no reference to this operand + # TODO: really needed? re = /\b#{var}\b/n - if re =~ insn.body or re =~ insn.sp_inc or insn.rets.any?{|t, v| re =~ v} or re =~ 'ic' + if re =~ insn.body or re =~ insn.sp_inc or insn.rets.any?{|t, v| re =~ v} or re =~ 'ic' or re =~ 'ci' ops << " #{type} #{var} = (#{type})GET_OPERAND(#{i+1});" end + n += 1 } @opn = n @@ -938,6 +941,8 @@ class RubyVM "TS_GENTRY" when /^IC/ "TS_IC" + when /^CALL_INFO/ + "TS_CALLINFO" when /^\.\.\./ "TS_VARIABLE" when /^CDHASH/ @@ -958,7 +963,8 @@ class RubyVM 'TS_VALUE' => 'V', 'TS_ID' => 'I', 'TS_GENTRY' => 'G', - 'TS_IC' => 'C', + 'TS_IC' => 'K', + 'TS_CALLINFO' => 'C', 'TS_CDHASH' => 'H', 'TS_ISEQ' => 'S', 'TS_VARIABLE' => '.', @@ -134,14 +134,21 @@ struct iseq_inline_cache_entry { VALUE ic_class; union { VALUE value; - rb_method_entry_t *method; long index; } ic_value; - union { - VALUE defined_class; - } ic_value2; }; +/* rb_call_info_t contains calling information including inline cache */ +typedef struct rb_call_info_struct { + /* inline cache: keys */ + VALUE ic_vmstat; + VALUE ic_class; + + /* inline cache: values */ + rb_method_entry_t *method; + VALUE defined_class; +} rb_call_info_t; + #if 1 #define GetCoreDataFromValue(obj, type, ptr) do { \ (ptr) = (type*)DATA_PTR(obj); \ @@ -201,6 +208,9 @@ struct rb_iseq_struct { struct iseq_inline_cache_entry *ic_entries; int ic_size; + rb_call_info_t *callinfo_entries; + int callinfo_size; + /** * argument information * @@ -661,6 +671,7 @@ enum vm_special_object_type { /* inline cache */ typedef struct iseq_inline_cache_entry *IC; +typedef rb_call_info_t *CALL_INFO; void rb_vm_change_state(void); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 34de8e430f..06cc85934a 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1430,25 +1430,27 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic) } static inline const rb_method_entry_t * -vm_method_search(VALUE id, VALUE klass, IC ic, VALUE *defined_class_ptr) +vm_method_search(VALUE id, VALUE klass, CALL_INFO ci, VALUE *defined_class_ptr) { rb_method_entry_t *me; #if OPT_INLINE_METHOD_CACHE - if (LIKELY(klass == ic->ic_class && - GET_VM_STATE_VERSION() == ic->ic_vmstat)) { - me = ic->ic_value.method; - if (defined_class_ptr) - *defined_class_ptr = ic->ic_value2.defined_class; + if (LIKELY(klass == ci->ic_class && + GET_VM_STATE_VERSION() == ci->ic_vmstat)) { + me = ci->method; + if (defined_class_ptr) { + *defined_class_ptr = ci->defined_class; + } } else { VALUE defined_class; me = rb_method_entry(klass, id, &defined_class); - if (defined_class_ptr) + if (defined_class_ptr) { *defined_class_ptr = defined_class; - ic->ic_class = klass; - ic->ic_value.method = me; - ic->ic_value2.defined_class = defined_class; - ic->ic_vmstat = GET_VM_STATE_VERSION(); + } + ci->ic_class = klass; + ci->method = me; + ci->defined_class = defined_class; + ci->ic_vmstat = GET_VM_STATE_VERSION(); } #else me = rb_method_entry(klass, id, defined_class_ptr); @@ -1773,7 +1775,7 @@ static inline #endif VALUE -opt_eq_func(VALUE recv, VALUE obj, IC ic) +opt_eq_func(VALUE recv, VALUE obj, CALL_INFO ci) { if (FIXNUM_2_P(recv, obj) && BASIC_OP_UNREDEFINED_P(BOP_EQ, FIXNUM_REDEFINED_OP_FLAG)) { @@ -1803,7 +1805,7 @@ opt_eq_func(VALUE recv, VALUE obj, IC ic) } { - const rb_method_entry_t *me = vm_method_search(idEq, CLASS_OF(recv), ic, 0); + const rb_method_entry_t *me = vm_method_search(idEq, CLASS_OF(recv), ci, 0); if (check_cfunc(me, rb_obj_equal)) { return recv == obj ? Qtrue : Qfalse; diff --git a/vm_insnhelper.h b/vm_insnhelper.h index 11833386f2..8b8da831a3 100644 --- a/vm_insnhelper.h +++ b/vm_insnhelper.h @@ -239,7 +239,7 @@ enum vm_regan_acttype { #define CALL_SIMPLE_METHOD(num, id, recv) do { \ VALUE klass = CLASS_OF(recv), defined_class; \ - const rb_method_entry_t *me = vm_method_search((id), klass, ic, &defined_class); \ + const rb_method_entry_t *me = vm_method_search((id), klass, ci, &defined_class); \ CALL_METHOD((num), 0, 0, (id), me, (recv), defined_class); \ } while (0) |