[Mono-patches] r78139 - trunk/mono/mono/mini

Rodrigo Kumpera (kumpera@gmail.com) mono-patches-list at lists.ximian.com
Tue May 29 11:46:07 EDT 2007


Author: kumpera
Date: 2007-05-29 11:46:07 -0400 (Tue, 29 May 2007)
New Revision: 78139

Added:
   trunk/mono/mono/mini/devirtualization.cs
Modified:
   trunk/mono/mono/mini/ChangeLog
   trunk/mono/mono/mini/Makefile.am
   trunk/mono/mono/mini/inssel.brg
Log:
2007-05-29  Rodrigo Kumpera  <kumpera at gmail.com>

	* inssel.brg (mini_emit_virtual_call): Statically dispatch virtual calls to
	sealed classes or methods.
	*devirtualization.cs: tests for the new optimization



Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog	2007-05-29 15:25:03 UTC (rev 78138)
+++ trunk/mono/mono/mini/ChangeLog	2007-05-29 15:46:07 UTC (rev 78139)
@@ -1,3 +1,9 @@
+2007-05-29  Rodrigo Kumpera  <kumpera at gmail.com>
+
+	* inssel.brg (mini_emit_virtual_call): Statically dispatch virtual calls to
+	sealed classes or methods.
+	*devirtualization.cs: tests for the new optimization
+
 2007-05-29  Zoltan Varga  <vargaz at gmail.com>
 
 	* liveness.c (update_gen_kill_set): No need to set VOLATILE flags here, it is done

Modified: trunk/mono/mono/mini/Makefile.am
===================================================================
--- trunk/mono/mono/mini/Makefile.am	2007-05-29 15:25:03 UTC (rev 78138)
+++ trunk/mono/mono/mini/Makefile.am	2007-05-29 15:46:07 UTC (rev 78139)
@@ -232,6 +232,7 @@
 	basic-math.cs	\
 	basic.cs		\
 	exceptions.cs	\
+	devirtualization.cs	\
 	iltests.il.in		\
 	test.cs
 
@@ -252,7 +253,7 @@
 mono_debugger_sources =
 endif
 
-regtests=basic.exe arrays.exe basic-float.exe basic-math.exe basic-long.exe objects.exe basic-calls.exe iltests.exe exceptions.exe bench.exe
+regtests=basic.exe arrays.exe basic-float.exe basic-math.exe basic-long.exe objects.exe basic-calls.exe iltests.exe exceptions.exe bench.exe devirtualization.exe
 regtests2=generics.exe il2tests.exe
 
 common_BURGSRC= $(srcdir)/inssel.brg $(srcdir)/inssel-float.brg

