[mono/mono] [2 commits] 8c6864df: [mcs] Optimize DefiniteAssignmentBitSet

"Marek Safar ([email protected])" <[email protected]> Mon, 25 Nov 2013 15:10:22 +0000
Newsgroups gmane.comp.gnome.mono.patches
Message-ID <000001428fcfafd9-b3ac906e-5ada-437b-b8fe-e6012ad98f88-000000@email.amazonses.com>
   Branch: refs/heads/master
     Home: https://github.com/mono/mono
  Compare: https://github.com/mono/mono/compare/8a4e1ca74e65...1d5cefe7ad5e

   Commit: 8c6864df1c2175295180599773f296c13372b839
   Author: Marek Safar <[email protected]> (marek-safar)
     Date: 2013-11-25 15:02:58 GMT
      URL: https://github.com/mono/mono/commit/8c6864df1c2175295180599773f296c13372b839

[mcs] Optimize DefiniteAssignmentBitSet

Changed paths:
  M mcs/mcs/context.cs
  M mcs/mcs/flowanalysis.cs

Modified: mcs/mcs/context.cs
===================================================================
@@ -445,7 +445,9 @@ public FlowAnalysisContext (CompilerContext ctx, ParametersBlock parametersBlock
 			this.ctx = ctx;
 			this.ParametersBlock = parametersBlock;
 
-			DefiniteAssignment = new DefiniteAssignmentBitSet (definiteAssignmentLength);
+			DefiniteAssignment = definiteAssignmentLength == 0 ?
+				DefiniteAssignmentBitSet.Empty :
+				new DefiniteAssignmentBitSet (definiteAssignmentLength);
 		}
 
 		public DefiniteAssignmentBitSet DefiniteAssignment { get; set; }
@@ -469,7 +471,8 @@ public FlowAnalysisContext (CompilerContext ctx, ParametersBlock parametersBlock
 		public DefiniteAssignmentBitSet BranchDefiniteAssignment ()
 		{
 			var dat = DefiniteAssignment;
-			DefiniteAssignment = new DefiniteAssignmentBitSet (dat);
+			if (dat != DefiniteAssignmentBitSet.Empty)
+				DefiniteAssignment = new DefiniteAssignmentBitSet (dat);
 			return dat;
 		}
 

Modified: mcs/mcs/flowanalysis.cs
===================================================================
@@ -503,46 +503,79 @@ public static Reachability CreateUnreachable ()
 		}
 	}
 
