changeset 1590:03009473262a

[xemacs-hg @ 2003-07-26 14:00:27 by michaels] 2003-07-24 Mike Sperber <mike@xemacs.org> * lisp.h: * data.c: (init_marking_ephemerons): (continue_marking_ephemerons): (finish_marking_ephemerons): (prune_ephemerons): * alloc.c (garbage_collect_1): Rewrite the ephemeron marker once again to allow ephemerons to be used for implementing simple object finalization. * data.c (Fmake_ephemeron): Fix comments
author michaels
date Sat, 26 Jul 2003 14:00:28 +0000
parents ea138ff01850
children 75b8038f720e
files src/ChangeLog src/alloc.c src/data.c src/lisp.h
diffstat 4 files changed, 104 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Jul 25 21:52:27 2003 +0000
+++ b/src/ChangeLog	Sat Jul 26 14:00:28 2003 +0000
@@ -1,3 +1,16 @@
+2003-07-24  Mike Sperber  <mike@xemacs.org>
+
+	* lisp.h: 
+	* data.c: 
+	(init_marking_ephemerons): 
+	(continue_marking_ephemerons): 
+	(finish_marking_ephemerons): 
+	(prune_ephemerons): 
+	* alloc.c (garbage_collect_1): Rewrite the ephemeron marker once
+	again to allow ephemerons to be used for implementing simple
+	object finalization.
+	* data.c (Fmake_ephemeron): Fix comments
+
 2003-06-14  Ilya N. Golubev  <gin@mo.msk.ru>
 
 	* .gdbinit (pobj): Fix printing of symbol names.
--- a/src/alloc.c	Fri Jul 25 21:52:27 2003 +0000
+++ b/src/alloc.c	Sat Jul 26 14:00:28 2003 +0000
@@ -4609,10 +4609,19 @@
      a weak hash table might be unmarked, but after processing a later
      weak hash table, the former one might get marked.  So we have to
      iterate until nothing more gets marked. */
-
+  
+  init_marking_ephemerons ();
   while (finish_marking_weak_hash_tables () > 0 ||
 	 finish_marking_weak_lists       () > 0 ||
-	 finish_marking_ephemerons       () > 0)
+	 continue_marking_ephemerons     () > 0)
+    ;
+
+  /* At this point, we know which objects need to be finalized: we
+     still need to resurrect them */
+
+  while (finish_marking_ephemerons       () > 0 ||
+	 finish_marking_weak_lists       () > 0 ||
+	 finish_marking_weak_hash_tables () > 0)
     ;
 
   /* And prune (this needs to be called after everything else has been
--- a/src/data.c	Fri Jul 25 21:52:27 2003 +0000
+++ b/src/data.c	Sat Jul 26 14:00:28 2003 +0000
@@ -2132,72 +2132,106 @@
  */
 
 static Lisp_Object Vall_ephemerons; /* Gemarke es niemals ever!!! */
+static Lisp_Object Vnew_all_ephemerons;
 static Lisp_Object Vfinalize_list;
 
