diff --git a/src/julia_gc.c b/src/julia_gc.c index 9320b0c099..06d2379581 100644 --- a/src/julia_gc.c +++ b/src/julia_gc.c @@ -83,7 +83,7 @@ void JFinalizer(void * obj) /**************************************************************************** ** ** Treap functionality -** +** ** Treaps are probabilistically balanced binary trees. We use them for ** range queries on pointers for conservative scans. Unlike red-black ** trees, they're simple to implement, and unlike AVL trees, insertions @@ -405,6 +405,31 @@ static inline int JMark(void * obj) return jl_gc_mark_queue_obj(JContext, obj); } +// Overview of conservative stack scanning +// +// A key aspect of conservative marking is that (1) we need to determine +// whether a machine word is a pointer to a live object and (2) if it points +// to the interior of the object, to determine its base address. +// +// For Julia's internal objects, we call back to Julia to find out the +// necessary information. For external objects that we allocate ourselves in +// `alloc_bigval()`, we use balanced binary trees (treaps) to determine that +// information. Each node in such a tree contains an (address, size) pair +// and we use the usual binary tree search to figure out whether there is a +// node with an address range containing that address and, if so, returns +// the `address` part of the pair. +// +// While at the C level, we will generally always have a reference to the +// masterpointer, the presence of optimizing compilers, multiple threads, or +// Julia tasks (= coroutines) means that we cannot necessarily rely on this +// information; also, the `NewBag()` implementation may trigger a GC after +// allocating the bag contents, but before allocating the master pointer. +// +// As a consequence, we play it safe and assume that any word anywhere on +// the stack (including Julia task stacks) that points to a master pointer +// or the contents of a bag (including a location after the start of the +// bag) indicates a valid reference that needs to be marked. + static void TryMark(void * p) { jl_value_t * p2 = jl_gc_internal_obj_base_ptr(p); @@ -438,7 +463,6 @@ static void TryMark(void * p) } } - static void TryMarkRange(void * start, void * end) { if (lt_ptr(end, start)) {