Skip to content

Commit 396b3b6

Browse files
fix platform specific fixnum boundaries
1 parent 1c07a28 commit 396b3b6

3 files changed

Lines changed: 137 additions & 137 deletions

File tree

‎array.c‎

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -476,12 +476,12 @@ ary_narrow_count(VALUE ary, long needle)
476476
return count;
477477
}
478478

479-
/* Sum as a long. Cannot overflow below 2**31 elements; callers check. */
480-
static long
479+
/* long long, not long (32-bit on LLP64). Callers check the length. */
480+
static long long
481481
ary_narrow_sum(VALUE ary)
482482
{
483483
const long len = RARRAY_LEN(ary);
484-
long acc = 0;
484+
long long acc = 0;
485485
ARY_NARROW_DISPATCH(ary, T, p, {
486486
for (long i = 0; i < len; i++) acc += p[i];
487487
});
@@ -5888,9 +5888,20 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur)
58885888
rb_array_stride(ary2) != RARRAY_STRIDE_VALUE)) {
58895889
return ary_narrow_equal(ary1, ary2, true);
58905890
}
5891-
for (i = 0; i < RARRAY_LEN(ary1); i++) {
5892-
if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5893-
return Qfalse;
5891+
5892+
/* rb_eql() can resize either array and evacuate ptrs */
5893+
p1 = RARRAY_CONST_PTR(ary1);
5894+
p2 = RARRAY_CONST_PTR(ary2);
5895+
len1 = RARRAY_LEN(ary1);
5896+
5897+
for (i = 0; i < len1; i++) {
5898+
if (p1[i] != p2[i]) {
5899+
if (!rb_eql(p1[i], p2[i])) return Qfalse;
5900+
len1 = RARRAY_LEN(ary1);
5901+
if (len1 != RARRAY_LEN(ary2)) return Qfalse;
5902+
p1 = RARRAY_CONST_PTR(ary1);
5903+
p2 = RARRAY_CONST_PTR(ary2);
5904+
}
58945905
}
58955906
return Qtrue;
58965907
}
@@ -6020,12 +6031,15 @@ rb_ary_includes(VALUE ary, VALUE item)
60206031
}
60216032

60226033
/* Test hooks for the stride machinery. Not public API. */
6034+
6035+
/* :nodoc: */
60236036
static VALUE
60246037
rb_ary_narrow_bang(VALUE ary)
60256038
{
60266039
return INT2FIX(ary_try_narrow(ary));
60276040
}
60286041

6042+
/* :nodoc: */
60296043
static VALUE
60306044
rb_ary_stride_m(VALUE ary)
60316045
{
@@ -8796,7 +8810,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
87968810
if (!block_given && FIXNUM_P(v) &&
87978811
RB_UNLIKELY(rb_array_stride(ary) != RARRAY_STRIDE_VALUE) &&
87988812
RARRAY_LEN(ary) < (1L << 30)) {
8799-
return rb_int_plus(LONG2NUM(ary_narrow_sum(ary)), v);
8813+
return rb_int_plus(LL2NUM(ary_narrow_sum(ary)), v);
88008814
}
88018815

88028816
bool init_is_float = RB_FLOAT_TYPE_P(v);

‎internal/array.h‎

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,30 +34,30 @@ rarray_raw_ptr(VALUE ary)
3434
}
3535

3636
/* Load element i of a narrowed array as a C integer. The single place that
37-
* knows the width/sign encoding. */
38-
static inline long
37+
* knows the width/sign encoding. int64_t, not long: long is 32-bit on
38+
* LLP64 platforms. Dispatches once on the stride and sign flag bits
39+
* together, the same way io.c switches on FMODE_READABLE|FMODE_WRITABLE. */
40+
static inline int64_t
3941
rarray_narrow_load_int(VALUE ary, long i)
4042
{
4143
const void *p = rarray_raw_ptr(ary);
42-
if (rb_array_stride_unsigned_p(ary)) {
43-
switch (rb_array_stride(ary)) {
44-
case RARRAY_STRIDE_W8: return (long)((const uint8_t *)p)[i];
45-
case RARRAY_STRIDE_W16: return (long)((const uint16_t *)p)[i];
46-
default: return (long)((const uint32_t *)p)[i];
47-
}
48-
}
49-
switch (rb_array_stride(ary)) {
50-
case RARRAY_STRIDE_W8: return ((const int8_t *)p)[i];
51-
case RARRAY_STRIDE_W16: return ((const int16_t *)p)[i];
52-
default: return ((const int32_t *)p)[i];
44+
#define W(stride) ((VALUE)(stride) << RARRAY_STRIDE_SHIFT)
45+
switch (RBASIC(ary)->flags & (RARRAY_STRIDE_MASK | RARRAY_STRIDE_UNSIGNED)) {
46+
case W(RARRAY_STRIDE_W8): return ((const int8_t *)p)[i];
47+
case W(RARRAY_STRIDE_W16): return ((const int16_t *)p)[i];
48+
case W(RARRAY_STRIDE_W32): return ((const int32_t *)p)[i];
49+
case W(RARRAY_STRIDE_W8) | RARRAY_STRIDE_UNSIGNED: return ((const uint8_t *)p)[i];
50+
case W(RARRAY_STRIDE_W16) | RARRAY_STRIDE_UNSIGNED: return ((const uint16_t *)p)[i];
51+
default: return ((const uint32_t *)p)[i];
5352
}
53+
#undef W
5454
}
5555

5656
/* Decode element i of a narrowed array into a ::VALUE. */
5757
static inline VALUE
5858
rarray_narrow_aref(VALUE ary, long i)
5959
{
60-
return LONG2FIX(rarray_narrow_load_int(ary, i));
60+
return LL2NUM(rarray_narrow_load_int(ary, i));
6161
}
6262

6363
/* Core's RARRAY_AREF replaces the public macro. It adds a bounds assertion

0 commit comments

Comments
 (0)