From c4ccb861096f22f2de9727ce120123ea19d16530 Mon Sep 17 00:00:00 2001
From: Martin Stjernholm <mast@lysator.liu.se>
Date: Tue, 4 Jul 2000 02:43:58 +0200
Subject: [PATCH] Expelled even the innocent zeroing of destructed object
 references from the gc check pass. It's upsetting the debug checks, and it's
 cleaner to do all zapping of refs in the mark/cycle check pass anyway.

Rev: src/array.c:1.74
Rev: src/gc.c:1.101
Rev: src/gc.h:1.53
Rev: src/mapping.c:1.90
Rev: src/object.c:1.131
Rev: src/svalue.c:1.81
Rev: src/svalue.h:1.60
---
 src/array.c   | 40 +++++++++++----------
 src/gc.c      | 14 +++-----
 src/gc.h      | 18 ++++------
 src/mapping.c | 26 +++++++++-----
 src/object.c  |  5 ++-
 src/svalue.c  | 99 ++++++++++++++++++++++++++-------------------------
 src/svalue.h  | 14 ++++----
 7 files changed, 110 insertions(+), 106 deletions(-)

diff --git a/src/array.c b/src/array.c
index fb4ef40079..ccfbf4c355 100644
--- a/src/array.c
+++ b/src/array.c
@@ -23,7 +23,7 @@
 #include "stuff.h"
 #include "bignum.h"
 
-RCSID("$Id: array.c,v 1.73 2000/06/09 22:43:04 mast Exp $");
+RCSID("$Id: array.c,v 1.74 2000/07/04 00:43:56 mast Exp $");
 
 struct array empty_array=
 {
@@ -1784,25 +1784,15 @@ static void gc_check_array(struct array *a)
 {
   if(a->type_field & BIT_COMPLEX)
   {
-    TYPE_FIELD t;
     if (a->flags & ARRAY_WEAK_FLAG)
-      t=debug_gc_check_weak_svalues(ITEM(a), a->size, T_ARRAY, a);
+      debug_gc_check_weak_svalues(ITEM(a), a->size, T_ARRAY, a);
     else
-      t=debug_gc_check_svalues(ITEM(a), a->size, T_ARRAY, a);
-
-    /* Ugly, but we are not allowed to change type_field
-     * at the same time as the array is being built...
-     * Actually we just need better primitives for building arrays.
-     */
-    if(!(a->type_field & BIT_UNFINISHED) || a->refs!=1)
-      a->type_field = t;
-    else
-      a->type_field |= t;
+      debug_gc_check_svalues(ITEM(a), a->size, T_ARRAY, a);
   }
 }
 
 static void gc_recurse_weak_array(struct array *a,
-				  TYPE_FIELD (*recurse_fn)(struct svalue *, int))
+				  TYPE_FIELD (*recurse_fn)(struct svalue *, size_t))
 {
   int e;
   TYPE_FIELD t;
@@ -1857,8 +1847,15 @@ void gc_mark_array_as_referenced(struct array *a)
     {
       if (a->flags & ARRAY_WEAK_FLAG)
 	gc_recurse_weak_array(a, gc_mark_weak_svalues);
-      else
-	gc_mark_svalues(ITEM(a), a->size);
+      else {
+	TYPE_FIELD t;
+	if ((t = gc_mark_svalues(ITEM(a), a->size))) {
+	  if(!(a->type_field & BIT_UNFINISHED) || a->refs!=1)
+	    a->type_field = t;
+	  else
+	    a->type_field |= t;
+	}
+      }
     }
   }
 }
@@ -1874,8 +1871,15 @@ static void low_gc_cycle_check_array(struct array *a)
   {
     if (a->flags & ARRAY_WEAK_FLAG)
       gc_recurse_weak_array(a, gc_cycle_check_weak_svalues);
-    else
-      gc_cycle_check_svalues(ITEM(a), a->size);
+    else {
+      TYPE_FIELD t;
+      if ((t = gc_cycle_check_svalues(ITEM(a), a->size))) {
+	if(!(a->type_field & BIT_UNFINISHED) || a->refs!=1)
+	  a->type_field = t;
+	else
+	  a->type_field |= t;
+      }
+    }
   }
 }
 
