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:
parent
4be0c562a4
commit
7ea3edc409
7 changed files with 107 additions and 51 deletions
17
ChangeLog
17
ChangeLog
|
@ -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
|
||||
|
|
32
compile.c
32
compile.c
|
@ -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");
|
||||
|
|
50
insns.def
50
insns.def
|
@ -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;
|
||||
|
|
|
@ -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' => '.',
|
||||
|
|
19
vm_core.h
19
vm_core.h
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in a new issue