mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[Bug #19029] Don't start GC during compaction
RARRAY_PTR when called with a transient array detransients the array before returning its pointer which allocates in the heap. Because RARRAY_PTR was being used during compaction (when re-embedding arrays that have moved between size pools) this introduces the possibility that we can hit a malloc threshold, triggering GC, while in the middle of compaction. We should avoid this by using safer functions to get hold of the pointer. Since we know that the array is not embedded here, we can use ARY_HEAP_PTR and ARY_EMBED_PTR directly
This commit is contained in:
parent
4ced7bfb23
commit
892f350a7d
Notes:
git
2022-09-29 22:22:37 +09:00
1 changed files with 9 additions and 5 deletions
14
array.c
14
array.c
|
@ -505,15 +505,19 @@ rb_ary_make_embedded(VALUE ary)
|
||||||
{
|
{
|
||||||
assert(rb_ary_embeddable_p(ary));
|
assert(rb_ary_embeddable_p(ary));
|
||||||
if (!ARY_EMBED_P(ary)) {
|
if (!ARY_EMBED_P(ary)) {
|
||||||
VALUE *buf = RARRAY_PTR(ary);
|
const VALUE *buf = ARY_HEAP_PTR(ary);
|
||||||
long len = RARRAY_LEN(ary);
|
long len = ARY_HEAP_LEN(ary);
|
||||||
|
bool was_transient = RARRAY_TRANSIENT_P(ary);
|
||||||
|
|
||||||
|
// FL_SET_EMBED also unsets the transient flag
|
||||||
FL_SET_EMBED(ary);
|
FL_SET_EMBED(ary);
|
||||||
ARY_SET_EMBED_LEN(ary, len);
|
ARY_SET_EMBED_LEN(ary, len);
|
||||||
RARY_TRANSIENT_UNSET(ary);
|
|
||||||
|
|
||||||
memmove(RARRAY_PTR(ary), buf, len * sizeof(VALUE));
|
MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
|
||||||
ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
|
|
||||||
|
if (!was_transient) {
|
||||||
|
ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue