diff --git a/src/gc.c b/src/gc.c
index 30983d1b4de9dd3bbd8d589c30f8fd395de9bde3..e3fd8dd3bcdda940b4cfd2095aa600191e2b8cb1 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: gc.c,v 1.301 2007/12/28 13:38:15 nilsson Exp $
+|| $Id: gc.c,v 1.302 2008/03/29 16:20:15 mast Exp $
 */
 
 #include "global.h"
@@ -3376,7 +3376,7 @@ size_t do_gc(void *ignored, int explicit_call)
     gc_check_all_programs();
     gc_check_all_objects();
 #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP)
-    debug_gc_check_all_types();
+    gc_check_all_types();
 #endif
   } END_ACCEPT_UNFINISHED_TYPE_FIELDS;
 
diff --git a/src/global.h b/src/global.h
index b3a430ef99084d6856bd353befd209334c02136b..8c08d3bfb943f25103a45258614e57e64284b402 100644
--- a/src/global.h
+++ b/src/global.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: global.h,v 1.110 2007/06/18 09:21:24 mast Exp $
+|| $Id: global.h,v 1.111 2008/03/29 16:20:16 mast Exp $
 */
 
 #ifndef GLOBAL_H
@@ -435,6 +435,12 @@ typedef struct p_wchar_p
 #define NDEBUG
 #endif
 
+#if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP)
+#define DO_IF_DEBUG_OR_CLEANUP(X) X
+#else
+#define DO_IF_DEBUG_OR_CLEANUP(X)
+#endif
+
 #ifdef INTERNAL_PROFILING
 #define DO_IF_INTERNAL_PROFILING(X) X
 #else
diff --git a/src/module.c b/src/module.c
index 82a330fc5c2f75cc9a1dac77f68bd237e288e7d0..616114646c4c94b904d042fbaf0f19511e955fd1 100644
--- a/src/module.c
+++ b/src/module.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: module.c,v 1.49 2008/02/15 17:37:04 grubba Exp $
+|| $Id: module.c,v 1.50 2008/03/29 16:20:16 mast Exp $
 */
 
 #include "global.h"
@@ -191,7 +191,8 @@ static void exit_builtin_modules(void)
       type_type_string, void_type_string, zero_type_string, any_type_string, \
       weak_type_string,
 
-#define REPORT_LINKED_LIST_LEAKS(TYPE, START, STATICS, T_TYPE, NAME) do { \
+#define REPORT_LINKED_LIST_LEAKS(TYPE, START, STATICS, T_TYPE, NAME,	\
+				 PRINT_EXTRA) do {			\
       struct TYPE *x;							\
       for (x = START; x; x = x->next) {					\
 	struct marker *m = find_marker (x);				\
@@ -213,37 +214,64 @@ static void exit_builtin_modules(void)
 	      fputs ("Leak(s) found at exit:\n", stderr);		\
 	      leak_found = 1;						\
 	    }								\
-	    fprintf (stderr, NAME " got %d unaccounted references: ",	\
-		     x->refs - (m->refs + is_static));			\
-	    print_short_svalue (stderr, (union anything *) &x, T_TYPE);	\
+	    fprintf (stderr, NAME " at %p got %d unaccounted references: ", \
+		     x, x->refs - (m->refs + is_static));		\
+	    safe_print_short_svalue (stderr, (union anything *) &x, T_TYPE); \
 	    fputc ('\n', stderr);					\
-	    DO_IF_DEBUG(if (T_TYPE == T_PROGRAM) {			\
-			  struct program *p = (struct program *)x;	\
-			  if (p->parent) {				\
-			    fprintf(stderr, "    Parent is: %p\n", \
-				    p->parent);				\
-			    dump_program_tables(p->parent, 6);		\
-			  }						\
-			  fprintf(stderr, "  Symbol tables:\n");	\
-			  dump_program_tables(p, 4);			\
-			});						\
-	    DO_IF_DMALLOC (debug_malloc_dump_references (x, 2, 1, 0));	\
+	    {PRINT_EXTRA;}						\
+	    DO_IF_DMALLOC (						\
+	      debug_malloc_dump_references (x, 2, 1, 0);		\
+	      fputc ('\n', stderr);					\
+	    );								\
 	  }								\
 	}								\
       }									\
     } while (0)
 
