Cache implicitly created static delegates
authorMarek Safar <marek.safar@gmail.com>
Fri, 15 Mar 2013 17:37:18 +0000 (18:37 +0100)
committerMarek Safar <marek.safar@gmail.com>
Fri, 15 Mar 2013 17:37:59 +0000 (18:37 +0100)
mcs/mcs/class.cs
mcs/mcs/delegate.cs
mcs/tests/ver-il-net_4_5.xml

index fc8b628c88a4c070845423544bd1459cecea3ed2..24a6bf223eb027179039c4739a187b48d87cb54a 100644 (file)
@@ -544,6 +544,7 @@ namespace Mono.CSharp
 
                public int DynamicSitesCounter;
                public int AnonymousMethodsCounter;
+               public int MethodGroupsCounter;
 
                static readonly string[] attribute_targets = new string[] { "type" };
 
index 2731635683d37c21926e1656fec4f6f08714a01a..a73c9f68c75cb81a94973da5046804f9d6c7163e 100644 (file)
@@ -645,12 +645,93 @@ namespace Mono.CSharp {
        //
        public class ImplicitDelegateCreation : DelegateCreation
        {
+               Field mg_cache;
+
                public ImplicitDelegateCreation (TypeSpec delegateType, MethodGroupExpr mg, Location loc)
                {
                        type = delegateType;
                        this.method_group = mg;
                        this.loc = loc;
                }
+
+               //
+               // Returns true when type is MVAR or has MVAR reference
+               //
+               static bool ContainsMethodTypeParameter (TypeSpec type)
+               {
+                       var tps = type as TypeParameterSpec;
+                       if (tps != null)
+                               return tps.IsMethodOwned;
+
+                       var ec = type as ElementTypeSpec;
+                       if (ec != null)
+                               return ContainsMethodTypeParameter (ec.Element);
+
+                       foreach (var t in type.TypeArguments) {
+                               if (ContainsMethodTypeParameter (t)) {
+                                       return true;
+                               }
+                       }
+
+                       return false;
+               }
+
+               protected override Expression DoResolve (ResolveContext ec)
+               {
+                       var expr = base.DoResolve (ec);
+                       if (expr == null)
+                               return null;
+
+                       if (ec.IsInProbingMode)
+                               return expr;
+
+                       //
+                       // Cache any static delegate creation
+                       //
+                       if (method_group.InstanceExpression != null)
+                               return expr;
+
+                       //
+                       // Cannot easily cache types with MVAR
+                       //
+                       if (ContainsMethodTypeParameter (type))
+                               return expr;
+
+                       if (ContainsMethodTypeParameter (method_group.BestCandidate.DeclaringType))
+                               return expr;
+
+                       //
+                       // Create type level cache for a delegate instance
+                       //
+                       var parent = ec.CurrentMemberDefinition.Parent.PartialContainer;
+                       int id = parent.MethodGroupsCounter++;
+
+                       mg_cache = new Field (parent, new TypeExpression (type, loc),
+                               Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
+                               new MemberName (CompilerGeneratedContainer.MakeName (null, "f", "mg$cache", id), loc), null);
+                       mg_cache.Define ();
+                       parent.AddField (mg_cache);
+
+                       return expr;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Label l_initialized = ec.DefineLabel ();
+
+                       if (mg_cache != null) {
+                               ec.Emit (OpCodes.Ldsfld, mg_cache.Spec);
+                               ec.Emit (OpCodes.Brtrue_S, l_initialized);
+                       }
+
+                       base.Emit (ec);
+
+                       if (mg_cache != null) {
+                               ec.Emit (OpCodes.Stsfld, mg_cache.Spec);
+                               ec.MarkLabel (l_initialized);
+                               ec.Emit (OpCodes.Ldsfld, mg_cache.Spec);
+                       }
+               }
        }
        
        //
index fe8be5ebbeba41e53d9fd300566e36909899aa1b..b5f611c816ffb4ef08829d420c2882952bfbf34a 100644 (file)
         <size>37</size>\r
       </method>\r
       <method name="Void InvokeTest()" attrs="129">\r
-        <size>459</size>\r
+        <size>476</size>\r
       </method>\r
       <method name="Void InvokeMember()" attrs="129">\r
         <size>907</size>\r
         <size>2</size>\r
       </method>\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>175</size>\r
+        <size>192</size>\r
       </method>\r
       <method name="System.Object &lt;Main&gt;m__0(System.Object)" attrs="145">\r
         <size>10</size>\r
         <size>5</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>28</size>\r
+        <size>62</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>42</size>\r
       </method>\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>332</size>\r
+        <size>349</size>\r
       </method>\r
       <method name="Int32 Foo(Int32)" attrs="145">\r
         <size>11</size>\r
   <test name="gtest-161.cs">\r
     <type name="App">\r
       <method name="Void Main()" attrs="150">\r
-        <size>57</size>\r
+        <size>74</size>\r
       </method>\r
       <method name="U apply[T,U](T, FP+Mapping`2[T,U])" attrs="145">\r
         <size>16</size>\r
         <size>8</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>51</size>\r
+        <size>68</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>2</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>19</size>\r
+        <size>36</size>\r
       </method>\r
     </type>\r
     <type name="X+&lt;Foo&gt;c__AnonStorey0`1[T]">\r
         <size>10</size>\r
       </method>\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>28</size>\r
+        <size>45</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>30</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>142</size>\r
+        <size>210</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
   <test name="gtest-334.cs">\r
     <type name="Test">\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>128</size>\r
+        <size>179</size>\r
       </method>\r
       <method name="Void DelegateMethod(Boolean)" attrs="145">\r
         <size>2</size>\r
         <size>2</size>\r
       </method>\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>172</size>\r
+        <size>189</size>\r
       </method>\r
       <method name="Void Method(Thing+Handler, System.String[])" attrs="150">\r
         <size>2</size>\r
         <size>2</size>\r
       </method>\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>228</size>\r
+        <size>245</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>10</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>25</size>\r
+        <size>42</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>68</size>\r
       </method>\r
       <method name="System.Action`1[System.Int32] Test_15(System.Action`1[System.Int32])" attrs="129">\r
-        <size>29</size>\r
+        <size>46</size>\r
       </method>\r
       <method name="Void Helper[T](T)" attrs="145">\r
         <size>2</size>\r
         <size>31</size>\r
       </method>\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>27</size>\r
+        <size>44</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>2</size>\r
       </method>\r
       <method name="Void Bug()" attrs="134">\r
-        <size>20</size>\r
+        <size>37</size>\r
       </method>\r
       <method name="Void Handler(System.Object, System.EventArgs)" attrs="150">\r
         <size>2</size>\r
     </type>\r
     <type name="TestBug.MainClass">\r
       <method name="Void Main()" attrs="150">\r
-        <size>26</size>\r
+        <size>43</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>2</size>\r
       </method>\r
       <method name="Void Main(System.String[])" attrs="150">\r
-        <size>101</size>\r
+        <size>169</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>16</size>\r
       </method>\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>91</size>\r
+        <size>125</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>17</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>30</size>\r
+        <size>47</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>18</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>27</size>\r
+        <size>44</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>98</size>\r
       </method>\r
       <method name="Void ConvertTest_10()" attrs="129">\r
-        <size>164</size>\r
+        <size>181</size>\r
       </method>\r
       <method name="Void ConvertTest_11()" attrs="129">\r
         <size>102</size>\r
         <size>313</size>\r
       </method>\r
       <method name="Void EqualTestDelegate_3()" attrs="129">\r
-        <size>213</size>\r
+        <size>230</size>\r
       </method>\r
       <method name="Void ExclusiveOrTest()" attrs="129">\r
         <size>116</size>\r
         <size>2</size>\r
       </method>\r
       <method name="Int32 Main()" attrs="150">\r
-        <size>243</size>\r
+        <size>294</size>\r
       </method>\r
       <method name="IEnumerable`1 &lt;Main&gt;m__0(IEnumerable)" attrs="145">\r
         <size>7</size>\r
         <size>2</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>20</size>\r
+        <size>37</size>\r
       </method>\r
       <method name="Void .ctor(Foo)" attrs="6278">\r
         <size>8</size>\r
         <size>15</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>114</size>\r
+        <size>165</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>31</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>129</size>\r
+        <size>180</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>56</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>72</size>\r
+        <size>89</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>7</size>\r
       </method>\r
       <method name="Void .cctor()" attrs="6289">\r
-        <size>24</size>\r
+        <size>41</size>\r
       </method>\r
     </type>\r
   </test>\r
         <size>32</size>\r
       </method>\r
       <method name="Void &lt;Main&gt;m__0()" attrs="145">\r
-        <size>19</size>\r
+        <size>36</size>\r
       </method>\r
     </type>\r
   </test>\r
         <size>10</size>\r
       </method>\r
       <method name="Void X()" attrs="134">\r
-        <size>20</size>\r
+        <size>37</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
   <test name="test-708.cs">\r
     <type name="A">\r
       <method name="A+ADelegate Delegate2(Boolean)" attrs="150">\r
-        <size>33</size>\r
+        <size>50</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
         <size>2</size>\r
         <size>10</size>\r
       </method>\r
       <method name="Int32 GetPhones()" attrs="129">\r
-        <size>30</size>\r
+        <size>47</size>\r
       </method>\r
       <method name="Int32 Main()" attrs="150">\r
         <size>36</size>\r
         <size>38</size>\r
       </method>\r
       <method name="Void StaticCallback()" attrs="134">\r
-        <size>32</size>\r
+        <size>49</size>\r
       </method>\r
       <method name="Void StaticCallback(System.String)" attrs="150">\r
         <size>36</size>\r
         <size>2</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>32</size>\r
+        <size>66</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r
         <size>12</size>\r
       </method>\r
       <method name="Void Main()" attrs="150">\r
-        <size>40</size>\r
+        <size>57</size>\r
       </method>\r
       <method name="Void .ctor()" attrs="6278">\r
         <size>7</size>\r