[macruby-changes] [1407] MacRuby/branches/experimental/roxor.cpp

source_changes at macosforge.org source_changes at macosforge.org
Fri Apr 10 21:19:05 PDT 2009


Revision: 1407
          http://trac.macosforge.org/projects/ruby/changeset/1407
Author:   lsansonetti at apple.com
Date:     2009-04-10 21:19:05 -0700 (Fri, 10 Apr 2009)
Log Message:
-----------
fixed bugs in the ultra lazy JIT (still a work in progress)

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

Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp	2009-04-09 23:26:11 UTC (rev 1406)
+++ MacRuby/branches/experimental/roxor.cpp	2009-04-11 04:19:05 UTC (rev 1407)
@@ -436,10 +436,35 @@
 	std::vector<jmp_buf *> return_from_block_jmp_bufs;
 
 #if ROXOR_ULTRA_LAZY_JIT
-	std::map<Class, std::map<SEL, rb_vm_method_source_t *> *>
+	std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
 	    method_sources;
+	std::multimap<Class, SEL> method_source_sels;
+
+	std::map<Class, rb_vm_method_source_t *> *
+	method_sources_for_sel(SEL sel, bool create)
+	{
+	    std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>::iterator
+		iter = method_sources.find(sel);
+		
+	    std::map<Class, rb_vm_method_source_t *> *map = NULL;
+	    if (iter == method_sources.end()) {
+		if (!create) {
+		    return NULL;
+		}
+		map = new std::map<Class, rb_vm_method_source_t *>();
+		method_sources[sel] = map;
+	    }
+	    else {
+		map = iter->second;
+	    }
+	    return map;
+	}
 #endif
 
+#if ROXOR_VM_DEBUG
+	long functions_compiled;
+#endif
+
 	RoxorVM(void);
 
 	IMP compile(Function *func);
@@ -2219,6 +2244,10 @@
     previous_block = NULL;
     parse_in_eval = false;
 
+#if ROXOR_VM_DEBUG
+    functions_compiled = 0;
+#endif
+
     load_path = rb_ary_new();
     rb_objc_retain((void *)load_path);
     loaded_features = rb_ary_new();
@@ -2282,6 +2311,10 @@
 	func, elapsedNano);
 #endif
 
+#if ROXOR_VM_DEBUG
+    functions_compiled++;
+#endif
+
     return imp;
 }
 
@@ -5107,35 +5140,9 @@
 }
 
 #if ROXOR_ULTRA_LAZY_JIT
-static bool
-rb_vm_resolve_method(Class klass, SEL sel)
+static void
+resolve_method(Class klass, SEL sel, rb_vm_method_source_t *m)
 {
-    //printf("rb_vm_resolve_method %s (%p) %s\n",class_getName(klass),klass,(char*)sel);
-    rb_vm_method_source_t *m = NULL;
-    std::map<SEL, rb_vm_method_source_t *> *dict = NULL;
-
-    while (true) {
-	std::map<Class, std::map<SEL, rb_vm_method_source_t *> *>::iterator
-	    iter = GET_VM()->method_sources.find(klass);
-
-	if (iter != GET_VM()->method_sources.end()) {
-	    dict = iter->second;
-	    std::map<SEL, rb_vm_method_source_t *>::iterator iter2 =
-		dict->find(sel);
-
-	    if (iter2 != dict->end()) {
-		m = iter2->second;
-		break;
-	    }
-	}
-	klass = class_getSuperclass(klass);
-	if (klass == NULL) {
-	    return false;
-	}
-    }
-
-    //printf("LLVM func %p\n",m->func);
-
     IMP imp = GET_VM()->compile(m->func);
 
     const int oc_arity = rb_vm_node_arity(m->node).real;
@@ -5150,11 +5157,59 @@
     types[3 + oc_arity] = '\0';
 
     GET_VM()->add_method(klass, sel, imp, m->node, types);
+} 
 
