Fix off-by-one error for declarative marking
The for loops for marking and reference updating declaratively marked TypedData objects did not mark/reference update the very last element. When RGENGC_CHECK_MODE is turned on, this caused the test in Enumerator to fail with: tool/lib/test/unit/testcase.rb:173:in `rescue in run': failed to allocate memory (NoMemoryError)
This commit is contained in:
parent
260bf60e52
commit
70618a48f7
4
gc.c
4
gc.c
@ -7444,7 +7444,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
|
||||
if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(any->as.typeddata.type)) {
|
||||
size_t *offset_list = (size_t *)RANY(obj)->as.typeddata.type->function.dmark;
|
||||
|
||||
for (size_t offset = *offset_list; *offset_list != RUBY_REF_END; offset = *offset_list++) {
|
||||
for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
|
||||
rb_gc_mark_movable(*(VALUE *)((char *)ptr + offset));
|
||||
}
|
||||
}
|
||||
@ -10814,7 +10814,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
|
||||
if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(any->as.typeddata.type)) {
|
||||
size_t *offset_list = (size_t *)RANY(obj)->as.typeddata.type->function.dmark;
|
||||
|
||||
for (size_t offset = *offset_list; *offset_list != RUBY_REF_END; offset = *offset_list++) {
|
||||
for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
|
||||
VALUE *ref = (VALUE *)((char *)ptr + offset);
|
||||
if (SPECIAL_CONST_P(*ref)) continue;
|
||||
*ref = rb_gc_location(*ref);
|
||||
|
@ -862,6 +862,20 @@ class TestEnumerator < Test::Unit::TestCase
|
||||
assert_equal(33, chain.next)
|
||||
end
|
||||
|
||||
def test_lazy_chain_under_gc_compact_stress
|
||||
EnvUtil.under_gc_compact_stress do
|
||||
ea = (10..).lazy.select(&:even?).take(10)
|
||||
ed = (20..).lazy.select(&:odd?)
|
||||
chain = (ea + ed).select{|x| x % 3 == 0}
|
||||
assert_equal(12, chain.next)
|
||||
assert_equal(18, chain.next)
|
||||
assert_equal(24, chain.next)
|
||||
assert_equal(21, chain.next)
|
||||
assert_equal(27, chain.next)
|
||||
assert_equal(33, chain.next)
|
||||
end
|
||||
end
|
||||
|
||||
def test_chain_undef_methods
|
||||
chain = [1].to_enum + [2].to_enum
|
||||
meths = (chain.methods & [:feed, :next, :next_values, :peek, :peek_values])
|
||||
|
Loading…
x
Reference in New Issue
Block a user