[macruby-changes] [1844] MacRuby/branches/experimental/vm.cpp

source_changes at macosforge.org source_changes at macosforge.org
Thu Jun 11 23:28:29 PDT 2009


Revision: 1844
          http://trac.macosforge.org/projects/ruby/changeset/1844
Author:   lsansonetti at apple.com
Date:     2009-06-11 23:28:12 -0700 (Thu, 11 Jun 2009)
Log Message:
-----------
support for -forwardInvocation: style message forwarding

Modified Paths:
--------------
    MacRuby/branches/experimental/vm.cpp

Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp	2009-06-12 03:41:50 UTC (rev 1843)
+++ MacRuby/branches/experimental/vm.cpp	2009-06-12 06:28:12 UTC (rev 1844)
@@ -2169,6 +2169,21 @@
     rcache.node = node;
 }
 
+static force_inline bool
+can_forwardInvocation(VALUE recv, SEL sel)
+{
+    if (!SPECIAL_CONST_P(recv)) {
+	static SEL methodSignatureForSelector = 0;
+	if (methodSignatureForSelector == 0) {
+	    methodSignatureForSelector =
+		sel_registerName("methodSignatureForSelector:");	
+	}
+	return objc_msgSend((id)recv, methodSignatureForSelector, (id)sel)
+	    != nil;
+    }
+    return false;
+}
+
 static force_inline void
 fill_ocache(struct mcache *cache, VALUE self, Class klass, IMP imp, SEL sel,
 	    Method method, int argc)
@@ -2187,7 +2202,8 @@
 		sel_getName(sel));
 	abort();
     }
-    if (ocache.bs_method != NULL && ocache.bs_method->variadic) {
+    if (ocache.bs_method != NULL && ocache.bs_method->variadic
+	&& method != NULL) {
 	const int real_argc = method_getNumberOfArguments(method) - 2;
 	if (real_argc < argc) {
 	    const size_t s = strlen(types);
@@ -2250,12 +2266,19 @@
 	}
 	else {
 	    // Method is not found...
-	    const char *selname = (const char *)sel;
-	    size_t selname_len = strlen(selname);
 
+	    // Does the receiver implements -forwardInvocation:?
+	    if (can_forwardInvocation(self, sel)) {
+		fill_ocache(cache, self, klass, (IMP)objc_msgSend, sel, NULL,
+			argc);
+		goto dispatch;
+	    }
+
 	    // Let's see if are not trying to call a Ruby method that accepts
 	    // a regular argument then a optional Hash argument, to be
 	    // compatible with the Ruby specification.
+	    const char *selname = (const char *)sel;
+	    size_t selname_len = strlen(selname);
 	    if (argc > 1) {
 		const char *p = strchr(selname, ':');
 		if (p != NULL && p + 1 != '\0') {
@@ -2331,6 +2354,7 @@
 	}
     }
 
+dispatch:
     if (cache->flag == MCACHE_RCALL) {
 	if (rcache.klass != klass) {
 	    goto recache;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090611/4b31c78a/attachment.html>


More information about the macruby-changes mailing list