@@ -516,67 +516,66 @@ static inline void objprofile_count(void* ty, int old, int sz)
516516
517517#define inc_sat (v ,s ) v = (v) >= s ? s : (v)+1
518518
519- static inline int gc_setmark_big (void * o , int mark_mode )
519+ static inline int gc_setmark_big (void * o , int bits )
520520{
521+ int mark_mode = GC_MARKED_NOESC ;
521522#ifdef GC_VERIFY
522523 if (verifying ) {
523524 _gc_setmark (o , mark_mode );
524525 return 0 ;
525526 }
526527#endif
527528 bigval_t * hdr = bigval_header (o );
528- int bits = gc_bits (o );
529- if (bits == GC_QUEUED || bits == GC_MARKED )
530- mark_mode = GC_MARKED ;
531- if ((mark_mode == GC_MARKED ) & (bits != GC_MARKED )) {
532- // Move hdr from big_objects list to big_objects_marked list
533- * hdr -> prev = hdr -> next ;
534- if (hdr -> next )
535- hdr -> next -> prev = hdr -> prev ;
536- hdr -> next = big_objects_marked ;
537- hdr -> prev = & big_objects_marked ;
538- if (big_objects_marked )
539- big_objects_marked -> prev = & hdr -> next ;
540- big_objects_marked = hdr ;
541- }
542529 if (!(bits & GC_MARKED )) {
530+ if (bits == GC_QUEUED )
531+ mark_mode = GC_MARKED ;
532+ if ((mark_mode == GC_MARKED ) & (bits != GC_MARKED )) {
533+ // Move hdr from big_objects list to big_objects_marked list
534+ * hdr -> prev = hdr -> next ;
535+ if (hdr -> next )
536+ hdr -> next -> prev = hdr -> prev ;
537+ hdr -> next = big_objects_marked ;
538+ hdr -> prev = & big_objects_marked ;
539+ if (big_objects_marked )
540+ big_objects_marked -> prev = & hdr -> next ;
541+ big_objects_marked = hdr ;
542+ }
543543 if (mark_mode == GC_MARKED )
544544 perm_scanned_bytes += hdr -> sz & ~3 ;
545545 else
546546 scanned_bytes += hdr -> sz & ~3 ;
547547#ifdef OBJPROFILE
548548 objprofile_count (jl_typeof (o ), mark_mode == GC_MARKED , hdr -> sz & ~3 );
549549#endif
550+ _gc_setmark (o , mark_mode );
550551 }
551- _gc_setmark (o , mark_mode );
552552 verify_val (jl_valueof (o ));
553553 return mark_mode ;
554554}
555555
556- static inline int gc_setmark_pool (void * o , int mark_mode )
556+ static inline int gc_setmark_pool (void * o , int bits )
557557{
558+ int mark_mode = GC_MARKED_NOESC ;
558559#ifdef GC_VERIFY
559560 if (verifying ) {
560561 _gc_setmark (o , mark_mode );
561562 return mark_mode ;
562563 }
563564#endif
564- gcpage_t * page = page_metadata (o );
565- int bits = gc_bits (o );
566- if (bits == GC_QUEUED || bits == GC_MARKED ) {
567- mark_mode = GC_MARKED ;
568- }
569565 if (!(bits & GC_MARKED )) {
566+ if (bits == GC_QUEUED )
567+ mark_mode = GC_MARKED ;
568+ gcpage_t * page = page_metadata (o );
570569 if (mark_mode == GC_MARKED )
571570 perm_scanned_bytes += page -> osize ;
572571 else
573572 scanned_bytes += page -> osize ;
574573#ifdef OBJPROFILE
575574 objprofile_count (jl_typeof (o ), mark_mode == GC_MARKED , page -> osize );
576575#endif
576+ _gc_setmark (o , mark_mode );
577+ page -> gc_bits |= mark_mode ;
577578 }
578- _gc_setmark (o , mark_mode );
579- page -> gc_bits |= mark_mode ;
580579 verify_val (jl_valueof (o ));
581580 return mark_mode ;
582581}
@@ -601,14 +600,19 @@ static inline int gc_setmark(jl_value_t *v, int sz, int mark_mode)
601600inline void gc_setmark_buf (void * o , int mark_mode )
602601{
603602 buff_t * buf = gc_val_buf (o );
603+ int bits = gc_bits (buf );
604+ if (mark_mode == GC_MARKED && bits != GC_MARKED ) {
605+ _gc_setmark (buf , GC_QUEUED );
606+ bits = GC_QUEUED ;
607+ }
604608#ifdef MEMDEBUG
605- gc_setmark_big (buf , mark_mode );
609+ gc_setmark_big (buf , bits );
606610 return ;
607611#endif
608612 if (buf -> pooled )
609- gc_setmark_pool (buf , mark_mode );
613+ gc_setmark_pool (buf , bits );
610614 else
611- gc_setmark_big (buf , mark_mode );
615+ gc_setmark_big (buf , bits );
612616}
613617
614618static NOINLINE void * malloc_page (void )
@@ -1450,16 +1454,20 @@ void jl_gc_setmark(jl_value_t *v) // TODO rename this as it is misleading now
14501454 if (!gc_marked (o )) {
14511455 // objprofile_count(jl_typeof(v), 1, 16);
14521456#ifdef MEMDEBUG
1453- gc_setmark_big (o , GC_MARKED_NOESC );
1457+ gc_setmark_big (o , gc_bits ( o ) );
14541458#else
1455- gc_setmark_pool (o , GC_MARKED_NOESC );
1459+ gc_setmark_pool (o , gc_bits ( o ) );
14561460#endif
14571461 }
14581462 // perm_scanned_bytes = s;
14591463}
1460-
1464+ static char * gc_stack_top ;
1465+ static char * gc_stack_bot ;
14611466static void gc_mark_stack (jl_value_t * ta , jl_gcframe_t * s , ptrint_t offset , int d )
14621467{
1468+ jl_task_t * task = (jl_task_t * )ta ;
1469+ char * stkbuf = task == jl_current_task ? gc_stack_top : task -> stkbuf ;
1470+ char * stkend = task == jl_current_task ? gc_stack_bot : stkbuf + task -> ssize ;
14631471 while (s != NULL ) {
14641472 s = (jl_gcframe_t * )((char * )s + offset );
14651473 jl_value_t * * * rts = (jl_value_t * * * )(((void * * )s )+ 2 );
@@ -1473,9 +1481,17 @@ static void gc_mark_stack(jl_value_t* ta, jl_gcframe_t *s, ptrint_t offset, int
14731481 }
14741482 else {
14751483 for (size_t i = 0 ; i < nr ; i ++ ) {
1476- if (rts [i ] != NULL ) {
1484+ void * v = rts [i ];
1485+ if (v != NULL ) {
14771486 verify_parent2 ("task" , ta , & rts [i ], "stack(%d)" , (int )i );
1478- gc_push_root (rts [i ], d );
1487+ if (stkbuf <= (char * )v && (char * )v <= stkend ) {
1488+ // if v is on the stack it is kept permanently marked
1489+ // but we still need to scan it once
1490+ push_root (v , d , gc_bits (jl_astaggedvalue (v )));
1491+ }
1492+ else {
1493+ gc_push_root (v , d );
1494+ }
14791495 }
14801496 }
14811497 }
@@ -1576,12 +1592,12 @@ static int push_root(jl_value_t *v, int d, int bits)
15761592 int refyoung = 0 ;
15771593
15781594 if (vt == (jl_value_t * )jl_weakref_type ) {
1579- bits = gc_setmark (v , sizeof (jl_weakref_t ), GC_MARKED_NOESC );
1595+ bits = gc_setmark (v , sizeof (jl_weakref_t ), bits );
15801596 goto ret ;
15811597 }
15821598 if ((jl_is_datatype (vt ) && ((jl_datatype_t * )vt )-> pointerfree )) {
15831599 int sz = jl_datatype_size (vt );
1584- bits = gc_setmark (v , sz , GC_MARKED_NOESC );
1600+ bits = gc_setmark (v , sz , bits );
15851601 goto ret ;
15861602 }
15871603#define MARK (v , s ) do { \
@@ -1597,7 +1613,7 @@ static int push_root(jl_value_t *v, int d, int bits)
15971613 // some values have special representations
15981614 if (vt == (jl_value_t * )jl_simplevector_type ) {
15991615 size_t l = jl_svec_len (v );
1600- MARK (v , bits = gc_setmark (v , l * sizeof (void * ) + sizeof (jl_svec_t ), GC_MARKED_NOESC ));
1616+ MARK (v , bits = gc_setmark (v , l * sizeof (void * ) + sizeof (jl_svec_t ), bits ));
16011617 jl_value_t * * data = ((jl_svec_t * )v )-> data ;
16021618 for (size_t i = 0 ; i < l ; i ++ ) {
16031619 jl_value_t * elt = data [i ];
@@ -1618,7 +1634,7 @@ static int push_root(jl_value_t *v, int d, int bits)
16181634#define _gc_setmark_pool gc_setmark_pool
16191635#endif
16201636 MARK (a ,
1621- bits = _gc_setmark_pool (o , GC_MARKED_NOESC );
1637+ bits = _gc_setmark_pool (o , bits );
16221638 if (a -> how == 2 && todo ) {
16231639 objprofile_count (MATY , gc_bits (o ) == GC_MARKED , array_nbytes (a ));
16241640 if (gc_bits (o ) == GC_MARKED )
@@ -1628,7 +1644,7 @@ static int push_root(jl_value_t *v, int d, int bits)
16281644 });
16291645 else
16301646 MARK (a ,
1631- bits = gc_setmark_big (o , GC_MARKED_NOESC );
1647+ bits = gc_setmark_big (o , bits );
16321648 if (a -> how == 2 && todo ) {
16331649 objprofile_count (MATY , gc_bits (o ) == GC_MARKED , array_nbytes (a ));
16341650 if (gc_bits (o ) == GC_MARKED )
@@ -1670,11 +1686,11 @@ static int push_root(jl_value_t *v, int d, int bits)
16701686 }
16711687 }
16721688 else if (vt == (jl_value_t * )jl_module_type ) {
1673- MARK (v , bits = gc_setmark (v , sizeof (jl_module_t ), GC_MARKED_NOESC ));
1689+ MARK (v , bits = gc_setmark (v , sizeof (jl_module_t ), bits ));
16741690 refyoung |= gc_mark_module ((jl_module_t * )v , d );
16751691 }
16761692 else if (vt == (jl_value_t * )jl_task_type ) {
1677- MARK (v , bits = gc_setmark (v , sizeof (jl_task_t ), GC_MARKED_NOESC ));
1693+ MARK (v , bits = gc_setmark (v , sizeof (jl_task_t ), bits ));
16781694 gc_mark_task ((jl_task_t * )v , d );
16791695 // tasks should always be remarked since we do not trigger the write barrier
16801696 // for stores to stack slots
@@ -1697,7 +1713,7 @@ static int push_root(jl_value_t *v, int d, int bits)
16971713 dtsz = NWORDS (sizeof (jl_datatype_t ) + jl_datatype_nfields (v )* sizeof (jl_fielddesc_t ))* sizeof (void * );
16981714 else
16991715 dtsz = jl_datatype_size (dt );
1700- MARK (v , bits = gc_setmark (v , dtsz , GC_MARKED_NOESC ));
1716+ MARK (v , bits = gc_setmark (v , dtsz , bits ));
17011717 int nf = (int )jl_datatype_nfields (dt );
17021718 // TODO check if there is a perf improvement for objects with a lot of fields
17031719 // int fdsz = sizeof(void*)*nf;
@@ -1956,6 +1972,7 @@ void jl_gc_collect(int full)
19561972 JL_SIGATOMIC_BEGIN ();
19571973 jl_in_gc = 1 ;
19581974 uint64_t t0 = jl_hrtime ();
1975+ gc_stack_top = (char * )& t0 ;
19591976 int recollect = 0 ;
19601977#if defined(GC_TIME )
19611978 int wb_activations = mark_sp - saved_mark_sp ;
@@ -2366,6 +2383,8 @@ void jl_gc_init(void)
23662383 if (maxmem > max_collect_interval )
23672384 max_collect_interval = maxmem ;
23682385#endif
2386+ char _dummy ;
2387+ gc_stack_bot = & _dummy ;
23692388}
23702389
23712390// GC summary stats
0 commit comments