Don't call hash tombstone compaction from GC compaction

Tombstone removal may possibly require allocation, and we're not allowed
to allocate during GC.  This commit also renames `set_compact` to
`set_update_references` to differentiate tombstone removal compaction with GC
object compaction.

Co-Authored-By: Max Bernstein <max.bernstein@shopify.com>
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
This commit is contained in:
Aaron Patterson 2025-04-29 11:33:42 -07:00 committed by Aaron Patterson
parent 9cdc46587d
commit e6974be545
Notes: git 2025-04-29 20:33:28 +00:00
2 changed files with 15 additions and 3 deletions

5
set.c
View File

@ -179,10 +179,9 @@ set_replace_ref(st_data_t *key, st_data_t argp, int existing)
}
static void
set_compact(void *ptr)
set_update_references(void *ptr)
{
struct set_object *sobj = ptr;
set_compact_table(&sobj->table);
set_foreach_with_replace(&sobj->table, set_foreach_replace, set_replace_ref, 0);
}
@ -192,7 +191,7 @@ static const rb_data_type_t set_data_type = {
.dmark = set_mark,
.dfree = set_free,
.dsize = set_size,
.dcompact = set_compact,
.dcompact = set_update_references,
},
.flags = RUBY_TYPED_EMBEDDABLE | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE
};

View File

@ -864,6 +864,19 @@ class TC_Set < Test::Unit::TestCase
assert_equal(klass.new([a]), set, klass.name)
}
end
def test_set_gc_compact_does_not_allocate
assert_in_out_err([], <<-"end;", [], [])
def x
s = Set.new
s << Object.new
s
end
x
GC.compact
end;
end
end
class TC_Enumerable < Test::Unit::TestCase