Skip to content

Commit

Permalink
kernel: add 'void * ref' to all GC mark functions (#5662)
Browse files Browse the repository at this point in the history
This helps the Julia GC to pass along certain global state through
marking functions to `MarkBag`, instead of needing to use global
variables for that (which is not thread safe).

For GASMAN and Boehm, this does nothing.

The main downside is that it breaks kernel extensions defining
custom marking functions. But as far as I can tell, that only
affects `Semigroups`, for which I am confident we can get a patch
in that will make it work with this while staying compatible with
older kernel versions. Enabling this is why I've added

    #define GAP_MARK_FUNC_WITH_REF 1

to this PR: then one can add something like

    #ifdef GAP_MARK_FUNC_WITH_REF
    #define MarkBag(obj,ref) MarkBag(obj)
    #endif

to code that needs to stay compatible with GAP versions before
and after this patch.
  • Loading branch information
fingolfin authored Mar 13, 2024
1 parent c8e9ab4 commit 2b0e78d
Show file tree
Hide file tree
Showing 14 changed files with 121 additions and 129 deletions.
30 changes: 15 additions & 15 deletions src/bags.inc
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,43 @@
#include "error.h"
#include "gasman.h"

void MarkArrayOfBags(const Bag array[], UInt count)
void MarkArrayOfBags(const Bag array[], UInt count, void * ref)
{
for (UInt i = 0; i < count; i++) {
MarkBag(array[i]);
MarkBag(array[i], ref);
}
}

void MarkNoSubBags(Bag bag)
void MarkNoSubBags(Bag bag, void * ref)
{
}

void MarkOneSubBags(Bag bag)
void MarkOneSubBags(Bag bag, void * ref)
{
MarkArrayOfBags(CONST_PTR_BAG(bag), 1);
MarkArrayOfBags(CONST_PTR_BAG(bag), 1, ref);
}

void MarkTwoSubBags(Bag bag)
void MarkTwoSubBags(Bag bag, void * ref)
{
MarkArrayOfBags(CONST_PTR_BAG(bag), 2);
MarkArrayOfBags(CONST_PTR_BAG(bag), 2, ref);
}

void MarkThreeSubBags(Bag bag)
void MarkThreeSubBags(Bag bag, void * ref)
{
MarkArrayOfBags(CONST_PTR_BAG(bag), 3);
MarkArrayOfBags(CONST_PTR_BAG(bag), 3, ref);
}

void MarkFourSubBags(Bag bag)
void MarkFourSubBags(Bag bag, void * ref)
{
MarkArrayOfBags(CONST_PTR_BAG(bag), 4);
MarkArrayOfBags(CONST_PTR_BAG(bag), 4, ref);
}

void MarkAllSubBags(Bag bag)
void MarkAllSubBags(Bag bag, void * ref)
{
MarkArrayOfBags(CONST_PTR_BAG(bag), SIZE_BAG(bag) / sizeof(Bag));
MarkArrayOfBags(CONST_PTR_BAG(bag), SIZE_BAG(bag) / sizeof(Bag), ref);
}

void MarkAllButFirstSubBags(Bag bag)
void MarkAllButFirstSubBags(Bag bag, void * ref)
{
MarkArrayOfBags(CONST_PTR_BAG(bag) + 1, SIZE_BAG(bag) / sizeof(Bag) - 1);
MarkArrayOfBags(CONST_PTR_BAG(bag) + 1, SIZE_BAG(bag) / sizeof(Bag) - 1, ref);
}
4 changes: 2 additions & 2 deletions src/calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -1611,13 +1611,13 @@ static void LoadFunction(Obj func)
**
** 'MarkFunctionSubBags' is the marking function for bags of type 'T_FUNCTION'.
*/
static void MarkFunctionSubBags(Obj func)
static void MarkFunctionSubBags(Obj func, void * ref)
{
// the first eight slots are pointers to C functions, so we need
// to skip those for marking
UInt size = SIZE_BAG(func) / sizeof(Obj) - 8;
const Bag * data = CONST_PTR_BAG(func) + 8;
MarkArrayOfBags(data, size);
MarkArrayOfBags(data, size, ref);
}


Expand Down
4 changes: 2 additions & 2 deletions src/cyclotom.c
Original file line number Diff line number Diff line change
Expand Up @@ -1942,9 +1942,9 @@ static Obj FuncCycList(Obj self, Obj list)
**
** 'MarkCycSubBags' is the marking function for bags of type 'T_CYC'.
*/
static void MarkCycSubBags(Obj cyc)
static void MarkCycSubBags(Obj cyc, void * ref)
{
MarkArrayOfBags( COEFS_CYC( cyc ), SIZE_CYC(cyc) );
MarkArrayOfBags( COEFS_CYC( cyc ), SIZE_CYC(cyc), ref );
}


Expand Down
20 changes: 10 additions & 10 deletions src/gasman.c
Original file line number Diff line number Diff line change
Expand Up @@ -672,9 +672,9 @@ void InitSweepFuncBags (
** the second time raises a warning, because a non-default marking function
** is being replaced.
*/
static void MarkAllSubBagsDefault(Bag bag)
static void MarkAllSubBagsDefault(Bag bag, void * ref)
{
MarkArrayOfBags(CONST_PTR_BAG(bag), SIZE_BAG(bag) / sizeof(Bag));
MarkArrayOfBags(CONST_PTR_BAG(bag), SIZE_BAG(bag) / sizeof(Bag), ref);
}


Expand Down Expand Up @@ -770,7 +770,7 @@ static Int DisableMarkBagValidation = 0;
// Other marking functions don't get to inline MarkBag calls anymore,
// but luckily these are rare (and usually not performance critical
// to start with).
inline void MarkBag(Bag bag)
inline void MarkBag(Bag bag, void * ref)
{
if ( IS_BAG_ID(bag)
&& YoungBags < CONST_PTR_BAG(bag) // points to a young bag
Expand Down Expand Up @@ -1918,7 +1918,7 @@ static NOINLINE void ScanRange(void * vpA, void * vpB)
// Need to mark this pointer as readable for valgrind
VALGRIND_MAKE_MEM_DEFINED(&pcpy, sizeof(pcpy));
#endif
MarkBag(*pcpy);
MarkBag(*pcpy, 0);
}
}
}
Expand All @@ -1930,7 +1930,7 @@ static NOINLINE void ScanRange(void * vpA, void * vpB)
// Need to mark this pointer as readable for valgrind
VALGRIND_MAKE_MEM_DEFINED(&pcpy, sizeof(pcpy));
#endif
MarkBag(*pcpy);
MarkBag(*pcpy, 0);
}
}
}
Expand Down Expand Up @@ -1961,7 +1961,7 @@ static NOINLINE void GenStackFuncBags(void)
// slightly. unusual.
for (p = (Bag *)RegsBags;
p < (Bag *)((char *)RegsBags + sizeof(RegsBags)); p++)
MarkBag( *p );
MarkBag(*p, 0);

