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



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24085 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2009-07-13 09:30:23 +00:00
Родитель 762f9b28c6
Коммит 20d9aefccb
8 изменённых файлов: 83 добавлений и 27 удалений

Просмотреть файл

@ -1,3 +1,18 @@
Mon Jul 13 17:49:11 2009 Koichi Sasada <ko1@atdot.net>
* 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 <ko1@atdot.net> Mon Jul 13 13:35:08 2009 Koichi Sasada <ko1@atdot.net>
* insns.def, vm_insnhelper.c (getinstancevariable): * insns.def, vm_insnhelper.c (getinstancevariable):

Просмотреть файл

@ -12,6 +12,7 @@
#include "ruby/ruby.h" #include "ruby/ruby.h"
#define USE_INSN_STACK_INCREASE 1 #define USE_INSN_STACK_INCREASE 1
#define USE_INSN_ICLEN 1
#include "vm_core.h" #include "vm_core.h"
#include "iseq.h" #include "iseq.h"
#include "insns.inc" #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; struct iseq_insn_info_entry *insn_info_table;
LINK_ELEMENT *list; LINK_ELEMENT *list;
VALUE *generated_iseq; VALUE *generated_iseq;
int ic_size = 0;
int ic_index = 0;
int k, pos, sp, stack_max = 0, line = 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; iobj = (INSN *)list;
line = iobj->line_no; line = iobj->line_no;
pos += insn_data_length(iobj); pos += insn_data_length(iobj);
ic_size += insn_iclen(iobj->insn_id);
k++; k++;
break; break;
} }
@ -1310,6 +1314,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
/* make instruction sequence */ /* make instruction sequence */
generated_iseq = ALLOC_N(VALUE, pos); generated_iseq = ALLOC_N(VALUE, pos);
insn_info_table = ALLOC_N(struct iseq_insn_info_entry, k); 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); list = FIRST_ELEMENT(anchor);
k = pos = sp = 0; k = pos = sp = 0;
@ -1318,7 +1325,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
switch (list->type) { switch (list->type) {
case ISEQ_ELEMENT_INSN: case ISEQ_ELEMENT_INSN:
{ {
int j, len, insn, iclen = 0, i; int j, len, insn, iclen = 0;
const char *types; const char *types;
VALUE *operands; VALUE *operands;
@ -1337,12 +1344,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
generated_iseq[pos] = insn; generated_iseq[pos] = insn;
types = insn_op_types(insn); types = insn_op_types(insn);
len = insn_len(insn); len = insn_len(insn);
iclen = insn_iclen(insn);
for (i=0; i<len; i++) {
if (types[i] == TS_IC) {
iclen++;
}
}
/* operand check */ /* operand check */
if (iobj->operand_size + iclen != len - 1) { if (iobj->operand_size + iclen != len - 1) {
@ -1432,9 +1434,12 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
} }
case TS_IC: /* inline cache */ case TS_IC: /* inline cache */
{ {
VALUE v = (VALUE)NEW_INLINE_CACHE_ENTRY(); IC ic = &iseq->ic_entries[ic_index++];
generated_iseq[pos + 1 + j] = v; if (UNLIKELY(ic_index > ic_size)) {
iseq_add_mark_object(iseq, v); rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d",
ic_index, ic_size);
}
generated_iseq[pos + 1 + j] = (VALUE)ic;
break; break;
} }
case TS_ID: /* ID */ 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)); argv[j] = (VALUE)rb_global_entry(SYM2ID(op));
break; break;
case TS_IC: case TS_IC:
argv[j] = (VALUE)NEW_INLINE_CACHE_ENTRY();
iseq_add_mark_object(iseq, argv[j]);
break; break;
case TS_ID: case TS_ID:
argv[j] = rb_convert_type(op, T_SYMBOL, argv[j] = rb_convert_type(op, T_SYMBOL,

Просмотреть файл

@ -1223,7 +1223,7 @@ setinlinecache
{ {
IC ic = GET_CONST_INLINE_CACHE(dst); 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; ic->ic_vmstat = GET_VM_STATE_VERSION() - ruby_vm_const_missing_count;
ruby_vm_const_missing_count = 0; ruby_vm_const_missing_count = 0;
} }

12
iseq.c
Просмотреть файл

@ -74,6 +74,7 @@ iseq_free(void *ptr)
RUBY_FREE_UNLESS_NULL(iseq->iseq); RUBY_FREE_UNLESS_NULL(iseq->iseq);
RUBY_FREE_UNLESS_NULL(iseq->insn_info_table); RUBY_FREE_UNLESS_NULL(iseq->insn_info_table);
RUBY_FREE_UNLESS_NULL(iseq->local_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->catch_table);
RUBY_FREE_UNLESS_NULL(iseq->arg_opt_table); RUBY_FREE_UNLESS_NULL(iseq->arg_opt_table);
compile_data_free(iseq->compile_data); compile_data_free(iseq->compile_data);
@ -86,11 +87,12 @@ iseq_free(void *ptr)
static void static void
iseq_mark(void *ptr) iseq_mark(void *ptr)
{ {
rb_iseq_t *iseq;
RUBY_MARK_ENTER("iseq"); RUBY_MARK_ENTER("iseq");
if (ptr) { 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_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->mark_ary);
RUBY_MARK_UNLESS_NULL(iseq->name); 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->cached_special_block); */
RUBY_MARK_UNLESS_NULL(iseq->orig); RUBY_MARK_UNLESS_NULL(iseq->orig);
for (i=0; i<iseq->ic_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) { if (iseq->compile_data != 0) {
RUBY_MARK_UNLESS_NULL(iseq->compile_data->mark_ary); RUBY_MARK_UNLESS_NULL(iseq->compile_data->mark_ary);
RUBY_MARK_UNLESS_NULL(iseq->compile_data->err_info); 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->local_table_size * sizeof(ID);
size += iseq->catch_table_size * sizeof(struct iseq_catch_table_entry); size += iseq->catch_table_size * sizeof(struct iseq_catch_table_entry);
size += iseq->arg_opts * sizeof(VALUE); size += iseq->arg_opts * sizeof(VALUE);
size += iseq->ic_size * sizeof(struct iseq_inline_cache_entry);
if (iseq->compile_data) { if (iseq->compile_data) {
struct iseq_compile_data_storage *cur; struct iseq_compile_data_storage *cur;

Просмотреть файл

@ -23,6 +23,10 @@ static const int insn_len_info[] = {
<%= operands_num_info %> <%= operands_num_info %>
}; };
static const int insn_iclen_info[] = {
<%= icoperands_num_info %>
};
#ifdef USE_INSN_RET_NUM #ifdef USE_INSN_RET_NUM
static const int insn_stack_push_num_info[] = { static const int insn_stack_push_num_info[] = {
<%= stack_num_info %> <%= stack_num_info %>
@ -81,3 +85,11 @@ insn_ret_num(int insn)
return insn_stack_push_num_info[insn]; return insn_stack_push_num_info[insn];
} }
#endif #endif
#ifdef USE_INSN_ICLEN
static int
insn_iclen(int insn)
{
return insn_iclen_info[insn];
}
#endif

Просмотреть файл

@ -977,6 +977,8 @@ class RubyVM
# operands info # operands info
operands_info = '' operands_info = ''
operands_num_info = '' operands_num_info = ''
icoperands_num_info = ''
@insns.each{|insn| @insns.each{|insn|
opes = insn.opes opes = insn.opes
operands_info << ' ' operands_info << ' '
@ -987,6 +989,12 @@ class RubyVM
num = opes.size + 1 num = opes.size + 1
operands_num_info << " #{num},\n" operands_num_info << " #{num},\n"
icnum = 0
opes.each{|e|
icnum += 1 if e[0] == 'IC'
}
icoperands_num_info << " #{icnum},\n"
} }
# stack num # stack num

Просмотреть файл

@ -106,6 +106,18 @@ typedef struct rb_compile_option_struct {
int debug_level; int debug_level;
} rb_compile_option_t; } 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 #if 1
#define GetCoreDataFromValue(obj, type, ptr) do { \ #define GetCoreDataFromValue(obj, type, ptr) do { \
ptr = (type*)DATA_PTR(obj); \ ptr = (type*)DATA_PTR(obj); \
@ -143,6 +155,9 @@ struct rb_iseq_struct {
/* method, class frame: sizeof(vars) + 1, block frame: sizeof(vars) */ /* method, class frame: sizeof(vars) + 1, block frame: sizeof(vars) */
int local_size; int local_size;
struct iseq_inline_cache_entry *ic_entries;
int ic_size;
/** /**
* argument information * argument information
* *
@ -522,13 +537,8 @@ typedef struct {
(VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC) (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
/* inline (method|const) cache */ /* inline cache */
#define NEW_INLINE_CACHE_ENTRY() NEW_NODE_LONGLIFE(NODE_WHILE, Qundef, 0, 0) typedef struct iseq_inline_cache_entry *IC;
#define ic_class u1.value
#define ic_method u2.node
#define ic_value u2.value
#define ic_vmstat u3.value
typedef NODE *IC;
void rb_vm_change_state(void); void rb_vm_change_state(void);

Просмотреть файл

@ -1180,7 +1180,7 @@ vm_getivar(VALUE obj, ID id, IC ic)
VALUE klass = RBASIC(obj)->klass; VALUE klass = RBASIC(obj)->klass;
if (ic->ic_class == klass) { if (ic->ic_class == klass) {
long index = ic->ic_vmstat; long index = ic->ic_index;
long len = ROBJECT_NUMIV(obj); long len = ROBJECT_NUMIV(obj);
VALUE *ptr = ROBJECT_IVPTR(obj); VALUE *ptr = ROBJECT_IVPTR(obj);
@ -1199,8 +1199,8 @@ vm_getivar(VALUE obj, ID id, IC ic)
if (index < len) { if (index < len) {
val = ptr[index]; val = ptr[index];
} }
ic->ic_class = CLASS_OF(obj); ic->ic_class = RBASIC(obj)->klass;
ic->ic_vmstat = index; ic->ic_index = index;
} }
} }
} }
@ -1231,8 +1231,8 @@ vm_method_search(VALUE id, VALUE klass, IC ic)
} }
else { else {
mn = rb_method_node(klass, id); mn = rb_method_node(klass, id);
ic->ic_class = rb_gc_write_barrier(klass); ic->ic_class = klass;
ic->ic_method = (NODE *)rb_gc_write_barrier((VALUE)mn); ic->ic_method = mn;
ic->ic_vmstat = GET_VM_STATE_VERSION(); ic->ic_vmstat = GET_VM_STATE_VERSION();
} }
} }