@@ -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{
@@ -1593,6 +1585,7 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
15931585 MEMMOVE (RARRAY_PTR (ary ) + beg , RARRAY_CONST_PTR (rpl ), VALUE , rlen );
15941586 }
15951587 }
1588+ RB_GC_GUARD (rpl );
15961589}
15971590
15981591void
@@ -3077,7 +3070,7 @@ ary_reject(VALUE orig, VALUE result)
30773070 for (i = 0 ; i < RARRAY_LEN (orig ); i ++ ) {
30783071 VALUE v = RARRAY_AREF (orig , i );
30793072 if (!RTEST (rb_yield (v ))) {
3080- rb_ary_push_1 (result , v );
3073+ rb_ary_push (result , v );
30813074 }
30823075 }
30833076 return result ;
@@ -4690,6 +4683,25 @@ rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
46904683#define tmpary (n ) rb_ary_tmp_new(n)
46914684#define tmpary_discard (a ) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
46924685
4686+ /*
4687+ * Build a ruby array of the corresponding values and yield it to the
4688+ * associated block.
4689+ * Return the class of +values+ for reentry check.
4690+ */
4691+ static int
4692+ yield_indexed_values (const VALUE values , const long r , const long * const p )
4693+ {
4694+ const VALUE result = rb_ary_new2 (r );
4695+ VALUE * const result_array = RARRAY_PTR (result );
4696+ const VALUE * const values_array = RARRAY_CONST_PTR (values );
4697+ long i ;
4698+
4699+ for (i = 0 ; i < r ; i ++ ) result_array [i ] = values_array [p [i ]];
4700+ ARY_SET_LEN (result , r );
4701+ rb_yield (result );
4702+ return !RBASIC (values )-> klass ;
4703+ }
4704+
46934705/*
46944706 * Recursively compute permutations of +r+ elements of the set
46954707 * <code>[0..n-1]</code>.
@@ -4707,7 +4719,7 @@ rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
47074719static void
47084720permute0 (long n , long r , long * p , long index , char * used , VALUE values )
47094721{
4710- long i , j ;
4722+ long i ;
47114723 for (i = 0 ; i < n ; i ++ ) {
47124724 if (used [i ] == 0 ) {
47134725 p [index ] = i ;
@@ -4718,17 +4730,7 @@ permute0(long n, long r, long *p, long index, char *used, VALUE values)
47184730 used [i ] = 0 ; /* index unused */
47194731 }
47204732 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 ) {
4733+ if (!yield_indexed_values (values , r , p )) {
47324734 rb_raise (rb_eRuntimeError , "permute reentered" );
47334735 }
47344736 }
@@ -4826,7 +4828,7 @@ rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
48264828 }
48274829 }
48284830 else { /* this is the general case */
4829- volatile VALUE t0 = tmpbuf (n ,sizeof (long ));
4831+ volatile VALUE t0 = tmpbuf (r ,sizeof (long ));
48304832 long * p = (long * )RSTRING_PTR (t0 );
48314833 volatile VALUE t1 = tmpbuf (n ,sizeof (char ));
48324834 char * used = (char * )RSTRING_PTR (t1 );
@@ -4897,21 +4899,19 @@ rb_ary_combination(VALUE ary, VALUE num)
48974899 }
48984900 }
48994901 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 );
4902+ VALUE ary0 = ary_make_shared_copy (ary ); /* private defensive copy of ary */
4903+ volatile VALUE t0 ;
4904+ long * stack = ALLOCV_N (long , t0 , n + 1 );
49044905 long lev = 0 ;
49054906
4906- MEMZERO (stack , long , n );
4907+ RBASIC_CLEAR_CLASS (ary0 );
4908+ MEMZERO (stack + 1 , long , n );
49074909 stack [0 ] = -1 ;
49084910 for (;;) {
4909- chosen [lev ] = RARRAY_AREF (ary , stack [lev + 1 ]);
49104911 for (lev ++ ; lev < n ; lev ++ ) {
4911- chosen [ lev ] = RARRAY_AREF ( ary , stack [lev + 1 ] = stack [lev ]+ 1 ) ;
4912+ stack [lev + 1 ] = stack [lev ]+ 1 ;
49124913 }
4913- rb_yield (rb_ary_new4 (n , chosen ));
4914- if (RBASIC (t0 )-> klass ) {
4914+ if (!yield_indexed_values (ary0 , n , stack + 1 )) {
49154915 rb_raise (rb_eRuntimeError , "combination reentered" );
49164916 }
49174917 do {
@@ -4920,8 +4920,8 @@ rb_ary_combination(VALUE ary, VALUE num)
49204920 } while (stack [lev + 1 ]+ n == len + lev + 1 );
49214921 }
49224922 done :
4923- tmpbuf_discard (t0 );
4924- tmpary_discard ( cc );
4923+ ALLOCV_END (t0 );
4924+ RBASIC_SET_CLASS_RAW ( ary0 , rb_cArray );
49254925 }
49264926 return ary ;
49274927}
@@ -4942,24 +4942,14 @@ rb_ary_combination(VALUE ary, VALUE num)
49424942static void
49434943rpermute0 (long n , long r , long * p , long index , VALUE values )
49444944{
4945- long i , j ;
4945+ long i ;
49464946 for (i = 0 ; i < n ; i ++ ) {
49474947 p [index ] = i ;
49484948 if (index < r - 1 ) { /* if not done yet */
49494949 rpermute0 (n , r , p , index + 1 , values ); /* recurse */
49504950 }
49514951 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 ) {
4952+ if (!yield_indexed_values (values , r , p )) {
49634953 rb_raise (rb_eRuntimeError , "repeated permute reentered" );
49644954 }
49654955 }
@@ -5040,22 +5030,14 @@ rb_ary_repeated_permutation(VALUE ary, VALUE num)
50405030static void
50415031rcombinate0 (long n , long r , long * p , long index , long rest , VALUE values )
50425032{
5043- long j ;
50445033 if (rest > 0 ) {
50455034 for (; index < n ; ++ index ) {
50465035 p [r - rest ] = index ;
50475036 rcombinate0 (n , r , p , index , rest - 1 , values );
50485037 }
50495038 }
50505039 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 ) {
5040+ if (!yield_indexed_values (values , r , p )) {
50595041 rb_raise (rb_eRuntimeError , "repeated combination reentered" );
50605042 }
50615043 }
0 commit comments