diff options
-rw-r--r-- | array.c | 5 | ||||
-rw-r--r-- | test/ruby/test_array.rb | 4 | ||||
-rw-r--r-- | tool/lib/envutil.rb | 9 |
3 files changed, 17 insertions, 1 deletions
@@ -1204,7 +1204,10 @@ ary_make_partial(VALUE ary, VALUE klass, long offset, long len) else { 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_LEN(result, RARRAY_LEN(ary)); diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index 6c0db0832b..838ef15b91 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -1693,6 +1693,10 @@ class TestArray < Test::Unit::TestCase assert_equal([100], a.slice(-1, 1_000_000_000)) 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! a = @cls[1, 2, 3, 4, 5] assert_equal(3, a.slice!(2)) diff --git a/tool/lib/envutil.rb b/tool/lib/envutil.rb index 1ca76d17a7..e47523a24b 100644 --- a/tool/lib/envutil.rb +++ b/tool/lib/envutil.rb @@ -245,6 +245,15 @@ module EnvUtil end 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) suppress_warning { Encoding.default_external = enc } yield |