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

ruby-changes:6715

From: ko1 <ko1@a...>
Date: Sun, 27 Jul 2008 15:00:50 +0900 (JST)
Subject: [ruby-changes:6715] Ruby:r18231 (trunk): * include/ruby/ruby.h: add a type T_DEFERRED.

ko1	2008-07-27 14:59:32 +0900 (Sun, 27 Jul 2008)

  New Revision: 18231

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

  Log:
    * include/ruby/ruby.h: add a type T_DEFERRED.
    * gc.c: fix deferred finalizer system.  finalize processes of
      T_DATA and T_FILE are executed after gc process.
      And fix to use BUILTIN_TYPE() instead of seeing flag.
    * thread.c, vm_core.h: add RUBY_VM_SET_FINALIZER_INTERRUPT()
      and check intterupt_flag at rb_thread_execute_interrupts().
    * thread.c (mutex_mark): fix to mark next_mutex.
    * vm.c (rb_thread_mark): fix to mark keeping_mutexes.

  Modified files:
    trunk/ChangeLog
    trunk/gc.c
    trunk/include/ruby/ruby.h
    trunk/thread.c
    trunk/vm.c
    trunk/vm_core.h

Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h	(revision 18230)
+++ include/ruby/ruby.h	(revision 18231)
@@ -302,6 +302,7 @@
     RUBY_T_UNDEF  = 0x1b,
     RUBY_T_NODE   = 0x1c,
     RUBY_T_ICLASS = 0x1d,
+    RUBY_T_DEFERRED = 0x1e,
 
     RUBY_T_MASK   = 0x1f
 };
@@ -330,6 +331,7 @@
 #define T_COMPLEX RUBY_T_COMPLEX
 #define T_UNDEF  RUBY_T_UNDEF
 #define T_NODE   RUBY_T_NODE
+#define T_DEFERRED RUBY_T_DEFERRED
 #define T_MASK   RUBY_T_MASK
 
 #define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 18230)
+++ ChangeLog	(revision 18231)
@@ -1,3 +1,18 @@
+Sun Jul 27 14:48:37 2008  Koichi Sasada  <ko1@a...>
+
+	* include/ruby/ruby.h: add a type T_DEFERRED.
+
+	* gc.c: fix deferred finalizer system.  finalize processes of
+	  T_DATA and T_FILE are executed after gc process.
+	  And fix to use BUILTIN_TYPE() instead of seeing flag.
+
+	* thread.c, vm_core.h: add RUBY_VM_SET_FINALIZER_INTERRUPT()
+	  and check intterupt_flag at rb_thread_execute_interrupts().
+
+	* thread.c (mutex_mark): fix to mark next_mutex.
+
+	* vm.c (rb_thread_mark): fix to mark keeping_mutexes.
+
 Sun Jul 27 09:15:28 2008  Nobuyoshi Nakada  <nobu@r...>
 
 	* dln.h (dln_find_exe, dln_find_file): deprecated, use reentrant
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 18230)
+++ vm_core.h	(revision 18231)
@@ -690,12 +690,13 @@
 
 #define RUBY_VM_SET_INTERRUPT(th) ((th)->interrupt_flag |= 0x02)
 #define RUBY_VM_SET_TIMER_INTERRUPT(th) ((th)->interrupt_flag |= 0x01)
+#define RUBY_VM_SET_FINALIZER_INTERRUPT(th) ((th)->interrupt_flag |= 0x04)
 #define RUBY_VM_INTERRUPTED(th) ((th)->interrupt_flag & 0x02)
 
 void rb_thread_execute_interrupts(rb_thread_t *);
 
 #define RUBY_VM_CHECK_INTS_TH(th) do { \
-  if(th->interrupt_flag){ \
+  if (th->interrupt_flag) { \
     /* TODO: trap something event */ \
     rb_thread_execute_interrupts(th); \
   } \
Index: thread.c
===================================================================
--- thread.c	(revision 18230)
+++ thread.c	(revision 18231)
@@ -935,8 +935,12 @@
 rb_thread_execute_interrupts(rb_thread_t *th)
 {
     if (th->raised_flag) return;
+
     while (th->interrupt_flag) {
 	enum rb_thread_status status = th->status;
+	int timer_interrupt = th->interrupt_flag & 0x01;
+	int finalizer_interrupt = th->interrupt_flag & 0x04;
+
 	th->status = THREAD_RUNNABLE;
 	th->interrupt_flag = 0;
 
@@ -963,10 +967,15 @@
 	}
 	th->status = status;
 
-	/* thread pass */
-	rb_thread_schedule();
+	if (finalizer_interrupt) {
+	    rb_gc_finalize_deferred();
+	}
+
+	if (timer_interrupt) {
+	    EXEC_EVENT_HOOK(th, RUBY_EVENT_SWITCH, th->cfp->self, 0, 0);
+	    rb_thread_schedule();
+	}
     }
-    EXEC_EVENT_HOOK(th, RUBY_EVENT_SWITCH, th->cfp->self, 0, 0);
 }
 
 
@@ -2494,6 +2503,7 @@
 {
     if (ptr) {
 	mutex_t *mutex = ptr;
+	rb_gc_mark(mutex->next_mutex);
 	if (mutex->th) {
 	    rb_gc_mark(mutex->th->self);
 	}
Index: gc.c
===================================================================
--- gc.c	(revision 18230)
+++ gc.c	(revision 18231)
@@ -578,7 +578,6 @@
 	    objs--;
 	}
     }
-    	
 
     lo = 0;
     hi = heaps_used;
@@ -1081,7 +1080,7 @@
 	rb_mark_generic_ivar(ptr);
     }
 
-    switch (obj->as.basic.flags & T_MASK) {
+    switch (BUILTIN_TYPE(obj)) {
       case T_NIL:
       case T_FIXNUM:
 	rb_bug("rb_gc_mark() called for broken object");
@@ -1224,7 +1223,7 @@
     }
 
     gc_mark(objspace, obj->as.basic.klass, lev);
-    switch (obj->as.basic.flags & T_MASK) {
+    switch (BUILTIN_TYPE(obj)) {
       case T_ICLASS:
       case T_CLASS:
       case T_MODULE:
@@ -1316,18 +1315,27 @@
 	}
 	break;
 
-      case T_UNDEF:
+      case T_DEFERRED:
 	break;
 
       default:
 	rb_bug("rb_gc_mark(): unknown data type 0x%lx(%p) %s",
-	       obj->as.basic.flags & T_MASK, obj,
+	       BUILTIN_TYPE(obj), obj,
 	       is_pointer_to_heap(objspace, obj) ? "corrupted object" : "non object");
     }
 }
 
 static int obj_free(rb_objspace_t *, VALUE);
 
+static inline void
+add_freelist(rb_objspace_t *objspace, RVALUE *p)
+{
+    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
+    p->as.free.flags = 0;
+    p->as.free.next = freelist;
+    freelist = p;
+}
+
 static void
 finalize_list(rb_objspace_t *objspace, RVALUE *p)
 {
@@ -1335,10 +1343,7 @@
 	RVALUE *tmp = p->as.free.next;
 	run_final(objspace, (VALUE)p);
 	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;
+	    add_freelist(objspace, p);
 	}
 	p = tmp;
     }
@@ -1388,6 +1393,7 @@
 
     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;
@@ -1400,25 +1406,28 @@
 	int n = 0;
 	RVALUE *free = freelist;
 	RVALUE *final = final_list;
+	int deferred;
 
 	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) ||
-		    need_call_final && FL_TEST(p, FL_FINALIZE)) {
-		    p->as.free.flags |= FL_MARK; /* remain marked */
+		if (p->as.basic.flags &&
+		    ((deferred = obj_free(objspace, (VALUE)p)) ||
+		     ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) {
+		    if (!deferred) {
+			p->as.free.flags = T_DEFERRED;
+			RDATA(p)->dfree = 0;
+		    }
+		    p->as.free.flags |= FL_MARK;
 		    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;
+		    add_freelist(objspace, p);
 		}
 		n++;
 	    }
-	    else if (RBASIC(p)->flags == FL_MARK) {
+	    else if (BUILTIN_TYPE(p) == T_DEFERRED) {
 		/* objects to be finalized */
 		/* do nothing remain marked */
 	    }
@@ -1455,25 +1464,24 @@
     /* clear finalization list */
     if (final_list) {
 	deferred_final_list = final_list;
-	return;
+	RUBY_VM_SET_FINALIZER_INTERRUPT(GET_THREAD());
     }
-    free_unused_heaps(objspace);
+    else{
+	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);
+    add_freelist(objspace, (RVALUE *)p);
 }
 
 static int
 obj_free(rb_objspace_t *objspace, VALUE obj)
 {
-    switch (RANY(obj)->as.basic.flags & T_MASK) {
+    switch (BUILTIN_TYPE(obj)) {
       case T_NIL:
       case T_FIXNUM:
       case T_TRUE:
@@ -1486,7 +1494,7 @@
 	rb_free_generic_ivar((VALUE)obj);
     }
 
-    switch (RANY(obj)->as.basic.flags & T_MASK) {
+    switch (BUILTIN_TYPE(obj)) {
       case T_OBJECT:
 	if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) &&
             RANY(obj)->as.object.as.heap.ivptr) {
@@ -1527,9 +1535,14 @@
 		xfree(DATA_PTR(obj));
 	    }
 	    else if (RANY(obj)->as.data.dfree) {
-		RANY(obj)->as.basic.flags &= ~T_MASK;
-		RANY(obj)->as.basic.flags |= T_UNDEF;
-		return 1;
+		if (1) {
+		    RANY(obj)->as.basic.flags &= ~T_MASK;
+		    RANY(obj)->as.basic.flags |= T_DEFERRED;
+		    return 1;
+		}
+		else {
+		    (*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
+		}
 	    }
 	}
 	break;
@@ -1545,11 +1558,16 @@
       case T_FILE:
 	if (RANY(obj)->as.file.fptr) {
 	    rb_io_t *fptr = RANY(obj)->as.file.fptr;
-	    RANY(obj)->as.basic.flags &= ~T_MASK;
-	    RANY(obj)->as.basic.flags |= T_UNDEF;
-	    RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize;
-	    RDATA(obj)->data = fptr;
-	    return 1;
+	    if (1) {
+		RANY(obj)->as.basic.flags &= ~T_MASK;
+		RANY(obj)->as.basic.flags |= T_DEFERRED;
+		RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize;
+		RDATA(obj)->data = fptr;
+		return 1;
+	    }
+	    else {
+		rb_io_fptr_finalize(fptr);
+	    }
 	}
 	break;
       case T_RATIONAL:
@@ -1587,14 +1605,14 @@
 	}
 	break;
 
-      case T_UNDEF:
+      case T_DEFERRED:
 	break;
 
       default:
 	rb_bug("gc_sweep(): unknown data type 0x%lx(%p)",
-	       RANY(obj)->as.basic.flags & T_MASK, (void*)obj);
+	       BUILTIN_TYPE(obj), (void*)obj);
     }
