Просмотр исходного кода

rework coalesce

svn path=/trunk/mcs/; revision=104466
Jb Evain 17 лет назад
Родитель
Сommit
201aeafc02
1 измененных файлов с 41 добавлено и 44 удалено
  1. 41 44
      mcs/class/System.Core/System.Linq.Expressions/BinaryExpression.cs

+ 41 - 44
mcs/class/System.Core/System.Linq.Expressions/BinaryExpression.cs

@@ -243,50 +243,47 @@ namespace System.Linq.Expressions {
 
 		void EmitCoalesce (EmitContext ec)
 		{
-			ILGenerator ig = ec.ig;
-
-			LocalBuilder vleft;
-			LocalBuilder vright;
-
-			MethodInfo has_value = left.Type.GetMethod ("get_HasValue");
-
-			Label exit = ig.DefineLabel ();
-			Label try_right = ig.DefineLabel ();
-			Label setup_null = ig.DefineLabel ();
-
-			vleft = ec.EmitStored (left);
-			if (IsNullable (left.Type)){
-				ig.Emit (OpCodes.Ldloca, vleft);
-				ig.Emit (OpCodes.Call, has_value);
-			} else
-				ig.Emit (OpCodes.Ldloc, vleft);
-
-			ig.Emit (OpCodes.Brfalse, try_right);
-			ig.Emit (OpCodes.Ldloc, vleft);
-			ig.Emit (OpCodes.Br, exit);
-
-		// try_right;
-			ig.MarkLabel (try_right);
-			vright = ec.EmitStored (right);
-			if (IsNullable (right.Type)){
-				ig.Emit (OpCodes.Ldloca, vright);
-				ig.Emit (OpCodes.Call, has_value);
-			} else
-				ig.Emit (OpCodes.Ldloc, vright);
-
-			ig.Emit (OpCodes.Brfalse, setup_null);
-			ig.Emit (OpCodes.Ldloc, vright);
-			ig.Emit (OpCodes.Br, exit);
-
-		// setup_null:
-			ig.MarkLabel (setup_null);
-			LocalBuilder ret = ig.DeclareLocal (Type);
-			ig.Emit (OpCodes.Ldloca, ret);
-			ig.Emit (OpCodes.Initobj, Type);
-			ig.Emit (OpCodes.Ldloc, ret);
-
-		// exit:
-			ig.MarkLabel (exit);
+			if (IsNullable (left.Type))
+				EmitNullableCoalesce (ec);
+			else
+				EmitReferenceCoalesce (ec);
+		}
+
+		void EmitReferenceCoalesce (EmitContext ec)
+		{
+			var ig = ec.ig;
+			var done = ig.DefineLabel ();
+			var load_right = ig.DefineLabel ();
+
+			var left = ec.EmitStored (this.left);
+			ec.EmitLoad (left);
+			ig.Emit (OpCodes.Brfalse, load_right);
+			ec.EmitLoad (left);
+			ig.Emit (OpCodes.Br, done);
+
+			ig.MarkLabel (load_right);
+			ec.Emit (this.right);
+
+			ig.MarkLabel (done);
+		}
+
+		void EmitNullableCoalesce (EmitContext ec)
+		{
+			var ig = ec.ig;
+			var load_right = ig.DefineLabel ();
+			var done = ig.DefineLabel ();
+
+			var left = ec.EmitStored (this.left);
+			ec.EmitNullableHasValue (left);
+			ig.Emit (OpCodes.Brfalse, load_right);
+
+			ec.EmitLoad (left);
+			ig.Emit (OpCodes.Br, done);
+
+			ig.MarkLabel (load_right);
+			ec.Emit (this.right);
+
+			ig.MarkLabel (done);
 		}
 
 		static bool IsInt32OrInt64 (Type type)