Added: trunk/mono/mono/mini/devirtualization.cs
===================================================================
--- trunk/mono/mono/mini/devirtualization.cs	2007-05-29 15:25:03 UTC (rev 78138)
+++ trunk/mono/mono/mini/devirtualization.cs	2007-05-29 15:46:07 UTC (rev 78139)
@@ -0,0 +1,196 @@
+using System;
+using System.Reflection;
+
+/*
+ * Regression tests for the mono JIT.
+ *
+ * Each test needs to be of the form:
+ *
+ * static int test_<result>_<name> ();
+ *
+ * where <result> is an integer (the value that needs to be returned by
+ * the method to make it pass.
+ * <name> is a user-displayed name used to identify the test.
+ *
+ * The tests can be driven in two ways:
+ * *) running the program directly: Main() uses reflection to find and invoke
+ * 	the test methods (this is useful mostly to check that the tests are correct)
+ * *) with the --regression switch of the jit (this is the preferred way since
+ * 	all the tests will be run with optimizations on and off)
+ *
+ * The reflection logic could be moved to a .dll since we need at least another
+ * regression test file written in IL code to have better control on how
+ * the IL code looks.
+ */
+
+delegate int IntNoArgs();
+
+public class Base {
+
+	public virtual int method1 () {
+		return 1;
+	}
+
+	public virtual int method2 () {
+		return 1;
+	}
+	
+	public virtual int method3 () {
+		return 1;
+	}
+
+	public virtual int method4 () {
+		return 1;
+	}
+
+	public virtual int method5 () {
+		return 1;
+	}
+	
+}
+
+public class Middle : Base {
+	public override int method2 () {
+		return 2;
+	}
+	
+	public override int method4 () {
+		return 2;
+	}
+	
+	public override sealed int method5 () {
+		return 2;
+	}
+}
+
+
+public class OpenFinal : Middle {
+	public override sealed int method4 () {
+		return 3;
+	}
+	
+	static public int staticMethod() {
+		return 3;
+	}
+
+}
+
+sealed public class SealedFinal : Middle {
+	public override int method1 () {
+		return 4;
+	}
+	
+	static public int staticMethod() {
+		return 4;
+	}
+}
+
+
+class Tests {
+
+	static int Main  (string[] args) {
+		return TestDriver.RunTests (typeof (Tests), args);
+	}
+	
+	static public int test_0_sealed_class_devirt_right_method () {
+		SealedFinal x = new SealedFinal ();
+		if (x.method1 () != 4)
+			return 1;
+		if (x.method2 () != 2)
+			return 2;
+		if (x.method3 () != 1)
+			return 1;
+		return 0;	
+	}
+	
+	static public int test_0_sealed_method_devirt_right_method () {
+		OpenFinal x = new OpenFinal ();
+		if (x.method4 () != 3)
+			return 1;
+		if (x.method5 () != 2)
+			return 2;
+		return 0;	
+	}
+	
+	static public int test_0_sealed_class_devirt_right_method_using_delegates () {
+		SealedFinal x = new SealedFinal ();
+		IntNoArgs d1 = new IntNoArgs(x.method1);
+		IntNoArgs d2 = new IntNoArgs(x.method2);
+		IntNoArgs d3 = new IntNoArgs(x.method3);
+		
+		if (d1 () != 4)
+			return 1;
+		if (d2 () != 2)
+			return 2;
+		if (d3 () != 1)
+			return 1;
+		return 0;	
+	}
+	
+	static public int test_0_sealed_method_devirt_right_method_using_delegates () {
+		OpenFinal x = new OpenFinal ();
+		IntNoArgs d1 = new IntNoArgs(x.method4);
+		IntNoArgs d2 = new IntNoArgs(x.method5);
+		
+		if (d1 () != 3)
+			return 1;
+		if (d2 () != 2)
+			return 2;
+		return 0;	
+	}
+	
+	
+	static public int test_0_delegate_over_static_method_devirtualize_ok () {
+		IntNoArgs d1 = new IntNoArgs(OpenFinal.staticMethod);
+		IntNoArgs d2 = new IntNoArgs(SealedFinal.staticMethod);
+		
+		if (d1 () != 3)
+			return 1;
+		if (d2 () != 4)
+			return 2;
+			
+		return 0;
+	}
+
+	static public int test_0_npe_still_happens() {
+		OpenFinal x = null;
+		SealedFinal y = null;
+		
+		try {
+			y.method1();
+			return 1;
+		} catch(NullReferenceException e) {
+			;//ok
+		}
+
+		try {
+			y.method2();
+			return 2;
+		} catch(NullReferenceException e) {
+			;//ok
+		}
+
+		try {
+			y.method3();
+			return 3;
+		} catch(NullReferenceException e) {
+			;//ok
+		}
+		
+		try {
+			x.method4();
+			return 4;
+		} catch(NullReferenceException e) {
+			;//ok
+		}
+
+		try {
+			x.method5();
+			return 5;
+		} catch(NullReferenceException e) {
+			;//ok
+		}
+		
+		return 0;
+	}
+}
\ No newline at end of file

Modified: trunk/mono/mono/mini/inssel.brg
===================================================================
--- trunk/mono/mono/mini/inssel.brg	2007-05-29 15:25:03 UTC (rev 78138)
+++ trunk/mono/mono/mini/inssel.brg	2007-05-29 15:46:07 UTC (rev 78139)
@@ -1698,7 +1698,23 @@
 		mono_bblock_add_inst (cfg->cbb, tree);
 		return;
 	}
+	
+	if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) &&
+		((method->flags &  METHOD_ATTRIBUTE_FINAL) ||
+			(method->klass && method->klass->flags & TYPE_ATTRIBUTE_SEALED))) {
+		/*
+		 * the method is virtual, but we can statically dispatch since either
+		 * it's class or the method itself are sealed.
+		 * But first we need to ensure it's not a null reference.
+		 */
+		MONO_EMIT_NEW_UNALU (cfg, OP_CHECK_THIS, -1, this_reg);
 
+		tree->dreg = state->reg1;
+		tree->opcode = novirtop;
+		mono_bblock_add_inst (cfg->cbb, tree);
+		return;
+	}
+
 	/* Initialize method->slot */
 	mono_class_setup_vtable (method->klass);
 



More information about the Mono-patches mailing list