[macruby-changes] [2531] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Sep 9 23:15:09 PDT 2009


Revision: 2531
          http://trac.macosforge.org/projects/ruby/changeset/2531
Author:   lsansonetti at apple.com
Date:     2009-09-09 23:15:04 -0700 (Wed, 09 Sep 2009)
Log Message:
-----------
implemented super from a block

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

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2009-09-10 02:35:15 UTC (rev 2530)
+++ MacRuby/trunk/compiler.cpp	2009-09-10 06:15:04 UTC (rev 2531)
@@ -126,6 +126,7 @@
     setjmpFunc = NULL;
     setScopeFunc = NULL;
     setCurrentClassFunc = NULL;
+    getCacheFunc = NULL;
 
 #if __LP64__
     RubyObjTy = IntTy = Type::Int64Ty;
@@ -532,6 +533,24 @@
 }
 
 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, Type::Int8Ty,
+			NULL));
+    }
+
+    std::vector<Value *> params;
+    params.push_back(sel);
+    params.push_back(ConstantInt::get(Type::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);
@@ -3843,7 +3862,9 @@
 		if (super_call) {
 		    mid = current_mid;
 		}
-		assert(mid > 0);
+		else {
+		    assert(mid > 0);
+		}
 
 		Function::ArgumentListType &fargs =
 		    bb->getParent()->getArgumentList();
@@ -3922,16 +3943,33 @@
 		// Prepare the dispatcher parameters.
 		std::vector<Value *> params;
 
-		// Method cache.
-		const SEL sel = mid_to_sel(mid, positive_arity ? 1 : 0);
-		params.push_back(compile_mcache(sel, super_call));
+		// Method cache (and prepare the selector).
+		Value *sel_val;
+		SEL sel;
+		if (mid != 0) {
+		    sel = mid_to_sel(mid, positive_arity ? 1 : 0);
+		    params.push_back(compile_mcache(sel, super_call));
+		    sel_val = compile_sel(sel);
+		}
+		else {
+		    assert(super_call);
+		    sel = 0;
+		    // A super call outside a method definition (probably
+		    // in a block). Retrieve the SEL as the second parameter
+		    // of the current function.
+		    Function *f = bb->getParent();
+		    Function::arg_iterator arg = f->arg_begin();
+		    arg++; // skip self
+		    sel_val = arg;
+		    params.push_back(compile_get_mcache(sel_val, true));
+		}
 
 		// Self.
 		params.push_back(recv == NULL ? current_self
 			: compile_node(recv));
 
 		// Selector.
-		params.push_back(compile_sel(sel));
+		params.push_back(sel_val);
 
 		// RubySpec requires that we compile the block *after* the
 		// arguments, so we do pass NULL as the block for the moment.
@@ -3954,11 +3992,17 @@
 		// Arguments.
 		int argc = 0;
 		if (nd_type(node) == NODE_ZSUPER) {
-		    params.push_back(ConstantInt::get(Type::Int32Ty,
-				fargs_arity));
+		    const int arity = mid == 0
+			? fargs_arity - 2 // skip dvars and current_block
+			: fargs_arity;
+		    params.push_back(ConstantInt::get(Type::Int32Ty, arity));
 		    Function::ArgumentListType::iterator iter = fargs.begin();
 		    iter++; // skip self
 		    iter++; // skip sel
+		    if (mid == 0) {
+			iter++; // skip dvars
+			iter++; // skip current_block
+		    }
 		    const int rest_pos = current_arity.max == -1
 			? (current_arity.left_req
 				+ (current_arity.real - current_arity.min - 1))
@@ -6608,28 +6652,31 @@
 {
     // VALUE foo(VALUE rcv, SEL sel, int argc, VALUE *argv)
     // {
-    //     return rb_vm_block_eval2(block, rcv, argc, argv);
+    //     return rb_vm_block_eval2(block, rcv, sel, argc, argv);
     // }
     Function *f = cast<Function>(module->getOrInsertFunction("",
 		RubyObjTy, RubyObjTy, PtrTy, Type::Int32Ty, RubyObjPtrTy,
 		NULL));
     Function::arg_iterator arg = f->arg_begin();
     Value *rcv = arg++;
-    arg++; // sel
+    Value *sel = arg++;
     Value *argc = arg++;
     Value *argv = arg++;
 
     bb = BasicBlock::Create("EntryBlock", f);
 
     if (blockEvalFunc == NULL) {
+	// VALUE rb_vm_block_eval2(rb_vm_block_t *b, VALUE self, SEL sel,
+	//	int argc, const VALUE *argv)
 	blockEvalFunc = cast<Function>(module->getOrInsertFunction(
 		    "rb_vm_block_eval2",
-		    RubyObjTy, PtrTy, RubyObjTy, Type::Int32Ty, RubyObjPtrTy,
-		    NULL));
+		    RubyObjTy, PtrTy, RubyObjTy, PtrTy, Type::Int32Ty,
+		    RubyObjPtrTy, NULL));
     }
     std::vector<Value *> params;
     params.push_back(compile_const_pointer(block));
     params.push_back(rcv);
+    params.push_back(sel);
     params.push_back(argc);
     params.push_back(argv);
 

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2009-09-10 02:35:15 UTC (rev 2530)
+++ MacRuby/trunk/compiler.h	2009-09-10 06:15:04 UTC (rev 2531)
@@ -179,6 +179,7 @@
 	Function *setjmpFunc;
 	Function *setScopeFunc;
 	Function *setCurrentClassFunc;
+	Function *getCacheFunc;
 
 	Constant *zeroVal;
 	Constant *oneVal;
@@ -265,6 +266,7 @@
 	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 Instruction *compile_sel(SEL sel, bool add_to_bb=true) {
 	    return compile_const_pointer(sel, PtrTy, add_to_bb);

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-09-10 02:35:15 UTC (rev 2530)
+++ MacRuby/trunk/vm.cpp	2009-09-10 06:15:04 UTC (rev 2531)
@@ -816,7 +816,8 @@
     const long klass_version = RCLASS_VERSION(klass);
     if ((klass_version & RCLASS_IS_RUBY_CLASS) != RCLASS_IS_RUBY_CLASS
 	|| (klass_version & RCLASS_IS_OBJECT_SUBCLASS)
-	    != RCLASS_IS_OBJECT_SUBCLASS) {
+	    != RCLASS_IS_OBJECT_SUBCLASS
+	|| klass == rb_cClass || klass == rb_cModule) {
 	return false;
     }
     return true;
@@ -1070,8 +1071,9 @@
 rb_vm_ivar_get(VALUE obj, ID name, int *slot_cache)
 {
 #if ROXOR_VM_DEBUG
-    printf("get ivar %p.%s slot %d\n", (void *)obj, rb_id2name(name), 
-	    slot_cache == NULL ? -1 : *slot_cache);
+    printf("get ivar <%s %p>.%s slot %d\n",
+	    class_getName((Class)CLASS_OF(obj)), (void *)obj,
+	    rb_id2name(name), slot_cache == NULL ? -1 : *slot_cache);
 #endif
     if (slot_cache == NULL || *slot_cache == -1) {
 	return rb_ivar_get(obj, name);
@@ -1867,11 +1869,11 @@
 		continue;
 	    }
 
-#if ROXOR_DEBUG_VM
+#if ROXOR_VM_DEBUG
 	    printf("lazy copy %c[%s %s] to %s\n",
 		    class_isMetaClass(from_class) ? '+' : '-',
 		    class_getName(from_class),
-		    sel_getName(method_getName(method)),
+		    sel_getName(sel),
 		    class_getName(to_class));
 #endif
 
@@ -2215,8 +2217,9 @@
 }
 
 static force_inline VALUE
-__rb_vm_bcall(VALUE self, VALUE dvars, rb_vm_block_t *b,
-	      IMP pimp, const rb_vm_arity_t &arity, int argc, const VALUE *argv)
+__rb_vm_bcall(VALUE self, SEL sel, VALUE dvars, rb_vm_block_t *b,
+	      IMP pimp, const rb_vm_arity_t &arity, int argc,
+	      const VALUE *argv)
 {
     if ((arity.real != argc) || (arity.max == -1)) {
 	VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * arity.real);
@@ -2231,25 +2234,25 @@
 
     switch (argc) {
 	case 0:
-	    return (*imp)(self, 0, dvars, b);
+	    return (*imp)(self, sel, dvars, b);
 	case 1:
-	    return (*imp)(self, 0, dvars, b, argv[0]);
+	    return (*imp)(self, sel, dvars, b, argv[0]);
 	case 2:
-	    return (*imp)(self, 0, dvars, b, argv[0], argv[1]);
+	    return (*imp)(self, sel, dvars, b, argv[0], argv[1]);
 	case 3:
-	    return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2]);
+	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2]);
 	case 4:
