mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Add missing write barriers to Array#replace
Previously it made object references without using write barriers, creating GC inconsistencies. See: http://ci.rvm.jp/results/trunk-gc-asserts@phosphorus-docker/3925529
This commit is contained in:
parent
0626e6f959
commit
c416dbb3c7
Notes:
git
2022-04-29 00:31:52 +09:00
2 changed files with 12 additions and 2 deletions
6
array.c
6
array.c
|
@ -4680,14 +4680,16 @@ rb_ary_replace(VALUE copy, VALUE orig)
|
||||||
* contents of orig. */
|
* contents of orig. */
|
||||||
else if (ARY_EMBED_P(orig)) {
|
else if (ARY_EMBED_P(orig)) {
|
||||||
long len = ARY_EMBED_LEN(orig);
|
long len = ARY_EMBED_LEN(orig);
|
||||||
|
|
||||||
VALUE *ptr = ary_heap_alloc(copy, len);
|
VALUE *ptr = ary_heap_alloc(copy, len);
|
||||||
MEMCPY(ptr, ARY_EMBED_PTR(orig), VALUE, len);
|
|
||||||
|
|
||||||
FL_UNSET_EMBED(copy);
|
FL_UNSET_EMBED(copy);
|
||||||
ARY_SET_PTR(copy, ptr);
|
ARY_SET_PTR(copy, ptr);
|
||||||
ARY_SET_LEN(copy, len);
|
ARY_SET_LEN(copy, len);
|
||||||
ARY_SET_CAPA(copy, len);
|
ARY_SET_CAPA(copy, len);
|
||||||
|
|
||||||
|
// No allocation and exception expected that could leave `copy` in a
|
||||||
|
// bad state from the edits above.
|
||||||
|
ary_memcpy(copy, 0, len, RARRAY_CONST_PTR_TRANSIENT(orig));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Otherwise, orig is on heap and copy does not have enough space to embed
|
/* Otherwise, orig is on heap and copy does not have enough space to embed
|
||||||
|
|
|
@ -1439,6 +1439,14 @@ class TestArray < Test::Unit::TestCase
|
||||||
assert_raise(FrozenError) { fa.replace(42) }
|
assert_raise(FrozenError) { fa.replace(42) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_replace_wb_variable_width_alloc
|
||||||
|
small_embed = []
|
||||||
|
4.times { GC.start } # age small_embed
|
||||||
|
large_embed = [1, 2, 3, 4, 5, Array.new] # new young object
|
||||||
|
small_embed.replace(large_embed) # adds old to young reference
|
||||||
|
GC.verify_internal_consistency
|
||||||
|
end
|
||||||
|
|
||||||
def test_reverse
|
def test_reverse
|
||||||
a = @cls[*%w( dog cat bee ant )]
|
a = @cls[*%w( dog cat bee ant )]
|
||||||
assert_equal(@cls[*%w(ant bee cat dog)], a.reverse)
|
assert_equal(@cls[*%w(ant bee cat dog)], a.reverse)
|
||||||
|
|
Loading…
Add table
Reference in a new issue