Don't copy RUBY_FL_PROMOTED flag in rb_obj_setup
RUBY_FL_PROMOTED is used by the garbage collector to track when an object becomes promoted to the old generation. rb_obj_setup must not copy that flag over because then it may become out-of-sync with the age of the object. This fixes a bug in Method#clone where the cloned Method object may get RUBY_FL_PROMOTED incorrectly set.
This commit is contained in:
parent
1b5f3dd6a1
commit
b4efa4b700
3
object.c
3
object.c
@ -119,7 +119,8 @@ rb_obj_reveal(VALUE obj, VALUE klass)
|
||||
VALUE
|
||||
rb_obj_setup(VALUE obj, VALUE klass, VALUE type)
|
||||
{
|
||||
RBASIC(obj)->flags = type;
|
||||
VALUE ignored_flags = RUBY_FL_PROMOTED;
|
||||
RBASIC(obj)->flags = (type & ~ignored_flags) | (RBASIC(obj)->flags & ignored_flags);
|
||||
RBASIC_SET_CLASS(obj, klass);
|
||||
return obj;
|
||||
}
|
||||
|
@ -450,6 +450,17 @@ class TestMethod < Test::Unit::TestCase
|
||||
assert_equal(:bar, m.clone.bar)
|
||||
end
|
||||
|
||||
def test_clone_under_gc_compact_stress
|
||||
EnvUtil.under_gc_compact_stress do
|
||||
o = Object.new
|
||||
def o.foo; :foo; end
|
||||
m = o.method(:foo)
|
||||
def m.bar; :bar; end
|
||||
assert_equal(:foo, m.clone.call)
|
||||
assert_equal(:bar, m.clone.bar)
|
||||
end
|
||||
end
|
||||
|
||||
def test_inspect
|
||||
o = Object.new
|
||||
def o.foo; end; line_no = __LINE__
|
||||
|
Loading…
x
Reference in New Issue
Block a user