Skip to content

Commit

Permalink
Don't copy RUBY_FL_PROMOTED flag in rb_obj_setup
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
peterzhu2118 committed Dec 25, 2023
1 parent 1b5f3dd commit b4efa4b
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 1 deletion.
3 changes: 2 additions & 1 deletion object.c
Expand Up @@ -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;
}
Expand Down
11 changes: 11 additions & 0 deletions test/ruby/test_method.rb
Expand Up @@ -450,6 +450,17 @@ def m.bar; :bar; end
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__
Expand Down

0 comments on commit b4efa4b

Please sign in to comment.