-    RANY(obj)->as.basic.flags &= ~T_MASK;
+
     return 0;
 }
 
@@ -1867,7 +1885,7 @@
 		  case T_NONE:
 		  case T_ICLASS:
 		  case T_NODE:
-		  case T_UNDEF:
+		  case T_DEFERRED:
 		    continue;
 		  case T_CLASS:
 		    if (FL_TEST(p, FL_SINGLETON)) continue;
@@ -2018,17 +2036,19 @@
 run_final(rb_objspace_t *objspace, VALUE obj)
 {
     long i;
-    int status, critical_save = rb_thread_critical;
+    int status;
     VALUE args[3], table, objid;
 
     objid = rb_obj_id(obj);	/* make obj into id */
-    rb_thread_critical = Qtrue;
-    if ((RANY(obj)->as.basic.flags & T_MASK) == T_UNDEF) {
-	(*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
+
+    if (RDATA(obj)->dfree) {
+	(*RDATA(obj)->dfree)(DATA_PTR(obj));
     }
-    args[1] = 0;
-    args[2] = (VALUE)rb_safe_level();
-    if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) {
+
+    if (finalizer_table &&
+	st_delete(finalizer_table, (st_data_t*)&obj, &table)) {
+	args[1] = 0;
+	args[2] = (VALUE)rb_safe_level();
 	if (!args[1] && RARRAY_LEN(table) > 0) {
 	    args[1] = rb_obj_freeze(rb_ary_new3(1, objid));
 	}
@@ -2039,15 +2059,14 @@
 	    rb_protect(run_single_final, (VALUE)args, &status);
 	}
     }
-    rb_thread_critical = critical_save;
 }
 
 static void
 gc_finalize_deferred(rb_objspace_t *objspace)
 {
     RVALUE *p = deferred_final_list;
+    deferred_final_list = 0;
 
-    deferred_final_list = 0;
     if (p) {
 	finalize_list(objspace, p);
     }
@@ -2065,7 +2084,10 @@
 {
     RVALUE *p = (RVALUE *)key, **final_list = (RVALUE **)arg;
     if (p->as.basic.flags & FL_FINALIZE) {
-	p->as.free.flags = FL_MARK; /* remain marked */
+	if (BUILTIN_TYPE(p) != T_DEFERRED) {
+	    p->as.free.flags = FL_MARK | T_DEFERRED; /* remain marked */
+	    RDATA(p)->dfree = 0;
+	}
 	p->as.free.next = *final_list;
 	*final_list = p;
     }
@@ -2345,6 +2367,7 @@
 	    COUNT_TYPE(T_UNDEF);
 	    COUNT_TYPE(T_NODE);
 	    COUNT_TYPE(T_ICLASS);
+	    COUNT_TYPE(T_DEFERRED);
 #undef COUNT_TYPE
           default:              type = INT2NUM(i); break;
         }
Index: vm.c
===================================================================
--- vm.c	(revision 18230)
+++ vm.c	(revision 18231)
@@ -1551,6 +1551,7 @@
 	RUBY_MARK_UNLESS_NULL(th->last_status);
 
 	RUBY_MARK_UNLESS_NULL(th->locking_mutex);
+	RUBY_MARK_UNLESS_NULL(th->keeping_mutexes);
 
 	rb_mark_tbl(th->local_storage);
 

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

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