diff --git a/src/gc.c b/src/gc.c
index 96ff37c2fc..18ad5dcb86 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -29,7 +29,7 @@ struct callback *gc_evaluator_callback=0;
 
 #include "block_alloc.h"
 
-RCSID("$Id: gc.c,v 1.100 2000/07/03 18:38:26 mast Exp $");
+RCSID("$Id: gc.c,v 1.101 2000/07/04 00:43:57 mast Exp $");
 
 /* Run garbage collect approximately every time
  * 20 percent of all arrays, objects and programs is
@@ -453,26 +453,22 @@ void debug_gc_xmark_svalues(struct svalue *s, int num, char *fromwhere)
   found_in=0;
 }
 
-TYPE_FIELD debug_gc_check_svalues(struct svalue *s, int num, TYPE_T t, void *data)
+void debug_gc_check_svalues(struct svalue *s, int num, TYPE_T t, void *data)
 {
-  TYPE_FIELD ret;
   found_in=data;
   found_in_type=t;
-  ret=gc_check_svalues(s,num);
+  gc_check_svalues(s,num);
   found_in_type=T_UNKNOWN;
   found_in=0;
-  return ret;
 }
 
-TYPE_FIELD debug_gc_check_weak_svalues(struct svalue *s, int num, TYPE_T t, void *data)
+void debug_gc_check_weak_svalues(struct svalue *s, int num, TYPE_T t, void *data)
 {
-  TYPE_FIELD ret;
   found_in=data;
   found_in_type=t;
-  ret=gc_check_weak_svalues(s,num);
+  gc_check_weak_svalues(s,num);
   found_in_type=T_UNKNOWN;
   found_in=0;
-  return ret;
 }
 
 void debug_gc_check_short_svalue(union anything *u, TYPE_T type, TYPE_T t, void *data)
diff --git a/src/gc.h b/src/gc.h
index 2ab06c3958..2cf31512f8 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -1,5 +1,5 @@
 /*
- * $Id: gc.h,v 1.52 2000/07/03 16:50:09 mast Exp $
+ * $Id: gc.h,v 1.53 2000/07/04 00:43:57 mast Exp $
  */
 #ifndef GC_H
 #define GC_H
@@ -49,24 +49,18 @@ extern void *gc_svalue_location;
 } while(0)
 #endif
 
-#define LOW_GC_FREE() do {						\
+#define GC_FREE() do {							\
   DO_IF_DEBUG(								\
     extern int d_flag;							\
     if(d_flag) CHECK_INTERPRETER_LOCK();				\
+    if(Pike_in_gc == GC_PASS_CHECK)					\
+      fatal("Freeing objects in this gc pass is not allowed.\n");	\
     if(num_objects < 1)							\
       fatal("Panic!! less than zero objects!\n");			\
   )									\
   num_objects-- ;							\
 }while(0)
 
-#define GC_FREE() do {							\
-  DO_IF_DEBUG(								\
-    if(Pike_in_gc == GC_PASS_CHECK)					\
-      fatal("Freeing objects in this gc pass is not allowed.\n");	\
-  );									\
-  LOW_GC_FREE();							\
-} while (0)
-
 struct marker
 {
   struct marker *next;
@@ -123,8 +117,8 @@ void describe_location(void *memblock, int type, void *location,int indent, int
 void debug_gc_fatal(void *a, int flags, const char *fmt, ...)
   ATTRIBUTE((format(printf, 3, 4)));
 void debug_gc_xmark_svalues(struct svalue *s, int num, char *fromwhere);
-TYPE_FIELD debug_gc_check_svalues(struct svalue *s, int num, TYPE_T t, void *data);
-TYPE_FIELD debug_gc_check_weak_svalues(struct svalue *s, int num, TYPE_T t, void *data);
+void debug_gc_check_svalues(struct svalue *s, int num, TYPE_T t, void *data);
+void debug_gc_check_weak_svalues(struct svalue *s, int num, TYPE_T t, void *data);
 void debug_gc_check_short_svalue(union anything *u, TYPE_T type, TYPE_T t, void *data);
 void debug_gc_check_weak_short_svalue(union anything *u, TYPE_T type, TYPE_T t, void *data);
 int debug_gc_check(void *x, TYPE_T t, void *data);
diff --git a/src/mapping.c b/src/mapping.c
index 8e020ae11e..ce79e7a213 100644
--- a/src/mapping.c
+++ b/src/mapping.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: mapping.c,v 1.89 2000/07/03 20:14:07 mast Exp $");
+RCSID("$Id: mapping.c,v 1.90 2000/07/04 00:43:57 mast Exp $");
 #include "main.h"
 #include "object.h"
 #include "mapping.h"
@@ -1891,8 +1891,13 @@ void gc_mark_mapping_as_referenced(struct mapping *m)
       else
 	NEW_MAPPING_LOOP(m->data)
 	{
-	  gc_mark_svalues(&k->ind, 1);
-	  gc_mark_svalues(&k->val, 1);
+	  if (gc_mark_svalues(&k->ind, 1) ||
+	      gc_mark_svalues(&k->val, 1)) {
+#ifdef PIKE_DEBUG
+	    fatal("Looks like check_mapping_for_destruct "
+		  "didn't do its job properly.\n");
+#endif
+	  }
 	}
     }
   }
