@@ -2061,7 +2061,8 @@ STATIC_INLINE void gc_mark_objarray(jl_ptls_t ptls, jl_value_t *obj_parent, jl_v
20612061 // the first young object before starting this chunk
20622062 // (this also would be valid for young objects, but probably less beneficial)
20632063 for (; obj_begin < obj_end ; obj_begin += step ) {
2064- new_obj = * obj_begin ;
2064+ jl_value_t * * slot = obj_begin ;
2065+ new_obj = * slot ;
20652066 if (new_obj != NULL ) {
20662067 verify_parent2 ("obj array" , obj_parent , obj_begin , "elem(%d)" ,
20672068 gc_slot_to_arrayidx (obj_parent , obj_begin ));
@@ -2070,7 +2071,7 @@ STATIC_INLINE void gc_mark_objarray(jl_ptls_t ptls, jl_value_t *obj_parent, jl_v
20702071 nptr |= 1 ;
20712072 if (!gc_marked (o -> header ))
20722073 break ;
2073- gc_heap_snapshot_record_array_edge (obj_parent , & new_obj );
2074+ gc_heap_snapshot_record_array_edge (obj_parent , slot );
20742075 }
20752076 }
20762077 }
@@ -2092,12 +2093,13 @@ STATIC_INLINE void gc_mark_objarray(jl_ptls_t ptls, jl_value_t *obj_parent, jl_v
20922093 }
20932094 }
20942095 for (; obj_begin < scan_end ; obj_begin += step ) {
2096+ jl_value_t * * slot = obj_begin ;
20952097 new_obj = * obj_begin ;
20962098 if (new_obj != NULL ) {
20972099 verify_parent2 ("obj array" , obj_parent , obj_begin , "elem(%d)" ,
20982100 gc_slot_to_arrayidx (obj_parent , obj_begin ));
20992101 gc_try_claim_and_push (mq , new_obj , & nptr );
2100- gc_heap_snapshot_record_array_edge (obj_parent , & new_obj );
2102+ gc_heap_snapshot_record_array_edge (obj_parent , slot );
21012103 }
21022104 }
21032105 if (too_big ) {
@@ -2128,7 +2130,8 @@ STATIC_INLINE void gc_mark_array8(jl_ptls_t ptls, jl_value_t *ary8_parent, jl_va
21282130 for (; ary8_begin < ary8_end ; ary8_begin += elsize ) {
21292131 int early_end = 0 ;
21302132 for (uint8_t * pindex = elem_begin ; pindex < elem_end ; pindex ++ ) {
2131- new_obj = ary8_begin [* pindex ];
2133+ jl_value_t * * slot = & ary8_begin [* pindex ];
2134+ new_obj = * slot ;
21322135 if (new_obj != NULL ) {
21332136 verify_parent2 ("array" , ary8_parent , & new_obj , "elem(%d)" ,
21342137 gc_slot_to_arrayidx (ary8_parent , ary8_begin ));
@@ -2139,7 +2142,7 @@ STATIC_INLINE void gc_mark_array8(jl_ptls_t ptls, jl_value_t *ary8_parent, jl_va
21392142 early_end = 1 ;
21402143 break ;
21412144 }
2142- gc_heap_snapshot_record_array_edge (ary8_parent , & new_obj );
2145+ gc_heap_snapshot_record_array_edge (ary8_parent , slot );
21432146 }
21442147 }
21452148 if (early_end )
@@ -2165,12 +2168,13 @@ STATIC_INLINE void gc_mark_array8(jl_ptls_t ptls, jl_value_t *ary8_parent, jl_va
21652168 }
21662169 for (; ary8_begin < ary8_end ; ary8_begin += elsize ) {
21672170 for (uint8_t * pindex = elem_begin ; pindex < elem_end ; pindex ++ ) {
2168- new_obj = ary8_begin [* pindex ];
2171+ jl_value_t * * slot = & ary8_begin [* pindex ];
2172+ new_obj = * slot ;
21692173 if (new_obj != NULL ) {
21702174 verify_parent2 ("array" , ary8_parent , & new_obj , "elem(%d)" ,
21712175 gc_slot_to_arrayidx (ary8_parent , ary8_begin ));
21722176 gc_try_claim_and_push (mq , new_obj , & nptr );
2173- gc_heap_snapshot_record_array_edge (ary8_parent , & new_obj );
2177+ gc_heap_snapshot_record_array_edge (ary8_parent , slot );
21742178 }
21752179 }
21762180 }
@@ -2193,7 +2197,34 @@ STATIC_INLINE void gc_mark_array16(jl_ptls_t ptls, jl_value_t *ary16_parent, jl_
21932197 jl_gc_markqueue_t * mq = & ptls -> mark_queue ;
21942198 jl_value_t * new_obj ;
21952199 size_t elsize = ((jl_array_t * )ary16_parent )-> elsize / sizeof (jl_value_t * );
2196- // Decide whether need to chunk ary16
2200+ assert (elsize > 0 );
2201+ // Decide whether need to chunk objary
2202+ if ((nptr & 0x2 ) == 0x2 ) {
2203+ // pre-scan this object: most of this object should be old, so look for
2204+ // the first young object before starting this chunk
2205+ // (this also would be valid for young objects, but probably less beneficial)
2206+ for (; ary16_begin < ary16_end ; ary16_begin += elsize ) {
2207+ int early_end = 0 ;
2208+ for (uint16_t * pindex = elem_begin ; pindex < elem_end ; pindex ++ ) {
2209+ jl_value_t * * slot = & ary16_begin [* pindex ];
2210+ new_obj = * slot ;
2211+ if (new_obj != NULL ) {
2212+ verify_parent2 ("array" , ary16_parent , & new_obj , "elem(%d)" ,
2213+ gc_slot_to_arrayidx (ary16_parent , ary16_begin ));
2214+ jl_taggedvalue_t * o = jl_astaggedvalue (new_obj );
2215+ if (!gc_old (o -> header ))
2216+ nptr |= 1 ;
2217+ if (!gc_marked (o -> header )){
2218+ early_end = 1 ;
2219+ break ;
2220+ }
2221+ gc_heap_snapshot_record_array_edge (ary16_parent , slot );
2222+ }
2223+ }
2224+ if (early_end )
2225+ break ;
2226+ }
2227+ }
21972228 size_t too_big = (ary16_end - ary16_begin ) / GC_CHUNK_BATCH_SIZE > elsize ; // use this order of operations to avoid idiv
21982229 jl_value_t * * scan_end = ary16_end ;
21992230 int pushed_chunk = 0 ;
@@ -2213,12 +2244,13 @@ STATIC_INLINE void gc_mark_array16(jl_ptls_t ptls, jl_value_t *ary16_parent, jl_
22132244 }
22142245 for (; ary16_begin < scan_end ; ary16_begin += elsize ) {
22152246 for (uint16_t * pindex = elem_begin ; pindex < elem_end ; pindex ++ ) {
2216- new_obj = ary16_begin [* pindex ];
2247+ jl_value_t * * slot = & ary16_begin [* pindex ];
2248+ new_obj = * slot ;
22172249 if (new_obj != NULL ) {
22182250 verify_parent2 ("array" , ary16_parent , & new_obj , "elem(%d)" ,
22192251 gc_slot_to_arrayidx (ary16_parent , ary16_begin ));
22202252 gc_try_claim_and_push (mq , new_obj , & nptr );
2221- gc_heap_snapshot_record_array_edge (ary16_parent , & new_obj );
2253+ gc_heap_snapshot_record_array_edge (ary16_parent , slot );
22222254 }
22232255 }
22242256 }
0 commit comments