[macruby-changes] [2959] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Nov 4 18:08:58 PST 2009


Revision: 2959
          http://trac.macosforge.org/projects/ruby/changeset/2959
Author:   lsansonetti at apple.com
Date:     2009-11-04 18:08:58 -0800 (Wed, 04 Nov 2009)
Log Message:
-----------
now caching respond_to? for better performance

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

Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp	2009-11-05 02:08:24 UTC (rev 2958)
+++ MacRuby/trunk/dispatcher.cpp	2009-11-05 02:08:58 UTC (rev 2959)
@@ -1757,8 +1757,8 @@
 
 extern IMP basic_respond_to_imp; // vm_method.c
 
-static bool
-respond_to(VALUE obj, SEL sel, bool priv, bool check_override)
+bool
+RoxorCore::respond_to(VALUE obj, SEL sel, bool priv, bool check_override)
 {
     VALUE klass = CLASS_OF(obj);
 
@@ -1768,30 +1768,43 @@
 	: false;
 
     if (!overriden) {
-	// FIXME: too slow!
-	bool reject_pure_ruby_methods = false;
-	Method m = class_getInstanceMethod((Class)klass, sel);
-	if (m == NULL) {
-	    const char *selname = sel_getName(sel);
-	    sel = helper_sel(selname, strlen(selname));
-	    if (sel != NULL) {
-		m = class_getInstanceMethod((Class)klass, sel);
-		reject_pure_ruby_methods = true;
+	lock();
+	const long key = respond_to_key((Class)klass, sel);
+	std::map<long, int>::iterator iter = respond_to_cache.find(key);
+	unlock();
+	int status;
+	if (iter != respond_to_cache.end()) {
+	    status = iter->second;
+	}
+	else {
+	    Method m = class_getInstanceMethod((Class)klass, sel);
+	    if (m == NULL) {
+		const char *selname = sel_getName(sel);
+		sel = helper_sel(selname, strlen(selname));
+		if (sel != NULL) {
+		    m = class_getInstanceMethod((Class)klass, sel);
+		}
 	    }
-	}
 
-	IMP imp = method_getImplementation(m);
-	if (UNAVAILABLE_IMP(imp)) {
-	    return false;
+	    IMP imp = method_getImplementation(m);
+	    if (UNAVAILABLE_IMP(imp)) {
+		status = RESPOND_TO_NOT_EXIST;
+	    }
+	    else {
+		rb_vm_method_node_t *node = method_node_get(m);
+		if (node != NULL && (node->flags & VM_METHOD_PRIVATE)) {
+		    status = RESPOND_TO_PRIVATE;
+		}
+		else {
+		    status = RESPOND_TO_PUBLIC;
+		}
+	    }
+	    lock();
+	    respond_to_cache[key] = status;
+	    unlock();
 	}
-
-	rb_vm_method_node_t *node = GET_CORE()->method_node_get(m);
-	if (node != NULL
-	    && (reject_pure_ruby_methods
-		|| (!priv && (node->flags & VM_METHOD_PRIVATE)))) {
-	    return false;
-	}
-        return true;
+	return status == RESPOND_TO_PUBLIC
+	    || (priv && status == RESPOND_TO_PRIVATE);
     }
     else {
 	VALUE args[2];
@@ -1804,6 +1817,12 @@
     }
 }
 
+static bool
+respond_to(VALUE obj, SEL sel, bool priv, bool check_override)
+{
+    return GET_CORE()->respond_to(obj, sel, priv, check_override);
+}
+
 extern "C"
 bool
 rb_vm_respond_to(VALUE obj, SEL sel, bool priv)

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-11-05 02:08:24 UTC (rev 2958)
+++ MacRuby/trunk/vm.cpp	2009-11-05 02:08:58 UTC (rev 2959)
@@ -825,6 +825,9 @@
 	ruby_imps[ruby_imp] = node;
     }
 
+    // Invalidate respond_to cache.
+    invalidate_respond_to_cache();
+
     // Invalidate dispatch cache.
     std::map<SEL, struct mcache *>::iterator iter3 = mcache.find(sel);
     if (iter3 != mcache.end()) {
@@ -1771,6 +1774,8 @@
     m->func = func;
     m->arity = arity;
     m->flags = flags;
+
+    invalidate_respond_to_cache();
 }
 
 static void
@@ -2296,6 +2301,7 @@
 #endif
 
     class_replaceMethod((Class)klass, sel, (IMP)rb_vm_undefined_imp, "@@:");
+    invalidate_respond_to_cache();
 
 #if 0
     std::map<Method, rb_vm_method_node_t *>::iterator iter

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2009-11-05 02:08:24 UTC (rev 2958)
+++ MacRuby/trunk/vm.h	2009-11-05 02:08:58 UTC (rev 2959)
@@ -629,6 +629,12 @@
 	std::map<SEL, std::string *> bs_informal_protocol_imethods,
 	    bs_informal_protocol_cmethods;
 
+	// respond_to? cache.
+#define RESPOND_TO_NOT_EXIST	0
+#define RESPOND_TO_PUBLIC 	1
+#define RESPOND_TO_PRIVATE 	2
+	std::map<long, int> respond_to_cache;
+
 #if ROXOR_VM_DEBUG
 	long functions_compiled;
 #endif
@@ -780,6 +786,14 @@
 	void unregister_finalizer(rb_vm_finalizer_t *finalizer);
 	void call_all_finalizers(void);
 
+	long respond_to_key(Class klass, SEL sel) {
+	    return (long)klass + (long)sel;
+	}
+	void invalidate_respond_to_cache(void) {
+	    respond_to_cache.clear();
+	}
+	bool respond_to(VALUE obj, SEL sel, bool priv, bool check_override);
+
     private:
 	bool register_bs_boxed(bs_element_type_t type, void *value);
 	void register_bs_class(bs_element_class_t *bs_class);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091104/324d0e89/attachment-0001.html>


More information about the macruby-changes mailing list