public bool VirtualMethodIsInDemand(IMethodDefinition methodDefinition) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(methodDefinition)); Contract.Requires(methodDefinition.IsVirtual); return(runtimeTargetsByDispatch.ContainsKey(methodDefinition)); }
// Called when the first new T() is detected. // This method is where we add worst-case-scenario // constructed types for those stategies. // t-devinc: Now that we don't do construct reachable types // this maybe doesn't make sense. private void NoteFirstTypeVariableConstructed() { IEnumerable <ITypeDefinition> potentialUniverse; switch (createInstanceStrategy) { case TypeVariableCreateInstanceStrategy.ConstructAll: potentialUniverse = wholeProgram.AllDefinedTypes(); break; default: // do nothing potentialUniverse = new HashSet <ITypeDefinition>(); break; } foreach (ITypeDefinition t in potentialUniverse) { if (GarbageCollectHelper.TypeIsConstructable(t)) { ConstructionFound(t); // t-devinc: We should associate a reason with this! } } }
private void NoteGenericParameterFlow(ITypeDefinition actual, IGenericParameter formal) { if (createInstanceStrategy == TypeVariableCreateInstanceStrategy.ConstructAllConcreteParameters) { if (!(actual is IGenericParameter)) { // actual is concrete ITypeDefinition unspecializedConcreteType = GarbageCollectHelper.UnspecializeAndResolveTypeReference(actual); unspecializedTypesPassedAsTypeVariables.Add(unspecializedConcreteType); if (GarbageCollectHelper.TypeIsConstructable(unspecializedConcreteType)) { // t-devinc: We should associate a reason with this construction found ConstructionFound(unspecializedConcreteType); IMethodDefinition defaultConstructor = TypeHelper.GetMethod(unspecializedConcreteType, wholeProgram.Host().NameTable.GetNameFor(".ctor")); if (!(defaultConstructor is Dummy)) { // t-devinc: Add reason for this NotePotentialNonVirtualMethodReachedForReason(defaultConstructor, null); } } } } }
public bool MethodIsReachable(IMethodDefinition method) { Contract.Requires(!method.IsAbstract); Contract.Assert(GarbageCollectHelper.MethodDefinitionIsUnspecialized(method)); return(methods.Contains(method)); }
private void TypeUseFound(ITypeDefinition t) { Contract.Requires(t != null); Contract.Requires(!(t is Dummy)); Contract.Requires(GarbageCollectHelper.UnspecializeAndResolveTypeReference(t) == t); Contract.Ensures(this.types.Contains(t)); if (this.types.Contains(t)) { return; } // add all base classes of this class foreach (var baseclass in GarbageCollectHelper.BaseClasses(t)) { this.TypeUseFound(GarbageCollectHelper.UnspecializeAndResolveTypeReference(baseclass)); } this.types.Add(t); // add static constructor to worklist var cctor = GarbageCollectHelper.GetStaticConstructor(this.wholeProgram.Host().NameTable, t); if (!(cctor is Dummy)) { this.AddToWorklist(GarbageCollectHelper.UnspecializeAndResolveMethodReference(cctor)); } }
/// <summary> /// A version of Implements that works over instantiated types and methods. /// /// t-devinc: Not entirely convinced this is correct. /// </summary> /// <param name="derived"></param> /// <param name="upto"></param> /// <param name="m"></param> /// <returns></returns> internal static IMethodDefinition ImplementsInstantiated(ITypeDefinition derived, IMethodDefinition m) { Contract.Requires(derived != null); Contract.Requires(!(derived is Dummy)); Contract.Requires(m != null); Contract.Requires(!(m is Dummy)); Contract.Requires(TypeHelper.Type1DerivesFromOrIsTheSameAsType2(derived, m.ContainingTypeDefinition)); Contract.Requires(!derived.IsInterface); Contract.Ensures(Contract.Result <IMethodDefinition>() != null); Contract.Ensures(!(Contract.Result <IMethodDefinition>() is Dummy)); var classHierarchyChain = new ITypeDefinition[] { derived }.Concat(GarbageCollectHelper.AllSuperClasses(derived)); foreach (var classInHierarchy in classHierarchyChain) { IMethodDefinition specializedImplementation = ImplementationForMethodInClass(m, classInHierarchy); if (specializedImplementation != null) { return(specializedImplementation); } } // We shouldn't get here return(null); }
private bool VirtualMethodIsInDemand(IMethodDefinition virtualMethod) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(virtualMethod)); Contract.Requires(virtualMethod.IsVirtual); return(virtualCallsInDemand.VirtualMethodIsInDemand(virtualMethod)); }
private void MarkMethodAsReachable(IMethodDefinition method) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(method)); Contract.Requires(!method.IsAbstract); Contract.Ensures(methods.Contains(method)); methods.Add(method); }
public bool NoteVirtualMethodMayDispatchToMethod(IMethodDefinition compileTimeMethod, IMethodDefinition runtimeTarget) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(compileTimeMethod)); Contract.Requires(compileTimeMethod.IsVirtual); NoteDispatchIsInDemand(compileTimeMethod); return(runtimeTargetsByDispatch[compileTimeMethod].Add(runtimeTarget)); }
/// <summary> /// Find possible implementations of m for derived, upto (and including) 'upto'). /// /// If m is an unspecialized generic interface, they may be multiple possible implementations; at this /// point we can't tell which one would be called since we've removed all specialization from m. /// /// We require 'derived' to be unspecialized, but note that its super types may be specialized. /// We require 'm' to be unspecialized. /// /// </summary> internal static ICollection <IMethodDefinition> Implements(ITypeDefinition derived, ITypeDefinition upto, IMethodDefinition m) { Contract.Requires(derived != null); Contract.Requires(!(derived is Dummy)); Contract.Requires(upto != null); Contract.Requires(!(upto is Dummy)); Contract.Requires(m != null); Contract.Requires(!(m is Dummy)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(derived)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(m)); Contract.Requires(!derived.IsInterface); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => GarbageCollectHelper.MethodDefinitionIsUnspecialized(resultM))); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => resultM != null && !(resultM is Dummy)) ); ISet <IMethodDefinition> foundImplementations = new HashSet <IMethodDefinition>(); // If derived implements an interface multiple times, there may be multiple specialized versions for derived IEnumerable <IMethodDefinition> versionsOfMSpecializedForDerived = SearchSpecializedHierarchyForVersionOfMethod(derived, m); var classHierarchyChain = new ITypeDefinition[] { derived }.Concat(GarbageCollectHelper.AllSuperClasses(derived)); foreach (IMethodDefinition mSpecializedForDerived in versionsOfMSpecializedForDerived) { // Check explicit implementation overrides before implicit methods IMethodDefinition foundImplementation = null; foreach (var classInHierarchy in classHierarchyChain) { IMethodDefinition specializedImplementation = ImplementationForMethodInClass(mSpecializedForDerived, classInHierarchy); if (specializedImplementation != null) { foundImplementation = specializedImplementation; break; } if (TypeHelper.TypesAreEquivalent(GarbageCollectHelper.UnspecializeAndResolveTypeReference(classInHierarchy), upto)) { break; } } // Do we really expect to find an implementation for EACH mSpecializedForDerived; or do we expect to find at least one overall all? Contract.Assert(foundImplementation != null); foundImplementations.Add(GarbageCollectHelper.UnspecializeAndResolveMethodReference(foundImplementation)); } return(foundImplementations); }
public void ProcessSummary(ReachabilitySummary summary, IMethodDefinition summarizedMethod) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(summarizedMethod)); foreach (IMethodDefinition nonvirtuallyCalledMethod in summary.NonvirtuallyCalledMethods) { NoteGenericParameterFlowForMethod(nonvirtuallyCalledMethod); IMethodDefinition unspecializedMethod = GarbageCollectHelper.UnspecializeAndResolveMethodReference(nonvirtuallyCalledMethod); analysisReasons.NoteNonVirtualDispatchReachableForReason(nonvirtuallyCalledMethod, analysisReasons.DispatchReachedBecauseContainingMethodWasReached(summarizedMethod)); if (nonvirtualDispatches.Add(unspecializedMethod)) { MethodReachedReason reason = analysisReasons.MethodReachedByDispatchAgainstNonVirtualMethod(unspecializedMethod); NotePotentialNonVirtualMethodReachedForReason(unspecializedMethod, reason); } } foreach (IMethodDefinition virtuallyCalledMethod in summary.VirtuallyCalledMethods) { NoteGenericParameterFlowForMethod(virtuallyCalledMethod); IMethodDefinition unspecializedMethod = GarbageCollectHelper.UnspecializeAndResolveMethodReference(virtuallyCalledMethod); analysisReasons.NoteVirtualDispatchReachableForReason(unspecializedMethod, analysisReasons.DispatchReachedBecauseContainingMethodWasReached(summarizedMethod)); NoteVirtualDispatch(unspecializedMethod); } foreach (ITypeDefinition reachableType in summary.ReachableTypes) { TypeUseFound(GarbageCollectHelper.UnspecializeAndResolveTypeReference(reachableType)); } foreach (ITypeDefinition constructedType in summary.ConstructedTypes) { ITypeDefinition unspecializedConstructedType = GarbageCollectHelper.UnspecializeAndResolveTypeReference(constructedType); ConstructionFoundWithReason(unspecializedConstructedType, analysisReasons.TypeConstructedBecauseAllocatingMethodReached(summarizedMethod)); } foreach (IFieldDefinition reachableField in summary.ReachableFields) { fields.Add(GarbageCollectHelper.UnspecializeAndResolveFieldReference(reachableField)); } foreach (IGenericParameter genericParameter in summary.ConstructedTypeParameters) { NoteTypeVariableConstructed(genericParameter); } unresolvedReferences.UnionWith(summary.UnresolvedReferences); }
private static bool AssemblyShouldBeRewritten(IAssembly assembly) { // Fragile if (GarbageCollectHelper.AssemblyMayBeSystemOrFramework(assembly)) { return(false); } return(true); }
// For debugging purposes only internal static bool MethodDefinitionHasName(IMethodDefinition methodDefinition, string className, string methodName) { IMethodDefinition unspecializedMethodDefinition = GarbageCollectHelper.UnspecializeAndResolveMethodReference(methodDefinition); if (unspecializedMethodDefinition.Name.Value.Equals(methodName)) { INamedTypeDefinition containingType = unspecializedMethodDefinition.ContainingTypeDefinition as INamedTypeDefinition; if (containingType != null && containingType.Name.Value.Equals(className)) { return(true); } } return(false); }
public void NoteDispatchIsInDemand(IMethodDefinition compileTimeMethod) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(compileTimeMethod)); Contract.Requires(compileTimeMethod.IsVirtual); Contract.Ensures(VirtualMethodIsInDemand(compileTimeMethod)); Contract.Ensures(runtimeTargetsByDispatch[compileTimeMethod] != null); HashSet <IMethodDefinition> calls = null; if (!runtimeTargetsByDispatch.TryGetValue(compileTimeMethod, out calls)) { calls = new HashSet <IMethodDefinition>(new MethodDefinitionEqualityComparer()); runtimeTargetsByDispatch[compileTimeMethod] = calls; } }
private void NoteDispatch(IMethodDefinition compileTimeMethod, IMethodDefinition runtimeMethod, ITypeDefinition runtimeType) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(compileTimeMethod)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(runtimeMethod)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(runtimeType)); // Note: runtimeType may not be type containing runtimeMethod, but it will be a subtype of it. // Might want a contract for this. if (virtualCallsInDemand.NoteVirtualMethodMayDispatchToMethod(compileTimeMethod, runtimeMethod)) { AddToWorklist(runtimeMethod); analysisReasons.NoteMethodReachableForReason(runtimeMethod, analysisReasons.MethodReachedByDispatchAgainstVirtualMethodWithTypeConstructed(compileTimeMethod, runtimeType)); } }
private void NotePotentialNonVirtualMethodReachedForReason(IMethodDefinition targetMethodDefinition, MethodReachedReason reason) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(targetMethodDefinition)); this.TypeUseFound(GarbageCollectHelper.UnspecializeAndResolveTypeReference(targetMethodDefinition.ContainingTypeDefinition)); this.AddToWorklist(GarbageCollectHelper.UnspecializeAndResolveMethodReference(targetMethodDefinition)); // Really should a precondition requiring reason to not be null, // but for now there are some situations where we still don't // create reasons, so they pass null as a cop out. if (reason != null) { analysisReasons.NoteMethodReachableForReason(targetMethodDefinition, reason); } }
private void ConstructionFound(ITypeDefinition t) { Contract.Requires(t != null); Contract.Requires(!(t is Dummy)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(t)); Contract.Requires(GarbageCollectHelper.TypeIsConstructable(t)); Contract.Ensures(this.constructed.Contains(t)); //Console.WriteLine("Found construction of {0}", t); if (this.constructed.Contains(t)) { return; } this.constructed.Add(t); // t-devinc: should change AllSuperTypes, etc. to include t foreach (var baseclass in new ITypeDefinition[] { t }.Concat(GarbageCollectHelper.AllSuperTypes(t))) { ITypeDefinition unspecializedBaseClass = GarbageCollectHelper.UnspecializeAndResolveTypeReference(baseclass); foreach (var m in unspecializedBaseClass.Methods) { if (m.IsVirtual && VirtualMethodIsInDemand(m)) { ICollection <IMethodDefinition> implementationsOfMForT = GarbageCollectHelper.Implements(t, unspecializedBaseClass, m); Contract.Assert(implementationsOfMForT.Count() > 0); foreach (IMethodDefinition mprime in implementationsOfMForT) { NoteDispatch(m, GarbageCollectHelper.UnspecializeAndResolveMethodReference(mprime), t); } } } } // If a type is constructed then its Finalize method may be called ICollection <IMethodDefinition> implementationsOfFinalizeForT = GarbageCollectHelper.Implements(t, systemObjectType, systemObjectFinalizeMethod); Contract.Assert(implementationsOfFinalizeForT.Count() == 1); // t-devinc: Need to to add reason for this this.AddToWorklist(GarbageCollectHelper.UnspecializeAndResolveMethodReference(implementationsOfFinalizeForT.First())); }
private void NoteVirtualDispatch(IMethodDefinition methodDispatchedUpon) { Contract.Requires(methodDispatchedUpon != null); Contract.Requires(!(methodDispatchedUpon is Dummy)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(methodDispatchedUpon)); Contract.Requires(methodDispatchedUpon.IsVirtual); Contract.Ensures(VirtualMethodIsInDemand(methodDispatchedUpon)); //Console.WriteLine("VirtCallFound on {0} of type {1}", methodDefinition, methodDefinition.GetType()); bool virtualMethodIsAlreadyKnown = VirtualMethodIsInDemand(methodDispatchedUpon); MarkVirtualMethodAsInDemand(methodDispatchedUpon); if (virtualMethodIsAlreadyKnown) { return; } // The code below this point is called only the first time we learn that // someone has dispatched against this method. //Console.WriteLine("{0} has {1} derived methods", methodDefinition, this.callgraph.GetAllDerivedMethods(methodDefinition).ToArray().Length); ITypeDefinition typeDefiningM = methodDispatchedUpon.ContainingTypeDefinition; this.TypeUseFound(typeDefiningM); // t-devinc: clean this up foreach (ITypeDefinition subType in new ITypeDefinition[] { typeDefiningM }.Concat(wholeProgram.ClassHierarchy().AllSubClassesOfClass(typeDefiningM))) { if (GarbageCollectHelper.TypeIsConstructable(subType) && ((subType.IsStruct || constructed.Contains(subType)))) { ICollection <IMethodDefinition> implementationsOfMethodDefinitionForSubType = GarbageCollectHelper.Implements(subType, typeDefiningM, methodDispatchedUpon); Contract.Assert(implementationsOfMethodDefinitionForSubType.Count() > 0); foreach (IMethodDefinition implementationOfM in implementationsOfMethodDefinitionForSubType) { NoteDispatch(methodDispatchedUpon, GarbageCollectHelper.UnspecializeAndResolveMethodReference(implementationOfM), subType); } } } }
public RapidTypeAnalysis(WholeProgram wholeProgram, TargetProfile profile) { Contract.Ensures(!this.FinishedAnalysis); this.types = new HashSet <ITypeDefinition>(new TypeDefinitionEqualityComparer()); this.methods = new HashSet <IMethodDefinition>(new MethodDefinitionEqualityComparer()); this.virtualCallsInDemand = new VirtualDispatchDemand(); this.nonvirtualDispatches = new HashSet <IMethodDefinition>(new MethodDefinitionEqualityComparer()); this.fields = new HashSet <IFieldDefinition>(new FieldDefinitionEqualityComparer()); this.constructed = new HashSet <ITypeDefinition>(new TypeDefinitionEqualityComparer()); this.constructedGenericParameters = new HashSet <IGenericParameter>(new TypeDefinitionEqualityComparer()); // Note: we use the interned key as the hashcode, so this set should be deterministic this.worklist = new HashSet <IMethodDefinition>(new MethodDefinitionEqualityComparer()); this.wholeProgram = wholeProgram; this.reflectionSummarizers = new HashSet <IMethodSummarizer>(); this.simpleBytecodeSummarizer = new SimpleBytecodeMethodSummarizer(); this.reachabilityFlowBytecodeSummarizer = new ReachabilityBasedLocalFlowMethodSummarizer(); //systemObjectType = wholeProgram.Host().PlatformType.SystemObject.ResolvedType; // Weak heuristic -- should provide custom host? IAssembly coreAssembly = wholeProgram.HeuristicFindCoreAssemblyForProfile(profile); Contract.Assert(coreAssembly != null); systemObjectType = GarbageCollectHelper.CreateTypeReference(wholeProgram.Host(), coreAssembly, "System.Object").ResolvedType; Contract.Assert(!(systemObjectType is Dummy)); systemObjectFinalizeMethod = TypeHelper.GetMethod(systemObjectType, wholeProgram.Host().NameTable.GetNameFor("Finalize")); Contract.Assert(!(systemObjectFinalizeMethod is Dummy)); methodsRequiringReflectionSummary = new HashSet <IMethodDefinition>(new MethodDefinitionEqualityComparer()); unresolvedReferences = new HashSet <IReference>(new ReferenceEqualityComparer()); unspecializedTypesPassedAsTypeVariables = new HashSet <ITypeDefinition>(new TypeDefinitionEqualityComparer()); }
// Filter all methods in methodref by those that ILGC says are reachable. public IEnumerable <IMethodReference> GetMethodCallees(IMethodReference methodref) { Contract.Requires(methodref != null); Contract.Requires(!(methodref is Dummy)); Contract.Requires(this.FinishedAnalysis); // use a set to remove potential duplicates. ISet <IMethodDefinition> calls = new HashSet <IMethodDefinition>(new MethodDefinitionEqualityComparer()); // get unspecialized definition of this method reference IMethodDefinition methoddef = GarbageCollectHelper.UnspecializeAndResolveMethodReference(methodref); IMethodSummarizer bestSummarizer = new CompleteBytecodeMethodSummarizer(); ReachabilitySummary summary = bestSummarizer.SummarizeMethod(methoddef, wholeProgram); if (summary != null) { foreach (var method in summary.NonvirtuallyCalledMethods) { if (this.ReachableMethods().Contains(GarbageCollectHelper.UnspecializeAndResolveMethodReference(method as IMethodReference))) // && this.ReachableTypes().Contains(method.ContainingTypeDefinition)) { calls.Add(method); } } foreach (var method in summary.VirtuallyCalledMethods) { if (this.ReachableMethods().Contains(GarbageCollectHelper.UnspecializeAndResolveMethodReference(method as IMethodReference)))// && this.ReachableTypes().Contains(method.ContainingTypeDefinition)) { calls.Add(method); } } } return(calls); }
public void Run(IEnumerable <IMethodReference> roots) { // add the rootset foreach (var rootReference in roots) { IMethodDefinition rootDefinition = GarbageCollectHelper.UnspecializeAndResolveMethodReference(rootReference); NotePotentialNonVirtualMethodReachedForReason(rootDefinition, analysisReasons.MethodReachedBecauseEntryPoint()); // If a constructor for a type is an entry point, we consider that type to be constructed. if (rootDefinition.IsConstructor) { ITypeDefinition constructedType = rootDefinition.ContainingTypeDefinition; ConstructionFoundWithReason(constructedType, analysisReasons.TypeConstructedBecauseConstructorIsEntryPoint()); } } // walk over worklist do { IMethodDefinition m = this.worklist.First(); this.worklist.Remove(m); //Console.WriteLine("Pulled method {0} off of worklist", m); if (!m.IsExternal) { IMethodSummarizer bestSummarizer = GetBytecodeSummarizerForMethod(m); ReachabilitySummary bytecodeSummary = bestSummarizer.SummarizeMethod(m, wholeProgram); if (bytecodeSummary != null) { ProcessSummary(bytecodeSummary, m); ISet <ReachabilitySummary> reflectionSummaries = RunReflectionSummarizers(m, wholeProgram); foreach (ReachabilitySummary summary in reflectionSummaries) { ProcessSummary(summary, m); } bool gotReflectionSummary = reflectionSummaries.Count() > 0; if (!gotReflectionSummary && IsReflectionSummaryProbablyNeeded(bytecodeSummary, m)) { //Console.WriteLine("{0} calls reflection but doesn't have a summary. (UNSOUND?).", m); methodsRequiringReflectionSummary.Add(m); } } } else { if (!m.IsAbstract) { // Boy, there are a lot of these // Console.WriteLine("Note: cannot process external method {0}. (UNSOUND)", m); } } } while (this.worklist.Count > 0); Console.WriteLine("Used flow-based summarizer for {0}/{1} methods", countUsedFlowBasedSummarizer, ReachableMethods().Count()); }
private void MarkVirtualMethodAsInDemand(IMethodDefinition virtualMethod) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(virtualMethod)); Contract.Requires(virtualMethod.IsVirtual); virtualCallsInDemand.NoteDispatchIsInDemand(virtualMethod); }
/// <summary> /// Find possible implementations of m for derived, upto (and including) 'upto'). /// /// If m is an unspecialized generic interface, they may be multiple possible implementations; at this /// point we can't tell which one would be called since we've removed all specialization from m. /// /// We require 'derived' to be unspecialized, but note that its super types may be specialized. /// We require 'm' to be unspecialized. /// /// </summary> internal static ICollection <IMethodDefinition> Implements(ITypeDefinition derived, ITypeDefinition upto, IMethodDefinition m) { Contract.Requires(derived != null); Contract.Requires(!(derived is Dummy)); Contract.Requires(upto != null); Contract.Requires(!(upto is Dummy)); Contract.Requires(m != null); Contract.Requires(!(m is Dummy)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(derived)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(m)); Contract.Requires(!derived.IsInterface); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => GarbageCollectHelper.MethodDefinitionIsUnspecialized(resultM))); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => resultM != null && !(resultM is Dummy)) ); ISet <IMethodDefinition> foundImplementations = new HashSet <IMethodDefinition>(); // If derived implements an interface multiple times, there may be multiple specialized versions for derived IEnumerable <IMethodDefinition> versionsOfMSpecializedForDerived = SearchSpecializedHierarchyForVersionOfMethod(derived, m); var classHierarchyChain = new ITypeDefinition[] { derived }.Concat(GarbageCollectHelper.AllSuperClasses(derived)); foreach (IMethodDefinition mSpecializedForDerived in versionsOfMSpecializedForDerived) { IMethodDefinition foundImplementation = null; // If this is a method defined on an inteface, we must first search the hierarchy for explicit implementations, // since an explicit implementation on a base type supercedes an implicit implementation on a derived type if (m.ContainingTypeDefinition.IsInterface) { foreach (var classInHierarchy in classHierarchyChain) { foreach (IMethodImplementation methodImplementation in classInHierarchy.ExplicitImplementationOverrides) { if (methodImplementation.ImplementedMethod.InternedKey == mSpecializedForDerived.InternedKey) { foundImplementation = methodImplementation.ImplementingMethod.ResolvedMethod; break; } } if (foundImplementation != null) { break; } if (TypeHelper.TypesAreEquivalent(GarbageCollectHelper.UnspecializeAndResolveTypeReference(classInHierarchy), upto)) { break; } } } // If we found an explicit implementation, don't seach for an implicit one if (foundImplementation == null) { foreach (var classInHierarchy in classHierarchyChain) { foundImplementation = ImplementationForMethodInClass(mSpecializedForDerived, classInHierarchy); if (foundImplementation != null) { break; } if (TypeHelper.TypesAreEquivalent(GarbageCollectHelper.UnspecializeAndResolveTypeReference(classInHierarchy), upto)) { break; } } } // Do we really expect to find an implementation for EACH mSpecializedForDerived; or do we expect to find at least one overall all? Contract.Assert(foundImplementation != null); foundImplementations.Add(GarbageCollectHelper.UnspecializeAndResolveMethodReference(foundImplementation)); } return(foundImplementations); }