Index: gc.c
===================================================================
--- gc.c	(revision 39754)
+++ gc.c	(working copy)
@@ -261,6 +261,8 @@
 	void *data;
 	void (*mark_func)(VALUE v, void *data);
     } *mark_func_data;
+
+    char *profile_bitmap_dirname;
 } rb_objspace_t;
 
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
@@ -380,6 +382,7 @@
     memset(objspace, 0, sizeof(*objspace));
     malloc_limit = initial_malloc_limit;
     ruby_gc_stress = ruby_initial_gc_stress;
+    objspace->profile_bitmap_dirname = getenv("RUBY_HEAP_PROFILE_BITMAP");
 
     return objspace;
 }
@@ -2955,6 +2958,63 @@
     gc_prof_mark_timer_stop(objspace);
 
     objspace->mark_func_data = prev_mark_func_data;
+
+    if (objspace->profile_bitmap_dirname) {
+	char filename[1024];
+	FILE *fp;
+	unsigned int i;
+	int *data;
+	int data_size = 4 * HEAP_OBJ_LIMIT;
+	size_t total_byte = 0;
+
+	snprintf(filename, 1023, "%s/gcbitmap-%05d-%08d-%dx%d",
+		 objspace->profile_bitmap_dirname, getpid(), objspace->count,
+		 objspace->heap.used, HEAP_OBJ_LIMIT);
+
+	if ((fp = fopen(filename, "wb")) == NULL) {
+	  failed:
+	    perror("profile bitmap failed.");
+	    exit(1);
+	}
+
+	data = (int *)malloc(data_size);
+	for (i=0; i<objspace->heap.used; i++) {
+	    struct heaps_header *header = objspace->heap.sorted[i];
+	    /* assume int is 32bit */
+	    unsigned int a;
+
+	    for (a=0; a<header->limit; a++) {
+		int color = 0;
+		VALUE obj = (VALUE)&header->start[a];
+
+		if (RBASIC(obj)->flags) {
+		    switch (BUILTIN_TYPE(obj)) {
+		      case T_NONE:   color = 0xffff00; break; /* Yellow  */
+		      case T_STRING: color = 0xff0000; break; /* RED     */
+		      case T_ARRAY:  color = 0x00ff00; break; /* GREEN   */
+		      case T_HASH:   color = 0x0000ff; break; /* BLUE    */
+		      default:
+			color = 0x808080;
+			break;
+		    }
+		}
+		data[a] = color;
+	    }
+
+	    if (0) fprintf(stderr, "write %d data\n", data_size);
+	    total_byte += fwrite(data, data_size, 1, fp) * data_size;
+	}
+
+	free(data);
+	fclose(fp);
+
+	if (total_byte != (data_size * objspace->heap.used)) {
+	    fprintf(stderr, "size mismuch: %d but %d\n",
+		    data_size * objspace->heap.used,
+		    total_byte);
+	    goto failed;
+	}
+    }
 }
 
 /* GC */
