Revision: 3633 http://trac.macosforge.org/projects/ruby/changeset/3633 Author: martinlagardette@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);
participants (1)
-
source_changes@macosforge.org