@@ -1915,8 +1920,13 @@ void low_gc_cycle_check_mapping(struct mapping *m)
     else
       NEW_MAPPING_LOOP(m->data)
       {
-	gc_cycle_check_svalues(&k->ind, 1);
-	gc_cycle_check_svalues(&k->val, 1);
+	if (gc_cycle_check_svalues(&k->ind, 1) ||
+	    gc_cycle_check_svalues(&k->val, 1)) {
+#ifdef PIKE_DEBUG
+	  fatal("Looks like check_mapping_for_destruct "
+		"didn't do its job properly.\n");
+#endif
+	}
       }
   }
 }
@@ -1955,8 +1965,7 @@ static void gc_check_mapping(struct mapping *m)
 	  continue;
 
 	debug_gc_check_weak_svalues(&k->ind, 1, T_MAPPING, m);
-	m->data->val_types |=
-	  debug_gc_check_weak_svalues(&k->val, 1, T_MAPPING, m);
+	debug_gc_check_weak_svalues(&k->val, 1, T_MAPPING, m);
       }
     }
     else {
@@ -1970,8 +1979,7 @@ static void gc_check_mapping(struct mapping *m)
 	  continue;
 
 	debug_gc_check_svalues(&k->ind, 1, T_MAPPING, m);
-	m->data->val_types |=
-	  debug_gc_check_svalues(&k->val, 1, T_MAPPING, m);
+	debug_gc_check_svalues(&k->val, 1, T_MAPPING, m);
       }
     }
   }
