[mcs] Wrap exceptions in async state machine with no resume points
authorMarek Safar <marek.safar@gmail.com>
Mon, 14 Jul 2014 08:41:54 +0000 (10:41 +0200)
committerMarek Safar <marek.safar@gmail.com>
Mon, 14 Jul 2014 09:22:27 +0000 (11:22 +0200)
mcs/mcs/async.cs
mcs/mcs/iterators.cs
mcs/tests/test-async-73.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

index c11216d9bae5a435698471e5861927c7862c4b73..0029cf894067c2e7c6bb3fa2537aa52c132fa9a5 100644 (file)
@@ -474,6 +474,24 @@ namespace Mono.CSharp
                        throw new NotImplementedException ();
                }
 
+               public void EmitCatchBlock (EmitContext ec)
+               {
+                       var catch_value = LocalVariable.CreateCompilerGenerated (ec.Module.Compiler.BuiltinTypes.Exception, block, Location);
+
+                       ec.BeginCatchBlock (catch_value.Type);
+                       catch_value.EmitAssign (ec);
+
+                       ec.EmitThis ();
+                       ec.EmitInt ((int) IteratorStorey.State.After);
+                       ec.Emit (OpCodes.Stfld, storey.PC.Spec);
+
+                       ((AsyncTaskStorey) Storey).EmitSetException (ec, new LocalVariableReference (catch_value, Location));
+
+                       ec.Emit (OpCodes.Leave, move_next_ok);
+                       ec.EndExceptionBlock ();
+
+               }
+
                protected override void EmitMoveNextEpilogue (EmitContext ec)
                {
                        var storey = (AsyncTaskStorey) Storey;
index 8b45f88a911a054c4156b8d13f545f430d2e707a..202438dc03ef9d5c440ae32c2f4774ce221a4560 100644 (file)
@@ -723,7 +723,7 @@ namespace Mono.CSharp
                //
                // The state as we generate the machine
                //
-               Label move_next_ok;
+               protected Label move_next_ok;
                protected Label move_next_error;
                LocalBuilder skip_finally;
                protected LocalBuilder current_pc;
@@ -827,8 +827,15 @@ namespace Mono.CSharp
 
                        BodyEnd = ec.DefineLabel ();
 
+                       var async_init = this as AsyncInitializer;
+                       if (async_init != null)
+                               ec.BeginExceptionBlock ();
+
                        block.EmitEmbedded (ec);
 
+                       if (async_init != null)
+                               async_init.EmitCatchBlock (ec);
+
                        ec.MarkLabel (BodyEnd);
 
                        EmitMoveNextEpilogue (ec);
@@ -839,6 +846,8 @@ namespace Mono.CSharp
                                ec.EmitInt (0);
                                ec.Emit (OpCodes.Ret);
                        }
+
+                       ec.MarkLabel (move_next_ok);
                }
 
                void EmitMoveNext (EmitContext ec)
@@ -895,19 +904,7 @@ namespace Mono.CSharp
                        ec.MarkLabel (BodyEnd);
 
                        if (async_init != null) {
-                               var catch_value = LocalVariable.CreateCompilerGenerated (ec.Module.Compiler.BuiltinTypes.Exception, block, Location);
-
-                               ec.BeginCatchBlock (catch_value.Type);
-                               catch_value.EmitAssign (ec);
-
-                               ec.EmitThis ();
-                               ec.EmitInt ((int) IteratorStorey.State.After);
-                               ec.Emit (OpCodes.Stfld, storey.PC.Spec);
-
-                               ((AsyncTaskStorey) async_init.Storey).EmitSetException (ec, new LocalVariableReference (catch_value, Location));
-
-                               ec.Emit (OpCodes.Leave, move_next_ok);
-                               ec.EndExceptionBlock ();
+                               async_init.EmitCatchBlock (ec);
                        }
 
                        ec.Mark (Block.Original.EndLocation);
diff --git a/mcs/tests/test-async-73.cs b/mcs/tests/test-async-73.cs
new file mode 100644 (file)
index 0000000..dc1935f
--- /dev/null
@@ -0,0 +1,31 @@
+using System.Threading.Tasks;
+using System;
+
+class X
+{
+       static async Task<int> Foo ()
+       {
+               var v = Throws ();
+
+               try {
+                       await v;   
+               } catch (Exception e) {
+                       return 0;
+               }
+
+               return 1;
+       }
+
+       static async Task<int> Throws ()
+       {
+               throw new Exception ();
+       }
+
+       static int Main ()
+       {
+               if (Foo ().Result != 0)
+                       return 1;
+
+               return 0;
+       }
+}
\ No newline at end of file
index df971b0e648f73c2dde03a0fed2f02868f00fc2c..70fd4e54d6cc3d5e45e328c3873da9e80dda1647 100644 (file)
     </type>\r
     <type name="C+&lt;SynchronousCall&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>49</size>\r
