зеркало из https://github.com/github/ruby.git
* insns.def, vm.c, vm_insnhelper.c, vm_insnhelper.h, vm_method.c: split
ruby_vm_global_state_version into two separate counters - one for the global method state and one for the global constant state. This means changes to constants do not affect method caches, and changes to methods do not affect constant caches. In particular, this means inclusions of modules containing constants no longer globally invalidate the method cache. * class.c, eval.c, include/ruby/intern.h, insns.def, vm.c, vm_method.c: rename rb_clear_cache_by_class to rb_clear_method_cache_by_class * class.c, include/ruby/intern.h, variable.c, vm_method.c: add rb_clear_constant_cache * compile.c, vm_core.h, vm_insnhelper.c: rename vmstat field in rb_call_info_struct to method_state * vm_method.c: rename vmstat field in struct cache_entry to method_state git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43455 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
e2ec76056a
Коммит
7fafa8f376
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
|||
Tue Oct 29 09:53:00 2013 Charlie Somerville <charliesome@ruby-lang.org>
|
||||
|
||||
* insns.def, vm.c, vm_insnhelper.c, vm_insnhelper.h, vm_method.c: split
|
||||
ruby_vm_global_state_version into two separate counters - one for the
|
||||
global method state and one for the global constant state. This means
|
||||
changes to constants do not affect method caches, and changes to
|
||||
methods do not affect constant caches. In particular, this means
|
||||
inclusions of modules containing constants no longer globally
|
||||
invalidate the method cache.
|
||||
|
||||
* class.c, eval.c, include/ruby/intern.h, insns.def, vm.c, vm_method.c:
|
||||
rename rb_clear_cache_by_class to rb_clear_method_cache_by_class
|
||||
|
||||
* class.c, include/ruby/intern.h, variable.c, vm_method.c: add
|
||||
rb_clear_constant_cache
|
||||
|
||||
* compile.c, vm_core.h, vm_insnhelper.c: rename vmstat field in
|
||||
rb_call_info_struct to method_state
|
||||
|
||||
* vm_method.c: rename vmstat field in struct cache_entry to method_state
|
||||
|
||||
Mon Oct 28 23:26:04 2013 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* test/readline/test_readline.rb (teardown): Clear Readline.input and
|
||||
|
|
4
class.c
4
class.c
|
@ -900,8 +900,8 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module)
|
|||
module = RCLASS_SUPER(module);
|
||||
}
|
||||
|
||||
if (method_changed) rb_clear_cache_by_class(klass);
|
||||
if (constant_changed) rb_clear_cache();
|
||||
if (method_changed) rb_clear_method_cache_by_class(klass);
|
||||
if (constant_changed) rb_clear_constant_cache();
|
||||
|
||||
return method_changed;
|
||||
}
|
||||
|
|
|
@ -961,7 +961,7 @@ new_callinfo(rb_iseq_t *iseq, ID mid, int argc, VALUE block, unsigned long flag)
|
|||
ci->flag |= VM_CALL_ARGS_SKIP_SETUP;
|
||||
}
|
||||
}
|
||||
ci->vmstat = 0;
|
||||
ci->method_state = 0;
|
||||
ci->seq = 0;
|
||||
ci->blockptr = 0;
|
||||
ci->recv = Qundef;
|
||||
|
|
4
eval.c
4
eval.c
|
@ -1263,7 +1263,7 @@ mod_using(VALUE self, VALUE module)
|
|||
}
|
||||
Check_Type(module, T_MODULE);
|
||||
rb_using_module(cref, module);
|
||||
rb_clear_cache_by_class(rb_cObject);
|
||||
rb_clear_method_cache_by_class(rb_cObject);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -1399,7 +1399,7 @@ top_using(VALUE self, VALUE module)
|
|||
}
|
||||
Check_Type(module, T_MODULE);
|
||||
rb_using_module(cref, module);
|
||||
rb_clear_cache_by_class(rb_cObject);
|
||||
rb_clear_method_cache_by_class(rb_cObject);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
|
@ -376,7 +376,8 @@ void rb_define_alloc_func(VALUE, rb_alloc_func_t);
|
|||
void rb_undef_alloc_func(VALUE);
|
||||
rb_alloc_func_t rb_get_alloc_func(VALUE);
|
||||
void rb_clear_cache(void);
|
||||
void rb_clear_cache_by_class(VALUE);
|
||||
void rb_clear_constant_cache(void);
|
||||
void rb_clear_method_cache_by_class(VALUE);
|
||||
void rb_alias(VALUE, ID, ID);
|
||||
void rb_attr(VALUE,ID,int,int,int);
|
||||
int rb_method_boundp(VALUE, ID, int);
|
||||
|
|
|
@ -218,7 +218,6 @@ setconstant
|
|||
{
|
||||
vm_check_if_namespace(cbase);
|
||||
rb_const_set(cbase, id, val);
|
||||
rb_clear_cache_by_class(cbase);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -974,8 +973,6 @@ defineclass
|
|||
class_iseq->iseq_encoded, GET_SP(),
|
||||
class_iseq->local_size, 0, class_iseq->stack_max);
|
||||
RESTORE_REGS();
|
||||
|
||||
rb_clear_cache_by_class(klass);
|
||||
NEXT_INSN();
|
||||
}
|
||||
|
||||
|
@ -1186,7 +1183,7 @@ getinlinecache
|
|||
()
|
||||
(VALUE val)
|
||||
{
|
||||
if (ic->ic_vmstat == GET_VM_STATE_VERSION()) {
|
||||
if (ic->ic_vmstat == GET_CONSTANT_STATE_VERSION()) {
|
||||
val = ic->ic_value.value;
|
||||
JUMP(dst);
|
||||
}
|
||||
|
@ -1211,7 +1208,7 @@ setinlinecache
|
|||
rb_iseq_add_mark_object(GET_ISEQ(), val);
|
||||
}
|
||||
ic->ic_value.value = val;
|
||||
ic->ic_vmstat = GET_VM_STATE_VERSION() - ruby_vm_const_missing_count;
|
||||
ic->ic_vmstat = GET_CONSTANT_STATE_VERSION() - ruby_vm_const_missing_count;
|
||||
ruby_vm_const_missing_count = 0;
|
||||
}
|
||||
|
||||
|
|
12
variable.c
12
variable.c
|
@ -1941,7 +1941,7 @@ rb_const_remove(VALUE mod, ID id)
|
|||
rb_class_name(mod), QUOTE_ID(id));
|
||||
}
|
||||
|
||||
rb_clear_cache();
|
||||
rb_clear_constant_cache();
|
||||
|
||||
val = ((rb_const_entry_t*)v)->value;
|
||||
if (val == Qundef) {
|
||||
|
@ -2151,7 +2151,7 @@ rb_const_set(VALUE klass, ID id, VALUE val)
|
|||
load = autoload_data(klass, id);
|
||||
/* for autoloading thread, keep the defined value to autoloading storage */
|
||||
if (load && (ele = check_autoload_data(load)) && (ele->thread == rb_thread_current())) {
|
||||
rb_clear_cache();
|
||||
rb_clear_constant_cache();
|
||||
|
||||
ele->value = val; /* autoload_i is shady */
|
||||
return;
|
||||
|
@ -2175,7 +2175,7 @@ rb_const_set(VALUE klass, ID id, VALUE val)
|
|||
}
|
||||
}
|
||||
|
||||
rb_clear_cache();
|
||||
rb_clear_constant_cache();
|
||||
|
||||
|
||||
ce = ALLOC(rb_const_entry_t);
|
||||
|
@ -2222,7 +2222,7 @@ set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag)
|
|||
id = rb_check_id(&val);
|
||||
if (!id) {
|
||||
if (i > 0) {
|
||||
rb_clear_cache();
|
||||
rb_clear_constant_cache();
|
||||
}
|
||||
|
||||
rb_name_error_str(val, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined",
|
||||
|
@ -2234,13 +2234,13 @@ set_const_visibility(VALUE mod, int argc, VALUE *argv, rb_const_flag_t flag)
|
|||
}
|
||||
else {
|
||||
if (i > 0) {
|
||||
rb_clear_cache();
|
||||
rb_clear_constant_cache();
|
||||
}
|
||||
rb_name_error(id, "constant %"PRIsVALUE"::%"PRIsVALUE" not defined",
|
||||
rb_class_name(mod), QUOTE_ID(id));
|
||||
}
|
||||
}
|
||||
rb_clear_cache();
|
||||
rb_clear_constant_cache();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
11
vm.c
11
vm.c
|
@ -71,7 +71,8 @@ static VALUE
|
|||
vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class,
|
||||
int argc, const VALUE *argv, const rb_block_t *blockptr);
|
||||
|
||||
static vm_state_version_t ruby_vm_global_state_version = 1;
|
||||
static vm_state_version_t ruby_vm_method_state_version = 1;
|
||||
static vm_state_version_t ruby_vm_constant_state_version = 1;
|
||||
static vm_state_version_t ruby_vm_sequence = 1;
|
||||
|
||||
#include "vm_insnhelper.h"
|
||||
|
@ -2075,12 +2076,12 @@ vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval,
|
|||
OBJ_WRITE(miseq->self, &miseq->klass, klass);
|
||||
miseq->defined_method_id = id;
|
||||
rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, noex);
|
||||
rb_clear_cache_by_class(klass);
|
||||
rb_clear_method_cache_by_class(klass);
|
||||
|
||||
if (!is_singleton && noex == NOEX_MODFUNC) {
|
||||
klass = rb_singleton_class(klass);
|
||||
rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, NOEX_PUBLIC);
|
||||
rb_clear_cache_by_class(klass);
|
||||
rb_clear_method_cache_by_class(klass);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2130,8 +2131,8 @@ m_core_undef_method(VALUE self, VALUE cbase, VALUE sym)
|
|||
{
|
||||
REWIND_CFP({
|
||||
rb_undef(cbase, SYM2ID(sym));
|
||||
rb_clear_cache_by_class(cbase);
|
||||
rb_clear_cache_by_class(self);
|
||||
rb_clear_method_cache_by_class(cbase);
|
||||
rb_clear_method_cache_by_class(self);
|
||||
});
|
||||
return Qnil;
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ typedef struct rb_call_info_struct {
|
|||
rb_iseq_t *blockiseq;
|
||||
|
||||
/* inline cache: keys */
|
||||
vm_state_version_t vmstat;
|
||||
vm_state_version_t method_state;
|
||||
vm_state_version_t seq;
|
||||
VALUE klass;
|
||||
|
||||
|
|
|
@ -846,7 +846,7 @@ vm_search_method(rb_call_info_t *ci, VALUE recv)
|
|||
VALUE klass = CLASS_OF(recv);
|
||||
|
||||
#if OPT_INLINE_METHOD_CACHE
|
||||
if (LIKELY(GET_VM_STATE_VERSION() == ci->vmstat && RCLASS_EXT(klass)->seq == ci->seq)) {
|
||||
if (LIKELY(GET_METHOD_STATE_VERSION() == ci->method_state && RCLASS_EXT(klass)->seq == ci->seq)) {
|
||||
/* cache hit! */
|
||||
return;
|
||||
}
|
||||
|
@ -856,7 +856,7 @@ vm_search_method(rb_call_info_t *ci, VALUE recv)
|
|||
ci->klass = klass;
|
||||
ci->call = vm_call_general;
|
||||
#if OPT_INLINE_METHOD_CACHE
|
||||
ci->vmstat = GET_VM_STATE_VERSION();
|
||||
ci->method_state = GET_METHOD_STATE_VERSION();
|
||||
ci->seq = RCLASS_EXT(klass)->seq;
|
||||
#endif
|
||||
}
|
||||
|
@ -924,7 +924,7 @@ rb_equal_opt(VALUE obj1, VALUE obj2)
|
|||
rb_call_info_t ci;
|
||||
ci.mid = idEq;
|
||||
ci.klass = 0;
|
||||
ci.vmstat = 0;
|
||||
ci.method_state = 0;
|
||||
ci.me = NULL;
|
||||
ci.defined_class = 0;
|
||||
return opt_eq_func(obj1, obj2, &ci);
|
||||
|
|
|
@ -260,10 +260,10 @@ enum vm_regan_acttype {
|
|||
} while (0)
|
||||
|
||||
#define NEXT_CLASS_SEQUENCE() (++ruby_vm_sequence)
|
||||
#define GET_VM_STATE_VERSION() (ruby_vm_global_state_version)
|
||||
#define INC_VM_STATE_VERSION() do { \
|
||||
ruby_vm_global_state_version = (ruby_vm_global_state_version + 1); \
|
||||
} while (0)
|
||||
#define GET_METHOD_STATE_VERSION() (ruby_vm_method_state_version)
|
||||
#define INC_METHOD_STATE_VERSION() (++ruby_vm_method_state_version)
|
||||
#define GET_CONSTANT_STATE_VERSION() (ruby_vm_constant_state_version)
|
||||
#define INC_CONSTANT_STATE_VERSION() (++ruby_vm_constant_state_version)
|
||||
|
||||
static VALUE make_no_method_exception(VALUE exc, const char *format,
|
||||
VALUE obj, int argc, const VALUE *argv);
|
||||
|
|
32
vm_method.c
32
vm_method.c
|
@ -25,7 +25,7 @@ static void rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VAL
|
|||
#define attached id__attached__
|
||||
|
||||
struct cache_entry {
|
||||
vm_state_version_t vm_state;
|
||||
vm_state_version_t method_state;
|
||||
vm_state_version_t seq;
|
||||
ID mid;
|
||||
rb_method_entry_t* me;
|
||||
|
@ -46,15 +46,23 @@ rb_class_clear_method_cache(VALUE klass)
|
|||
void
|
||||
rb_clear_cache(void)
|
||||
{
|
||||
INC_VM_STATE_VERSION();
|
||||
rb_warning("rb_clear_cache() is deprecated.");
|
||||
INC_METHOD_STATE_VERSION();
|
||||
INC_CONSTANT_STATE_VERSION();
|
||||
}
|
||||
|
||||
void
|
||||
rb_clear_cache_by_class(VALUE klass)
|
||||
rb_clear_constant_cache(void)
|
||||
{
|
||||
INC_CONSTANT_STATE_VERSION();
|
||||
}
|
||||
|
||||
void
|
||||
rb_clear_method_cache_by_class(VALUE klass)
|
||||
{
|
||||
if (klass && klass != Qundef) {
|
||||
if (klass == rb_cBasicObject || klass == rb_cObject || klass == rb_mKernel) {
|
||||
INC_VM_STATE_VERSION();
|
||||
INC_METHOD_STATE_VERSION();
|
||||
}
|
||||
else {
|
||||
rb_class_clear_method_cache(klass);
|
||||
|
@ -203,7 +211,7 @@ rb_add_refined_method_entry(VALUE refined_class, ID mid)
|
|||
|
||||
if (me) {
|
||||
make_method_entry_refined(me);
|
||||
rb_clear_cache_by_class(refined_class);
|
||||
rb_clear_method_cache_by_class(refined_class);
|
||||
}
|
||||
else {
|
||||
rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0,
|
||||
|
@ -302,7 +310,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
|
|||
|
||||
me = ALLOC(rb_method_entry_t);
|
||||
|
||||
rb_clear_cache_by_class(klass);
|
||||
rb_clear_method_cache_by_class(klass);
|
||||
|
||||
me->flag = NOEX_WITH_SAFE(noex);
|
||||
me->mark = 0;
|
||||
|
@ -464,7 +472,7 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_
|
|||
if (type != VM_METHOD_TYPE_UNDEF && type != VM_METHOD_TYPE_REFINED) {
|
||||
method_added(klass, mid);
|
||||
}
|
||||
rb_clear_cache_by_class(klass);
|
||||
rb_clear_method_cache_by_class(klass);
|
||||
return me;
|
||||
}
|
||||
|
||||
|
@ -542,7 +550,7 @@ rb_method_entry_get_without_cache(VALUE klass, ID id,
|
|||
struct cache_entry *ent;
|
||||
ent = GLOBAL_METHOD_CACHE(klass, id);
|
||||
ent->seq = RCLASS_EXT(klass)->seq;
|
||||
ent->vm_state = GET_VM_STATE_VERSION();
|
||||
ent->method_state = GET_METHOD_STATE_VERSION();
|
||||
ent->defined_class = defined_class;
|
||||
ent->mid = id;
|
||||
|
||||
|
@ -580,7 +588,7 @@ rb_method_entry(VALUE klass, ID id, VALUE *defined_class_ptr)
|
|||
#if OPT_GLOBAL_METHOD_CACHE
|
||||
struct cache_entry *ent;
|
||||
ent = GLOBAL_METHOD_CACHE(klass, id);
|
||||
if (ent->vm_state == GET_VM_STATE_VERSION() &&
|
||||
if (ent->method_state == GET_METHOD_STATE_VERSION() &&
|
||||
ent->seq == RCLASS_EXT(klass)->seq &&
|
||||
ent->mid == id) {
|
||||
if (defined_class_ptr)
|
||||
|
@ -701,7 +709,7 @@ remove_method(VALUE klass, ID mid)
|
|||
st_delete(RCLASS_M_TBL(klass), &key, &data);
|
||||
|
||||
rb_vm_check_redefinition_opt_method(me, klass);
|
||||
rb_clear_cache_by_class(klass);
|
||||
rb_clear_method_cache_by_class(klass);
|
||||
rb_unlink_method_entry(me);
|
||||
|
||||
CALL_METHOD_HOOK(self, removed, mid);
|
||||
|
@ -1232,7 +1240,7 @@ rb_alias(VALUE klass, ID name, ID def)
|
|||
|
||||
if (flag == NOEX_UNDEF) flag = orig_me->flag;
|
||||
rb_method_entry_set(target_klass, name, orig_me, flag);
|
||||
rb_clear_cache_by_class(target_klass);
|
||||
rb_clear_method_cache_by_class(target_klass);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1287,7 +1295,7 @@ set_method_visibility(VALUE self, int argc, VALUE *argv, rb_method_flag_t ex)
|
|||
}
|
||||
rb_export_method(self, id, ex);
|
||||
}
|
||||
rb_clear_cache_by_class(self);
|
||||
rb_clear_method_cache_by_class(self);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
|
Загрузка…
Ссылка в новой задаче