diff --git a/src/array.c b/src/array.c
index fb4ef40079a2f38cfae742e85de97cb24d006ac6..ccfbf4c355eede6ee2445103dc8e4e8c2746fd6a 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 96ff37c2fcad12019a29d1348da57ce25789394c..18ad5dcb8618aa283c5881030828268a0619a795 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 2ab06c39585510afb44f402aa8ad046055f19643..2cf31512f88a69c5ea932af03d33ccc3396e346f 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 8e020ae11e25d86388ed05165e13ce39f9e70b04..ce79e7a21352cba54b656a7b7bed2e64156c6c69 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 64425d970bfa9ce9488f1e927fcebcdacf22eb29..1a80fa5e4685aa06bf4eb248815ac85e2258574a 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 28ad48b240df07de5eac8ba3431d8ea2657d6652..d2032aba1fa60f10c1ea1ea6710430ac238f2cc6 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 293dc1e338816b90d1141483323bcfaf33ae5bfb..8951eeb5d6db1c8448ff732357bb4339e1fb8528 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);