/* -----------------------------------------------------------------------------
- * $Id: Storage.h,v 1.5 1999/01/21 10:31:52 simonm Exp $
+ * $Id: Storage.h,v 1.16 2000/04/14 15:18:07 sewardj Exp $
+ *
+ * (c) The GHC Team, 1998-1999
*
* External Storage Manger Interface
*
lnat allocated_bytes(void) Returns the number of bytes allocated
via allocate() since the last GC.
Used in the reoprting of statistics.
+
+ SMP: allocate and doYouWantToGC can be used from STG code, they are
+ surrounded by a mutex.
-------------------------------------------------------------------------- */
extern StgPtr allocate(nat n);
-------------------------------------------------------------------------- */
#define ExtendNursery(hp,hplim) \
- (current_nursery->free = (P_)(hp)+1, \
- current_nursery->link == NULL ? rtsFalse : \
- (current_nursery = current_nursery->link, \
+ (CurrentNursery->free = (P_)(hp)+1, \
+ CurrentNursery->link == NULL ? rtsFalse : \
+ (CurrentNursery = CurrentNursery->link, \
OpenNursery(hp,hplim), \
rtsTrue))
MarkRoot(StgClosure *p) Returns the new location of the root.
-------------------------------------------------------------------------- */
-extern void GarbageCollect(void (*get_roots)(void));
+extern void GarbageCollect(void (*get_roots)(void),rtsBool force_major_gc);
extern StgClosure *MarkRoot(StgClosure *p);
/* -----------------------------------------------------------------------------
Generational garbage collection support
- RecordMutable(StgPtr p) Informs the garbage collector that a
+ recordMutable(StgPtr p) Informs the garbage collector that a
previously immutable object has
become (permanently) mutable. Used
by thawArray and similar.
- UpdateWithIndirection(p1,p2) Updates the object at p1 with an
+ updateWithIndirection(p1,p2) Updates the object at p1 with an
indirection pointing to p2. This is
normally called for objects in an old
generation (>0) when they are updated.
+ updateWithPermIndirection(p1,p2) As above but uses a permanent indir.
+
-------------------------------------------------------------------------- */
-extern void recordMutable(StgMutClosure *p);
+static inline void
+recordMutable(StgMutClosure *p)
+{
+ bdescr *bd;
+
+#ifdef SMP
+ ASSERT(p->header.info == &WHITEHOLE_info || closure_MUTABLE(p));
+#else
+ ASSERT(closure_MUTABLE(p));
+#endif
+
+ bd = Bdescr((P_)p);
+ if (bd->gen->no > 0) {
+ p->mut_link = bd->gen->mut_list;
+ bd->gen->mut_list = p;
+ }
+}
+
+static inline void
+recordOldToNewPtrs(StgMutClosure *p)
+{
+ bdescr *bd;
+
+ bd = Bdescr((P_)p);
+ if (bd->gen->no > 0) {
+ p->mut_link = bd->gen->mut_once_list;
+ bd->gen->mut_once_list = p;
+ }
+}
+
+#define updateWithIndirection(info, p1, p2) \
+ { \
+ bdescr *bd; \
+ \
+ bd = Bdescr((P_)p1); \
+ if (bd->gen->no == 0) { \
+ ((StgInd *)p1)->indirectee = p2; \
+ SET_INFO(p1,&IND_info); \
+ TICK_UPD_NEW_IND(); \
+ } else { \
+ ((StgIndOldGen *)p1)->indirectee = p2; \
+ if (info != &BLACKHOLE_BQ_info) { \
+ ((StgIndOldGen *)p1)->mut_link = bd->gen->mut_once_list; \
+ bd->gen->mut_once_list = (StgMutClosure *)p1; \
+ } \
+ SET_INFO(p1,&IND_OLDGEN_info); \
+ TICK_UPD_OLD_IND(); \
+ } \
+ }
+#if defined(TICKY_TICKY) || defined(PROFILING)
static inline void
-updateWithIndirection(StgClosure *p1, StgClosure *p2)
+updateWithPermIndirection(const StgInfoTable *info, StgClosure *p1, StgClosure *p2)
{
bdescr *bd;
bd = Bdescr((P_)p1);
if (bd->gen->no == 0) {
- SET_INFO(p1,&IND_info);
((StgInd *)p1)->indirectee = p2;
- TICK_UPD_NEW_IND();
+ SET_INFO(p1,&IND_PERM_info);
+ TICK_UPD_NEW_PERM_IND(p1);
} else {
- SET_INFO(p1,&IND_OLDGEN_info);
((StgIndOldGen *)p1)->indirectee = p2;
- ((StgIndOldGen *)p1)->mut_link = bd->gen->mut_list;
- bd->gen->mut_list = (StgMutClosure *)p1;
- TICK_UPD_OLD_IND();
+ if (info != &BLACKHOLE_BQ_info) {
+ ((StgIndOldGen *)p1)->mut_link = bd->gen->mut_once_list;
+ bd->gen->mut_once_list = (StgMutClosure *)p1;
+ }
+ SET_INFO(p1,&IND_OLDGEN_PERM_info);
+ TICK_UPD_OLD_PERM_IND();
}
}
+#endif
/* -----------------------------------------------------------------------------
- The CAF list - used to let us revert CAFs
+ The CAF table - used to let us revert CAFs
-------------------------------------------------------------------------- */
-extern StgCAF* enteredCAFs;
+#if defined(INTERPRETER)
+typedef struct StgCAFTabEntry_ {
+ StgClosure* closure;
+ StgInfoTable* origItbl;
+} StgCAFTabEntry;
+
+extern void addToECafTable ( StgClosure* closure, StgInfoTable* origItbl );
+extern void clearECafTable ( void );
+
+extern StgCAF* ecafList;
+extern StgCAFTabEntry* ecafTable;
+extern StgInt usedECafTable;
+extern StgInt sizeECafTable;
+#endif
+
+#if defined(DEBUG)
+void printMutOnceList(generation *gen);
+void printMutableList(generation *gen);
+#endif DEBUG
#endif STORAGE_H