[前][次][番号順一覧][スレッド一覧]

ruby-changes:6371

From: nari <ko1@a...>
Date: Sat, 5 Jul 2008 16:16:25 +0900 (JST)
Subject: [ruby-changes:6371] Ruby:r17887 (trunk): * gc.c: revert. before lazy sweep.

nari	2008-07-05 16:15:41 +0900 (Sat, 05 Jul 2008)

  New Revision: 17887

  Modified files:
    trunk/ChangeLog
    trunk/gc.c

  Log:
    * gc.c: revert. before lazy sweep.
    


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17887

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 17886)
+++ ChangeLog	(revision 17887)
@@ -1,3 +1,7 @@
+Sat Jul  5 16:12:54 2008  Narihiro Nakamura  <authorNari@g...>
+
+	* gc.c: revert. before lazy sweep.
+
 Sat Jul  5 09:55:44 2008  Masaki Suketa  <masaki.suketa@n...>
 
 	* ext/win32ole/win32ole.c: add WIN32OLE#ole_respond_to?
@@ -56,7 +60,7 @@
 
 	* lib/net/ftp.rb (Net::FTP#sendport): use divmod.  [ruby-core:17557]
 
-Fri Jul  4 11:08:37 2008  nari  <authorNari@g...>
+Fri Jul  4 11:08:37 2008  Narihiro Nakamura  <authorNari@g...>
 
 	* gc.c (garbage_collect_force): sweep is completely ended.
 
Index: gc.c
===================================================================
--- gc.c	(revision 17886)
+++ gc.c	(revision 17887)
@@ -129,17 +129,10 @@
 #pragma pack(pop)
 #endif
 
-enum slot_color {
-    WHITE = 0x00,  /* garbage */
-    BLACK = 0x01,  /* used */
-    GRAY  = 0x02,  /* not sweep */
-};
-
 struct heaps_slot {
     void *membase;
     RVALUE *slot;
     int limit;
-    enum slot_color color;
 };
 
 #define HEAP_MIN_SLOTS 10000
@@ -169,11 +162,6 @@
 	RVALUE *freelist;
 	RVALUE *range[2];
 	RVALUE *freed;
-	size_t live;
-	size_t dead;
-	size_t do_heap_free;
-	size_t sweep_index;
-	size_t sweep_increment;
     } heap;
     struct {
 	int dont_gc;
@@ -191,7 +179,6 @@
     struct gc_list *global_list;
     unsigned int count;
     int gc_stress;
-    int gc_not_lazy_sweep;
 } rb_objspace_t;
 
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
@@ -213,11 +200,6 @@
 #define himem			objspace->heap.range[1]
 #define heaps_inc		objspace->heap.increment
 #define heaps_freed		objspace->heap.freed
-#define live			objspace->heap.live
-#define dead			objspace->heap.dead
-#define do_heap_free		objspace->heap.do_heap_free
-#define heaps_sweep_index	objspace->heap.sweep_index
-#define heaps_sweep_inc 	objspace->heap.sweep_increment
 #define dont_gc 		objspace->flags.dont_gc
 #define during_gc		objspace->flags.during_gc
 #define finalizer_table 	objspace->final.table
@@ -227,7 +209,6 @@
 #define mark_stack_overflow	objspace->markstack.overflow
 #define global_List		objspace->global_list
 #define ruby_gc_stress		objspace->gc_stress
-#define ruby_gc_not_lazy_sweep	objspace->gc_not_lazy_sweep
 
 #define need_call_final 	(finalizer_table && finalizer_table->num_entries)
 
@@ -268,7 +249,6 @@
 
 static void run_final(rb_objspace_t *objspace, VALUE obj);
 static int garbage_collect(rb_objspace_t *objspace);
-static int garbage_collect_force(rb_objspace_t *objspace);
 
 void
 rb_global_variable(VALUE *var)
@@ -345,11 +325,11 @@
 
     if ((ruby_gc_stress && !ruby_disable_gc_stress) ||
 	(malloc_increase+size) > malloc_limit) {
-	garbage_collect_force(objspace);
+	garbage_collect(objspace);
     }
     RUBY_CRITICAL(mem = malloc(size));
     if (!mem) {
-	if (garbage_collect_force(objspace)) {
+	if (garbage_collect(objspace)) {
 	    RUBY_CRITICAL(mem = malloc(size));
 	}
 	if (!mem) {
@@ -385,9 +365,10 @@
     objspace->malloc_params.allocated_size -= size;
     ptr = (size_t *)ptr - 1;
 #endif
+
     RUBY_CRITICAL(mem = realloc(ptr, size));
     if (!mem) {
-	if (garbage_collect_force(objspace)) {
+	if (garbage_collect(objspace)) {
 	    RUBY_CRITICAL(mem = realloc(ptr, size));
 	}
 	if (!mem) {
@@ -578,8 +559,6 @@
     heaps_length = next_heaps_length;
 }
 
-#define RANY(o) ((RVALUE*)(o))
-
 static void
 assign_heap_slot(rb_objspace_t *objspace)
 {
@@ -623,7 +602,6 @@
     heaps[hi].membase = membase;
     heaps[hi].slot = p;
     heaps[hi].limit = objs;
-    heaps[hi].color = BLACK;
     pend = p + objs;
     if (lomem == 0 || lomem > p) lomem = p;
     if (himem < pend) himem = pend;
@@ -635,9 +613,6 @@
 	freelist = p;
 	p++;
     }
-    if (hi < heaps_sweep_index) {
-	heaps_sweep_index++;
-    }
 }
 
 static void
@@ -680,13 +655,15 @@
     return Qfalse;
 }
 
+#define RANY(o) ((RVALUE*)(o))
+
 static VALUE
 rb_newobj_from_heap(rb_objspace_t *objspace)
 {
     VALUE obj;
 	
     if ((ruby_gc_stress && !ruby_disable_gc_stress) || !freelist) {
-   	if (!garbage_collect(objspace)) {
+    	if (!heaps_increment(objspace) && !garbage_collect(objspace)) {
 	    rb_memerror();
 	}
     }
@@ -1063,7 +1040,6 @@
     if (obj->as.basic.flags == 0) return;       /* free cell */
     if (obj->as.basic.flags & FL_MARK) return;  /* already marked */
     obj->as.basic.flags |= FL_MARK;
-    live++;
 
     if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) {
 	if (!mark_stack_overflow) {
@@ -1099,7 +1075,6 @@
     if (obj->as.basic.flags == 0) return;       /* free cell */
     if (obj->as.basic.flags & FL_MARK) return;  /* already marked */
     obj->as.basic.flags |= FL_MARK;
-    live++;
 
   marking:
     if (FL_TEST(obj, FL_EXIVAR)) {
@@ -1359,131 +1334,139 @@
 	if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
             VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
 	    p->as.free.flags = 0;
+	    p->as.free.next = freelist;
+	    freelist = p;
 	}
 	p = tmp;
     }
 }
 
-void rb_gc_abort_threads(void);
-
-static int
-slot_sweep(rb_objspace_t *objspace, struct heaps_slot *target)
+static void
+free_unused_heaps(rb_objspace_t *objspace)
 {
-    RVALUE *p, *pend, *free;
-    RVALUE *final;
-    int freed = 0;
+    size_t i, j;
+    RVALUE *last = 0;
 
-    if (target->color == BLACK || target->color == WHITE) {
-	return Qfalse;
-    }
-
-    final = deferred_final_list;
-    free = freelist;
-    p = target->slot; pend = p + target->limit;
-    while (p < pend) {
-	if (!(p->as.basic.flags & FL_MARK)) {
-	    if (p->as.basic.flags) {
-		obj_free(objspace, (VALUE)p);
+    for (i = j = 1; j < heaps_used; i++) {
+	if (heaps[i].limit == 0) {
+	    if (!last) {
+		last = heaps[i].membase;
 	    }
-	    if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
-		p->as.free.flags = FL_MARK; /* remain marked */
-		p->as.free.next = deferred_final_list;
-		deferred_final_list = p;
-	    }
 	    else {
-		VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-		p->as.free.flags = 0;
-		p->as.free.next = freelist;
-		freelist = p;
+		free(heaps[i].membase);
 	    }
-	    freed++;
+	    heaps_used--;
 	}
-	else if (RBASIC(p)->flags == FL_MARK) {
-	    /* objects to be finalized */
-	    /* do nothing remain marked */
-	}
 	else {
-	    p->as.basic.flags &= ~FL_MARK;
+	    if (i != j) {
+		heaps[j] = heaps[i];
+	    }
+	    j++;
 	}
-	p++;
     }
-    dead += freed;
-    if (freed == target->limit && dead > do_heap_free) {
-	RVALUE *pp;
-
-	target->limit = 0;
-	target->color = WHITE;
-	for (pp = deferred_final_list; pp != final; pp = pp->as.free.next) {
-	    pp->as.free.flags |= FL_SINGLETON; /* freeing page mark */
+    if (last) {
+	if (last < heaps_freed) {
+	    free(heaps_freed);
+	    heaps_freed = last;
 	}
-	freelist = free;	/* cancel this page from freelist */
+	else {
+	    free(last);
+	}
     }
-    else {
-	target->color = BLACK;
-    }
-    return Qtrue;
 }
 
 static void
-heap_sweep_increment(rb_objspace_t *objspace)
+gc_sweep(rb_objspace_t *objspace)
 {
-    int i = 0;
+    RVALUE *p, *pend, *final_list;
+    size_t freed = 0;
+    size_t i;
+    size_t live = 0, free_min = 0, do_heap_free = 0;
 
-    while (i < heaps_sweep_inc && heaps_sweep_index < heaps_used) {
-	if (slot_sweep(objspace, &heaps[heaps_sweep_index])) {
-	    i++;
-	}
-	heaps_sweep_index++;
+    do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65;
+    free_min = (heaps_used * HEAP_OBJ_LIMIT)  * 0.2;
+    if (free_min < FREE_MIN) {
+	do_heap_free = heaps_used * HEAP_OBJ_LIMIT;
+        free_min = FREE_MIN;
     }
-}
 
-static void
-heap_sweep(rb_objspace_t *objspace)
-{
-    while (!freelist && heaps_sweep_index < heaps_used) {
-	slot_sweep(objspace, &heaps[heaps_sweep_index]);
-	heaps_sweep_index++;
-    }
-}
+    freelist = 0;
+    final_list = deferred_final_list;
+    deferred_final_list = 0;
+    for (i = 0; i < heaps_used; i++) {
+	int n = 0;
+	RVALUE *free = freelist;
+	RVALUE *final = final_list;
 
-#define GC_NOT_LAZY_SWEEP 0
+	p = heaps[i].slot; pend = p + heaps[i].limit;
+	while (p < pend) {
+	    if (!(p->as.basic.flags & FL_MARK)) {
+		if (p->as.basic.flags) {
+		    obj_free(objspace, (VALUE)p);
+		}
+		if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
+		    p->as.free.flags = FL_MARK; /* remain marked */
+		    p->as.free.next = final_list;
+		    final_list = p;
+		}
+		else {
+                    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
+		    p->as.free.flags = 0;
+		    p->as.free.next = freelist;
+		    freelist = p;
+		}
+		n++;
+	    }
+	    else if (RBASIC(p)->flags == FL_MARK) {
+		/* objects to be finalized */
+		/* do nothing remain marked */
+	    }
+	    else {
+		RBASIC(p)->flags &= ~FL_MARK;
+		live++;
+	    }
+	    p++;
+	}
+	if (n == heaps[i].limit && freed > do_heap_free) {
+	    RVALUE *pp;
 
-static void
-heap_all_sweep(rb_objspace_t *objspace)
-{
-    while (heaps_sweep_index < heaps_used) {
-	slot_sweep(objspace, &heaps[heaps_sweep_index]);
-	heaps_sweep_index++;
+	    heaps[i].limit = 0;
+	    for (pp = final_list; pp != final; pp = pp->as.free.next) {
+		p->as.free.flags |= FL_SINGLETON; /* freeing page mark */
+	    }
+	    freelist = free;	/* cancel this page from freelist */
+	}
+	else {
+	    freed += n;
+	}
     }
-}
-
-static int
-gc_lazy_sweep(rb_objspace_t *objspace, rb_thread_t *th)
-{
-
-    if (heaps_increment(objspace)) {
-	heap_sweep_increment(objspace);
+    if (malloc_increase > malloc_limit) {
+	malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
+	if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
     }
-    else {
-	heap_sweep(objspace);
+    malloc_increase = 0;
+    if (freed < free_min) {
+    	set_heaps_increment(objspace);
+	heaps_increment(objspace);
     }
+    during_gc = 0;
 
-    if (ruby_gc_not_lazy_sweep || GC_NOT_LAZY_SWEEP) {
-        heap_all_sweep(objspace);
+    /* clear finalization list */
+    if (final_list) {
+	deferred_final_list = final_list;
+	return;
     }
-
-    if (!freelist) {
-	return Qfalse;
-    }
-
-    return Qtrue;
+    free_unused_heaps(objspace);
 }
 
 void
 rb_gc_force_recycle(VALUE p)
 {
+    rb_objspace_t *objspace = &rb_objspace;
     VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
     RANY(p)->as.free.flags = 0;
+    RANY(p)->as.free.next = freelist;
+    freelist = RANY(p);
 }
 
 static void
@@ -1684,87 +1667,30 @@
 
 void rb_gc_mark_encodings(void);
 
-static void
-gc_mark_all_clear(rb_objspace_t *objspace)
+static int
+garbage_collect(rb_objspace_t *objspace)
 {
-    RVALUE *last = 0;
-    size_t i, j;
-    
-    for (i = j = 0; j < heaps_used; i++) {
-	if (heaps[i].color == WHITE && !deferred_final_list) {
-	    if (!last) {
-		last = heaps[i].membase;
-	    }
-	    else {
-		free(heaps[i].membase);
-	    }
-	    heaps_used--;
-	}
-	else {
-	    if (heaps[i].color == GRAY) {
-		RVALUE *p, *pend;
-		p = heaps[i].slot; pend = p + heaps[i].limit;
-		while (p < pend) {
-		    if (!(RBASIC(p)->flags & FL_MARK)) {
-			if (p->as.basic.flags && !FL_TEST(p, FL_FINALIZE)) {
-			    obj_free(objspace, (VALUE)p);
-			    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
-			    p->as.free.flags = 0;
-			}
-		    }
-		    else if (RBASIC(p)->flags != FL_MARK) {
-			p->as.basic.flags &= ~FL_MARK;
-		    }
-		    p++;
-		}
-	    }
-	    else {
-		heaps[i].color = GRAY;
-	    }
-	    if (i != j) {
-		heaps[j] = heaps[i];
-	    }
-	    j++;
-	}
-    }
-    if (last) {
-	if (last < heaps_freed) {
-	    free(heaps_freed);
-	    heaps_freed = last;
-	}
-	else {
-	    free(last);
-	}
-    }
-}
+    struct gc_list *list;
+    rb_thread_t *th = GET_THREAD();
 
-static void
-set_lazy_sweep_params(rb_objspace_t *objspace)
-{
-    size_t free_min = 0;
+    if (GC_NOTIFY) printf("start garbage_collect()\n");
 
-    dead = 0;
-    heaps_sweep_index = 0;
-    heaps_sweep_inc = (heaps_used / 10) + 1;
-    do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65;
-    free_min = (heaps_used * HEAP_OBJ_LIMIT)  * 0.2;
-    if (free_min < FREE_MIN) free_min = FREE_MIN;
-    if (free_min > (heaps_used * HEAP_OBJ_LIMIT - live)) {
-	set_heaps_increment(objspace);
-	heaps_sweep_inc = (heaps_used + heaps_sweep_inc) / heaps_sweep_inc + 1;
+    if (!heaps) {
+	return Qfalse;
     }
-}
 
-static void
-gc_marks(rb_objspace_t *objspace, rb_thread_t *th)
-{
-    struct gc_list *list;
+    if (dont_gc || during_gc) {
+	if (!freelist) {
+            if (!heaps_increment(objspace)) {
+                set_heaps_increment(objspace);
+                heaps_increment(objspace);
+            }
+	}
+	return Qtrue;
+    }
+    during_gc++;
+    objspace->count++;
 
-    live = 0;
-    freelist = 0;
-
-    gc_mark_all_clear(objspace);
-
     SET_STACK_END;
 
     init_mark_stack(objspace);
@@ -1781,7 +1707,6 @@
     rb_gc_mark_symbols();
     rb_gc_mark_encodings();
 
-
     /* mark protected global variables */
     for (list = global_List; list; list = list->next) {
 	rb_gc_mark_maybe(*list->varptr);
@@ -1807,55 +1732,9 @@
 	}
     }
 
-    set_lazy_sweep_params(objspace);
-}
+    gc_sweep(objspace);
 
-static int
-garbage_collect_force(rb_objspace_t *objspace)
-{
-    int is_gc_success;
-
-    if (malloc_increase > malloc_limit) {
-	malloc_limit += (malloc_increase - malloc_limit) * (double)live / (heaps_used * HEAP_OBJ_LIMIT);
-	if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
-    }
-    malloc_increase = 0;
-    ruby_gc_not_lazy_sweep = Qtrue;
-    is_gc_success = garbage_collect(objspace);
-    ruby_gc_not_lazy_sweep = Qfalse;
-    return is_gc_success;
-}
-
-static int
-garbage_collect(rb_objspace_t *objspace)
-{
-    rb_thread_t *th = GET_THREAD();
-
-    if (GC_NOTIFY) printf("start garbage_collect()\n");
-
-    if (!heaps) {
-	return Qfalse;
-    }
-
-    if (dont_gc || during_gc) {
-	if (!freelist) {
-            if (!heaps_increment(objspace)) {
-                set_heaps_increment(objspace);
-                heaps_increment(objspace);
-            }
-	}
-	return Qtrue;
-    }
-    during_gc++;
-    objspace->count++;
-
-    while (!gc_lazy_sweep(objspace, th)) {
-        gc_marks(objspace, th);
-    }
-
     if (GC_NOTIFY) printf("end garbage_collect()\n");
-    during_gc = 0;
-
     return Qtrue;
 }
 
@@ -1970,7 +1849,6 @@
 
 	p = heaps[i].slot; pend = p + heaps[i].limit;
 	for (;p < pend; p++) {
-	    if (!freelist) garbage_collect_force(objspace);
 	    if (p->as.basic.flags) {
 		switch (BUILTIN_TYPE(p)) {
 		  case T_NONE:
@@ -2156,6 +2034,7 @@
     if (p) {
 	finalize_list(objspace, p);
     }
+    free_unused_heaps(objspace);
 }
 
 void
@@ -2227,8 +2106,8 @@
 rb_gc(void)
 {
     rb_objspace_t *objspace = &rb_objspace;
-    gc_finalize_deferred(objspace);
     garbage_collect(objspace);
+    gc_finalize_deferred(objspace);
 }
 
 /*

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]