summaryrefslogtreecommitdiff
path: root/array.c
diff options
context:
space:
mode:
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)
{