From 10b81c59c3dc8e66f1a61e58edcac5b12fd39922 Mon Sep 17 00:00:00 2001
From: simonm <unknown>
Date: Fri, 26 Feb 1999 17:46:09 +0000
Subject: [PATCH] [project @ 1999-02-26 17:46:04 by simonm] Fix a bug in weak
 pointer support: if finalize is called on a weak pointer, then a DEAD_WEAK
 object could appear on the weak pointer list.

To avoid needing to double-link this list, add a link field to
DEAD_WEAK objects, and remove them from the list at garbage collection
time.
---
 ghc/includes/Closures.h |  7 ++++++-
 ghc/rts/GC.c            | 12 +++++++++++-
 ghc/rts/PrimOps.hc      | 13 ++++++++-----
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/ghc/includes/Closures.h b/ghc/includes/Closures.h
index 23446c457c4d..76aeecc5680c 100644
--- a/ghc/includes/Closures.h
+++ b/ghc/includes/Closures.h
@@ -1,5 +1,5 @@
 /* ----------------------------------------------------------------------------
- * $Id: Closures.h,v 1.9 1999/02/19 18:26:04 sewardj Exp $
+ * $Id: Closures.h,v 1.10 1999/02/26 17:46:04 simonm Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -265,6 +265,11 @@ typedef struct _StgWeak {	/* Weak v */
   struct _StgWeak *link;
 } StgWeak;
 
+typedef struct _StgDeadWeak {	/* Weak v */
+  StgHeader header;
+  struct _StgWeak *link;
+} StgDeadWeak;
+
 /* Dynamic stack frames - these have a liveness mask in the object
  * itself, rather than in the info table.  Useful for generic heap
  * check code.
diff --git a/ghc/rts/GC.c b/ghc/rts/GC.c
index 71048a16f90e..64108c9b4d3e 100644
--- a/ghc/rts/GC.c
+++ b/ghc/rts/GC.c
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: GC.c,v 1.44 1999/02/26 13:36:12 simonm Exp $
+ * $Id: GC.c,v 1.45 1999/02/26 17:46:08 simonm Exp $
  *
  * (c) The GHC Team 1998-1999
  *
@@ -758,6 +758,16 @@ traverse_weak_ptr_list(void)
       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.
diff --git a/ghc/rts/PrimOps.hc b/ghc/rts/PrimOps.hc
index 33e2d2332d75..37af75ff9264 100644
--- a/ghc/rts/PrimOps.hc
+++ b/ghc/rts/PrimOps.hc
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: PrimOps.hc,v 1.17 1999/02/26 12:46:48 simonm Exp $
+ * $Id: PrimOps.hc,v 1.18 1999/02/26 17:46:09 simonm Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -348,10 +348,11 @@ FN_(finalizzeWeakzh_fast)
 {
   /* R1.p = weak ptr
    */
-  StgWeak *w;
+  StgDeadWeak *w;
+  StgClosure *f;
   FB_
   TICK_RET_UNBOXED_TUP(0);
-  w = (StgWeak *)R1.p;
+  w = (StgDeadWeak *)R1.p;
 
   /* already dead? */
   if (w->header.info == &DEAD_WEAK_info) {
@@ -360,12 +361,14 @@ FN_(finalizzeWeakzh_fast)
 
   /* kill it */
   w->header.info = &DEAD_WEAK_info;
+  f = ((StgWeak *)w)->finalizer;
+  w->link = ((StgWeak *)w)->link;
 
   /* return the finalizer */
-  if (w->finalizer == &NO_FINALIZER_closure) {
+  if (f == &NO_FINALIZER_closure) {
       RET_NP(0,&NO_FINALIZER_closure);
   } else {
-      RET_NP(1,w->finalizer);
+      RET_NP(1,f);
   }
   FE_
 }
-- 
GitLab