[macruby-changes] [3927] MacRuby/branches/vm-mcache

source_changes at macosforge.org source_changes at macosforge.org
Tue Apr 13 20:07:31 PDT 2010


Revision: 3927
          http://trac.macosforge.org/projects/ruby/changeset/3927
Author:   lsansonetti at apple.com
Date:     2010-04-13 20:07:29 -0700 (Tue, 13 Apr 2010)
Log Message:
-----------
experimental per-VM method cache

Modified Paths:
--------------
    MacRuby/branches/vm-mcache/array.c
    MacRuby/branches/vm-mcache/compar.c
    MacRuby/branches/vm-mcache/compiler.cpp
    MacRuby/branches/vm-mcache/compiler.h
    MacRuby/branches/vm-mcache/dispatcher.cpp
    MacRuby/branches/vm-mcache/enum.c
    MacRuby/branches/vm-mcache/enumerator.c
    MacRuby/branches/vm-mcache/hash.c
    MacRuby/branches/vm-mcache/id.c
    MacRuby/branches/vm-mcache/id.h
    MacRuby/branches/vm-mcache/include/ruby/ruby.h
    MacRuby/branches/vm-mcache/object.c
    MacRuby/branches/vm-mcache/proc.c
    MacRuby/branches/vm-mcache/process.c
    MacRuby/branches/vm-mcache/range.c
    MacRuby/branches/vm-mcache/vm.cpp
    MacRuby/branches/vm-mcache/vm.h
    MacRuby/branches/vm-mcache/vm_eval.c

Modified: MacRuby/branches/vm-mcache/array.c
===================================================================
--- MacRuby/branches/vm-mcache/array.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/array.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -1889,8 +1889,8 @@
     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;
 }

Modified: MacRuby/branches/vm-mcache/compar.c
===================================================================
--- MacRuby/branches/vm-mcache/compar.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/compar.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
     rb_objc_define_method(rb_mComparable, "between?", cmp_between, 2);
 
     cmp = sel_registerName("<=>:");
-    cmp_cache = rb_vm_get_call_cache(cmp);
 }

Modified: MacRuby/branches/vm-mcache/compiler.cpp
===================================================================
--- MacRuby/branches/vm-mcache/compiler.cpp	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/compiler.cpp	2010-04-14 03:07:29 UTC (rev 3927)
@@ -268,7 +268,6 @@
     Value *condVal;
     if (comparedToVal != NULL) {
 	std::vector<Value *> 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 @@
 {
     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<Function>(module->getOrInsertFunction(name, \
-			RubyObjTy, PtrTy, RubyObjTy, RubyObjTy, NULL)); \
+			RubyObjTy, RubyObjTy, RubyObjTy, NULL)); \
 	} \
 	func = storage; \
     } \
@@ -474,7 +473,6 @@
     }
 
     std::vector<Value *> params;
-    params.push_back(compile_mcache(sel, false));
     params.push_back(selfVal);
     params.push_back(otherVal);
 
@@ -485,17 +483,15 @@
 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<Function>
 	    (module->getOrInsertFunction("rb_vm_when_splat",
-					 RubyObjTy, PtrTy, Int1Ty,
-					 RubyObjTy, RubyObjTy, NULL));
+					 RubyObjTy, Int1Ty, RubyObjTy,
+					 RubyObjTy, NULL));
     }
 
     std::vector<Value *> 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);