diff --git a/src/object.c b/src/object.c
index 64425d970b..1a80fa5e46 100644
--- a/src/object.c
+++ b/src/object.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: object.c,v 1.130 2000/07/03 18:38:55 mast Exp $");
+RCSID("$Id: object.c,v 1.131 2000/07/04 00:43:57 mast Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -734,8 +734,7 @@ void schedule_really_free_object(struct object *o)
       /* It's a fake object which isn't counted by the gc, so
        * counteract the num_objects-- done by GC_FREE. */
       num_objects++;
-    /* This is the only free allowed in the gc check pass. */
-    LOW_GC_FREE();
+    GC_FREE();
 
     FREE_PROT(o);
 
diff --git a/src/svalue.c b/src/svalue.c
index 28ad48b240..d2032aba1f 100644
--- a/src/svalue.c
+++ b/src/svalue.c
@@ -23,7 +23,7 @@
 #include "queue.h"
 #include "bignum.h"
 
-RCSID("$Id: svalue.c,v 1.80 2000/07/03 20:14:07 mast Exp $");
+RCSID("$Id: svalue.c,v 1.81 2000/07/04 00:43:57 mast Exp $");
 
 struct svalue dest_ob_zero = { T_INT, 0 };
 
@@ -1283,86 +1283,63 @@ void real_gc_xmark_svalues(struct svalue *s, ptrdiff_t num)
       fatal("Cannot have a function in a short svalue.\n");
 
 #define DO_CHECK_OBJ(U, T, ZAP, GC_DO)					\
-      if (U.object->prog)						\
-	GC_DO(U.object);						\
-      else ZAP();							\
+      GC_DO(U.object);							\
       break;
 
 #define DO_CHECK_OBJ_WEAK(U, T, ZAP, GC_DO)				\
-      if(U.object->prog)						\
-	if (U.object->prog->flags & PROGRAM_NO_WEAK_FREE)		\
-	  gc_check(U.object);						\
-	else								\
-	  gc_check_weak(U.object);					\
-      else ZAP();							\
+      if (U.object->prog &&						\
+	  !(U.object->prog->flags & PROGRAM_NO_WEAK_FREE))		\
+	gc_check_weak(U.object);					\
+      else								\
+	gc_check(U.object);						\
       break;
 
-#define ZAP_SVALUE()							\
-      do {								\
-	free_svalue(s);							\
-	s->type = T_INT;						\
-	s->u.integer = 0;						\
-	s->subtype = NUMBER_DESTRUCTED;					\
-      } while (0)
-
-#define ZAP_SHORT_SVALUE()						\
-      do {								\
-	free_short_svalue(u, type);					\
-	u->refs = 0;							\
-      } while (0)
+#define NEVER_ZAP()
 
 #define SET_SUB_SVALUE(V) s->subtype = (V)
 
 #define SET_SUB_SHORT_SVALUE(V)
 
-TYPE_FIELD real_gc_check_svalues(struct svalue *s, size_t num)
+void real_gc_check_svalues(struct svalue *s, size_t num)
 {
 #ifdef PIKE_DEBUG
   extern void * check_for;
 #endif
   size_t e;
-  TYPE_FIELD f;
-  f=0;
   for(e=0;e<num;e++,s++)
   {
     check_svalue(s);
 #ifdef PIKE_DEBUG
     gc_svalue_location=(void *)s;
 #endif
-    GC_CHECK_SWITCH((s->u), (s->type), ZAP_SVALUE, gc_check,
+    GC_CHECK_SWITCH((s->u), (s->type), NEVER_ZAP, gc_check,
 		    {}, DO_CHECK_FUNC_SVALUE,
 		    DO_CHECK_OBJ);
-    f|= 1 << s->type;
   }
 #ifdef PIKE_DEBUG
   gc_svalue_location=0;
 #endif
-  return f;
 }
 
-TYPE_FIELD gc_check_weak_svalues(struct svalue *s, size_t num)
+void gc_check_weak_svalues(struct svalue *s, size_t num)
 {
 #ifdef PIKE_DEBUG
   extern void * check_for;
 #endif
   size_t e;
-  TYPE_FIELD f;
-  f=0;
   for(e=0;e<num;e++,s++)
   {
     check_svalue(s);
 #ifdef PIKE_DEBUG
     gc_svalue_location=(void *)s;
 #endif
-    GC_CHECK_SWITCH((s->u), (s->type), ZAP_SVALUE, gc_check_weak,
+    GC_CHECK_SWITCH((s->u), (s->type), NEVER_ZAP, gc_check_weak,
 		    {}, DO_CHECK_FUNC_SVALUE,
 		    DO_CHECK_OBJ_WEAK);
-    f|= 1 << s->type;
   }
 #ifdef PIKE_DEBUG
   gc_svalue_location=0;
 #endif
-  return f;
 }
 
 void real_gc_check_short_svalue(union anything *u, TYPE_T type)
@@ -1372,7 +1349,7 @@ void real_gc_check_short_svalue(union anything *u, TYPE_T type)
   gc_svalue_location=(void *)u;
 #endif
   debug_malloc_touch(u);
-  GC_CHECK_SWITCH((*u), type, ZAP_SHORT_SVALUE, gc_check,
+  GC_CHECK_SWITCH((*u), type, NEVER_ZAP, gc_check,
 		  {if (!u->refs) return;}, DO_FUNC_SHORT_SVALUE,
 		  DO_CHECK_OBJ);
 #ifdef PIKE_DEBUG
@@ -1387,7 +1364,7 @@ void gc_check_weak_short_svalue(union anything *u, TYPE_T type)
   gc_svalue_location=(void *)u;
 #endif
   debug_malloc_touch(u);
-  GC_CHECK_SWITCH((*u), type, ZAP_SHORT_SVALUE, gc_check_weak,
+  GC_CHECK_SWITCH((*u), type, NEVER_ZAP, gc_check_weak,
 		  {if (!u->refs) return;}, DO_FUNC_SHORT_SVALUE,
 		  DO_CHECK_OBJ_WEAK);
 #ifdef PIKE_DEBUG
@@ -1395,17 +1372,31 @@ void gc_check_weak_short_svalue(union anything *u, TYPE_T type)
 #endif
 }
 
+#define ZAP_SVALUE()							\
+      do {								\
+	free_svalue(s);							\
+	s->type = T_INT;						\
+	s->u.integer = 0;						\
+	s->subtype = NUMBER_DESTRUCTED;					\
+      } while (0)
+
+#define ZAP_SHORT_SVALUE()						\
+      do {								\
+	free_short_svalue(u, type);					\
+	u->refs = 0;							\
+      } while (0)
+
 #define GC_RECURSE_SWITCH(U,T,ZAP,FREE_WEAK,GC_DO,PRE,DO_FUNC,DO_STR)	\
   switch (T) {								\
     case T_FUNCTION:							\
       PRE DO_FUNC(U, T, ZAP, GC_DO)					\
     case T_OBJECT:							\
       PRE								\
-      DO_IF_DEBUG(							\
-	if (!U.object->prog)						\
-	  gc_fatal(U.object, 0,						\
-		   "Unfreed destructed object in mark pass.\n");	\
-      )									\
+      if (!U.object->prog) {						\
+	ZAP();								\
+	freed = 1;							\
+	break;								\
+      }									\
       FREE_WEAK(U, T, ZAP) GC_DO(U, object);				\
       break;								\
     case T_STRING:							\
@@ -1449,8 +1440,10 @@ void gc_check_weak_short_svalue(union anything *u, TYPE_T type)
       break;								\
     }
 
-void real_gc_mark_svalues(struct svalue *s, size_t num)
+TYPE_FIELD real_gc_mark_svalues(struct svalue *s, size_t num)
 {
+  TYPE_FIELD t = 0;
+  int freed = 0;
   size_t e;
   for(e=0;e<num;e++,s++)
   {
@@ -1458,7 +1451,9 @@ void real_gc_mark_svalues(struct svalue *s, size_t num)
     GC_RECURSE_SWITCH((s->u), (s->type), ZAP_SVALUE, DONT_FREE_WEAK,
 		      GC_DO_MARK, {},
 		      DO_MARK_FUNC_SVALUE, DO_MARK_STRING);
+    t |= 1 << s->type;
   }
+  return freed ? t : 0;
 }
 
 TYPE_FIELD gc_mark_weak_svalues(struct svalue *s, size_t num)
@@ -1477,12 +1472,14 @@ TYPE_FIELD gc_mark_weak_svalues(struct svalue *s, size_t num)
   return freed ? t : 0;
 }
 
-void real_gc_mark_short_svalue(union anything *u, TYPE_T type)
+int real_gc_mark_short_svalue(union anything *u, TYPE_T type)
 {
+  int freed = 0;
   debug_malloc_touch(u);
   GC_RECURSE_SWITCH((*u), type, ZAP_SHORT_SVALUE, DONT_FREE_WEAK,
-		    GC_DO_MARK, {if (!u->refs) return;},
+		    GC_DO_MARK, {if (!u->refs) return 0;},
 		    DO_FUNC_SHORT_SVALUE, DO_MARK_STRING);
+  return freed;
 }
 
 int gc_mark_weak_short_svalue(union anything *u, TYPE_T type)
@@ -1504,8 +1501,10 @@ int gc_mark_weak_short_svalue(union anything *u, TYPE_T type)
 #define GC_DO_CYCLE_CHECK(U, TN) PIKE_CONCAT(gc_cycle_check_, TN)(U.TN)
 #define GC_DO_CYCLE_CHECK_WEAK(U, TN) PIKE_CONCAT3(gc_cycle_check_, TN, _weak)(U.TN)
 
-void real_gc_cycle_check_svalues(struct svalue *s, size_t num)
+TYPE_FIELD real_gc_cycle_check_svalues(struct svalue *s, size_t num)
 {
+  TYPE_FIELD t = 0;
+  int freed = 0;
   size_t e;
   for(e=0;e<num;e++,s++)
   {
@@ -1513,7 +1512,9 @@ void real_gc_cycle_check_svalues(struct svalue *s, size_t num)
     GC_RECURSE_SWITCH((s->u), (s->type), ZAP_SVALUE, DONT_FREE_WEAK,
 		      GC_DO_CYCLE_CHECK, {},
 		      DO_CYCLE_CHECK_FUNC_SVALUE, DO_CYCLE_CHECK_STRING);
+    t |= 1 << s->type;
   }
+  return freed ? t : 0;
 }
 
 TYPE_FIELD gc_cycle_check_weak_svalues(struct svalue *s, size_t num)
@@ -1532,12 +1533,14 @@ TYPE_FIELD gc_cycle_check_weak_svalues(struct svalue *s, size_t num)
   return freed ? t : 0;
 }
 
-void real_gc_cycle_check_short_svalue(union anything *u, TYPE_T type)
+int real_gc_cycle_check_short_svalue(union anything *u, TYPE_T type)
 {
+  int freed = 0;
   debug_malloc_touch(u);
   GC_RECURSE_SWITCH((*u), type, ZAP_SHORT_SVALUE, DONT_FREE_WEAK,
-		    GC_DO_CYCLE_CHECK, {if (!u->refs) return;},
+		    GC_DO_CYCLE_CHECK, {if (!u->refs) return 0;},
 		    DO_FUNC_SHORT_SVALUE, DO_CYCLE_CHECK_STRING);
+  return freed;
 }
 
 int gc_cycle_check_weak_short_svalue(union anything *u, TYPE_T type)
diff --git a/src/svalue.h b/src/svalue.h
index 293dc1e338..8951eeb5d6 100644
--- a/src/svalue.h
+++ b/src/svalue.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: svalue.h,v 1.59 2000/07/03 20:14:08 mast Exp $
+ * $Id: svalue.h,v 1.60 2000/07/04 00:43:58 mast Exp $
  */
 #ifndef SVALUE_H
 #define SVALUE_H
@@ -375,16 +375,16 @@ void copy_svalues_recursively_no_free(struct svalue *to,
 void check_short_svalue(union anything *u, TYPE_T type);
 void debug_check_svalue(struct svalue *s);
 void real_gc_xmark_svalues(struct svalue *s, ptrdiff_t num);
-TYPE_FIELD real_gc_check_svalues(struct svalue *s, size_t num);
+void real_gc_check_svalues(struct svalue *s, size_t num);
 void real_gc_check_short_svalue(union anything *u, TYPE_T type);
-TYPE_FIELD gc_check_weak_svalues(struct svalue *s, size_t num);
+void gc_check_weak_svalues(struct svalue *s, size_t num);
 void gc_check_weak_short_svalue(union anything *u, TYPE_T type);
-void real_gc_mark_svalues(struct svalue *s, size_t num);
-void real_gc_mark_short_svalue(union anything *u, TYPE_T type);
+TYPE_FIELD real_gc_mark_svalues(struct svalue *s, size_t num);
+int real_gc_mark_short_svalue(union anything *u, TYPE_T type);
 TYPE_FIELD gc_mark_weak_svalues(struct svalue *s, size_t num);
 int gc_mark_weak_short_svalue(union anything *u, TYPE_T type);
-void real_gc_cycle_check_svalues(struct svalue *s, size_t num);
-void real_gc_cycle_check_short_svalue(union anything *u, TYPE_T type);
+TYPE_FIELD real_gc_cycle_check_svalues(struct svalue *s, size_t num);
+int real_gc_cycle_check_short_svalue(union anything *u, TYPE_T type);
 TYPE_FIELD gc_cycle_check_weak_svalues(struct svalue *s, size_t num);
 int gc_cycle_check_weak_short_svalue(union anything *u, TYPE_T type);
 INT32 pike_sizeof(struct svalue *s);
-- 
GitLab