diff --git a/array.c b/array.c index b979d55e4..e640f16d6 100644 --- a/array.c +++ b/array.c @@ -1889,8 +1889,8 @@ take_items(VALUE obj, long n) args[0] = result; args[1] = (VALUE)n; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, - (VALUE(*)(ANYARGS))take_i, (VALUE)args); + rb_objc_block_call(obj, selEach, 0, 0, (VALUE(*)(ANYARGS))take_i, + (VALUE)args); return result; } diff --git a/compar.c b/compar.c index cd89137c0..6547b4a62 100644 --- a/compar.c +++ b/compar.c @@ -16,7 +16,6 @@ VALUE rb_mComparable; static SEL cmp = 0; -static struct mcache *cmp_cache = NULL; void rb_cmperr(VALUE x, VALUE y) @@ -37,14 +36,14 @@ rb_cmperr(VALUE x, VALUE y) VALUE rb_objs_cmp(VALUE x, VALUE y) { - return rb_vm_call_with_cache(cmp_cache, x, cmp, 1, &y); + return rb_vm_call(x, cmp, 1, &y, false); } static VALUE cmp_eq(VALUE *a) { //VALUE c = rb_funcall(a[0], cmp, 1, a[1]); - VALUE c = rb_vm_call_with_cache(cmp_cache, a[0], cmp, 1, &a[1]); + VALUE c = rb_vm_call(a[0], cmp, 1, &a[1], false); if (NIL_P(c)) { return Qfalse; @@ -93,7 +92,7 @@ static VALUE cmp_gt(VALUE x, SEL sel, VALUE y) { //VALUE c = rb_funcall(x, cmp, 1, y); - VALUE c = rb_vm_call_with_cache(cmp_cache, x, cmp, 1, &y); + VALUE c = rb_vm_call(x, cmp, 1, &y, false); if (rb_cmpint(c, x, y) > 0) return Qtrue; return Qfalse; @@ -111,7 +110,7 @@ static VALUE cmp_ge(VALUE x, SEL sel, VALUE y) { //VALUE c = rb_funcall(x, cmp, 1, y); - VALUE c = rb_vm_call_with_cache(cmp_cache, x, cmp, 1, &y); + VALUE c = rb_vm_call(x, cmp, 1, &y, false); if (rb_cmpint(c, x, y) >= 0) return Qtrue; return Qfalse; @@ -129,7 +128,7 @@ static VALUE cmp_lt(VALUE x, SEL sel, VALUE y) { //VALUE c = rb_funcall(x, cmp, 1, y); - VALUE c = rb_vm_call_with_cache(cmp_cache, x, cmp, 1, &y); + VALUE c = rb_vm_call(x, cmp, 1, &y, false); if (rb_cmpint(c, x, y) < 0) return Qtrue; return Qfalse; @@ -147,7 +146,7 @@ static VALUE cmp_le(VALUE x, SEL sel, VALUE y) { //VALUE c = rb_funcall(x, cmp, 1, y); - VALUE c = rb_vm_call_with_cache(cmp_cache, x, cmp, 1, &y); + VALUE c = rb_vm_call(x, cmp, 1, &y, false); if (rb_cmpint(c, x, y) <= 0) return Qtrue; return Qfalse; @@ -225,5 +224,4 @@ Init_Comparable(void) rb_objc_define_method(rb_mComparable, "between?", cmp_between, 2); cmp = sel_registerName("<=>:"); - cmp_cache = rb_vm_get_call_cache(cmp); } diff --git a/compiler.cpp b/compiler.cpp index def6640d7..18bbc3189 100644 --- a/compiler.cpp +++ b/compiler.cpp @@ -268,7 +268,6 @@ RoxorCompiler::compile_single_when_argument(NODE *arg, Value *comparedToVal, Value *condVal; if (comparedToVal != NULL) { std::vector params; - params.push_back(compile_mcache(selEqq, false)); params.push_back(current_self); params.push_back(subnodeVal); params.push_back(compile_sel(selEqq)); @@ -425,12 +424,12 @@ RoxorCompiler::compile_fast_op_call(SEL sel, Value *selfVal, Value *otherVal) { Function *func = NULL; - // VALUE rb_vm_fast_op(struct mcache *cache, VALUE left, VALUE right); + // VALUE rb_vm_fast_op(VALUE left, VALUE right); #define fast_op(storage, name) \ do { \ if (storage == NULL) { \ storage = cast(module->getOrInsertFunction(name, \ - RubyObjTy, PtrTy, RubyObjTy, RubyObjTy, NULL)); \ + RubyObjTy, RubyObjTy, RubyObjTy, NULL)); \ } \ func = storage; \ } \ @@ -474,7 +473,6 @@ RoxorCompiler::compile_fast_op_call(SEL sel, Value *selfVal, Value *otherVal) } std::vector params; - params.push_back(compile_mcache(sel, false)); params.push_back(selfVal); params.push_back(otherVal); @@ -485,17 +483,15 @@ Value * RoxorCompiler::compile_when_splat(Value *comparedToVal, Value *splatVal) { if (whenSplatFunc == NULL) { - // VALUE rb_vm_when_splat(struct mcache *cache, - // unsigned char overriden, - // VALUE comparedTo, VALUE splat) + // VALUE rb_vm_when_splat(unsigned char overriden, + // VALUE comparedTo, VALUE splat) whenSplatFunc = cast (module->getOrInsertFunction("rb_vm_when_splat", - RubyObjTy, PtrTy, Int1Ty, - RubyObjTy, RubyObjTy, NULL)); + RubyObjTy, Int1Ty, RubyObjTy, + RubyObjTy, NULL)); } std::vector params; - params.push_back(compile_mcache(selEqq, false)); GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(selEqq, true); params.push_back(new LoadInst(is_redefined, "", bb)); params.push_back(comparedToVal); @@ -570,55 +566,6 @@ RoxorCompiler::compile_const_global_string(const char *str, return gvar; } -Value * -RoxorCompiler::compile_get_mcache(Value *sel, bool super) -{ - if (getCacheFunc == NULL) { - // void *rb_vm_get_call_cache2(SEL sel, unsigned char super); - getCacheFunc = - cast(module->getOrInsertFunction( - "rb_vm_get_call_cache2", PtrTy, PtrTy, Int8Ty, - NULL)); - } - - std::vector params; - params.push_back(sel); - params.push_back(ConstantInt::get(Int8Ty, super ? 1 : 0)); - - return CallInst::Create(getCacheFunc, params.begin(), params.end(), "", bb); -} - -Value * -RoxorCompiler::compile_mcache(SEL sel, bool super) -{ - struct mcache *cache = GET_CORE()->method_cache_get(sel, super); - return compile_const_pointer(cache); -} - -Value * -RoxorAOTCompiler::compile_mcache(SEL sel, bool super) -{ - if (super) { - char buf[100]; - snprintf(buf, sizeof buf, "__super__:%s", sel_getName(sel)); - sel = sel_registerName(buf); - } - - GlobalVariable *gvar; - std::map::iterator iter = mcaches.find(sel); - if (iter == mcaches.end()) { - gvar = new GlobalVariable(*RoxorCompiler::module, PtrTy, false, - GlobalValue::InternalLinkage, Constant::getNullValue(PtrTy), - ""); - assert(gvar != NULL); - mcaches[sel] = gvar; - } - else { - gvar = iter->second; - } - return new LoadInst(gvar, "", bb); -} - Value * RoxorCompiler::compile_ccache(ID name) { @@ -757,10 +704,9 @@ Value * RoxorCompiler::compile_dispatch_call(std::vector ¶ms) { if (dispatcherFunc == NULL) { - // VALUE rb_vm_dispatch(struct mcache *cache, VALUE top, VALUE self, - // SEL sel, void *block, unsigned char opt, int argc, ...); + // VALUE rb_vm_dispatch(VALUE top, VALUE self, SEL sel, void *block, + // unsigned char opt, int argc, ...); std::vector types; - types.push_back(PtrTy); types.push_back(RubyObjTy); types.push_back(RubyObjTy); types.push_back(PtrTy); @@ -805,7 +751,6 @@ RoxorCompiler::compile_attribute_assign(NODE *node, Value *extra_val) std::vector params; const SEL sel = mid_to_sel(mid, argc); - params.push_back(compile_mcache(sel, false)); params.push_back(current_self); params.push_back(recv); params.push_back(compile_sel(sel)); @@ -2203,7 +2148,7 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, return NULL; } - Value *val = params[2]; // self + Value *val = params[1]; // self Function *f = bb->getParent(); @@ -2236,7 +2181,7 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(sel, true); - Value *leftVal = params[2]; // self + Value *leftVal = params[1]; // self Value *rightVal = params.back(); VALUE leftRVal = Qundef, rightRVal = Qundef; @@ -2552,7 +2497,7 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, return NULL; } - if (params.size() - argc > 7) { + if (params.size() - argc > 6) { // Looks like there is a splat argument there, we can't handle this // in the primitives. return NULL; @@ -2561,31 +2506,34 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, Function *opt_func = NULL; if (sel == selLTLT) { - opt_func = cast(module->getOrInsertFunction("rb_vm_fast_shift", - RubyObjTy, RubyObjTy, RubyObjTy, PtrTy, Int1Ty, NULL)); + opt_func = cast(module->getOrInsertFunction( + "rb_vm_fast_shift", + RubyObjTy, RubyObjTy, RubyObjTy, Int1Ty, NULL)); } else if (sel == selAREF) { - opt_func = cast(module->getOrInsertFunction("rb_vm_fast_aref", - RubyObjTy, RubyObjTy, RubyObjTy, PtrTy, Int1Ty, NULL)); + opt_func = cast(module->getOrInsertFunction( + "rb_vm_fast_aref", + RubyObjTy, RubyObjTy, RubyObjTy, Int1Ty, NULL)); } else if (sel == selASET) { - opt_func = cast(module->getOrInsertFunction("rb_vm_fast_aset", - RubyObjTy, RubyObjTy, RubyObjTy, RubyObjTy, PtrTy, - Int1Ty, NULL)); + opt_func = cast(module->getOrInsertFunction( + "rb_vm_fast_aset", + RubyObjTy, RubyObjTy, RubyObjTy, RubyObjTy, Int1Ty, + NULL)); } else { abort(); } std::vector new_params; - new_params.push_back(params[2]); // self + new_params.push_back(params[1]); // self if (argc == 1) { new_params.push_back(params.back()); // other } else { - new_params.insert(new_params.end(), params.end() - 2, params.end()); + new_params.insert(new_params.end(), params.end() - 2, + params.end()); } - new_params.push_back(params[0]); // cache GlobalVariable *is_redefined = GET_CORE()->redefined_op_gvar(sel, true); new_params.push_back(new LoadInst(is_redefined, "", bb)); @@ -2624,16 +2572,15 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, bb = thenBB; std::vector new_params; - new_params.push_back(compile_mcache(new_sel, false)); // Compile a null top reference, to ignore protected visibility. new_params.push_back(ConstantInt::get(RubyObjTy, 0)); - new_params.push_back(params[2]); + new_params.push_back(params[1]); new_params.push_back(compile_sel(new_sel)); - new_params.push_back(params[4]); + new_params.push_back(params[3]); new_params.push_back(ConstantInt::get(Int8Ty, DISPATCH_FCALL)); new_params.push_back(ConstantInt::get(Int32Ty, argc - 1)); for (int i = 0; i < argc - 1; i++) { - new_params.push_back(params[8 + i]); + new_params.push_back(params[7 + i]); } Value *thenVal = compile_dispatch_call(new_params); thenBB = bb; @@ -2651,118 +2598,6 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc, return pn; } -#if 0 - // XXX this optimization is disabled because it's buggy and not really - // interesting - // #eval - else if (sel == selEval) { - - if (current_block_func != NULL || argc != 1) { - return NULL; - } - Value *strVal = params.back(); - if (!ConstantInt::classof(strVal)) { - return NULL; - } - VALUE str = cast(strVal)->getZExtValue(); - if (TYPE(str) != T_STRING) { - return NULL; - } - // FIXME: - // - pass the real file/line arguments - // - catch potential parsing exceptions - NODE *new_node = rb_compile_string("", str, 0); - if (new_node == NULL) { - return NULL; - } - if (nd_type(new_node) != NODE_SCOPE || new_node->nd_body == NULL) { - return NULL; - } - - GlobalVariable *is_redefined = GET_VM()->redefined_op_gvar(sel, true); - - Value *is_redefined_val = new LoadInst(is_redefined, "", bb); - Value *isOpRedefined = new ICmpInst(ICmpInst::ICMP_EQ, - is_redefined_val, ConstantInt::getFalse(), "", bb); - - Function *f = bb->getParent(); - - BasicBlock *thenBB = BasicBlock::Create("op_not_redefined", f); - BasicBlock *elseBB = BasicBlock::Create("op_dispatch", f); - BasicBlock *mergeBB = BasicBlock::Create("op_merge", f); - - BranchInst::Create(thenBB, elseBB, isOpRedefined, bb); - - bb = thenBB; - Value *thenVal = compile_node(new_node->nd_body); - thenBB = bb; - BranchInst::Create(mergeBB, thenBB); - - bb = elseBB; - Value *elseVal = compile_dispatch_call(params); - BranchInst::Create(mergeBB, elseBB); - - bb = mergeBB; - PHINode *pn = PHINode::Create(RubyObjTy, "op_tmp", mergeBB); - pn->addIncoming(thenVal, thenBB); - pn->addIncoming(elseVal, elseBB); - - return pn; - - } -#endif -#if 0 - // TODO: block inlining optimization - else if (current_block_func != NULL) { - static SEL selTimes = 0; - if (selTimes == 0) { - selTimes = rb_intern("times"); - } - - if (sel == selTimes && argc == 0) { - Value *val = params[1]; // self - - long valLong; - if (unbox_fixnum_constant(val, &valLong)) { - GlobalVariable *is_redefined = redefined_op_gvar(sel, true); - - Value *is_redefined_val = new LoadInst(is_redefined, "", bb); - Value *isOpRedefined = new ICmpInst(ICmpInst::ICMP_EQ, is_redefined_val, ConstantInt::getFalse(), "", bb); - - Function *f = bb->getParent(); - - BasicBlock *thenBB = BasicBlock::Create("op_not_redefined", f); - BasicBlock *elseBB = BasicBlock::Create("op_dispatch", f); - BasicBlock *mergeBB = BasicBlock::Create("op_merge", f); - - BranchInst::Create(thenBB, elseBB, isOpRedefined, bb); - bb = thenBB; - - - -// Val *mem = new AllocaInst(RubyObjTy, "", bb); -// new StoreInst(zeroVal, mem, "", bb); -// Val *i = LoadInst(mem, "", bb); - - - - Value *thenVal = val; - BranchInst::Create(mergeBB, thenBB); - - Value *elseVal = dispatchCall; - elseBB->getInstList().push_back(dispatchCall); - BranchInst::Create(mergeBB, elseBB); - - PHINode *pn = PHINode::Create(Type::Int32Ty, "op_tmp", mergeBB); - pn->addIncoming(thenVal, thenBB); - pn->addIncoming(elseVal, elseBB); - bb = mergeBB; - - return pn; - } - } - } -#endif return NULL; } @@ -3631,7 +3466,6 @@ RoxorCompiler::compile_node(NODE *node) assert(node->nd_next->nd_vid > 0); sel = mid_to_sel(node->nd_next->nd_vid, 0); } - params.push_back(compile_mcache(sel, false)); params.push_back(current_self); params.push_back(recv); params.push_back(compile_sel(sel)); @@ -3691,7 +3525,6 @@ RoxorCompiler::compile_node(NODE *node) ? node->nd_mid : node->nd_next->nd_mid; sel = mid_to_sel(mid, 1); params.clear(); - params.push_back(compile_mcache(sel, false)); params.push_back(current_self); params.push_back(tmp); params.push_back(compile_sel(sel)); @@ -3716,7 +3549,6 @@ RoxorCompiler::compile_node(NODE *node) sel = mid_to_sel(node->nd_next->nd_aid, 1); } params.clear(); - params.push_back(compile_mcache(sel, false)); params.push_back(current_self); params.push_back(recv); params.push_back(compile_sel(sel)); @@ -3768,7 +3600,6 @@ RoxorCompiler::compile_node(NODE *node) } std::vector params; - params.push_back(compile_mcache(selBackquote, false)); params.push_back(current_self); params.push_back(current_self); params.push_back(compile_sel(selBackquote)); @@ -4215,7 +4046,7 @@ RoxorCompiler::compile_node(NODE *node) // Prepare the dispatcher parameters. std::vector params; - // Method cache (and prepare the selector). + // Prepare the selector. Value *sel_val; SEL sel; if (mid != 0) { @@ -4241,10 +4072,6 @@ RoxorCompiler::compile_node(NODE *node) dyn_sel, compile_const_pointer(NULL)); sel_val = SelectInst::Create(is_null, sel_val, dyn_sel, "", bb); - params.push_back(compile_get_mcache(sel_val, true)); - } - else { - params.push_back(compile_mcache(sel, super_call)); } } else { @@ -4252,7 +4079,6 @@ RoxorCompiler::compile_node(NODE *node) // A super call outside a method definition. Compile a // null selector, the runtime will raise an exception. sel = 0; - params.push_back(compile_const_pointer(NULL)); sel_val = compile_const_pointer(NULL); } @@ -4364,7 +4190,7 @@ RoxorCompiler::compile_node(NODE *node) blockVal = compile_const_pointer(NULL); } } - params[4] = blockVal; + params[3] = blockVal; // If we are calling a method that needs a top-level binding // object, let's create it. @@ -4641,7 +4467,6 @@ RoxorCompiler::compile_node(NODE *node) } std::vector params; - params.push_back(compile_mcache(selEqTilde, false)); params.push_back(current_self); params.push_back(reTarget); params.push_back(compile_sel(selEqTilde)); @@ -5236,7 +5061,6 @@ RoxorCompiler::compile_node(NODE *node) // dispatch #each on the receiver std::vector params; - params.push_back(compile_mcache((is_lambda ? selLambda : selEach), false)); params.push_back(current_self); if (!is_lambda) { @@ -5252,9 +5076,11 @@ RoxorCompiler::compile_node(NODE *node) params.push_back(current_self); } - params.push_back(compile_sel((is_lambda ? selLambda : selEach))); + params.push_back(compile_sel(is_lambda + ? selLambda : selEach)); params.push_back(compile_block_create()); - params.push_back(ConstantInt::get(Int8Ty, (is_lambda ? DISPATCH_FCALL : 0))); + params.push_back(ConstantInt::get(Int8Ty, is_lambda + ? DISPATCH_FCALL : 0)); params.push_back(ConstantInt::get(Int32Ty, 0)); caller = compile_dispatch_call(params); @@ -5454,7 +5280,6 @@ RoxorCompiler::compile_node(NODE *node) std::vector params; SEL sel = sel_registerName("at_exit"); - params.push_back(compile_mcache(sel, false)); params.push_back(current_self); params.push_back(compile_nsobject()); params.push_back(compile_sel(sel)); @@ -5544,36 +5369,6 @@ RoxorAOTCompiler::compile_main_function(NODE *node) function->getEntryBlock().getInstList(); bb = &function->getEntryBlock(); - // Compile method caches. - - Function *getMethodCacheFunc = cast(module->getOrInsertFunction( - "rb_vm_get_method_cache", - PtrTy, PtrTy, NULL)); - - for (std::map::iterator i = mcaches.begin(); - i != mcaches.end(); - ++i) { - - SEL sel = i->first; - GlobalVariable *gvar = i->second; - - std::vector params; - Value *load = compile_sel(sel, false); - params.push_back(load); - - Instruction *call = CallInst::Create(getMethodCacheFunc, - params.begin(), params.end(), ""); - - Instruction *assign = new StoreInst(call, gvar, ""); - - list.insert(list.begin(), assign); - list.insert(list.begin(), call); - Instruction *load_insn = dyn_cast(load); - if (load_insn != NULL) { - list.insert(list.begin(), load_insn); - } - } - // Compile constant caches. Function *getConstCacheFunc = cast(module->getOrInsertFunction( diff --git a/compiler.h b/compiler.h index 260b475d6..1d9337f7e 100644 --- a/compiler.h +++ b/compiler.h @@ -305,8 +305,6 @@ class RoxorCompiler { void compile_return_from_block(Value *val, int id); void compile_return_from_block_handler(int id); Value *compile_jump(NODE *node); - virtual Value *compile_mcache(SEL sel, bool super); - Value *compile_get_mcache(Value *sel, bool super); virtual Value *compile_ccache(ID id); virtual Value *compile_sel(SEL sel, bool add_to_bb=true) { return compile_const_pointer(sel, PtrTy); @@ -386,7 +384,6 @@ class RoxorAOTCompiler : public RoxorCompiler { Function *compile_main_function(NODE *node); private: - std::map mcaches; std::map ccaches; std::map sels; std::map ids; @@ -398,7 +395,6 @@ class RoxorAOTCompiler : public RoxorCompiler { GlobalVariable *cStandardError_gvar; std::vector class_gvars; - Value *compile_mcache(SEL sel, bool super); Value *compile_ccache(ID id); Value *compile_sel(SEL sel, bool add_to_bb=true); void compile_prepare_method(Value *classVal, Value *sel, diff --git a/dispatcher.cpp b/dispatcher.cpp index 54436f0af..e310097e5 100644 --- a/dispatcher.cpp +++ b/dispatcher.cpp @@ -23,6 +23,7 @@ #include #define ROXOR_VM_DEBUG 0 +#define ROXOR_MCACHE_DEBUG 1 #define MAX_DISPATCH_ARGS 100 static force_inline void @@ -347,10 +348,8 @@ method_missing(VALUE obj, SEL sel, rb_vm_block_t *block, int argc, return Qnil; // never reached } else { - struct mcache *cache = GET_CORE()->method_cache_get(selMethodMissing, - false); - return rb_vm_call_with_cache2(cache, block, obj, NULL, selMethodMissing, - argc + 1, new_argv); + return rb_vm_call2(block, obj, NULL, selMethodMissing, argc + 1, + new_argv); } } @@ -551,16 +550,37 @@ sel_equal(Class klass, SEL x, SEL y) return x_imp == y_imp; } +static inline int +mcache_hash(Class klass, SEL sel) +{ + return (((unsigned long)klass >> 3) ^ (unsigned long)sel) + & (MCACHE_SIZE - 1); +} + +#if ROXOR_MCACHE_DEBUG +static long cached_count = 0; +static long collision_count = 0; +#endif + +extern "C" +void +rb_vm_dispatch_finalize(void) +{ +#if ROXOR_MCACHE_DEBUG + printf("cached count %ld, collision count %ld\n", cached_count, + collision_count); +#endif +} + static force_inline VALUE -__rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self, - Class klass, SEL sel, rb_vm_block_t *block, unsigned char opt, - int argc, const VALUE *argv) +__rb_vm_dispatch(RoxorVM *vm, VALUE top, VALUE self, Class klass, SEL sel, + rb_vm_block_t *block, unsigned char opt, int argc, const VALUE *argv) { - if (cache == NULL) { - if (sel == 0 && opt == DISPATCH_SUPER) { + if (sel == 0) { + if (opt == DISPATCH_SUPER) { rb_raise(rb_eNoMethodError, "super called outside of method"); } - abort(); + abort(); } if (klass == NULL) { @@ -570,17 +590,43 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self, #if ROXOR_VM_DEBUG bool cached = true; #endif + int cache_hash = 0; bool cache_method = true; - Class current_super_class = vm->get_current_super_class(); - SEL current_super_sel = vm->get_current_super_sel(); - - // XXX: super method cache is disabled because it causes random runtime - // bugs in rails. Instead of fixing the problem, we wait for the new - // method cache implementation which should be different (and thread-safe). + struct mcache *cache; if (opt == DISPATCH_SUPER) { - cache->flag = 0; + cache_hash = mcache_hash(klass, sel) + 1; + cache = &vm->mcache[cache_hash]; + if (!(cache->flag & MCACHE_SUPER) || cache->sel != sel) { + cache->flag = 0; // recache +#if ROXOR_MCACHE_DEBUG + collision_count++; +#endif + } +#if ROXOR_MCACHE_DEBUG + else { + cached_count++; + } +#endif } + else { + cache_hash = mcache_hash(klass, sel); + cache = &vm->mcache[cache_hash]; + if (cache->sel != sel) { + cache->flag = 0; // recache +#if ROXOR_MCACHE_DEBUG + collision_count++; +#endif + } +#if ROXOR_MCACHE_DEBUG + else { + cached_count++; + } +#endif + } + + Class current_super_class = vm->get_current_super_class(); + SEL current_super_sel = vm->get_current_super_sel(); if (cache->flag == 0) { recache: @@ -620,6 +666,11 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self, // objc call fill_ocache(cache, self, klass, imp, sel, method, argc); } + + if (opt == DISPATCH_SUPER) { + cache->flag |= MCACHE_SUPER; + } + cache->sel = sel; } else { // Method is not found... @@ -732,7 +783,7 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self, } dispatch: - if (cache->flag == MCACHE_RCALL) { + if (cache->flag & MCACHE_RCALL) { if (rcache.klass != klass) { goto recache; } @@ -741,7 +792,7 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self, } #if ROXOR_VM_DEBUG - printf("ruby dispatch %c[<%s %p> %s] (imp %p block %p argc %d opt %d cache %p cached %s)\n", + printf("ruby dispatch %c[<%s %p> %s] (imp %p block %p argc %d opt %d cache hash %d cached %s)\n", class_isMetaClass(klass) ? '+' : '-', class_getName(klass), (void *)self, @@ -750,7 +801,7 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self, block, argc, opt, - cache, + cache_hash, cached ? "true" : "false"); #endif @@ -820,7 +871,7 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self, return v; } - else if (cache->flag == MCACHE_OCALL) { + else if (cache->flag & MCACHE_OCALL) { if (ocache.klass != klass) { goto recache; } @@ -856,13 +907,14 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self, } #if ROXOR_VM_DEBUG - printf("objc dispatch %c[<%s %p> %s] imp=%p argc=%d (cached=%s)\n", + printf("objc dispatch %c[<%s %p> %s] imp %p argc %d cache hash %d cached %s\n", class_isMetaClass(klass) ? '+' : '-', class_getName(klass), (void *)self, sel_getName(sel), ocache.imp, argc, + cache_hash, cached ? "true" : "false"); #endif @@ -912,7 +964,7 @@ __rb_vm_dispatch(RoxorVM *vm, struct mcache *cache, VALUE top, VALUE self, return __rb_vm_objc_dispatch(ocache.stub, ocache.imp, ocrcv, sel, argc, argv); } - else if (cache->flag == MCACHE_FCALL) { + else if (cache->flag & MCACHE_FCALL) { #if ROXOR_VM_DEBUG printf("C dispatch %s() imp=%p argc=%d (cached=%s)\n", fcache.bs_function->name, @@ -1032,8 +1084,8 @@ __rb_vm_resolve_args(VALUE **pargv, size_t argv_size, int *pargc, va_list ar) extern "C" VALUE -rb_vm_dispatch(struct mcache *cache, VALUE top, VALUE self, SEL sel, - rb_vm_block_t *block, unsigned char opt, int argc, ...) +rb_vm_dispatch(VALUE top, VALUE self, SEL sel, rb_vm_block_t *block, + unsigned char opt, int argc, ...) { VALUE base_argv[MAX_DISPATCH_ARGS]; VALUE *argv = base_argv; @@ -1066,47 +1118,24 @@ rb_vm_dispatch(struct mcache *cache, VALUE top, VALUE self, SEL sel, ~Finally() { vm->pop_current_binding(); } } finalizer(vm); - VALUE retval = __rb_vm_dispatch(vm, cache, top, self, NULL, sel, block, - opt, argc, argv); - - return retval; + return __rb_vm_dispatch(vm, top, self, NULL, sel, block, opt, argc, argv); } extern "C" VALUE rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *argv, bool super) { - struct mcache *cache; - unsigned char opt = DISPATCH_FCALL; - if (super) { - cache = (struct mcache *)alloca(sizeof(struct mcache)); - cache->flag = 0; - opt = DISPATCH_SUPER; - } - else { - cache = GET_CORE()->method_cache_get(sel, false); - } - - return __rb_vm_dispatch(GET_VM(), cache, 0, self, NULL, sel, NULL, opt, - argc, argv); + return __rb_vm_dispatch(GET_VM(), 0, self, NULL, sel, NULL, + super ? DISPATCH_SUPER : DISPATCH_FCALL, argc, argv); } extern "C" VALUE -rb_vm_call_with_cache(void *cache, VALUE self, SEL sel, int argc, +rb_vm_call2(rb_vm_block_t *block, VALUE self, VALUE klass, SEL sel, int argc, const VALUE *argv) { - return __rb_vm_dispatch(GET_VM(), (struct mcache *)cache, 0, self, NULL, - sel, NULL, DISPATCH_FCALL, argc, argv); -} - -extern "C" -VALUE -rb_vm_call_with_cache2(void *cache, rb_vm_block_t *block, VALUE self, - VALUE klass, SEL sel, int argc, const VALUE *argv) -{ - return __rb_vm_dispatch(GET_VM(), (struct mcache *)cache, 0, self, - (Class)klass, sel, block, DISPATCH_FCALL, argc, argv); + return __rb_vm_dispatch(GET_VM(), 0, self, (Class)klass, sel, block, + DISPATCH_FCALL, argc, argv); } // The rb_vm_fast_* functions don't check if the selector has been redefined or @@ -1130,122 +1159,134 @@ extern "C" { extern "C" VALUE -rb_vm_fast_plus(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_plus(VALUE self, VALUE other) { switch (TYPE(self)) { // TODO: Array, String case T_BIGNUM: return rb_big_plus(self, other); + case T_FIXNUM: return rb_fix_plus(self, other); + case T_FLOAT: return rb_flo_plus(self, other); + case T_COMPLEX: return rb_nu_plus(self, other); } - return rb_vm_dispatch(cache, 0, self, selPLUS, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selPLUS, NULL, 0, 1, other); } extern "C" VALUE -rb_vm_fast_minus(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_minus(VALUE self, VALUE other) { switch (TYPE(self)) { // TODO: Array, String case T_BIGNUM: return rb_big_minus(self, other); + case T_FIXNUM: return rb_fix_minus(self, other); + case T_FLOAT: return rb_flo_minus(self, other); + case T_COMPLEX: return rb_nu_minus(self, other); } - return rb_vm_dispatch(cache, 0, self, selMINUS, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selMINUS, NULL, 0, 1, other); } extern "C" VALUE -rb_vm_fast_div(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_div(VALUE self, VALUE other) { switch (TYPE(self)) { case T_BIGNUM: return rb_big_div(self, other); + case T_FIXNUM: return rb_fix_div(self, other); + case T_FLOAT: return rb_flo_div(self, other); + case T_COMPLEX: return rb_nu_div(self, other); } - return rb_vm_dispatch(cache, 0, self, selDIV, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selDIV, NULL, 0, 1, other); } extern "C" VALUE -rb_vm_fast_mult(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_mult(VALUE self, VALUE other) { switch (TYPE(self)) { // TODO: Array, String case T_BIGNUM: return rb_big_mul(self, other); + case T_FIXNUM: return rb_fix_mul(self, other); + case T_FLOAT: return rb_flo_mul(self, other); + case T_COMPLEX: return rb_nu_mul(self, other); } - return rb_vm_dispatch(cache, 0, self, selMULT, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selMULT, NULL, 0, 1, other); } extern "C" VALUE -rb_vm_fast_lt(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_lt(VALUE self, VALUE other) { switch (TYPE(self)) { case T_BIGNUM: return FIX2INT(rb_big_cmp(self, other)) < 0 ? Qtrue : Qfalse; } - return rb_vm_dispatch(cache, 0, self, selLT, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selLT, NULL, 0, 1, other); } extern "C" VALUE -rb_vm_fast_le(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_le(VALUE self, VALUE other) { switch (TYPE(self)) { case T_BIGNUM: return FIX2INT(rb_big_cmp(self, other)) <= 0 ? Qtrue : Qfalse; } - return rb_vm_dispatch(cache, 0, self, selLE, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selLE, NULL, 0, 1, other); } extern "C" VALUE -rb_vm_fast_gt(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_gt(VALUE self, VALUE other) { switch (TYPE(self)) { case T_BIGNUM: return FIX2INT(rb_big_cmp(self, other)) > 0 ? Qtrue : Qfalse; } - return rb_vm_dispatch(cache, 0, self, selGT, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selGT, NULL, 0, 1, other); } extern "C" VALUE -rb_vm_fast_ge(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_ge(VALUE self, VALUE other) { switch (TYPE(self)) { case T_BIGNUM: return FIX2INT(rb_big_cmp(self, other)) >= 0 ? Qtrue : Qfalse; } - return rb_vm_dispatch(cache, 0, self, selGE, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selGE, NULL, 0, 1, other); } extern "C" VALUE -rb_vm_fast_eq(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_eq(VALUE self, VALUE other) { const int self_type = TYPE(self); switch (self_type) { @@ -1282,20 +1323,20 @@ rb_vm_fast_eq(struct mcache *cache, VALUE self, VALUE other) case T_BIGNUM: return rb_big_eq(self, other); } - return rb_vm_dispatch(cache, 0, self, selEq, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selEq, NULL, 0, 1, other); } extern "C" VALUE -rb_vm_fast_neq(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_neq(VALUE self, VALUE other) { // TODO - return rb_vm_dispatch(cache, 0, self, selNeq, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selNeq, NULL, 0, 1, other); } extern "C" VALUE -rb_vm_fast_eqq(struct mcache *cache, VALUE self, VALUE other) +rb_vm_fast_eqq(VALUE self, VALUE other) { switch (TYPE(self)) { // TODO: Range @@ -1316,14 +1357,13 @@ rb_vm_fast_eqq(struct mcache *cache, VALUE self, VALUE other) return rb_obj_is_kind_of(other, self); default: - return rb_vm_dispatch(cache, 0, self, selEqq, NULL, 0, 1, other); + return rb_vm_dispatch(0, self, selEqq, NULL, 0, 1, other); } } extern "C" VALUE -rb_vm_when_splat(struct mcache *cache, unsigned char overriden, - VALUE comparedTo, VALUE splat) +rb_vm_when_splat(unsigned char overriden, VALUE comparedTo, VALUE splat) { VALUE ary = rb_check_convert_type(splat, T_ARRAY, "Array", "to_a"); if (NIL_P(ary)) { @@ -1333,7 +1373,7 @@ rb_vm_when_splat(struct mcache *cache, unsigned char overriden, if (overriden == 0) { for (int i = 0; i < count; ++i) { VALUE o = RARRAY_AT(ary, i); - if (RTEST(rb_vm_fast_eqq(cache, o, comparedTo))) { + if (RTEST(rb_vm_fast_eqq(o, comparedTo))) { return Qtrue; } } @@ -1341,8 +1381,7 @@ rb_vm_when_splat(struct mcache *cache, unsigned char overriden, else { for (int i = 0; i < count; ++i) { VALUE o = RARRAY_AT(ary, i); - if (RTEST(rb_vm_dispatch(cache, 0, o, selEqq, NULL, 0, 1, - comparedTo))) { + if (RTEST(rb_vm_dispatch(0, o, selEqq, NULL, 0, 1, comparedTo))) { return Qtrue; } } @@ -1352,8 +1391,7 @@ rb_vm_when_splat(struct mcache *cache, unsigned char overriden, extern "C" VALUE -rb_vm_fast_shift(VALUE obj, VALUE other, struct mcache *cache, - unsigned char overriden) +rb_vm_fast_shift(VALUE obj, VALUE other, unsigned char overriden) { if (overriden == 0) { switch (TYPE(obj)) { @@ -1373,14 +1411,13 @@ rb_vm_fast_shift(VALUE obj, VALUE other, struct mcache *cache, #endif } } - return __rb_vm_dispatch(GET_VM(), cache, 0, obj, NULL, selLTLT, NULL, 0, 1, + return __rb_vm_dispatch(GET_VM(), 0, obj, NULL, selLTLT, NULL, 0, 1, &other); } extern "C" VALUE -rb_vm_fast_aref(VALUE obj, VALUE other, struct mcache *cache, - unsigned char overriden) +rb_vm_fast_aref(VALUE obj, VALUE other, unsigned char overriden) { if (overriden == 0) switch (TYPE(obj)) { @@ -1396,14 +1433,13 @@ rb_vm_fast_aref(VALUE obj, VALUE other, struct mcache *cache, } break; } - return __rb_vm_dispatch(GET_VM(), cache, 0, obj, NULL, selAREF, NULL, 0, 1, + return __rb_vm_dispatch(GET_VM(), 0, obj, NULL, selAREF, NULL, 0, 1, &other); } extern "C" VALUE -rb_vm_fast_aset(VALUE obj, VALUE other1, VALUE other2, struct mcache *cache, - unsigned char overriden) +rb_vm_fast_aset(VALUE obj, VALUE other1, VALUE other2, unsigned char overriden) { if (overriden == 0) { switch (TYPE(obj)) { @@ -1424,7 +1460,7 @@ rb_vm_fast_aset(VALUE obj, VALUE other1, VALUE other2, struct mcache *cache, } } VALUE args[2] = { other1, other2 }; - return __rb_vm_dispatch(GET_VM(), cache, 0, obj, NULL, selASET, NULL, 0, 2, + return __rb_vm_dispatch(GET_VM(), 0, obj, NULL, selASET, NULL, 0, 2, args); } @@ -1579,9 +1615,13 @@ rb_vm_block_eval0(rb_vm_block_t *b, SEL sel, VALUE self, int argc, } finalizer(vm, b, old_current_class); if (b->flags & VM_BLOCK_METHOD) { +#if 0 + // TODO rb_vm_method_t *m = (rb_vm_method_t *)b->imp; return rb_vm_call_with_cache2(m->cache, NULL, m->recv, m->oclass, m->sel, argc, argv); +#endif + return Qnil; } return __rb_vm_bcall(self, sel, (VALUE)b->dvars, b, b->imp, b->arity, argc, argv); diff --git a/enum.c b/enum.c index ecce960cd..aed755e6a 100644 --- a/enum.c +++ b/enum.c @@ -81,7 +81,8 @@ enum_grep(VALUE obj, SEL sel, VALUE pat) arg[0] = pat; arg[1] = ary; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg); + rb_objc_block_call(obj, selEach, 0, 0, + rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg); return ary; } @@ -164,7 +165,7 @@ enum_count(VALUE obj, SEL sel, int argc, VALUE *argv) } memo[0] = 0; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, func, (VALUE)&memo); + rb_objc_block_call(obj, selEach, 0, 0, func, (VALUE)&memo); return INT2NUM(memo[0]); } @@ -203,7 +204,7 @@ enum_find(VALUE obj, SEL sel, int argc, VALUE *argv) rb_scan_args(argc, argv, "01", &if_none); RETURN_ENUMERATOR(obj, argc, argv); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, find_i, (VALUE)&memo); + rb_objc_block_call(obj, selEach, 0, 0, find_i, (VALUE)&memo); if (memo != Qundef) { return memo; } @@ -277,7 +278,7 @@ enum_find_index(VALUE obj, SEL sel, int argc, VALUE *argv) memo[0] = Qnil; memo[1] = 0; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, func, (VALUE)memo); + rb_objc_block_call(obj, selEach, 0, 0, func, (VALUE)memo); return memo[0]; } @@ -313,7 +314,7 @@ enum_find_all(VALUE obj, SEL sel) RETURN_ENUMERATOR(obj, 0, 0); ary = rb_ary_new(); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, find_all_i, ary); + rb_objc_block_call(obj, selEach, 0, 0, find_all_i, ary); return ary; } @@ -348,7 +349,7 @@ enum_reject(VALUE obj, SEL sel) RETURN_ENUMERATOR(obj, 0, 0); ary = rb_ary_new(); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, reject_i, ary); + rb_objc_block_call(obj, selEach, 0, 0, reject_i, ary); return ary; } @@ -390,7 +391,7 @@ enum_collect(VALUE obj, SEL sel) RETURN_ENUMERATOR(obj, 0, 0); ary = rb_ary_new(); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, collect_i, ary); + rb_objc_block_call(obj, selEach, 0, 0, collect_i, ary); return ary; } @@ -410,7 +411,7 @@ enum_to_a(VALUE obj, SEL sel, int argc, VALUE *argv) { VALUE ary = rb_ary_new(); - rb_objc_block_call(obj, selEach, cacheEach, argc, argv, collect_all, ary); + rb_objc_block_call(obj, selEach, argc, argv, collect_all, ary); return ary; } @@ -518,7 +519,7 @@ enum_inject(VALUE obj, SEL sel, int argc, VALUE *argv) iter = inject_op_i; break; } - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, iter, (VALUE)memo); + rb_objc_block_call(obj, selEach, 0, 0, iter, (VALUE)memo); if (memo[0] == Qundef) { return Qnil; } @@ -560,7 +561,7 @@ enum_partition(VALUE obj, SEL sel) ary[0] = rb_ary_new(); ary[1] = rb_ary_new(); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, partition_i, (VALUE)ary); + rb_objc_block_call(obj, selEach, 0, 0, partition_i, (VALUE)ary); return rb_assoc_new(ary[0], ary[1]); } @@ -605,7 +606,7 @@ enum_group_by(VALUE obj, SEL sel) RETURN_ENUMERATOR(obj, 0, 0); hash = rb_hash_new(); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, group_by_i, hash); + rb_objc_block_call(obj, selEach, 0, 0, group_by_i, hash); return hash; } @@ -658,7 +659,7 @@ enum_first(VALUE obj, SEL sel, int argc, VALUE *argv) ary[0] = n; ary[1] = rb_ary_new2(NUM2LONG(n)); } - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, first_i, (VALUE)ary); + rb_objc_block_call(obj, selEach, 0, 0, first_i, (VALUE)ary); return ary[1]; } @@ -792,7 +793,7 @@ enum_sort_by(VALUE obj, SEL sel) else { ary = rb_ary_new(); } - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, sort_by_i, ary); + rb_objc_block_call(obj, selEach, 0, 0, sort_by_i, ary); if (RARRAY_LEN(ary) > 1) { qsort_r((VALUE *)RARRAY_PTR(ary), RARRAY_LEN(ary), sizeof(VALUE), NULL, sort_by_cmp); @@ -850,7 +851,8 @@ enum_all(VALUE obj, SEL sel) { VALUE result = Qtrue; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, rb_block_given_p() ? all_iter_i : all_i, (VALUE)&result); + rb_objc_block_call(obj, selEach, 0, 0, + rb_block_given_p() ? all_iter_i : all_i, (VALUE)&result); return result; } @@ -889,7 +891,8 @@ enum_any(VALUE obj, SEL sel) { VALUE result = Qfalse; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, rb_block_given_p() ? any_iter_i : any_i, (VALUE)&result); + rb_objc_block_call(obj, selEach, 0, 0, + rb_block_given_p() ? any_iter_i : any_i, (VALUE)&result); return result; } @@ -933,8 +936,11 @@ enum_one(VALUE obj, SEL sel) { VALUE result = Qundef; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, rb_block_given_p() ? one_iter_i : one_i, (VALUE)&result); - if (result == Qundef) return Qfalse; + rb_objc_block_call(obj, selEach, 0, 0, + rb_block_given_p() ? one_iter_i : one_i, (VALUE)&result); + if (result == Qundef) { + return Qfalse; + } return result; } @@ -970,7 +976,8 @@ enum_none(VALUE obj, SEL sel) { VALUE result = Qtrue; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, rb_block_given_p() ? none_iter_i : none_i, (VALUE)&result); + rb_objc_block_call(obj, selEach, 0, 0, + rb_block_given_p() ? none_iter_i : none_i, (VALUE)&result); return result; } @@ -1038,12 +1045,14 @@ enum_min(VALUE obj, SEL sel) result[0] = Qundef; if (rb_block_given_p()) { result[1] = rb_ary_new3(2, Qnil, Qnil); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, min_ii, (VALUE)result); + rb_objc_block_call(obj, selEach, 0, 0, min_ii, (VALUE)result); } else { - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, min_i, (VALUE)result); + rb_objc_block_call(obj, selEach, 0, 0, min_i, (VALUE)result); + } + if (result[0] == Qundef) { + return Qnil; } - if (result[0] == Qundef) return Qnil; return result[0]; } @@ -1110,12 +1119,14 @@ enum_max(VALUE obj, SEL sel) result[0] = Qundef; if (rb_block_given_p()) { result[1] = rb_ary_new3(2, Qnil, Qnil); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, max_ii, (VALUE)result); + rb_objc_block_call(obj, selEach, 0, 0, max_ii, (VALUE)result); } else { - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, max_i, (VALUE)result); + rb_objc_block_call(obj, selEach, 0, 0, max_i, (VALUE)result); + } + if (result[0] == Qundef) { + return Qnil; } - if (result[0] == Qundef) return Qnil; return result[0]; } @@ -1197,10 +1208,10 @@ enum_minmax(VALUE obj, SEL sel) result[0] = Qundef; if (rb_block_given_p()) { result[2] = ary; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, minmax_ii, (VALUE)result); + rb_objc_block_call(obj, selEach, 0, 0, minmax_ii, (VALUE)result); } else { - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, minmax_i, (VALUE)result); + rb_objc_block_call(obj, selEach, 0, 0, minmax_i, (VALUE)result); } if (result[0] != Qundef) { rb_ary_store(ary, 0, result[0]); @@ -1248,7 +1259,7 @@ enum_min_by(VALUE obj, SEL sel) memo[0] = Qundef; memo[1] = Qnil; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, min_by_i, (VALUE)memo); + rb_objc_block_call(obj, selEach, 0, 0, min_by_i, (VALUE)memo); return memo[1]; } @@ -1291,7 +1302,7 @@ enum_max_by(VALUE obj, SEL sel) memo[0] = Qundef; memo[1] = Qnil; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, max_by_i, (VALUE)memo); + rb_objc_block_call(obj, selEach, 0, 0, max_by_i, (VALUE)memo); return memo[1]; } @@ -1345,7 +1356,7 @@ enum_minmax_by(VALUE obj, SEL sel) memo[1] = Qundef; memo[2] = Qnil; memo[3] = Qnil; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, minmax_by_i, (VALUE)memo); + rb_objc_block_call(obj, selEach, 0, 0, minmax_by_i, (VALUE)memo); return rb_assoc_new(memo[2], memo[3]); } @@ -1379,7 +1390,7 @@ enum_member(VALUE obj, SEL sel, VALUE val) memo[0] = val; memo[1] = Qfalse; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, member_i, (VALUE)memo); + rb_objc_block_call(obj, selEach, 0, 0, member_i, (VALUE)memo); return memo[1]; } @@ -1415,7 +1426,8 @@ enum_each_with_index(VALUE obj, SEL sel, int argc, VALUE *argv) RETURN_ENUMERATOR(obj, argc, argv); memo = 0; - rb_objc_block_call(obj, selEach, cacheEach, argc, argv, each_with_index_i, (VALUE)&memo); + rb_objc_block_call(obj, selEach, argc, argv, each_with_index_i, + (VALUE)&memo); return obj; } @@ -1571,7 +1583,8 @@ enum_zip(VALUE obj, SEL sel, int argc, VALUE *argv) result = rb_ary_new(); } memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), 0); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo); + rb_objc_block_call(obj, selEach, 0, 0, allary ? zip_ary : zip_i, + (VALUE)memo); return result; } @@ -1607,7 +1620,7 @@ enum_take(VALUE obj, SEL sel, VALUE n) args[1] = len; args[0] = rb_ary_new(); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, take_i, (VALUE)args); + rb_objc_block_call(obj, selEach, 0, 0, take_i, (VALUE)args); return args[0]; } @@ -1639,7 +1652,7 @@ enum_take_while(VALUE obj, SEL sel) RETURN_ENUMERATOR(obj, 0, 0); ary = rb_ary_new(); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, take_while_i, (VALUE)&ary); + rb_objc_block_call(obj, selEach, 0, 0, take_while_i, (VALUE)&ary); return ary; } @@ -1679,7 +1692,7 @@ enum_drop(VALUE obj, SEL sel, VALUE n) args[1] = len; args[0] = rb_ary_new(); - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, drop_i, (VALUE)args); + rb_objc_block_call(obj, selEach, 0, 0, drop_i, (VALUE)args); return args[0]; } @@ -1719,7 +1732,7 @@ enum_drop_while(VALUE obj, SEL sel) RETURN_ENUMERATOR(obj, 0, 0); args[0] = rb_ary_new(); args[1] = Qfalse; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, drop_while_i, (VALUE)args); + rb_objc_block_call(obj, selEach, 0, 0, drop_while_i, (VALUE)args); return args[0]; } @@ -1773,7 +1786,7 @@ enum_cycle(VALUE obj, SEL sel, int argc, VALUE *argv) #if !WITH_OBJC RBASIC(ary)->klass = 0; #endif - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, cycle_i, ary); + rb_objc_block_call(obj, selEach, 0, 0, cycle_i, ary); len = RARRAY_LEN(ary); if (len == 0) return Qnil; while (n < 0 || 0 < --n) { diff --git a/enumerator.c b/enumerator.c index 452893355..4993948c3 100644 --- a/enumerator.c +++ b/enumerator.c @@ -14,6 +14,8 @@ #include "ruby/ruby.h" #include "id.h" +#include "ruby/node.h" +#include "vm.h" /* * Document-class: Enumerable::Enumerator @@ -141,7 +143,7 @@ enum_each_slice(VALUE obj, SEL sel, VALUE n) args[0] = rb_ary_new2(size); args[1] = (VALUE)size; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, each_slice_i, (VALUE)args); + rb_objc_block_call(obj, selEach, 0, 0, each_slice_i, (VALUE)args); ary = args[0]; if (RARRAY_LEN(ary) > 0) rb_yield(ary); @@ -198,7 +200,7 @@ enum_each_cons(VALUE obj, SEL sel, VALUE n) args[0] = rb_ary_new2(size); args[1] = (VALUE)size; - rb_objc_block_call(obj, selEach, cacheEach, 0, 0, each_cons_i, (VALUE)args); + rb_objc_block_call(obj, selEach, 0, 0, each_cons_i, (VALUE)args); return Qnil; } @@ -321,7 +323,7 @@ enumerator_each(VALUE obj, SEL sel) argc = RARRAY_LEN(e->args); argv = RARRAY_PTR(e->args); } - return rb_objc_block_call(e->obj, e->sel, NULL, argc, (VALUE *)argv, + return rb_objc_block_call(e->obj, e->sel, argc, (VALUE *)argv, enumerator_each_i, (VALUE)e); } @@ -356,7 +358,7 @@ enumerator_with_index(VALUE obj, SEL sel) argc = RARRAY_LEN(e->args); argv = RARRAY_PTR(e->args); } - return rb_objc_block_call(e->obj, e->sel, NULL, argc, (VALUE *)argv, + return rb_objc_block_call(e->obj, e->sel, argc, (VALUE *)argv, enumerator_with_index_i, (VALUE)&memo); } diff --git a/hash.c b/hash.c index d31dc9b4b..b31bbce93 100644 --- a/hash.c +++ b/hash.c @@ -31,8 +31,6 @@ VALUE rb_cRubyHash; static ID id_yield; -static void *defaultCache = NULL; -static void *hashCache = NULL; static SEL selFlattenBang = 0; static SEL selDefault = 0; static SEL selHash = 0; @@ -40,7 +38,7 @@ static SEL selHash = 0; VALUE rb_hash(VALUE obj) { - VALUE v = rb_vm_call_with_cache(hashCache, obj, selHash, 0, NULL); + VALUE v = rb_vm_call(obj, selHash, 0, NULL, false); retry: switch (TYPE(v)) { case T_FIXNUM: @@ -437,8 +435,7 @@ rhash_aref(VALUE hash, SEL sel, VALUE key) && RHASH(hash)->ifnone == Qnil) { return Qnil; } - return rb_vm_call_with_cache(defaultCache, hash, selDefault, - 1, &key); + return rb_vm_call(hash, selDefault, 1, &key, false); } return val; } @@ -1768,8 +1765,6 @@ Init_Hash(void) selFlattenBang = sel_registerName("flatten!:"); selDefault = sel_registerName("default:"); selHash = sel_registerName("hash"); - defaultCache = rb_vm_get_call_cache(selDefault); - hashCache = rb_vm_get_call_cache(selHash); id_yield = rb_intern("yield"); diff --git a/id.c b/id.c index cc8402c64..e9bca897e 100644 --- a/id.c +++ b/id.c @@ -106,8 +106,6 @@ Init_id(void) selLambda = sel_registerName("lambda"); selObjectForKey = sel_registerName("objectForKey:"); selSetObjectForKey = sel_registerName("setObject:forKey:"); - - cacheEach = rb_vm_get_call_cache(selEach); #endif idAREF = rb_intern("[]"); diff --git a/id.h b/id.h index 8525e5655..71de822de 100644 --- a/id.h +++ b/id.h @@ -119,6 +119,5 @@ extern SEL selSetObjectForKey; extern ID idIncludedModules; extern ID idIncludedInClasses; extern ID idAncestors; -extern void *cacheEach; #endif #endif /* RUBY_ID_H */ diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index 9bfa0f0db..b89febed0 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -967,8 +967,6 @@ int rb_block_given_p(void); void rb_need_block(void); VALUE rb_iterate(VALUE(*)(VALUE),VALUE,VALUE(*)(ANYARGS),VALUE); VALUE rb_block_call(VALUE,ID,int,VALUE*,VALUE(*)(ANYARGS),VALUE); -VALUE rb_objc_block_call(VALUE obj, SEL sel, void *cache, int argc, - VALUE *argv, VALUE (*bl_proc) (ANYARGS), VALUE data2); VALUE rb_rescue(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE); VALUE rb_rescue2(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE,...); VALUE rb_ensure(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE); diff --git a/object.c b/object.c index 091ca7594..fc4ad3f35 100644 --- a/object.c +++ b/object.c @@ -41,18 +41,11 @@ VALUE rb_cFalseClass; static ID id_eq, id_match, id_inspect, id_init_copy; static SEL eqlSel = 0; -static void *eqlCache = NULL; - -static void *allocCache = NULL; -static void *initializeCache = NULL; -static void *initialize2Cache = NULL; -static void *eqCache = NULL; -static void *dupCache = NULL; inline VALUE rb_send_dup(VALUE obj) { - return rb_vm_call_with_cache(dupCache, obj, selDup, 0, NULL); + return rb_vm_call(obj, selDup, 0, NULL, false); } /* @@ -70,7 +63,7 @@ rb_equal(VALUE obj1, VALUE obj2) if (obj1 == obj2) { return Qtrue; } - VALUE result = rb_vm_call_with_cache(eqCache, obj1, selEq, 1, &obj2); + VALUE result = rb_vm_call(obj1, selEq, 1, &obj2, false); if (RTEST(result)) { return Qtrue; } @@ -86,7 +79,7 @@ rb_equal_imp(VALUE obj1, SEL sel, VALUE obj2) int rb_eql(VALUE obj1, VALUE obj2) { - return RTEST(rb_vm_call_with_cache(eqlCache, obj1, eqlSel, 1, &obj2)); + return RTEST(rb_vm_call(obj1, eqlSel, 1, &obj2, false)); } /* @@ -147,7 +140,7 @@ rb_obj_not(VALUE obj, SEL sel) static VALUE rb_obj_not_equal(VALUE obj1, SEL sel, VALUE obj2) { - VALUE result = rb_vm_call_with_cache(eqCache, obj1, selEq, 1, &obj2); + VALUE result = rb_vm_call(obj1, selEq, 1, &obj2, false); return RTEST(result) ? Qfalse : Qtrue; } @@ -1932,7 +1925,7 @@ rb_obj_alloc0(VALUE klass) // Fast path! return rb_robject_allocate_instance(klass); } - return rb_vm_call_with_cache(allocCache, klass, selAlloc, 0, NULL); + return rb_vm_call(klass, selAlloc, 0, NULL, false); } VALUE @@ -1973,12 +1966,10 @@ rb_class_new_instance0(int argc, VALUE *argv, VALUE klass) rb_vm_block_t *block = rb_vm_current_block(); if (argc == 0) { - rb_vm_call_with_cache2(initializeCache, block, obj, CLASS_OF(obj), - selInitialize, argc, argv); + rb_vm_call2(block, obj, CLASS_OF(obj), selInitialize, argc, argv); } else { - rb_vm_call_with_cache2(initialize2Cache, block, obj, CLASS_OF(obj), - selInitialize2, argc, argv); + rb_vm_call2(block, obj, CLASS_OF(obj), selInitialize2, argc, argv); } return obj; @@ -2987,13 +2978,7 @@ Init_Object(void) RCLASS_SET_VERSION_FLAG(rb_cRubyObject, RCLASS_IS_OBJECT_SUBCLASS); rb_define_object_special_methods(rb_cRubyObject); - allocCache = rb_vm_get_call_cache(selAlloc); - initializeCache = rb_vm_get_call_cache(selInitialize); - initialize2Cache = rb_vm_get_call_cache(selInitialize2); - eqCache = rb_vm_get_call_cache(selEq); - dupCache = rb_vm_get_call_cache(selDup); eqlSel = sel_registerName("eql?:"); - eqlCache = rb_vm_get_call_cache(eqlSel); rb_objc_define_method(*(VALUE *)rb_cModule, "alloc", rb_module_s_alloc, 0); rb_objc_define_method(*(VALUE *)rb_cClass, "alloc", rb_class_s_alloc, 0); diff --git a/proc.c b/proc.c index 388bd1d5c..133db9812 100644 --- a/proc.c +++ b/proc.c @@ -1063,8 +1063,12 @@ rb_method_call(VALUE method, SEL sel, int argc, VALUE *argv) } } + VALUE result = Qnil; +#if 0 + // TODO VALUE result = rb_vm_call_with_cache2(data->cache, NULL, data->recv, data->oclass, data->sel, argc, argv); +#endif if (safe >= 0) { rb_set_safe_level_force(safe); diff --git a/process.c b/process.c index 93ec4da93..78dcf6f6d 100644 --- a/process.c +++ b/process.c @@ -16,6 +16,8 @@ #include "ruby/io.h" #include "ruby/util.h" #include "id.h" +#include "ruby/node.h" +#include "vm.h" #include #include @@ -1819,8 +1821,7 @@ save_env(VALUE save) VALUE env = rb_const_get(rb_cObject, rb_intern("ENV")); if (RTEST(env)) { VALUE ary = hide_obj(rb_ary_new()); - rb_objc_block_call(env, selEach, cacheEach, 0, 0, save_env_i, - (VALUE)ary); + rb_objc_block_call(env, selEach, 0, 0, save_env_i, (VALUE)ary); rb_ary_store(save, EXEC_OPTION_ENV, ary); } rb_ary_store(save, EXEC_OPTION_UNSETENV_OTHERS, Qtrue); diff --git a/range.c b/range.c index 0a9e2ca65..ec4f86afd 100644 --- a/range.c +++ b/range.c @@ -18,7 +18,6 @@ VALUE rb_cRange; static SEL selUpto, selBeg, selEnd, selExcludeEnd, selInclude; -static void *cacheUpto = NULL; #define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0]) #define RANGE_END(r) (RSTRUCT(r)->as.ary[1]) @@ -371,7 +370,7 @@ range_step(VALUE range, SEL sel, int argc, VALUE *argv) args[1] = EXCL(range) ? Qtrue : Qfalse; iter[0] = INT2FIX(1); iter[1] = step; - rb_objc_block_call(b, selUpto, cacheUpto, 2, args, step_i, (VALUE)iter); + rb_objc_block_call(b, selUpto, 2, args, step_i, (VALUE)iter); } else { VALUE args[2]; @@ -443,7 +442,7 @@ range_each(VALUE range, SEL sel) args[0] = end; args[1] = EXCL(range) ? Qtrue : Qfalse; - rb_objc_block_call(beg, selUpto, cacheUpto, 2, args, rb_yield, 0); + rb_objc_block_call(beg, selUpto, 2, args, rb_yield, 0); } else { range_each_func(range, each_i, NULL); @@ -515,7 +514,7 @@ range_first(VALUE range, SEL sel, int argc, VALUE *argv) rb_scan_args(argc, argv, "1", &n); ary[0] = n; ary[1] = rb_ary_new2(NUM2LONG(n)); - rb_objc_block_call(range, selEach, cacheEach, 0, 0, first_i, (VALUE)ary); + rb_objc_block_call(range, selEach, 0, 0, first_i, (VALUE)ary); return ary[1]; } @@ -1000,7 +999,6 @@ Init_Range(void) rb_objc_define_method(rb_cRange, "cover?", range_cover, 1); selUpto = sel_registerName("upto:"); - cacheUpto = rb_vm_get_call_cache(selUpto); selBeg = sel_registerName("begin"); selEnd = sel_registerName("end"); selExcludeEnd = sel_registerName("exclude_end?"); diff --git a/vm.cpp b/vm.cpp index d8b6cb70e..efe4f31fa 100644 --- a/vm.cpp +++ b/vm.cpp @@ -345,6 +345,10 @@ RoxorVM::RoxorVM(void) return_from_block = -1; current_super_class = NULL; current_super_sel = 0; + + mcache = (struct mcache *)malloc(sizeof(struct mcache) * MCACHE_SIZE); + assert(mcache != NULL); + memset(mcache, 0, sizeof(struct mcache) * MCACHE_SIZE); } static inline void * @@ -406,6 +410,10 @@ RoxorVM::RoxorVM(const RoxorVM &vm) throw_exc = NULL; current_super_class = NULL; current_super_sel = 0; + + mcache = (struct mcache *)malloc(sizeof(struct mcache) * MCACHE_SIZE); + assert(mcache != NULL); + memcpy(mcache, vm.mcache, sizeof(struct mcache) * MCACHE_SIZE); } RoxorVM::~RoxorVM(void) @@ -421,6 +429,8 @@ RoxorVM::~RoxorVM(void) GC_RELEASE(broken_with); GC_RELEASE(last_status); GC_RELEASE(errinfo); + + free(mcache); } static void @@ -677,33 +687,6 @@ rb_vm_get_constant_cache(const char *name) return GET_CORE()->constant_cache_get(rb_intern(name)); } -struct mcache * -RoxorCore::method_cache_get(SEL sel, bool super) -{ - if (super) { - struct mcache *cache = (struct mcache *)malloc(sizeof(struct mcache)); - cache->flag = 0; - // TODO store the cache somewhere and invalidate it appropriately. - return cache; - } - std::map::iterator iter = mcache.find(sel); - if (iter == mcache.end()) { - struct mcache *cache = (struct mcache *)malloc(sizeof(struct mcache)); - cache->flag = 0; - mcache[sel] = cache; - return cache; - } - return iter->second; -} - -extern "C" -void * -rb_vm_get_method_cache(SEL sel) -{ - const bool super = strncmp(sel_getName(sel), "__super__:", 10) == 0; - return GET_CORE()->method_cache_get(sel, super); -} - rb_vm_method_node_t * RoxorCore::method_node_get(IMP imp, bool create) { @@ -875,10 +858,13 @@ RoxorCore::method_added(Class klass, SEL sel) void RoxorCore::invalidate_method_cache(SEL sel) { +#if 0 // TODO std::map::iterator iter = mcache.find(sel); if (iter != mcache.end()) { iter->second->flag = 0; } +#endif + memset(GET_VM()->mcache, 0, sizeof(struct mcache) * MCACHE_SIZE); } rb_vm_method_node_t * @@ -3216,20 +3202,6 @@ rb_vm_pop_binding(void) GET_VM()->pop_current_binding(false); } -extern "C" -void * -rb_vm_get_call_cache(SEL sel) -{ - return GET_CORE()->method_cache_get(sel, false); -} - -extern "C" -void * -rb_vm_get_call_cache2(SEL sel, unsigned char super) -{ - return GET_CORE()->method_cache_get(sel, super); -} - // Should be used inside a method implementation. extern "C" int @@ -5144,6 +5116,8 @@ Init_PostVM(void) rb_define_const(rb_cThGroup, "Default", group); } +extern "C" void rb_vm_dispatch_finalize(void); + extern "C" void rb_vm_finalize(void) @@ -5158,6 +5132,7 @@ rb_vm_finalize(void) GET_CORE()->get_functions_compiled()); #endif + rb_vm_dispatch_finalize(); // XXX: deleting the core is not safe at this point because there might be // threads still running and trying to unregister. diff --git a/vm.h b/vm.h index 8e3fe0c1c..05c7a4bda 100644 --- a/vm.h +++ b/vm.h @@ -307,11 +307,8 @@ void rb_vm_alias(VALUE klass, ID name, ID def); bool rb_vm_copy_method(Class klass, Method method); void rb_vm_copy_methods(Class from_class, Class to_class); VALUE rb_vm_call(VALUE self, SEL sel, int argc, const VALUE *args, bool super); -VALUE rb_vm_call_with_cache(void *cache, VALUE self, SEL sel, int argc, - const VALUE *argv); -VALUE rb_vm_call_with_cache2(void *cache, rb_vm_block_t *block, VALUE self, - VALUE klass, SEL sel, int argc, const VALUE *argv); -void *rb_vm_get_call_cache(SEL sel); +VALUE rb_vm_call2(rb_vm_block_t *block, VALUE self, VALUE klass, SEL sel, + int argc, const VALUE *argv); VALUE rb_vm_yield(int argc, const VALUE *argv); VALUE rb_vm_yield_under(VALUE klass, VALUE self, int argc, const VALUE *argv); bool rb_vm_respond_to(VALUE obj, SEL sel, bool priv); @@ -326,6 +323,10 @@ VALUE rb_vm_get_outer(VALUE klass); VALUE rb_vm_catch(VALUE tag); VALUE rb_vm_throw(VALUE tag, VALUE value); +// TODO defined in vm_eval.c, should be renamed as rb_vm_block_call +VALUE rb_objc_block_call(VALUE obj, SEL sel, int argc, VALUE *argv, + VALUE (*bl_proc) (ANYARGS), VALUE data2); + static inline void rb_vm_regrow_robject_slots(struct RObject *obj, unsigned int new_num_slot) { @@ -545,10 +546,12 @@ typedef VALUE rb_vm_long_arity_bstub_t(IMP imp, id self, SEL sel, int argc, const VALUE *argv); struct mcache { -#define MCACHE_RCALL 0x1 // Ruby call -#define MCACHE_OCALL 0x2 // Objective-C call -#define MCACHE_FCALL 0x4 // C call +#define MCACHE_RCALL 0x1 // Ruby call +#define MCACHE_OCALL 0x2 // Objective-C call +#define MCACHE_FCALL 0x4 // C call +#define MCACHE_SUPER 0x8 // super call (only applied with RCALL or OCALL) uint8_t flag; + SEL sel; union { struct { Class klass; @@ -638,8 +641,7 @@ class RoxorCore { std::map ruby_imps; std::map ruby_methods; - // Method and constant caches. - std::map mcache; + // Constant cache. std::map ccache; // Instance variable slots cache. @@ -780,7 +782,6 @@ class RoxorCore { char *path, size_t path_len, unsigned long *ln, char *name, size_t name_len); - struct mcache *method_cache_get(SEL sel, bool super); void invalidate_method_cache(SEL sel); rb_vm_method_node_t *method_node_get(IMP imp, bool create=false); rb_vm_method_node_t *method_node_get(Method m, bool create=false); @@ -910,6 +911,9 @@ class RoxorVM { return RoxorVM::main; } +#define MCACHE_SIZE 0x1000 + struct mcache *mcache; + private: // Cache to avoid allocating the same block twice. std::map blocks; diff --git a/vm_eval.c b/vm_eval.c index 163f71793..4de7d16b7 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -40,10 +40,8 @@ rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, int scope, } } - void *cache = rb_vm_get_call_cache(sel); rb_vm_block_t *block = pass_current_block ? rb_vm_current_block() : NULL; - return rb_vm_call_with_cache2(cache, block, recv, CLASS_OF(recv), - sel, argc, argv); + return rb_vm_call2(block, recv, CLASS_OF(recv), sel, argc, argv); } /* @@ -259,14 +257,11 @@ rb_f_loop(VALUE rcv, SEL sel) } VALUE -rb_objc_block_call(VALUE obj, SEL sel, void *cache, int argc, VALUE *argv, - VALUE (*bl_proc) (ANYARGS), VALUE data2) +rb_objc_block_call(VALUE obj, SEL sel, int argc, VALUE *argv, + VALUE (*bl_proc) (ANYARGS), VALUE data2) { rb_vm_block_t *b = rb_vm_create_block((IMP)bl_proc, obj, data2); - if (cache == NULL) { - cache = rb_vm_get_call_cache(sel); - } - return rb_vm_call_with_cache2(cache, b, obj, 0, sel, argc, argv); + return rb_vm_call2(b, obj, 0, sel, argc, argv); } VALUE @@ -282,7 +277,7 @@ rb_block_call(VALUE obj, ID mid, int argc, VALUE *argv, snprintf(buf, sizeof buf, "%s:", rb_id2name(mid)); sel = sel_registerName(buf); } - return rb_objc_block_call(obj, sel, NULL, argc, argv, bl_proc, data2); + return rb_objc_block_call(obj, sel, argc, argv, bl_proc, data2); } VALUE