Skip to content

Commit e00398f

Browse files
fix CI bug issue with unsigned values fitting long and zjit bindings stale
1 parent cbafe04 commit e00398f

3 files changed

Lines changed: 26 additions & 44 deletions

File tree

‎array.c‎

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -614,16 +614,16 @@ ary_fit_stride_batch(VALUE ary, const VALUE *argv, long argc)
614614
if (all_fix && ary_fixnum_fits_stride(lo, stride, uns) && ary_fixnum_fits_stride(hi, stride, uns)) {
615615
return; /* everything fits as is */
616616
}
617-
if (ARY_SHARED_P(ary)) rb_ary_cancel_sharing(ary); /* see ary_fit_stride */
617+
/* A view must not change the root's buffer: take a private copy first. */
618+
if (ARY_SHARED_P(ary)) rb_ary_cancel_sharing(ary);
618619
if (!all_fix || (uns && lo < 0)) {
619620
rb_ary_widen(ary); /* non-Fixnum, or negative into unsigned */
620621
return;
621622
}
622-
/* Width these elements need, keeping the array's signedness: a signed
623-
* array must stay signed even if every element here is non-negative. */
624-
long range_lo = (!uns && lo >= 0) ? -1 : lo;
623+
/* A signed array stays signed even if every element here is non-negative. */
624+
if (!uns && lo >= 0) lo = -1;
625625
int need_uns;
626-
int need = ary_stride_for_range(range_lo, hi, &need_uns);
626+
int need = ary_stride_for_range(lo, hi, &need_uns);
627627
if (need == RARRAY_STRIDE_VALUE) {
628628
rb_ary_widen(ary);
629629
}
@@ -638,7 +638,8 @@ ary_fixnum_fits_stride(long v, int stride, int uns)
638638
{
639639
if (stride == RARRAY_STRIDE_VALUE) return true;
640640

641-
long min, max;
641+
/* int64_t, not long: UINT32_MAX does not fit a 32-bit long (LLP64, i686). */
642+
int64_t min, max;
642643
if (uns) {
643644
min = 0;
644645
switch (stride) {
@@ -989,36 +990,7 @@ ary_fit_stride(VALUE ary, VALUE elem)
989990
if (FIXNUM_P(elem) && ary_fixnum_fits_stride(FIX2LONG(elem), stride, rb_array_stride_unsigned_p(ary))) {
990991
return; /* fits as is; a view may write in place into its root's buffer */
991992
}
992-
993-
/* The representation has to change. A view must not do that to the
994-
* root's buffer: take a private copy first. */
995-
if (ARY_SHARED_P(ary)) rb_ary_cancel_sharing(ary);
996-
997-
if (!FIXNUM_P(elem)) {
998-
rb_ary_widen(ary);
999-
return;
1000-
}
1001-
1002-
long v = FIX2LONG(elem);
1003-
int uns = rb_array_stride_unsigned_p(ary);
1004-
if (ary_fixnum_fits_stride(v, stride, uns)) return;
1005-
1006-
int new_uns;
1007-
int needed = ary_stride_for_fixnum(v, &new_uns);
1008-
1009-
/* Sign mismatch: picking a signed width that also covers the existing
1010-
* elements needs a scan of the buffer. Widen for now. */
1011-
if (uns != new_uns) {
1012-
rb_ary_widen(ary);
1013-
return;
1014-
}
1015-
1016-
if (needed == RARRAY_STRIDE_VALUE) {
1017-
rb_ary_widen(ary);
1018-
return;
1019-
}
1020-
1021-
ary_promote_stride(ary, needed, uns);
993+
ary_fit_stride_batch(ary, &elem, 1);
1022994
}
1023995

1024996
static void

‎test/ruby/test_array_stride.rb‎

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -881,14 +881,23 @@ def test_push_widens_above_32_bits
881881
assert_equal 2**40, a[-1]
882882
end
883883

884-
def test_push_of_opposite_sign_widens
885-
# An unsigned array receiving a negative (or vice versa) widens rather
886-
# than rescanning for a signed width. Values must still round-trip.
887-
a = pushed
888-
a << -1
889-
assert_equal WIDE, stride(a)
890-
assert_equal -1, a[-1]
891-
assert_equal (0...N).map { |i| i % 256 } + [-1], a
884+
# [elements, value, stride after writing value]
885+
SIGN_CHANGES = {
886+
"signed W8 + positive" => [->(i) { (i % 100) - 50 }, 200, W16],
887+
"signed W16 + positive" => [->(i) { (i % 100) * 300 - 15_000 }, 40_000, W32],
888+
"unsigned W8 + negative" => [->(i) { i % 256 }, -1, WIDE],
889+
"unsigned W16 + negative"=> [->(i) { i * 200 }, -1, WIDE],
890+
}
891+
892+
def test_opposite_sign_writes_match_for_single_and_batch
893+
SIGN_CHANGES.each do |name, (blk, v, want)|
894+
ref = (0...N).map(&blk)
895+
single = pushed(&blk); single << v
896+
batch = pushed(&blk); batch.push(v, 1)
897+
assert_equal ref + [v], single, name
898+
assert_equal ref + [v, 1], batch, name
899+
assert_equal [want, want], [stride(single), stride(batch)], name
900+
end
892901
end
893902

894903
def test_push_keeps_working_after_widening

‎zjit/src/cruby_bindings.inc.rs‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)