@@ -571,55 +567,6 @@
 }
 
 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<Function>(module->getOrInsertFunction(
-			"rb_vm_get_call_cache2", PtrTy, PtrTy, Int8Ty,
-			NULL));
-    }
-
-    std::vector<Value *> 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<SEL, GlobalVariable *>::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)
 {
     struct ccache *cache = GET_CORE()->constant_cache_get(name);
@@ -757,10 +704,9 @@
 RoxorCompiler::compile_dispatch_call(std::vector<Value *> &params)
 {
     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<const Type *> types;
-	types.push_back(PtrTy);
 	types.push_back(RubyObjTy);
 	types.push_back(RubyObjTy);
 	types.push_back(PtrTy);
@@ -805,7 +751,6 @@
 
     std::vector<Value *> 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 @@
 	    return NULL;
 	}
 	
-	Value *val = params[2]; // self
+	Value *val = params[1]; // self
 
 	Function *f = bb->getParent();
 
@@ -2236,7 +2181,7 @@
 
 	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 @@
 	    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 @@
 	Function *opt_func = NULL;
 
 	if (sel == selLTLT) {
-	    opt_func = cast<Function>(module->getOrInsertFunction("rb_vm_fast_shift",
-			RubyObjTy, RubyObjTy, RubyObjTy, PtrTy, Int1Ty, NULL));
+	    opt_func = cast<Function>(module->getOrInsertFunction(
+			"rb_vm_fast_shift",
+			RubyObjTy, RubyObjTy, RubyObjTy, Int1Ty, NULL));
 	}
 	else if (sel == selAREF) {
-	    opt_func = cast<Function>(module->getOrInsertFunction("rb_vm_fast_aref",
-			RubyObjTy, RubyObjTy, RubyObjTy, PtrTy, Int1Ty, NULL));
+	    opt_func = cast<Function>(module->getOrInsertFunction(
+			"rb_vm_fast_aref",
+			RubyObjTy, RubyObjTy, RubyObjTy, Int1Ty, NULL));
 	}
 	else if (sel == selASET) {
-	    opt_func = cast<Function>(module->getOrInsertFunction("rb_vm_fast_aset",
-			RubyObjTy, RubyObjTy, RubyObjTy, RubyObjTy, PtrTy,
-			Int1Ty, NULL));
+	    opt_func = cast<Function>(module->getOrInsertFunction(
+			"rb_vm_fast_aset",
+			RubyObjTy, RubyObjTy, RubyObjTy, RubyObjTy, Int1Ty,
+			NULL));
 	}
 	else {
 	    abort();
 	}
 
 	std::vector<Value *> 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 @@
 
 	bb = thenBB;
 	std::vector<Value *> 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 @@
 
 	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<ConstantInt>(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 @@
 		    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 @@
 			? 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 @@
 		    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 @@
 		}
 
 		std::vector<Value *> 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 @@
 		// Prepare the dispatcher parameters.
 		std::vector<Value *> params;
 
-		// Method cache (and prepare the selector).
+		// Prepare the selector.
 		Value *sel_val;
 		SEL sel;
 		if (mid != 0) {
@@ -4241,18 +4072,13 @@
 				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 {
 		    assert(super_call);
 		    // 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 @@
 			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 @@
 		}
 
 		std::vector<Value *> 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 @@
 		    // dispatch #each on the receiver
 		    std::vector<Value *> params;
 
-		    params.push_back(compile_mcache((is_lambda ? selLambda : selEach), false));
 		    params.push_back(current_self);
 
 		    if (!is_lambda) {
@@ -5252,9 +5076,11 @@
 			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 @@
 
 		std::vector<Value *> 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 @@
 	function->getEntryBlock().getInstList();
     bb = &function->getEntryBlock();
 
-    // Compile method caches.
-
-    Function *getMethodCacheFunc = cast<Function>(module->getOrInsertFunction(
-		"rb_vm_get_method_cache",
-		PtrTy, PtrTy, NULL));
-
-    for (std::map<SEL, GlobalVariable *>::iterator i = mcaches.begin();
-	 i != mcaches.end();
-	 ++i) {
-
-	SEL sel = i->first;
-	GlobalVariable *gvar = i->second;
-
-	std::vector<Value *> 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<Instruction>(load);
-	if (load_insn != NULL) {
-	    list.insert(list.begin(), load_insn);
-	}
-    }
-
     // Compile constant caches.
 	
     Function *getConstCacheFunc = cast<Function>(module->getOrInsertFunction(

Modified: MacRuby/branches/vm-mcache/compiler.h
===================================================================
--- MacRuby/branches/vm-mcache/compiler.h	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/compiler.h	2010-04-14 03:07:29 UTC (rev 3927)
@@ -305,8 +305,6 @@
 	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 @@
 	Function *compile_main_function(NODE *node);
 
     private:
-	std::map<SEL, GlobalVariable *> mcaches;
 	std::map<ID, GlobalVariable *> ccaches;
 	std::map<SEL, GlobalVariable *> sels;
 	std::map<ID, GlobalVariable *> ids;
@@ -398,7 +395,6 @@
 	GlobalVariable *cStandardError_gvar;
 	std::vector<GlobalVariable *> 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,

Modified: MacRuby/branches/vm-mcache/dispatcher.cpp
===================================================================
--- MacRuby/branches/vm-mcache/dispatcher.cpp	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/dispatcher.cpp	2010-04-14 03:07:29 UTC (rev 3927)
@@ -23,6 +23,7 @@
 #include <dlfcn.h>
 
 #define ROXOR_VM_DEBUG		0
+#define ROXOR_MCACHE_DEBUG	1
 #define MAX_DISPATCH_ARGS 	100
 
 static force_inline void
@@ -347,10 +348,8 @@
 	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 @@
     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,18 +590,44 @@
 #if ROXOR_VM_DEBUG
     bool cached = true;
 #endif
+    int cache_hash = 0;
     bool cache_method = true;
 
+    struct mcache *cache;
+    if (opt == DISPATCH_SUPER) {
+	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();
 
-    // 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).
-    if (opt == DISPATCH_SUPER) {
-	cache->flag = 0;
-    }
-
     if (cache->flag == 0) {
 recache:
 #if ROXOR_VM_DEBUG
@@ -620,6 +666,11 @@
 		// 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 @@
     }
 
 dispatch:
-    if (cache->flag == MCACHE_RCALL) {
+    if (cache->flag & MCACHE_RCALL) {
 	if (rcache.klass != klass) {
 	    goto recache;
 	}
@@ -741,7 +792,7 @@
 	}
 
 #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 @@
 		block,
 		argc,
 		opt,
-		cache,
+		cache_hash,
 		cached ? "true" : "false");
 #endif
 
@@ -820,7 +871,7 @@
 
 	return v;
     }
-    else if (cache->flag == MCACHE_OCALL) {
+    else if (cache->flag & MCACHE_OCALL) {
 	if (ocache.klass != klass) {
 	    goto recache;
 	}
@@ -856,13 +907,14 @@
 	}
 
 #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 @@
 	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 @@
 
 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,49 +1118,26 @@
 	~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);
+    return __rb_vm_dispatch(GET_VM(), 0, self, (Class)klass, sel, block,
+	    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);
-}
-
 // The rb_vm_fast_* functions don't check if the selector has been redefined or
 // not, because this is already handled by the compiler.
 // Also, fixnums and floats are already handled.
@@ -1130,122 +1159,134 @@
 
 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 @@
 	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 @@
 	    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 @@
     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 @@
     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 @@
 
 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 @@
 #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 @@
 		}
 		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 @@
 	}
     }
     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 @@
     } 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);

