diff options
author | Matt Valentine-House <matt@eightbitraptor.com> | 2022-06-09 15:59:08 +0100 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2022-07-12 08:50:33 -0400 |
commit | 214ed4cbc6f33675230602dd09268b436da96f7d (patch) | |
tree | 0c1cd73729447e53136643b7975b39385ee7a711 /array.c | |
parent | 0f8a0c5f371b0886e8e31e35a9095bc9843de27c (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.c | 42 |
1 files changed, 41 insertions, 1 deletions
@@ -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) { |