#ifdef DEBUG_GASMAN_MARKING
DisableMarkBagValidation = 0;
Expand All @@ -1986,7 +1986,7 @@ static UInt CollectBags_Mark(UInt FullBags)

// mark from the static area
for (int i = 0; i < GlobalBags.nr; i++)
MarkBag( *GlobalBags.addr[i] );
MarkBag( *GlobalBags.addr[i], 0 );

/* allow installing a custom marking function. This is used for integrating
GAP (possibly linked as a shared library) with other code bases which use
Expand Down Expand Up @@ -2031,9 +2031,9 @@ static UInt CollectBags_Mark(UInt FullBags)
// bag, which does not prevent the young bag itself from being
// collected (which is what we need).
if (CONST_PTR_BAG(first) <= YoungBags)
(*TabMarkFuncBags[TNUM_BAG(first)])( first );
(*TabMarkFuncBags[TNUM_BAG(first)])( first, 0 );
else
MarkBag(first);
MarkBag(first, 0);
}


Expand All @@ -2059,7 +2059,7 @@ static UInt CollectBags_Mark(UInt FullBags)
}

// mark subbags
(*TabMarkFuncBags[TNUM_BAG(first)])( first );
(*TabMarkFuncBags[TNUM_BAG(first)])( first, 0 );

// collect some statistics
nrLiveBags++;
Expand Down
32 changes: 17 additions & 15 deletions src/gasman.h
Original file line number Diff line number Diff line change
Expand Up @@ -661,10 +661,11 @@ Bag MakeBagReadOnly(Bag bag);
** function for a type before it allocates any bag of that type. It is
** probably best to install all marking functions before allocating any bag.
**
** A marking function is a function that takes a single argument of type
** 'Bag' and returns nothing, i.e., has return type 'void'. Such a function
** must apply the function 'MarkBag' to each bag identifier that appears in
** the bag (see below).
** A marking function is a function that takes a two arguments, one of type
** 'Bag' and one of type 'void *' and returns nothing, i.e., has return type
** 'void'. Such a function must apply the function 'MarkBag' to each bag
** identifier that appears in the bag (see below), passing on its 'void *'
** argument unchanged to 'MarkBag' as second argument.
**
** Those functions are applied during the garbage collection to each marked
** bag, i.e., bags that are assumed to be still live, to also mark their
Expand All @@ -673,7 +674,8 @@ Bag MakeBagReadOnly(Bag bag);
**
** {\Gasman} already provides several marking functions, see below.
*/
typedef void (* TNumMarkFuncBags )( Bag bag );
#define GAP_MARK_FUNC_WITH_REF 1
typedef void (* TNumMarkFuncBags )( Bag bag, void * ref );
void InitMarkFuncBags(UInt type, TNumMarkFuncBags mark_func);

