Add some caching for generic task
authorMarek Safar <marek.safar@gmail.com>
Mon, 6 Jun 2011 09:23:08 +0000 (10:23 +0100)
committerMarek Safar <marek.safar@gmail.com>
Mon, 6 Jun 2011 09:55:39 +0000 (10:55 +0100)
mcs/mcs/async.cs
mcs/mcs/decl.cs
mcs/mcs/generic.cs
mcs/mcs/iterators.cs
mcs/mcs/statement.cs
mcs/mcs/typemanager.cs
mcs/mcs/typespec.cs
mcs/tests/test-async-02.cs
mcs/tests/ver-il-net_4_0.xml

index 2f30d716b7bbf564968d562d36734814aac34074..95aafd9b5dd1340425633ce9a72fe74105d21e2d 100644 (file)
@@ -316,7 +316,7 @@ namespace Mono.CSharp
                {
                        if (returnType.Kind != MemberKind.Void &&
                                returnType != host.Module.PredefinedTypes.Task.TypeSpec &&
-                               returnType.MemberDefinition != host.Module.PredefinedTypes.TaskGeneric.TypeSpec.MemberDefinition) {
+                               !returnType.IsGenericTask) {
                                host.Compiler.Report.Error (1983, loc, "The return type of an async method must be void, Task, or Task<T>");
                        }
 
index 41500d66f52f7a0c338c7eefc0447d042a411d22..b00ec6eb4b2e371b4d81e444d3dcc233a64c3d9c 100644 (file)
@@ -915,6 +915,7 @@ namespace Mono.CSharp {
                        InflatedExpressionType = 1 << 19,
                        InflatedNullableType = 1 << 20,
                        GenericIterateInterface = 1 << 21,
+                       GenericTask = 1 << 22
                }
 
                protected Modifiers modifiers;
index 5ce22381308601642873683a9b1cdd5a3281bd70..e306999a56bb5f87fbeeb52e6869ac509d38a5d1 100644 (file)
@@ -1505,6 +1505,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override bool IsGenericTask {
+                       get {
+                               return (open_type.state & StateFlags.GenericTask) != 0;
+                       }
+               }
+
                public override bool IsNullableType {
                        get {
                                return (open_type.state & StateFlags.InflatedNullableType) != 0;
index 930e459df64a87387040a7eb89cf041c6ba5f964..bc9314fee130aafd82b5ba1894abd7ee970ca563 100644 (file)
@@ -643,7 +643,13 @@ namespace Mono.CSharp
                        ctx.StartFlowBranching (this, ec.CurrentBranching);
                        Block.Resolve (ctx);
 
-                       ctx.CurrentBranching.CurrentUsageVector.Goto ();
+                       //
+                       // Explicit return is required for Task<T> state machine
+                       //
+                       var task_storey = storey as AsyncTaskStorey;
+                       if (task_storey == null || !task_storey.ReturnType.IsGenericTask)
+                               ctx.CurrentBranching.CurrentUsageVector.Goto ();
+
                        ctx.EndFlowBranching ();
 
                        var move_next = new StateMachineMethod (storey, this, new TypeExpression (ReturnType, loc), Modifiers.PUBLIC, new MemberName ("MoveNext", loc));
index 6ff99cc02efbe8c804fb32cfdba8c953620184b4..11a5a2ce5c5eade8dbf024828e1903b32655d91e 100644 (file)
@@ -750,7 +750,7 @@ namespace Mono.CSharp {
                                                var storey = (AsyncTaskStorey) am.Storey;
                                                var async_type = storey.ReturnType;
 
-                                               if (async_type.MemberDefinition != ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MemberDefinition) {
+                                               if (!async_type.IsGenericTask) {
                                                        ec.Report.Error (1997, loc,
                                                                "`{0}': A return keyword must not be followed by an expression when async method returns Task. Consider using Task<T>",
                                                                ec.GetSignatureForError ());
index 0e98e11cdc00f20ff43582619ee653c81c29f942..2e2d17064d2bfc3450f3879907e71dc8f3526755 100644 (file)
@@ -300,7 +300,8 @@ namespace Mono.CSharp
                                ExpressionGeneric.TypeSpec.IsExpressionTreeType = true;
 
                        Task.Define ();
-                       TaskGeneric.Define ();
+                       if (TaskGeneric.Define ())
+                               TaskGeneric.TypeSpec.IsGenericTask = true;
                }
        }
 
index 03fa923fb2349505c34b7b7e3afed48ee01a836a..abe6b5b9fa8279bfef64f405e59b225b942a2446 100644 (file)
@@ -197,6 +197,18 @@ namespace Mono.CSharp
                        }
                }
 
+               //
+               // Returns true for instances of System.Threading.Tasks.Task<T>
+               //
+               public virtual bool IsGenericTask {
+                       get {
+                               return false;
+                       }
+                       set {
+                               state = value ? state | StateFlags.GenericTask : state & ~StateFlags.GenericTask;
+                       }
+               }
+
                // TODO: Should probably do
                // IsGenericType -- recursive
                // HasTypeParameter -- non-recursive
index bb5cc845a736c24ada3b7df678c3b15bda2bc2ba..0346848613b508a9c2612fad1446775101d0887f 100644 (file)
@@ -58,7 +58,7 @@ class C
                if (t2.Result != 5)
                        return 4;
 
-               if (t.Status != TaskStatus.RanToCompletion)
+               if (t2.Status != TaskStatus.RanToCompletion)
                        return 5;
 
                return 0;
index 0849d24ffdc71cd4c582f5baef836397ac023d43..2bd96546544820dce60e98e0cdd1beb1941dc2c2 100644 (file)
       </method>
     </type>
   </test>
+  <test name="test-async-04.cs">
+    <type name="C">
+      <method name="System.Threading.Tasks.Task`1[System.Int32] TestTaskGeneric()">
+        <size>34</size>
+      </method>
+      <method name="System.Threading.Tasks.Task`1[System.Int32] CallGeneric()">
+        <size>23</size>
+      </method>
+      <method name="Int32 Main()">
+        <size>84</size>
+      </method>
+      <method name="Int32 &lt;CallGeneric&gt;m__0()">
+        <size>14</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>19</size>
+      </method>
+    </type>
+    <type name="C+&lt;&gt;c__async0">
+      <method name="Void MoveNext()">
+        <size>145</size>
+      </method>
+      <method name="Void .ctor()">
+        <size>36</size>
+      </method>
+    </type>
+  </test>
   <test name="test-async-05.cs">
     <type name="C">
       <method name="System.Threading.Tasks.Task Method()">