Avoid creating a temporary variable when target await expression is does not include...
[mono.git] / mcs / mcs / ecore.cs
index 9da600c8e61107f72f987ef1cbdc4c500b60e69e..b61fc91782f0880fad06edc990d10bb8eeedfe25 100644 (file)
@@ -519,22 +519,33 @@ namespace Mono.CSharp {
                        if (IsSideEffectFree)
                                return this;
 
+                       bool needs_temporary = ContainsEmitWithAwait ();
+                       if (!needs_temporary)
+                               ec.EmitThis ();
+
                        // Emit original code
                        EmitToFieldSource (ec);
 
-                       // Create temporary local (we cannot load this before Emit)
-                       var temp = ec.GetTemporaryLocal (type);
-                       ec.Emit (OpCodes.Stloc, temp);
-
                        //
-                       // Store the result to temporary field
+                       // Store the result to temporary field when we
+                       // cannot load this directly
                        //
                        var field = ec.GetTemporaryField (type);
-                       ec.EmitThis ();
-                       ec.Emit (OpCodes.Ldloc, temp);
-                       field.EmitAssignFromStack (ec);
+                       if (needs_temporary) {
+                               //
+                               // Create temporary local (we cannot load this before Emit)
+                               //
+                               var temp = ec.GetTemporaryLocal (type);
+                               ec.Emit (OpCodes.Stloc, temp);
 
-                       ec.FreeTemporaryLocal (temp, type);
+                               ec.EmitThis ();
+                               ec.Emit (OpCodes.Ldloc, temp);
+                               field.EmitAssignFromStack (ec);
+
+                               ec.FreeTemporaryLocal (temp, type);
+                       } else {
+                               field.EmitAssignFromStack (ec);
+                       }
 
                        return field;
                }
@@ -2947,6 +2958,7 @@ namespace Mono.CSharp {
                                        InstanceExpression.Emit (ec);
                                        t.Store (ec);
                                        t.AddressOf (ec, AddressOp.Store);
+                                       t.Release (ec);
                                }
                        } else {
                                InstanceExpression.Emit (ec);
@@ -5318,13 +5330,22 @@ namespace Mono.CSharp {
 
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
                {
-                       if (ec.HasSet (BuilderContext.Options.AsyncBody) && source.ContainsEmitWithAwait ()) {
-                               source = source.EmitToField (ec);
+                       bool has_await_source = ec.HasSet (BuilderContext.Options.AsyncBody) && source.ContainsEmitWithAwait ();
+                       if (isCompound && !(source is DynamicExpressionStatement)) {
+                               if (has_await_source) {
+                                       if (IsInstance)
+                                               InstanceExpression = InstanceExpression.EmitToField (ec);
+                               } else {
+                                       prepared = true;
+                               }
                        }
 
-                       prepared = isCompound && !(source is DynamicExpressionStatement);
-                       if (IsInstance)
+                       if (IsInstance) {
+                               if (has_await_source)
+                                       source = source.EmitToField (ec);
+
                                EmitInstance (ec, prepared);
+                       }
 
                        source.Emit (ec);