+void
+init_marking_ephemerons(void)
+{
+  Vnew_all_ephemerons = Qnil;
+}
+
+/* Move all live ephemerons with live keys over to
+ * Vnew_all_ephemerons, marking the values and finalizers along the
+ * way. */
+
+int
+continue_marking_ephemerons(void)
+{
+  Lisp_Object rest = Vall_ephemerons, next, prev = Qnil;
+  int did_mark = 0;
+
+  while (!NILP (rest))
+    {
+      next = XEPHEMERON_NEXT (rest);
+
+      if (marked_p (rest))
+	{
+	  MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain));
+	  if (marked_p (XEPHEMERON (rest)->key))
+	    {
+	      mark_object (XCAR (XEPHEMERON (rest)->cons_chain));
+	      did_mark = 1;
+	      XSET_EPHEMERON_NEXT (rest, Vnew_all_ephemerons);
+	      Vnew_all_ephemerons = rest;
+	      if (NILP (prev))
+		Vall_ephemerons = next;
+	      else
+		XSET_EPHEMERON_NEXT (prev, next);
+	    }
+	  else
+	    prev = rest;
+	}
+      else
+	prev = rest;
+
+      rest = next;
+    }
+
+  return did_mark;
+}
+
+/* At this point, everything that's in Vall_ephemerons is dead.
+ * Well, almost: we still need to run the finalizers, so we need to
+ * resurrect them.
+ */
+
 int
 finish_marking_ephemerons(void)
 {
-  Lisp_Object rest;
+  Lisp_Object rest = Vall_ephemerons, next, prev = Qnil;
   int did_mark = 0;
 
-  for (rest = Vall_ephemerons;
-       !NILP (rest);
-       rest = XEPHEMERON_NEXT (rest))
-    {
-      if (marked_p (rest) && ! marked_p (XEPHEMERON (rest)->cons_chain))
-	{
-	  MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain));
-	  mark_object (XCAR (XEPHEMERON (rest)->cons_chain));
-	  did_mark = 1;
-	}
-    }
-  return did_mark;
-}
-
-void
-prune_ephemerons(void)
-{
-  int removep = 0;
-  Lisp_Object rest = Vall_ephemerons, next, prev = Qnil;
-
   while (! NILP (rest))
     {
       next = XEPHEMERON_NEXT (rest);
 
       if (marked_p (rest))
-	/* The ephemeron itself is live ... */
+	/* The ephemeron itself is live, but its key is garbage */
 	{
-	  if (! marked_p(XEPHEMERON (rest)->key))
-	    /* ... but its key is garbage */
+	  /* tombstone */
+	  XSET_EPHEMERON_VALUE (rest, Qnil);
+
+	  if (! NILP (XEPHEMERON_FINALIZER (rest)))
 	    {
-	      removep = 1;
-	      XSET_EPHEMERON_VALUE (rest, Qnil);
-	      if (! NILP (XEPHEMERON_FINALIZER (rest)))
-		/* Register the finalizer */
-		{
-		  XSET_EPHEMERON_NEXT (rest, Vfinalize_list);
-		  Vfinalize_list = XEPHEMERON (rest)->cons_chain;
-		}
+	      MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain));
+	      mark_object (XCAR (XEPHEMERON (rest)->cons_chain));
+
+	      /* Register the finalizer */
+	      XSET_EPHEMERON_NEXT (rest, Vfinalize_list);
+	      Vfinalize_list = XEPHEMERON (rest)->cons_chain;
+	      did_mark = 1;
 	    }
-	}
-      else
-	/* The ephemeron itself is dead. */
-	removep = 1;
 
-      if (removep)
-	{
 	  /* Remove it from the list. */
 	  if (NILP (prev))
 	    Vall_ephemerons = next;
 	  else
 	    XSET_EPHEMERON_NEXT (prev, next);
-	  removep = 0;
 	}
       else
 	prev = rest;
 
       rest = next;
     }
+  
+  return did_mark;
+}
+
+void
+prune_ephemerons(void)
+{
+  Vall_ephemerons = Vnew_all_ephemerons;
 }
 
 Lisp_Object
@@ -2282,13 +2316,13 @@
 			       struct ephemeron);
 
 DEFUN ("make-ephemeron", Fmake_ephemeron, 2, 3, 0, /*
-Return a new ephemeron with key KEY, value CONTENTS, and finalizer FINALIZER.
-The ephemeron is a reference to CONTENTS which may be extracted with
-`ephemeron-ref'.  CONTENTS is only reachable through the ephemeron as
+Return a new ephemeron with key KEY, value VALUE, and finalizer FINALIZER.
+The ephemeron is a reference to VALUE which may be extracted with
+`ephemeron-ref'.  VALUE is only reachable through the ephemeron as
 long as KEY is reachable; the ephemeron does not contribute to the
 reachability of KEY.  When KEY becomes unreachable while the ephemeron
-itself is still reachable, CONTENTS is queued for finalization: FINALIZER
-will possibly be called on CONTENTS some time in the future.  Moreover,
+itself is still reachable, VALUE is queued for finalization: FINALIZER
+will possibly be called on VALUE some time in the future.  Moreover,
 future calls to `ephemeron-ref' will return NIL.
 */
        (key, value, finalizer))
--- a/src/lisp.h	Fri Jul 25 21:52:27 2003 +0000
+++ b/src/lisp.h	Sat Jul 26 14:00:28 2003 +0000
@@ -2756,6 +2756,8 @@
 
 void prune_ephemerons (void);
 Lisp_Object ephemeron_value(Lisp_Object ephi);
+void init_marking_ephemerons(void);
+int continue_marking_ephemerons(void);
 int finish_marking_ephemerons(void);
 Lisp_Object zap_finalize_list(void);
 Lisp_Object make_ephemeron(Lisp_Object key, Lisp_Object value, Lisp_Object finalizer);