[macruby-changes] [2741] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Oct 6 16:55:43 PDT 2009


Revision: 2741
          http://trac.macosforge.org/projects/ruby/changeset/2741
Author:   lsansonetti at apple.com
Date:     2009-10-06 16:55:43 -0700 (Tue, 06 Oct 2009)
Log Message:
-----------
now honoring the sel_of_type BridgeSupport attribute

Modified Paths:
--------------
    MacRuby/trunk/bridgesupport.cpp
    MacRuby/trunk/dispatcher.cpp
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h

Modified: MacRuby/trunk/bridgesupport.cpp
===================================================================
--- MacRuby/trunk/bridgesupport.cpp	2009-10-06 21:14:36 UTC (rev 2740)
+++ MacRuby/trunk/bridgesupport.cpp	2009-10-06 23:55:43 UTC (rev 2741)
@@ -1093,13 +1093,12 @@
 	}
     }
 #endif
-#if 0
-    static bool R6401816_fixed = false;
-    /* XXX work around for <rdar://problem/6401816> -[NSObject performSelector:withObject:] has wrong sel_of_type attributes*/
-    if (!R6401816_fixed) {
-	bs_element_method_t *bs_method = 
-	    rb_bs_find_method((Class)rb_cNSObject, 
-			      @selector(performSelector:withObject:));
+    static bool R7281806fixed = false;
+    // XXX work around for
+    // <rdar://problem/7281806> -[NSObject performSelector:] has wrong sel_of_type attributes
+    if (!R7281806fixed) {
+	bs_element_method_t *bs_method = GET_CORE()->find_bs_method((Class)rb_cNSObject,
+		sel_registerName("performSelector:"));
 	if (bs_method != NULL) {
 	    bs_element_arg_t *arg = bs_method->args;
 	    while (arg != NULL) {
@@ -1107,14 +1106,13 @@
 		    && arg->sel_of_type != NULL
 		    && arg->sel_of_type[0] != '@') {
 		    arg->sel_of_type[0] = '@';
-		    R6401816_fixed = true;
+		    R7281806fixed = true;
 		    break;
 		}
 		arg++;
 	    }
 	}	
     }
-#endif
 }
 
 extern "C"

Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp	2009-10-06 21:14:36 UTC (rev 2740)
+++ MacRuby/trunk/dispatcher.cpp	2009-10-06 23:55:43 UTC (rev 2741)
@@ -452,6 +452,25 @@
 	    argc, true);
 }
 
+static bool
+reinstall_method_maybe(Class klass, SEL sel, const char *types)
+{
+    Method m = class_getInstanceMethod(klass, sel);
+    if (m == NULL) {
+	return false;
+    }
+
+    rb_vm_method_node_t *node = GET_CORE()->method_node_get(m);
+    if (node == NULL) {
+	// We only do that for pure Ruby methods.
+	return false;
+    }
+
+    GET_CORE()->retype_method(klass, node, types);
+
+    return true;
+}
+
 static force_inline VALUE
 __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE self, Class klass,
 	SEL sel, rb_vm_block_t *block, unsigned char opt, int argc,
@@ -725,7 +744,46 @@
 		cached ? "true" : "false");
 #endif
 
-	return (*ocache.stub)(ocache.imp, RB2OC(self), sel, argc, argv);
+	id ocrcv = RB2OC(self);
+
+ 	if (ocache.bs_method != NULL) {
+	    for (int i = 0; i < (int)ocache.bs_method->args_count; i++) {
+		bs_element_arg_t *arg = &ocache.bs_method->args[i];
+		if (arg->sel_of_type != NULL) {
+		    // BridgeSupport tells us that this argument contains a
+		    // selector of the given type, but we don't have any
+		    // information regarding the target. RubyCocoa and the
+		    // other ObjC bridges do not really require it since they
+		    // use the NSObject message forwarding mechanism, but
+		    // MacRuby registers all methods in the runtime.
+		    //
+		    // Therefore, we apply here a naive heuristic by assuming
+		    // that either the receiver or one of the arguments of this
+		    // call is the future target.
+		    ID arg_selid = rb_to_id(argv[i]);
+		    SEL arg_sel = sel_registerName(rb_id2name(arg_selid));
+
+		    if (reinstall_method_maybe(*(Class *)ocrcv, arg_sel,
+			    arg->sel_of_type)) {
+			goto sel_target_found;
+		    }
+		    for (int j = 0; j < argc; j++) {
+			if (j != i && !SPECIAL_CONST_P(argv[j])) {
+			    if (reinstall_method_maybe(*(Class *)argv[j], arg_sel,
+					arg->sel_of_type)) {
+				goto sel_target_found;
+			    }
+			}
+		    }
+
+sel_target_found:
+		    // There can only be one sel_of_type argument.
+		    break; 
+		}
+	    }
+	}
+
+	return (*ocache.stub)(ocache.imp, ocrcv, sel, argc, argv);
     }
     else if (cache->flag == MCACHE_FCALL) {
 #if ROXOR_VM_DEBUG

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-10-06 21:14:36 UTC (rev 2740)
+++ MacRuby/trunk/vm.cpp	2009-10-06 23:55:43 UTC (rev 2741)
@@ -1430,6 +1430,24 @@
 }
 
 rb_vm_method_node_t *
+RoxorCore::retype_method(Class klass, rb_vm_method_node_t *node,
+	const char *types)
+{
+    // TODO: 1) don't reinstall method in case the types didn't change
+    // 2) free LLVM machine code from old objc IMP
+
+    // Re-generate ObjC stub. 
+    Function *objc_func = RoxorCompiler::shared->compile_objc_stub(NULL,
+	    node->ruby_imp, node->arity, types);
+    node->objc_imp = compile(objc_func);
+    objc_to_ruby_stubs[node->ruby_imp] = node->objc_imp;
+
+    // Re-add the method.
+    return add_method(klass, node->sel, node->objc_imp, node->ruby_imp,
+	    node->arity, node->flags, types);
+}
+
+rb_vm_method_node_t *
 RoxorCore::resolve_method(Class klass, SEL sel, Function *func,
 	const rb_vm_arity_t &arity, int flags, IMP imp, Method m)
 {

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2009-10-06 21:14:36 UTC (rev 2740)
+++ MacRuby/trunk/vm.h	2009-10-06 23:55:43 UTC (rev 2741)
@@ -689,6 +689,8 @@
 	rb_vm_method_node_t *resolve_method(Class klass, SEL sel,
 		Function *func, const rb_vm_arity_t &arity, int flags,
 		IMP imp, Method m);
+	rb_vm_method_node_t *retype_method(Class klass,
+		rb_vm_method_node_t *node, const char *types);
 	void undef_method(Class klass, SEL sel);
 	bool resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
 		Class klass, SEL sel);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091006/81f8e3d7/attachment.html>


More information about the macruby-changes mailing list