-    REPORT_LINKED_LIST_LEAKS (array, first_array, STATIC_ARRAYS, T_ARRAY, "Array");
-    REPORT_LINKED_LIST_LEAKS (multiset, first_multiset, NOTHING, T_MULTISET, "Multiset");
-    REPORT_LINKED_LIST_LEAKS (mapping, first_mapping, NOTHING, T_MAPPING, "Mapping");
-    REPORT_LINKED_LIST_LEAKS (program, first_program, NOTHING, T_PROGRAM, "Program");
-    REPORT_LINKED_LIST_LEAKS (object, first_object, NOTHING, T_OBJECT, "Object");
-    report_all_type_leaks();
+    REPORT_LINKED_LIST_LEAKS (array, first_array, STATIC_ARRAYS, T_ARRAY, "Array", {});
+    REPORT_LINKED_LIST_LEAKS (multiset, first_multiset, NOTHING, T_MULTISET, "Multiset", {});
+    REPORT_LINKED_LIST_LEAKS (mapping, first_mapping, NOTHING, T_MAPPING, "Mapping", {});
+    REPORT_LINKED_LIST_LEAKS (
+      program, first_program, NOTHING, T_PROGRAM, "Program",
+      {
+	/* This kind of info is rarely useful - the output from
+	 * print_short_svalue is usually enough to identify the program, and
+	 * the dmalloc ref dump shows where it has been used.
+	DO_IF_DEBUG(
+	  struct program *p = (struct program *)x;
+	  if (p->parent) {
+	    fprintf(stderr, "    Parent is: %p\n",
+		    p->parent);
+	    dump_program_tables(p->parent, 6);
+	  }
+	  fprintf(stderr, "  Symbol tables:\n");
+	  dump_program_tables(p, 4);
+	);
+	*/
+      }
+    );
+    REPORT_LINKED_LIST_LEAKS (
+      object, first_object, NOTHING, T_OBJECT, "Object", {
+	DO_IF_DEBUG (
+	  if (!x->prog) {
+	    struct program *p = id_to_program (x->program_id);
+	    if (p) {
+	      fputs ("Destructed object - program was: ", stderr);
+	      safe_print_short_svalue (stderr,
+				       (union anything *) &p, T_PROGRAM);
+	      fputc ('\n', stderr);
+	    }
+	    else
+	      fprintf (stderr, "Destructed object - "
+		       "program gone too, its id was %d\n", x->program_id);
+	  }
+	);
+      });
 
     {
       size_t index;
       for (index = 0; index < pike_type_hash_size; index++) {
-	REPORT_LINKED_LIST_LEAKS(pike_type, pike_type_hash[index], STATIC_TYPES, PIKE_T_TYPE, "Type");
+	REPORT_LINKED_LIST_LEAKS(pike_type, pike_type_hash[index], STATIC_TYPES, PIKE_T_TYPE, "Type", {});
       }
     }
 
diff --git a/src/pike_types.c b/src/pike_types.c
index 39303c501b77bdcaf3672cfeb3407c3618f0beaf..16be2c671f03eca7eebc7ee579e0bcf7ef328219 100644
--- a/src/pike_types.c
+++ b/src/pike_types.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: pike_types.c,v 1.317 2008/03/27 12:31:11 grubba Exp $
+|| $Id: pike_types.c,v 1.318 2008/03/29 16:20:16 mast Exp $
 */
 
 #include "global.h"
@@ -2417,34 +2417,6 @@ void debug_gc_check_all_types (void)
   }
 }
 
