[macruby-changes] [1418] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Tue Apr 14 16:45:08 PDT 2009


Revision: 1418
          http://trac.macosforge.org/projects/ruby/changeset/1418
Author:   lsansonetti at apple.com
Date:     2009-04-14 16:45:08 -0700 (Tue, 14 Apr 2009)
Log Message:
-----------
working on a new objc dispatch, marked a few methods are always_inline

Modified Paths:
--------------
    MacRuby/branches/experimental/id.c
    MacRuby/branches/experimental/id.h
    MacRuby/branches/experimental/objc.h
    MacRuby/branches/experimental/objc.m
    MacRuby/branches/experimental/roxor.cpp

Modified: MacRuby/branches/experimental/id.c
===================================================================
--- MacRuby/branches/experimental/id.c	2009-04-13 22:09:37 UTC (rev 1417)
+++ MacRuby/branches/experimental/id.c	2009-04-14 23:45:08 UTC (rev 1418)
@@ -75,6 +75,7 @@
     selSend = sel_registerName("send:");
     sel__send__ = sel_registerName("__send__:");
     selEqTilde = sel_registerName("=~:");
+    selClass = sel_registerName("class");
     selEval = sel_registerName("eval:");
     selInstanceEval = sel_registerName("instance_eval:");
     selClassEval = sel_registerName("class_eval:");

Modified: MacRuby/branches/experimental/id.h
===================================================================
--- MacRuby/branches/experimental/id.h	2009-04-13 22:09:37 UTC (rev 1417)
+++ MacRuby/branches/experimental/id.h	2009-04-14 23:45:08 UTC (rev 1418)
@@ -84,6 +84,7 @@
 extern SEL selSend;
 extern SEL sel__send__;
 extern SEL selEqTilde;
+extern SEL selClass;
 extern SEL selEval;
 extern SEL selInstanceEval;
 extern SEL selClassEval;

Modified: MacRuby/branches/experimental/objc.h
===================================================================
--- MacRuby/branches/experimental/objc.h	2009-04-13 22:09:37 UTC (rev 1417)
+++ MacRuby/branches/experimental/objc.h	2009-04-14 23:45:08 UTC (rev 1418)
@@ -14,7 +14,8 @@
 
 bs_element_method_t * rb_bs_find_method(Class klass, SEL sel);
 
-bool rb_objc_fill_sig(VALUE recv, Class klass, SEL sel, struct rb_objc_method_sig *sig, bs_element_method_t *bs_method);
+bool rb_objc_get_types(VALUE recv, Class klass, SEL sel,
+	bs_element_method_t *bs_method, char *buf, size_t buflen);
 
 VALUE rb_objc_call(VALUE recv, SEL sel, int argc, VALUE *argv);
 