+        <size>79</size>\r
       </method>\r
       <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="Program+&lt;Main&gt;c__async7">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>44</size>\r
+        <size>69</size>\r
       </method>\r
     </type>\r
     <type name="Program+&lt;Main&gt;c__AnonStorey1">\r
     </type>\r
     <type name="Program+&lt;Main&gt;c__async4">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>43</size>\r
+        <size>68</size>\r
       </method>\r
     </type>\r
     <type name="Program+&lt;Main&gt;c__AnonStorey1">\r
     </type>\r
     <type name="AsyncTypeInference+&lt;Main&gt;c__asyncB">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>37</size>\r
+        <size>67</size>\r
       </method>\r
     </type>\r
     <type name="AsyncTypeInference+&lt;Main&gt;c__async2">\r
     </type>\r
     <type name="Test+&lt;Main&gt;c__async2">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>38</size>\r
+        <size>63</size>\r
       </method>\r
       <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="A+&lt;async&gt;c__async1">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>38</size>\r
+        <size>63</size>\r
       </method>\r
     </type>\r
     <type name="A">\r
     </type>\r
     <type name="A+&lt;async&gt;c__async2">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>37</size>\r
+        <size>62</size>\r
       </method>\r
     </type>\r
     <type name="A+&lt;CastTest&gt;c__async3">\r
     </type>\r
     <type name="A+async&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>31</size>\r
+        <size>61</size>\r
       </method>\r
     </type>\r
     <type name="D">\r
     </type>\r
     <type name="D+&lt;M&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>31</size>\r
+        <size>61</size>\r
       </method>\r
     </type>\r
     <type name="asyncAttribute+async">\r
     </type>\r
     <type name="C+&lt;Test2&gt;c__async1">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>59</size>\r
+        <size>89</size>\r
       </method>\r
     </type>\r
     <type name="C+&lt;Test&gt;c__async0">\r
     </type>\r
     <type name="C+&lt;Test&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>60</size>\r
+        <size>90</size>\r
       </method>\r
       <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="App+&lt;Test&gt;c__async1">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>51</size>\r
+        <size>76</size>\r
       </method>\r
     </type>\r
     <type name="App+&lt;Test&gt;c__async0">\r
     </type>\r
     <type name="Program+&lt;LoadPlayers&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>87</size>\r
+        <size>117</size>\r
       </method>\r
     </type>\r
     <type name="Program">\r
     </type>\r
     <type name="X+&lt;Foo&gt;c__AnonStorey1+&lt;Foo&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>43</size>\r
+        <size>73</size>\r
       </method>\r
       <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="B+&lt;GetAsync&gt;c__async0">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>49</size>\r
+        <size>74</size>\r
       </method>\r
       <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="X+&lt;AddItemAt&gt;c__async1">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>43</size>\r
+        <size>68</size>\r
       </method>\r
       <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
     </type>\r
     <type name="X+&lt;Foo&gt;c__async6">\r
       <method name="Void MoveNext()" attrs="486">\r
-        <size>100</size>\r
+        <size>130</size>\r
       </method>\r
       <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">\r
         <size>13</size>\r
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-async-73.cs">\r
+    <type name="X">\r
+      <method name="System.Threading.Tasks.Task`1[System.Int32] Foo()" attrs="145">\r
+        <size>33</size>\r
+      </method>\r
+      <method name="System.Threading.Tasks.Task`1[System.Int32] Throws()" attrs="145">\r
+        <size>33</size>\r
+      </method>\r
+      <method name="Int32 Main()" attrs="145">\r
+        <size>32</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+    <type name="X+&lt;Foo&gt;c__async0">\r
+      <method name="Void MoveNext()" attrs="486">\r
+        <size>214</size>\r
+      </method>\r
+      <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">\r
+        <size>13</size>\r
+      </method>\r
+    </type>\r
+    <type name="X+&lt;Throws&gt;c__async1">\r
+      <method name="Void MoveNext()" attrs="486">\r
+        <size>63</size>\r
+      </method>\r
+      <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">\r
+        <size>13</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-cls-00.cs">\r
     <type name="CLSCLass_6">\r
       <method name="Void add_Disposed(Delegate)" attrs="2182">\r