+	//
+	// Special version of bit array. Many operations can be simplified because
+	// we are always dealing with arrays of same sizes
+	//
 	public class DefiniteAssignmentBitSet
 	{
-		// Make it
-		// int bits;
-		// int int[] bits_extended; // when bits overflows
+		const uint copy_on_write_flag = 1u << 31;
+
+		uint bits;
+
+		// Used when bits overflows
+		int[] large_bits;
 
-		System.Collections.BitArray bits;
-		bool copy_on_write;
+		public static readonly DefiniteAssignmentBitSet Empty = new DefiniteAssignmentBitSet (0);
 
 		public DefiniteAssignmentBitSet (int length)
 		{
-			bits = new System.Collections.BitArray (length);
+			if (length > 31)
+				large_bits = new int[(length + 31) / 32];
 		}
 
 		public DefiniteAssignmentBitSet (DefiniteAssignmentBitSet source)
 		{
-			bits = source.bits;
-
-			copy_on_write = true;
-		}
-
-		private DefiniteAssignmentBitSet (System.Collections.BitArray bits)
-		{
-			this.bits = bits;
+			large_bits = source.large_bits;
+			bits = source.bits | copy_on_write_flag;
 		}
 
 		public static DefiniteAssignmentBitSet operator & (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
 		{
-			if (a.bits == b.bits)
+			if (AreEqual (a, b))
 				return a;
 
-			return new DefiniteAssignmentBitSet (a.bits.And (b.bits));
+			DefiniteAssignmentBitSet res;
+			if (a.large_bits == null) {
+				res = new DefiniteAssignmentBitSet (a);
+				res.bits &= (b.bits & ~copy_on_write_flag);
+				return res;
+			}
+
+			res = new DefiniteAssignmentBitSet (a);
+			res.Clone ();
+			var dest = res.large_bits;
+			var src = b.large_bits;
+			for (int i = 0; i < dest.Length; ++i) {
+				dest[i] &= src[i];
+			}
+
+			return res;
 		}
 
 		public static DefiniteAssignmentBitSet operator | (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
 		{
-			if (a.bits == b.bits)
+			if (AreEqual (a, b))
 				return a;
 
-			return new DefiniteAssignmentBitSet (a.bits.Or (b.bits));
+			DefiniteAssignmentBitSet res;
+			if (a.large_bits == null) {
+				res = new DefiniteAssignmentBitSet (a);
+				res.bits |= b.bits;
+				res.bits &= ~copy_on_write_flag;
+				return res;
+			}
+
+			res = new DefiniteAssignmentBitSet (a);
+			res.Clone ();
+			var dest = res.large_bits;
+			var src = b.large_bits;
+
+			for (int i = 0; i < dest.Length; ++i) {
+				dest[i] |= src[i];
+			}
+
+			return res;
 		}
 
 		public static DefiniteAssignmentBitSet And (List<DefiniteAssignmentBitSet> das)
@@ -550,7 +583,7 @@ public static DefiniteAssignmentBitSet And (List<DefiniteAssignmentBitSet> das)
 			if (das.Count == 0)
 				throw new ArgumentException ("Empty das");
 
-			DefiniteAssignmentBitSet res = das [0];
+			DefiniteAssignmentBitSet res = das[0];
 			for (int i = 1; i < das.Count; ++i) {
 				res &= das[i];
 			}
@@ -558,45 +591,87 @@ public static DefiniteAssignmentBitSet And (List<DefiniteAssignmentBitSet> das)
 			return res;
 		}
 
+		bool CopyOnWrite {
+			get {
+				return (bits & copy_on_write_flag) != 0;
+			}
+		}
+
+		int Length {
+			get {
+				return large_bits == null ? 31 : large_bits.Length * 32;
+			}
+		}
+
 		public void Set (int index)
 		{
-			if (copy_on_write && !bits[index])
+			if (CopyOnWrite && !this[index])
 				Clone ();
 
-			bits[index] = true;
+			SetBit (index);
 		}
 
 		public void Set (int index, int length)
 		{
 			for (int i = 0; i < length; ++i) {
-				if (copy_on_write && !bits[index + i])
+				if (CopyOnWrite && !this[index + i])
 					Clone ();
 
-				bits[index + i] = true;
+				SetBit (index + i);
 			}
- 		}
+		}
 
-		public bool this [int index] {
+		public bool this[int index] {
 			get {
-				return bits [index];
+				return GetBit (index);
 			}
 		}
 
-		void Clone ()
-		{
-			bits = new System.Collections.BitArray (bits);
-			copy_on_write = false;
-		}
-
 		public override string ToString ()
 		{
-			var length = bits.Length;
+			var length = Length;
 			StringBuilder sb = new StringBuilder (length);
 			for (int i = 0; i < length; ++i) {
-				sb.Append (bits[i] ? '1' : '0');
+				sb.Append (this[i] ? '1' : '0');
 			}
 
 			return sb.ToString ();
 		}
+
+		void Clone ()
+		{
+			if (large_bits != null)
+				large_bits = (int[]) large_bits.Clone ();
+
+			bits &= ~copy_on_write_flag;
+		}
+
+		bool GetBit (int index)
+		{
+			return large_bits == null ?
+				(bits & (1 << index)) != 0 :
+				(large_bits[index >> 5] & (1 << (index & 31))) != 0;
+		}
+
+		void SetBit (int index)
+		{
+			if (large_bits == null)
+				bits = (uint) ((int) bits | (1 << index));
+			else
+				large_bits[index >> 5] |= (1 << (index & 31));
+		}
+
+		static bool AreEqual (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
+		{
+			if (a.large_bits == null)
+				return (a.bits & ~copy_on_write_flag) == (b.bits & ~copy_on_write_flag);
+
+			for (int i = 0; i < a.large_bits.Length; ++i) {
+				if (a.large_bits[i] != b.large_bits[i])
+					return false;
+			}
+
+			return true;
+		}
 	}
 }

   Commit: 1d5cefe7ad5e5253a410ec3dd5c6e825317c7557
   Author: Marek Safar <[email protected]> (marek-safar)
     Date: 2013-11-25 15:02:58 GMT
      URL: https://github.com/mono/mono/commit/1d5cefe7ad5e5253a410ec3dd5c6e825317c7557

[mcs] Arguments flow analysis needs to ignore out modifier.

Changed paths:
  M mcs/mcs/argument.cs
Added paths:
  A mcs/errors/cs0165-29.cs
  A mcs/errors/cs0165-30.cs
  A mcs/errors/cs0165-31.cs
  A mcs/errors/cs0165-32.cs

Added: mcs/errors/cs0165-29.cs
===================================================================
@@ -0,0 +1,12 @@
+// CS0165: Use of unassigned local variable `j'
+// Line: 10
+
+class Test
+{
+	static void Main ()
+	{
+		int? i;
+		int? j;
+		int? x = (i = 7) ?? j;
+    }
+}
\ No newline at end of file

Added: mcs/errors/cs0165-30.cs
===================================================================
@@ -0,0 +1,11 @@
+// CS0165: Use of unassigned local variable `a'
+// Line: 9
+
+using System;
+
+class Test {
+	
+	static void Main () {
+		Action a = () => a();
+	}
+}
\ No newline at end of file

Added: mcs/errors/cs0165-31.cs
===================================================================
@@ -0,0 +1,11 @@
+// CS0165: Use of unassigned local variable `i'
+// Line: 9
+
+public class MainClass
+{
+	public void Foo ()
+	{
+		int i;
+		i++;
+	}
+}

Added: mcs/errors/cs0165-32.cs
===================================================================
@@ -0,0 +1,16 @@
+// CS0165: Use of unassigned local variable `a'
+// Line: 9
+
+class C
+{
+	static void Main ()
+	{
+		int a;
+		Foo (out a, a);
+	}
+
+	static void Foo (out int a, int b)
+	{
+		a = b;
+	}
+}
\ No newline at end of file

Modified: mcs/mcs/argument.cs
===================================================================
@@ -499,8 +499,25 @@ public virtual Arguments Emit (EmitContext ec, bool dup_args, bool prepareAwait)
 
 		public void FlowAnalysis (FlowAnalysisContext fc)
 		{
-			foreach (var arg in args)
+			bool has_out = false;
+			foreach (var arg in args) {
+				if (arg.ArgType == Argument.AType.Out) {
+					has_out = true;
+					continue;
+				}
+
 				arg.FlowAnalysis (fc);
+			}
+
+			if (!has_out)
+				return;
+
+			foreach (var arg in args) {
+				if (arg.ArgType != Argument.AType.Out)
+					continue;
+
+				arg.FlowAnalysis (fc);
+			}
 		}
 
 		public List<Argument>.Enumerator GetEnumerator ()


_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches