@@ -803,7 +803,7 @@ static int mark_reset_age = 0;
803803 * 
804804 * <-[(quick)sweep]- 
805805 *                 | 
806-  *     ---->  GC_OLD  <--[(quick)sweep && age>promotion] -- 
806+  *     ---->  GC_OLD  <--[(quick)sweep]----------------- -- 
807807 *     |     |                                           | 
808808 *     |     |  GC_MARKED (in remset)                    | 
809809 *     |     |     ^            |                        | 
@@ -820,9 +820,9 @@ static int mark_reset_age = 0;
820820 *  ========= above this line objects are old =========  | 
821821 *                                                       | 
822822 *  ----[new]------> GC_CLEAN ------[mark]-----------> GC_MARKED 
823-  *                    |    ^                                   |  
824-  *  <-[(quick)sweep]---    |                                   |  
825-  *                         --[(quick)sweep && age<=promotion]---  
823+  *                    | 
824+  *  <-[(quick)sweep]--- 
825+  * 
826826 */ 
827827
828828// A quick sweep is a sweep where `!sweep_full` 
@@ -836,20 +836,11 @@ static int mark_reset_age = 0;
836836// When a write barrier triggers, the offending marked object is both queued, 
837837// so as not to trigger the barrier again, and put in the remset. 
838838
839- 
840- #define  PROMOTE_AGE  1
841- // this cannot be increased as is without changing : 
842- // - sweep_page which is specialized for 1bit age 
843- // - the size of the age storage in jl_gc_pagemeta_t 
844- 
845- 
846839static  int64_t  scanned_bytes ; // young bytes scanned while marking 
847840static  int64_t  perm_scanned_bytes ; // old bytes scanned while marking 
848841int  prev_sweep_full  =  1 ;
849842int  current_sweep_full  =  0 ;
850843
851- #define  inc_sat (v ,s ) v = (v) >= s ? s : (v)+1
852- 
853844// Full collection heuristics 
854845static  int64_t  pool_live_bytes  =  0 ;
855846static  int64_t  live_bytes  =  0 ;
@@ -954,9 +945,8 @@ STATIC_INLINE void gc_setmark_big(jl_ptls_t ptls, jl_taggedvalue_t *o,
954945        // We can't easily tell if the object is old or being promoted 
955946        // from the gc bits but if the `age` is `0` then the object 
956947        // must be already on a young list. 
957-         if  (mark_reset_age   &&   hdr -> age ) {
948+         if  (mark_reset_age ) {
958949            // Reset the object as if it was just allocated 
959-             hdr -> age  =  0 ;
960950            gc_queue_big_marked (ptls , hdr , 1 );
961951        }
962952    }
@@ -981,10 +971,6 @@ STATIC_INLINE void gc_setmark_pool_(jl_ptls_t ptls, jl_taggedvalue_t *o,
981971        ptls -> gc_cache .scanned_bytes  +=  page -> osize ;
982972        if  (mark_reset_age ) {
983973            page -> has_young  =  1 ;
984-             char  * page_begin  =  gc_page_data (o ) +  GC_PAGE_OFFSET ;
985-             int  obj_id  =  (((char * )o ) -  page_begin ) / page -> osize ;
986-             uint8_t  * ages  =  page -> ages  +  obj_id  / 8 ;
987-             jl_atomic_fetch_and_relaxed ((_Atomic (uint8_t )* )ages , ~(1  << (obj_id  % 8 )));
988974        }
989975    }
990976    objprofile_count (jl_typeof (jl_valueof (o )),
@@ -1035,37 +1021,6 @@ void gc_setmark_buf(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) JL
10351021    gc_setmark_buf_ (ptls , o , mark_mode , minsz );
10361022}
10371023
1038- void  jl_gc_force_mark_old (jl_ptls_t  ptls , jl_value_t  * v ) JL_NOTSAFEPOINT 
1039- {
1040-     jl_taggedvalue_t  * o  =  jl_astaggedvalue (v );
1041-     jl_datatype_t  * dt  =  (jl_datatype_t * )jl_typeof (v );
1042-     size_t  dtsz  =  jl_datatype_size (dt );
1043-     if  (o -> bits .gc  ==  GC_OLD_MARKED )
1044-         return ;
1045-     o -> bits .gc  =  GC_OLD_MARKED ;
1046-     if  (dt  ==  jl_simplevector_type ) {
1047-         size_t  l  =  jl_svec_len (v );
1048-         dtsz  =  l  *  sizeof (void * ) +  sizeof (jl_svec_t );
1049-     }
1050-     else  if  (dt -> name  ==  jl_array_typename ) {
1051-         jl_array_t  * a  =  (jl_array_t * )v ;
1052-         if  (!a -> flags .pooled )
1053-             dtsz  =  GC_MAX_SZCLASS  +  1 ;
1054-     }
1055-     else  if  (dt  ==  jl_module_type ) {
1056-         dtsz  =  sizeof (jl_module_t );
1057-     }
1058-     else  if  (dt  ==  jl_task_type ) {
1059-         dtsz  =  sizeof (jl_task_t );
1060-     }
1061-     else  if  (dt  ==  jl_symbol_type ) {
1062-         return ;
1063-     }
1064-     gc_setmark (ptls , o , GC_OLD_MARKED , dtsz );
1065-     if  (dt -> layout -> npointers  !=  0 )
1066-         jl_gc_queue_root (v );
1067- }
1068- 
10691024STATIC_INLINE  void  maybe_collect (jl_ptls_t  ptls )
10701025{
10711026    if  (jl_atomic_load_relaxed (& ptls -> gc_num .allocd ) >= 0  ||  jl_gc_debug_check_other ()) {
@@ -1161,7 +1116,6 @@ STATIC_INLINE jl_value_t *jl_gc_big_alloc_inner(jl_ptls_t ptls, size_t sz)
11611116    memset (v , 0xee , allocsz );
11621117#endif 
11631118    v -> sz  =  allocsz ;
1164-     v -> age  =  0 ;
11651119    gc_big_object_link (v , & ptls -> heap .big_objects );
11661120    return  jl_valueof (& v -> header );
11671121}
@@ -1199,16 +1153,8 @@ static bigval_t **sweep_big_list(int sweep_full, bigval_t **pv) JL_NOTSAFEPOINT
11991153        int  old_bits  =  bits ;
12001154        if  (gc_marked (bits )) {
12011155            pv  =  & v -> next ;
1202-             int  age  =  v -> age ;
1203-             if  (age  >= PROMOTE_AGE  ||  bits  ==  GC_OLD_MARKED ) {
1204-                 if  (sweep_full  ||  bits  ==  GC_MARKED ) {
1205-                     bits  =  GC_OLD ;
1206-                 }
1207-             }
1208-             else  {
1209-                 inc_sat (age , PROMOTE_AGE );
1210-                 v -> age  =  age ;
1211-                 bits  =  GC_CLEAN ;
1156+             if  (sweep_full  ||  bits  ==  GC_MARKED ) {
1157+                 bits  =  GC_OLD ;
12121158            }
12131159            v -> bits .gc  =  bits ;
12141160        }
@@ -1386,14 +1332,13 @@ STATIC_INLINE jl_taggedvalue_t *gc_reset_page(jl_ptls_t ptls2, const jl_gc_pool_
13861332    assert (GC_PAGE_OFFSET  >= sizeof (void * ));
13871333    pg -> nfree  =  (GC_PAGE_SZ  -  GC_PAGE_OFFSET ) / p -> osize ;
13881334    pg -> pool_n  =  p  -  ptls2 -> heap .norm_pools ;
1389-     memset (pg -> ages , 0 , GC_PAGE_SZ  / 8  / p -> osize  +  1 );
13901335    jl_taggedvalue_t  * beg  =  (jl_taggedvalue_t * )(pg -> data  +  GC_PAGE_OFFSET );
13911336    pg -> has_young  =  0 ;
13921337    pg -> has_marked  =  0 ;
1393-     pg -> fl_begin_offset  =  -1 ;
1394-     pg -> fl_end_offset  =  -1 ;
13951338    pg -> prev_nold  =  0 ;
13961339    pg -> nold  =  0 ;
1340+     pg -> fl_begin_offset  =  UINT16_MAX ;
1341+     pg -> fl_end_offset  =  UINT16_MAX ;
13971342    return  beg ;
13981343}
13991344
@@ -1416,7 +1361,6 @@ static NOINLINE jl_taggedvalue_t *gc_add_page(jl_gc_pool_t *p) JL_NOTSAFEPOINT
14161361        pg  =  jl_gc_alloc_page ();
14171362    }
14181363    pg -> osize  =  p -> osize ;
1419-     pg -> ages  =  (uint8_t * )malloc_s (GC_PAGE_SZ  / 8  / p -> osize  +  1 );
14201364    pg -> thread_n  =  ptls -> tid ;
14211365    set_page_metadata (pg );
14221366    push_lf_back (& ptls -> page_metadata_allocd , pg );
@@ -1524,7 +1468,6 @@ static void gc_sweep_page(jl_gc_pool_t *p, jl_gc_page_stack_t *allocd, jl_gc_pag
15241468                          jl_gc_pagemeta_t  * pg , int  osize ) JL_NOTSAFEPOINT 
15251469{
15261470    char  * data  =  pg -> data ;
1527-     uint8_t  * ages  =  pg -> ages ;
15281471    jl_taggedvalue_t  * v  =  (jl_taggedvalue_t * )(data  +  GC_PAGE_OFFSET );
15291472    char  * lim  =  data  +  GC_PAGE_SZ  -  osize ;
15301473    char  * lim_newpages  =  data  +  GC_PAGE_SZ ;
@@ -1572,43 +1515,25 @@ static void gc_sweep_page(jl_gc_pool_t *p, jl_gc_page_stack_t *allocd, jl_gc_pag
15721515        jl_taggedvalue_t  * fl  =  NULL ;
15731516        jl_taggedvalue_t  * * pfl  =  & fl ;
15741517        jl_taggedvalue_t  * * pfl_begin  =  NULL ;
1575-         uint8_t  msk  =  1 ; // mask for the age bit in the current age byte 
15761518        while  ((char * )v  <= lim ) {
15771519            int  bits  =  v -> bits .gc ;
15781520            // if an object is past `lim_newpages` then we can guarantee it's garbage 
15791521            if  (!gc_marked (bits ) ||  (char * )v  >= lim_newpages ) {
15801522                * pfl  =  v ;
15811523                pfl  =  & v -> next ;
1582-                 pfl_begin  =  pfl_begin  ? pfl_begin  : pfl ;
1524+                 pfl_begin  =  ( pfl_begin   !=   NULL )  ? pfl_begin  : pfl ;
15831525                pg_nfree ++ ;
1584-                 * ages  &= ~msk ;
15851526            }
15861527            else  { // marked young or old 
1587-                 if  (* ages  &  msk  ||  bits  ==  GC_OLD_MARKED ) { // old enough 
1588-                     // `!age && bits == GC_OLD_MARKED` is possible for 
1589-                     // non-first-class objects like `jl_binding_t` 
1590-                     if  (current_sweep_full  ||  bits  ==  GC_MARKED ) {
1591-                         bits  =  v -> bits .gc  =  GC_OLD ; // promote 
1592-                     }
1593-                     prev_nold ++ ;
1594-                 }
1595-                 else  {
1596-                     assert (bits  ==  GC_MARKED );
1597-                     bits  =  v -> bits .gc  =  GC_CLEAN ; // unmark 
1598-                     has_young  =  1 ;
1528+                 if  (current_sweep_full  ||  bits  ==  GC_MARKED ) { // old enough 
1529+                     bits  =  v -> bits .gc  =  GC_OLD ; // promote 
15991530                }
1531+                 prev_nold ++ ;
16001532                has_marked  |= gc_marked (bits );
1601-                 * ages  |= msk ;
16021533                freedall  =  0 ;
16031534            }
16041535            v  =  (jl_taggedvalue_t * )((char * )v  +  osize );
1605-             msk  <<= 1 ;
1606-             if  (!msk ) {
1607-                 msk  =  1 ;
1608-                 ages ++ ;
1609-             }
16101536        }
1611- 
16121537        assert (!freedall );
16131538        pg -> has_marked  =  has_marked ;
16141539        pg -> has_young  =  has_young ;
@@ -1617,8 +1542,8 @@ static void gc_sweep_page(jl_gc_pool_t *p, jl_gc_page_stack_t *allocd, jl_gc_pag
16171542            pg -> fl_end_offset  =  (char * )pfl  -  data ;
16181543        }
16191544        else  {
1620-             pg -> fl_begin_offset  =  -1 ;
1621-             pg -> fl_end_offset  =  -1 ;
1545+             pg -> fl_begin_offset  =  UINT16_MAX ;
1546+             pg -> fl_end_offset  =  UINT16_MAX ;
16221547        }
16231548
16241549        pg -> nfree  =  pg_nfree ;
@@ -1668,7 +1593,7 @@ static void gc_sweep_other(jl_ptls_t ptls, int sweep_full) JL_NOTSAFEPOINT
16681593
16691594static  void  gc_pool_sync_nfree (jl_gc_pagemeta_t  * pg , jl_taggedvalue_t  * last ) JL_NOTSAFEPOINT 
16701595{
1671-     assert (pg -> fl_begin_offset  !=  ( uint16_t ) -1 );
1596+     assert (pg -> fl_begin_offset  !=  UINT16_MAX );
16721597    char  * cur_pg  =  gc_page_data (last );
16731598    // Fast path for page that has no allocation 
16741599    jl_taggedvalue_t  * fl_beg  =  (jl_taggedvalue_t * )(cur_pg  +  pg -> fl_begin_offset );
@@ -1777,7 +1702,7 @@ static void gc_sweep_pool(void)
17771702            pfl [t_i  *  JL_GC_N_POOLS  +  i ] =  & p -> freelist ;
17781703
17791704            last  =  p -> newpages ;
1780-             if  (last ) {
1705+             if  (last   !=   NULL ) {
17811706                char  * last_p  =  (char * )last ;
17821707                jl_gc_pagemeta_t  * pg  =  jl_assume (page_metadata_unsafe (last_p  -  1 ));
17831708                assert (last_p  -  gc_page_data (last_p  -  1 ) >= GC_PAGE_OFFSET );
@@ -4010,7 +3935,6 @@ jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz)
40103935    // old pointer. 
40113936    bigval_t  * newbig  =  (bigval_t * )gc_managed_realloc_ (ptls , hdr , allocsz , oldsz , 1 , s , 0 );
40123937    newbig -> sz  =  allocsz ;
4013-     newbig -> age  =  0 ;
40143938    gc_big_object_link (newbig , & ptls -> heap .big_objects );
40153939    jl_value_t  * snew  =  jl_valueof (& newbig -> header );
40163940    * (size_t * )snew  =  sz ;
@@ -4184,7 +4108,7 @@ JL_DLLEXPORT jl_value_t *jl_gc_internal_obj_base_ptr(void *p)
41844108{
41854109    p  =  (char  * ) p  -  1 ;
41864110    jl_gc_pagemeta_t  * meta  =  page_metadata (p );
4187-     if  (meta   &&   meta -> ages ) {
4111+     if  (meta ) {
41884112        char  * page  =  gc_page_data (p );
41894113        // offset within page. 
41904114        size_t  off  =  (char  * )p  -  page ;
@@ -4219,7 +4143,7 @@ JL_DLLEXPORT jl_value_t *jl_gc_internal_obj_base_ptr(void *p)
42194143            char  * data  =  gc_page_data (newpages );
42204144            if  (data  !=  meta -> data ) {
42214145                // Pages on newpages form a linked list where only the 
4222-                 // first one is allocated from (see reset_page ()). 
4146+                 // first one is allocated from (see gc_reset_page ()). 
42234147                // All other pages are empty. 
42244148                return  NULL ;
42254149            }
@@ -4247,19 +4171,16 @@ JL_DLLEXPORT jl_value_t *jl_gc_internal_obj_base_ptr(void *p)
42474171        // entries and 1 for live objects. The above subcases arise 
42484172        // because allocating a cell will not update the age bit, so we 
42494173        // need extra logic for pages that have been allocated from. 
4250-         unsigned  obj_id  =  (off  -  off2 ) / osize ;
42514174        // We now distinguish between the second and third subcase. 
42524175        // Freelist entries are consumed in ascending order. Anything 
42534176        // before the freelist pointer was either live during the last 
42544177        // sweep or has been allocated since. 
42554178        if  (gc_page_data (cell ) ==  gc_page_data (pool -> freelist )
42564179            &&  (char  * )cell  <  (char  * )pool -> freelist )
42574180            goto valid_object ;
4258-         // We know now that the age bit reflects liveness status during 
4259-         // the last sweep and that the cell has not been reused since. 
4260-         if  (!(meta -> ages [obj_id  / 8 ] &  (1  << (obj_id  % 8 )))) {
4261-             return  NULL ;
4262-         }
4181+         // already skipped marked or old objects above, so here 
4182+         // the age bits are 0, thus the object is on the freelist 
4183+         return  NULL ;
42634184        // Not a freelist entry, therefore a valid object. 
42644185    valid_object :
42654186        // We have to treat objects with type `jl_buff_tag` differently, 
0 commit comments