[macruby-changes] [2918] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Oct 28 22:45:09 PDT 2009


Revision: 2918
          http://trac.macosforge.org/projects/ruby/changeset/2918
Author:   lsansonetti at apple.com
Date:     2009-10-28 22:45:05 -0700 (Wed, 28 Oct 2009)
Log Message:
-----------
implemented ObjectSpace finalizers (experimental)

Modified Paths:
--------------
    MacRuby/trunk/gc.c
    MacRuby/trunk/id.c
    MacRuby/trunk/id.h

Modified: MacRuby/trunk/gc.c
===================================================================
--- MacRuby/trunk/gc.c	2009-10-29 04:09:49 UTC (rev 2917)
+++ MacRuby/trunk/gc.c	2009-10-29 05:45:05 UTC (rev 2918)
@@ -18,6 +18,7 @@
 #include "ruby/util.h"
 #include "objc.h"
 #include "vm.h"
+#include "id.h"
 #include <stdio.h>
 #include <setjmp.h>
 #include <sys/types.h>
@@ -725,19 +726,45 @@
  *
  */
 
-static CFMutableDictionaryRef __os_finalizers = NULL;
+typedef struct {
+    VALUE klass;
+    VALUE finalizers;
+} rb_vm_finalizer_t;
 
+static VALUE rb_cFinalizer;
+
+static void *finalizer_key = NULL; // only used for its address
+
+static IMP rb_objc_finalizer_finalize_super = NULL;
+
+static VALUE rb_obj_id(VALUE obj, SEL sel);
+
+static void
+rb_objc_finalizer_finalize(void *rcv, SEL sel)
+{
+    rb_vm_set_multithreaded(true);
+    rb_vm_finalizer_t *f = (rb_vm_finalizer_t *)rcv;
+    for (int i = 0, count = RARRAY_LEN(f->finalizers); i < count; i++) {
+	VALUE b = RARRAY_AT(f->finalizers, i);
+	VALUE objid = rb_obj_id((VALUE)rcv, 0);
+	rb_vm_call(b, selCall, 1, &objid, false);	
+    }
+    if (rb_objc_finalizer_finalize_super != NULL) {
+	((void(*)(void *, SEL))rb_objc_finalizer_finalize_super)(rcv, sel);
+    }
+}
+
 static VALUE
 undefine_final(VALUE os, SEL sel, VALUE obj)
 {
-    if (__os_finalizers != NULL)
-	CFDictionaryRemoveValue(__os_finalizers, (const void *)obj);
-    
-    if (NATIVE(obj)) {
-	rb_objc_flag_set((void *)obj, FL_FINALIZE, false);
+    if (SPECIAL_CONST_P(obj)) {
+	rb_raise(rb_eArgError, "immediate types are not finalizable");
     }
-    else {
-	FL_UNSET(obj, FL_FINALIZE);
+    rb_vm_finalizer_t *finalizer = rb_objc_get_associative_ref((void *)obj,
+	    &finalizer_key);
+    if (finalizer != NULL) {
+	rb_ary_clear(finalizer->finalizers);
+	rb_objc_set_associative_ref((void *)obj, &finalizer_key, NULL);
     }
     return obj;
 }
@@ -754,91 +781,47 @@
 static VALUE
 define_final(VALUE os, SEL sel, int argc, VALUE *argv)
 {
-    VALUE obj, block, table;
+    VALUE obj, block;
 
-    if (__os_finalizers == NULL)
-	__os_finalizers = CFDictionaryCreateMutable(NULL, 0, NULL,
-	    &kCFTypeDictionaryValueCallBacks);
-
     rb_scan_args(argc, argv, "11", &obj, &block);
     if (argc == 1) {
 	block = rb_block_proc();
     }
     else if (!rb_respond_to(block, rb_intern("call"))) {
 	rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
-		 rb_obj_classname(block));
+		rb_obj_classname(block));
     }
 
-    table = (VALUE)CFDictionaryGetValue((CFDictionaryRef)__os_finalizers, 
-	(const void *)obj);
-
-    if (table == 0) {
-	table = rb_ary_new();
-	CFDictionarySetValue(__os_finalizers, (const void *)obj, 
-	    (const void *)table);
+    if (SPECIAL_CONST_P(obj)) {
+	rb_raise(rb_eArgError, "immediate types are not finalizable");
     }
 
-    rb_ary_push(table, block);
-    
-    if (NATIVE(obj)) {
-	rb_objc_flag_set((void *)obj, FL_FINALIZE, true);
+    rb_vm_finalizer_t *finalizer = rb_objc_get_associative_ref((void *)obj,
+	    &finalizer_key);
+    if (finalizer == NULL) {
+	finalizer = (rb_vm_finalizer_t *)
+	    rb_objc_newobj(sizeof(rb_vm_finalizer_t *));
+	finalizer->klass = rb_cFinalizer;
+	GC_WB(&finalizer->finalizers, rb_ary_new());
+	rb_objc_set_associative_ref((void *)obj, &finalizer_key, finalizer);
     }
-    else {
-	FL_SET(obj, FL_FINALIZE);
-    }
 
-    VALUE ret = rb_ary_new3(2, INT2FIX(rb_safe_level()), block);
-    OBJ_FREEZE(ret);
-    return ret;
+    rb_ary_push(finalizer->finalizers, block);
+    
+    // For RubySpec conformance.
+    return rb_ary_new3(2, INT2FIX(rb_safe_level()), block);
 }
 
 void
 rb_gc_copy_finalizer(VALUE dest, VALUE obj)
 {
-    VALUE table;
-
-    if (__os_finalizers == NULL)
-	return;
-
-    if (NATIVE(obj)) {
-	if (!rb_objc_flag_check((void *)obj, FL_FINALIZE))
-	    return;
-    }
-    else {
-	if (!FL_TEST(obj, FL_FINALIZE))
-	    return;
-    }
-
-    table = (VALUE)CFDictionaryGetValue((CFDictionaryRef)__os_finalizers,
-	(const void *)obj);
-
-    if (table == 0) {
-	CFDictionaryRemoveValue(__os_finalizers, (const void *)dest);
-    }
-    else {
-	CFDictionarySetValue(__os_finalizers, (const void *)dest, 
-	    (const void *)table);	
-    }
+    // TODO
 }
 
-static void rb_call_os_finalizer2(VALUE, VALUE);
-
-static void
-os_finalize_cb(const void *key, const void *val, void *context)
-{
-    rb_call_os_finalizer2((VALUE)key, (VALUE)val);
-}
-
 void
 rb_gc_call_finalizer_at_exit(void)
 {
-    if (__os_finalizers != NULL) {
-	CFDictionaryApplyFunction((CFDictionaryRef)__os_finalizers,
-    	    os_finalize_cb, NULL);
-	CFDictionaryRemoveAllValues(__os_finalizers);
-	CFRelease(__os_finalizers);
-    }
-
+    // This should magically trigger -[__Finalizer finalize].
     auto_collect(__auto_zone, AUTO_COLLECT_FULL_COLLECTION, NULL);
 }
 
@@ -915,7 +898,7 @@
  *  <code>Fixnum</code> will be truncated before being used.
  */
 
-VALUE
+static VALUE
 rb_obj_id(VALUE obj, SEL sel)
 {
     return (VALUE)LONG2NUM((SIGNED_VALUE)obj);
@@ -1046,91 +1029,6 @@
  *  are also available via the <code>ObjectSpace</code> module.
  */
 
-static VALUE
-run_single_final(VALUE arg)
-{
-    VALUE *args = (VALUE *)arg;
-    rb_eval_cmd(args[0], args[1], (int)args[2]);
-    return Qnil;
-}
-
-static void
-rb_call_os_finalizer2(VALUE obj, VALUE table)
-{
-    long i, count;
-    VALUE args[3];
-    int status, critical_save;
-
-    critical_save = rb_thread_critical;
-    rb_thread_critical = Qtrue;
-
-    args[1] = rb_ary_new3(1, rb_obj_id(obj, 0));
-    args[2] = (VALUE)rb_safe_level();
-
-    for (i = 0, count = RARRAY_LEN(table); i < count; i++) {
-	args[0] = RARRAY_AT(table, i);
-	rb_protect(run_single_final, (VALUE)args, &status);
-    }
-
-    rb_thread_critical = critical_save;
-}
-
-void
-rb_call_os_finalizer(void *obj)
-{
-    if (__os_finalizers != NULL) {
-	VALUE table;
-
-	table = (VALUE)CFDictionaryGetValue((CFDictionaryRef)__os_finalizers,
-	    (const void *)obj);
-
-	if (table != 0) {
-	    rb_call_os_finalizer2((VALUE)obj, table);
-	    CFDictionaryRemoveValue(__os_finalizers, (const void *)obj);
-	}
-    }
-}
-
-static void
-rb_obj_imp_finalize(void *obj, SEL sel)
-{
-//printf("FINALIZE %p %s\n", obj, class_getName(*(Class *)obj));
-
-#if 0
-//    const bool need_protection = 
-//	GET_THREAD()->thread_id != pthread_self();
-    bool call_finalize, free_ivar;
-
-    if (NATIVE((VALUE)obj)) {
-	long flag;
-
-	flag = rb_objc_remove_flags(obj);
-
-	call_finalize = (flag & FL_FINALIZE) == FL_FINALIZE;
-	free_ivar = (flag & FL_EXIVAR) == FL_EXIVAR;
-    }
-    else {
-	call_finalize = FL_TEST(obj, FL_FINALIZE);
-	free_ivar = FL_TEST(obj, FL_EXIVAR);
-    }
-
-    if (call_finalize || free_ivar) {
-//	if (need_protection) {
-//	    native_mutex_lock(&GET_THREAD()->vm->global_interpreter_lock);
-//	}
-	if (call_finalize) {
-	    rb_call_os_finalizer(obj);
-	}
-	if (free_ivar) {
-	    rb_free_generic_ivar((VALUE)obj);
-	}
-//	if (need_protection) {
-//	    native_mutex_unlock(&GET_THREAD()->vm->global_interpreter_lock);
-//	}
-    }
-#endif
-}
-
 static bool gc_disabled = false;
 
 void
@@ -1154,10 +1052,6 @@
 	gc_disabled = true;
     }
 
-    Method m = class_getInstanceMethod((Class)objc_getClass("NSObject"), sel_registerName("finalize"));
-    assert(m != NULL);
-    method_setImplementation(m, (IMP)rb_obj_imp_finalize);
-
     auto_collector_disable(__auto_zone);
 }
 
@@ -1201,4 +1095,9 @@
     rb_objc_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
 
     rb_objc_define_method(*(VALUE *)rb_mObSpace, "count_objects", count_objects, -1);
+
+    rb_cFinalizer = rb_define_class("__Finalizer", rb_cObject);
+    rb_objc_finalizer_finalize_super =
+	rb_objc_install_method2((Class)rb_cFinalizer,
+		"finalize", (IMP)rb_objc_finalizer_finalize);
 }

Modified: MacRuby/trunk/id.c
===================================================================
--- MacRuby/trunk/id.c	2009-10-29 04:09:49 UTC (rev 2917)
+++ MacRuby/trunk/id.c	2009-10-29 05:45:05 UTC (rev 2918)
@@ -82,6 +82,7 @@
     selToAry = sel_registerName("to_ary");
     selSend = sel_registerName("send:");
     sel__send__ = sel_registerName("__send__:");
+    selCall = sel_registerName("call:");
     selEqTilde = sel_registerName("=~:");
     selClass = sel_registerName("class");
     selEval = sel_registerName("eval:");

Modified: MacRuby/trunk/id.h
===================================================================
--- MacRuby/trunk/id.h	2009-10-29 04:09:49 UTC (rev 2917)
+++ MacRuby/trunk/id.h	2009-10-29 05:45:05 UTC (rev 2918)
@@ -91,6 +91,7 @@
 extern SEL sel_zone;
 extern SEL selSend;
 extern SEL sel__send__;
+extern SEL selCall;
 extern SEL selEqTilde;
 extern SEL selClass;
 extern SEL selEval;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091028/2fe058fe/attachment.html>


More information about the macruby-changes mailing list