summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2021-05-04 13:37:02 +0000
committerPeter Zhu <peter@peterzhu.ca>2021-05-04 11:46:23 -0400
commit3ca291c9ae1b6de09cce76e17aa3f08e92e1a2bf (patch)
tree7bb2c625a07cd9b87a04c52b174626b7fcc9de02
parentd09988502ed75cae65b787865465361b675cf1ee (diff)
Correctly update array capacity after realloc
Reallocating to a smaller size in the transient heap may result in no change in the actual capacity but the capacity of the array is still updated to the smaller value. This commit changes `ary_heap_realloc` to return the new capacity which can be used by the caller to correctly update the capacity.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4448
-rw-r--r--array.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/array.c b/array.c
index 76f11581d2..50e2418462 100644
--- a/array.c
+++ b/array.c
@@ -354,14 +354,16 @@ ary_heap_free(VALUE ary)
}
}
-static void
+static size_t
ary_heap_realloc(VALUE ary, size_t new_capa)
{
+ size_t alloc_capa = new_capa;
size_t old_capa = ARY_HEAP_CAPA(ary);
if (RARRAY_TRANSIENT_P(ary)) {
if (new_capa <= old_capa) {
/* do nothing */
+ alloc_capa = old_capa;
}
else {
VALUE *new_ptr = rb_transient_heap_alloc(ary, sizeof(VALUE) * new_capa);
@@ -379,6 +381,8 @@ ary_heap_realloc(VALUE ary, size_t new_capa)
SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, old_capa);
}
ary_verify(ary);
+
+ return alloc_capa;
}
#if USE_TRANSIENT_HEAP
@@ -443,6 +447,7 @@ ary_resize_capa(VALUE ary, long capacity)
assert(!ARY_SHARED_P(ary));
if (capacity > RARRAY_EMBED_LEN_MAX) {
+ size_t new_capa = capacity;
if (ARY_EMBED_P(ary)) {
long len = ARY_EMBED_LEN(ary);
VALUE *ptr = ary_heap_alloc(ary, capacity);
@@ -453,9 +458,9 @@ ary_resize_capa(VALUE ary, long capacity)
ARY_SET_HEAP_LEN(ary, len);
}
else {
- ary_heap_realloc(ary, capacity);
+ new_capa = ary_heap_realloc(ary, capacity);
}
- ARY_SET_CAPA(ary, capacity);
+ ARY_SET_CAPA(ary, new_capa);
}
else {
if (!ARY_EMBED_P(ary)) {
@@ -2267,8 +2272,8 @@ rb_ary_resize(VALUE ary, long len)
}
else {
if (olen > len + ARY_DEFAULT_SIZE) {
- ary_heap_realloc(ary, len);
- ARY_SET_CAPA(ary, len);
+ size_t new_capa = ary_heap_realloc(ary, len);
+ ARY_SET_CAPA(ary, new_capa);
}
ARY_SET_HEAP_LEN(ary, len);
}