[macruby-changes] [2017] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Sat Jul 11 20:36:08 PDT 2009


Revision: 2017
          http://trac.macosforge.org/projects/ruby/changeset/2017
Author:   lsansonetti at apple.com
Date:     2009-07-11 20:36:07 -0700 (Sat, 11 Jul 2009)
Log Message:
-----------
AOT compiler: now supporting objc stubs and super dispatch

Modified Paths:
--------------
    MacRuby/branches/experimental/compiler.cpp
    MacRuby/branches/experimental/compiler.h
    MacRuby/branches/experimental/vm.cpp
    MacRuby/branches/experimental/vm.h

Modified: MacRuby/branches/experimental/compiler.cpp
===================================================================
--- MacRuby/branches/experimental/compiler.cpp	2009-07-11 09:36:55 UTC (rev 2016)
+++ MacRuby/branches/experimental/compiler.cpp	2009-07-12 03:36:07 UTC (rev 2017)
@@ -453,27 +453,27 @@
 Value *
 RoxorAOTCompiler::compile_mcache(SEL sel, bool super)
 {
-    GlobalVariable *gvar;
     if (super) {
-	abort(); // TODO
+	char buf[100];
+	snprintf(buf, sizeof buf, "__super__:%s", sel_getName(sel));
+        sel = sel_registerName(buf);
     }
+
+    GlobalVariable *gvar;
+    std::map<SEL, GlobalVariable *>::iterator iter = mcaches.find(sel);
+    if (iter == mcaches.end()) {
+	gvar = new GlobalVariable(
+		PtrTy,
+		false,
+		GlobalValue::InternalLinkage,
+		Constant::getNullValue(PtrTy),
+		"",
+		RoxorCompiler::module);
+	assert(gvar != NULL);
+	mcaches[sel] = gvar;
+    }
     else {
-	std::map<SEL, GlobalVariable *>::iterator iter =
-	    mcaches.find(sel);
-	if (iter == mcaches.end()) {
-	    gvar = new GlobalVariable(
-		    PtrTy,
-		    false,
-		    GlobalValue::InternalLinkage,
-		    Constant::getNullValue(PtrTy),
-		    "",
-		    RoxorCompiler::module);
-	    assert(gvar != NULL);
-	    mcaches[sel] = gvar;
-	}
-	else {
-	    gvar = iter->second;
-	}
+	gvar = iter->second;
     }
     return new LoadInst(gvar, "", bb);
 }
@@ -532,18 +532,27 @@
 	: new LoadInst(gvar, "");
 }
 
+inline Value *
+RoxorCompiler::compile_arity(rb_vm_arity_t &arity)
+{
+    uint64_t v;
+    assert(sizeof(uint64_t) == sizeof(rb_vm_arity_t));
+    memcpy(&v, &arity, sizeof(rb_vm_arity_t));
+    return ConstantInt::get(Type::Int64Ty, v);
+}
+
 void
 RoxorCompiler::compile_prepare_method(Value *classVal, Value *sel,
 	Function *new_function, rb_vm_arity_t &arity, NODE *body)
 {
     if (prepareMethodFunc == NULL) {
 	// void rb_vm_prepare_method(Class klass, SEL sel,
-	//			     Function *f, NODE *node);
+	//	Function *func, rb_vm_arity_t arity, int flags)
 	prepareMethodFunc = 
 	    cast<Function>(module->getOrInsertFunction(
 			"rb_vm_prepare_method",
 			Type::VoidTy, RubyObjTy, PtrTy, PtrTy,
-			PtrTy, NULL));
+			Type::Int64Ty, Type::Int32Ty, NULL));
     }
 
     std::vector<Value *> params;
@@ -553,28 +562,20 @@
 
     params.push_back(compile_const_pointer(new_function));
     rb_objc_retain((void *)body);
-    params.push_back(compile_const_pointer(body));
+    params.push_back(compile_arity(arity));
+    params.push_back(ConstantInt::get(Type::Int32Ty, rb_vm_node_flags(body)));
 
     CallInst::Create(prepareMethodFunc, params.begin(),
 	    params.end(), "", bb);
 }
 
