8000 Fix off-by-one error for declarative marking · github/ruby@70618a4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 70618a4

Browse files
committed
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)
1 parent 260bf60 commit 70618a4

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

gc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7444,7 +7444,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
74447444
if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(any->as.typeddata.type)) {
74457445
size_t *offset_list = (size_t *)RANY(obj)->as.typeddata.type->function.dmark;
74467446

7447-
for (size_t offset = *offset_list; *offset_list != RUBY_REF_END; offset = *offset_list++) {
7447+
for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
74487448
rb_gc_mark_movable(*(VALUE *)((char *)ptr + offset));
74497449
}
74507450
}
@@ -10814,7 +10814,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
1081410814
if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(any->as.typeddata.type)) {
1081510815
size_t *offset_list = (size_t *)RANY(obj)->as.typeddata.type->function.dmark;
1081610816

10817-
for (size_t offset = *offset_list; *offset_list != RUBY_REF_END; offset = *offset_list++) {
10817+
for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
1081810818
VALUE *ref = (VALUE *)((char *)ptr + offset);
1081910819
if (SPECIAL_CONST_P(*ref)) continue;
1082010820
*ref = rb_gc_location(*ref);

test/ruby/test_enumerator.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,20 @@ def test_lazy_chain
862862
assert_equal(33, chain.next)
863863
end
864864

865+
def test_lazy_chain_under_gc_compact_stress
866+
EnvUtil.under_gc_compact_stress do
867+
ea = (10..).lazy.select(&:even?).take(10)
868+
ed = (20..).lazy.select(&:odd?)
869+
chain = (ea + ed).select{|x| x % 3 == 0}
870+
assert_equal(12, chain.next)
871+ assert_equal(18, chain.next)
872+
assert_equal(24, chain.next)
873+
assert_equal(21, chain.next)
874+
assert_equal(27, chain.next)
875+
assert_equal(33, chain.next)
876+
end
877+
end
878+
865879
def test_chain_undef_methods
866880
chain = [1].to_enum + [2].to_enum
867881
meths = (chain.methods & [:feed, :next, :next_values, :peek, :peek_values])

0 commit comments

Comments
 (0)
0