[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