@@ -237,9 +237,7 @@ rb_ary_embeddable_p(VALUE ary)
237237 * flag.
238238 * - Shared: we don't want to re-embed an array that points to a shared
239239 * root (to save memory).
240- * - Narrowed: the buffer is not VALUEs, so it cannot be copied into the
241- * slot as-is, and GC compaction (the caller) cannot widen because it
242- * must not allocate.
240+ * - Narrowed: the buffer is not VALUEs, and compaction cannot widen.
243241 */
244242 if (ARY_SHARED_ROOT_P (ary ) || OBJ_FROZEN (ary ) || ARY_SHARED_P (ary ) ||
245243 rb_array_stride (ary ) != RARRAY_STRIDE_VALUE ) return false;
@@ -302,8 +300,6 @@ ary_verify_(VALUE ary, const char *file, int line)
302300 RUBY_ASSERT (ARY_CAPA (ary ) >= RARRAY_LEN (ary ));
303301 }
304302 if (RARRAY_LEN (ary ) > 0 ) {
305- /* RARRAY_AREF is narrow-aware and does not widen, so an assertion
306- * cannot change the array's representation. */
307303 volatile VALUE v = RARRAY_AREF (ary , 0 ); /* access check: HEAD only */
308304 v = v ;
309305 }
@@ -347,10 +343,8 @@ rb_ary_widen(VALUE ary)
347343{
348344 if (rb_array_stride (ary ) == RARRAY_STRIDE_VALUE ) return ;
349345
350- /* A frozen narrow array may be Ractor-shareable, so two Ractors can reach
351- * this point in parallel through RARRAY_CONST_PTR. Widening swaps and
352- * frees the buffer, which must happen exactly once. Take the VM lock and
353- * re-check: whoever loses the race finds the array already widened. */
346+ /* A frozen narrow array may be shareable, so two Ractors can widen it
347+ * concurrently. Lock and re-check so the buffer swap happens once. */
354348 RB_VM_LOCKING () {
355349 if (rb_array_stride (ary ) != RARRAY_STRIDE_VALUE ) {
356350 ary_widen_locked (ary );
@@ -427,10 +421,8 @@ rb_ary_narrow(VALUE ary)
427421
428422/* ---- narrow fast paths ------------------------------------------------- */
429423
430- /* Run BODY once with `const T *p` bound to a narrowed array's packed buffer,
431- * where T is the element's C type. This hoists the width/sign dispatch out
432- * of the caller's loop: inside BODY, p[i] is a plain typed load the compiler
433- * can vectorize, instead of a per-element RARRAY_AREF decode. */
424+ /* Run BODY with `const T *p` bound to the packed buffer, so the width/sign
425+ * dispatch happens once instead of per element. */
434426#define ARY_NARROW_DISPATCH (ary , T , p , BODY ) do { \
435427 const void *narrow_raw_ = rarray_raw_ptr(ary); \
436428 if (rb_array_stride_unsigned_p(ary)) { \
@@ -449,10 +441,8 @@ rb_ary_narrow(VALUE ary)
449441 } \
450442} while (0)
451443
452- /* Index of the first (or last) element equal to needle, or -1. Equality on
453- * unboxed integers is a plain compare, so this is only valid when Integer#==
454- * is not redefined; callers check. A needle the element type cannot
455- * represent cannot be present, which the round trip through T detects. */
444+ /* Index of the first (or last) element equal to needle, or -1. Valid only
445+ * when Integer#== is not redefined; callers check. */
456446static long
457447ary_narrow_find (VALUE ary , long needle , bool from_end )
458448{
@@ -486,8 +476,7 @@ ary_narrow_count(VALUE ary, long needle)
486476 return count ;
487477}
488478
489- /* Sum of a narrowed array as a long. Elements are at most 32 bits, so the
490- * accumulator cannot overflow for fewer than 2**31 elements; callers check. */
479+ /* Sum as a long. Cannot overflow below 2**31 elements; callers check. */
491480static long
492481ary_narrow_sum (VALUE ary )
493482{
@@ -499,8 +488,8 @@ ary_narrow_sum(VALUE ary)
499488 return acc ;
500489}
501490
502- /* Minimum (or maximum ) of a non-empty narrowed array. Only valid when
503- * Integer#<=> is not redefined; callers check. */
491+ /* Min (or max ) of a non-empty narrowed array. Valid only when Integer#<=>
492+ * is not redefined; callers check. */
504493static long
505494ary_narrow_minmax (VALUE ary , bool want_max )
506495{
@@ -516,10 +505,8 @@ ary_narrow_minmax(VALUE ary, bool want_max)
516505 return best ;
517506}
518507
519- /* Decode a narrowed array's elements into dst[0..len) as VALUEs, in order or
520- * reversed. One dispatch, then a tight typed loop: ~8x faster than
521- * RARRAY_AREF per element. Elements are immediates, so dst needs no write
522- * barrier. */
508+ /* Decode into dst[0..len) as VALUEs, in order or reversed. Elements are
509+ * immediates, so no write barrier is needed. */
523510static void
524511ary_narrow_decode (VALUE src , VALUE * dst , long len , bool reversed )
525512{
@@ -1200,11 +1187,8 @@ ary_make_shared(VALUE ary)
12001187{
12011188 ary_verify (ary );
12021189
1203- /* A shared root's buffer is read as VALUEs by every array that borrows
1204- * it, and borrowers copy the raw pointer. A narrow array must therefore
1205- * never become a root; widen before handing the buffer out. This is the
1206- * frozen case in practice: narrowing happens on freeze, and a frozen
1207- * array is returned below as its own root. */
1190+ /* Borrowers read a shared root's buffer as VALUEs, so a narrow array
1191+ * must be widened before it can become one. */
12081192 if (RB_UNLIKELY (rb_array_stride (ary ) != RARRAY_STRIDE_VALUE )) {
12091193 rb_ary_widen (ary );
12101194 }
@@ -5732,9 +5716,8 @@ rb_ary_rassoc(VALUE ary, VALUE value)
57325716 return Qnil ;
57335717}
57345718
5735- /* Two wide heap arrays that share one buffer are trivially equal. A narrow
5736- * array has no VALUE buffer to compare, and asking for one would widen it;
5737- * narrow arrays never share a buffer, so the shortcut simply does not apply. */
5719+ /* Two wide heap arrays sharing one buffer are trivially equal. Narrow arrays
5720+ * never share a buffer, so the shortcut does not apply to them. */
57385721static inline bool
57395722ary_same_buffer_p (VALUE ary1 , VALUE ary2 )
57405723{
@@ -5743,9 +5726,8 @@ ary_same_buffer_p(VALUE ary1, VALUE ary2)
57435726 RARRAY_CONST_PTR (ary1 ) == RARRAY_CONST_PTR (ary2 );
57445727}
57455728
5746- /* Element-wise == from index i, re-reading both arrays every iteration.
5747- * rb_equal() may run Ruby code that mutates, widens or shrinks either array,
5748- * so nothing is cached across it. Lengths were equal on entry. */
5729+ /* Element-wise == from index i. rb_equal() may mutate, widen or shrink
5730+ * either array, so nothing is cached across it. */
57495731static VALUE
57505732ary_equal_slow_from (VALUE ary1 , VALUE ary2 , long i , bool eql )
57515733{
@@ -5762,11 +5744,9 @@ ary_equal_slow_from(VALUE ary1, VALUE ary2, long i, bool eql)
57625744 return Qtrue ;
57635745}
57645746
5765- /* == where at least one side is narrow. Two equal-width narrow arrays are a
5766- * memcmp. Otherwise the dispatch is hoisted onto the narrow side and the
5767- * other side is read through RARRAY_AREF; a mismatch against a Fixnum is a
5768- * definite inequality (Integer#== not redefined), anything else drops to the
5769- * slow path, which is safe against rb_equal() mutating the arrays. */
5747+ /* == where at least one side is narrow. Equal-width narrow arrays are a
5748+ * memcmp; otherwise compare element-wise, falling back to the slow path for
5749+ * anything that is not a Fixnum mismatch. */
57705750static VALUE
57715751ary_narrow_equal (VALUE ary1 , VALUE ary2 , bool eql )
57725752{
@@ -5780,8 +5760,7 @@ ary_narrow_equal(VALUE ary1, VALUE ary2, bool eql)
57805760 return RBOOL (memcmp (rarray_raw_ptr (ary1 ), rarray_raw_ptr (ary2 ), (size_t )len * ary_stride_bytes (ary1 )) == 0 );
57815761 }
57825762
5783- /* Two Fixnums that are not identical are never == (unless Integer#== is
5784- * redefined) and never eql?. Anything else goes to the slow path. */
5763+ /* Distinct Fixnums are never == (Integer#== not redefined) nor eql?. */
57855764 const bool fix_mismatch_decides = eql || BASIC_OP_UNREDEFINED_P (BOP_EQ , INTEGER_REDEFINED_OP_FLAG );
57865765 long i = 0 ;
57875766 if (n1 && n2 ) {
@@ -5833,8 +5812,7 @@ recursive_equal(VALUE ary1, VALUE ary2, int recur)
58335812 return ary_narrow_equal (ary1 , ary2 , false);
58345813 }
58355814
5836- /* Both wide: the original cached-pointer loop. rb_equal() can evacuate
5837- * ptrs, hence the re-fetch after each call that returns true. */
5815+ /* Both wide: rb_equal() can evacuate ptrs, hence the re-fetch. */
58385816 p1 = RARRAY_CONST_PTR (ary1 );
58395817 p2 = RARRAY_CONST_PTR (ary2 );
58405818 len1 = RARRAY_LEN (ary1 );
@@ -5993,10 +5971,8 @@ rb_ary_hash(VALUE ary)
59935971{
59945972 RBIMPL_ASSERT_OR_ASSUME (ary );
59955973 if (RB_UNLIKELY (rb_array_stride (ary ) != RARRAY_STRIDE_VALUE )) {
5996- /* Same combine sequence as ary_hash_values, over decoded elements, so
5997- * a narrowed array hashes identically to its wide equivalent (they
5998- * are ==, so they must). Elements are immediates: rb_hash cannot
5999- * re-enter and change the array, so no length re-check is needed. */
5974+ /* Same combine sequence as ary_hash_values, so a narrowed array
5975+ * hashes identically to its wide equivalent. */
60005976 const long len = RARRAY_LEN (ary );
60015977 st_index_t h = rb_hash_start (len );
60025978 h = rb_hash_uint (h , (st_index_t )rb_ary_hash_values );
@@ -6034,8 +6010,6 @@ rb_ary_includes(VALUE ary, VALUE item)
60346010 return RBOOL (ary_narrow_find (ary , FIX2LONG (item ), false) >= 0 );
60356011 }
60366012
6037- /* RARRAY_AREF is narrow-aware inside core, so this loop reads a narrowed
6038- * array in place without widening it. */
60396013 for (i = 0 ; i < RARRAY_LEN (ary ); i ++ ) {
60406014 e = RARRAY_AREF (ary , i );
60416015 if (rb_equal (e , item )) {
@@ -6045,8 +6019,7 @@ rb_ary_includes(VALUE ary, VALUE item)
60456019 return Qfalse ;
60466020}
60476021
6048- /* Test hooks. Not public API: they exist so the stride machinery can be
6049- * driven directly from the test suite before any automatic policy exists. */
6022+ /* Test hooks for the stride machinery. Not public API. */
60506023static VALUE
60516024rb_ary_narrow_bang (VALUE ary )
60526025{
@@ -8819,9 +8792,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
88198792 n = 0 ;
88208793 r = Qundef ;
88218794
8822- /* Narrow fast path: unboxed elements are summed as plain longs. Mirrors
8823- * the Fixnum loop below (which also adds natively); elements are <= 32
8824- * bits, so the accumulator is safe below 2**31 elements. */
8795+ /* Narrow fast path: sum unboxed elements as longs (see ary_narrow_sum). */
88258796 if (!block_given && FIXNUM_P (v ) &&
88268797 RB_UNLIKELY (rb_array_stride (ary ) != RARRAY_STRIDE_VALUE ) &&
88278798 RARRAY_LEN (ary ) < (1L << 30 )) {
0 commit comments