зеркало из https://github.com/github/ruby.git
* 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:
Родитель
762f9b28c6
Коммит
20d9aefccb
15
ChangeLog
15
ChangeLog
|
@ -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):
|
||||||
|
|
27
compile.c
27
compile.c
|
@ -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
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
|
||||||
|
|
24
vm_core.h
24
vm_core.h
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче