diff --git a/Makefile b/Makefile
index c7aaaf3930eeeb8e533d9467bfef1ab350c532c0..3e294fc24a7e0e175a866471069bb7ac4437fb1b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile,v 1.167 2008/08/17 20:21:13 mast Exp $
+# $Id: Makefile,v 1.168 2009/11/28 13:36:19 mast Exp $
 #
 # Meta Makefile
 #
@@ -15,11 +15,11 @@
 
 # Set to a flag for parallelizing make, e.g. -j2. It's given to make
 # at the level where it's most effective.
-#MAKE_PARALLEL=-j`test -f /proc/cpuinfo && grep ^processor /proc/cpuinfo | wc -l || echo 1`
+MAKE_PARALLEL=-j`test -f /proc/cpuinfo && grep ^processor /proc/cpuinfo | wc -l || echo 1`
 
 # Tip: Remove "-r" from the line below if you don't want to rebuild
 # from scratch every time you upgrade the kernel.
-OS=`uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"`
+OS=`uname -s -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"`
 
 VPATH=.
 BUILDDIR=build/$(OS)
diff --git a/src/array.c b/src/array.c
index c2442c2e2435922f5880c61536293b2a8e0369ab..8acb9a3e70fcf5effdbfcf7159fe843496b8b909 100644
--- a/src/array.c
+++ b/src/array.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: array.c,v 1.225 2009/11/28 13:14:00 mast Exp $
+|| $Id: array.c,v 1.226 2009/11/28 13:36:20 mast Exp $
 */
 
 #include "global.h"
