summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--array.c5
-rw-r--r--test/ruby/test_array.rb25
3 files changed, 42 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 279b2a8653..96b7b936c5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Thu Apr 10 19:11:11 2014 Koichi Sasada <ko1@atdot.net>
+
+ * array.c (rb_ary_modify): remember shared array owner if a shared
+ array owner is promoted and a shared array is not promoted.
+
+ Now, shared array is WB-unprotected so that shared arrays are not
+ promoted. All objects referred from shared array should be marked
+ correctly.
+
+ [ruby-core:61919] [ruby-trunk - Bug #9718]
+
+ * test/ruby/test_array.rb: add a test for above.
+
Thu Apr 10 18:57:12 2014 Koichi Sasada <ko1@atdot.net>
* gc.c (gc_verify_internal_consistency): move lines and enable
diff --git a/array.c b/array.c
index 7249ed7112..1112a22238 100644
--- a/array.c
+++ b/array.c
@@ -343,6 +343,11 @@ rb_ary_modify(VALUE ary)
ARY_SET_CAPA(ary, len);
ARY_SET_PTR(ary, ptr);
}
+
+ /* TODO: age2 promotion, OBJ_PROMOTED() checks not infant. */
+ if (OBJ_PROMOTED(ary) && !OBJ_PROMOTED(shared)) {
+ rb_gc_writebarrier_remember_promoted(ary);
+ }
}
}
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index d8ee3abb28..0bd138cc49 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -2389,7 +2389,7 @@ class TestArray < Test::Unit::TestCase
assert_equal([], a.rotate!(13))
assert_equal([], a.rotate!(-13))
a = [].freeze
- assert_raise_with_message(RuntimeError, /can't modify frozen/) {a.rotate!}
+ assert_raise_with_message(RuntimeError, /can\'t modify frozen/) {a.rotate!}
a = [1,2,3]
assert_raise(ArgumentError) { a.rotate!(1, 1) }
end
@@ -2428,4 +2428,27 @@ class TestArray < Test::Unit::TestCase
assert_include([4, 7], a.bsearch {|x| (2**100).coerce((1 - x / 4) * (2**100)).first })
end
+
+ def test_shared_marking
+ assert_normal_exit <<-EOS, '[Bug #9718]'
+ begin
+ require 'timeout'
+ timeout(5) do
+ queue = []
+ i = 0
+ srand(0)
+ loop do
+ if (i+=1) > rand(100_000)
+ GC.verify_internal_consistency
+ queue.shift.call
+ i = 0
+ end
+ queue << lambda{}
+ end
+ end
+ rescue TimeoutError
+ assert(true)
+ end
+ EOS
+ end
end