diff --git a/src/calls.c b/src/calls.c index f0766a9e79..0e2eb39039 100644 --- a/src/calls.c +++ b/src/calls.c @@ -39,6 +39,9 @@ #include "bool.h" #include "code.h" #include "error.h" +#ifdef USE_GASMAN +#include "gasman_intern.h" +#endif #include "gvars.h" #include "integer.h" #include "io.h" diff --git a/src/gap.c b/src/gap.c index 4f7a447cc7..59da0e5572 100644 --- a/src/gap.c +++ b/src/gap.c @@ -20,6 +20,9 @@ #include "error.h" #include "funcs.h" #include "gapstate.h" +#ifdef USE_GASMAN +#include "gasman_intern.h" +#endif #include "gvars.h" #include "integer.h" #include "io.h" diff --git a/src/gasman.c b/src/gasman.c index dd6a13ccf9..6bf830196f 100644 --- a/src/gasman.c +++ b/src/gasman.c @@ -112,6 +112,7 @@ */ #include "gasman.h" +#include "gasman_intern.h" #include "gaputils.h" #include "io.h" diff --git a/src/gasman.h b/src/gasman.h index 50540bc62b..e24556f07d 100644 --- a/src/gasman.h +++ b/src/gasman.h @@ -223,7 +223,9 @@ static inline UInt SIZE_BAG_CONTENTS(const void *ptr) { ** Note that 'LINK_BAG' is a macro, so do not call it with arguments that ** have side effects. */ +#ifdef USE_GASMAN #define LINK_BAG(bag) (BAG_HEADER(bag)->link) +#endif /**************************************************************************** @@ -833,23 +835,6 @@ extern void MarkBag( Bag bag ); #define MARK_BAG(bag) MarkBag(bag) -/**************************************************************************** -** -*F MarkBagWeakly() . . . . . . . . . . . . . mark a bag as weakly live -** -** 'MarkBagWeakly' is an alternative to MarkBag, intended to be used by the -** marking functions of weak pointer objects. A bag which is marked both -** weakly and strongly is treated as strongly marked. A bag which is only -** weakly marked will be recovered by garbage collection, but its identifier -** remains, marked in a way which can be detected by -** "IS_WEAK_DEAD_BAG". Which should always be checked before copying or -** using such an identifier. -*/ -#if !defined(USE_BOEHM_GC) -extern void MarkBagWeakly( Bag bag ); -#endif - - /**************************************************************************** ** *F MarkArrayOfBags(,) . . . . . . . mark all bags in an array @@ -860,32 +845,6 @@ extern void MarkBagWeakly( Bag bag ); extern void MarkArrayOfBags(const Bag array[], UInt count); -/**************************************************************************** -** -*F -*/ - -#ifdef USE_GASMAN - -extern Bag * MptrBags; -extern Bag * MptrEndBags; -extern Bag * AllocBags; - -#define IS_WEAK_DEAD_BAG(bag) ( (((UInt)bag & (sizeof(Bag)-1)) == 0) && \ - (Bag)MptrBags <= (bag) && \ - (bag) < (Bag)MptrEndBags && \ - (((UInt)*bag) & (sizeof(Bag)-1)) == 1) - -#elif defined(USE_BOEHM_GC) - -#define IS_WEAK_DEAD_BAG(bag) (!(bag)) -#define REGISTER_WP(loc, obj) \ - GC_general_register_disappearing_link((void **)(loc), (obj)) -#define FORGET_WP(loc) \ - GC_unregister_disappearing_link((void **)(loc)) - -#endif - /**************************************************************************** ** *F InitSweepFuncBags(,) . . . . install sweeping function @@ -921,26 +880,6 @@ extern void InitSweepFuncBags ( TNumSweepFuncBags sweep_func ); #endif -/**************************************************************************** -** -*V GlobalBags . . . . . . . . . . . . . . . . . . . . . list of global bags -*/ -#ifdef USE_GASMAN - -#ifndef NR_GLOBAL_BAGS -#define NR_GLOBAL_BAGS 20000L -#endif - - -typedef struct { - Bag * addr [NR_GLOBAL_BAGS]; - const Char * cookie [NR_GLOBAL_BAGS]; - UInt nr; -} TNumGlobalBags; - -extern TNumGlobalBags GlobalBags; - -#endif /**************************************************************************** ** @@ -971,24 +910,6 @@ extern void InitGlobalBag ( Bag * addr, const Char * cookie ); -#ifdef USE_GASMAN - -extern void SortGlobals( UInt byWhat ); - -extern Bag * GlobalByCookie( - const Char * cookie ); - - -extern void StartRestoringBags( UInt nBags, UInt maxSize); - - -extern Bag NextBagRestoring( UInt type, UInt flags, UInt size ); - - -extern void FinishedRestoringBags( void ); - -#endif - /**************************************************************************** ** @@ -1045,26 +966,6 @@ extern void InitCollectFuncBags ( #endif -/**************************************************************************** -** -*F CheckMasterPointers() . . . . . . . . . . . . do some consistency checks -** -** 'CheckMasterPointers' tests for masterpointers which are not one of the -** following: -** -** 0 denoting the end of the free chain -** NewWeakDeadBagMarker denoting the relic of a bag that was weakly -** OldWeakDeadBagMarker but not strongly linked at the last garbage -** collection -** a pointer into the masterpointer area a link on the free chain -** a pointer into the bags area a real object -** -*/ -#ifdef USE_GASMAN -extern void CheckMasterPointers( void ); -#endif - - /**************************************************************************** ** *F InitBags(...) . . . . . . . . . . . . . . . . . . . . . initialize Gasman @@ -1122,20 +1023,6 @@ extern void InitBags(UInt initial_size, extern void FinishBags( void ); -/**************************************************************************** -** -*F CallbackForAllBags( ) call a C function on all non-zero mptrs -** -** This calls a C function on every bag, including ones that are not -** reachable from the root, and will be deleted at the next garbage -** collection, by simply walking the masterpointer area. Not terribly safe. -** -*/ -#ifdef USE_GASMAN -extern void CallbackForAllBags( void (*func)(Bag) ); -#endif - - #if !defined(USE_GASMAN) void *AllocateMemoryBlock(UInt size); #endif diff --git a/src/gasman_intern.h b/src/gasman_intern.h new file mode 100644 index 0000000000..d662703a53 --- /dev/null +++ b/src/gasman_intern.h @@ -0,0 +1,98 @@ +#ifndef GAP_GASMAN_INTERN_H +#define GAP_GASMAN_INTERN_H + +#include "gasman.h" + +#ifndef USE_GASMAN +#error This file must only be included if GASMAN is used +#endif + + +/**************************************************************************** +** +*F MarkBagWeakly() . . . . . . . . . . . . . mark a bag as weakly live +** +** 'MarkBagWeakly' is an alternative to MarkBag, intended to be used by the +** marking functions of weak pointer objects. A bag which is marked both +** weakly and strongly is treated as strongly marked. A bag which is only +** weakly marked will be recovered by garbage collection, but its identifier +** remains, marked in a way which can be detected by +** "IS_WEAK_DEAD_BAG". Which should always be checked before copying or +** using such an identifier. +*/ +extern void MarkBagWeakly( Bag bag ); + + +/**************************************************************************** +** +*/ +extern Bag * MptrBags; +extern Bag * MptrEndBags; +extern Bag * AllocBags; + + +/**************************************************************************** +** +*V GlobalBags . . . . . . . . . . . . . . . . . . . . . list of global bags +*/ +#ifndef NR_GLOBAL_BAGS +#define NR_GLOBAL_BAGS 20000L +#endif + + +typedef struct { + Bag * addr [NR_GLOBAL_BAGS]; + const Char * cookie [NR_GLOBAL_BAGS]; + UInt nr; +} TNumGlobalBags; + +extern TNumGlobalBags GlobalBags; + + + +extern void SortGlobals( UInt byWhat ); + +extern Bag * GlobalByCookie( + const Char * cookie ); + + +extern void StartRestoringBags( UInt nBags, UInt maxSize); + + +extern Bag NextBagRestoring( UInt type, UInt flags, UInt size ); + + +extern void FinishedRestoringBags( void ); + + +/**************************************************************************** +** +*F CheckMasterPointers() . . . . . . . . . . . . do some consistency checks +** +** 'CheckMasterPointers' tests for masterpointers which are not one of the +** following: +** +** 0 denoting the end of the free chain +** NewWeakDeadBagMarker denoting the relic of a bag that was weakly +** OldWeakDeadBagMarker but not strongly linked at the last garbage +** collection +** a pointer into the masterpointer area a link on the free chain +** a pointer into the bags area a real object +** +*/ +extern void CheckMasterPointers( void ); + + +/**************************************************************************** +** +*F CallbackForAllBags( ) call a C function on all non-zero mptrs +** +** This calls a C function on every bag, including ones that are not +** reachable from the root, and will be deleted at the next garbage +** collection, by simply walking the masterpointer area. Not terribly safe. +** +*/ +extern void CallbackForAllBags( void (*func)(Bag) ); + + +#endif diff --git a/src/opers.c b/src/opers.c index e2f91e72ea..8ec1a46c94 100644 --- a/src/opers.c +++ b/src/opers.c @@ -20,6 +20,9 @@ #include "calls.h" #include "error.h" #include "gapstate.h" +#ifdef USE_GASMAN +#include "gasman_intern.h" +#endif #include "gvars.h" #include "io.h" #include "lists.h" @@ -1650,7 +1653,7 @@ static void HandleMethodNotFound(Obj oper, ** */ -#ifdef GASMAN +#ifdef USE_GASMAN static Obj FLUSH_ALL_METHOD_CACHES; @@ -1670,7 +1673,7 @@ static void FixTypeIDs( Bag b ) { Obj FuncCOMPACT_TYPE_IDS( Obj self ) { -#ifdef GASMAN +#ifdef USE_GASMAN NextTypeID = INT_INTOBJ_MIN; CallbackForAllBags( FixTypeIDs ); CALL_0ARGS(FLUSH_ALL_METHOD_CACHES); diff --git a/src/plist.c b/src/plist.c index b0e2c1b58e..b0a3318873 100644 --- a/src/plist.c +++ b/src/plist.c @@ -23,7 +23,7 @@ ** list, and so on. If the physical length of a list is greater than the ** logical, there will be unused entries at the end of the list, comtaining ** 0. The physical length might be greater than the logical, because the -** physical size of a list is increased by at least 12.5\%, to avoid doing +** physical size of a list is increased by at least 25\%, to avoid doing ** this too often. ** ** This representation is encoded by the macros 'NEW_PLIST', 'GROW_PLIST', @@ -62,7 +62,7 @@ *F GROW_PLIST(,) . . . . make sure a plain list is large enough ** */ -Int GrowPlist ( +void GrowPlist ( Obj list, UInt need ) { @@ -83,9 +83,6 @@ Int GrowPlist ( /* resize the plain list */ ResizeBag( list, ((plen)+1)*sizeof(Obj) ); - - /* return something (to please some C compilers) */ - return 0L; } diff --git a/src/plist.h b/src/plist.h index 0581e8baa5..c1a66d03bc 100644 --- a/src/plist.h +++ b/src/plist.h @@ -104,7 +104,7 @@ static inline Int CAPACITY_PLIST(Obj list) return SIZE_OBJ(list) / sizeof(Obj) - 1; } -extern Int GrowPlist ( +extern void GrowPlist ( Obj list, UInt need ); diff --git a/src/saveload.c b/src/saveload.c index 668da7e069..fe8a9a1341 100644 --- a/src/saveload.c +++ b/src/saveload.c @@ -19,6 +19,9 @@ #include "compstat.h" #include "error.h" #include "finfield.h" +#ifdef USE_GASMAN +#include "gasman_intern.h" +#endif #include "gvars.h" #include "io.h" #include "modules.h" diff --git a/src/weakptr.c b/src/weakptr.c index 8459dc2c8b..979d6a8a70 100644 --- a/src/weakptr.c +++ b/src/weakptr.c @@ -20,6 +20,9 @@ #include "bool.h" #include "error.h" +#ifdef USE_GASMAN +#include "gasman_intern.h" +#endif #include "lists.h" #include "modules.h" #include "plist.h" @@ -37,6 +40,28 @@ # include #endif +/**************************************************************************** +** +*F +*/ + +#ifdef USE_GASMAN + +#define IS_WEAK_DEAD_BAG(bag) ( (((UInt)bag & (sizeof(Bag)-1)) == 0) && \ + (Bag)MptrBags <= (bag) && \ + (bag) < (Bag)MptrEndBags && \ + (((UInt)*bag) & (sizeof(Bag)-1)) == 1) + +#elif defined(USE_BOEHM_GC) + +#define IS_WEAK_DEAD_BAG(bag) (!(bag)) +#define REGISTER_WP(loc, obj) \ + GC_general_register_disappearing_link((void **)(loc), (obj)) +#define FORGET_WP(loc) \ + GC_unregister_disappearing_link((void **)(loc)) + +#endif + /**************************************************************************** ** @@ -92,35 +117,31 @@ /**************************************************************************** ** -*F GROW_WPOBJ(,) . make sure a weak pointer object is large enough +*F GROW_WPOBJ(,) . make sure a weak pointer object is large enough ** ** 'GROW_WPOBJ' grows the weak pointer object if necessary to -** ensure that it has room for at least elements. -** -** Note that 'GROW_WPOBJ' is a macro, so do not call it with arguments that -** have side effects. */ - -#define GROW_WPOBJ(wp,plen) ((plen) < SIZE_OBJ(wp)/sizeof(Obj) ? \ - 0L : GrowWPObj(wp,plen) ) +** ensure that it has room for at least elements. +*/ -Int GrowWPObj ( - Obj wp, - UInt need ) +static inline void GROW_WPOBJ(Obj wp, UInt need) { UInt plen; /* new physical length */ UInt good; /* good new physical length */ - /* find out how large the object should become */ + // if there is already enough space, do nothing + if (need < SIZE_OBJ(wp)/sizeof(Obj)) + return; + + // find out how large the object should become at least (we grow by + // at least 25%, like plain lists) + /* find out how large the plain list should become */ good = 5 * (SIZE_OBJ(wp)/sizeof(Obj)-1) / 4 + 4; /* but maybe we need more */ if ( need < good ) { plen = good; } else { plen = need; } -#ifndef USE_BOEHM_GC - /* resize the plain list */ - ResizeBag( wp, ((plen)+1)*sizeof(Obj) ); -#else +#ifdef USE_BOEHM_GC Obj copy = NewBag(T_WPOBJ, (plen+1) * sizeof(Obj)); STORE_LEN_WPOBJ(copy, STORED_LEN_WPOBJ(wp)); @@ -136,22 +157,23 @@ Int GrowWPObj ( ELM_WPOBJ(copy, i) = tmp; } SET_PTR_BAG(wp, PTR_BAG(copy)); +#else + // resize the weak pointer object + ResizeBag( wp, ((plen)+1)*sizeof(Obj) ); #endif - - /* return something (to please some C compilers) */ - return 0L; } /**************************************************************************** ** -*F FuncWeakPointerObj( , ) . . . . . .make a weak pointer object +*F FuncWeakPointerObj( , ) . . . . . make a weak pointer object ** -** Handler for the GAP function WeakPointerObject(), which makes a new -** WP object +** Handler for the GAP function WeakPointerObject(), which makes a new +** WP object. */ -Obj FuncWeakPointerObj( Obj self, Obj list ) { +Obj FuncWeakPointerObj(Obj self, Obj list) +{ Obj wp; Int i; Int len; @@ -209,22 +231,16 @@ Int LengthWPObj(Obj wp) return len; #endif -#ifndef USE_BOEHM_GC Obj elm; - while (len > 0 && - (!(elm = ELM_WPOBJ(wp,len)) || - IS_WEAK_DEAD_BAG(elm))) { + while (len > 0) { + elm = ELM_WPOBJ(wp, len); + if (elm && !IS_WEAK_DEAD_BAG(elm)) + break; changed = 1; if (elm) - ELM_WPOBJ(wp,len) = 0; - len--; - } -#else - while (len > 0 && !ELM_WPOBJ(wp, len)) { - changed = 1; + ELM_WPOBJ(wp, len) = 0; len--; } -#endif if (changed) STORE_LEN_WPOBJ(wp,len); return len; @@ -351,13 +367,13 @@ Int IsBoundElmWPObj( Obj wp, Obj pos) if (elm == 0 || ELM_WPOBJ(wp, ipos) == 0) return 0; #else + if (elm == 0) + return 0; if (IS_WEAK_DEAD_BAG(elm)) { ELM_WPOBJ(wp,ipos) = 0; return 0; } - if (elm == 0) - return 0; #endif return 1; } @@ -406,9 +422,7 @@ Obj FuncUnbindElmWPObj( Obj self, Obj wp, Obj pos) Int len = LengthWPObj(wp); if ( ipos <= len ) { -#ifndef USE_BOEHM_GC - ELM_WPOBJ( wp, ipos) = 0; -#else +#ifdef USE_BOEHM_GC /* Ensure the result is visible on the stack in case a garbage * collection happens after the read. */ @@ -419,6 +433,8 @@ Obj FuncUnbindElmWPObj( Obj self, Obj wp, Obj pos) FORGET_WP( &ELM_WPOBJ(wp, ipos)); ELM_WPOBJ( wp, ipos) = 0; } +#else + ELM_WPOBJ( wp, ipos) = 0; #endif } return 0; @@ -432,7 +448,7 @@ Obj FuncUnbindElmWPObj( Obj self, Obj wp, Obj pos) ** GAP handler for access to WP Object. If the entry is not bound, then fail ** is returned. It would not be correct to return an error, because there ** would be no way to safely access an element, which might evaporate -** between a call to Isbound and the access. This, of course, causes +** between a call to IsBound and the access. This, of course, causes ** possible confusion with a WP object which does have a value of fail ** stored in it. This, however can be checked with a subsequent call to ** IsBound, relying on the fact that fail can never dissapear in a garbage @@ -582,7 +598,9 @@ void CopyWPObj(Obj copy, Obj original) MEMBAR_READ(); if (IS_BAG_REF(tmp) && IS_BAG_REF(*ptr)) { *copyptr = ReplaceByCopy(tmp); +#ifdef USE_BOEHM_GC REGISTER_WP(copyptr, tmp); +#endif } ptr++; copyptr++; @@ -660,17 +678,7 @@ void MakeImmutableWPObj( Obj obj ) { UInt i; -#ifndef USE_BOEHM_GC - /* remove any weak dead bags */ - for (i = 1; i <= STORED_LEN_WPOBJ(obj); i++) - { - Obj elm = ELM_WPOBJ(obj,i); - if (elm != 0 && IS_WEAK_DEAD_BAG(elm)) - ELM_WPOBJ(obj,i) = 0; - } - /* Change the type */ - RetypeBag( obj, T_PLIST+IMMUTABLE); -#else +#ifdef USE_BOEHM_GC UInt len = 0; Obj copy = NewBag(T_PLIST+IMMUTABLE, SIZE_BAG(obj)); for (i = 1; i <= STORED_LEN_WPOBJ(obj); i++) { @@ -688,6 +696,15 @@ void MakeImmutableWPObj( Obj obj ) } SET_LEN_PLIST(copy, len); SET_PTR_BAG(obj, PTR_BAG(copy)); +#else + /* remove any weak dead bags */ + for (i = 1; i <= STORED_LEN_WPOBJ(obj); i++) { + Obj elm = ELM_WPOBJ(obj,i); + if (elm != 0 && IS_WEAK_DEAD_BAG(elm)) + ELM_WPOBJ(obj,i) = 0; + } + /* Change the type */ + RetypeBag( obj, T_PLIST+IMMUTABLE); #endif } @@ -744,26 +761,6 @@ void CleanObjWPObjCopy ( #endif //!defined(USE_THREADSAFE_COPYING) -/**************************************************************************** -** -*F FinalizeWeapPointerObj( ) -*/ - -#if defined(HPCGAP) && !defined(USE_BOEHM_GC) -void FinalizeWeakPointerObj( Obj wpobj ) -{ - volatile Obj keep = wpobj; - UInt i, len; - len = STORED_LEN_WPOBJ(wpobj); - for (i = 1; i <= len; i++) { - volatile Obj tmp = ELM_WPOBJ(wpobj, i); - MEMBAR_READ(); - if (IS_BAG_REF(tmp) && ELM_WPOBJ(wpobj, i)) - FORGET_WP(&ELM_WPOBJ(wpobj, i)); - } -} -#endif - /**************************************************************************** ** *F SaveWPObj( ) @@ -871,10 +868,6 @@ static Int InitKernel ( InitMarkFuncBags ( T_WPOBJ +COPYING, MarkWeakPointerObj ); InitSweepFuncBags( T_WPOBJ +COPYING, SweepWeakPointerObj ); #endif - #ifdef HPCGAP - InitFreeFuncBag( T_WPOBJ, FinalizeWeakPointerObj ); - InitFreeFuncBag( T_WPOBJ+COPYING, FinalizeWeakPointerObj ); - #endif #else #error Unknown garbage collector implementation, no weak pointer object implemention available #endif