-	    return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3]);
+	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3]);
 	case 5:
-	    return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4]);
+	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4]);
 	case 6:
-	    return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
+	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
 	case 7:
-	    return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
+	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
 	case 8:
-	    return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
+	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
 	case 9:
-	    return (*imp)(self, 0, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
+	    return (*imp)(self, sel, dvars, b, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
     }	
     printf("invalid argc %d\n", argc);
     abort();
@@ -3018,7 +3021,7 @@
     return method_missing((VALUE)self, sel, block, argc, argv, status);
 }
 
-#define MAX_DISPATCH_ARGS 200
+#define MAX_DISPATCH_ARGS 500
 
 static force_inline int
 __rb_vm_resolve_args(VALUE *argv, int argc, va_list ar)
@@ -3807,6 +3810,13 @@
     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
@@ -4002,7 +4012,8 @@
 }
 
 static inline VALUE
-rb_vm_block_eval0(rb_vm_block_t *b, VALUE self, int argc, const VALUE *argv)
+rb_vm_block_eval0(rb_vm_block_t *b, SEL sel, VALUE self, int argc,
+	const VALUE *argv)
 {
     if ((b->flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC) {
 	// Special case for blocks passed with rb_objc_block_call(), to
@@ -4092,7 +4103,7 @@
 	return rb_vm_call_with_cache2(m->cache, NULL, m->recv, m->oclass,
 		m->sel, argc, argv);
     }
-    return __rb_vm_bcall(self, (VALUE)b->dvars, b, b->imp, b->arity,
+    return __rb_vm_bcall(self, sel, (VALUE)b->dvars, b, b->imp, b->arity,
 	    argc, argv);
 }
 
@@ -4100,15 +4111,16 @@
 VALUE
 rb_vm_block_eval(rb_vm_block_t *b, int argc, const VALUE *argv)
 {
-    return rb_vm_block_eval0(b, b->self, argc, argv);
+    return rb_vm_block_eval0(b, NULL, b->self, argc, argv);
 }
 
 extern "C"
 VALUE
-rb_vm_block_eval2(rb_vm_block_t *b, VALUE self, int argc, const VALUE *argv)
+rb_vm_block_eval2(rb_vm_block_t *b, VALUE self, SEL sel, int argc,
+	const VALUE *argv)
 {
     // TODO check given arity and raise exception
-    return rb_vm_block_eval0(b, self, argc, argv);
+    return rb_vm_block_eval0(b, sel, self, argc, argv);
 }
 
 static inline VALUE
@@ -4134,7 +4146,7 @@
 	}
     } finalizer(vm, b);
 
-    return rb_vm_block_eval0(b, b->self, argc, argv);
+    return rb_vm_block_eval0(b, NULL, b->self, argc, argv);
 }
 
 extern "C"
@@ -4176,7 +4188,7 @@
 	}
     } finalizer(vm, b, old_class, old_self);
 
-    return rb_vm_block_eval0(b, b->self, argc, argv);
+    return rb_vm_block_eval0(b, NULL, b->self, argc, argv);
 }
 
 extern "C"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090909/328d0195/attachment-0001.html>


More information about the macruby-changes mailing list