Modified: MacRuby/branches/vm-mcache/enum.c
===================================================================
--- MacRuby/branches/vm-mcache/enum.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/enum.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -81,7 +81,8 @@
     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 @@
     }
 
     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 @@
 
     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 @@
 
     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 @@
     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 @@
     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 @@
     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 @@
 {
     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 @@
 	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 @@
 
     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 @@
     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 @@
 	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 @@
     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 @@
 {
     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 @@
 {
     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 @@
 {
     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 @@
 {
     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 @@
     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 @@
     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 @@
     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 @@
 
     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 @@
 
     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 @@
     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 @@
 
     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 @@
     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 @@
 	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 @@
 
     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 @@
 
     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 @@
 
     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 @@
     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 @@
 #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) {

Modified: MacRuby/branches/vm-mcache/enumerator.c
===================================================================
--- MacRuby/branches/vm-mcache/enumerator.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/enumerator.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -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 @@
     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 @@
     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 @@
 	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 @@
 	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);
 }
 

Modified: MacRuby/branches/vm-mcache/hash.c
===================================================================
--- MacRuby/branches/vm-mcache/hash.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/hash.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -31,8 +31,6 @@
 
 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 @@
 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(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 @@
     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");
 

Modified: MacRuby/branches/vm-mcache/id.c
===================================================================
--- MacRuby/branches/vm-mcache/id.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/id.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -106,8 +106,6 @@
     selLambda = sel_registerName("lambda");
     selObjectForKey = sel_registerName("objectForKey:");
     selSetObjectForKey = sel_registerName("setObject:forKey:");
-
-    cacheEach = rb_vm_get_call_cache(selEach);
 #endif
 
     idAREF = rb_intern("[]");

Modified: MacRuby/branches/vm-mcache/id.h
===================================================================
--- MacRuby/branches/vm-mcache/id.h	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/id.h	2010-04-14 03:07:29 UTC (rev 3927)
@@ -119,6 +119,5 @@
 extern ID idIncludedModules;
 extern ID idIncludedInClasses;
 extern ID idAncestors;
-extern void *cacheEach;
 #endif
 #endif /* RUBY_ID_H */

Modified: MacRuby/branches/vm-mcache/include/ruby/ruby.h
===================================================================
--- MacRuby/branches/vm-mcache/include/ruby/ruby.h	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/include/ruby/ruby.h	2010-04-14 03:07:29 UTC (rev 3927)
@@ -967,8 +967,6 @@
 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);

Modified: MacRuby/branches/vm-mcache/object.c
===================================================================
--- MacRuby/branches/vm-mcache/object.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/object.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -41,18 +41,11 @@
 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 @@
     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 @@
 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 @@
 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 @@
 	// 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_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 @@
     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);

Modified: MacRuby/branches/vm-mcache/proc.c
===================================================================
--- MacRuby/branches/vm-mcache/proc.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/proc.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -1063,8 +1063,12 @@
 	}
     }
 