#if !defined(USE_THREADSAFE_COPYING) && !defined(USE_BOEHM_GC)
Expand All @@ -689,7 +691,7 @@ extern TNumMarkFuncBags TabMarkFuncBags[NUM_TYPES];
** simply returns. For example in {\GAP} the bags for large integers
** contain only the digits and no identifiers of bags.
*/
void MarkNoSubBags(Bag bag);
void MarkNoSubBags(Bag bag, void * ref);


/****************************************************************************
Expand All @@ -703,10 +705,10 @@ void MarkNoSubBags(Bag bag);
** the indicated number as bag identifiers as their initial entries.
** These functions mark those subbags and return.
*/
void MarkOneSubBags(Bag bag);
void MarkTwoSubBags(Bag bag);
void MarkThreeSubBags(Bag bag);
void MarkFourSubBags(Bag bag);
void MarkOneSubBags(Bag bag, void * ref);
void MarkTwoSubBags(Bag bag, void * ref);
void MarkThreeSubBags(Bag bag, void * ref);
void MarkFourSubBags(Bag bag, void * ref);


/****************************************************************************
Expand All @@ -725,14 +727,14 @@ void MarkFourSubBags(Bag bag);
** bag identifiers for the elements of the list or 0 if an entry has no
** assigned value.
*/
void MarkAllSubBags(Bag bag);
void MarkAllSubBags(Bag bag, void * ref);


/****************************************************************************
**
*F MarkAllButFirstSubBags(<bag>) . . . . marks all subbags except the first
*/
void MarkAllButFirstSubBags(Bag bag);
void MarkAllButFirstSubBags(Bag bag, void * ref);


/****************************************************************************
Expand All @@ -749,11 +751,11 @@ void MarkAllButFirstSubBags(Bag bag);
** identifier.
*/
#ifdef USE_BOEHM_GC
EXPORT_INLINE void MarkBag( Bag bag )
EXPORT_INLINE void MarkBag( Bag bag, void * ref )
{
}
#else
void MarkBag(Bag bag);
void MarkBag(Bag bag, void * ref);
#endif


Expand All @@ -764,7 +766,7 @@ void MarkBag(Bag bag);
** 'MarkArrayOfBags' iterates over <count> all bags in the given array,
** and marks each bag using MarkBag.
*/
extern void MarkArrayOfBags(const Bag array[], UInt count);
extern void MarkArrayOfBags(const Bag array[], UInt count, void * ref);


/****************************************************************************
Expand Down
16 changes: 8 additions & 8 deletions src/hpc/aobjects.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,15 +403,15 @@ static Obj FuncFromAtomicList(Obj self, Obj list)
return FromAtomicList(list);
}

static void MarkAtomicList(Bag bag)
static void MarkAtomicList(Bag bag, void * ref)
{
UInt len;
const AtomicObj *ptr, *ptrend;
ptr = CONST_ADDR_ATOM(bag);
len = ALIST_LEN((UInt)(ptr++->atom));
ptrend = ptr + len + 1;
while (ptr < ptrend)
MarkBag(ptr++->obj);
MarkBag(ptr++->obj, ref);
}

/* T_AREC_INNER substructure:
Expand Down Expand Up @@ -449,24 +449,24 @@ static Obj GetTLInner(Obj obj)
return contents;
}

static void MarkTLRecord(Bag bag)
static void MarkTLRecord(Bag bag, void * ref)
{
MarkBag(GetTLInner(bag));
MarkBag(GetTLInner(bag), ref);
}


static void MarkAtomicRecord(Bag bag)
static void MarkAtomicRecord(Bag bag, void * ref)
{
MarkBag(GetTLInner(bag));
MarkBag(GetTLInner(bag), ref);
}

static void MarkAtomicRecord2(Bag bag)
static void MarkAtomicRecord2(Bag bag, void * ref)
{
const AtomicObj *p = CONST_ADDR_ATOM(bag);
UInt cap = p->atom;
p += 5;
while (cap) {
MarkBag(p->obj);
MarkBag(p->obj, ref);
p += 2;
cap--;
}
Expand Down
Loading

0 comments on commit 2b0e78d

Please sign in to comment.