/* -----------------------------------------------------------------------------
- * $Id: GC.c,v 1.43 1999/02/26 12:46:46 simonm Exp $
+ * $Id: GC.c,v 1.45 1999/02/26 17:46:08 simonm Exp $
*
* (c) The GHC Team 1998-1999
*
Static function declarations
-------------------------------------------------------------------------- */
-static StgClosure *evacuate(StgClosure *q);
-static void zeroStaticObjectList(StgClosure* first_static);
-static rtsBool traverse_weak_ptr_list(void);
-static void zeroMutableList(StgMutClosure *first);
-static void revertDeadCAFs(void);
+static StgClosure * evacuate ( StgClosure *q );
+static void zero_static_object_list ( StgClosure* first_static );
+static void zero_mutable_list ( StgMutClosure *first );
+static void revert_dead_CAFs ( void );
-static void scavenge_stack(StgPtr p, StgPtr stack_end);
-static void scavenge_large(step *step);
-static void scavenge(step *step);
-static void scavenge_static(void);
-static void scavenge_mutable_list(generation *g);
-static void scavenge_mut_once_list(generation *g);
+static rtsBool traverse_weak_ptr_list ( void );
+static void cleanup_weak_ptr_list ( void );
+
+static void scavenge_stack ( StgPtr p, StgPtr stack_end );
+static void scavenge_large ( step *step );
+static void scavenge ( step *step );
+static void scavenge_static ( void );
+static void scavenge_mutable_list ( generation *g );
+static void scavenge_mut_once_list ( generation *g );
#ifdef DEBUG
-static void gcCAFs(void);
+static void gcCAFs ( void );
#endif
/* -----------------------------------------------------------------------------
scavenged_static_objects = END_OF_STATIC_LIST;
/* zero the mutable list for the oldest generation (see comment by
- * zeroMutableList below).
+ * zero_mutable_list below).
*/
if (major_gc) {
- zeroMutableList(generations[RtsFlags.GcFlags.generations-1].mut_once_list);
+ zero_mutable_list(generations[RtsFlags.GcFlags.generations-1].mut_once_list);
}
/* Save the old to-space if we're doing a two-space collection
/* Mark the weak pointer list, and prepare to detect dead weak
* pointers.
*/
- markWeakList();
old_weak_ptr_list = weak_ptr_list;
weak_ptr_list = NULL;
weak_done = rtsFalse;
*/
scavengeEverything();
/* revert dead CAFs and update enteredCAFs list */
- revertDeadCAFs();
+ revert_dead_CAFs();
#endif
markHugsObjects();
#if 0
}
}
- /* Now see which stable names are still alive
+ /* Final traversal of the weak pointer list (see comment by
+ * cleanUpWeakPtrList below).
+ */
+ cleanup_weak_ptr_list();
+
+ /* Now see which stable names are still alive.
*/
gcStablePtrTable(major_gc);
}
/* revert dead CAFs and update enteredCAFs list */
- revertDeadCAFs();
+ revert_dead_CAFs();
/* mark the garbage collected CAFs as dead */
#ifdef DEBUG
/* zero the scavenged static object list */
if (major_gc) {
- zeroStaticObjectList(scavenged_static_objects);
+ zero_static_object_list(scavenged_static_objects);
}
/* Reset the nursery
last_w = &old_weak_ptr_list;
for (w = old_weak_ptr_list; w; w = next_w) {
+ /* First, this weak pointer might have been evacuated. If so,
+ * remove the forwarding pointer from the weak_ptr_list.
+ */
+ if (get_itbl(w)->type == EVACUATED) {
+ w = (StgWeak *)((StgEvacuated *)w)->evacuee;
+ *last_w = w;
+ }
+
+ /* There might be a DEAD_WEAK on the list if finalizeWeak# was
+ * called on a live weak pointer object. Just remove it.
+ */
+ if (w->header.info == &DEAD_WEAK_info) {
+ next_w = ((StgDeadWeak *)w)->link;
+ *last_w = next_w;
+ continue;
+ }
+
+ ASSERT(get_itbl(w)->type == WEAK);
+
+ /* Now, check whether the key is reachable.
+ */
if ((new = isAlive(w->key))) {
w->key = new;
/* evacuate the value and finalizer */
}
/* -----------------------------------------------------------------------------
+ After GC, the live weak pointer list may have forwarding pointers
+ on it, because a weak pointer object was evacuated after being
+ moved to the live weak pointer list. We remove those forwarding
+ pointers here.
+
+ Also, we don't consider weak pointer objects to be reachable, but
+ we must nevertheless consider them to be "live" and retain them.
+ Therefore any weak pointer objects which haven't as yet been
+ evacuated need to be evacuated now.
+ -------------------------------------------------------------------------- */
+
+static void
+cleanup_weak_ptr_list ( void )
+{
+ StgWeak *w, **last_w;
+
+ last_w = &weak_ptr_list;
+ for (w = weak_ptr_list; w; w = w->link) {
+
+ if (get_itbl(w)->type == EVACUATED) {
+ w = (StgWeak *)((StgEvacuated *)w)->evacuee;
+ *last_w = w;
+ }
+
+ if (Bdescr((P_)w)->evacuated == 0) {
+ (StgClosure *)w = evacuate((StgClosure *)w);
+ *last_w = w;
+ }
+ last_w = &(w->link);
+ }
+}
+
+/* -----------------------------------------------------------------------------
isAlive determines whether the given closure is still alive (after
a garbage collection) or not. It returns the new address of the
closure if it is alive, or NULL otherwise.
}
static void
-zeroStaticObjectList(StgClosure* first_static)
+zero_static_object_list(StgClosure* first_static)
{
StgClosure* p;
StgClosure* link;
* mutable list.
*/
static void
-zeroMutableList(StgMutClosure *first)
+zero_mutable_list( StgMutClosure *first )
{
StgMutClosure *next, *c;
}
}
-void revertDeadCAFs(void)
+void revert_dead_CAFs(void)
{
StgCAF* caf = enteredCAFs;
enteredCAFs = END_CAF_LIST;
break;
}
default:
- barf("revertDeadCAFs: enteredCAFs list corrupted");
+ barf("revert_dead_CAFs: enteredCAFs list corrupted");
}
caf = next;
}