[macruby-changes] [3633] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Fri Feb 26 03:11:55 PST 2010


Revision: 3633
          http://trac.macosforge.org/projects/ruby/changeset/3633
Author:   martinlagardette at apple.com
Date:     2010-02-26 03:11:53 -0800 (Fri, 26 Feb 2010)
Log Message:
-----------
Allow methods/blocks with 12+ arguments

Methods/Blocks with 0 to 11 arguments are hardcoded for faster response time. Starting 12 arguments, LLVM is used to compile a stub receiving as much arguments as needed, and the stub is then cached for later faster retrieval.

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

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2010-02-26 05:24:06 UTC (rev 3632)
+++ MacRuby/trunk/compiler.cpp	2010-02-26 11:11:53 UTC (rev 3633)
@@ -7023,6 +7023,100 @@
     return f;
 }
 
+Function *
+RoxorCompiler::compile_long_arity_stub(int argc, bool is_block)
+{
+    Function *f;
+
+    if (is_block) {
+	// VALUE stubX(IMP imp, VALUE self, SEL sel,
+	//	       VALUE dvars, rb_vm_block_t *b, int argc, VALUE *argv)
+	// {
+	//	return (*imp)(self, sel, dvars, b, argv[0], ..., argv[X - 1]);
+	// }
+	f = cast<Function>(module->getOrInsertFunction("",
+		RubyObjTy,
+		PtrTy, RubyObjTy, PtrTy,
+		RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy, NULL));
+    }
+    else {
+	// VALUE stubX(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
+	// {
+	//     return (*imp)(self, sel, argv[0], argv[1], ..., argv[X - 1]);
+	// }
+	f = cast<Function>(module->getOrInsertFunction("",
+		RubyObjTy,
+		PtrTy, RubyObjTy, PtrTy, Int32Ty, RubyObjPtrTy, NULL));
+    }
+
+    bb = BasicBlock::Create(context, "EntryBlock", f);
+
+    Function::arg_iterator arg = f->arg_begin();
+
+    Value *imp_arg = arg++;
+    Value *self_arg = arg++;
+    Value *sel_arg = arg++;
+    Value *dvars_arg;
+    Value *block_arg;
+    if (is_block) {
+	dvars_arg = arg++;
+	block_arg = arg++;
+    }
+    /*Value *argc_arg = */arg++;
+    Value *argv_arg = arg++;
+
+    std::vector<const Type *> f_types;
+    std::vector<Value *> params;
+
+    // Return type
+    const Type *ret_type = RubyObjTy;
+
+    // self
+    f_types.push_back(RubyObjTy);
+    params.push_back(self_arg);
+
+    // sel
+    f_types.push_back(PtrTy);
+    params.push_back(sel_arg);
+
+    if (is_block) {
+	// dvars
+	f_types.push_back(RubyObjTy);
+	params.push_back(dvars_arg);
+
+	// block
+	f_types.push_back(PtrTy);
+	params.push_back(block_arg);
+    }
+
+    for (int i = 0; i < argc; i++) {
+	f_types.push_back(RubyObjTy);
+
+	// Get an int
+	Value *index = ConstantInt::get(Int32Ty, i);
+	// Get the slot (aka argv[index])
+	Value *slot = GetElementPtrInst::Create(argv_arg, index, "", bb);
+	// Load the slot into memory and add it as an argument
+	Value *arg_val = new LoadInst(slot, "", bb);
+	params.push_back(arg_val);
+    }
+
+    // Get the function type, aka:    VALUE (*)(VALUE, SEL, ...)
+    FunctionType *ft = FunctionType::get(ret_type, f_types, false);
+    // Cast imp as the function type
+    Value *imp = new BitCastInst(imp_arg, PointerType::getUnqual(ft), "", bb);
+
+    // Compile call to the function
+    CallInst *imp_call = CallInst::Create(imp, params.begin(), params.end(),
+	"", bb);
+
+    // Compile return value
+    Value *retval = imp_call;
+    ReturnInst::Create(context, retval, bb);
+
+    return f;
+}
+
 bool
 RoxorCompiler::compile_lvars(ID *tbl)
 {

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2010-02-26 05:24:06 UTC (rev 3632)
+++ MacRuby/trunk/compiler.h	2010-02-26 11:11:53 UTC (rev 3633)
@@ -48,6 +48,7 @@
 	Function *compile_write_attr(ID name);
 	Function *compile_stub(const char *types, bool variadic, int min_argc,
 		bool is_objc);
+	Function *compile_long_arity_stub(int argc, bool is_block);
 	Function *compile_bs_struct_new(rb_vm_bs_boxed_t *bs_boxed);
 	Function *compile_bs_struct_writer(rb_vm_bs_boxed_t *bs_boxed,
 		int field);

Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp	2010-02-26 05:24:06 UTC (rev 3632)
+++ MacRuby/trunk/dispatcher.cpp	2010-02-26 11:11:53 UTC (rev 3633)
@@ -107,9 +107,13 @@
 	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
 	case 9:
 	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
-    }	
-    printf("invalid argc %d\n", argc);
-    abort();
+    }
+
+    rb_vm_long_arity_bstub_t *stub;
+
+    stub = (rb_vm_long_arity_bstub_t *)GET_CORE()->gen_large_arity_stub(argc,
+	true);
+    return (*stub)(pimp, (id)self, sel, dvars, b, argc, argv);
 }
 
 static force_inline VALUE
