2002-08-13 Martin Baulig <martin@gnome.org>
authorMartin Baulig <martin@novell.com>
Tue, 13 Aug 2002 19:09:39 +0000 (19:09 -0000)
committerMartin Baulig <martin@novell.com>
Tue, 13 Aug 2002 19:09:39 +0000 (19:09 -0000)
Rewrote TypeContainer.FindMembers to use a member cache.  This
gives us a speed increase of about 35% for the self-hosting MCS
build and of about 15-20% for the class libs (both on GNU/Linux).

* report.cs (Timer): New class to get enhanced profiling.  This
whole class is "TIMER" conditional since it remarkably slows down
compilation speed.

* class.cs (MemberList): New class.  This is an IList wrapper
which we're now using instead of passing MemberInfo[]'s around to
avoid copying this array unnecessarily.
(IMemberFinder.FindMember): Return a MemberList, not a MemberInfo [].
(ICachingMemberFinder, IMemberContainer): New interface.
(TypeManager.FilterWithClosure): If `criteria' is null, the name
has already been checked, otherwise use it for the name comparision.
(TypeManager.FindMembers): Renamed to RealMemberFinder and
provided wrapper which tries to use ICachingMemberFinder.FindMembers
if possible.  Returns a MemberList, not a MemberInfo [].
(TypeHandle): New class, implements IMemberContainer.  We create
one instance of this class per type, it contains a MemberCache
which is used to do the member lookups.
(MemberCache): New class.  Each instance of this class contains
all members of a type and a name-based hash table.
(MemberCache.FindMembers): This is our new member lookup
function.  First, it looks up all members of the requested name in
the hash table.  Then, it walks this list and sorts out all
applicable members and returns them.

svn path=/trunk/mcs/; revision=6615

13 files changed:
mcs/mcs/ChangeLog
mcs/mcs/class.cs
mcs/mcs/const.cs
mcs/mcs/delegate.cs
mcs/mcs/driver.cs
mcs/mcs/enum.cs
mcs/mcs/interface.cs
mcs/mcs/makefile
mcs/mcs/pending.cs
mcs/mcs/report.cs
mcs/mcs/rootcontext.cs
mcs/mcs/statement.cs
mcs/mcs/typemanager.cs

index d7d26ae507c0e873e99248d8ee8f57f3e596820e..f4ef9a9ca2f4b68b0ce0164e472cecea18763bf5 100755 (executable)
@@ -1,3 +1,33 @@
+2002-08-13  Martin Baulig  <martin@gnome.org>
+
+       Rewrote TypeContainer.FindMembers to use a member cache.  This
+       gives us a speed increase of about 35% for the self-hosting MCS
+       build and of about 15-20% for the class libs (both on GNU/Linux).
+
+       * report.cs (Timer): New class to get enhanced profiling.  This
+       whole class is "TIMER" conditional since it remarkably slows down
+       compilation speed.
+
+       * class.cs (MemberList): New class.  This is an IList wrapper
+       which we're now using instead of passing MemberInfo[]'s around to
+       avoid copying this array unnecessarily.
+       (IMemberFinder.FindMember): Return a MemberList, not a MemberInfo [].
+       (ICachingMemberFinder, IMemberContainer): New interface.
+       (TypeManager.FilterWithClosure): If `criteria' is null, the name
+       has already been checked, otherwise use it for the name comparision.
+       (TypeManager.FindMembers): Renamed to RealMemberFinder and
+       provided wrapper which tries to use ICachingMemberFinder.FindMembers
+       if possible.  Returns a MemberList, not a MemberInfo [].
+       (TypeHandle): New class, implements IMemberContainer.  We create
+       one instance of this class per type, it contains a MemberCache
+       which is used to do the member lookups.
+       (MemberCache): New class.  Each instance of this class contains
+       all members of a type and a name-based hash table.
+       (MemberCache.FindMembers): This is our new member lookup
+       function.  First, it looks up all members of the requested name in
+       the hash table.  Then, it walks this list and sorts out all
+       applicable members and returns them.
+
 2002-08-13  Martin Baulig  <martin@gnome.org>
 
        In addition to a nice code cleanup, this gives us a performance
index 09cf97579fa799bd7eb3e8142a36cb38ab15e94e..2ede8c38e6b24c13b85f1a55896f08c54e475776 100755 (executable)
@@ -976,7 +976,7 @@ namespace Mono.CSharp {
                                //
                                ptype = TypeBuilder.BaseType;
                                if (ptype != null){
-                                       defined_names = FindMembers (
+                                       defined_names = (MemberInfo []) FindMembers (
                                                ptype, MemberTypes.All & ~MemberTypes.Constructor,
                                                BindingFlags.Public | BindingFlags.Instance |
                                                BindingFlags.Static, null, null);
@@ -1097,8 +1097,8 @@ namespace Mono.CSharp {
                //
                // Since the whole process is a no-op, it is fine to check for null here.
                //
-               public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
-                                                 MemberFilter filter, object criteria)
+               public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                              MemberFilter filter, object criteria)
                {
                        ArrayList members = new ArrayList ();
                        bool priv = (bf & BindingFlags.NonPublic) != 0;
@@ -1270,34 +1270,24 @@ namespace Mono.CSharp {
                        // Lookup members in parent if requested.
                        //
                        if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
-                               MemberInfo [] mi;
-
-                               mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
-                               if (mi != null)
-                                       members.AddRange (mi);
-                       }
-                       
-                       int count = members.Count;
-                       if (count > 0){
-                               MemberInfo [] mi = new MemberInfo [count];
-                               members.CopyTo (mi);
-                               return mi;
+                               MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
+                               members.AddRange (list);
                        }
 
-                       return null;
+                       return new MemberList (members);
                }
 
                
 
-               public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
-                                                        MemberFilter filter, object criteria)
+               public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+                                                     MemberFilter filter, object criteria)
                {
                        TypeContainer tc = TypeManager.LookupTypeContainer (t);
 
                        if (tc != null)
                                return tc.FindMembers (mt, bf, filter, criteria);
                        else
-                               return t.FindMembers (mt, bf, filter, criteria);
+                               return new MemberList (t.FindMembers (mt, bf, filter, criteria));
                }
 
                //
