Optimize extension methods lookup
authorMarek Safar <marek.safar@gmail.com>
Wed, 25 Jan 2012 10:38:23 +0000 (10:38 +0000)
committerMarek Safar <marek.safar@gmail.com>
Thu, 26 Jan 2012 08:44:14 +0000 (08:44 +0000)
mcs/mcs/cs-tokenizer.cs
mcs/mcs/decl.cs
mcs/mcs/location.cs
mcs/mcs/namespace.cs

index 18948d7b23829aa964e0b5c78cd302653f33e5bb..7077e9596c8678b0a83422683043f5913626744f 100644 (file)
@@ -1970,7 +1970,7 @@ namespace Mono.CSharp
                                        
                                        char [] quotes = { '\"' };
                                        
-                                       string name = arg.Substring (pos). Trim (quotes);
+                                       string name = arg.Substring (pos).Trim (quotes);
                                        ref_name = context.LookupFile (file_name, name);
                                        file_name.AddIncludeFile (ref_name);
                                        hidden = false;
index 088eba96e54f22bdc2f27c235af953b710d23368..8f2c3411aa1d9b33b0deaf7065ae7c370624a2f4 100644 (file)
@@ -657,14 +657,22 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               //
+               // Does extension methods look up to find a method which matches name and extensionType.
+               // Search starts from this namespace and continues hierarchically up to top level.
+               //
                public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
                {
-                       return LookupExtensionMethod (this, extensionType, name, arity);
-               }
+                       var m = Parent;
+                       do {
+                               var ns = m as NamespaceContainer;
+                               if (ns != null)
+                                       return ns.LookupExtensionMethod (this, extensionType, name, arity, ns, 0);
 
-               protected virtual ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity)
-               {
-                       return Parent.LookupExtensionMethod (invocationContext, extensionType, name, arity);
+                               m = m.Parent;
+                       } while (m != null);
+
+                       return null;
                }
 
                public virtual FullNamedExpression LookupNamespaceAlias (string name)
index 921141b9b36042244d987886a5c172045cf841e9..4b0bd637213483ef379243d5391c95f90cee8bfc 100644 (file)
@@ -220,7 +220,7 @@ namespace Mono.CSharp {
                static Checkpoint [] checkpoints;
                static int checkpoint_index;
                
-               public readonly static Location Null = new Location (-1);
+               public readonly static Location Null = new Location ();
                public static bool InEmacs;
                
                static Location ()
@@ -269,11 +269,6 @@ namespace Mono.CSharp {
                        // File is always pushed before being changed.
                }
                
-               public Location (int row)
-                       : this (row, 0)
-               {
-               }
-
                public Location (int row, int column)
                {
                        if (row <= 0)
index 3d7f204abbb3fd8085312dfe9965f510b2ca0abb..3a0359705d9127258d0ed2edbcc336caaf9b1d74 100644 (file)
@@ -83,10 +83,10 @@ namespace Mono.CSharp {
                string fullname;
                protected Dictionary<string, Namespace> namespaces;
                protected Dictionary<string, IList<TypeSpec>> types;
+               List<TypeSpec> extension_method_types;
                Dictionary<string, TypeExpr> cached_types;
                RootNamespace root;
                bool cls_checked;
-               bool? has_extension_method;
 
                public readonly MemberName MemberName;
 
@@ -404,34 +404,38 @@ namespace Mono.CSharp {
                //
                public List<MethodSpec> LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity)
                {
-                       if (has_extension_method == false)
+                       if (extension_method_types == null)
                                return null;
 
                        List<MethodSpec> found = null;
-                       if (types != null) {
-                               foreach (var tgroup in types.Values) {
-                                       foreach (var ts in tgroup) {
-                                               if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0)
-                                                       continue;
+                       for (int i = 0; i < extension_method_types.Count; ++i) {
+                               var ts = extension_method_types[i];
 
-                                               has_extension_method = true;
+                               //
+                               // When the list was built we didn't know what members the type
+                               // contains
+                               //
+                               if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) {
+                                       if (extension_method_types.Count == 1) {
+                                               extension_method_types = null;
+                                               return found;
+                                       }
 
-                                               var res = ts.MemberCache.FindExtensionMethods (invocationContext, extensionType, name, arity);
-                                               if (res == null)
-                                                       continue;
+                                       extension_method_types.RemoveAt (i--);
+                                       continue;
+                               }
 
-                                               if (found == null) {
-                                                       found = res;
-                                               } else {
-                                                       found.AddRange (res);
-                                               }
-                                       }
+                               var res = ts.MemberCache.FindExtensionMethods (invocationContext, extensionType, name, arity);
+                               if (res == null)
+                                       continue;
+
+                               if (found == null) {
+                                       found = res;
+                               } else {
+                                       found.AddRange (res);
                                }
                        }
 
-                       if (has_extension_method == null)
-                               has_extension_method = false;
-
                        return found;
                }
 
@@ -441,6 +445,14 @@ namespace Mono.CSharp {
                                types = new Dictionary<string, IList<TypeSpec>> (64);
                        }
 
+                       if (ts.IsStatic && ts.Arity == 0 &&
+                               (ts.MemberDefinition.DeclaringAssembly == null || ts.MemberDefinition.DeclaringAssembly.HasExtensionMethod)) {
+                               if (extension_method_types == null)
+                                       extension_method_types = new List<TypeSpec> ();
+
+                               extension_method_types.Add (ts);
+                       }
+
                        var name = ts.Name;
                        IList<TypeSpec> existing;
                        if (types.TryGetValue (name, out existing)) {
@@ -766,15 +778,6 @@ namespace Mono.CSharp {
                        base.EmitContainer ();
                }
 
-               //
-               // Does extension methods look up to find a method which matches name and extensionType.
-               // Search starts from this namespace and continues hierarchically up to top level.
-               //
-               protected override ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity)
-               {
-                       return LookupExtensionMethod (invocationContext, extensionType, name, arity, this, 0);
-               }
-
                public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, NamespaceContainer container, int position)
                {
                        //