Modified: MacRuby/branches/experimental/objc.m
===================================================================
--- MacRuby/branches/experimental/objc.m	2009-04-13 22:09:37 UTC (rev 1417)
+++ MacRuby/branches/experimental/objc.m	2009-04-14 23:45:08 UTC (rev 1418)
@@ -1086,18 +1086,17 @@
 static inline const char *
 SkipStackSize(const char *type)
 {
-    while ((*type >= '0') && (*type <= '9'))
+    while ((*type >= '0') && (*type <= '9')) {
 	type += 1;
+    }
     return type;
 }
 
 static inline const char *
 SkipFirstType(const char *type)
 {
-    while (1)
-    {
-        switch (*type++)
-        {
+    while (1) {
+        switch (*type++) {
             case 'O':   /* bycopy */
             case 'n':   /* in */
             case 'o':   /* out */
@@ -1418,6 +1417,7 @@
     }
 }
 
+#if 0
 VALUE
 rb_objc_call(VALUE recv, SEL sel, int argc, VALUE *argv)
 {
@@ -1432,6 +1432,7 @@
     return rb_objc_call2(recv, klass, sel, method_getImplementation(method), 
 	    &sig, NULL, argc, argv);
 }
+#endif
 
 static inline const char *
 rb_get_bs_method_type(bs_element_method_t *bs_method, int arg)
@@ -1453,65 +1454,75 @@
 }
 
 bool
-rb_objc_fill_sig(VALUE recv, Class klass, SEL sel, struct rb_objc_method_sig *sig, bs_element_method_t *bs_method)
+rb_objc_get_types(VALUE recv, Class klass, SEL sel,
+		  bs_element_method_t *bs_method, char *buf, size_t buflen)
 {
     Method method;
     const char *type;
-    char buf[100];
     unsigned i;
 
     method = class_getInstanceMethod(klass, sel);
     if (method != NULL) {
 	if (bs_method == NULL) {
-	    sig->types = method_getTypeEncoding(method);
-	    sig->argc = method_getNumberOfArguments(method);
+	    type = method_getTypeEncoding(method);
+	    assert(strlen(type) < buflen);
+	    buf[0] = '\0';
+	    do {
+		const char *type2 = SkipFirstType(type);
+		strncat(buf, type, type2 - type);
+		type = SkipStackSize(type2);
+	    }
+	    while (*type != '\0');
+	    //strlcpy(buf, method_getTypeEncoding(method), buflen);
+	    //sig->argc = method_getNumberOfArguments(method);
 	}
 	else {
 	    char buf2[100];
 	    type = rb_get_bs_method_type(bs_method, -1);
 	    if (type != NULL) {
-		strlcpy(buf, type, sizeof buf);
+		strlcpy(buf, type, buflen);
 	    }
 	    else {
 		method_getReturnType(method, buf2, sizeof buf2);
-		strlcpy(buf, buf2, sizeof buf);
+		strlcpy(buf, buf2, buflen);
 	    }
 
-	    sig->argc = method_getNumberOfArguments(method);
-	    for (i = 0; i < sig->argc; i++) {
-		if (i >= 2 && (type = rb_get_bs_method_type(bs_method, i - 2)) != NULL) {
-		    strlcat(buf, type, sizeof buf);
+	    //sig->argc = method_getNumberOfArguments(method);
+	    int argc = method_getNumberOfArguments(method);
+	    for (i = 0; i < argc; i++) {
+		if (i >= 2 && (type = rb_get_bs_method_type(bs_method, i - 2))
+			!= NULL) {
+		    strlcat(buf, type, buflen);
 		}
 		else {
 		    method_getArgumentType(method, i, buf2, sizeof(buf2));
-		    strlcat(buf, buf2, sizeof buf);
+		    strlcat(buf, buf2, buflen);
 		}
 	    }
-
-	    sig->types = (char *)sel_registerName(buf); /* unify the string */
 	}
 	return true;
     }
     else if (!SPECIAL_CONST_P(recv)) {
 	NSMethodSignature *msig = [(id)recv methodSignatureForSelector:sel];
 	if (msig != NULL) {
-	    char buf[100];
 	    unsigned i;
 
 	    type = rb_get_bs_method_type(bs_method, -1);
-	    if (type == NULL)
+	    if (type == NULL) {
 		type = [msig methodReturnType];
-	    strlcpy(buf, type, sizeof buf);
+	    }
+	    strlcpy(buf, type, buflen);
 
-	    sig->argc = [msig numberOfArguments];
-	    for (i = 0; i < sig->argc; i++) {
-		if (i < 2 || (type = rb_get_bs_method_type(bs_method, i - 2)) == NULL) {
+	    //sig->argc = [msig numberOfArguments];
+	    int argc = [msig numberOfArguments];
+	    for (i = 0; i < argc; i++) {
+		if (i < 2 || (type = rb_get_bs_method_type(bs_method, i - 2))
+			== NULL) {
 		    type = [msig getArgumentTypeAtIndex:i];
 		}
-		strlcat(buf, type, sizeof buf);
+		strlcat(buf, type, buflen);
 	    }
 
-	    sig->types = (char *)sel_registerName(buf); /* unify the string */
 	    return true;
 	}
     }

Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp	2009-04-13 22:09:37 UTC (rev 1417)
+++ MacRuby/branches/experimental/roxor.cpp	2009-04-14 23:45:08 UTC (rev 1418)
@@ -342,10 +342,8 @@
     VALUE val;
 };
 
-struct ocall_helper {
-    struct rb_objc_method_sig sig;
-    bs_element_method_t *bs_method;
-};
+typedef VALUE rb_vm_objc_stub_t(IMP imp, VALUE self, SEL sel, int argc,
+				const VALUE *argv);
 
 struct mcache {
 #define MCACHE_RCALL 0x1
@@ -362,7 +360,8 @@
 	struct {
 	    Class klass;
 	    IMP imp;
-	    struct ocall_helper *helper;
+	    bs_element_method_t *bs_method;	
+	    rb_vm_objc_stub_t *stub;
 	} ocall;
     } as;
 };
@@ -438,6 +437,8 @@
 	std::map<VALUE, rb_vm_catch_t *> catch_jmp_bufs;
 	std::vector<jmp_buf *> return_from_block_jmp_bufs;
 
+	std::map<std::string, void *> stubs;
+
 #if ROXOR_ULTRA_LAZY_JIT
 	std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
 	    method_sources;
@@ -5531,7 +5532,8 @@
     return Qnil;
 }
 
-static inline VALUE
+__attribute__((always_inline))
+static VALUE
 __rb_vm_bcall(VALUE self, VALUE dvars, IMP pimp, const rb_vm_arity_t &arity, int argc, const VALUE *argv)
 {
     if ((arity.real != argc) || (arity.max == -1)) {
@@ -5612,11 +5614,11 @@
     abort();
 }
 
-static inline VALUE
+__attribute__((always_inline))
+static VALUE
 __rb_vm_rcall(VALUE self, SEL sel, NODE *node, IMP pimp,
 	      const rb_vm_arity_t &arity, int argc, const VALUE *argv)
 {
-    // TODO investigate why this function is not inlined!
     if ((arity.real != argc) || (arity.max == -1)) {
 	VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * arity.real);
 	assert(argc >= arity.min);
@@ -5844,7 +5846,19 @@
     return rb_vm_call(obj, selMethodMissing, argc + 1, new_argv, false);
 }
 
-static inline VALUE
+static void *
+vm_gen_stub(std::string types, int argc, bool is_objc)
+{
+    std::map<std::string, void *>::iterator iter = GET_VM()->stubs.find(types);
+    if (iter != GET_VM()->stubs.end()) {
+	return iter->second;
+    }
+printf("vm_gen_stub %s\n", types.c_str());
+    return NULL;
+}
+
+__attribute__((always_inline))
+static VALUE
 __rb_vm_dispatch(struct mcache *cache, VALUE self, Class klass, SEL sel, 
 		 unsigned char opt, int argc, const VALUE *argv)
 {
@@ -5888,14 +5902,19 @@
 		cache->flag = MCACHE_OCALL;
 		ocache.klass = klass;
 		ocache.imp = imp;
-		ocache.helper = (struct ocall_helper *)malloc(
-			sizeof(struct ocall_helper));
-		ocache.helper->bs_method = rb_bs_find_method(klass, sel);
-		const bool ok = rb_objc_fill_sig(self, klass, sel, 
-			    &ocache.helper->sig, ocache.helper->bs_method);
-		if (!ok) {
+		ocache.bs_method = rb_bs_find_method(klass, sel);
+
+		char types[200];
+		if (!rb_objc_get_types(self, klass, sel, ocache.bs_method,
+				       types, sizeof types)) {
+		    printf("cannot get encoding types for %c[%s %s]\n",
+			    class_isMetaClass(klass) ? '+' : '-',
+			    class_getName(klass),
+			    sel_getName(sel));
 		    abort();
 		}
+		ocache.stub = (rb_vm_objc_stub_t *)vm_gen_stub(types, argc,
+			true);
 	    }
 	}
 	else {
@@ -5958,10 +5977,33 @@
     }
     else if (cache->flag == MCACHE_OCALL) {
 	if (ocache.klass != klass) {
-	    free(ocache.helper);
 	    goto recache;
 	}
 
+	if (sel == selClass) {
+	    if (RCLASS_META(klass)) {
+		// Because +[NSObject class] returns self.
+		return RCLASS_MODULE(self) ? rb_cModule : rb_cClass;
+	    }
+	    // Because the CF classes should be hidden, for Ruby compat.
+	    if (klass == (Class)rb_cCFString) {
+		return RSTRING_IMMUTABLE(self)
+		    ? rb_cNSString : rb_cNSMutableString;
+	    }
+	    if (klass == (Class)rb_cCFArray) {
+		return RARRAY_IMMUTABLE(self)
+		    ? rb_cNSArray : rb_cNSMutableArray;
+	    }
+	    if (klass == (Class)rb_cCFHash) {
+		return RHASH_IMMUTABLE(self)
+		    ? rb_cNSHash : rb_cNSMutableHash;
+	    }
+	    if (klass == (Class)rb_cCFSet) {
+		return RSET_IMMUTABLE(self)
+		    ? rb_cNSSet : rb_cNSMutableSet;
+	    }
+	}
+
 #if ROXOR_VM_DEBUG
 	printf("objc dispatch %c[<%s %p> %s] imp=%p (cached=%s)\n",
 		class_isMetaClass(klass) ? '+' : '-',
@@ -5972,6 +6014,7 @@
 		cached ? "true" : "false");
 #endif
 
+#if 0
 	return rb_objc_call2((VALUE)self, 
 		(VALUE)klass, 
 		sel, 
@@ -5980,6 +6023,8 @@
 		ocache.helper->bs_method, 
 		argc, 
 		(VALUE *)argv);
+#endif
+	return (*ocache.stub)(ocache.imp, self, sel, argc, argv);
     }
 #undef rcache
 #undef ocache
@@ -6303,12 +6348,8 @@
     if (super) {
 	struct mcache cache; 
 	cache.flag = 0;
-	VALUE retval = __rb_vm_dispatch(&cache, self, NULL, sel, 
-					DISPATCH_SUPER, argc, argv);
-	if (cache.flag == MCACHE_OCALL) {
-	    free(cache.as.ocall.helper);
-	}
-	return retval;
+	return  __rb_vm_dispatch(&cache, self, NULL, sel, 
+				 DISPATCH_SUPER, argc, argv);
     }
     else {
 	struct mcache *cache = GET_VM()->method_cache_get(sel, false);
@@ -7140,6 +7181,19 @@
     return Qnil; // never reached
 }
 
+static VALUE
+builtin_stub1(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
+{
+    return ((VALUE (*)(VALUE, SEL))*imp)(self, sel);
+}
+
+static void
+setup_builtin_stubs(void)
+{
+    GET_VM()->stubs.insert(std::make_pair("@@:", (void *)builtin_stub1));
+    GET_VM()->stubs.insert(std::make_pair("#@:", (void *)builtin_stub1));
+}
+
 #if ROXOR_ULTRA_LAZY_JIT
 static IMP old_resolveClassMethod_imp = NULL;
 static IMP old_resolveInstanceMethod_imp = NULL;
@@ -7172,6 +7226,8 @@
     RoxorCompiler::module = new llvm::Module("Roxor");
     RoxorVM::current = new RoxorVM();
 
+    setup_builtin_stubs();
+
 #if ROXOR_ULTRA_LAZY_JIT
     Method m;
     Class ns_object = (Class)objc_getClass("NSObject");
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090414/1805f171/attachment-0001.html>


More information about the macruby-changes mailing list