@@ -2689,7 +2689,7 @@ static void gc_check_array(struct array *a)
 
 void gc_mark_array_as_referenced(struct array *a)
 {
-  if(gc_mark(a))
+  if(gc_mark(a, T_ARRAY))
     GC_ENTER (a, T_ARRAY) {
       if (a == gc_mark_array_pos)
 	gc_mark_array_pos = a->next;
diff --git a/src/gc.c b/src/gc.c
index 72068d5b0f5b57e35b1586e57f484a049686a1be..f8feb134ecc53cf14405efa8bedabc05274092bf 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.337 2009/11/28 11:49:47 mast Exp $
+|| $Id: gc.c,v 1.338 2009/11/28 13:36:20 mast Exp $
 */
 
 #include "global.h"
@@ -993,7 +993,7 @@ static void describe_marker(struct marker *m)
 
 #endif /* PIKE_DEBUG */
 
-static void debug_gc_fatal_va (void *a, int flags,
+static void debug_gc_fatal_va (void *a, int type, int flags,
 			       const char *fmt, va_list args)
 {
 #ifdef PIKE_DEBUG
@@ -1005,10 +1005,13 @@ static void debug_gc_fatal_va (void *a, int flags,
 
 #ifdef PIKE_DEBUG
   if (a) {
+    void *inblock;
     /* Temporarily jumping out of gc to avoid being caught in debug
      * checks in describe(). */
     Pike_in_gc = 0;
-    describe(a);
+    if (type == PIKE_T_UNKNOWN)
+      type = attempt_to_identify (a, &inblock);
+    describe_something (a, type, 0, 0, 0, inblock);
     if (flags & 1) locate_references(a);
     Pike_in_gc = orig_gc_pass;
   }
@@ -1027,7 +1030,15 @@ void debug_gc_fatal (void *a, int flags, const char *fmt, ...)
 {
   va_list args;
   va_start (args, fmt);
-  debug_gc_fatal_va (a, flags, fmt, args);
+  debug_gc_fatal_va (a, PIKE_T_UNKNOWN, flags, fmt, args);
+  va_end (args);
+}
+
+void debug_gc_fatal_2 (void *a, int type, int flags, const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  debug_gc_fatal_va (a, type, flags, fmt, args);
   va_end (args);
 }
 
@@ -1037,7 +1048,7 @@ static void dloc_gc_fatal (const char *file, int line,
   va_list args;
   fprintf (stderr, "%s:%d: GC fatal:\n", file, line);
   va_start (args, fmt);
-  debug_gc_fatal_va (a, flags, fmt, args);
+  debug_gc_fatal_va (a, PIKE_T_UNKNOWN, flags, fmt, args);
   va_end (args);
 }
 
@@ -2459,14 +2470,14 @@ void gc_delayed_free(void *a, int type)
   m->flags |= GC_GOT_DEAD_REF;
 }
 
-int gc_mark(void *a)
+int gc_mark_func(void *a DO_IF_DEBUG (COMMA int type))
 {
   struct marker *m;
 
 #ifdef PIKE_DEBUG
   if (Pike_in_gc == GC_PASS_ZAP_WEAK && !find_marker (a))
-    gc_fatal (a, 0, "gc_mark() called for for thing without marker "
-	      "in zap weak pass.\n");
+    gc_fatal_2 (a, type, 0, "gc_mark() called for for thing without marker "
+		"in zap weak pass.\n");
 #endif
 
   m = get_marker (a);
@@ -2483,9 +2494,9 @@ int gc_mark(void *a)
   if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_ZAP_WEAK)
     Pike_fatal("GC mark attempted in invalid pass.\n");
   if (!*(INT32 *) a)
-    gc_fatal(a, 0, "Marked a thing without refs.\n");
+    gc_fatal_2 (a, type, 1, "Marked a thing without refs.\n");
   if (m->weak_refs < 0)
-    gc_fatal(a, 0, "Marked a thing scheduled for weak free.\n");
+    gc_fatal_2 (a, type, 1, "Marked a thing scheduled for weak free.\n");
 #endif
 
   if (Pike_in_gc == GC_PASS_ZAP_WEAK) {
@@ -2495,8 +2506,8 @@ int gc_mark(void *a)
      * internal cyclic nonweak refs. */
 #ifdef PIKE_DEBUG
     if (!(m->flags & GC_MARKED))
-      gc_fatal(a, 0, "gc_mark() called for thing in zap weak pass "
-	       "that wasn't marked before.\n");
+      gc_fatal_2 (a, type, 0, "gc_mark() called for thing in zap weak pass "
+		  "that wasn't marked before.\n");
 #endif
     if (m->flags & GC_FREE_VISITED) {
       debug_malloc_touch (a);
@@ -2513,8 +2524,8 @@ int gc_mark(void *a)
     debug_malloc_touch (a);
 #ifdef PIKE_DEBUG
     if (m->weak_refs != 0)
-      gc_fatal (a, 0, "weak_refs changed in marker "
-		"already visited by gc_mark().\n");
+      gc_fatal_2 (a, type, 0, "weak_refs changed in marker "
+		  "already visited by gc_mark().\n");
 #endif
     return 0;
   }
diff --git a/src/gc.h b/src/gc.h
index fcfd234743ef291867d99714720b2e2161b129a6..46d7e52a9d16f0ea8f125b896a6bfa2d8dd23395 100644
--- a/src/gc.h
+++ b/src/gc.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: gc.h,v 1.137 2009/11/11 20:05:07 mast Exp $
+|| $Id: gc.h,v 1.138 2009/11/28 13:36:20 mast Exp $
 */
 
 #ifndef GC_H
@@ -296,6 +296,7 @@ void describe_location(void *real_memblock,
 		       int depth,
 		       int flags);
 void debug_gc_fatal(void *a, int flags, const char *fmt, ...);
+void debug_gc_fatal_2 (void *a, int type, int flags, const char *fmt, ...);
 void low_describe_something(void *a,
 			    int t,
 			    int indent,
@@ -319,7 +320,7 @@ void debug_really_free_gc_frame(struct gc_frame *l);
 int gc_do_weak_free(void *a);
 void gc_delayed_free(void *a, int type);
 void debug_gc_mark_enqueue(queue_call call, void *data);
-int gc_mark(void *a);
+int gc_mark_func(void *a DO_IF_DEBUG (COMMA int type));
 void gc_move_marker (void *old_thing, void *new_thing);
 PMOD_EXPORT void gc_cycle_enqueue(gc_cycle_check_cb *checkfn, void *data, int weak);
 void gc_cycle_run_queue(void);
@@ -339,6 +340,12 @@ void cleanup_gc(void);
 #define DMALLOC_TOUCH_MARKER(X, EXPR) (EXPR)
 #endif
 
+#ifdef PIKE_DEBUG
+#define gc_mark(DATA, TYPE) gc_mark_func (DATA, TYPE)
+#else
+#define gc_mark(DATA, TYPE) gc_mark_func (DATA)
+#endif
+
 #define gc_check(VP) \
   DMALLOC_TOUCH_MARKER(VP, real_gc_check(debug_malloc_pass(VP)))
 #define gc_check_weak(VP) \
@@ -438,6 +445,8 @@ static INLINE int debug_gc_check_weak (void *a, const char *place)
 
 #define gc_fatal \
   fprintf(stderr, "%s:%d: GC fatal:\n", __FILE__, __LINE__), debug_gc_fatal
+#define gc_fatal_2 \
+  fprintf(stderr, "%s:%d: GC fatal:\n", __FILE__, __LINE__), debug_gc_fatal_2
 
 #ifdef PIKE_DEBUG
 
diff --git a/src/mapping.c b/src/mapping.c
index 1fbee8a4d8095da2ad6dd96247a62bdeebfd4374..760e3d44ba3d826f45a71a0d31431f3079b8b520 100644
--- a/src/mapping.c
+++ b/src/mapping.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: mapping.c,v 1.213 2009/09/22 15:45:09 grubba Exp $
+|| $Id: mapping.c,v 1.214 2009/11/28 13:36:20 mast Exp $
 */
 
 #include "global.h"
@@ -2583,7 +2583,7 @@ void gc_mark_mapping_as_referenced(struct mapping *m)
   debug_malloc_touch(m);
   debug_malloc_touch(m->data);
 
-  if(gc_mark(m))
+  if(gc_mark(m, T_MAPPING))
     GC_ENTER (m, T_MAPPING) {
       struct mapping_data *md = m->data;
 
@@ -2596,7 +2596,8 @@ void gc_mark_mapping_as_referenced(struct mapping *m)
 	DOUBLELINK(first_mapping, m); /* Linked in first. */
       }
 
-      if(gc_mark(md) && ((md->ind_types | md->val_types) & BIT_COMPLEX)) {
+      if(gc_mark(md, T_MAPPING_DATA) &&
+	 ((md->ind_types | md->val_types) & BIT_COMPLEX)) {
 	TYPE_FIELD ind_types = 0, val_types = 0;
 	if (MAPPING_DATA_IN_USE(md)) {
 	  /* Must leave the mapping data untouched if it's busy. */
diff --git a/src/multiset.c b/src/multiset.c
index 46f27763bc4c60098b266eed6b560da97e506094..d1153d5a2035a60105ddd2433b3de525a87abb7d 100644
--- a/src/multiset.c
+++ b/src/multiset.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: multiset.c,v 1.118 2009/08/10 14:27:47 grubba Exp $
+|| $Id: multiset.c,v 1.119 2009/11/28 13:36:20 mast Exp $
 */
 
 #include "global.h"
@@ -4163,7 +4163,7 @@ static void gc_unlink_msnode_shared (struct multiset_data *msd,
 
 void gc_mark_multiset_as_referenced (struct multiset *l)
 {
-  if (gc_mark (l))
+  if (gc_mark (l, T_MULTISET))
     GC_ENTER (l, T_MULTISET) {
       struct multiset_data *msd = l->msd;
 
@@ -4176,7 +4176,7 @@ void gc_mark_multiset_as_referenced (struct multiset *l)
 	DOUBLELINK (first_multiset, l); /* Linked in first. */
       }
 
-      if (gc_mark (msd) && msd->root &&
+      if (gc_mark (msd, T_MULTISET_DATA) && msd->root &&
 	  ((msd->ind_types | msd->val_types) & BIT_COMPLEX)) {
 	struct marker *m = get_marker (msd);
 	TYPE_FIELD ind_types = 0, val_types = 0;
diff --git a/src/object.c b/src/object.c
index efa0edb52e295069e6474bde7c164dc41f150db3..891175b45fa164b70f5c8f3caa96aaf5266902c4 100644
--- a/src/object.c
+++ b/src/object.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: object.c,v 1.303 2009/08/25 16:59:22 grubba Exp $
+|| $Id: object.c,v 1.304 2009/11/28 13:36:20 mast Exp $
 */
 
 #include "global.h"
@@ -2027,7 +2027,7 @@ PMOD_EXPORT void gc_mark_object_as_referenced(struct object *o)
   debug_malloc_touch(o);
   debug_malloc_touch(o->storage);
 
-  if(gc_mark(o)) {
+  if(gc_mark(o, T_OBJECT)) {
     if(o->next == o) return; /* Fake object used by compiler */
 
     GC_ENTER (o, T_OBJECT) {
diff --git a/src/pike_types.c b/src/pike_types.c
index 86ab672880f193894552ed09a2fb0890a53b950b..5ed3931df638de190834694935eecea1afd4b8a5 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.360 2009/04/11 12:42:22 grubba Exp $
+|| $Id: pike_types.c,v 1.361 2009/11/28 13:36:21 mast Exp $
 */
 
 #include "global.h"
@@ -8022,7 +8022,7 @@ PMOD_EXPORT void visit_type (struct pike_type *t, int action)
 
 void gc_mark_type_as_referenced(struct pike_type *t)
 {
-  if (gc_mark(t)) {
+  if (gc_mark(t, PIKE_T_TYPE)) {
     GC_ENTER(t, PIKE_T_TYPE) {
       switch(t->type) {
       case PIKE_T_SCOPE:
diff --git a/src/program.c b/src/program.c
index 1e15cab9c1ed42ae1ac6ca22a5dbdb75a7cd55fa..ca66019f91a707b604a60206a3d70c666cfa00a6 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.772 2009/11/20 10:58:09 grubba Exp $
+|| $Id: program.c,v 1.773 2009/11/28 13:36:21 mast Exp $
 */
 
 #include "global.h"
@@ -10185,7 +10185,7 @@ void gc_mark_program_as_referenced(struct program *p)
      */
     debug_malloc_touch(p);
 
-    if (gc_mark(p)) {
+    if (gc_mark(p, T_PROGRAM)) {
       if (p == gc_mark_program_pos)
 	gc_mark_program_pos = p->next;
       if (p == gc_internal_program)
@@ -10199,7 +10199,7 @@ void gc_mark_program_as_referenced(struct program *p)
     return;
   }
   
-  if(gc_mark(p))
+  if(gc_mark(p, T_PROGRAM))
     GC_ENTER (p, T_PROGRAM) {
       int e;
 
diff --git a/src/svalue.c b/src/svalue.c
index f925962028d03338d3ae5a69f3a116901b6d7119..2bd0114c73e74500c1573e7ccf4414995d55880e 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.254 2009/08/20 16:24:36 mast Exp $
+|| $Id: svalue.c,v 1.255 2009/11/28 13:36:21 mast Exp $
 */
 
 #include "global.h"
@@ -2291,9 +2291,16 @@ void gc_check_weak_short_svalue(const union anything *u, TYPE_T type)
 
 #define GC_DONT_MARK(U, TN) do {} while (0)
 
+#define MARK_PRE {							\
+    DO_IF_DEBUG (							\
+      if (!s->u.refs)							\
+	(gc_fatal_2 (s->u.ptr, s->type, 0, "Marking thing without refs.\n")); \
+    );									\
+  }
+
 #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));		\
+	DO_IF_DEBUG (if (d_flag) gc_mark (s->u.efun->name, T_STRING));	\
 	DO_IF_DEBUG_OR_CLEANUP (GC_DO_MARK ((*s->u.efun), type));	\
 	break;								\
       }									\
@@ -2310,7 +2317,7 @@ void gc_check_weak_short_svalue(const union anything *u, TYPE_T type)
 	GC_DO_MARK(U, TN)
 
 #define DO_MARK_STRING(U)						\
-      DO_IF_DEBUG(if (U.refs && d_flag) gc_mark(U.string))
+      DO_IF_DEBUG(if (U.refs && d_flag) gc_mark(U.string, T_STRING))
 
 #define DONT_MARK_STRING(U)
 
@@ -2323,7 +2330,7 @@ PMOD_EXPORT TYPE_FIELD real_gc_mark_svalues(struct svalue *s, size_t num)
   {
     dmalloc_touch_svalue(s);
     GC_RECURSE_SWITCH((s->u), (s->type), ZAP_SVALUE, DONT_FREE_WEAK,
-		      GC_DO_MARK, {},
+		      GC_DO_MARK, MARK_PRE,
 		      DO_MARK_FUNC_SVALUE, GC_DO_MARK,
 		      DO_MARK_STRING, GC_DO_MARK);
     t |= 1 << s->type;
@@ -2340,7 +2347,7 @@ TYPE_FIELD gc_mark_weak_svalues(struct svalue *s, size_t num)
   {
     dmalloc_touch_svalue(s);
     GC_RECURSE_SWITCH((s->u), (s->type), ZAP_SVALUE, FREE_WEAK,
-		      GC_DONT_MARK, {},
+		      GC_DONT_MARK, MARK_PRE,
 		      DO_MARK_FUNC_SVALUE, DO_MARK_OBJ_WEAK,
 		      DO_MARK_STRING, GC_DO_MARK);
     t |= 1 << s->type;
@@ -2375,7 +2382,7 @@ int gc_mark_without_recurse(struct svalue *s)
   int freed = 0;
   dmalloc_touch_svalue(s);
   GC_RECURSE_SWITCH((s->u), (s->type), ZAP_SVALUE, DONT_FREE_WEAK,
-		    GC_DONT_MARK, {},
+		    GC_DONT_MARK, MARK_PRE,
 		    DONT_MARK_FUNC_SVALUE, GC_DONT_MARK,
 		    DONT_MARK_STRING, GC_DONT_MARK);
   return freed;
@@ -2386,7 +2393,7 @@ int gc_mark_weak_without_recurse(struct svalue *s)
   int freed = 0;
   dmalloc_touch_svalue(s);
   GC_RECURSE_SWITCH((s->u), (s->type), ZAP_SVALUE, FREE_WEAK,
-		    GC_DONT_MARK, {},
+		    GC_DONT_MARK, MARK_PRE,
 		    DONT_MARK_FUNC_SVALUE, GC_DONT_MARK,
 		    DONT_MARK_STRING, GC_DONT_MARK);
   return freed;