summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--compile.c32
-rw-r--r--insns.def50
-rwxr-xr-xtool/instruction.rb10
-rw-r--r--vm_core.h19
-rw-r--r--vm_insnhelper.c28
-rw-r--r--vm_insnhelper.h2
7 files changed, 107 insertions, 51 deletions
diff --git a/ChangeLog b/ChangeLog
index 8e1d294317..a22376fa22 100644
--- a/ChangeLog
+++ b/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
diff --git a/compile.c b/compile.c
index 1d943ed0bb..e03d0f9ac6 100644
--- a/compile.c
+++ b/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");
diff --git a/insns.def b/insns.def
index 0afc2f799a..ae1998af63 100644
--- a/insns.def
+++ b/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;
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' => '.',
diff --git a/vm_core.h b/vm_core.h
index 8d5140729b..6213863da4 100644
--- a/vm_core.h
+++ b/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);
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)