@@ -152,9 +156,12 @@
 	    return (*imp)(self, sel, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
 	case 11:
 	    return (*imp)(self, sel, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
-    }	
-    printf("invalid argc %d\n", argc);
-    abort();
+    }
+
+    rb_vm_long_arity_stub_t *stub;
+
+    stub = (rb_vm_long_arity_stub_t *)GET_CORE()->gen_large_arity_stub(argc);
+    return (*stub)(pimp, (id)self, sel, argc, argv);
 }
 
 static void

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2010-02-26 05:24:06 UTC (rev 3632)
+++ MacRuby/trunk/vm.cpp	2010-02-26 11:11:53 UTC (rev 3633)
@@ -2861,6 +2861,28 @@
 }
 
 void *
+RoxorCore::gen_large_arity_stub(int argc, bool is_block)
+{
+    lock();
+    std::map<int, void *> &stubs =
+	is_block ? rb_large_arity_bstubs : rb_large_arity_rstubs;
+    std::map<int, void *>::iterator iter = stubs.find(argc);
+    void *stub;
+    if (iter == stubs.end()) {
+	Function *f = RoxorCompiler::shared->compile_long_arity_stub(argc,
+		is_block);
+	stub = (void *)compile(f);
+	stubs.insert(std::make_pair(argc, stub));
+    }
+    else {
+	stub = iter->second;
+    }
+    unlock();
+
+    return stub;
+}
+
+void *
 RoxorCore::gen_stub(std::string types, bool variadic, int min_argc,
 	bool is_objc)
 {

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2010-02-26 05:24:06 UTC (rev 3632)
+++ MacRuby/trunk/vm.h	2010-02-26 11:11:53 UTC (rev 3633)
@@ -526,8 +526,11 @@
 
 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);
+#define rb_vm_long_arity_stub_t rb_vm_objc_stub_t
+typedef VALUE rb_vm_long_arity_bstub_t(IMP imp, id self, SEL sel,
+				       VALUE dvars, rb_vm_block_t *b,
+				       int argc, const VALUE *argv);
 
 struct mcache {
 #define MCACHE_RCALL 0x1 // Ruby call
@@ -640,6 +643,8 @@
 	std::map<std::string, void *> c_stubs, objc_stubs,
 	    to_rval_convertors, to_ocval_convertors;
 	std::map<IMP, IMP> objc_to_ruby_stubs;
+	std::map<int, void *> rb_large_arity_rstubs; // Large arity Ruby calls
+	std::map<int, void *> rb_large_arity_bstubs; // Large arity block calls
 
 	// Caches for the lazy JIT.
 	std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
@@ -724,6 +729,7 @@
 	// This callback is public for the only reason it's called by C.
 	void bs_parse_cb(bs_element_type_t type, void *value, void *ctx);
 
+	void *gen_large_arity_stub(int argc, bool is_block=false);
 	void *gen_stub(std::string types, bool variadic, int min_argc,
 		bool is_objc);
 	void *gen_to_rval_convertor(std::string type);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100226/81d877bd/attachment.html>


More information about the macruby-changes mailing list