diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 569454817dc28c34e90950b31ed44e1c155d00b2..5287bcd9f7f082c03bf1c44fe6029a796457c695 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.233 2000/01/29 13:42:14 mirar Exp $");
+RCSID("$Id: builtin_functions.c,v 1.234 2000/02/02 00:38:27 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -6017,5 +6017,9 @@ void init_builtin_efuns(void)
   ADD_EFUN("_describe",f__describe,
 	   tFunc(tSetvar(1,tMix),tVar(1)),OPT_SIDE_EFFECT);
 #endif
+
+  ADD_EFUN("_gc_status",f__gc_status,
+	   tFunc(tNone,tMap(tString,tOr(tInt,tFloat))),
+	   OPT_EXTERNAL_DEPEND);
 }
 
diff --git a/src/gc.c b/src/gc.c
index 04ccb8ac97021d6ecba252cb140440b0ca54cb60..a04d1984c37d6952e8dec17835a9463e7d6c2ebc 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -21,6 +21,7 @@ struct callback *gc_evaluator_callback=0;
 #include "pike_types.h"
 #include "time_stuff.h"
 #include "constants.h"
+#include "interpret.h"
 
 #include "gc.h"
 #include "main.h"
@@ -28,7 +29,7 @@ struct callback *gc_evaluator_callback=0;
 
 #include "block_alloc.h"
 
-RCSID("$Id: gc.c,v 1.45 2000/02/01 06:24:40 hubbe Exp $");
+RCSID("$Id: gc.c,v 1.46 2000/02/02 00:38:27 hubbe Exp $");
 
 /* Run garbage collect approximate every time we have
  * 20 percent of all arrays, objects and programs is
@@ -59,19 +60,6 @@ struct callback *debug_add_gc_callback(callback_func call,
   return add_to_callback(&gc_callbacks, call, arg, free_func);
 }
 
-#define GC_REFERENCED 1
-#define GC_XREFERENCED 2
-
-struct marker
-{
-  INT32 refs;
-#ifdef PIKE_DEBUG
-  INT32 xrefs;
-#endif
-  INT32 flags;
-  struct marker *next;
-  void *data;
-};
 
 #undef INIT_BLOCK
 #ifdef PIKE_DEBUG
@@ -442,6 +430,7 @@ static void init_gc(void)
   MEMSET((char *)hash,0,sizeof(struct marker **)*hashsize);
   markers_left_in_chunk=0;
 #else
+/*  init_marker_hash(num_objects*8); */
   init_marker_hash();
 #endif
 }
@@ -505,11 +494,13 @@ void locate_references(void *a)
 }
 #endif
 
-int gc_is_referenced(void *a)
+#ifdef PIKE_DEBUG
+
+int debug_gc_is_referenced(void *a)
 {
   struct marker *m;
   m=get_marker(a);
-#ifdef PIKE_DEBUG
+
   if(m->refs + m->xrefs > *(INT32 *)a ||
      (!(m->refs < *(INT32 *)a) && m->xrefs) )
   {
@@ -527,9 +518,10 @@ int gc_is_referenced(void *a)
 	  refs,
 	  xrefs);
   }
-#endif
+
   return m->refs < *(INT32 *)a;
 }
+#endif
 
 #ifdef PIKE_DEBUG
 int gc_external_mark(void *a)
@@ -570,11 +562,12 @@ int gc_mark(void *a)
   }
 }
 
-int gc_do_free(void *a)
+#ifdef PIKE_DEBUG
+int debug_gc_do_free(void *a)
 {
   struct marker *m;
   m=get_marker(a);
-#ifdef PIKE_DEBUG
+
   if( !(m->flags & GC_REFERENCED)  && m->flags & GC_XREFERENCED )
   {
     INT32 refs=m->refs;
@@ -591,9 +584,10 @@ int gc_do_free(void *a)
 	  refs,
 	  xrefs);
   }
-#endif
+
   return !(m->flags & GC_REFERENCED);
 }
+#endif
 
 void do_gc(void)
 {
@@ -699,3 +693,31 @@ void do_gc(void)
 }
 
 
+void f__gc_status(INT32 args)
+{
+  pop_n_elems(args);
+
+  push_constant_text("num_objects");
+  push_int(num_objects);
+
+  push_constant_text("num_allocs");
+  push_int(num_allocs);
+
+  push_constant_text("alloc_threshold");
+  push_int(alloc_threshold);
+
+  push_constant_text("objects_alloced");
+  push_int(objects_alloced);
+
+  push_constant_text("objects_freed");
+  push_int(objects_freed);
+
+  push_constant_text("last_gc");
+  push_int(last_gc);
+
+  push_constant_text("projected_garbage");
+  push_float(objects_freed * (double) num_allocs / (double) alloc_threshold);
+
+  f_aggregate_mapping(14);
+}
+
diff --git a/src/gc.h b/src/gc.h
index a879ae136f9d04b9c05d6a5be2b5b28ef06b88fb..988926ad759e4efa2f23f6598640f74b96a0dc12 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -1,5 +1,5 @@
 /*
- * $Id: gc.h,v 1.22 1999/05/02 08:11:42 hubbe Exp $
+ * $Id: gc.h,v 1.23 2000/02/02 00:38:27 hubbe Exp $
  */
 #ifndef GC_H
 #define GC_H
@@ -27,12 +27,24 @@ extern void *gc_svalue_location;
 #define GC_ALLOC() do{ num_objects++; num_allocs++;  if(num_allocs == alloc_threshold && !gc_evaluator_callback) ADD_GC_CALLBACK(); } while(0)
 #endif
 
+struct marker
+{
+  struct marker *next;
+  INT32 refs;
+#ifdef PIKE_DEBUG
+  INT32 xrefs;
+#endif
+  INT32 flags;
+  void *data;
+};
+
+#include "block_alloc_h.h"
+PTR_HASH_ALLOC(marker,MARKER_CHUNK_SIZE)
+
 /* Prototypes begin here */
 struct callback *debug_add_gc_callback(callback_func call,
 				 void *arg,
 				 callback_func free_func);
-struct marker;
-struct marker_chunk;
 void dump_gc_info(void);
 TYPE_T attempt_to_identify(void *something);
 void describe_location(void *memblock, TYPE_T type, void *location);
@@ -45,11 +57,12 @@ void describe(void *x);
 void debug_describe_svalue(struct svalue *s);
 INT32 gc_check(void *a);
 void locate_references(void *a);
-int gc_is_referenced(void *a);
+int debug_gc_is_referenced(void *a);
 int gc_external_mark(void *a);
 int gc_mark(void *a);
-int gc_do_free(void *a);
+int debug_gc_do_free(void *a);
 void do_gc(void);
+void f__gc_status(INT32 args);
 /* Prototypes end here */
 
 #ifdef PIKE_DEBUG
@@ -66,4 +79,16 @@ void do_gc(void);
 #define add_gc_callback(X,Y,Z) \
   dmalloc_touch(struct callback *,debug_add_gc_callback((X),(Y),(Z)))
 
+#define GC_REFERENCED 1
+#define GC_XREFERENCED 2
+
+
+#ifdef PIKE_DEBUG
+#define gc_is_referenced debug_gc_is_referenced
+#define gc_do_free debug_gc_do_free
+#else
+#define gc_is_referenced(X) (get_marker(X)->refs < *(INT32 *)(X))
+#define gc_do_free(X) ( ! (get_marker(X)->flags & GC_REFERENCED ) )
+#endif
+
 #endif