summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Sasada <[email protected]>2019-08-09 11:00:34 +0900
committerKoichi Sasada <[email protected]>2019-08-09 11:05:11 +0900
commit71efad1ed391ee0c5398a76306fdbaaadd4dc52e ()
treed560b4a717ee7d15d23dc4ea02b1708f7d1d71ea
parentc7acb37248d4cef76647f8bc7ebd7dc291d9a853 (diff)
introduce RCLASS_CLONED flag for inline cache.
Methods on duplicated class/module refer same constant inline cache (IC). Constant access lookup should be done for cloned class/modules but inline cache doesn't check it. To check it, this introduce new RCLASS_CLONED flag which are set when if class/module is cloned (both orig and dst). [Bug #15877]
-rw-r--r--class.c8
-rw-r--r--internal.h1
-rw-r--r--test/ruby/test_class.rb22
-rw-r--r--test/ruby/test_module.rb33
-rw-r--r--vm_insnhelper.c8
5 files changed, 59 insertions, 13 deletions
@@ -308,11 +308,17 @@ class_init_copy_check(VALUE clone, VALUE orig)
rb_raise(rb_eTypeError, "can't copy singleton class");
}
}
-
/* :nodoc: */
VALUE
rb_mod_init_copy(VALUE clone, VALUE orig)
{
if (RB_TYPE_P(clone, T_CLASS)) {
class_init_copy_check(clone, orig);
}
@@ -1056,6 +1056,7 @@ int rb_singleton_class_internal_p(VALUE sklass);
#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class)
#define RCLASS_SERIAL(c) (RCLASS_EXT(c)->class_serial)
#define RICLASS_IS_ORIGIN FL_USER5
static inline void
@@ -329,18 +329,22 @@ class TestClass < Test::Unit::TestCase
end;
end
- module M
- C = 1
- def self.m
- C
- end
end
- def test_constant_access_from_method_in_cloned_module # [ruby-core:47834]
- m = M.dup
- assert_equal 1, m::C
- assert_equal 1, m.m
end
def test_invalid_superclass
@@ -2418,6 +2418,39 @@ class TestModule < Test::Unit::TestCase
}
end
private
def assert_top_method_is_private(method)
@@ -785,8 +785,9 @@ vm_get_const_key_cref(const VALUE *ep)
const rb_cref_t *key_cref = cref;
while (cref) {
- if (FL_TEST(CREF_CLASS(cref), FL_SINGLETON)) {
- return key_cref;
}
cref = CREF_NEXT(cref);
}
@@ -3722,7 +3723,8 @@ static int
vm_ic_hit_p(IC ic, const VALUE *reg_ep)
{
if (ic->ic_serial == GET_GLOBAL_CONSTANT_STATE()) {
- return (ic->ic_cref == NULL || ic->ic_cref == vm_get_cref(reg_ep));
}
return FALSE;
}