+    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);

Modified: MacRuby/branches/vm-mcache/process.c
===================================================================
--- MacRuby/branches/vm-mcache/process.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/process.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -16,6 +16,8 @@
 #include "ruby/io.h"
 #include "ruby/util.h"
 #include "id.h"
+#include "ruby/node.h"
+#include "vm.h"
 
 #include <stdio.h>
 #include <errno.h>
@@ -1819,8 +1821,7 @@
         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);

Modified: MacRuby/branches/vm-mcache/range.c
===================================================================
--- MacRuby/branches/vm-mcache/range.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/range.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -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 @@
 	    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 @@
 
 	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 @@
     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 @@
     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?");

Modified: MacRuby/branches/vm-mcache/vm.cpp
===================================================================
--- MacRuby/branches/vm-mcache/vm.cpp	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/vm.cpp	2010-04-14 03:07:29 UTC (rev 3927)
@@ -345,6 +345,10 @@
     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 @@
     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 @@
     GC_RELEASE(broken_with);
     GC_RELEASE(last_status);
     GC_RELEASE(errinfo);
+
+    free(mcache);
 }
 
 static void
@@ -677,33 +687,6 @@
     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<SEL, struct mcache *>::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 @@
 void
 RoxorCore::invalidate_method_cache(SEL sel)
 {
+#if 0 // TODO
     std::map<SEL, struct mcache *>::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 @@
     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 @@
     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 @@
 	    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.

Modified: MacRuby/branches/vm-mcache/vm.h
===================================================================
--- MacRuby/branches/vm-mcache/vm.h	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/vm.h	2010-04-14 03:07:29 UTC (rev 3927)
@@ -307,11 +307,8 @@
 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_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 @@
 				       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 @@
 	std::map<IMP, rb_vm_method_node_t *> ruby_imps;
 	std::map<Method, rb_vm_method_node_t *> ruby_methods;
 
-	// Method and constant caches.
-	std::map<SEL, struct mcache *> mcache;
+	// Constant cache.
 	std::map<ID, struct ccache *> ccache;
 
 	// Instance variable slots cache.
@@ -780,7 +782,6 @@
 		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 @@
 	    return RoxorVM::main;
 	}
 
+#define MCACHE_SIZE 0x1000
+	struct mcache *mcache;
+
     private:
 	// Cache to avoid allocating the same block twice.
 	std::map<void *, rb_vm_block_t *> blocks;

Modified: MacRuby/branches/vm-mcache/vm_eval.c
===================================================================
--- MacRuby/branches/vm-mcache/vm_eval.c	2010-04-14 03:01:30 UTC (rev 3926)
+++ MacRuby/branches/vm-mcache/vm_eval.c	2010-04-14 03:07:29 UTC (rev 3927)
@@ -40,10 +40,8 @@
 	}
     }
 
-    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 @@
 }
 
 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 @@
 	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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100413/c1545416/attachment-0001.html>


More information about the macruby-changes mailing list