@@ -236,9 +236,7 @@ rb_ary_embeddable_p(VALUE ary)
236236 * flag.
237237 * - Shared: we don't want to re-embed an array that points to a shared
238238 * root (to save memory).
239- * - Narrowed: the buffer is not VALUEs, so it cannot be copied into the
240- * slot as-is, and GC compaction (the caller) cannot widen because it
241- * must not allocate.
239+ * - Narrowed: the buffer is not VALUEs, and compaction cannot widen.
242240 */
243241 if (ARY_SHARED_ROOT_P (ary ) || OBJ_FROZEN (ary ) || ARY_SHARED_P (ary ) ||
244242 rb_array_stride (ary ) != RARRAY_STRIDE_VALUE ) return false;
@@ -300,8 +298,6 @@ ary_verify_(VALUE ary, const char *file, int line)
300298 RUBY_ASSERT (ARY_CAPA (ary ) >= RARRAY_LEN (ary ));
301299 }
302300 if (RARRAY_LEN (ary ) > 0 ) {
303- /* RARRAY_AREF is narrow-aware and does not widen, so an assertion
304- * cannot change the array's representation. */
305301 volatile VALUE v = RARRAY_AREF (ary , 0 ); /* access check: HEAD only */
306302 v = v ;
307303 }
@@ -345,10 +341,8 @@ rb_ary_widen(VALUE ary)
345341{
346342 if (rb_array_stride (ary ) == RARRAY_STRIDE_VALUE ) return ;
347343
348- /* A frozen narrow array may be Ractor-shareable, so two Ractors can reach
349- * this point in parallel through RARRAY_CONST_PTR. Widening swaps and
350- * frees the buffer, which must happen exactly once. Take the VM lock and
351- * re-check: whoever loses the race finds the array already widened. */
344+ /* A frozen narrow array may be shareable, so two Ractors can widen it
345+ * concurrently. Lock and re-check so the buffer swap happens once. */
352346 RB_VM_LOCKING () {
353347 if (rb_array_stride (ary ) != RARRAY_STRIDE_VALUE ) {
354348 ary_widen_locked (ary );
@@ -425,10 +419,8 @@ rb_ary_narrow(VALUE ary)
425419
426420/* ---- narrow fast paths ------------------------------------------------- */
427421
428- /* Run BODY once with `const T *p` bound to a narrowed array's packed buffer,
429- * where T is the element's C type. This hoists the width/sign dispatch out
430- * of the caller's loop: inside BODY, p[i] is a plain typed load the compiler
431- * can vectorize, instead of a per-element RARRAY_AREF decode. */
422+ /* Run BODY with `const T *p` bound to the packed buffer, so the width/sign
423+ * dispatch happens once instead of per element. */
432424#define ARY_NARROW_DISPATCH (ary , T , p , BODY ) do { \
433425 const void *narrow_raw_ = rarray_raw_ptr(ary); \
434426 if (rb_array_stride_unsigned_p(ary)) { \
@@ -447,10 +439,8 @@ rb_ary_narrow(VALUE ary)
447439 } \
448440} while (0)
449441
450- /* Index of the first (or last) element equal to needle, or -1. Equality on
451- * unboxed integers is a plain compare, so this is only valid when Integer#==
452- * is not redefined; callers check. A needle the element type cannot
453- * represent cannot be present, which the round trip through T detects. */
442+ /* Index of the first (or last) element equal to needle, or -1. Valid only
443+ * when Integer#== is not redefined; callers check. */
454444static long
455445ary_narrow_find (VALUE ary , long needle , bool from_end )
456446{
@@ -484,8 +474,7 @@ ary_narrow_count(VALUE ary, long needle)
484474 return count ;
485475}
486476
487- /* Sum of a narrowed array as a long. Elements are at most 32 bits, so the
488- * accumulator cannot overflow for fewer than 2**31 elements; callers check. */
477+ /* Sum as a long. Cannot overflow below 2**31 elements; callers check. */
489478static long
490479ary_narrow_sum (VALUE ary )
491480{
@@ -497,8 +486,8 @@ ary_narrow_sum(VALUE ary)
497486 return acc ;
498487}
499488
500- /* Minimum (or maximum ) of a non-empty narrowed array. Only valid when
501- * Integer#<=> is not redefined; callers check. */
489+ /* Min (or max ) of a non-empty narrowed array. Valid only when Integer#<=>
490+ * is not redefined; callers check. */
502491static long
503492ary_narrow_minmax (VALUE ary , bool want_max )
504493{
@@ -514,10 +503,8 @@ ary_narrow_minmax(VALUE ary, bool want_max)
514503 return best ;
515504}
516505
517- /* Decode a narrowed array's elements into dst[0..len) as VALUEs, in order or
518- * reversed. One dispatch, then a tight typed loop: ~8x faster than
519- * RARRAY_AREF per element. Elements are immediates, so dst needs no write
520- * barrier. */
506+ /* Decode into dst[0..len) as VALUEs, in order or reversed. Elements are
507+ * immediates, so no write barrier is needed. */
521508static void
522509ary_narrow_decode (VALUE src , VALUE * dst , long len , bool reversed )
523510{
@@ -1198,11 +1185,8 @@ ary_make_shared(VALUE ary)
11981185{
11991186 ary_verify (ary );
12001187
1201- /* A shared root's buffer is read as VALUEs by every array that borrows
1202- * it, and borrowers copy the raw pointer. A narrow array must therefore
1203- * never become a root; widen before handing the buffer out. This is the
1204- * frozen case in practice: narrowing happens on freeze, and a frozen
1205- * array is returned below as its own root. */
1188+ /* Borrowers read a shared root's buffer as VALUEs, so a narrow array
1189+ * must be widened before it can become one. */
12061190 if (RB_UNLIKELY (rb_array_stride (ary ) != RARRAY_STRIDE_VALUE )) {
12071191 rb_ary_widen (ary );
12081192 }
@@ -5724,9 +5708,8 @@ rb_ary_rassoc(VALUE ary, VALUE value)
57245708 return Qnil ;
57255709}
57265710
5727- /* Two wide heap arrays that share one buffer are trivially equal. A narrow
5728- * array has no VALUE buffer to compare, and asking for one would widen it;
5729- * narrow arrays never share a buffer, so the shortcut simply does not apply. */
5711+ /* Two wide heap arrays sharing one buffer are trivially equal. Narrow arrays
5712+ * never share a buffer, so the shortcut does not apply to them. */
57305713static inline bool
57315714ary_same_buffer_p (VALUE ary1 , VALUE ary2 )
57325715{
@@ -5735,9 +5718,8 @@ ary_same_buffer_p(VALUE ary1, VALUE ary2)
57355718 RARRAY_CONST_PTR (ary1 ) == RARRAY_CONST_PTR (ary2 );
57365719}
57375720
5738- /* Element-wise == from index i, re-reading both arrays every iteration.
5739- * rb_equal() may run Ruby code that mutates, widens or shrinks either array,
5740- * so nothing is cached across it. Lengths were equal on entry. */
5721+ /* Element-wise == from index i. rb_equal() may mutate, widen or shrink
5722+ * either array, so nothing is cached across it. */
57415723static VALUE
57425724ary_equal_slow_from (VALUE ary1 , VALUE ary2 , long i , bool eql )
57435725{
@@ -5754,11 +5736,9 @@ ary_equal_slow_from(VALUE ary1, VALUE ary2, long i, bool eql)
57545736 return Qtrue ;
57555737}
57565738
5757- /* == where at least one side is narrow. Two equal-width narrow arrays are a
5758- * memcmp. Otherwise the dispatch is hoisted onto the narrow side and the
5759- * other side is read through RARRAY_AREF; a mismatch against a Fixnum is a
5760- * definite inequality (Integer#== not redefined), anything else drops to the
5761- * slow path, which is safe against rb_equal() mutating the arrays. */
5739+ /* == where at least one side is narrow. Equal-width narrow arrays are a
5740+ * memcmp; otherwise compare element-wise, falling back to the slow path for
5741+ * anything that is not a Fixnum mismatch. */
57625742static VALUE
57635743ary_narrow_equal (VALUE ary1 , VALUE ary2 , bool eql )
57645744{
@@ -5772,8 +5752,7 @@ ary_narrow_equal(VALUE ary1, VALUE ary2, bool eql)
57725752 return RBOOL (memcmp (rarray_raw_ptr (ary1 ), rarray_raw_ptr (ary2 ), (size_t )len * ary_stride_bytes (ary1 )) == 0 );
57735753 }
57745754
5775- /* Two Fixnums that are not identical are never == (unless Integer#== is
5776- * redefined) and never eql?. Anything else goes to the slow path. */
5755+ /* Distinct Fixnums are never == (Integer#== not redefined) nor eql?. */
57775756 const bool fix_mismatch_decides = eql || BASIC_OP_UNREDEFINED_P (BOP_EQ , INTEGER_REDEFINED_OP_FLAG );
57785757 long i = 0 ;
57795758 if (n1 && n2 ) {
@@ -5825,8 +5804,7 @@ recursive_equal(VALUE ary1, VALUE ary2, int recur)
58255804 return ary_narrow_equal (ary1 , ary2 , false);
58265805 }
58275806
5828- /* Both wide: the original cached-pointer loop. rb_equal() can evacuate
5829- * ptrs, hence the re-fetch after each call that returns true. */
5807+ /* Both wide: rb_equal() can evacuate ptrs, hence the re-fetch. */
58305808 p1 = RARRAY_CONST_PTR (ary1 );
58315809 p2 = RARRAY_CONST_PTR (ary2 );
58325810 len1 = RARRAY_LEN (ary1 );
@@ -5984,10 +5962,8 @@ rb_ary_hash(VALUE ary)
59845962{
59855963 RBIMPL_ASSERT_OR_ASSUME (ary );
59865964 if (RB_UNLIKELY (rb_array_stride (ary ) != RARRAY_STRIDE_VALUE )) {
5987- /* Same combine sequence as ary_hash_values, over decoded elements, so
5988- * a narrowed array hashes identically to its wide equivalent (they
5989- * are ==, so they must). Elements are immediates: rb_hash cannot
5990- * re-enter and change the array, so no length re-check is needed. */
5965+ /* Same combine sequence as ary_hash_values, so a narrowed array
5966+ * hashes identically to its wide equivalent. */
59915967 const long len = RARRAY_LEN (ary );
59925968 st_index_t h = rb_hash_start (len );
59935969 h = rb_hash_uint (h , (st_index_t )rb_ary_hash_values );
@@ -6025,8 +6001,6 @@ rb_ary_includes(VALUE ary, VALUE item)
60256001 return RBOOL (ary_narrow_find (ary , FIX2LONG (item ), false) >= 0 );
60266002 }
60276003
6028- /* RARRAY_AREF is narrow-aware inside core, so this loop reads a narrowed
6029- * array in place without widening it. */
60306004 for (i = 0 ; i < RARRAY_LEN (ary ); i ++ ) {
60316005 e = RARRAY_AREF (ary , i );
60326006 if (rb_equal (e , item )) {
@@ -6036,8 +6010,7 @@ rb_ary_includes(VALUE ary, VALUE item)
60366010 return Qfalse ;
60376011}
60386012
6039- /* Test hooks. Not public API: they exist so the stride machinery can be
6040- * driven directly from the test suite before any automatic policy exists. */
6013+ /* Test hooks for the stride machinery. Not public API. */
60416014static VALUE
60426015rb_ary_narrow_bang (VALUE ary )
60436016{
@@ -8786,9 +8759,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
87868759 n = 0 ;
87878760 r = Qundef ;
87888761
8789- /* Narrow fast path: unboxed elements are summed as plain longs. Mirrors
8790- * the Fixnum loop below (which also adds natively); elements are <= 32
8791- * bits, so the accumulator is safe below 2**31 elements. */
8762+ /* Narrow fast path: sum unboxed elements as longs (see ary_narrow_sum). */
87928763 if (!block_given && FIXNUM_P (v ) &&
87938764 RB_UNLIKELY (rb_array_stride (ary ) != RARRAY_STRIDE_VALUE ) &&
87948765 RARRAY_LEN (ary ) < (1L << 30 )) {
0 commit comments