[macruby-changes] [2741] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Tue Oct 6 16:55:43 PDT 2009
Revision: 2741
http://trac.macosforge.org/projects/ruby/changeset/2741
Author: lsansonetti at apple.com
Date: 2009-10-06 16:55:43 -0700 (Tue, 06 Oct 2009)
Log Message:
-----------
now honoring the sel_of_type BridgeSupport attribute
Modified Paths:
--------------
MacRuby/trunk/bridgesupport.cpp
MacRuby/trunk/dispatcher.cpp
MacRuby/trunk/vm.cpp
MacRuby/trunk/vm.h
Modified: MacRuby/trunk/bridgesupport.cpp
===================================================================
--- MacRuby/trunk/bridgesupport.cpp 2009-10-06 21:14:36 UTC (rev 2740)
+++ MacRuby/trunk/bridgesupport.cpp 2009-10-06 23:55:43 UTC (rev 2741)
@@ -1093,13 +1093,12 @@
}
}
#endif
-#if 0
- static bool R6401816_fixed = false;
- /* XXX work around for <rdar://problem/6401816> -[NSObject performSelector:withObject:] has wrong sel_of_type attributes*/
- if (!R6401816_fixed) {
- bs_element_method_t *bs_method =
- rb_bs_find_method((Class)rb_cNSObject,
- @selector(performSelector:withObject:));
+ static bool R7281806fixed = false;
+ // XXX work around for
+ // <rdar://problem/7281806> -[NSObject performSelector:] has wrong sel_of_type attributes
+ if (!R7281806fixed) {
+ bs_element_method_t *bs_method = GET_CORE()->find_bs_method((Class)rb_cNSObject,
+ sel_registerName("performSelector:"));
if (bs_method != NULL) {
bs_element_arg_t *arg = bs_method->args;
while (arg != NULL) {
@@ -1107,14 +1106,13 @@
&& arg->sel_of_type != NULL
&& arg->sel_of_type[0] != '@') {
arg->sel_of_type[0] = '@';
- R6401816_fixed = true;
+ R7281806fixed = true;
break;
}
arg++;
}
}
}
-#endif
}
extern "C"
Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp 2009-10-06 21:14:36 UTC (rev 2740)
+++ MacRuby/trunk/dispatcher.cpp 2009-10-06 23:55:43 UTC (rev 2741)
@@ -452,6 +452,25 @@
argc, true);
}
+static bool
+reinstall_method_maybe(Class klass, SEL sel, const char *types)
+{
+ Method m = class_getInstanceMethod(klass, sel);
+ if (m == NULL) {
+ return false;
+ }
+
+ rb_vm_method_node_t *node = GET_CORE()->method_node_get(m);
+ if (node == NULL) {
+ // We only do that for pure Ruby methods.
+ return false;
+ }
+
+ GET_CORE()->retype_method(klass, node, types);
+
+ return true;
+}
+
static force_inline VALUE
__rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE self, Class klass,
SEL sel, rb_vm_block_t *block, unsigned char opt, int argc,
@@ -725,7 +744,46 @@
cached ? "true" : "false");
#endif
- return (*ocache.stub)(ocache.imp, RB2OC(self), sel, argc, argv);
+ id ocrcv = RB2OC(self);
+
+ if (ocache.bs_method != NULL) {
+ for (int i = 0; i < (int)ocache.bs_method->args_count; i++) {
+ bs_element_arg_t *arg = &ocache.bs_method->args[i];
+ if (arg->sel_of_type != NULL) {
+ // BridgeSupport tells us that this argument contains a
+ // selector of the given type, but we don't have any
+ // information regarding the target. RubyCocoa and the
+ // other ObjC bridges do not really require it since they
+ // use the NSObject message forwarding mechanism, but
+ // MacRuby registers all methods in the runtime.
+ //
+ // Therefore, we apply here a naive heuristic by assuming
+ // that either the receiver or one of the arguments of this
+ // call is the future target.
+ ID arg_selid = rb_to_id(argv[i]);
+ SEL arg_sel = sel_registerName(rb_id2name(arg_selid));
+
+ if (reinstall_method_maybe(*(Class *)ocrcv, arg_sel,
+ arg->sel_of_type)) {
+ goto sel_target_found;
+ }
+ for (int j = 0; j < argc; j++) {
+ if (j != i && !SPECIAL_CONST_P(argv[j])) {
+ if (reinstall_method_maybe(*(Class *)argv[j], arg_sel,
+ arg->sel_of_type)) {
+ goto sel_target_found;
+ }
+ }
+ }
+
+sel_target_found:
+ // There can only be one sel_of_type argument.
+ break;
+ }
+ }
+ }
+
+ return (*ocache.stub)(ocache.imp, ocrcv, sel, argc, argv);
}
else if (cache->flag == MCACHE_FCALL) {
#if ROXOR_VM_DEBUG
Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp 2009-10-06 21:14:36 UTC (rev 2740)
+++ MacRuby/trunk/vm.cpp 2009-10-06 23:55:43 UTC (rev 2741)
@@ -1430,6 +1430,24 @@
}
rb_vm_method_node_t *
+RoxorCore::retype_method(Class klass, rb_vm_method_node_t *node,
+ const char *types)
+{
+ // TODO: 1) don't reinstall method in case the types didn't change
+ // 2) free LLVM machine code from old objc IMP
+
+ // Re-generate ObjC stub.
+ Function *objc_func = RoxorCompiler::shared->compile_objc_stub(NULL,
+ node->ruby_imp, node->arity, types);
+ node->objc_imp = compile(objc_func);
+ objc_to_ruby_stubs[node->ruby_imp] = node->objc_imp;
+
+ // Re-add the method.
+ return add_method(klass, node->sel, node->objc_imp, node->ruby_imp,
+ node->arity, node->flags, types);
+}
+
+rb_vm_method_node_t *
RoxorCore::resolve_method(Class klass, SEL sel, Function *func,
const rb_vm_arity_t &arity, int flags, IMP imp, Method m)
{
Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h 2009-10-06 21:14:36 UTC (rev 2740)
+++ MacRuby/trunk/vm.h 2009-10-06 23:55:43 UTC (rev 2741)
@@ -689,6 +689,8 @@
rb_vm_method_node_t *resolve_method(Class klass, SEL sel,
Function *func, const rb_vm_arity_t &arity, int flags,
IMP imp, Method m);
+ rb_vm_method_node_t *retype_method(Class klass,
+ rb_vm_method_node_t *node, const char *types);
void undef_method(Class klass, SEL sel);
bool resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
Class klass, SEL sel);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091006/81f8e3d7/attachment.html>
More information about the macruby-changes
mailing list