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.
parent a93ef815
......@@ -21,7 +21,14 @@ typedef struct mrb_shared_array {
mrb_value *ptr;
} mrb_shared_array;
#define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value)))
#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,13 +50,21 @@ 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)
#define RARRAY_LEN(a) ARY_LEN(RARRAY(a))
......
......@@ -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);
}
ARY_SET_EMBED_LEN(a, 0);
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;
}
......
......@@ -6,6 +6,7 @@
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;
......
......@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment