Fix compaction during ary_make_partial
The ary_make_shared call may allocate, which can trigger a GC compaction. This can cause the array to be embedded because it has a length of 0.
This commit is contained in:
parent
3af56e87ca
commit
150ed44d87
5
array.c
5
array.c
@ -1204,7 +1204,10 @@ ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
|
|||||||
else {
|
else {
|
||||||
VALUE shared = ary_make_shared(ary);
|
VALUE shared = ary_make_shared(ary);
|
||||||
|
|
||||||
assert(!ARY_EMBED_P(result));
|
/* The ary_make_shared call may allocate, which can trigger a GC
|
||||||
|
* compaction. This can cause the array to be embedded because it has
|
||||||
|
* a length of 0. */
|
||||||
|
FL_UNSET_EMBED(result);
|
||||||
|
|
||||||
ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
|
ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
|
||||||
ARY_SET_LEN(result, RARRAY_LEN(ary));
|
ARY_SET_LEN(result, RARRAY_LEN(ary));
|
||||||
|
@ -1693,6 +1693,10 @@ class TestArray < Test::Unit::TestCase
|
|||||||
assert_equal([100], a.slice(-1, 1_000_000_000))
|
assert_equal([100], a.slice(-1, 1_000_000_000))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_slice_gc_compact_stress
|
||||||
|
EnvUtil.under_gc_compact_stress { assert_equal([1, 2, 3, 4, 5], (0..10).to_a[1, 5]) }
|
||||||
|
end
|
||||||
|
|
||||||
def test_slice!
|
def test_slice!
|
||||||
a = @cls[1, 2, 3, 4, 5]
|
a = @cls[1, 2, 3, 4, 5]
|
||||||
assert_equal(3, a.slice!(2))
|
assert_equal(3, a.slice!(2))
|
||||||
|
@ -245,6 +245,15 @@ module EnvUtil
|
|||||||
end
|
end
|
||||||
module_function :under_gc_stress
|
module_function :under_gc_stress
|
||||||
|
|
||||||
|
def under_gc_compact_stress(&block)
|
||||||
|
auto_compact = GC.auto_compact
|
||||||
|
GC.auto_compact = true
|
||||||
|
under_gc_stress(&block)
|
||||||
|
ensure
|
||||||
|
GC.auto_compact = auto_compact
|
||||||
|
end
|
||||||
|
module_function :under_gc_compact_stress
|
||||||
|
|
||||||
def with_default_external(enc)
|
def with_default_external(enc)
|
||||||
suppress_warning { Encoding.default_external = enc }
|
suppress_warning { Encoding.default_external = enc }
|
||||||
yield
|
yield
|
||||||
|
Loading…
x
Reference in New Issue
Block a user