-inline Value *
-RoxorCompiler::compile_arity(rb_vm_arity_t &arity)
-{
-    uint64_t v;
-    assert(sizeof(uint64_t) == sizeof(rb_vm_arity_t));
-    memcpy(&v, &arity, sizeof(rb_vm_arity_t));
-    return ConstantInt::get(Type::Int64Ty, v);
-}
-
 void
 RoxorAOTCompiler::compile_prepare_method(Value *classVal, Value *sel,
 	Function *new_function, rb_vm_arity_t &arity, NODE *body)
 {
     if (prepareMethodFunc == NULL) {
-	// void rb_vm_prepare_method2(Class klass, SEl sel, IMP imp,
-	//			      rb_vm_arity_t arity, int flags);
+	// void rb_vm_prepare_method2(Class klass, SEL sel,
+	//	IMP ruby_imp, rb_vm_arity_t arity, int flags)
 	prepareMethodFunc = 
 	    cast<Function>(module->getOrInsertFunction(
 			"rb_vm_prepare_method2",
@@ -5995,8 +5996,11 @@
 }
 
 Function *
-RoxorCompiler::compile_objc_stub(Function *ruby_func, const char *types)
+RoxorCompiler::compile_objc_stub(Function *ruby_func, IMP ruby_imp,
+	const rb_vm_arity_t &arity, const char *types)
 {
+    assert(ruby_func != NULL || ruby_imp != NULL);
+
     char buf[100];
     const char *p = types;
     std::vector<const Type *> f_types;
@@ -6026,7 +6030,7 @@
     // Arguments.
     std::vector<std::string> arg_types;
     std::vector<unsigned int> byval_args;
-    for (unsigned int i = 0; i < ruby_func->arg_size() - 2; i++) {
+    for (int i = 0; i < arity.real; i++) {
 	p = GetFirstType(p, buf, sizeof buf);
 	const Type *t = convert_type(buf);
 	if (GET_CORE()->is_large_struct_type(t)) {
@@ -6064,20 +6068,37 @@
     params.push_back(arg++); // sel
 
     // Convert every incoming argument into Ruby type.
-    for (unsigned int i = 0; i < ruby_func->arg_size() - 2; i++) {
+    for (int i = 0; i < arity.real; i++) {
 	Value *a = arg++;
 	if (std::find(byval_args.begin(), byval_args.end(), i + 3 + sret_i)
-	    != byval_args.end()) {
-	     a = new LoadInst(a, "", bb);
+		!= byval_args.end()) {
+	    a = new LoadInst(a, "", bb);
 	}
 	Value *ruby_arg = compile_conversion_to_ruby(arg_types[i].c_str(),
 		f_types[i + 2 + sret_i], a);
 	params.push_back(ruby_arg);
     }
 
+    // Create the Ruby implementation type (unless it's already provided).
+    Value *imp;
+    if (ruby_func == NULL) {
+	std::vector<const Type *> ruby_func_types;
+	ruby_func_types.push_back(RubyObjTy);
+	ruby_func_types.push_back(PtrTy);
+	for (int i = 0; i < arity.real; i++) {
+	    ruby_func_types.push_back(RubyObjTy);
+	}
+	FunctionType *ft = FunctionType::get(RubyObjTy, ruby_func_types, false);
+	imp = new BitCastInst(compile_const_pointer((void *)ruby_imp),
+		PointerType::getUnqual(ft), "", bb);
+    }
+    else {
+	imp = ruby_func;
+    }
+
     // Call the Ruby implementation.
-    Value *ret_val = CallInst::Create(ruby_func, params.begin(),
-	    params.end(), "", bb);
+    Value *ret_val = CallInst::Create(imp, params.begin(), params.end(),
+	    "", bb);
 
     // Convert the return value into Objective-C type (if any).
     if (f_ret_type != Type::VoidTy) {

Modified: MacRuby/branches/experimental/compiler.h
===================================================================
--- MacRuby/branches/experimental/compiler.h	2009-07-11 09:36:55 UTC (rev 2016)
+++ MacRuby/branches/experimental/compiler.h	2009-07-12 03:36:07 UTC (rev 2017)
@@ -49,7 +49,8 @@
 	Function *compile_ffi_function(void *stub, void *imp, int argc);
 	Function *compile_to_rval_convertor(const char *type);
 	Function *compile_to_ocval_convertor(const char *type);
-	Function *compile_objc_stub(Function *ruby_func, const char *types);
+	Function *compile_objc_stub(Function *ruby_func, IMP ruby_imp,
+		const rb_vm_arity_t &arity, const char *types);
 	Function *compile_block_caller(rb_vm_block_t *block);
 
 	const Type *convert_type(const char *type);

Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp	2009-07-11 09:36:55 UTC (rev 2016)
+++ MacRuby/branches/experimental/vm.cpp	2009-07-12 03:36:07 UTC (rev 2017)
@@ -1269,32 +1269,30 @@
 }
 
 rb_vm_method_node_t *
-RoxorCore::resolve_method(Class klass, SEL sel, Function *func, NODE *node,
-	IMP imp, Method m)
+RoxorCore::resolve_method(Class klass, SEL sel, Function *func,
+	const rb_vm_arity_t &arity, int flags, IMP imp, Method m)
 {
-    const int oc_arity = rb_vm_node_arity(node).real + 3;
+    if (imp == NULL) {
+	assert(func != NULL);
+	imp = compile(func);
+    }
 
+    const int oc_arity = arity.real + 3;
     char types[100];
     resolve_method_type(types, sizeof types, klass, m, sel, oc_arity);
 
-    std::map<Function *, IMP>::iterator iter = objc_to_ruby_stubs.find(func);
+    std::map<IMP, IMP>::iterator iter = objc_to_ruby_stubs.find(imp);
     IMP objc_imp;
     if (iter == objc_to_ruby_stubs.end()) {
 	Function *objc_func = RoxorCompiler::shared->compile_objc_stub(func,
-		types);
+		imp, arity, types);
 	objc_imp = compile(objc_func);
-	objc_to_ruby_stubs[func] = objc_imp;
+	objc_to_ruby_stubs[imp] = objc_imp;
     }
     else {
 	objc_imp = iter->second;
     }
 
-    if (imp == NULL) {
-	imp = compile(func);
-    }
-
-    const rb_vm_arity_t arity = rb_vm_node_arity(node);
-    const int flags = rb_vm_node_flags(node);
     return add_method(klass, sel, objc_imp, imp, arity, flags, types);
 }
 
@@ -1312,7 +1310,8 @@
 
 	if (k != NULL) {
 	    rb_vm_method_source_t *m = iter->second;
-	    resolve_method(iter->first, sel, m->func, m->node, NULL, NULL);
+	    resolve_method(iter->first, sel, m->func, m->arity, m->flags,
+		    NULL, NULL);
 	    map->erase(iter++);
 	    free(m);
 	    did_something = true;
@@ -1367,15 +1366,15 @@
 }
 
 void
-RoxorCore::prepare_method(Class klass, SEL sel, Function *func, NODE *node)
+RoxorCore::prepare_method(Class klass, SEL sel, Function *func,
+	const rb_vm_arity_t &arity, int flags)
 {
 #if ROXOR_VM_DEBUG
-    printf("preparing %c[%s %s] with LLVM func %p node %p\n",
+    printf("preparing %c[%s %s] with LLVM func %p\n",
 	    class_isMetaClass(klass) ? '+' : '-',
 	    class_getName(klass),
 	    sel_getName(sel),
-	    func,
-	    node);
+	    func);
 #endif
 
     std::map<Class, rb_vm_method_source_t *> *map =
@@ -1394,12 +1393,13 @@
     }
 
     m->func = func;
-    m->node = node;
+    m->arity = arity;
+    m->flags = flags;
 }
 
-extern "C"
-void
-rb_vm_prepare_method(Class klass, SEL sel, Function *func, NODE *node)
+static void
+prepare_method(Class klass, SEL sel, void *data,
+	const rb_vm_arity_t &arity, int flags, bool precompiled)
 {
     Class k = GET_VM()->get_current_class();
     if (k != NULL) {
@@ -1410,7 +1410,6 @@
 	}
     }
 
-    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] == ':';
     bool redefined = false;
@@ -1421,16 +1420,23 @@
 prepare_method:
 
     m = class_getInstanceMethod(klass, sel);
-    if (m != NULL) {
-	// The method already exists - we need to JIT it.
-	if (imp == NULL) {
-	    imp = GET_CORE()->compile(func);
-	}
-	GET_CORE()->resolve_method(klass, sel, func, node, imp, m);
+    if (precompiled) {
+	imp = (IMP)data;
+	GET_CORE()->resolve_method(klass, sel, NULL, arity, flags, imp, m);
     }
     else {
-	// Let's keep the method and JIT it later on demand.
-	GET_CORE()->prepare_method(klass, sel, func, node);
+	Function *func = (Function *)data;
+	if (m != NULL) {
+	    // The method already exists - we need to JIT it.
+	    if (imp == NULL) {
+		imp = GET_CORE()->compile(func);
+	    }
+	    GET_CORE()->resolve_method(klass, sel, func, arity, flags, imp, m);
+	}
+	else {
+	    // Let's keep the method and JIT it later on demand.
+	    GET_CORE()->prepare_method(klass, sel, func, arity, flags);
+	}
     }
 
     if (!redefined) {
@@ -1460,24 +1466,32 @@
 	    int i, count = RARRAY_LEN(included_in_classes);
 	    for (i = 0; i < count; i++) {
 		VALUE mod = RARRAY_AT(included_in_classes, i);
-		rb_vm_prepare_method((Class)mod, orig_sel, func, node);
+		prepare_method((Class)mod, orig_sel, data, arity, flags,
+			precompiled);
 	    }
 	}
     }
 }
 
-static void __rb_vm_define_method(Class klass, SEL sel, IMP objc_imp,
-	IMP ruby_imp, const rb_vm_arity_t &arity, int flags, bool direct);
+extern "C"
+void
+rb_vm_prepare_method(Class klass, SEL sel, Function *func,
+	const rb_vm_arity_t arity, int flags)
+{
+    prepare_method(klass, sel, (void *)func, arity, flags, false);
+}
 
 extern "C"
 void
-rb_vm_prepare_method2(Class klass, SEL sel, IMP imp, rb_vm_arity_t arity,
-		      int flags)
+rb_vm_prepare_method2(Class klass, SEL sel, IMP ruby_imp,
+	const rb_vm_arity_t arity, int flags)
 {
-    // TODO: create objc_imp
-    __rb_vm_define_method(klass, sel, imp, imp, arity, flags, false);
+    prepare_method(klass, sel, (void *)ruby_imp, arity, flags, true);
 }
 
+static void __rb_vm_define_method(Class klass, SEL sel, IMP objc_imp,
+	IMP ruby_imp, const rb_vm_arity_t &arity, int flags, bool direct);
+
 #define VISI(x) ((x)&NOEX_MASK)
 #define VISI_CHECK(x,f) (VISI(x) == (f))
 
@@ -1567,6 +1581,7 @@
     GET_CORE()->get_methods(ary, (Class)mod, include_objc_methods, filter);
 }
 
+#if 0
 extern "C"
 GenericValue
 lle_X_rb_vm_prepare_method(const FunctionType *FT,
@@ -1584,6 +1599,7 @@
     GV.IntVal = 0;
     return GV;
 }
+#endif
 
 extern "C"
 void
@@ -1663,7 +1679,8 @@
 	    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;
+	    m->arity = iter2->second->arity;
+	    m->flags = iter2->second->flags;
 	    dict->insert(std::make_pair(to_class, m));
 	    sels_to_add.push_back(sel);
 	}
@@ -1733,22 +1750,14 @@
     if (read) {
 	Function *f = RoxorCompiler::shared->compile_read_attr(iname);
 	SEL sel = sel_registerName(name);
-	NODE *node = NEW_CFUNC(NULL, 0);
-	NODE *body = NEW_FBODY(NEW_METHOD(node, klass, noex), 0);
-	rb_objc_retain(body);
-
-	rb_vm_prepare_method(klass, sel, f, body);
+	rb_vm_prepare_method(klass, sel, f, rb_vm_arity(0), NODE_FBODY);
     }
 
     if (write) {
 	Function *f = RoxorCompiler::shared->compile_write_attr(iname);
 	snprintf(buf, sizeof buf, "%s=:", name);
 	SEL sel = sel_registerName(buf);
-	NODE *node = NEW_CFUNC(NULL, 1);
-	NODE *body = NEW_FBODY(NEW_METHOD(node, klass, noex), 0);
-	rb_objc_retain(body);
-
-	rb_vm_prepare_method(klass, sel, f, body);
+	rb_vm_prepare_method(klass, sel, f, rb_vm_arity(1), NODE_FBODY);
     }
 }
 

Modified: MacRuby/branches/experimental/vm.h
===================================================================
--- MacRuby/branches/experimental/vm.h	2009-07-11 09:36:55 UTC (rev 2016)
+++ MacRuby/branches/experimental/vm.h	2009-07-12 03:36:07 UTC (rev 2017)
@@ -438,7 +438,8 @@
 
 typedef struct {
     Function *func;
-    NODE *node;
+    rb_vm_arity_t arity;
+    int flags;
 } rb_vm_method_source_t;
 
 typedef VALUE rb_vm_objc_stub_t(IMP imp, id self, SEL sel, int argc,
@@ -538,7 +539,7 @@
 	// Maps to cache compiled stubs for a given Objective-C runtime type.
 	std::map<std::string, void *> c_stubs, objc_stubs,
 	    to_rval_convertors, to_ocval_convertors;
-	std::map<Function *, IMP> objc_to_ruby_stubs;
+	std::map<IMP, IMP> objc_to_ruby_stubs;
 
 	// Caches for the lazy JIT.
 	std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
@@ -643,12 +644,14 @@
 	struct mcache *method_cache_get(SEL sel, bool super);
 	rb_vm_method_node_t *method_node_get(IMP imp);
 
-	void prepare_method(Class klass, SEL sel, Function *func, NODE *node);
+	void prepare_method(Class klass, SEL sel, Function *func,
+		const rb_vm_arity_t &arity, int flag);
 	rb_vm_method_node_t *add_method(Class klass, SEL sel, IMP imp,
 		IMP ruby_imp, const rb_vm_arity_t &arity, int flags,
 		const char *types);
 	rb_vm_method_node_t *resolve_method(Class klass, SEL sel,
-		Function *func, NODE *node, IMP imp, Method m);
+		Function *func, const rb_vm_arity_t &arity, int flags,
+		IMP imp, Method m);
 	bool resolve_methods(std::map<Class, rb_vm_method_source_t *> *map,
 		Class klass, SEL sel);
 	void copy_methods(Class from_class, Class to_class);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090711/dacd7d9c/attachment-0001.html>


More information about the macruby-changes mailing list