summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--class.c4
-rw-r--r--compile.c2
-rw-r--r--eval.c4
-rw-r--r--include/ruby/intern.h3
-rw-r--r--insns.def7
-rw-r--r--variable.c12
-rw-r--r--vm.c11
-rw-r--r--vm_core.h2
-rw-r--r--vm_insnhelper.c6
-rw-r--r--vm_insnhelper.h8
-rw-r--r--vm_method.c32
12 files changed, 70 insertions, 42 deletions
diff --git a/ChangeLog b/ChangeLog
index b4622fc..1cf2c8d 100644
--- a/ChangeLog
+++ b/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
diff --git a/class.c b/class.c
index d2cdf74..9b286a8 100644
--- a/class.c
+++ b/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;
}
diff --git a/compile.c b/compile.c
index f371cc1..f235b2b 100644
--- a/compile.c
+++ b/compile.c
@@ -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;
diff --git a/eval.c b/eval.c
index 7d5156e..b6916d1 100644
--- a/eval.c
+++ b/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;
}
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index fa0c075..b294f2d 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -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);
diff --git a/insns.def b/insns.def
index 740ff5d..fcd8c2c 100644
--- a/insns.def
+++ b/insns.def
@@ -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;
}
diff --git a/variable.c b/variable.c
index 9da4ee2..d07f9ff 100644
--- a/variable.c
+++ b/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();
}
/*
diff --git a/vm.c b/vm.c
index 80e13de..af29665 100644
--- a/vm.c
+++ b/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;
}
diff --git a/vm_core.h b/vm_core.h
index e79fd7c..7ad0004 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -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;
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 8fd6b1e..91e9142 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -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);
diff --git a/vm_insnhelper.h b/vm_insnhelper.h
index 1c0d046..674e6ca 100644
--- a/vm_insnhelper.h
+++ b/vm_insnhelper.h
@@ -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);
diff --git a/vm_method.c b/vm_method.c
index 30bd6b6..239f8b2 100644
--- a/vm_method.c
+++ b/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