Skip to content

Commit

Permalink
Restructure mark functionality for the Julia GC.
Browse files Browse the repository at this point in the history
  • Loading branch information
rbehrends committed Apr 23, 2019
1 parent 7590998 commit efbb767
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 15 deletions.
37 changes: 24 additions & 13 deletions src/julia_gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,12 +459,10 @@ void InitMarkFuncBags(UInt type, TNumMarkFuncBags mark_func)
TabMarkFuncBags[type] = mark_func;
}

static inline int JMarkGapObjSafe(void * obj)
static inline int JMarkTyped(void * obj, jl_datatype_t * ty)
{
// only traverse objects internally used by GAP
void *ty = jl_typeof(obj);
if (ty != datatype_mptr && ty != datatype_bag
&& ty != datatype_largebag && ty != jl_weakref_type)
if (!jl_typeis(obj, ty))
return 0;
return jl_gc_mark_queue_obj(JuliaTLS, (jl_value_t *)obj);
}
Expand Down Expand Up @@ -581,7 +579,11 @@ static void TryMark(void * p)
if (jl_typeis(p2, datatype_mptr))
JMark(p2);
#else
JMarkGapObjSafe(p2);
void *ty = jl_typeof(p2);
if (ty != datatype_mptr && ty != datatype_bag
&& ty != datatype_largebag && ty != jl_weakref_type)
return;
JMark(p2);
#endif
}
}
Expand Down Expand Up @@ -755,7 +757,7 @@ static void PostGCHook(int full)

// the Julia marking function for master pointer objects (i.e., this function
// is called by the Julia GC whenever it marks a GAP master pointer object)
static uintptr_t JMarkMPtr(jl_ptls_t ptls, jl_value_t * obj)
static uintptr_t MPtrMarkFunc(jl_ptls_t ptls, jl_value_t * obj)
{
if (!*(void **)obj)
return 0;
Expand All @@ -772,7 +774,7 @@ static uintptr_t JMarkMPtr(jl_ptls_t ptls, jl_value_t * obj)

// the Julia marking function for bags (i.e., this function is called by the
// Julia GC whenever it marks a GAP bag object)
static uintptr_t JMarkBag(jl_ptls_t ptls, jl_value_t * obj)
static uintptr_t BagMarkFunc(jl_ptls_t ptls, jl_value_t * obj)
{
BagHeader * hdr = (BagHeader *)obj;
Bag contents = (Bag)(hdr + 1);
Expand Down Expand Up @@ -812,12 +814,12 @@ void InitBags(UInt initial_size, Bag * stack_bottom, UInt stack_align)
jl_set_const(jl_main_module, jl_symbol("ForeignGAP"),
(jl_value_t *)Module);
datatype_mptr = jl_new_foreign_type(jl_symbol("MPtr"), Module,
jl_any_type, JMarkMPtr, NULL, 1, 0);
jl_any_type, MPtrMarkFunc, NULL, 1, 0);
datatype_bag = jl_new_foreign_type(jl_symbol("Bag"), Module, jl_any_type,
JMarkBag, JFinalizer, 1, 0);
BagMarkFunc, JFinalizer, 1, 0);
datatype_largebag =
jl_new_foreign_type(jl_symbol("LargeBag"), Module, jl_any_type,
JMarkBag, JFinalizer, 1, 1);
BagMarkFunc, JFinalizer, 1, 1);

// export datatypes to Julia level
jl_set_const(Module, jl_symbol("MPtr"), (jl_value_t *)datatype_mptr);
Expand Down Expand Up @@ -1021,20 +1023,29 @@ inline void MarkBag(Bag bag)
// relies on Julia internals. It is functionally equivalent
// to:
//
// if (JMarkGapObjSafe(p)) YoungRef++;
// if (JMarkTyped(p, datatype_mptr)) YoungRef++;
//
switch (jl_astaggedvalue(p)->bits.gc) {
case 0:
if (JMarkGapObjSafe(p))
if (JMarkTyped(p, datatype_mptr))
YoungRef++;
break;
case 1:
YoungRef++;
break;
case 2:
JMarkGapObjSafe(p);
JMarkTyped(p, datatype_mptr);
break;
case 3:
break;
}
}

void MarkJuliaWeakRef(void * p)
{
// If `jl_nothing` gets passed in as an argument, it will not
// be marked. This is harmless, because `jl_nothing` will always
// be live regardless.
if (JMarkTyped(p, jl_weakref_type))
YoungRef++;
}
14 changes: 13 additions & 1 deletion src/julia_gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
**
*F MarkJuliaObj(<obj>) . . . . . . . . . . . . . . . . . . mark Julia object
**
** 'MarkJuliaObjSafe' marks a Julia object; the argument can be NULL.
** 'MarkJuliaObjSafe' marks a Julia object; the argument can be NULL. No
** further checks are performed. If <obj> is not a Julia object, a crash
** may result.
*/

void MarkJuliaObj(void * obj);
Expand All @@ -33,4 +35,14 @@ void MarkJuliaObj(void * obj);

void MarkJuliaObjSafe(void * obj);

/****************************************************************************
**
*F MarkJuliaWeakRef(<ref>) . . . . . . . . . . . mark Julia weak reference
**
** 'MarkJuliaWeakRef` marks a Julia weak reference. This must be a valid
** reference and cannot be NULL.
*/

void MarkJuliaWeakRef(void * obj);

#endif
19 changes: 18 additions & 1 deletion src/weakptr.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#ifdef USE_JULIA_GC
#include "julia.h"
#include "julia_gc.h"
#endif

#define RequireWPObj(funcname, op) \
Expand Down Expand Up @@ -552,6 +553,22 @@ static void SweepWeakPointerObj( Bag *src, Bag *dst, UInt len)

#endif

#ifdef USE_JULIA_GC

static void MarkWeakPointerObj(Obj wp)
{
// can't use the stored length here, in case we are in the middle of
// copying
const UInt len = SIZE_BAG(wp) / sizeof(Obj) - 1;
for (UInt i = 1; i <= len; i++) {
Bag elm = CONST_ADDR_OBJ(wp)[i];
if (IS_BAG_REF(elm))
MarkJuliaWeakRef(elm);
}
}

#endif


#ifdef USE_THREADSAFE_COPYING
#ifndef WARD_ENABLED
Expand Down Expand Up @@ -832,7 +849,7 @@ static Int InitKernel (
InitMarkFuncBags ( T_WPOBJ, MarkWeakPointerObj );
InitSweepFuncBags( T_WPOBJ, SweepWeakPointerObj );
#elif defined(USE_JULIA_GC)
InitMarkFuncBags ( T_WPOBJ, MarkAllButFirstSubBags );
InitMarkFuncBags ( T_WPOBJ, MarkWeakPointerObj );
#else
#error Unknown garbage collector implementation, no weak pointer object implemention available
#endif
Expand Down

0 comments on commit efbb767

Please sign in to comment.