* gc.c (heaps): manage slots and limits together.

* gc.c (add_heap): should not clear heaps slot even if realloc()
  failed.


Index: gc.c
===================================================================
RCS file: /cvs/ruby/src/ruby/gc.c,v
retrieving revision 1.156
diff -u -2 -p -r1.156 gc.c
--- gc.c	22 Aug 2003 08:09:57 -0000	1.156
+++ gc.c	1 Oct 2003 11:46:34 -0000
@@ -265,10 +265,12 @@ static RVALUE *deferred_final_list = 0;
 
 #define HEAPS_INCREMENT 10
-static RVALUE **heaps;
+static struct heaps_slot {
+    RVALUE *slot;
+    int limit;
+} *heaps;
 static int heaps_length = 0;
 static int heaps_used   = 0;
 
 #define HEAP_MIN_SLOTS 10000
-static int *heaps_limits;
 static int heap_slots = HEAP_MIN_SLOTS;
 
@@ -284,18 +286,23 @@ add_heap()
     if (heaps_used == heaps_length) {
 	/* Realloc heaps */
+	struct heaps_slot *p;
+	int length;
+
 	heaps_length += HEAPS_INCREMENT;
-	RUBY_CRITICAL(heaps = (heaps_used>0)?
-			(RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE*)):
-			(RVALUE**)malloc(heaps_length*sizeof(RVALUE*)));
-	if (heaps == 0) rb_memerror();
-	RUBY_CRITICAL(heaps_limits = (heaps_used>0)?
-			(int*)realloc(heaps_limits, heaps_length*sizeof(int)):
-			(int*)malloc(heaps_length*sizeof(int)));
-	if (heaps_limits == 0) rb_memerror();
+	length = heaps_length*sizeof(struct heaps_slot);
+	RUBY_CRITICAL(
+	    if (heaps_used > 0) {
+		p = (struct heaps_slot *)realloc(heaps, length);
+		if (p) heaps = p;
+	    }
+	    else {
+		p = heaps = (struct heaps_slot *)malloc(length);
+	    });
+	if (p == 0) rb_memerror();
     }
 
     for (;;) {
-	RUBY_CRITICAL(p = heaps[heaps_used] = (RVALUE*)malloc(sizeof(RVALUE)*heap_slots));
-	heaps_limits[heaps_used] = heap_slots;
+	RUBY_CRITICAL(p = heaps[heaps_used].slot = (RVALUE*)malloc(sizeof(RVALUE)*heap_slots));
+	heaps[heaps_used].limit = heap_slots;
 	if (p == 0) {
 	    if (heap_slots == HEAP_MIN_SLOTS) {
@@ -500,5 +507,5 @@ gc_mark_all()
     init_mark_stack();
     for (i = 0; i < heaps_used; i++) {
-	p = heaps[i]; pend = p + heaps_limits[i];
+	p = heaps[i].slot; pend = p + heaps[i].limit;
 	while (p < pend) {
 	    if ((p->as.basic.flags & FL_MARK) &&
@@ -539,6 +546,6 @@ is_pointer_to_heap(ptr)
     /* check if p looks like a pointer */
     for (i=0; i < heaps_used; i++) {
-	heap_org = heaps[i];
-	if (heap_org <= p && p < heap_org + heaps_limits[i] &&
+	heap_org = heaps[i].slot;
+	if (heap_org <= p && p < heap_org + heaps[i].limit &&
 	    ((((char*)p)-((char*)heap_org))%sizeof(RVALUE)) == 0)
 	    return Qtrue;
@@ -914,5 +921,5 @@ gc_sweep()
            if yacc's semantic stack is not allocated on machine stack */
 	for (i = 0; i < heaps_used; i++) {
-	    p = heaps[i]; pend = p + heaps_limits[i];
+	    p = heaps[i].slot; pend = p + heaps[i].limit;
 	    while (p < pend) {
 		if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE)
@@ -934,5 +941,5 @@ gc_sweep()
 	RVALUE *final = final_list;
 
-	p = heaps[i]; pend = p + heaps_limits[i];
+	p = heaps[i].slot; pend = p + heaps[i].limit;
 	while (p < pend) {
 	    if (!(p->as.basic.flags & FL_MARK)) {
@@ -962,8 +969,8 @@ gc_sweep()
 	    p++;
 	}
-	if (n == heaps_limits[i] && freed + n > FREE_MIN) {
+	if (n == heaps[i].limit && freed + n > FREE_MIN) {
 	    RVALUE *pp;
 
-	    heaps_limits[i] = 0;
+	    heaps[i].limit = 0;
 	    for (pp = final_list; pp != final; pp = pp->as.free.next) {
 		p->as.free.flags |= FL_SINGLETON; /* freeing page mark */
@@ -1003,6 +1010,6 @@ gc_sweep()
     }
     for (i = j = 1; j < heaps_used; i++) {
-	if (heaps_limits[i] == 0) {
-	    free(heaps[i]);
+	if (heaps[i].limit == 0) {
+	    free(heaps[i].slot);
 	    heaps_used--;
 	}
@@ -1010,5 +1017,4 @@ gc_sweep()
 	    if (i != j) {
 		heaps[j] = heaps[i];
-		heaps_limits[j] = heaps_limits[i];
 	    }
 	    j++;
@@ -1366,5 +1372,5 @@ os_live_obj()
 	RVALUE *p, *pend;
 
-	p = heaps[i]; pend = p + heaps_limits[i];
+	p = heaps[i].slot; pend = p + heaps[i].limit;
 	for (;p < pend; p++) {
 	    if (p->as.basic.flags) {
@@ -1399,5 +1405,5 @@ os_obj_of(of)
 	RVALUE *p, *pend;
 
-	p = heaps[i]; pend = p + heaps_limits[i];
+	p = heaps[i].slot; pend = p + heaps[i].limit;
 	for (;p < pend; p++) {
 	    if (p->as.basic.flags) {
@@ -1586,5 +1592,5 @@ rb_gc_call_finalizer_at_exit()
 	}
 	for (i = 0; i < heaps_used; i++) {
-	    p = heaps[i]; pend = p + heaps_limits[i];
+	    p = heaps[i].slot; pend = p + heaps[i].limit;
 	    while (p < pend) {
 		if (FL_TEST(p, FL_FINALIZE)) {
@@ -1599,5 +1605,5 @@ rb_gc_call_finalizer_at_exit()
     /* run data object's finalizers */
     for (i = 0; i < heaps_used; i++) {
-	p = heaps[i]; pend = p + heaps_limits[i];
+	p = heaps[i].slot; pend = p + heaps[i].limit;
 	while (p < pend) {
 	    if (BUILTIN_TYPE(p) == T_DATA &&
