public bool MethodIsReachable(IMethodDefinition method) { Contract.Requires(!method.IsAbstract); Contract.Assert(GarbageCollectHelper.MethodDefinitionIsUnspecialized(method)); return(methods.Contains(method)); }
public bool VirtualMethodIsInDemand(IMethodDefinition methodDefinition) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(methodDefinition)); Contract.Requires(methodDefinition.IsVirtual); return(runtimeTargetsByDispatch.ContainsKey(methodDefinition)); }
private bool VirtualMethodIsInDemand(IMethodDefinition virtualMethod) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(virtualMethod)); Contract.Requires(virtualMethod.IsVirtual); return(virtualCallsInDemand.VirtualMethodIsInDemand(virtualMethod)); }
public bool NoteVirtualMethodMayDispatchToMethod(IMethodDefinition compileTimeMethod, IMethodDefinition runtimeTarget) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(compileTimeMethod)); Contract.Requires(compileTimeMethod.IsVirtual); NoteDispatchIsInDemand(compileTimeMethod); return(runtimeTargetsByDispatch[compileTimeMethod].Add(runtimeTarget)); }
private void MarkMethodAsReachable(IMethodDefinition method) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(method)); Contract.Requires(!method.IsAbstract); Contract.Ensures(methods.Contains(method)); methods.Add(method); }
/// <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); }
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 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 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 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); } } } }
/// <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); }
private void MarkVirtualMethodAsInDemand(IMethodDefinition virtualMethod) { Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(virtualMethod)); Contract.Requires(virtualMethod.IsVirtual); virtualCallsInDemand.NoteDispatchIsInDemand(virtualMethod); }