2002-11-16 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mcs / typemanager.cs
index 536a0bb9f53bbc3b5accb8ef8cc5e8a7652973d7..e8d3e9bbd1ee6e9ec3ea9fdc1f2564babf0e52a5 100755 (executable)
@@ -9,7 +9,13 @@
 // (C) 2001 Ximian, Inc (http://www.ximian.com)
 //
 //
-#define CACHE
+
+//
+// We will eventually remove the SIMPLE_SPEEDUP, and should never change 
+// the behavior of the compilation.  This can be removed if we rework
+// the code to get a list of namespaces available.
+//
+#define SIMPLE_SPEEDUP
 
 using System;
 using System.Globalization;
@@ -22,142 +28,6 @@ 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 ();
-               }
-       }
-
-       public 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 {
-       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
@@ -315,7 +185,7 @@ public class TypeManager {
        // </remarks>
        static ArrayList user_types;
 
-       static PtrHashtable builder_to_member_finder;
+       static PtrHashtable builder_to_declspace;
 
        // <remarks>
        //   Tracks the interfaces implemented by typebuilders.  We only
@@ -436,7 +306,7 @@ public class TypeManager {
                types = new Hashtable ();
                typecontainers = new Hashtable ();
                
-               builder_to_member_finder = new PtrHashtable ();
+               builder_to_declspace = new PtrHashtable ();
                builder_to_attr = new PtrHashtable ();
                builder_to_method = new PtrHashtable ();
                method_arguments = new PtrHashtable ();
@@ -456,7 +326,7 @@ public class TypeManager {
                        types.Add (name, t);
                } catch {
                        Type prev = (Type) types [name];
-                       TypeContainer tc = builder_to_member_finder [prev] as TypeContainer;
+                       TypeContainer tc = builder_to_declspace [prev] as TypeContainer;
 
                        if (tc != null){
                                //
@@ -466,7 +336,7 @@ public class TypeManager {
                                return;
                        }
 
-                       tc = builder_to_member_finder [t] as TypeContainer;
+                       tc = builder_to_declspace [t] as TypeContainer;
                        
                        Report.Warning (
                                1595, "The type `" + name + "' is defined in an existing assembly;"+
@@ -493,7 +363,7 @@ public class TypeManager {
        
        public static void AddUserType (string name, TypeBuilder t, TypeContainer tc, Type [] ifaces)
        {
-               builder_to_member_finder.Add (t, tc);
+               builder_to_declspace.Add (t, tc);
                typecontainers.Add (name, tc);
                AddUserType (name, t, ifaces);
        }
@@ -501,19 +371,19 @@ public class TypeManager {
        public static void AddDelegateType (string name, TypeBuilder t, Delegate del)
        {
                types.Add (name, t);
-               builder_to_member_finder.Add (t, del);
+               builder_to_declspace.Add (t, del);
        }
        
        public static void AddEnumType (string name, TypeBuilder t, Enum en)
        {
                types.Add (name, t);
-               builder_to_member_finder.Add (t, en);
+               builder_to_declspace.Add (t, en);
        }
 
        public static void AddUserInterface (string name, TypeBuilder t, Interface i, Type [] ifaces)
        {
                AddUserType (name, t, ifaces);
-               builder_to_member_finder.Add (t, i);
+               builder_to_declspace.Add (t, i);
        }
 
        public static void AddMethod (MethodBuilder builder, MethodData method)
@@ -532,22 +402,33 @@ public class TypeManager {
        /// </summary>
        public static TypeContainer LookupTypeContainer (Type t)
        {
-               return builder_to_member_finder [t] as TypeContainer;
+               return builder_to_declspace [t] as TypeContainer;
+       }
+
+       public static IMemberContainer LookupMemberContainer (Type t)
+       {
+               if (t is TypeBuilder) {
+                       IMemberContainer container = builder_to_declspace [t] as IMemberContainer;
+                       if (container != null)
+                               return container;
+               }
+
+               return TypeHandle.GetTypeHandle (t);
        }
 
        public static Interface LookupInterface (Type t)
        {
-               return builder_to_member_finder [t] as Interface;
+               return builder_to_declspace [t] as Interface;
        }
 
        public static Delegate LookupDelegate (Type t)
        {
-               return builder_to_member_finder [t] as Delegate;
+               return builder_to_declspace [t] as Delegate;
        }
 
        public static Enum LookupEnum (Type t)
        {
-               return builder_to_member_finder [t] as Enum;
+               return builder_to_declspace [t] as Enum;
        }
        
        public static TypeContainer LookupAttr (Type t)
@@ -583,8 +464,56 @@ public class TypeManager {
                modules = n;
        }
 
+       //
+       // Low-level lookup, cache-less
+       //
+       static Type LookupTypeReflection (string name)
+       {
+               Type t;
+
+               foreach (Assembly a in assemblies){
+                       t = a.GetType (name);
+                       if (t != null)
+                               return t;
+               }
+
+               foreach (ModuleBuilder mb in modules) {
+                       t = mb.GetType (name);
+                       if (t != null){
+                               return t;
+                       }
+               }
+               return null;
+       }
+
+       static Hashtable negative_hits = new Hashtable ();
+       
+       //
+       // This function is used when you want to avoid the lookups, and want to go
+       // directly to the source.  This will use the cache.
+       //
+       // Notice that bypassing the cache is bad, because on Microsoft.NET runtime
+       // GetType ("DynamicType[]") != GetType ("DynamicType[]"), and there is no
+       // way to test things other than doing a fullname compare
+       //
+       public static Type LookupTypeDirect (string name)
+       {
+               Type t = (Type) types [name];
+               if (t != null)
+                       return t;
+
+               t = LookupTypeReflection (name);
+               if (t == null)
+                       return null;
+
+               types [name] = t;
+               return t;
+       }
+       
        /// <summary>
-       ///   Returns the Type associated with @name
+       ///   Returns the Type associated with @name, takes care of the fact that
+       ///   reflection expects nested types to be separated from the main type
+       ///   with a "+" instead of a "."
        /// </summary>
        public static Type LookupType (string name)
        {
@@ -598,26 +527,99 @@ public class TypeManager {
                if (t != null)
                        return t;
 
-               foreach (Assembly a in assemblies){
-                       t = a.GetType (name);
-                       if (t != null){
-                               types [name] = t;
+#if SIMPLE_SPEEDUP
+               if (negative_hits.Contains (name))
+                       return null;
+#endif
+               
+               //
+               // Optimization: ComposedCast will work with an existing type, and might already have the
+               // full name of the type, so the full system lookup can probably be avoided.
+               //
+               
+               string [] elements = name.Split ('.');
+               int count = elements.Length;
+
+               for (int n = 1; n <= count; n++){
+                       string top_level_type = String.Join (".", elements, 0, n);
 
+                       t = (Type) types [top_level_type];
+                       if (t == null){
+                               t = LookupTypeReflection (top_level_type);
+                               if (t == null)
+                                       continue;
+                       }
+                       
+                       if (count == n){
+                               types [name] = t;
                                return t;
+                       } 
+
+                       //
+                       // We know that System.Object does not have children, and since its the parent of 
+                       // all the objects, it always gets probbed for inner classes. 
+                       //
+                       if (top_level_type == "System.Object")
+                               return null;
+                       
+                       string newt = top_level_type + "+" + String.Join ("+", elements, n, count - n);
+                       t = LookupTypeDirect (newt);
+                       if (t != null)
+                               types [newt] = t;
+                       return t;
+               }
+
+#if SIMPLE_SPEEDUP
+               negative_hits [name] = true;
+#endif
+               return null;
+       }
+
+       //
+       // Returns a list of all namespaces in the assemblies and types loaded.
+       //
+       public static Hashtable GetNamespaces ()
+       {
+               Hashtable namespaces = new Hashtable ();
+
+               foreach (Assembly a in assemblies){
+                       foreach (Type t in a.GetTypes ()){
+                               string ns = t.Namespace;
+
+                               if (namespaces.Contains (ns))
+                                       continue;
+                               namespaces [ns] = ns;
                        }
                }
 
-               foreach (ModuleBuilder mb in modules) {
-                       t = mb.GetType (name);
-                       if (t != null) {
-                               types [name] = t;
-                               return t;
+               foreach (ModuleBuilder mb in modules){
+                       foreach (Type t in mb.GetTypes ()){
+                               string ns = t.Namespace;
+
+                               if (namespaces.Contains (ns))
+                                       continue;
+                               namespaces [ns] = ns;
                        }
                }
-               
-               return null;
+               Console.WriteLine ("Namespaces: " + namespaces.Count);
+               return namespaces;
        }
 
+       public static void GetAllTypes ()
+       {
+               Hashtable namespaces = new Hashtable ();
+
+               foreach (Assembly a in assemblies){
+                       foreach (Type t in a.GetTypes ()){
+                       }
+               }
+
+               foreach (ModuleBuilder mb in modules){
+                       foreach (Type t in mb.GetTypes ()){
+                       }
+               }
+       }
+       
        /// <summary>
        ///   Returns the C# name of a type if possible, or the full type name otherwise
        /// </summary>
@@ -980,50 +982,34 @@ public class TypeManager {
 
        static Hashtable type_hash = new Hashtable ();
 
+       /// <remarks>
+       ///   This is the "old", non-cache based FindMembers() function.  We cannot use
+       ///   the cache here because there is no member name argument.
+       /// </remarks>
        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;
-                       }
+               DeclSpace decl = (DeclSpace) builder_to_declspace [t];
 
-                       return caching_finder.FindMembers (mt, bf, (string) criteria, filter, null);
+               //
+               // `builder_to_declspace' contains all dynamic types.
+               //
+               if (decl != null) {
+                       MemberList list;
+                       Timer.StartTimer (TimerType.FindMembers);
+                       list = decl.FindMembers (mt, bf, filter, criteria);
+                       Timer.StopTimer (TimerType.FindMembers);
+                       return list;
                }
 
-               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
-       //
-       static MemberInfo [] RealFindMembers (Type t, MemberTypes mt, BindingFlags bf,
-                                             MemberFilter filter, object criteria)
-       {
                //
                // We have to take care of arrays specially, because GetType on
                // a TypeBuilder array will return a Type, not a TypeBuilder,
                // and we can not call FindMembers on this type.
                //
                if (t.IsSubclassOf (TypeManager.array_type))
-                       return TypeManager.array_type.FindMembers (mt, bf, filter, criteria);
+                       return new MemberList (TypeManager.array_type.FindMembers (mt, bf, filter, criteria));
 
-               if (t is TypeBuilder)
-                       return null;
-               
                //
                // Since FindMembers will not lookup both static and instance
                // members, we emulate this behaviour here.
@@ -1040,28 +1026,86 @@ public class TypeManager {
                                // If any of these are present, we are done!
                                //
                                if ((one is Type) || (one is EventInfo) || (one is FieldInfo))
-                                       return i_members;
+                                       return new MemberList (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 || s_len > 0)
+                               return new MemberList (i_members, s_members);
+                       else {
                                if (i_len > 0)
-                                       return i_members;
+                                       return new MemberList (i_members);
                                else
-                                       return s_members;
+                                       return new MemberList (s_members);
+                       }
+               }
+
+               return new MemberList (t.FindMembers (mt, bf, filter, criteria));
+       }
+
+
+       /// <summary>
+       ///   This method is only called from within MemberLookup.  It tries to use the member
+       ///   cache if possible and falls back to the normal FindMembers if not.  The `used_cache'
+       ///   flag tells the caller whether we used the cache or not.  If we used the cache, then
+       ///   our return value will already contain all inherited members and the caller don't need
+       ///   to check base classes and interfaces anymore.
+       /// </summary>
+       private static MemberList MemberLookup_FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+                                                           string name, out bool used_cache)
+       {
+               //
+               // We have to take care of arrays specially, because GetType on
+               // a TypeBuilder array will return a Type, not a TypeBuilder,
+               // and we can not call FindMembers on this type.
+               //
+               if (t.IsSubclassOf (TypeManager.array_type)) {
+                       used_cache = true;
+                       return TypeHandle.ArrayType.MemberCache.FindMembers (
+                               mt, bf, name, FilterWithClosure_delegate, null);
+               }
+
+               //
+               // If this is a dynamic type, it's always in the `builder_to_declspace' hash table
+               // and we can ask the DeclSpace for the MemberCache.
+               //
+               if (t is TypeBuilder) {
+                       DeclSpace decl = (DeclSpace) builder_to_declspace [t];
+                       MemberCache cache = decl.MemberCache;
+
+                       //
+                       // If this DeclSpace has a MemberCache, use it.
+                       //
+
+                       if (cache != null) {
+                               used_cache = true;
+                               return cache.FindMembers (
+                                       mt, bf, name, FilterWithClosure_delegate, null);
                        }
+
+                       // If there is no MemberCache, we need to use the "normal" FindMembers.
+
+                       MemberList list;
+                       Timer.StartTimer (TimerType.FindMembers);
+                       list = decl.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
+                                                FilterWithClosure_delegate, name);
+                       Timer.StopTimer (TimerType.FindMembers);
+                       used_cache = false;
+                       return list;
                }
-               return t.FindMembers (mt, bf, filter, criteria);
+
+               //
+               // This call will always succeed.  There is exactly one TypeHandle instance per
+               // type, TypeHandle.GetTypeHandle() will either return it or create a new one
+               // if it didn't already exist.
+               //
+               TypeHandle handle = TypeHandle.GetTypeHandle (t);
+
+               used_cache = true;
+               return handle.MemberCache.FindMembers (mt, bf, name, FilterWithClosure_delegate, null);
        }
 
        public static bool IsBuiltinType (Type t)
@@ -1090,7 +1134,47 @@ public class TypeManager {
                else
                        return false;
        }
-       
+
+       //
+       // Whether a type is unmanaged.  This is used by the unsafe code (25.2)
+       //
+       public static bool IsUnmanagedType (Type t)
+       {
+               if (IsBuiltinType (t) && t != TypeManager.string_type)
+                       return true;
+
+               if (IsEnumType (t))
+                       return true;
+
+               if (t.IsPointer)
+                       return true;
+
+               if (IsValueType (t)){
+                       if (t is TypeBuilder){
+                               TypeContainer tc = LookupTypeContainer (t);
+
+                               foreach (Field f in tc.Fields){
+                                       if (f.FieldBuilder.IsStatic)
+                                               continue;
+                                       if (!IsUnmanagedType (f.FieldBuilder.FieldType))
+                                               return false;
+                               }
+                       } else {
+                               FieldInfo [] fields = t.GetFields ();
+
+                               foreach (FieldInfo f in fields){
+                                       if (f.IsStatic)
+                                               continue;
+                                       if (!IsUnmanagedType (f.FieldType))
+                                               return false;
+                               }
+                       }
+                       return true;
+               }
+
+               return false;
+       }
+               
        public static bool IsValueType (Type t)
        {
                if (t.IsSubclassOf (TypeManager.value_type))
@@ -1101,7 +1185,7 @@ public class TypeManager {
        
        public static bool IsInterfaceType (Type t)
        {
-               Interface iface = builder_to_member_finder [t] as Interface;
+               Interface iface = builder_to_declspace [t] as Interface;
 
                if (iface != null)
                        return true;
@@ -1115,7 +1199,7 @@ public class TypeManager {
        public static bool IsSubclassOrNestedChildOf (Type type, Type parent)
        {
                do {
-                       if (type.IsSubclassOf (parent))
+                       if ((type == parent) || type.IsSubclassOf (parent))
                                return true;
 
                        // Handle nested types.
@@ -1125,6 +1209,17 @@ public class TypeManager {
                return false;
        }
 
+       //
+       // Checks whether `type' is a nested child of `parent'.
+       //
+       public static bool IsNestedChildOf (Type type, Type parent)
+       {
+               if ((type == parent) || type.IsSubclassOf (parent))
+                       return false;
+               else
+                       return IsSubclassOrNestedChildOf (type, parent);
+       }
+
        /// <summary>
        ///   Returns the User Defined Types
        /// </summary>
@@ -1363,57 +1458,6 @@ public class TypeManager {
                return true;
        }
 
-       //
-       // FIXME: we need to return the accessors depending on whether
-       // they are visible or not.
-       //
-       static public MethodInfo [] GetAccessors (PropertyInfo pi)
-       {
-               MethodInfo [] ret;
-
-               if (pi is PropertyBuilder){
-                       Pair pair = (Pair) properties [pi];
-
-                       ret = new MethodInfo [2];
-                       ret [0] = (MethodInfo) pair.First;
-                       ret [1] = (MethodInfo) pair.Second;
-
-                       return ret;
-               } else {
-                       MethodInfo [] mi = new MethodInfo [2];
-
-                       //
-                       // Why this and not pi.GetAccessors?
-                       // Because sometimes index 0 is the getter
-                       // sometimes it is 1
-                       //
-                       mi [0] = pi.GetGetMethod (true);
-                       mi [1] = pi.GetSetMethod (true);
-
-                       return mi;
-               }
-       }
-
-       static public MethodInfo GetPropertyGetter (PropertyInfo pi)
-       {
-               if (pi is PropertyBuilder){
-                       Pair de = (Pair) properties [pi];
-
-                       return (MethodInfo) de.Second;
-               } else
-                       return pi.GetSetMethod ();
-       }
-
-       static public MethodInfo GetPropertySetter (PropertyInfo pi)
-       {
-               if (pi is PropertyBuilder){
-                       Pair de = (Pair) properties [pi];
-
-                       return (MethodInfo) de.First;
-               } else
-                       return pi.GetGetMethod ();
-       }
-
        /// <summary>
        ///   Given an array of interface types, expand and eliminate repeated ocurrences
        ///   of an interface.  
@@ -1906,7 +1950,11 @@ public class TypeManager {
                //
 
                if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
-                       return false;
+                               return false;
+
+               if ((closure_start_type == closure_invocation_type) &&
+                   (m.DeclaringType == closure_invocation_type))
+                       return true;
 
                //
                // Ugly: we need to find out the type of `m', and depending
@@ -1917,7 +1965,7 @@ public class TypeManager {
                        MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
 
                        if (ma == MethodAttributes.Private)
-                               return closure_private_ok;
+                               return closure_private_ok || (closure_invocation_type == m.DeclaringType);
 
                        //
                        // FamAndAssem requires that we not only derivate, but we are on the
@@ -1940,12 +1988,15 @@ public class TypeManager {
 
                        // Family and FamANDAssem require that we derive.
                        if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
+                               if (closure_invocation_type == null)
+                                       return false;
+
                                if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
                                        return false;
 
                                // Although a derived class can access protected members of its base class
                                // it cannot do so through an instance of the base class (CS1540).
-                               if ((closure_invocation_type != closure_start_type) &&
+                               if (!mb.IsStatic && (closure_invocation_type != closure_start_type) &&
                                    closure_invocation_type.IsSubclassOf (closure_start_type))
                                        return false;
 
@@ -1961,7 +2012,7 @@ public class TypeManager {
                        FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
 
                        if (fa == FieldAttributes.Private)
-                               return closure_private_ok;
+                               return closure_private_ok || (closure_invocation_type == m.DeclaringType);
 
                        //
                        // FamAndAssem requires that we not only derivate, but we are on the
@@ -1984,12 +2035,15 @@ public class TypeManager {
 
                        // Family and FamANDAssem require that we derive.
                        if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
+                               if (closure_invocation_type == null)
+                                       return false;
+
                                if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
                                        return false;
 
                                // Although a derived class can access protected members of its base class
                                // it cannot do so through an instance of the base class (CS1540).
-                               if ((closure_invocation_type != closure_start_type) &&
+                               if (!fi.IsStatic && (closure_invocation_type != closure_start_type) &&
                                    closure_invocation_type.IsSubclassOf (closure_start_type))
                                        return false;
 
@@ -2001,7 +2055,8 @@ public class TypeManager {
                }
 
                //
-               // EventInfos and PropertyInfos, return true
+               // EventInfos and PropertyInfos, return true because they lack permission
+               // informaiton, so we need to check later on the methods.
                //
                return true;
        }
@@ -2040,6 +2095,7 @@ public class TypeManager {
                bool searching = (original_bf & BindingFlags.DeclaredOnly) == 0;
                bool private_ok;
                bool always_ok_flag = false;
+               bool skip_iface_check = true, used_cache = false;
 
                closure_name = name;
                closure_invocation_type = invocation_type;
@@ -2082,7 +2138,7 @@ public class TypeManager {
                                        private_ok = true;
                                } else
                                        private_ok = always_ok_flag;
-                               
+
                                if (private_ok || invocation_type.IsSubclassOf (current_type))
                                        bf = original_bf | BindingFlags.NonPublic;
                        } else {
@@ -2095,17 +2151,24 @@ public class TypeManager {
 
                        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);
-                       
+                       list = MemberLookup_FindMembers (current_type, mt, bf, name, out used_cache);
+
                        Timer.StartTimer (TimerType.MemberLookup);
 
+                       //
+                       // When queried for an interface type, the cache will automatically check all
+                       // inherited members, so we don't need to do this here.  However, this only
+                       // works if we already used the cache in the first iteration of this loop.
+                       //
+                       // If we used the cache in any further iteration, we can still terminate the
+                       // loop since the cache always looks in all parent classes.
+                       //
+
+                       if (used_cache)
+                               searching = false;
+                       else
+                               skip_iface_check = false;
+
                        if (current_type == TypeManager.object_type)
                                searching = false;
                        else {
@@ -2149,7 +2212,14 @@ public class TypeManager {
 
                if (method_list != null && method_list.Count > 0)
                        return (MemberInfo []) method_list.ToArray (typeof (MemberInfo));
-       
+
+               //
+               // This happens if we already used the cache in the first iteration, in this case
+               // the cache already looked in all interfaces.
+               //
+               if (skip_iface_check)
+                       return null;
+
                //
                // Interfaces do not list members they inherit, so we have to
                // scan those.
@@ -2178,235 +2248,133 @@ 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);
+/// <summary>
+///   There is exactly one instance of this class per type.
+/// </summary>
+public sealed class TypeHandle : IMemberContainer {
+       public readonly TypeHandle BaseType;
 
-               Timer.StopTimer (TimerType.CacheInit);
-       }
+       readonly int id = ++next_id;
+       static int next_id = 0;
 
-       void AddMembers (bool declared)
+       /// <summary>
+       ///   Lookup a TypeHandle instance for the given type.  If the type doesn't have
+       ///   a TypeHandle yet, a new instance of it is created.  This static method
+       ///   ensures that we'll only have one TypeHandle instance per type.
+       /// </summary>
+       public static TypeHandle GetTypeHandle (Type t)
        {
-               AddMembers (MemberTypes.Constructor, declared);
-               AddMembers (MemberTypes.Event, declared);
-               AddMembers (MemberTypes.Field, declared);
-               AddMembers (MemberTypes.Method, declared);
-               AddMembers (MemberTypes.Property, declared);
-               AddMembers (MemberTypes.NestedType, declared);
-       }
+               TypeHandle handle = (TypeHandle) type_hash [t];
+               if (handle != null)
+                       return handle;
 
-       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);
+               handle = new TypeHandle (t);
+               type_hash.Add (t, handle);
+               return handle;
        }
 
-       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;
+       /// <summary>
+       ///   Returns the TypeHandle for TypeManager.object_type.
+       /// </summary>
+       public static IMemberContainer ObjectType {
+               get {
+                       if (object_type != null)
+                               return object_type;
 
-                       ArrayList list = (ArrayList) MemberHash [name];
-                       if (list == null) {
-                               list = new ArrayList ();
-                               MemberHash.Add (name, list);
-                       }
+                       object_type = GetTypeHandle (TypeManager.object_type);
 
-                       list.Add (new CacheEntry (member, mt, new_bf));
+                       return object_type;
                }
        }
 
-       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;
+       /// <summary>
+       ///   Returns the TypeHandle for TypeManager.array_type.
+       /// </summary>
+       public static IMemberContainer ArrayType {
+               get {
+                       if (array_type != null)
+                               return array_type;
 
-               default:
-                       return false;
+                       array_type = GetTypeHandle (TypeManager.array_type);
+
+                       return array_type;
                }
        }
 
-       [Flags]
-       protected enum EntryType {
-               None            = 0x000,
-
-               Instance        = 0x001,
-               Static          = 0x002,
-               MaskStatic      = Instance|Static,
+       private static PtrHashtable type_hash = new PtrHashtable ();
 
-               Public          = 0x004,
-               NonPublic       = 0x008,
-               MaskProtection  = Public|NonPublic,
+       private static TypeHandle object_type = null;
+       private static TypeHandle array_type = null;
 
-               Declared        = 0x010,
+       private Type type;
+       private bool is_interface;
+       private MemberCache member_cache;
 
-               Constructor     = 0x020,
-               Event           = 0x040,
-               Field           = 0x080,
-               Method          = 0x100,
-               Property        = 0x200,
-               NestedType      = 0x400,
-
-               MaskType        = Constructor|Event|Field|Method|Property|NestedType
+       private TypeHandle (Type type)
+       {
+               this.type = type;
+               if (type.BaseType != null)
+                       BaseType = GetTypeHandle (type.BaseType);
+               else if ((type != TypeManager.object_type) && (type != typeof (object)))
+                       is_interface = true;
+               this.member_cache = new MemberCache (this);
        }
 
-       protected struct CacheEntry {
-               public EntryType EntryType;
-               public MemberInfo Member;
+       // IMemberContainer methods
 
-               public CacheEntry (MemberInfo member, MemberTypes mt, BindingFlags bf)
-               {
-                       this.Member = member;
-                       this.EntryType = GetEntryType (mt, bf);
+       public string Name {
+               get {
+                       return type.FullName;
                }
        }
 
-       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 Type Type {
+               get {
+                       return type;
                }
        }
 
-       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 IMemberContainer Parent {
+               get {
+                       return BaseType;
+               }
        }
-}
 
-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 bool IsInterface {
+               get {
+                       return is_interface;
+               }
        }
 
-       public MemberList GetMembers (MemberTypes mt, BindingFlags bf, bool declared)
+       public MemberList GetMembers (MemberTypes mt, BindingFlags bf)
        {
-               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));
+               if (mt == MemberTypes.Event)
+                       return new MemberList (type.GetEvents (bf | BindingFlags.DeclaredOnly));
+               else
+                       return new MemberList (type.FindMembers (mt, bf | BindingFlags.DeclaredOnly,
+                                                                null, null));
        }
 
-       public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
-                                      MemberFilter filter, object criteria)
-       {
-               throw new NotSupportedException ();
-       }
+       // IMemberFinder methods
 
        public MemberList FindMembers (MemberTypes mt, BindingFlags bf, string name,
                                       MemberFilter filter, object criteria)
        {
-               MemberList list;
+               return member_cache.FindMembers (mt, bf, name, filter, criteria);
+       }
 
-               Timer.StartTimer (TimerType.CachedLookup);
-               list = MemberCache.FindMembers (mt, bf, name, filter, criteria);
-               Timer.StopTimer (TimerType.CachedLookup);
+       public MemberCache MemberCache {
+               get {
+                       return member_cache;
+               }
+       }
 
-               return list;
+       public override string ToString ()
+       {
+               if (BaseType != null)
+                       return "TypeHandle (" + id + "," + Name + " : " + BaseType + ")";
+               else
+                       return "TypeHandle (" + id + "," + Name + ")";
        }
 }