1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37121 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2012-10-09 05:33:54 +00:00
parent 4be0c562a4
commit 7ea3edc409
7 changed files with 107 additions and 51 deletions

View file

@ -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

View file

@ -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");

View file

@ -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;

View file

@ -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' => '.',

View file

@ -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);

View file

@ -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;

View file

@ -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)