@@ -32,6 +32,15 @@ int jl_array_store_unboxed(jl_value_t *el_type)
3232    return  store_unboxed (el_type );
3333}
3434
35+ STATIC_INLINE  jl_value_t  * jl_array_owner (jl_array_t  * a )
36+ {
37+     if  (a -> flags .how  ==  3 ) {
38+         a  =  (jl_array_t * )jl_array_data_owner (a );
39+         assert (a -> flags .how  !=  3 );
40+     }
41+     return  (jl_value_t * )a ;
42+ }
43+ 
3544#if  defined(_P64 ) &&  defined(UINT128MAX )
3645typedef  __uint128_t  wideint_t ;
3746#else 
@@ -190,14 +199,9 @@ JL_DLLEXPORT jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data,
190199        a -> flags .ptrarray  =  1 ;
191200    }
192201
193-     jl_array_t  * owner  =  data ;
194202    // if data is itself a shared wrapper, 
195203    // owner should point back to the original array 
196-     if  (owner -> flags .how  ==  3 ) {
197-         owner  =  (jl_array_t * )jl_array_data_owner (owner );
198-     }
199-     assert (owner -> flags .how  !=  3 );
200-     jl_array_data_owner (a ) =  (jl_value_t * )owner ;
204+     jl_array_data_owner (a ) =  jl_array_owner (data );
201205
202206    a -> flags .how  =  3 ;
203207    a -> data  =  data -> data ;
@@ -526,11 +530,7 @@ JL_DLLEXPORT void jl_arrayset(jl_array_t *a, jl_value_t *rhs, size_t i)
526530    }
527531    else  {
528532        ((jl_value_t * * )a -> data )[i ] =  rhs ;
529-         jl_value_t  * owner  =  (jl_value_t * )a ;
530-         if  (a -> flags .how  ==  3 ) {
531-             owner  =  jl_array_data_owner (a );
532-         }
533-         jl_gc_wb (owner , rhs );
533+         jl_gc_wb (jl_array_owner (a ), rhs );
534534    }
535535}
536536
@@ -921,6 +921,67 @@ JL_DLLEXPORT jl_array_t *jl_array_copy(jl_array_t *ary)
921921    return  new_ary ;
922922}
923923
924+ // Copy element by element until we hit a young object, at which point 
925+ // we can continue using `memmove`. 
926+ static  NOINLINE  ssize_t  jl_array_ptr_copy_forward (jl_value_t  * owner ,
927+                                                   void  * * src_p , void  * * dest_p ,
928+                                                   ssize_t  n )
929+ {
930+     for  (ssize_t  i  =  0 ; i  <  n ; i ++ ) {
931+         void  * val  =  src_p [i ];
932+         dest_p [i ] =  val ;
933+         // `val` is young or old-unmarked 
934+         if  (val  &&  !(jl_astaggedvalue (val )-> bits .gc  &  GC_MARKED )) {
935+             jl_gc_queue_root (owner );
936+             return  i ;
937+         }
938+     }
939+     return  n ;
940+ }
941+ 
942+ static  NOINLINE  ssize_t  jl_array_ptr_copy_backward (jl_value_t  * owner ,
943+                                                    void  * * src_p , void  * * dest_p ,
944+                                                    ssize_t  n )
945+ {
946+     for  (ssize_t  i  =  0 ; i  <  n ; i ++ ) {
947+         void  * val  =  src_p [n  -  i  -  1 ];
948+         dest_p [n  -  i  -  1 ] =  val ;
949+         // `val` is young or old-unmarked 
950+         if  (val  &&  !(jl_astaggedvalue (val )-> bits .gc  &  GC_MARKED )) {
951+             jl_gc_queue_root (owner );
952+             return  i ;
953+         }
954+     }
955+     return  n ;
956+ }
957+ 
958+ // Unsafe, assume inbounds and that dest and src have the same eltype 
959+ // `doffs` and `soffs` are zero based. 
960+ JL_DLLEXPORT  void  jl_array_ptr_copy (jl_array_t  * dest , void  * * dest_p ,
961+                                     jl_array_t  * src , void  * * src_p , ssize_t  n )
962+ {
963+     assert (dest -> flags .ptrarray  &&  src -> flags .ptrarray );
964+     jl_value_t  * owner  =  jl_array_owner (dest );
965+     // Destination is old and doesn't refer any young object 
966+     if  (__unlikely (jl_astaggedvalue (owner )-> bits .gc  ==  GC_OLD_MARKED )) {
967+         jl_value_t  * src_owner  =  jl_array_owner (src );
968+         // Source is young or might refer young objects 
969+         if  (!(jl_astaggedvalue (src_owner )-> bits .gc  &  GC_OLD )) {
970+             ssize_t  done ;
971+             if  (dest_p  <  src_p  ||  desc_p  >  src_p  +  n ) {
972+                 done  =  jl_array_ptr_copy_forward (owner , src_p , dest_p , n );
973+                 dest_p  +=  done ;
974+                 src_p  +=  done ;
975+             }
976+             else  {
977+                 done  =  jl_array_ptr_copy_backward (owner , src_p , dest_p , n );
978+             }
979+             n  -=  done ;
980+         }
981+     }
982+     memmove (dest_p , src_p , n  *  sizeof (void * ));
983+ }
984+ 
924985JL_DLLEXPORT  void  jl_array_ptr_1d_push (jl_array_t  * a , jl_value_t  * item )
925986{
926987    assert (jl_typeis (a , jl_array_any_type ));
0 commit comments