-/* Leak reporting similar to the exit_with_cleanup code in
- * exit_builtin_modules. */
-
-void report_all_type_leaks (void)
-{
-  unsigned INT32 index;
-  if (!gc_keep_markers)
-    Pike_fatal ("Should only be called in final cleanup.\n");
-  for (index = 0; index < pike_type_hash_size; index++) {
-    struct pike_type *t;
-    for (t = pike_type_hash[index]; t; t = t->next) {
-      struct marker *m = find_marker (t);
-      /* We aren't hooked in to the gc mark pass so we don't have
-       * markers for types with only external references. */
-      INT32 m_refs = m ? m->refs : 0;
-      if (t->refs != m_refs) {
-	fprintf (stderr, "Type at %p got %d unaccounted refs: ",
-		 t, t->refs - m_refs);
-	simple_describe_type (t);
-	fputc ('\n', stderr);
-#ifdef DEBUG_MALLOC
-	debug_malloc_dump_references (t, 2, 1, 0);
-#endif
-      }
-    }
-  }
-}
-
 void free_all_leaked_types (void)
 {
   unsigned INT32 index;
@@ -2454,21 +2426,24 @@ void free_all_leaked_types (void)
     struct pike_type *t;
     for (t = pike_type_hash[index]; t; t = t->next) {
       struct marker *m = find_marker (t);
-      INT32 m_refs = m ? m->refs : 0;
-      INT32 refs = t->refs;
-      if (refs > m_refs) {
+      if (m) {
+	INT32 refs = t->refs;
+	if (refs > m->refs) {
 #ifdef PIKE_DEBUG
-	if (m) m->flags |= GC_CLEANUP_FREED;
+	  m->flags |= GC_CLEANUP_FREED;
 #endif /* PIKE_DEBUG */
-	do {
-	  free_type (t);
-	  refs--;
-	} while (refs > m_refs);
-	/* t is invalid here, as is its next pointer.
-	 * Start over from the top of this hash entry.
-	 */
-	index--;
-	break;
+	  do {
+	    free_type (t);
+	    refs--;
+	  } while (refs > m->refs);
+	  if (!refs) {
+	    /* t is invalid here, as is its next pointer.
+	     * Start over from the top of this hash entry.
+	     */
+	    index--;
+	    break;
+	  }
+	}
       }
     }
   }
@@ -7713,8 +7688,12 @@ void cleanup_pike_type_table(void)
 #endif /* DO_PIKE_CLEANUP */
 }
 
-#if 0
-#ifdef PIKE_DEBUG
+#if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP)
+
+/* This is only enough gc stuff to detect leaking pike_type structs
+ * and to locate references to them. More is needed if types are
+ * extended to contain pointers to other memory objects or if they
+ * might contain cycles. */
 
 void gc_mark_type_as_referenced(struct pike_type *t)
 {
@@ -7748,78 +7727,17 @@ void gc_mark_type_as_referenced(struct pike_type *t)
   }
 }
 
-unsigned gc_touch_all_types(void)
+static void gc_check_type (struct pike_type *t)
 {
-  size_t e;
-  unsigned n = 0;
-  if (!pike_type_hash) return 0;
-  for(e=0;e<pike_type_hash_size;e++)
-  {
-    struct pike_type *t;
-    for(t = pike_type_hash[e]; t; t=t->next) debug_gc_touch(t), n++;
-  }
-  return n;
-}
+  debug_malloc_touch (t);
 