-    dict->erase(sel);
-    free(m);
+static bool
+rb_vm_resolve_method(Class klass, SEL sel)
+{
+    if (!GET_VM()->is_running()) {
+	return false;
+    }
 
-    return true;
+#if ROXOR_VM_DEBUG
+    printf("resolving %c[%s %s]\n",
+	class_isMetaClass(klass) ? '+' : '-',
+	class_getName(klass),
+	sel_getName(sel));
+#endif
+
+    std::map<Class, rb_vm_method_source_t *> *map =
+	GET_VM()->method_sources_for_sel(sel, false);
+    if (map == NULL) {
+	return false;
+    }
+
+    // Find the class where the method should be defined.
+    while (map->find(klass) == map->end() && klass != NULL) {
+	klass = class_getSuperclass(klass);
+    }
+    if (klass == NULL) {
+	return false;
+    }
+
+    // Now let's resolve all methods of the given name on the given class
+    // and superclasses.
+    bool did_something = false;
+    std::map<Class, rb_vm_method_source_t *>::iterator iter = map->begin();
+    while (iter != map->end()) {
+	Class k = iter->first;
+	while (k != klass && k != NULL) {
+	    k = class_getSuperclass(k);
+	}
+
+	if (k != NULL) {
+	    rb_vm_method_source_t *m = iter->second;
+	    resolve_method(iter->first, sel, m);
+	    map->erase(iter++);
+	    free(m);
+	    did_something = true;
+	}
+	else {
+	    ++iter;
+	}
+    }
+
+    return did_something;
 }
 #endif
 
@@ -5168,19 +5223,6 @@
 
 #if ROXOR_ULTRA_LAZY_JIT
 
-    // Let's keep the LLVM function and JIT it later.
-    std::map<Class, std::map<SEL, rb_vm_method_source_t *> *>::iterator iter = 
-	GET_VM()->method_sources.find(klass);
-    std::map<SEL, rb_vm_method_source_t *> *dict;
-
-    if (iter == GET_VM()->method_sources.end()) {
-	dict = new std::map< SEL, rb_vm_method_source_t *>();
-	GET_VM()->method_sources[klass] = dict;
-    }
-    else {
-	dict = iter->second;
-    }
-
     const rb_vm_arity_t arity = rb_vm_node_arity(node);
     const char *sel_name = sel_getName(sel);
     const bool genuine_selector = sel_name[strlen(sel_name) - 1] == ':';
