@@ -343,6 +343,11 @@ rb_ary_modify(VALUE ary)
343343 ARY_SET_CAPA (ary , len );
344344 ARY_SET_PTR (ary , ptr );
345345 }
346+
347+ /* TODO: age2 promotion, OBJ_PROMOTED() checks not infant. */
348+ if (OBJ_PROMOTED (ary ) && !OBJ_PROMOTED (shared )) {
349+ rb_gc_writebarrier_remember_promoted (ary );
350+ }
346351 }
347352}
348353
@@ -898,19 +903,6 @@ rb_ary_push(VALUE ary, VALUE item)
898903 return ary ;
899904}
900905
901- static VALUE
902- rb_ary_push_1 (VALUE ary , VALUE item )
903- {
904- long idx = RARRAY_LEN (ary );
905-
906- if (idx >= ARY_CAPA (ary )) {
907- ary_double_capa (ary , idx );
908- }
909- RARRAY_ASET (ary , idx , item );
910- ARY_SET_LEN (ary , idx + 1 );
911- return ary ;
912- }
913-
914906VALUE
915907rb_ary_cat (VALUE ary , const VALUE * ptr , long len )
916908{
@@ -3077,7 +3069,7 @@ ary_reject(VALUE orig, VALUE result)
30773069 for (i = 0 ; i < RARRAY_LEN (orig ); i ++ ) {
30783070 VALUE v = RARRAY_AREF (orig , i );
30793071 if (!RTEST (rb_yield (v ))) {
3080- rb_ary_push_1 (result , v );
3072+ rb_ary_push (result , v );
30813073 }
30823074 }
30833075 return result ;
@@ -4690,6 +4682,25 @@ rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
46904682#define tmpary (n ) rb_ary_tmp_new(n)
46914683#define tmpary_discard (a ) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
46924684
4685+ /*
4686+ * Build a ruby array of the corresponding values and yield it to the
4687+ * associated block.
4688+ * Return the class of +values+ for reentry check.
4689+ */
4690+ static int
4691+ yield_indexed_values (const VALUE values , const long r , const long * const p )
4692+ {
4693+ const VALUE result = rb_ary_new2 (r );
4694+ VALUE * const result_array = RARRAY_PTR (result );
4695+ const VALUE * const values_array = RARRAY_CONST_PTR (values );
4696+ long i ;
4697+
4698+ for (i = 0 ; i < r ; i ++ ) result_array [i ] = values_array [p [i ]];
4699+ ARY_SET_LEN (result , r );
4700+ rb_yield (result );
4701+ return !RBASIC (values )-> klass ;
4702+ }
4703+
46934704/*
46944705 * Recursively compute permutations of +r+ elements of the set
46954706 * <code>[0..n-1]</code>.
@@ -4707,7 +4718,7 @@ rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
47074718static void
47084719permute0 (long n , long r , long * p , long index , char * used , VALUE values )
47094720{
4710- long i , j ;
4721+ long i ;
47114722 for (i = 0 ; i < n ; i ++ ) {
47124723 if (used [i ] == 0 ) {
47134724 p [index ] = i ;
@@ -4718,17 +4729,7 @@ permute0(long n, long r, long *p, long index, char *used, VALUE values)
47184729 used [i ] = 0 ; /* index unused */
47194730 }
47204731 else {
4721- /* We have a complete permutation of array indexes */
4722- /* Build a ruby array of the corresponding values */
4723- /* And yield it to the associated block */
4724- VALUE result = rb_ary_new2 (r );
4725- VALUE * result_array = RARRAY_PTR (result );
4726- const VALUE * values_array = RARRAY_PTR (values );
4727-
4728- for (j = 0 ; j < r ; j ++ ) result_array [j ] = values_array [p [j ]];
4729- ARY_SET_LEN (result , r );
4730- rb_yield (result );
4731- if (RBASIC (values )-> klass ) {
4732+ if (!yield_indexed_values (values , r , p )) {
47324733 rb_raise (rb_eRuntimeError , "permute reentered" );
47334734 }
47344735 }
@@ -4826,7 +4827,7 @@ rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
48264827 }
48274828 }
48284829 else { /* this is the general case */
4829- volatile VALUE t0 = tmpbuf (n ,sizeof (long ));
4830+ volatile VALUE t0 = tmpbuf (r ,sizeof (long ));
48304831 long * p = (long * )RSTRING_PTR (t0 );
48314832 volatile VALUE t1 = tmpbuf (n ,sizeof (char ));
48324833 char * used = (char * )RSTRING_PTR (t1 );
@@ -4897,21 +4898,19 @@ rb_ary_combination(VALUE ary, VALUE num)
48974898 }
48984899 }
48994900 else {
4900- volatile VALUE t0 = tmpbuf (n + 1 , sizeof (long ));
4901- long * stack = (long * )RSTRING_PTR (t0 );
4902- volatile VALUE cc = tmpary (n );
4903- VALUE * chosen = RARRAY_PTR (cc );
4901+ VALUE ary0 = ary_make_shared_copy (ary ); /* private defensive copy of ary */
4902+ volatile VALUE t0 ;
4903+ long * stack = ALLOCV_N (long , t0 , n + 1 );
49044904 long lev = 0 ;
49054905
4906- MEMZERO (stack , long , n );
4906+ RBASIC_CLEAR_CLASS (ary0 );
4907+ MEMZERO (stack + 1 , long , n );
49074908 stack [0 ] = -1 ;
49084909 for (;;) {
4909- chosen [lev ] = RARRAY_AREF (ary , stack [lev + 1 ]);
49104910 for (lev ++ ; lev < n ; lev ++ ) {
4911- chosen [ lev ] = RARRAY_AREF ( ary , stack [lev + 1 ] = stack [lev ]+ 1 ) ;
4911+ stack [lev + 1 ] = stack [lev ]+ 1 ;
49124912 }
4913- rb_yield (rb_ary_new4 (n , chosen ));
4914- if (RBASIC (t0 )-> klass ) {
4913+ if (!yield_indexed_values (ary0 , n , stack + 1 )) {
49154914 rb_raise (rb_eRuntimeError , "combination reentered" );
49164915 }
49174916 do {
@@ -4920,8 +4919,8 @@ rb_ary_combination(VALUE ary, VALUE num)
49204919 } while (stack [lev + 1 ]+ n == len + lev + 1 );
49214920 }
49224921 done :
4923- tmpbuf_discard (t0 );
4924- tmpary_discard ( cc );
4922+ ALLOCV_END (t0 );
4923+ RBASIC_SET_CLASS_RAW ( ary0 , rb_cArray );
49254924 }
49264925 return ary ;
49274926}
@@ -4942,24 +4941,14 @@ rb_ary_combination(VALUE ary, VALUE num)
49424941static void
49434942rpermute0 (long n , long r , long * p , long index , VALUE values )
49444943{
4945- long i , j ;
4944+ long i ;
49464945 for (i = 0 ; i < n ; i ++ ) {
49474946 p [index ] = i ;
49484947 if (index < r - 1 ) { /* if not done yet */
49494948 rpermute0 (n , r , p , index + 1 , values ); /* recurse */
49504949 }
49514950 else {
4952- /* We have a complete permutation of array indexes */
4953- /* Build a ruby array of the corresponding values */
4954- /* And yield it to the associated block */
4955- VALUE result = rb_ary_new2 (r );
4956- VALUE * result_array = RARRAY_PTR (result );
4957- const VALUE * values_array = RARRAY_PTR (values );
4958-
4959- for (j = 0 ; j < r ; j ++ ) result_array [j ] = values_array [p [j ]];
4960- ARY_SET_LEN (result , r );
4961- rb_yield (result );
4962- if (RBASIC (values )-> klass ) {
4951+ if (!yield_indexed_values (values , r , p )) {
49634952 rb_raise (rb_eRuntimeError , "repeated permute reentered" );
49644953 }
49654954 }
@@ -5040,22 +5029,14 @@ rb_ary_repeated_permutation(VALUE ary, VALUE num)
50405029static void
50415030rcombinate0 (long n , long r , long * p , long index , long rest , VALUE values )
50425031{
5043- long j ;
50445032 if (rest > 0 ) {
50455033 for (; index < n ; ++ index ) {
50465034 p [r - rest ] = index ;
50475035 rcombinate0 (n , r , p , index , rest - 1 , values );
50485036 }
50495037 }
50505038 else {
5051- VALUE result = rb_ary_new2 (r );
5052- VALUE * result_array = RARRAY_PTR (result );
5053- const VALUE * values_array = RARRAY_PTR (values );
5054-
5055- for (j = 0 ; j < r ; ++ j ) result_array [j ] = values_array [p [j ]];
5056- ARY_SET_LEN (result , r );
5057- rb_yield (result );
5058- if (RBASIC (values )-> klass ) {
5039+ if (!yield_indexed_values (values , r , p )) {
50595040 rb_raise (rb_eRuntimeError , "repeated combination reentered" );
50605041 }
50615042 }
0 commit comments