-void gc_mark_all_types(void)
-{
-  size_t e;
-  if(!pike_type_hash) return;
-  for(e=0;e<pike_type_hash_size;e++)
-  {
-    struct pike_type *t;
-    for(t=pike_type_hash[e]; t; t=t->next) {
-      if (gc_is_referenced(t)) {
-	gc_mark_type_as_referenced(t);
-      }
-    }
-  }
-}
-
-size_t gc_free_all_unreferenced_types(void)
-{
-  size_t unreferenced = 0;
-  size_t e;
-  for (e = 0; e < pike_type_hash_size; e++) {
-    struct pike_type *t;
-  loop:
-    for (t = pike_type_hash[e]; t; t = t->next) {
-      struct marker *m = find_marker(t);
-      if (!m) continue;
-      if ((m->flags & GC_GOT_EXTRA_REF) == GC_GOT_EXTRA_REF) {
-	if (gc_do_free(t)) {
-	  free_type(t);
-	  unreferenced++;
-	  /* The hash table may have been modified! */
-	  goto loop;
-	}
-      }
-    }
-  }
-  for (e = 0; e < pike_type_hash_size; e++) {
-    struct pike_type *t;
-    for (t = pike_type_hash[e]; t; t = t->next) {
-      struct marker *m = find_marker(t);
-      if (!m) continue;
-      if ((m->flags & GC_GOT_EXTRA_REF) == GC_GOT_EXTRA_REF) {
-	fprintf(stderr, "There's still an extra ref to ");
-	simple_describe_type(t);
-	fprintf(stderr, "\n");
-      }
-    }
-  }
-  return unreferenced;
-}
-
-void real_gc_cycle_check_type(struct pike_type *t, int weak)
-{
-  GC_CYCLE_ENTER(t, PIKE_T_TYPE, weak) {
+  GC_ENTER (t, PIKE_T_TYPE) {
     switch(t->type) {
       case PIKE_T_SCOPE:
       case T_ASSIGN:
       case PIKE_T_NAME:
       case PIKE_T_ATTRIBUTE:
-	if (t->cdr) gc_cycle_check_type(t->cdr, 0);
+	if (t->cdr) debug_gc_check (t->cdr, " as cdr in a type");
 	break;
       case PIKE_T_FUNCTION:
       case T_MANY:
@@ -7828,34 +7746,28 @@ void real_gc_cycle_check_type(struct pike_type *t, int weak)
       case PIKE_T_MAPPING:
       case T_OR:
       case T_AND:
-	if (t->cdr) gc_cycle_check_type(t->cdr, 0);
-      /* FALL_THOUGH */
+	if (t->cdr) debug_gc_check (t->cdr, " as cdr in a type");
+	/* FALL_THOUGH */
       case PIKE_T_ARRAY:
       case PIKE_T_MULTISET:
       case T_NOT:
       case PIKE_T_TYPE:
       case PIKE_T_PROGRAM:
-	if (t->car) gc_cycle_check_type(t->car, 0);
+	if (t->car) debug_gc_check (t->car, " as car in a type");
 	break;
     }
-  } GC_CYCLE_LEAVE;
+  } GC_LEAVE;
 }
 
-void gc_cycle_check_all_types(void)
+void gc_check_all_types (void)
 {
-#if 0
   size_t e;
-  if(!pike_type_hash) return;
+  if (!pike_type_hash) return;
   for(e=0;e<pike_type_hash_size;e++)
   {
     struct pike_type *t;
-    for(t=pike_type_hash[e]; t; t=t->next) {
-      real_gc_cycle_check_type(t, 0);
-      gc_cycle_run_queue();
-    }
+    for(t = pike_type_hash[e]; t; t=t->next) gc_check_type (t);
   }
-#endif
 }
 
-#endif /* PIKE_DEBUG */
-#endif /* 0 */
+#endif /* PIKE_DEBUG || DO_PIKE_CLEANUP */
diff --git a/src/pike_types.h b/src/pike_types.h
index 4e058122c0e4997279301ab772d63cfb7527b2ac..0051a356901ce47074e5cf48f62f704d87c917d5 100644
--- a/src/pike_types.h
+++ b/src/pike_types.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: pike_types.h,v 1.110 2007/11/11 13:49:01 nilsson Exp $
+|| $Id: pike_types.h,v 1.111 2008/03/29 16:20:17 mast Exp $
 */
 
 #ifndef PIKE_TYPES_H
@@ -94,15 +94,20 @@ extern struct pike_type *type_stack[PIKE_TYPE_STACK_SIZE];
 extern struct pike_type **pike_type_mark_stack[PIKE_TYPE_STACK_SIZE/4];
 
 #ifdef DEBUG_MALLOC
-#define free_type(T)	debug_free_type((struct pike_type *)debug_malloc_pass_named(T, "free_type"))
 #define check_type_string(T) debug_check_type_string((struct pike_type *)debug_malloc_pass_named(T, "check_type_string"))
-#else /* !DEBUG_MALLOC */
-#define free_type debug_free_type
-#ifdef PIKE_DEBUG
+#elif defined (PIKE_DEBUG)
 #define check_type_string debug_check_type_string
 #endif /* PIKE_DEBUG */
-#endif /* DEBUG_MALLOC */
 
+#define free_type(T) do {						\
+    struct pike_type *t_ = (T);						\
+    debug_malloc_touch_named (t_, "free_type");				\
+    DO_IF_DEBUG (							\
+      DO_IF_PIKE_CLEANUP (						\
+	if (gc_external_refs_zapped)					\
+	  gc_check_zapped (t_, PIKE_T_TYPE, __FILE__, __LINE__)));	\
+    debug_free_type (t_);						\
+  } while (0)
 
 extern int max_correct_args;
 PMOD_EXPORT extern struct pike_type *string0_type_string;
