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

source_changes at macosforge.org source_changes at macosforge.org
Fri Apr 24 21:13:51 PDT 2009


Revision: 1488
          http://trac.macosforge.org/projects/ruby/changeset/1488
Author:   lsansonetti at apple.com
Date:     2009-04-24 21:13:51 -0700 (Fri, 24 Apr 2009)
Log Message:
-----------
implement C functions dispatch

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

Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp	2009-04-25 00:39:26 UTC (rev 1487)
+++ MacRuby/branches/experimental/roxor.cpp	2009-04-25 04:13:51 UTC (rev 1488)
@@ -403,10 +403,12 @@
 typedef VALUE rb_vm_objc_stub_t(IMP imp, id self, SEL sel, int argc,
 				const VALUE *argv);
 
+typedef VALUE rb_vm_c_stub_t(IMP imp, int argc, const VALUE *argv);
+
 struct mcache {
-#define MCACHE_RCALL 0x1
-#define MCACHE_OCALL 0x2
-#define MCACHE_BCALL 0x4 
+#define MCACHE_RCALL 0x1 // Ruby call
+#define MCACHE_OCALL 0x2 // Objective-C call
+#define MCACHE_FCALL 0x4 // C call
     uint8_t flag;
     union {
 	struct {
@@ -421,6 +423,11 @@
 	    bs_element_method_t *bs_method;	
 	    rb_vm_objc_stub_t *stub;
 	} ocall;
+	struct {
+	    IMP imp;
+	    bs_element_function_t *bs_function;
+	    rb_vm_c_stub_t *stub;
+	} fcall;
     } as;
 };
 
@@ -499,7 +506,7 @@
 
 	bs_parser_t *bs_parser;
 	std::map<std::string, rb_vm_bs_boxed_t *> bs_boxed;
-	std::map<ID, bs_element_function_t *> bs_funcs;
+	std::map<std::string, bs_element_function_t *> bs_funcs;
 	std::map<ID, bs_element_constant_t *> bs_consts;
 	std::map<std::string, std::map<SEL, bs_element_method_t *> *>
 	    bs_classes_class_methods, bs_classes_instance_methods;
@@ -2727,7 +2734,7 @@
 
     // Cache the method node.
     NODE *old_node = method_node_get(imp);
