Index: intern.h
===================================================================
--- intern.h	(revision 12450)
+++ intern.h	(working copy)
@@ -250,6 +250,12 @@
 VALUE rb_gc_enable _((void));
 VALUE rb_gc_disable _((void));
 VALUE rb_gc_start _((void));
+unsigned long rb_os_live_objects _((void));
+#ifdef HAVE_LONG_LONG
+unsigned long long rb_os_allocated_objects _((void));
+#else
+unsigned long rb_os_allocated_objects _((void));
+#endif
 /* hash.c */
 void st_foreach_safe _((struct st_table *, int (*)(ANYARGS), unsigned long));
 void rb_hash_foreach _((VALUE, int (*)(ANYARGS), VALUE));
Index: gc.c
===================================================================
--- gc.c	(revision 12450)
+++ gc.c	(working copy)
@@ -74,6 +74,20 @@
 static VALUE nomem_error;
 static void garbage_collect();
 
+static unsigned long live_objects = 0;
+unsigned long rb_os_live_objects()
+{ return live_objects; }
+
+#if defined(HAVE_LONG_LONG)
+static unsigned long long allocated_objects = 0;
+unsigned long long rb_os_allocated_objects()
+{ return allocated_objects; }
+#else
+static unsigned long allocated_objects = 0;
+unsigned long rb_os_allocated_objects()
+{ return allocated_objects; }
+#endif
+
 void
 rb_memerror()
 {
@@ -387,6 +401,8 @@
     RANY(obj)->file = ruby_sourcefile;
     RANY(obj)->line = ruby_sourceline;
 #endif
+    live_objects++;
+    allocated_objects++;
     return obj;
 }
 
@@ -1044,6 +1060,7 @@
     int i;
     unsigned long live = 0;
     unsigned long free_min = 0;
+    live_objects = 0;
 
     for (i = 0; i < heaps_used; i++) {
         free_min += heaps[i].limit;
@@ -1102,7 +1119,7 @@
 	    }
 	    else {
 		RBASIC(p)->flags &= ~FL_MARK;
-		live++;
+		live_objects++;
 	    }
 	    p++;
 	}
@@ -1120,7 +1137,7 @@
 	}
     }
     if (malloc_increase > malloc_limit) {
-	malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
+	malloc_limit += (malloc_increase - malloc_limit) * (double)live_objects / (live_objects + freed);
 	if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
     }
     malloc_increase = 0;
@@ -2047,6 +2064,35 @@
     return (VALUE)((long)obj|FIXNUM_FLAG);
 }
 
+/* call-seq:
+ *  ObjectSpace.live_objects => number
+ *
+ * Returns the count of objects currently allocated in the system. This goes
+ * down after the garbage collector runs.
+ */
+static
+VALUE os_live_objects(VALUE self)
+{ return ULONG2NUM(live_objects); }
+
+/* call-seq:
+ *  ObjectSpace.allocated_objects => number
+ *
+ * Returns the count of objects allocated since the Ruby interpreter has
+ * started.  This number can only increase. To know how many objects are
+ * currently allocated, use ObjectSpace::live_objects
+ */
+static
+VALUE os_allocated_objects(VALUE self)
+{ 
+#if defined(HAVE_LONG_LONG)
+    return ULL2NUM(allocated_objects); 
+#else
+    return ULONG2NUM(allocated_objects); 
+#endif
+}
+
+
+
 /*
  *  The <code>GC</code> module provides an interface to Ruby's mark and
  *  sweep garbage collection mechanism. Some of the underlying methods
@@ -2071,6 +2117,8 @@
     rb_define_module_function(rb_mObSpace, "remove_finalizer", rm_final, 1);
     rb_define_module_function(rb_mObSpace, "finalizers", finals, 0);
     rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1);
+    rb_define_module_function(rb_mObSpace, "live_objects", os_live_objects, 0);
+    rb_define_module_function(rb_mObSpace, "allocated_objects", os_allocated_objects, 0);
 
     rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1);
     rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1);