@@ -217,7 +222,6 @@ void simple_describe_type(struct pike_type *s);
 void my_describe_type(struct pike_type *type);
 struct pike_string *describe_type(struct pike_type *type);
 void debug_gc_check_all_types (void);
-void report_all_type_leaks (void);
 void free_all_leaked_types (void);
 TYPE_T compile_type_to_runtime_type(struct pike_type *s);
 struct pike_type *or_pike_types(struct pike_type *a,
@@ -266,6 +270,8 @@ struct pike_type *object_type_to_program_type(struct pike_type *obj_t);
 PMOD_EXPORT char *get_name_of_type(TYPE_T t);
 void cleanup_pike_types(void);
 void cleanup_pike_type_table(void);
+void gc_mark_type_as_referenced(struct pike_type *t);
+void gc_check_all_types (void);
 int type_may_overload(struct pike_type *type, int lfun);
 void yyexplain_nonmatching_types(struct pike_type *type_a,
 				 struct pike_type *type_b,
@@ -273,7 +279,6 @@ void yyexplain_nonmatching_types(struct pike_type *type_a,
 struct pike_type *debug_make_pike_type(const char *t);
 struct pike_string *type_to_string(struct pike_type *t);
 int pike_type_allow_premature_toss(struct pike_type *type);
-void real_gc_cycle_check_type(struct pike_type *t, int weak);
 void register_attribute_handler(struct pike_string *attr,
 				struct svalue *handler);
 /* Prototypes end here */
@@ -375,13 +380,6 @@ void register_attribute_handler(struct pike_string *attr,
 #define push_finished_type_backwards debug_push_finished_type_backwards
 #endif
 
-#if 0
-#define gc_cycle_check_type(T, WEAK) \
-  gc_cycle_enqueue((gc_cycle_check_cb *)real_gc_cycle_check_type, (T), (WEAK))
-#else
-#define gc_cycle_check_type(T, WEAK)
-#endif /* 0 */
-
 #ifndef PIKE_DEBUG
 #define check_type_string(X)
 #endif
diff --git a/src/program.c b/src/program.c
index fdf862b108ab6e8eeeefbb6b80abfee0e3f69ba0..2d60e078a03f03ce98374dcad8df8be5d72003f1 100644
--- a/src/program.c
+++ b/src/program.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: program.c,v 1.655 2008/03/26 15:07:11 grubba Exp $
+|| $Id: program.c,v 1.656 2008/03/29 16:20:18 mast Exp $
 */
 
 #include "global.h"
@@ -8008,10 +8008,10 @@ void gc_mark_program_as_referenced(struct program *p)
       if(p->parent)
 	gc_mark_program_as_referenced(p->parent);
 
-      for(e=0;e<p->num_constants;e++)
+      for(e = p->num_constants - 1; e >= 0; e--)
 	gc_mark_svalues(& p->constants[e].sval, 1);
 
-      for(e=0;e<p->num_inherits;e++)
+      for(e = p->num_inherits - 1; e >= 0; e--)
       {
 	if(p->inherits[e].parent)
 	  gc_mark_object_as_referenced(p->inherits[e].parent);
@@ -8020,6 +8020,11 @@ void gc_mark_program_as_referenced(struct program *p)
 	  gc_mark_program_as_referenced(p->inherits[e].prog);
       }
 
+#if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP)
+      for (e = p->num_identifiers - 1; e >= 0; e--)
+	gc_mark_type_as_referenced (p->identifiers[e].type);
+#endif
+
     } GC_LEAVE;
 }
 
@@ -8030,10 +8035,10 @@ void real_gc_cycle_check_program(struct program *p, int weak)
 
     if (!(p->flags & PROGRAM_AVOID_CHECK))
     {
-      for(e=0;e<p->num_constants;e++)
+      for(e = p->num_constants - 1; e >= 0; e--)
 	gc_cycle_check_svalues(& p->constants[e].sval, 1);
       
-      for(e=0;e<p->num_inherits;e++)
+      for(e = p->num_inherits - 1; e >= 0; e--)
       {
 	if(p->inherits[e].parent)
 	  gc_cycle_check_object(p->inherits[e].parent, 0);
@@ -8042,11 +8047,6 @@ void real_gc_cycle_check_program(struct program *p, int weak)
 	  gc_cycle_check_program(p->inherits[e].prog, 0);
       }
 
-#ifdef DEBUG_MALLOC
-      for (e = 0; e < p->num_identifiers; e++)
-	gc_cycle_check_type(p->identifiers[e].type, 0);
-#endif
-      
       /* Strong ref follows. It must be last. */
       if(p->parent)
 	gc_cycle_check_program(p->parent, 0);
@@ -8072,11 +8072,11 @@ static void gc_check_program(struct program *p)
     if(p->parent)
       debug_gc_check (p->parent, " as parent program of a program");
   
-    for(e=0;e<p->num_constants;e++) {
+    for(e = p->num_constants - 1; e >= 0; e--) {
       debug_gc_check_svalues (&p->constants[e].sval, 1, " as program constant");
     }
   
-    for(e=0;e<p->num_inherits;e++)
+    for(e = p->num_inherits - 1; e >= 0; e--)
     {
       if(p->inherits[e].parent)
       {
@@ -8096,19 +8096,18 @@ static void gc_check_program(struct program *p)
 #if defined (PIKE_DEBUG) || defined (DO_PIKE_CLEANUP)
     if (gc_keep_markers || Pike_in_gc == GC_PASS_LOCATE)
     {
-      int e;
-      for(e=0;e<(int)p->num_strings;e++)
+      for(e = p->num_strings - 1; e >= 0; e--)
 	debug_gc_check (p->strings[e], " in the string storage of a program");
-
-      for(e=0;e<(int)p->num_identifiers;e++)
-      {
+      for(e = p->num_identifiers - 1; e >= 0; e--)
 	debug_gc_check (p->identifiers[e].name,
 			" as identifier name in a program");
-	debug_gc_check (p->identifiers[e].type,
-			" as identifier type in a program");
-      }
     }
+
+    for(e = p->num_identifiers - 1; e >= 0; e--)
+      debug_gc_check (p->identifiers[e].type,
+		      " as identifier type in a program");
 #endif
+
   } GC_LEAVE;
 }
 
diff --git a/src/svalue.c b/src/svalue.c
index b02b87df005bbb98d4334c1535cf714fa608ed0e..1f5d7a78b4276522c88753259a5c5513c17b1335 100644
--- a/src/svalue.c
+++ b/src/svalue.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: svalue.c,v 1.237 2008/03/29 02:43:42 mast Exp $
+|| $Id: svalue.c,v 1.238 2008/03/29 16:20:19 mast Exp $
 */
 
 #include "global.h"
@@ -2079,10 +2079,10 @@ PMOD_EXPORT void real_gc_mark_external_svalues(const struct svalue *s, ptrdiff_t
 
 #define DO_CHECK_FUNC_SVALUE(U, T, ZAP, GC_DO)				\
       if (s->subtype == FUNCTION_BUILTIN) {				\
-	DO_IF_DEBUG(							\
-	  if (d_flag && !gc_check(s->u.efun)) {				\
-	    gc_check(s->u.efun->name);					\
-	    gc_check(s->u.efun->type);					\
+	DO_IF_DEBUG_OR_CLEANUP (					\
+	  if (!gc_check (s->u.efun)) {					\
+	    DO_IF_DEBUG (if (d_flag) gc_check (s->u.efun->name));	\
+	    gc_check (s->u.efun->type);					\
 	  }								\
 	)								\
 	break;								\
@@ -2236,12 +2236,10 @@ void gc_check_weak_short_svalue(const union anything *u, TYPE_T type)
 
 #define DO_MARK_FUNC_SVALUE(U, T, ZAP, GC_DO)				\
       if (s->subtype == FUNCTION_BUILTIN) {				\
-	DO_IF_DEBUG(							\
-	  if (d_flag) {							\
-	    gc_mark(s->u.efun->name);					\
-	    gc_mark(s->u.efun->type);					\
-	  }								\
-	)								\
+	DO_IF_DEBUG (if (d_flag) gc_mark (s->u.efun->name));		\
+	DO_IF_DEBUG_OR_CLEANUP (					\
+	  gc_mark_enqueue ((queue_call) gc_mark_type_as_referenced,	\
+			   s->u.efun->type));				\
 	break;								\
       }									\
       /* Fall through to T_OBJECT. */