[mcs] Add reference to parent storey when current value type async storey needs fabri...
authorMarek Safar <marek.safar@gmail.com>
Mon, 29 Aug 2016 16:01:39 +0000 (18:01 +0200)
committerMarek Safar <marek.safar@gmail.com>
Mon, 29 Aug 2016 16:04:14 +0000 (18:04 +0200)
mcs/mcs/anonymous.cs
mcs/mcs/statement.cs
mcs/tests/test-async-89.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_x.xml

index 80481ed2091f6ba2cf1deb7c25e4c5514ce9e529..d27fe806048797af33538b202c262e0e040dff4e 100644 (file)
@@ -1595,6 +1595,15 @@ namespace Mono.CSharp {
                        if (res && errors != ec.Report.Errors)
                                return null;
 
+                       if (block.IsAsync && block.Original.ParametersBlock.HasCapturedThis && ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.block.IsAsync) {
+                               //
+                               // We'll do ldftn to load the fabricated m_X method but
+                               // because we are inside struct the method can be hoisted
+                               // anywhere in the parent scope
+                               //
+                               ec.CurrentBlock.ParametersBlock.HasReferenceToStoreyForInstanceLambdas = true;
+                       }
+
                        return res ? this : null;
                }
 
@@ -1798,6 +1807,8 @@ namespace Mono.CSharp {
                                                        parent = storey = sm;
                                                }
                                        }
+                               } else if (src_block.ParametersBlock.HasReferenceToStoreyForInstanceLambdas) {
+                                       src_block.ParametersBlock.StateMachine.AddParentStoreyReference (ec, storey);
                                }
 
                                modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
index d7105592ebb29cdcff8b38039e88696def303f62..7f54b33eeb599c16146c7adfcc0c2e12b3d5beaf 100644 (file)
@@ -2657,6 +2657,7 @@ namespace Mono.CSharp {
                        AwaitBlock = 1 << 13,
                        FinallyBlock = 1 << 14,
                        CatchBlock = 1 << 15,
+                       HasReferenceToStoreyForInstanceLambdas = 1 << 16,
                        Iterator = 1 << 20,
                        NoFlowAnalysis = 1 << 21,
                        InitializationEmitted = 1 << 22
@@ -3281,7 +3282,7 @@ namespace Mono.CSharp {
                                                        break;
                                        }
                                }
-                               
+
                                //
                                // We are the first storey on path and 'this' has to be hoisted
                                //
@@ -3349,7 +3350,7 @@ namespace Mono.CSharp {
 
                                                                //
                                                                // If we are state machine with no parent. We can hook into parent without additional
-                                                               // reference and capture this directly
+                                                               // reference and capture this directly
                                                                //
                                                                ExplicitBlock parent_storey_block = pb;
                                                                while (parent_storey_block.Parent != null) {
@@ -3666,6 +3667,15 @@ namespace Mono.CSharp {
 
                #region Properties
 
+               public bool HasReferenceToStoreyForInstanceLambdas {
+                       get {
+                               return (flags & Flags.HasReferenceToStoreyForInstanceLambdas) != 0;
+                       }
+                       set {
+                               flags = value ? flags | Flags.HasReferenceToStoreyForInstanceLambdas : flags & ~Flags.HasReferenceToStoreyForInstanceLambdas;
+                       }
+               }
+
                public bool IsAsync {
                        get {
                                return (flags & Flags.HasAsyncModifier) != 0;
diff --git a/mcs/tests/test-async-89.cs b/mcs/tests/test-async-89.cs
new file mode 100644 (file)
index 0000000..5a69685
--- /dev/null
@@ -0,0 +1,51 @@
+using System;
+using System.Threading.Tasks;
+
+class X
+{
+       public static void Main ()
+       {
+               new X ().Test ();
+       }
+
+       void Test ()
+       {
+               object v1 = null;
+
+               Action a = () =>
+               {
+                       if (v1 == null)
+                       {
+                               object v2 = null;
+
+                               Action a2 = () =>
+                               {
+                                       Console.WriteLine (v2);
+                               };
+                               
+                               Action a3 = async () =>
+                               {
+                                       // This scope needs to access to Scope which can do ldftn on instance method
+                                       {
+                                       Func<Task> a4 = async () =>
+                                       {
+                                               await Foo ();
+                                       };
+                                       }
+
+                                       await Task.Yield ();
+                               };
+
+                               a3 ();
+                       }
+               };
+
+               a ();
+       }
+
+       async Task Foo ()
+       {
+               await Task.FromResult (1);
+       }
+
+}
\ No newline at end of file
index 270fe53c92fdf6c81740a9b9d4f6d632b8673bd4..cde4e9e70d68ea66bba24d1169045aa8b6be1057 100644 (file)
       </method>
     </type>
   </test>
+  <test name="test-async-89.cs">
+    <type name="X">
+      <method name="Void Main()" attrs="150">
+        <size>12</size>
+      </method>
+      <method name="Void Test()" attrs="129">
+        <size>41</size>
+      </method>
+      <method name="System.Threading.Tasks.Task Foo()" attrs="129">
+        <size>33</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="X+&lt;Test&gt;c__AnonStorey1">
+      <method name="Void &lt;&gt;m__0()" attrs="131">
+        <size>67</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="X+&lt;Foo&gt;c__async0">
+      <method name="Void MoveNext()" attrs="486">
+        <size>158</size>
+      </method>
+      <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+        <size>13</size>
+      </method>
+    </type>
+    <type name="X+&lt;Test&gt;c__AnonStorey1+&lt;Test&gt;c__AnonStorey2">
+      <method name="Void &lt;&gt;m__0()" attrs="131">
+        <size>13</size>
+      </method>
+      <method name="Void &lt;&gt;m__1()" attrs="131">
+        <size>48</size>
+      </method>
+      <method name="System.Threading.Tasks.Task &lt;&gt;m__2()" attrs="131">
+        <size>46</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="X+&lt;Test&gt;c__AnonStorey1+&lt;Test&gt;c__AnonStorey2+&lt;Test&gt;c__async3">
+      <method name="Void MoveNext()" attrs="486">
+        <size>179</size>
+      </method>
+      <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+        <size>13</size>
+      </method>
+    </type>
+    <type name="X+&lt;Test&gt;c__AnonStorey1+&lt;Test&gt;c__AnonStorey2+&lt;Test&gt;c__async4">
+      <method name="Void MoveNext()" attrs="486">
+        <size>167</size>
+      </method>
+      <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+        <size>13</size>
+      </method>
+    </type>
+  </test>
   <test name="test-cls-00.cs">
     <type name="CLSCLass_6">
       <method name="Void add_Disposed(Delegate)" attrs="2182">