summaryrefslogtreecommitdiff
path: root/array.c
diff options
context:
space:
mode:
authorMatt Valentine-House <matt@eightbitraptor.com>2022-06-09 15:59:08 +0100
committerPeter Zhu <peter@peterzhu.ca>2022-07-12 08:50:33 -0400
commit214ed4cbc6f33675230602dd09268b436da96f7d (patch)
tree0c1cd73729447e53136643b7975b39385ee7a711 /array.c
parent0f8a0c5f371b0886e8e31e35a9095bc9843de27c (diff)
[Feature #18901] Support size pool movement for Arrays
This commit enables Arrays to move between size pools during compaction. This can occur if the array is mutated such that it would fit in a different size pool when embedded. The move is carried out in two stages: 1. The RVALUE is moved to a destination heap during object movement phase of compaction 2. The array data is re-embedded and the original buffer free'd if required. This happens during the update references step
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/6099
Diffstat (limited to 'array.c')
-rw-r--r--array.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/array.c b/array.c
index 7b3f5bd0b0..dc8c4abe07 100644
--- a/array.c
+++ b/array.c
@@ -107,7 +107,6 @@ should_not_be_shared_and_embedded(VALUE ary)
#define ARY_SET_EMBED_LEN(ary, n) do { \
long tmp_n = (n); \
assert(ARY_EMBED_P(ary)); \
- assert(!OBJ_FROZEN(ary)); \
RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
} while (0)
@@ -212,6 +211,30 @@ ary_embeddable_p(long capa)
#endif
}
+bool
+rb_ary_embeddable_p(VALUE ary)
+{
+ // if the array is shared or a shared root then it's not moveable
+ return !(ARY_SHARED_P(ary) || ARY_SHARED_ROOT_P(ary));
+}
+
+size_t
+rb_ary_size_as_embedded(VALUE ary)
+{
+ size_t real_size;
+
+ if (ARY_EMBED_P(ary)) {
+ real_size = ary_embed_size(ARY_EMBED_LEN(ary));
+ }
+ else if (rb_ary_embeddable_p(ary)) {
+ real_size = ary_embed_size(ARY_HEAP_CAPA(ary));
+ }
+ else {
+ real_size = sizeof(struct RString);
+ }
+ return real_size;
+}
+
#if ARRAY_DEBUG
#define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
@@ -468,6 +491,23 @@ rb_ary_detransient(VALUE ary)
}
#endif
+void
+rb_ary_make_embedded(VALUE ary)
+{
+ assert(rb_ary_embeddable_p(ary));
+ if (!ARY_EMBED_P(ary)) {
+ VALUE *buf = RARRAY_PTR(ary);
+ long len = RARRAY_LEN(ary);
+
+ FL_SET_EMBED(ary);
+ ARY_SET_EMBED_LEN(ary, len);
+ RARY_TRANSIENT_UNSET(ary);
+
+ memmove(RARRAY_PTR(ary), buf, len * sizeof(VALUE));
+ ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
+ }
+}
+
static void
ary_resize_capa(VALUE ary, long capacity)
{