@@ -5191,12 +5233,14 @@
 prepare_method:
 
     if (class_getInstanceMethod(klass, sel) != NULL) {
+	// The method already exists - we need to JIT it.
 	if (imp == NULL) {
 	    imp = GET_VM()->compile(func);
 	}
 	rb_vm_define_method(klass, sel, imp, node, true);
     }
     else {
+	// Let's keep the method and JIT it later on demand.
 #if ROXOR_VM_DEBUG
 	printf("preparing %c[%s %s] with LLVM func %p node %p\n",
 		class_isMetaClass(klass) ? '+' : '-',
@@ -5206,21 +5250,26 @@
 		node);
 #endif
 
-	std::map<SEL, rb_vm_method_source_t *>::iterator iter2 =
-	    dict->find(sel);
+	std::map<Class, rb_vm_method_source_t *> *map =
+	    GET_VM()->method_sources_for_sel(sel, true);
+
+	std::map<Class, rb_vm_method_source_t *>::iterator iter =
+	    map->find(klass);
+
 	rb_vm_method_source_t *m = NULL;
-	if (iter2 == dict->end()) {
+	if (iter == map->end()) {
 	    m = (rb_vm_method_source_t *)malloc(sizeof(rb_vm_method_source_t));
-	    dict->insert(std::make_pair(sel, m));
+	    map->insert(std::make_pair(klass, m));
+	    GET_VM()->method_source_sels.insert(std::make_pair(klass, sel));
 	}
 	else {
-	    m = iter2->second;
+	    m = iter->second;
 	}
 
 	m->func = func;
 	m->node = node;
     }
-    
+
     if (!redefined) {
 	if (!genuine_selector && arity.max != arity.min) {
 	    char buf[100];
@@ -5282,33 +5331,35 @@
     }
 
 #if ROXOR_ULTRA_LAZY_JIT
-    std::map<Class, std::map<SEL, rb_vm_method_source_t *> *>::iterator
-	iter = GET_VM()->method_sources.find(from_class);
+    std::multimap<Class, SEL>::iterator iter =
+	GET_VM()->method_source_sels.find(from_class);
 
-    if (iter != GET_VM()->method_sources.end()) {
-	std::map<SEL, rb_vm_method_source_t *> *from_dict = iter->second;
-
-	std::map<Class, std::map<SEL, rb_vm_method_source_t *> *>::iterator
-	    iter2 = GET_VM()->method_sources.find(to_class);
+    if (iter != GET_VM()->method_source_sels.end()) {
+	std::multimap<Class, SEL>::iterator last =
+	    GET_VM()->method_source_sels.upper_bound(from_class);
+	for (; iter != last; ++iter) {
+	    SEL sel = iter->second;
 	
-	std::map<SEL, rb_vm_method_source_t *> *to_dict;
-	if (iter2 == GET_VM()->method_sources.end()) {
-	    to_dict = new std::map< SEL, rb_vm_method_source_t *>();
-	    GET_VM()->method_sources[to_class] = to_dict;
-	}
-	else {
-	    to_dict = iter2->second;	
-	}
+	    std::map<Class, rb_vm_method_source_t *> *dict =
+		GET_VM()->method_sources_for_sel(sel, false);
 
-	for (std::map<SEL, rb_vm_method_source_t *>::iterator i = 
-		from_dict->begin(); i != from_dict->end(); ++i) {
-	    rb_vm_method_source_t *m = (rb_vm_method_source_t *)malloc(
-		    sizeof(rb_vm_method_source_t));
-	    m->func = i->second->func;
-	    m->node = i->second->node;
-	    to_dict->insert(std::make_pair(i->first, m));
+	    if (dict == NULL) {
+		continue;
+	    }
+
+	    std::map<Class, rb_vm_method_source_t *>::iterator
+		iter2 = dict->find(from_class);
+	    if (iter2 == dict->end()) {
+		continue;
+	    }
+
+	    rb_vm_method_source_t *m = (rb_vm_method_source_t *)
+		malloc(sizeof(rb_vm_method_source_t));
+	    m->func = iter2->second->func;
+	    m->node = iter2->second->node;
+	    dict->insert(std::make_pair(to_class, m));
 	}
-    }
+    } 
 #endif
 }
 
@@ -5658,7 +5709,8 @@
 
 #if ROXOR_VM_DEBUG
     printf("locating super method %s of class %s in ancestor chain %s\n", 
-	    sel_getName(sel), rb_class2name(klass), RSTRING_PTR(rb_inspect(ary)));
+	    sel_getName(sel), rb_class2name(klass),
+	    RSTRING_PTR(rb_inspect(ary)));
     printf("callstack: ");
     for (i = callstack_n - 1; i >= 0; i--) {
 	printf("%p ", callstack[i]);
@@ -5676,37 +5728,35 @@
         }
         if (klass_located) {
             if (i < count - 1) {
-		VALUE tmp;
-		Method method;
-
                 k = RARRAY_AT(ary, i + 1);
 
-		tmp = RCLASS_SUPER(k);
-		RCLASS_SUPER(k) = 0;
-		method = class_getInstanceMethod((Class)k, sel);
-		RCLASS_SUPER(k) = tmp;
+		Method method = class_getInstanceMethod((Class)k, sel);
+		VALUE super = RCLASS_SUPER(k);
 
-		if (method != NULL) {
-		    IMP imp = method_getImplementation(method);
+		if (method == NULL || (super != 0
+		    && class_getInstanceMethod((Class)super, sel) == method)) {
+		    continue;
+		}
 
-		    bool on_stack = false;
-		    for (int j = callstack_n - 1; j >= 0; j--) {
-			void *start = NULL;
-			if (GET_VM()->symbolize_call_address(callstack[j],
-				    &start, NULL, NULL, 0)) {
-			    if (start == (void *)imp) {
-				on_stack = true;
-				break;
-			    }
+		IMP imp = method_getImplementation(method);
+
+		bool on_stack = false;
+		for (int j = callstack_n - 1; j >= 0; j--) {
+		    void *start = NULL;
+		    if (GET_VM()->symbolize_call_address(callstack[j],
+				&start, NULL, NULL, 0)) {
+			if (start == (void *)imp) {
+			    on_stack = true;
+			    break;
 			}
 		    }
+		}
 
-		    if (!on_stack) {
+		if (!on_stack) {
 #if ROXOR_VM_DEBUG
-			printf("returning method implementation from class/module %s\n", rb_class2name(k));
+		    printf("returning method implementation from class/module %s\n", rb_class2name(k));
 #endif
-			return method;
-		    }
+		    return method;
 		}
             }
         }
@@ -5866,12 +5916,13 @@
 	}
 
 #if ROXOR_VM_DEBUG
-	printf("ruby dispatch %c[<%s %p> %s] (imp=%p, cached=%s)\n",
+	printf("ruby dispatch %c[<%s %p> %s] (imp=%p, node=%p, cached=%s)\n",
 		class_isMetaClass(klass) ? '+' : '-',
 		class_getName(klass),
 		(void *)self,
 		sel_getName(sel),
 		rcache.imp,
+		rcache.node,
 		cached ? "true" : "false");
 #endif
 
@@ -7169,4 +7220,8 @@
     RoxorCompiler::module->dump();
     printf("------------------------------------------------------\n");
 #endif
+#if ROXOR_VM_DEBUG
+    printf("functions all=%ld compiled=%ld\n", RoxorCompiler::module->size(),
+	    GET_VM()->functions_compiled);
+#endif
 }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090410/2652cee5/attachment-0001.html>


More information about the macruby-changes mailing list