@@ -2001,7 +1991,7 @@ namespace Mono.CSharp {
 
                        MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
                        if (!IsOperator) {
-                               MemberInfo [] mi_this;
+                               MemberList mi_this;
 
                                mi_this = TypeContainer.FindMembers (
                                        parent.TypeBuilder, MemberTypes.Method,
@@ -2010,7 +2000,7 @@ namespace Mono.CSharp {
                                        BindingFlags.DeclaredOnly,
                                        MethodSignature.method_signature_filter, ms);
 
-                               if (mi_this != null && mi_this.Length > 0) {
+                               if (mi_this.Count > 0) {
                                        Report.Error (111, Location, "Class `" + parent.Name + "' " +
                                                      "already defines a member called `" + Name + "' " +
                                                      "with the same parameter types");
@@ -2026,7 +2016,7 @@ namespace Mono.CSharp {
 
                        // ptype is only null for System.Object while compiling corlib.
                        if (ptype != null){
-                               MemberInfo [] mi, mi_static, mi_instance;
+                               MemberList mi, mi_static, mi_instance;
 
                                mi_static = TypeContainer.FindMembers (
                                        ptype, MemberTypes.Method,
@@ -2039,14 +2029,14 @@ namespace Mono.CSharp {
                                        MethodSignature.inheritable_method_signature_filter,
                                        ms);
 
-                               if (mi_instance != null && mi_instance.Length > 0){
+                               if (mi_instance.Count > 0){
                                        mi = mi_instance;
-                               } else if (mi_static != null && mi_static.Length > 0)
+                               } else if (mi_static.Count > 0)
                                        mi = mi_static;
                                else
                                        mi = null;
 
-                               if (mi != null && mi.Length > 0){
+                               if (mi != null && mi.Count > 0){
                                        parent_method = (MethodInfo) mi [0];
                                        string name = parent_method.DeclaringType.Name + "." +
                                                parent_method.Name;
@@ -3129,9 +3119,7 @@ namespace Mono.CSharp {
 
                                // ptype is only null for System.Object while compiling corlib.
                                if (ptype != null){
-                                       MemberInfo [] mi;
-                                       
-                                       mi = TypeContainer.FindMembers (
+                                       TypeContainer.FindMembers (
                                                ptype, MemberTypes.Method,
                                                BindingFlags.Public |
                                                BindingFlags.Static | BindingFlags.Instance,
@@ -3236,7 +3224,7 @@ namespace Mono.CSharp {
                                return false;
 
                        MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
-                       MemberInfo [] props_this;
+                       MemberList props_this;
 
                        props_this = TypeContainer.FindMembers (
                                parent.TypeBuilder, MemberTypes.Property,
@@ -3245,7 +3233,7 @@ namespace Mono.CSharp {
                                BindingFlags.DeclaredOnly,
                                MethodSignature.method_signature_filter, ms);
 
-                       if (props_this != null && props_this.Length > 0) {
+                       if (props_this.Count > 0) {
                                Report.Error (111, Location, "Class `" + parent.Name + "' " +
                                              "already defines a member called `" + Name + "' " +
                                              "with the same parameter types");
@@ -3255,13 +3243,13 @@ namespace Mono.CSharp {
                        //
                        // Find properties with the same name on the base class
                        //
-                       MemberInfo [] props;
-                       MemberInfo [] props_static = TypeContainer.FindMembers (
+                       MemberList props;
+                       MemberList props_static = TypeContainer.FindMembers (
                                parent.TypeBuilder.BaseType, MemberTypes.Property,
                                BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
                                MethodSignature.inheritable_property_signature_filter, ms);
 
-                       MemberInfo [] props_instance = TypeContainer.FindMembers (
+                       MemberList props_instance = TypeContainer.FindMembers (
                                parent.TypeBuilder.BaseType, MemberTypes.Property,
                                BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
                                MethodSignature.inheritable_property_signature_filter,
@@ -3270,16 +3258,16 @@ namespace Mono.CSharp {
                        //
                        // Find if we have anything
                        //
-                       if (props_static != null && props_static.Length > 0)
+                       if (props_static.Count > 0)
                                props = props_static;
-                       else if (props_instance != null && props_instance.Length > 0)
+                       else if (props_instance.Count > 0)
                                props = props_instance;
                        else
                                props = null;
 
                        //
                        // If we have something on the base.
-                       if (props != null && props.Length > 0){
+                       if (props != null && props.Count > 0){
                                PropertyInfo pi = (PropertyInfo) props [0];
 
                                MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
index e6643de5733908d9207b7bc7d2053abd80b0e1f2..2708592a86e306e9d169f0aef583515ec841a500 100755 (executable)
@@ -93,11 +93,11 @@ namespace Mono.CSharp {
                        Type ptype = parent.TypeBuilder.BaseType;
 
                        if (ptype != null) {
-                               MemberInfo [] mi = TypeContainer.FindMembers (
+                               MemberList list = TypeContainer.FindMembers (
                                        ptype, MemberTypes.Field, BindingFlags.Public,
                                        Type.FilterName, Name);
                                
-                               if (mi == null || mi.Length == 0)
+                               if (list.Count == 0)
                                        if ((ModFlags & Modifiers.NEW) != 0)
                                                WarningNotHiding (parent);
 
index 49ef6004b376d8921856760aba98c30e1a4956bd..53aedbe83b17ce6410757c3c162be9d29b8857b0 100644 (file)
@@ -452,7 +452,7 @@ namespace Mono.CSharp {
                }\r
                \r
                // Hack around System.Reflection as found everywhere else\r
-               public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)\r
+               public MemberList FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)\r
                {\r
                        ArrayList members = new ArrayList ();\r
 \r
@@ -474,15 +474,7 @@ namespace Mono.CSharp {
                                        members.Add (EndInvokeBuilder);\r
                        }\r
 \r
-                       int count = members.Count;\r
-\r
-                       if (count > 0) {\r
-                               MemberInfo [] mi = new MemberInfo [count];\r
-                               members.CopyTo (mi, 0);\r
-                               return mi;\r
-                       }\r
-\r
-                       return null;\r
+                       return new MemberList (members);\r
                }\r
                \r
                public void CloseDelegate ()\r
index a7f3209c2d6253fd5794343463d006424a5c19fc..755385c40666c6aea8863c1dc998e65703daba4b 100755 (executable)
@@ -83,13 +83,16 @@ namespace Mono.CSharp
                // Output file
                //
                static string output_file = null;
-               
+
                //
                // Last time we took the time
                //
-               static DateTime last_time;
-               static void ShowTime (string msg)
+               static DateTime last_time, first_time;
+               public static void ShowTime (string msg)
                {
+                       if (!timestamps)
+                               return;
+
                        DateTime now = DateTime.Now;
                        TimeSpan span = now - last_time;
                        last_time = now;
@@ -98,6 +101,20 @@ namespace Mono.CSharp
                                "[{0:00}:{1:000}] {2}",
                                (int) span.TotalSeconds, span.Milliseconds, msg);
                }
+
+               public static void ShowTotalTime (string msg)
+               {
+                       if (!timestamps)
+                               return;
+
+                       DateTime now = DateTime.Now;
+                       TimeSpan span = now - first_time;
+                       last_time = now;
+
+                       Console.WriteLine (
+                               "[{0:00}:{1:000}] {2}",
+                               (int) span.TotalSeconds, span.Milliseconds, msg);
+               }              
               
                static void tokenize_file (string input_file)
                {
@@ -705,7 +722,7 @@ namespace Mono.CSharp
                                
                        case "--timestamp":
                                timestamps = true;
-                               last_time = DateTime.Now;
+                               last_time = first_time = DateTime.Now;
                                debug_arglist.Add ("timestamp");
                                return true;
                                
@@ -1147,6 +1164,7 @@ namespace Mono.CSharp
                        //
                        if (timestamps)
                                ShowTime ("Emitting code");
+                       ShowTotalTime ("Total so far");
                        RootContext.EmitCode ();
                        if (timestamps)
                                ShowTime ("   done");
@@ -1157,7 +1175,7 @@ namespace Mono.CSharp
 
                        if (timestamps)
                                ShowTime ("Closing types");
-                       
+
                        RootContext.CloseTypes ();
 
                        PEFileKinds k = PEFileKinds.ConsoleApplication;
@@ -1206,9 +1224,13 @@ namespace Mono.CSharp
                        }
                        
                        CodeGen.Save (output_file);
-                       if (timestamps)
+                       if (timestamps) {
                                ShowTime ("Saved output");
+                               ShowTotalTime ("Total");
+                       }
 
+                       Timer.ShowTimers ();
+                       
                        if (want_debugging_support) {
                                CodeGen.SaveSymbols ();
                                if (timestamps)
index dd7c8261dda891e261c5b2823588669656c2aab1..12c4a9d0a30ea50af9f50c055017aca19055f2be 100755 (executable)
@@ -440,8 +440,8 @@ namespace Mono.CSharp {
                //
                // Hack around System.Reflection as found everywhere else
                //
-               public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
-                                                 MemberFilter filter, object criteria)
+               public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                              MemberFilter filter, object criteria)
                {
                        ArrayList members = new ArrayList ();
 
@@ -451,15 +451,7 @@ namespace Mono.CSharp {
                                                members.Add (fb);
                        }
 
-                       int count = members.Count;
-
-                       if (count > 0) {
-                               MemberInfo [] mi = new MemberInfo [count];
-                               members.CopyTo (mi, 0);
-                               return mi;
-                       }
-
-                       return null;
+                       return new MemberList (members);
                }
 
                public ArrayList ValueNames {
index 7d0e82e4d3352b78144075609a465d0c4dd9407c..9e0a882892dd98ccd3acf0d6061d8b55f17fa2eb 100755 (executable)
@@ -236,7 +236,7 @@ namespace Mono.CSharp {
                }
 
                // Hack around System.Reflection as found everywhere else
-               public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
+               public MemberList FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
                {
                        ArrayList members = new ArrayList ();
 
@@ -259,26 +259,15 @@ namespace Mono.CSharp {
                        }
 
                        if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
-                               MemberInfo [] parent_mi;
+                               MemberList parent_mi;
                                
                                parent_mi = TypeContainer.FindMembers (
                                        TypeBuilder.BaseType, mt, bf, filter, criteria);
 
-                               if (parent_mi != null)
-                                       members.AddRange (parent_mi);
+                               members.AddRange (parent_mi);
                        }
-                       
-                       // The rest of the cases, if any, are unhandled at present.
-
-                       int count = members.Count;
 
-                       if (count > 0) {
-                               MemberInfo [] mi = new MemberInfo [count];
-                               members.CopyTo (mi, 0);
-                               return mi;
-                       }
-
-                       return null;
+                       return new MemberList (members);
                }
 
                //
index 51bc4d30c1a77b3f0bd240b9a6632f7a18dc980c..f31d0d31663f348d39d4803aec752c5dc077d7f4 100755 (executable)
@@ -52,7 +52,7 @@ mcs3.exe: mcs2.exe
        $(TIME) $(RUNTIME) ./mcs2.exe --target exe -o mcs3.exe $(COMPILER_SOURCES)
 
 mcs-mono.exe: cs-parser.cs $(COMPILER_SOURCES) 
-       mono mcs.exe --timestamp -o mcs-mono.exe $(COMPILER_SOURCES) 
+       mono --precompile @mcs.exe mcs.exe --timestamp -o mcs-mono.exe $(COMPILER_SOURCES) 
 mm:
        mint $(MINTFLAGS) ./mcs.exe $(MCSFLAGS) --target exe -o mcs4.exe $(COMPILER_SOURCES)
 
index 4bfaa6ff15aa4a548b72b1f991673c36ae749575..251bfd54a5a4307bedd5af72cc8192cfd6c18344 100755 (executable)
@@ -83,7 +83,7 @@ namespace Mono.CSharp {
                        Type current_type = t;
                        
                        do {
-                               MemberInfo [] mi;
+                               MemberList mi;
                                
                                mi = TypeContainer.FindMembers (
                                        current_type, MemberTypes.Method,
@@ -99,14 +99,10 @@ namespace Mono.CSharp {
                                                searching = false;
                                }
 
-                               if (mi == null)
+                               if (mi.Count == 0)
                                        continue;
 
-                               int count = mi.Length;
-                               if (count == 0)
-                                       continue;
-
-                               if (count == 1 && !(mi [0] is MethodBase))
+                               if (mi.Count == 1 && !(mi [0] is MethodBase))
                                        searching = false;
                                else 
                                        list = TypeManager.CopyNewMethods (list, mi);
@@ -448,12 +444,12 @@ namespace Mono.CSharp {
                        
                        Type [] args = TypeManager.GetArgumentTypes (mi);
                        ms = new MethodSignature (mi.Name, mi.ReturnType, args);
-                       MemberInfo [] list = TypeContainer.FindMembers (
+                       MemberList list = TypeContainer.FindMembers (
                                container.TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,
                                BindingFlags.Public | BindingFlags.Instance,
                                MethodSignature.method_signature_filter, ms);
 
-                       if (list == null || list.Length == 0)
+                       if (list.Count == 0)
                                return false;
 
                        DefineProxy (iface_type, (MethodInfo) list [0], mi, args);
index 23a73a2bc665e4d36ec508e776bc0a833f145572..825e41b54f37f57a5e5d8d068ac0b500e08bd924 100644 (file)
@@ -246,6 +246,89 @@ namespace Mono.CSharp {
                        Console.WriteLine (error);
                }
        }
+
+       public enum TimerType {
+               FindMembers     = 0,
+               MemberLookup    = 1,
+               CachedLookup    = 2,
+               CacheInit       = 3,
+               MiscTimer       = 4,
+               CountTimers     = 5
+       }
+
+       public enum CounterType {
+               MemberCache     = 0,
+               MiscCounter     = 1,
+               CountCounters   = 2
+       }
+
+       [Conditional("TIMER")]
+       public class Timer
+       {
+               static DateTime[] timer_start;
+               static TimeSpan[] timers;
+               static long[] timer_counters;
+               static long[] counters;
+
+               static Timer ()
+               {
+                       timer_start = new DateTime [(int) TimerType.CountTimers];
+                       timers = new TimeSpan [(int) TimerType.CountTimers];
+                       timer_counters = new long [(int) TimerType.CountTimers];
+                       counters = new long [(int) CounterType.CountCounters];
+
+                       for (int i = 0; i < (int) TimerType.CountTimers; i++) {
+                               timer_start [i] = DateTime.Now;
+                               timers [i] = TimeSpan.Zero;
+                       }
+               }
+
+               [Conditional("TIMER")]
+               static public void IncrementCounter (CounterType which)
+               {
+                       ++counters [(int) which];
+               }
+
+               [Conditional("TIMER")]
+               static public void StartTimer (TimerType which)
+               {
+                       timer_start [(int) which] = DateTime.Now;
+               }
+
+               [Conditional("TIMER")]
+               static public void StopTimer (TimerType which)
+               {
+                       timers [(int) which] += DateTime.Now - timer_start [(int) which];
+                       ++timer_counters [(int) which];
+               }
+
+               [Conditional("TIMER")]
+               static public void ShowTimers ()
+               {
+                       ShowTimer (TimerType.FindMembers, "- FindMembers timer");
+                       ShowTimer (TimerType.MemberLookup, "- MemberLookup timer");
+                       ShowTimer (TimerType.CachedLookup, "- CachedLookup timer");
+                       ShowTimer (TimerType.CacheInit, "- Cache init");
+                       ShowTimer (TimerType.MiscTimer, "- Misc timer");
+
+                       ShowCounter (CounterType.MemberCache, "- Member cache");
+                       ShowCounter (CounterType.MiscCounter, "- Misc counter");
+               }
+
+               static public void ShowCounter (CounterType which, string msg)
+               {
+                       Console.WriteLine ("{0} {1}", counters [(int) which], msg);
+               }
+
+               static public void ShowTimer (TimerType which, string msg)
+               {
+                       Console.WriteLine (
+                               "[{0:00}:{1:000}] {2} (used {3} times)",
+                               (int) timers [(int) which].TotalSeconds,
+                               timers [(int) which].Milliseconds, msg,
+                               timer_counters [(int) which]);
+               }
+       }
 }
 
 
index 9de9670cf926bc4198463bb0d70c6c8ec406c931..2fa43966c0c6ee42cb265970d9be3e82c6aabcfa 100755 (executable)
@@ -693,7 +693,7 @@ namespace Mono.CSharp {
                                        Attribute.ApplyAttributes (temp_ec, ab, ab, attrs, attrs.Location);
                                }
                        }
-                       
+
                        if (attribute_types != null)
                                foreach (TypeContainer tc in attribute_types)
                                        tc.Emit ();
index e3e0389d2d36c809e1a997ab9f9f1e869a3ead8e..6ba7bc634ed038820dac50b754e764b40822719e 100755 (executable)
@@ -4607,13 +4607,13 @@ namespace Mono.CSharp {
                //
                static MethodInfo FetchMethodMoveNext (Type t)
                {
-                       MemberInfo [] move_next_list;
+                       MemberList move_next_list;
                        
                        move_next_list = TypeContainer.FindMembers (
                                t, MemberTypes.Method,
                                BindingFlags.Public | BindingFlags.Instance,
                                Type.FilterName, "MoveNext");
-                       if (move_next_list == null || move_next_list.Length == 0)
+                       if (move_next_list.Count == 0)
                                return null;
 
                        foreach (MemberInfo m in move_next_list){
@@ -4634,13 +4634,13 @@ namespace Mono.CSharp {
                //
                static MethodInfo FetchMethodGetCurrent (Type t)
                {
-                       MemberInfo [] move_next_list;
+                       MemberList move_next_list;
                        
                        move_next_list = TypeContainer.FindMembers (
                                t, MemberTypes.Method,
                                BindingFlags.Public | BindingFlags.Instance,
                                Type.FilterName, "get_Current");
-                       if (move_next_list == null || move_next_list.Length == 0)
+                       if (move_next_list.Count == 0)
                                return null;
 
                        foreach (MemberInfo m in move_next_list){
@@ -4781,14 +4781,14 @@ namespace Mono.CSharp {
 
                static bool TryType (Type t, ForeachHelperMethods hm)
                {
-                       MemberInfo [] mi;
+                       MemberList mi;
                        
                        mi = TypeContainer.FindMembers (t, MemberTypes.Method,
                                                        BindingFlags.Public | BindingFlags.NonPublic |
                                                        BindingFlags.Instance,
                                                        FilterEnumerator, hm);
 
-                       if (mi == null || mi.Length == 0)
+                       if (mi.Count == 0)
                                return false;
 
                        hm.get_enumerator = (MethodInfo) mi [0];
index 1b64acb0469b391322218f67f3a3e5ba4ac5d3cb..0080b286c12549c13399ab721151509ad2e69773 100755 (executable)
@@ -22,11 +22,142 @@ using System.Diagnostics;
 
 namespace Mono.CSharp {
 
+public class MemberList : IList {
+       public readonly IList List;
+       int count;
+
+       public MemberList (IList list)
+       {
+               if (list != null)
+                       this.List = list;
+               else
+                       this.List = new ArrayList ();
+               count = List.Count;
+       }
+
+       public static readonly MemberList Empty = new MemberList (new ArrayList ());
+
+       public static explicit operator MemberInfo [] (MemberList list)
+       {
+               Timer.StartTimer (TimerType.MiscTimer);
+               MemberInfo [] result = new MemberInfo [list.Count];
+               list.CopyTo (result, 0);
+               Timer.StopTimer (TimerType.MiscTimer);
+               return result;
+       }
+
+       // ICollection
+
+       public int Count {
+               get {
+                       return count;
+               }
+       }
+
+       public bool IsSynchronized {
+               get {
+                       return false;
+               }
+       }
+
+       public object SyncRoot {
+               get {
+                       throw new NotSupportedException ();
+               }
+       }
+
+       public void CopyTo (Array array, int index)
+       {
+               List.CopyTo (array, index);
+       }
+
+       // IEnumerable
+
+       public IEnumerator GetEnumerator ()
+       {
+               return List.GetEnumerator ();
+       }
+
+       // IList
+
+       public bool IsFixedSize {
+               get {
+                       return true;
+               }
+       }
+
+       public bool IsReadOnly {
+               get {
+                       return true;
+               }
+       }
+
+       object IList.this [int index] {
+               get {
+                       return List [index];
+               }
+
+               set {
+                       throw new NotSupportedException ();
+               }
+       }
+
+       MemberInfo this [int index] {
+               get {
+                       return (MemberInfo) List [index];
+               }
+       }
+
+       public int Add (object value)
+       {
+               throw new NotSupportedException ();
+       }
+
+       public void Clear ()
+       {
+               throw new NotSupportedException ();
+       }
+
+       public bool Contains (object value)
+       {
+               return List.Contains (value);
+       }
+
+       public int IndexOf (object value)
+       {
+               return List.IndexOf (value);
+       }
+
+       public void Insert (int index, object value)
+       {
+               throw new NotSupportedException ();
+       }
+
+       public void Remove (object value)
+       {
+               throw new NotSupportedException ();
+       }
+
+       public void RemoveAt (int index)
+       {
+               throw new NotSupportedException ();
+       }
+}
+
 public interface IMemberFinder {
-       MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
-                                  MemberFilter filter, object criteria);
+       MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                               MemberFilter filter, object criteria);
 }
-       
+
+public interface ICachingMemberFinder : IMemberFinder {
+       MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
+                               MemberFilter filter, object criteria);
+}
+
+public interface IMemberContainer : ICachingMemberFinder {
+       MemberList GetMembers (MemberTypes mt, BindingFlags bf, bool declared);
+}
+
 public class TypeManager {
        //
        // A list of core types that the compiler requires or uses
@@ -567,21 +698,26 @@ public class TypeManager {
        /// </summary>
        static MethodInfo GetMethod (Type t, string name, Type [] args)
        {
-               MemberInfo [] mi;
+               MemberList list;
                Signature sig;
 
                sig.name = name;
                sig.args = args;
                
-               mi = FindMembers (
-                       t, MemberTypes.Method,
-                       instance_and_static | BindingFlags.Public, signature_filter, sig);
-               if (mi == null || mi.Length == 0 || !(mi [0] is MethodInfo)){
+               list = FindMembers (t, MemberTypes.Method, instance_and_static | BindingFlags.Public,
+                                   signature_filter, sig);
+               if (list.Count == 0) {
+                       Report.Error (-19, "Can not find the core function `" + name + "'");
+                       return null;
+               }
+
+               MethodInfo mi = list [0] as MethodInfo;
+               if (mi == null) {
                        Report.Error (-19, "Can not find the core function `" + name + "'");
                        return null;
                }
 
-               return (MethodInfo) mi [0];
+               return mi;
        }
 
        /// <summary>
@@ -589,20 +725,27 @@ public class TypeManager {
        /// </summary>
        static ConstructorInfo GetConstructor (Type t, Type [] args)
        {
-               MemberInfo [] mi;
+               MemberList list;
                Signature sig;
 
                sig.name = ".ctor";
                sig.args = args;
                
-               mi = FindMembers (t, MemberTypes.Constructor,
-                                 instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly, signature_filter, sig);
-               if (mi == null || mi.Length == 0 || !(mi [0] is ConstructorInfo)){
+               list = FindMembers (t, MemberTypes.Constructor,
+                                   instance_and_static | BindingFlags.Public | BindingFlags.DeclaredOnly,
+                                   signature_filter, sig);
+               if (list.Count == 0){
                        Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
                        return null;
                }
 
-               return (ConstructorInfo) mi [0];
+               ConstructorInfo ci = list [0] as ConstructorInfo;
+               if (ci == null){
+                       Report.Error (-19, "Can not find the core constructor for type `" + t.Name + "'");
+                       return null;
+               }
+
+               return ci;
        }
 
        public static void InitEnumUnderlyingTypes ()
@@ -835,11 +978,40 @@ public class TypeManager {
 
        const BindingFlags instance_and_static = BindingFlags.Static | BindingFlags.Instance;
 
+       static Hashtable type_hash = new Hashtable ();
+
+       public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+                                             MemberFilter filter, object criteria)
+       {
+               IMemberFinder finder = (IMemberFinder) builder_to_member_finder [t];
+               ICachingMemberFinder caching_finder = finder as ICachingMemberFinder;
+
+               if (finder != null) {
+                       if ((caching_finder == null) || (filter != FilterWithClosure_delegate)) {
+                               MemberList list;
+                               Timer.StartTimer (TimerType.FindMembers);
+                               list = finder.FindMembers (mt, bf, filter, criteria);
+                               Timer.StopTimer (TimerType.FindMembers);
+                               return list;
+                       }
+
+                       return caching_finder.FindMembers (mt, bf, (string) criteria, filter, null);
+               }
+
+               if (filter != FilterWithClosure_delegate)
+                       return new MemberList (RealFindMembers (t, mt, bf, filter, criteria));
+
+               caching_finder = new TypeHandle (t);
+               builder_to_member_finder.Add (t, caching_finder);
+
+               return caching_finder.FindMembers (mt, bf, (string) criteria, filter, null);
+       }
+
        //
        // FIXME: This can be optimized easily.  speedup by having a single builder mapping
        //
-       public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
-                                                MemberFilter filter, object criteria)
+       static MemberInfo [] RealFindMembers (Type t, MemberTypes mt, BindingFlags bf,
+                                             MemberFilter filter, object criteria)
        {
                //
                // We have to take care of arrays specially, because GetType on
@@ -848,53 +1020,48 @@ public class TypeManager {
                //
                if (t.IsSubclassOf (TypeManager.array_type))
                        return TypeManager.array_type.FindMembers (mt, bf, filter, criteria);
+
+               if (t is TypeBuilder)
+                       return null;
                
-               if (!(t is TypeBuilder)){
-                       //
-                       // Since FindMembers will not lookup both static and instance
-                       // members, we emulate this behaviour here.
-                       //
-                       if ((bf & instance_and_static) == instance_and_static){
-                               MemberInfo [] i_members = t.FindMembers (
-                                       mt, bf & ~BindingFlags.Static, filter, criteria);
-
-                               int i_len = i_members.Length;
-                               if (i_len == 1){
-                                       MemberInfo one = i_members [0];
-
-                                       //
-                                       // If any of these are present, we are done!
-                                       //
-                                       if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
-                                               return i_members;
-                               }
-                               
-                               MemberInfo [] s_members = t.FindMembers (
-                                       mt, bf & ~BindingFlags.Instance, filter, criteria);
-
-                               int s_len = s_members.Length;
-                               if (i_len > 0 || s_len > 0){
-                                       MemberInfo [] both = new MemberInfo [i_len + s_len];
-
-                                       i_members.CopyTo (both, 0);
-                                       s_members.CopyTo (both, i_len);
-
-                                       return both;
-                               } else {
-                                       if (i_len > 0)
-                                               return i_members;
-                                       else
-                                               return s_members;
-                               }
+               //
+               // Since FindMembers will not lookup both static and instance
+               // members, we emulate this behaviour here.
+               //
+               if ((bf & instance_and_static) == instance_and_static){
+                       MemberInfo [] i_members = t.FindMembers (
+                               mt, bf & ~BindingFlags.Static, filter, criteria);
+
+                       int i_len = i_members.Length;
+                       if (i_len == 1){
+                               MemberInfo one = i_members [0];
+
+                               //
+                               // If any of these are present, we are done!
+                               //
+                               if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
+                                       return i_members;
                        }
-                       return t.FindMembers (mt, bf, filter, criteria);
-               }
+                               
+                       MemberInfo [] s_members = t.FindMembers (
+                               mt, bf & ~BindingFlags.Instance, filter, criteria);
 
-               IMemberFinder finder = (IMemberFinder) builder_to_member_finder [t];
-               if (finder != null)
-                       return finder.FindMembers (mt, bf, filter, criteria);
+                       int s_len = s_members.Length;
+                       if (i_len > 0 || s_len > 0){
+                               MemberInfo [] both = new MemberInfo [i_len + s_len];
 
-               return null;
+                               i_members.CopyTo (both, 0);
+                               s_members.CopyTo (both, i_len);
+
+                               return both;
+                       } else {
+                               if (i_len > 0)
+                                       return i_members;
+                               else
+                                       return s_members;
+                       }
+               }
+               return t.FindMembers (mt, bf, filter, criteria);
        }
 
        public static bool IsBuiltinType (Type t)
@@ -1612,7 +1779,7 @@ public class TypeManager {
        //
        // The name is assumed to be the same.
        //
-       public static ArrayList CopyNewMethods (ArrayList target_list, MemberInfo [] new_members)
+       public static ArrayList CopyNewMethods (ArrayList target_list, MemberList new_members)
        {
                if (target_list == null){
                        target_list = new ArrayList ();
@@ -1738,7 +1905,7 @@ public class TypeManager {
                // fields. 
                //
 
-               if (m.Name != closure_name)
+               if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
                        return false;
 
                //
@@ -1840,7 +2007,7 @@ public class TypeManager {
        }
 
        static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
-       
+
        //
        // Looks up a member called `name' in the `queried_type'.  This lookup
        // is done by code that is contained in the definition for `invocation_type'.
@@ -1852,6 +2019,19 @@ public class TypeManager {
        //
        public static MemberInfo [] MemberLookup (Type invocation_type, Type queried_type, 
                                                  MemberTypes mt, BindingFlags original_bf, string name)
+       {
+               Timer.StartTimer (TimerType.MemberLookup);
+
+               MemberInfo[] retval = RealMemberLookup (invocation_type, queried_type,
+                                                       mt, original_bf, name);
+
+               Timer.StopTimer (TimerType.MemberLookup);
+
+               return retval;
+       }
+
+       static MemberInfo [] RealMemberLookup (Type invocation_type, Type queried_type, 
+                                              MemberTypes mt, BindingFlags original_bf, string name)
        {
                BindingFlags bf = original_bf;
                
@@ -1886,7 +2066,7 @@ public class TypeManager {
                }
                
                do {
-                       MemberInfo [] mi;
+                       MemberList list;
 
                        //
                        // `NonPublic' is lame, because it includes both protected and
@@ -1913,10 +2093,19 @@ public class TypeManager {
                        closure_private_ok = private_ok;
                        closure_queried_type = current_type;
 
-                       mi = TypeManager.FindMembers (
-                               current_type, mt, bf | BindingFlags.DeclaredOnly,
-                               FilterWithClosure_delegate, name);
+                       Timer.StopTimer (TimerType.MemberLookup);
+
+                       if (MemberCache.IsSingleMemberType (mt)) {
+                               searching = false;
+                               list = TypeManager.FindMembers (current_type, mt, bf,
+                                       FilterWithClosure_delegate, name);
+                       } else
+                               list = TypeManager.FindMembers (
+                                       current_type, mt, bf | BindingFlags.DeclaredOnly,
+                                       FilterWithClosure_delegate, name);
                        
+                       Timer.StartTimer (TimerType.MemberLookup);
+
                        if (current_type == TypeManager.object_type)
                                searching = false;
                        else {
@@ -1930,12 +2119,7 @@ public class TypeManager {
                                        current_type = TypeManager.object_type;
                        }
                        
-                       if (mi == null)
-                               continue;
-                       
-                       int count = mi.Length;
-                       
-                       if (count == 0)
+                       if (list.Count == 0)
                                continue;
                        
                        //
@@ -1943,23 +2127,23 @@ public class TypeManager {
                        // searches, which means that our above FindMembers will
                        // return two copies of the same.
                        //
-                       if (count == 1 && !(mi [0] is MethodBase)){
-                               return mi;
+                       if (list.Count == 1 && !(list [0] is MethodBase)){
+                               return (MemberInfo []) list;
                        }
 
                        //
                        // Multiple properties: we query those just to find out the indexer
                        // name
                        //
-                       if (mi [0] is PropertyInfo)
-                               return mi;
+                       if (list [0] is PropertyInfo)
+                               return (MemberInfo []) list;
 
                        //
                        // We found methods, turn the search into "method scan"
                        // mode.
                        //
                        
-                       method_list = CopyNewMethods (method_list, mi);
+                       method_list = CopyNewMethods (method_list, list);
                        mt &= (MemberTypes.Method | MemberTypes.Constructor);
                } while (searching);
 
@@ -1994,4 +2178,236 @@ public class TypeManager {
        
 }
 
+public class MemberCache {
+       public readonly IMemberContainer Container;
+       protected Hashtable MemberHash;
+
+       public MemberCache (IMemberContainer container)
+       {
+               this.Container = container;
+               this.MemberHash = new Hashtable ();
+
+               Timer.IncrementCounter (CounterType.MemberCache);
+               Timer.StartTimer (TimerType.CacheInit);
+
+               AddMembers (true);
+               AddMembers (false);
+
+               Timer.StopTimer (TimerType.CacheInit);
+       }
+
+       void AddMembers (bool declared)
+       {
+               AddMembers (MemberTypes.Constructor, declared);
+               AddMembers (MemberTypes.Event, declared);
+               AddMembers (MemberTypes.Field, declared);
+               AddMembers (MemberTypes.Method, declared);
+               AddMembers (MemberTypes.Property, declared);
+               AddMembers (MemberTypes.NestedType, declared);
+       }
+
+       void AddMembers (MemberTypes mt, bool declared)
+       {
+               AddMembers (mt, BindingFlags.Static | BindingFlags.Public, declared);
+               AddMembers (mt, BindingFlags.Static | BindingFlags.NonPublic, declared);
+               AddMembers (mt, BindingFlags.Instance | BindingFlags.Public, declared);
+               AddMembers (mt, BindingFlags.Instance | BindingFlags.NonPublic, declared);
+       }
+
+       void AddMembers (MemberTypes mt, BindingFlags bf, bool declared)
+       {
+               MemberList members = Container.GetMembers (mt, bf, declared);
+               BindingFlags new_bf = declared ? bf | BindingFlags.DeclaredOnly : bf;
+
+               foreach (MemberInfo member in members) {
+                       string name = member.Name;
+
+                       ArrayList list = (ArrayList) MemberHash [name];
+                       if (list == null) {
+                               list = new ArrayList ();
+                               MemberHash.Add (name, list);
+                       }
+
+                       list.Add (new CacheEntry (member, mt, new_bf));
+               }
+       }
+
+       protected static EntryType GetEntryType (MemberTypes mt, BindingFlags bf)
+       {
+               EntryType type = EntryType.None;
+
+               if ((mt & MemberTypes.Constructor) != 0)
+                       type |= EntryType.Constructor;
+               if ((mt & MemberTypes.Event) != 0)
+                       type |= EntryType.Event;
+               if ((mt & MemberTypes.Field) != 0)
+                       type |= EntryType.Field;
+               if ((mt & MemberTypes.Method) != 0)
+                       type |= EntryType.Method;
+               if ((mt & MemberTypes.Property) != 0)
+                       type |= EntryType.Property;
+               if ((mt & MemberTypes.NestedType) != 0)
+                       type |= EntryType.NestedType;
+
+               if ((bf & BindingFlags.Instance) != 0)
+                       type |= EntryType.Instance;
+               if ((bf & BindingFlags.Static) != 0)
+                       type |= EntryType.Static;
+               if ((bf & BindingFlags.Public) != 0)
+                       type |= EntryType.Public;
+               if ((bf & BindingFlags.NonPublic) != 0)
+                       type |= EntryType.NonPublic;
+               if ((bf & BindingFlags.DeclaredOnly) != 0)
+                       type |= EntryType.Declared;
+
+               return type;
+       }
+
+       public static bool IsSingleMemberType (MemberTypes mt)
+       {
+               switch (mt) {
+               case MemberTypes.Constructor:
+               case MemberTypes.Event:
+               case MemberTypes.Field:
+               case MemberTypes.Method:
+               case MemberTypes.Property:
+               case MemberTypes.NestedType:
+                       return true;
+
+               default:
+                       return false;
+               }
+       }
+
+       [Flags]
+       protected enum EntryType {
+               None            = 0x000,
+
+               Instance        = 0x001,
+               Static          = 0x002,
+               MaskStatic      = Instance|Static,
+
+               Public          = 0x004,
+               NonPublic       = 0x008,
+               MaskProtection  = Public|NonPublic,
+
+               Declared        = 0x010,
+
+               Constructor     = 0x020,
+               Event           = 0x040,
+               Field           = 0x080,
+               Method          = 0x100,
+               Property        = 0x200,
+               NestedType      = 0x400,
+
+               MaskType        = Constructor|Event|Field|Method|Property|NestedType
+       }
+
+       protected struct CacheEntry {
+               public EntryType EntryType;
+               public MemberInfo Member;
+
+               public CacheEntry (MemberInfo member, MemberTypes mt, BindingFlags bf)
+               {
+                       this.Member = member;
+                       this.EntryType = GetEntryType (mt, bf);
+               }
+       }
+
+       protected void SearchMembers (ArrayList list, MemberTypes mt, BindingFlags bf, IList applicable,
+                                     MemberFilter filter, object criteria)
+       {
+               bool declared_only = (bf & BindingFlags.DeclaredOnly) != 0;
+               EntryType type = GetEntryType (mt, bf);
+
+               foreach (CacheEntry entry in applicable) {
+                       if (declared_only && ((entry.EntryType & EntryType.Declared) == 0))
+                               continue;
+
+                       if ((entry.EntryType & type & EntryType.MaskType) == 0)
+                               continue;
+
+                       if ((entry.EntryType & type & EntryType.MaskStatic) == 0)
+                               continue;
+
+                       if (filter (entry.Member, criteria))
+                               list.Add (entry.Member);
+               }
+       }
+
+       public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
+                                      MemberFilter filter, object criteria)
+       {
+               IList applicable = (IList) MemberHash [name];
+               if (applicable == null)
+                       return MemberList.Empty;
+
+               ArrayList list = new ArrayList ();
+
+               if ((bf & BindingFlags.Static) != 0) {
+                       SearchMembers (list, mt, bf & ~BindingFlags.Instance, applicable,
+                                      filter, criteria);
+
+                       if (list.Count == 1){
+                               MemberInfo one = (MemberInfo) list [0];
+
+                               //
+                               // If any of these are present, we are done!
+                               //
+                               if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
+                                       return new MemberList (list);
+                       }
+               }                               
+
+               if ((bf & BindingFlags.Instance) != 0)
+                       SearchMembers (list, mt, bf & ~BindingFlags.Static, applicable,
+                                      filter, criteria);
+
+               return new MemberList (list);
+       }
+}
+
+public class TypeHandle : IMemberContainer {
+       public readonly Type Type;
+       public readonly Type BaseType;
+       public readonly MemberCache MemberCache;
+
+       public TypeHandle (Type t)
+       {
+               this.Type = t;
+               this.BaseType = t.BaseType;
+               this.MemberCache = new MemberCache (this);
+       }
+
+       public MemberList GetMembers (MemberTypes mt, BindingFlags bf, bool declared)
+       {
+               if (declared)
+                       return new MemberList (Type.FindMembers (
+                               mt, bf | BindingFlags.DeclaredOnly, null, null));
+
+               if (BaseType == null)
+                       return MemberList.Empty;
+
+               return new MemberList (BaseType.FindMembers (mt, bf, null, null));
+       }
+
+       public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                      MemberFilter filter, object criteria)
+       {
+               throw new NotSupportedException ();
+       }
+
+       public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
+                                      MemberFilter filter, object criteria)
+       {
+               MemberList list;
+
+               Timer.StartTimer (TimerType.CachedLookup);
+               list = MemberCache.FindMembers (mt, bf, name, filter, criteria);
+               Timer.StopTimer (TimerType.CachedLookup);
+
+               return list;
+       }
+}
+
 }