Skip array embedding if `MRB_NO_BOXING` and `MRB_32BIT`; fix
On some platforms, `sizeof(mrb_value) > sizeof(void*)*3`, which makes
`MRB_ARY_EMBED_LEN_MAX` zero. And zero sized array cause compile errors.
MODIFY
include/mruby/array.h
include/mruby/array.h
@@ -21,7 +21,14 @@ typedef struct mrb_shared_array {
mrb_value *ptr;
} mrb_shared_array;
+#if defined(MRB_32BIT) && defined(MRB_NO_BOXING)
+# define MRB_ARY_NO_EMBED
+# define MRB_ARY_EMBED_LEN_MAX 0
+#else
# define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value)))
+mrb_static_assert(MRB_ARY_EMBED_LEN_MAX > 0, "MRB_ARY_EMBED_LEN_MAX > 0");
+#endif
+
struct RArray {
MRB_OBJECT_HEADER;
union {
@@ -33,7 +40,9 @@ struct RArray {
} aux;
mrb_value *ptr;
} heap;
+#ifndef MRB_ARY_NO_EMBED
mrb_value ary[MRB_ARY_EMBED_LEN_MAX];
+#endif
} as;
};
@@ -41,12 +50,20 @@ struct RArray {
#define mrb_ary_value(p) mrb_obj_value((void*)(p))
#define RARRAY(v) ((struct RArray*)(mrb_ptr(v)))
+#ifdef MRB_ARY_NO_EMBED
+#define ARY_EMBED_P(a) 0
+#define ARY_UNSET_EMBED_FLAG(a) (void)0
+#define ARY_EMBED_LEN(a) 0
+#define ARY_SET_EMBED_LEN(a,len) (void)0
+#define ARY_EMBED_PTR(a) 0
+#else
#define MRB_ARY_EMBED_MASK 7
#define ARY_EMBED_P(a) ((a)->flags & MRB_ARY_EMBED_MASK)
#define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED_MASK))
#define ARY_EMBED_LEN(a) ((mrb_int)(((a)->flags & MRB_ARY_EMBED_MASK) - 1))
#define ARY_SET_EMBED_LEN(a,len) ((a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | ((uint32_t)(len) + 1))
#define ARY_EMBED_PTR(a) ((a)->as.ary)
+#endif
#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len)
#define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr)

MODIFY
src/array.c
src/array.c
@@ -1123,8 +1123,14 @@ mrb_ary_clear(mrb_state *mrb, mrb_value self)
else if (!ARY_EMBED_P(a)){
mrb_free(mrb, a->as.heap.ptr);
}
+ if (MRB_ARY_EMBED_LEN_MAX > 0) {
ARY_SET_EMBED_LEN(a, 0);
-
+ }
+ else {
+ a->as.heap.ptr = NULL;
+ a->as.heap.aux.capa = 0;
+ ARY_SET_LEN(a, 0);
+ }
return self;
}

MODIFY
src/value_array.h
src/value_array.h
static inline void
value_move(mrb_value *s1, const mrb_value *s2, size_t n)
{
+ if (n == 0) return;
if (s1 > s2 && s1 < s2 + n)
{
s1 += n;

MODIFY
src/vm.c
src/vm.c
@@ -1823,7 +1823,7 @@ RETRY_TRY_BLOCK:
if (kd) regs[len + 1] = kdict;
/* copy mandatory and optional arguments */
- if (argv0 != argv) {
+ if (argv0 != argv && argv) {
value_move(&regs[1], argv, argc-mlen); /* m1 + o */
}
if (argc < m1) {

Skip array embedding if `MRB_NO_BOXING` and `MRB_32BIT`; fix #4382

On some platforms, `sizeof(mrb_value) > sizeof(void*)*3`, which makes
`MRB_ARY_EMBED_LEN_MAX` zero. And zero sized array cause compile errors.