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 ISet <ReachabilitySummary> RunReflectionSummarizers(IMethodDefinition method, WholeProgram wholeProgram) { ISet <ReachabilitySummary> summaries = new HashSet <ReachabilitySummary>(); foreach (IMethodSummarizer reflectionSummarizer in reflectionSummarizers) { ReachabilitySummary summary = reflectionSummarizer.SummarizeMethod(method, wholeProgram); if (summary != null) { summaries.Add(summary); } } return(summaries); }
private bool IsReflectionSummaryProbablyNeeded(ReachabilitySummary bytecodeSummary, IMethodDefinition containingMethod) { // Note we only get the compile-time targets for virtually called methods here. // This is not right; but we're really just using it as a heuristic to help debugging. // If a non-system class calls a reflection class, heuristically we probably need a summary // t-devinc: ToString(): gross if (!containingMethod.ContainingType.ToString().Contains("System")) { foreach (IMethodDefinition calledMethod in bytecodeSummary.NonvirtuallyCalledMethods.Concat(bytecodeSummary.VirtuallyCalledMethods)) { if (calledMethod.ContainingType.ToString().Contains("System.Reflection") || calledMethod.ContainingType.ToString().Contains("System.Activator") || calledMethod.ContainingType.ToString().Contains("System.Xml.Serialization.XmlSerializer")) { //Console.WriteLine("{0} calls reflection method {1}", containingMethod, calledMethod); return(true); } } } return(false); }
// 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()); }