3737** Various options controlling special features of the Julia GC code follow
3838*/
3939
40- // if DISABLE_BIGVAL_TRACKING is defined, we don't track the location of
41- // large bags; this speeds up some things, but may expose bugs in GAP code
42- // which incorrectly holds pointers into bags over a GC.
43- // #define DISABLE_BIGVAL_TRACKING
40+ // if SCAN_STACK_FOR_MPTRS_ONLY is defined, stack scanning will only
41+ // look for references to master pointers, but not bags themselves.
42+ // This should be safe, as Gasman uses the same mechanism, but it is
43+ // at least theoretically possible that an optimizing compiler will
44+ // remove the last master pointer reference before the last reference
45+ // to the bag itself.
46+ #define SCAN_STACK_FOR_MPTRS_ONLY
4447
4548// if REQUIRE_PRECISE_MARKING is defined, we assume that all marking
4649// functions are precise, i.e., they only invoke MarkBag on valid bags,
5457// if MARKING_STRESS_TEST is defined, we stress test the TryMark code
5558// #define MARKING_STRESS_TEST
5659
60+ // if VALIDATE_MARKING is defined, the program is aborted if we ever
61+ // encounter a reference during marking that does not meet additional
62+ // validation criteria. These tests are compararively expensive and
63+ // should not be enabled by default.
64+ // #define VALIDATE_MARKING
65+
5766
5867/****************************************************************************
5968**
@@ -124,7 +133,7 @@ static void JFinalizer(jl_value_t * obj)
124133 TabFreeFuncBags [tnum ]((Bag )& contents );
125134}
126135
127- #if !defined(DISABLE_BIGVAL_TRACKING )
136+ #if !defined(SCAN_STACK_FOR_MPTRS_ONLY )
128137
129138/****************************************************************************
130139**
@@ -196,7 +205,7 @@ static inline void * align_ptr(void * p)
196205 return (void * )u ;
197206}
198207
199- #if !defined(DISABLE_BIGVAL_TRACKING )
208+ #if !defined(SCAN_STACK_FOR_MPTRS_ONLY )
200209
201210typedef struct treap_t {
202211 struct treap_t * left , * right ;
@@ -403,7 +412,7 @@ static UInt StackAlignBags;
403412static Bag * GapStackBottom ;
404413static jl_ptls_t JuliaTLS , SaveTLS ;
405414static size_t max_pool_obj_size ;
406- #if !defined(DISABLE_BIGVAL_TRACKING )
415+ #if !defined(SCAN_STACK_FOR_MPTRS_ONLY )
407416static size_t bigval_startoffset ;
408417#endif
409418static UInt YoungRef ;
@@ -448,11 +457,29 @@ void InitMarkFuncBags(UInt type, TNumMarkFuncBags mark_func)
448457 TabMarkFuncBags [type ] = mark_func ;
449458}
450459
460+ static inline int JMarkGapObjSafe (void * obj )
461+ {
462+ // only traverse objects internally used by GAP
463+ void * ty = jl_typeof (obj );
464+ if (ty != datatype_mptr && ty != datatype_bag
465+ && ty != datatype_largebag && ty != jl_weakref_type )
466+ return 0 ;
467+ return jl_gc_mark_queue_obj (JuliaTLS , (jl_value_t * )obj );
468+ }
469+
451470static inline int JMark (void * obj )
452471{
472+ #ifdef VALIDATE_MARKING
473+ jl_value_t * ty = jl_typeof (obj );
474+ if (jl_gc_internal_obj_base_ptr (ty ) != ty )
475+ abort ();
476+ if (!jl_typeis (ty , jl_datatype_type ))
477+ abort ();
478+ #endif
453479 return jl_gc_mark_queue_obj (JuliaTLS , (jl_value_t * )obj );
454480}
455481
482+
456483// Overview of conservative stack scanning
457484//
458485// A key aspect of conservative marking is that (1) we need to determine
@@ -482,7 +509,7 @@ static void TryMark(void * p)
482509{
483510 jl_value_t * p2 = jl_gc_internal_obj_base_ptr (p );
484511 if (!p2 ) {
485- #if !defined(DISABLE_BIGVAL_TRACKING )
512+ #if !defined(SCAN_STACK_FOR_MPTRS_ONLY )
486513 // It is possible for p to point past the end of
487514 // the object, so we subtract one word from the
488515 // address. This is safe, as the object is preceded
@@ -513,7 +540,12 @@ static void TryMark(void * p)
513540#endif
514541 }
515542 if (p2 ) {
516- JMark (p2 );
543+ #ifdef SCAN_STACK_FOR_MPTRS_ONLY
544+ if (jl_typeis (p2 , datatype_mptr ))
545+ JMark (p2 );
546+ #else
547+ JMarkGapObjSafe (p2 );
548+ #endif
517549 }
518550}
519551
@@ -575,7 +607,7 @@ static void GapRootScanner(int full)
575607{
576608 // mark our Julia module (this contains references to our custom data
577609 // types, which thus also will not be collected prematurely)
578- JMark ( Module );
610+ jl_gc_mark_queue_obj ( JuliaTLS , ( jl_value_t * ) Module );
579611 jl_task_t * task = JuliaTLS -> current_task ;
580612 size_t size ;
581613 int tid ;
@@ -687,7 +719,11 @@ static uintptr_t JMarkMPtr(jl_ptls_t ptls, jl_value_t * obj)
687719{
688720 if (!* (void * * )obj )
689721 return 0 ;
690- if (JMark (BAG_HEADER ((Bag )obj )))
722+ void * header = BAG_HEADER ((Bag ) obj );
723+ void * ty = jl_typeof (header );
724+ if (ty != datatype_bag && ty != datatype_largebag )
725+ return 0 ;
726+ if (JMark (header ))
691727 return 1 ;
692728 return 0 ;
693729}
@@ -712,7 +748,7 @@ void InitBags(UInt initial_size, Bag * stack_bottom, UInt stack_align)
712748 TabMarkFuncBags [i ] = MarkAllSubBags ;
713749 // These callbacks need to be set before initialization so
714750 // that we can track objects allocated during `jl_init()`.
715- #if !defined(DISABLE_BIGVAL_TRACKING )
751+ #if !defined(SCAN_STACK_FOR_MPTRS_ONLY )
716752 jl_gc_set_cb_notify_external_alloc (alloc_bigval , 1 );
717753 jl_gc_set_cb_notify_external_free (free_bigval , 1 );
718754 bigval_startoffset = jl_gc_external_obj_hdr_size ();
@@ -825,7 +861,7 @@ Bag NewBag(UInt type, UInt size)
825861 if (size == 0 )
826862 alloc_size ++ ;
827863
828- #if defined(DISABLE_BIGVAL_TRACKING )
864+ #if defined(SCAN_STACK_FOR_MPTRS_ONLY )
829865 bag = jl_gc_alloc_typed (JuliaTLS , sizeof (void * ), datatype_mptr );
830866 SET_PTR_BAG (bag , 0 );
831867#endif
@@ -837,7 +873,7 @@ Bag NewBag(UInt type, UInt size)
837873 header -> size = size ;
838874
839875
840- #if !defined(DISABLE_BIGVAL_TRACKING )
876+ #if !defined(SCAN_STACK_FOR_MPTRS_ONLY )
841877 // allocate the new masterpointer
842878 bag = jl_gc_alloc_typed (JuliaTLS , sizeof (void * ), datatype_mptr );
843879 SET_PTR_BAG (bag , DATA (header ));
@@ -943,18 +979,19 @@ inline void MarkBag(Bag bag)
943979 // relies on Julia internals. It is functionally equivalent
944980 // to:
945981 //
946- // if (JMark (p)) YoungRef++;
982+ // if (JMarkGapObjSafe (p)) YoungRef++;
947983 //
948984 switch (jl_astaggedvalue (p )-> bits .gc ) {
949985 case 0 :
950- if (JMark (p ))
986+ if (JMarkGapObjSafe (p ))
951987 YoungRef ++ ;
952988 break ;
953989 case 1 :
954990 YoungRef ++ ;
955991 break ;
956992 case 2 :
957- JMark (p );
993+ JMarkGapObjSafe (p );
994+ break ;
958995 case 3 :
959996 break ;
960997 }
0 commit comments