summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--bootstraptest/test_class.rb14
-rw-r--r--insns.def3
-rw-r--r--variable.c6
-rw-r--r--vm.c8
-rw-r--r--vm_insnhelper.h1
6 files changed, 42 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 85d7c3de6b..41278cb7c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+Fri Jan 16 00:27:03 2009 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c (rb_vm_inc_const_missing_count, ruby_vm_const_missing_count):
+ added.
+
+ * vm_insnhelper.h: ditto.
+
+ * variable.c (rb_const_get_0), insns.def: Constants should not be
+ cached if const_missing is called. [ruby-core:21059] [Bug #967]
+
+ * bootstraptest/test_class.rb: add a test.
+
Fri Jan 16 00:25:09 2009 Koichi Sasada <ko1@atdot.net>
* common.mk: btest-ruby should receive option with OPTS.
diff --git a/bootstraptest/test_class.rb b/bootstraptest/test_class.rb
index 1c49b83037..ad2844106f 100644
--- a/bootstraptest/test_class.rb
+++ b/bootstraptest/test_class.rb
@@ -130,3 +130,17 @@ assert_equal "ok", %q{
:ok
end
}, '[ruby-core:14378]'
+
+assert_equal '3', %q{
+ $i = 0
+ class C
+ def self.const_missing *args
+ $i+=1
+ end
+ end
+
+ 3.times{
+ C::FOO
+ }
+ $i
+}
diff --git a/insns.def b/insns.def
index 669c491ed7..2ffd0ea783 100644
--- a/insns.def
+++ b/insns.def
@@ -1222,7 +1222,8 @@ setinlinecache
IC ic = GET_CONST_INLINE_CACHE(dst);
ic->ic_value = val;
- ic->ic_vmstat = GET_VM_STATE_VERSION();
+ ic->ic_vmstat = GET_VM_STATE_VERSION() - ruby_vm_const_missing_count;
+ ruby_vm_const_missing_count = 0;
}
/**
diff --git a/variable.c b/variable.c
index 283db99266..0cc87d7fd3 100644
--- a/variable.c
+++ b/variable.c
@@ -17,6 +17,8 @@
#include "node.h"
void rb_vm_change_state(void);
+void rb_vm_inc_const_missing_count(void);
+
st_table *rb_global_tbl;
st_table *rb_class_tbl;
static ID autoload, classpath, tmp_classpath;
@@ -1488,7 +1490,9 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse)
goto retry;
}
- return const_missing(klass, id);
+ value = const_missing(klass, id);
+ rb_vm_inc_const_missing_count();
+ return value;
}
VALUE
diff --git a/vm.c b/vm.c
index 1c3e4d9d76..8f33a8952a 100644
--- a/vm.c
+++ b/vm.c
@@ -34,6 +34,8 @@ VALUE rb_cEnv;
VALUE rb_mRubyVMFrozenCore;
VALUE ruby_vm_global_state_version = 1;
+VALUE ruby_vm_const_missing_count = 0;
+
char ruby_vm_redefined_flag[BOP_LAST_];
rb_thread_t *ruby_current_thread = 0;
@@ -49,6 +51,12 @@ rb_vm_change_state(void)
INC_VM_STATE_VERSION();
}
+void
+rb_vm_inc_const_missing_count(void)
+{
+ ruby_vm_const_missing_count +=1;
+}
+
/* control stack frame */
static inline VALUE
diff --git a/vm_insnhelper.h b/vm_insnhelper.h
index 6000f9478c..74ca8450e4 100644
--- a/vm_insnhelper.h
+++ b/vm_insnhelper.h
@@ -58,6 +58,7 @@ enum {
extern char ruby_vm_redefined_flag[BOP_LAST_];
extern VALUE ruby_vm_global_state_version;
+extern VALUE ruby_vm_const_missing_count;
#define GET_VM_STATE_VERSION() (ruby_vm_global_state_version)
#define INC_VM_STATE_VERSION() \