@@ -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