-    if (old_node == NULL) {
+    if (old_node == NULL && old_node != node) {
 	ruby_imps[imp] = new RoxorFunctionIMP(node, sel);
     }
 //    else {
@@ -5614,24 +5621,33 @@
 Function *
 RoxorCompiler::compile_stub(const char *types, int argc, bool is_objc)
 {
-    assert(is_objc); // for now
+    Function *f;
 
-    // VALUE stub(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
-    // {
-    //     return (*imp)(self, sel, argv[0], argv[1], ...);
-    // }
-    Function *f = cast<Function>(module->getOrInsertFunction("",
-		RubyObjTy, PtrTy, RubyObjTy, PtrTy, Type::Int32Ty, RubyObjPtrTy,
-		NULL));
+    if (is_objc) {
+	// VALUE stub(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
+	// {
+	//     return (*imp)(self, sel, argv[0], argv[1], ...);
+	// }
+	f = cast<Function>(module->getOrInsertFunction("",
+		    RubyObjTy,
+		    PtrTy, RubyObjTy, PtrTy, Type::Int32Ty, RubyObjPtrTy,
+		    NULL));
+    }
+    else {
+	// VALUE stub(IMP imp, int argc, VALUE *argv)
+	// {
+	//     return (*imp)(argv[0], argv[1], ...);
+	// }
+	f = cast<Function>(module->getOrInsertFunction("",
+		    RubyObjTy,
+		    PtrTy, Type::Int32Ty, RubyObjPtrTy,
+		    NULL));
+    }
 
     bb = BasicBlock::Create("EntryBlock", f);
 
     Function::arg_iterator arg = f->arg_begin();
     Value *imp_arg = arg++;
-    Value *self_arg = arg++;
-    Value *sel_arg = arg++;
-    /*Value *argc_arg =*/ arg++; // XXX do we really need this argument?
-    Value *argv_arg = arg++;
 
     std::vector<const Type *> f_types;
     std::vector<Value *> params;
@@ -5642,7 +5658,6 @@
     const Type *ret_type = convert_type(buf);
 
     Value *sret = NULL;
-
     if (GET_VM()->is_large_struct_type(ret_type)) {
 	// We are returning a large struct, we need to pass a pointer as the
 	// first argument to the structure data and return void to conform to
@@ -5653,16 +5668,23 @@
 	ret_type = Type::VoidTy;
     }
 
-    // self
-    p = SkipFirstType(p);
-    f_types.push_back(RubyObjTy);
-    params.push_back(self_arg);
+    if (is_objc) {
+	// self
+	p = SkipFirstType(p);
+	f_types.push_back(RubyObjTy);
+	Value *self_arg = arg++;
+	params.push_back(self_arg);
 
-    // sel
-    p = SkipFirstType(p);
-    f_types.push_back(PtrTy);
-    params.push_back(sel_arg);
+	// sel
+	p = SkipFirstType(p);
+	f_types.push_back(PtrTy);
+	Value *sel_arg = arg++;
+	params.push_back(sel_arg);
+    }
 
+    /*Value *argc_arg =*/ arg++; // XXX do we really need this argument?
+    Value *argv_arg = arg++;
+
     // Arguments.
     std::vector<int> byval_args;
     for (int i = 0; i < argc; i++) {
@@ -7033,7 +7055,7 @@
 }
 
 static void *
-vm_gen_stub(const char *types, int argc, bool is_objc)
+vm_gen_stub(std::string types, int argc, bool is_objc)
 {
     std::map<std::string, void *> &stubs = 
 	is_objc ? GET_VM()->objc_stubs : GET_VM()->c_stubs;
@@ -7044,13 +7066,23 @@
 
     //printf("generating %s stub %s argc %d\n", is_objc ? "objc" : "c", types, argc);
 
-    Function *f = RoxorCompiler::shared->compile_stub(types, argc, is_objc);
+    Function *f = RoxorCompiler::shared->compile_stub(types.c_str(), argc,
+	    is_objc);
     void *stub = (void *)GET_VM()->compile(f);
     stubs.insert(std::make_pair(types, stub));
 
     return stub;
 }
 
+static inline void
+vm_gen_bs_func_types(bs_element_function_t *bs_func, std::string &types)
+{
+    types.append(bs_func->retval == NULL ? "v" : bs_func->retval->type);
+    for (unsigned i = 0; i < bs_func->args_count; i++) {
+	types.append(bs_func->args[i].type);
+    }
+}
+
 static inline SEL
 helper_sel(SEL sel)
 {
@@ -7105,6 +7137,7 @@
 
 #define rcache cache->as.rcall
 #define ocache cache->as.ocall
+#define fcache cache->as.fcall
 
 	if (method != NULL) {
 	    IMP imp = method_getImplementation(method);
@@ -7139,6 +7172,8 @@
 	    }
 	}
 	else {
+	    // Method is not found... let's try to see if we are not given a
+	    // helper selector.
 	    SEL new_sel = helper_sel(sel);
 	    if (new_sel != NULL) {
 		Method m = class_getInstanceMethod(klass, new_sel);
@@ -7152,8 +7187,32 @@
 		}
 	    }
 
-	    // TODO bridgesupport C call?
-	    return method_missing((VALUE)self, sel, argc, argv, opt);
+	    // Then let's see if we are not trying to call a not-yet-JITed
+	    // BridgeSupport function.
+	    const char *selname = (const char *)sel;
+	    size_t selnamelen = strlen(selname);
+	    if (selname[selnamelen - 1] == ':') {
+		selnamelen--;
+	    }
+	    std::string name(selname, selnamelen);
+	    std::map<std::string, bs_element_function_t *>::iterator iter =
+		GET_VM()->bs_funcs.find(name);
+	    if (iter != GET_VM()->bs_funcs.end()) {
+		bs_element_function_t *bs_func = iter->second;
+		std::string types;
+		vm_gen_bs_func_types(bs_func, types);
+
+		cache->flag = MCACHE_FCALL;
+		fcache.bs_function = bs_func;
+		fcache.imp = (IMP)dlsym(RTLD_DEFAULT, bs_func->name);
+		assert(fcache.imp != NULL);
+		fcache.stub = (rb_vm_c_stub_t *)vm_gen_stub(types, argc,
+			false);
+	    }
+	    else {
+		// Still nothing, then let's call #method_missing.
+		return method_missing((VALUE)self, sel, argc, argv, opt);
+	    }
 	}
     }
 
@@ -7257,20 +7316,21 @@
 		cached ? "true" : "false");
 #endif
 
-#if 0
-	return rb_objc_call2((VALUE)self, 
-		(VALUE)klass, 
-		sel, 
-		ocache.imp, 
-		&ocache.helper->sig, 
-		ocache.helper->bs_method, 
-		argc, 
-		(VALUE *)argv);
-#endif
 	return (*ocache.stub)(ocache.imp, RB2OC(self), sel, argc, argv);
     }
+    else if (cache->flag == MCACHE_FCALL) {
+#if ROXOR_VM_DEBUG
+	printf("C dispatch %s() imp=%p (cached=%s)\n",
+		fcache.bs_function->name,
+		fcache.imp,
+		cached ? "true" : "false");
+#endif
+	return (*fcache.stub)(fcache.imp, argc, argv);
+    }
+
 #undef rcache
 #undef ocache
+#undef fcache
 
     printf("BOUH %s\n", (char *)sel);
     abort();
@@ -9085,9 +9145,9 @@
 	case BS_ELEMENT_FUNCTION:
 	{
 	    bs_element_function_t *bs_func = (bs_element_function_t *)value;
-	    ID name = rb_intern(bs_func->name);
+	    std::string name(bs_func->name);
 
-	    std::map<ID, bs_element_function_t *>::iterator iter =
+	    std::map<std::string, bs_element_function_t *>::iterator iter =
 		GET_VM()->bs_funcs.find(name);
 	    if (iter == GET_VM()->bs_funcs.end()) {
 		GET_VM()->bs_funcs[name] = bs_func;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090424/d31b6ed4/attachment-0001.html>


More information about the macruby-changes mailing list