private static void OutputWholeProgramReports(RapidTypeAnalysis rta, string reportingDirectory) { using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ConstructedTypesFileName)) { foreach (var constructedType in rta.ConstructedTypes()) { outfile.WriteLine(constructedType); } } using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ConstructedGenericParametersFileName)) { foreach (var constructedParameter in rta.ConstructedGenericParameters()) { if (constructedParameter is IGenericTypeParameter) { outfile.WriteLine("{0} from type {1}", constructedParameter, ((IGenericTypeParameter)constructedParameter).DefiningType); } else { outfile.WriteLine("{0} from method {1}", constructedParameter, ((IGenericMethodParameter)constructedParameter).DefiningMethod); } } } ISet <IMethodDefinition> methodsRequiringReflectionSummary = rta.MethodsRequiringReflectionSummary(); if (methodsRequiringReflectionSummary.Count() > 0) { Console.WriteLine("Found {0} methods requiring a reflection summary. List written in report directory to {1}", methodsRequiringReflectionSummary.Count(), ReflectionSummaryRequiredFileName); using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ReflectionSummaryRequiredFileName)) { foreach (var constructedType in methodsRequiringReflectionSummary) { outfile.WriteLine(constructedType); } } } ISet <IReference> unresolvedReferences = rta.UnresolvedReferences(); if (unresolvedReferences.Count() > 0) { Console.WriteLine("Found {0} unresolved references. List written in report directory to {1}", unresolvedReferences.Count(), UnresolvedReferencesFileName); using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + UnresolvedReferencesFileName)) { foreach (var reference in unresolvedReferences) { outfile.WriteLine(reference); } } } }
private static void OutputPerAssemblyReports(RapidTypeAnalysis rta, string reportingDirectory) { foreach (IAssembly assembly in rta.WholeProgram().AllAssemblies()) { AssemblyReport report = AssemblyReport.CreateAssemblyReportFromRTA(assembly, rta); string assemblyName = assembly.Name.Value; int reachableMethodsCount = report.ReachableMethods.Count; report.WriteReportToDirectory(reportingDirectory); } }
private static void OutputRTAStatistics(RapidTypeAnalysis rta, string reportingDirectory) { Console.WriteLine("Writing mark report to {0}", reportingDirectory); System.IO.Directory.CreateDirectory(reportingDirectory); OutputPerAssemblyReports(rta, reportingDirectory); OutputWholeProgramReports(rta, reportingDirectory); OutputAnalysisReasons(rta, reportingDirectory); }
private static RapidTypeAnalysis RunRTA(WholeProgram wholeProgram, IEnumerable <ILGarbageCollect.Summaries.IMethodSummarizer> reflectionSummarizers, IEnumerable <IMethodReference> entryPoints, string reportPath, TargetProfile profile) { var rta = new RapidTypeAnalysis(wholeProgram, profile); rta.ReflectionSummarizers = reflectionSummarizers; Console.WriteLine("Running Rapid Type Analysis with {0} entry points", entryPoints.Count()); rta.Run(entryPoints); stopwatch.Stop(); OutputRTAStatistics(rta, reportPath); return(rta); }
/// <summary> /// Searches the analysis for a method by the name of f and returns a bool depending on whether f is reachable /// </summary> static bool IsMethodReachable(PeReader.DefaultHost host, RapidTypeAnalysis analysis, string className, string methodName) { var methodIName = host.NameTable.GetNameFor(methodName); var classIName = host.NameTable.GetNameFor(className); // t-devinc: perhaps should change this to use TestCompilerResult.FindMethod() // This would allow us to be more clear about specialized vs. not // in our tests. bool found = false; foreach (var reachableMethod in analysis.ReachableMethods()) { var containingTypeReference = reachableMethod.ContainingType; //Going to fail if we have a specialized method (which we will -- will have to make sure to get the unspecialized in the RTA). INamedTypeReference containingNamedTypeReference; if (containingTypeReference is IGenericTypeInstanceReference) { containingNamedTypeReference = ((IGenericTypeInstanceReference)containingTypeReference).GenericType; } else { containingNamedTypeReference = ((INamedTypeReference)containingTypeReference); } IName reachableClassIName = containingNamedTypeReference.Name; if (methodIName.UniqueKey == reachableMethod.Name.UniqueKey && classIName.UniqueKey == reachableClassIName.UniqueKey) { found = true; break; } } return found; }
/// <summary> /// Searches the analysis for a field by the name of f and returns a bool depending on whether f is reachable /// </summary> static bool IsFieldReachable(PeReader.DefaultHost host, RapidTypeAnalysis analysis, string f) { var fieldName = host.NameTable.GetNameFor(f); bool found = false; foreach (var field in analysis.ReachableFields()) { if (fieldName.UniqueKey == field.Name.UniqueKey) { found = true; break; } } return found; }
public void TestReachabilityWithConstructorEntryPoint() { // Tests for running the RTA with multiple entry points. string source = @" class A { public static void AEntry(SuperClass s) { s.M(); } } class SuperClass { public virtual void M() {} } class SubClass1 : SuperClass { public override void M() {} } class SubClass2 : SuperClass { public override void M() {} } "; ConstructWholeProgramForSources(new string[] { source }, (compilerResults, wholeProgram) => { RapidTypeAnalysis rta = new RapidTypeAnalysis(wholeProgram, TargetProfile.Desktop); IMethodDefinition[] entryPoints = new IMethodDefinition[] { compilerResults.FindMethodWithName("A", "AEntry"), compilerResults.FindMethodWithName("SubClass1", ".ctor") }; rta.Run(entryPoints); Assert.IsTrue(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "A", "AEntry")); Assert.IsTrue(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "SubClass1", "M")); Assert.IsTrue(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "SubClass1", ".ctor")); Assert.IsFalse(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "SubClass2", "M")); Assert.IsFalse(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "SubClass2", ".ctor")); Assert.IsFalse(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "SuperClass", "M")); }); }
public void TestReachabilityWithMultipleEntryPoints() { // Tests for running the RTA with multiple entry points. string source = @" class A { public static void AEntry() { F(); } public static void F() {} public static void Main(string[] args) {} } class B { public static void BEntry() { G(); } public static void G() {} } "; ConstructWholeProgramForSources(new string[] { source }, (compilerResults, wholeProgram) => { RapidTypeAnalysis rta = new RapidTypeAnalysis(wholeProgram, TargetProfile.Desktop); IMethodDefinition[] entryPoints = new IMethodDefinition[] { compilerResults.FindMethodWithName("A", "AEntry"), compilerResults.FindMethodWithName("B", "BEntry") }; rta.Run(entryPoints); Assert.IsTrue(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "A", "AEntry")); Assert.IsTrue(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "A", "F")); Assert.IsTrue(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "B", "BEntry")); Assert.IsTrue(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "B", "G")); Assert.IsFalse(RapidTypeAnalysisTests.IsMethodReachable(compilerResults.Host, rta, "A", "Main")); }); }
private static void OutputAnalysisReasons(RapidTypeAnalysis rta, string reportingDirectory) { // Clearly we could do better here with some factoring out, etc. AnalysisReasons reasons = rta.GetAnalysisReasons(); //Console.WriteLine("Calculating Best Reasons"); //reasons.CalculateBestReasons(); // Type reached reasons using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ConstructedTypesReasonsFileName)) { foreach (var constructedType in rta.ConstructedTypes()) { outfile.WriteLine(constructedType); HashSet<TypeConstructedReason> constructedReasons = reasons.GetReasonsTypeWasConstructed(constructedType); if (constructedReasons.Count() == 0) { outfile.WriteLine("\t<UNKNOWN>"); } else { foreach (TypeConstructedReason reason in constructedReasons) { outfile.WriteLine("\t" + reason); } } } } // Dispatch Reached Reasons (t-devinc: CLEAN THIS UP) using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ReachedNonVirtualDispatchReasonsFileName)) { foreach (var methodDispatchedAgainst in reasons.AllMethodsNonVirtuallyDispatchedAgainst()) { outfile.WriteLine(methodDispatchedAgainst); HashSet<DispatchReachedReason> dispatchReasons = reasons.GetReasonsNonVirtualDispatchWasReached(methodDispatchedAgainst); if (dispatchReasons.Count() == 0) { outfile.WriteLine("\t<UNKNOWN>"); } else { foreach (DispatchReachedReason reason in dispatchReasons) { outfile.WriteLine("\t" + reason); } } } } using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ReachedVirtualDispatchReasonsFileName)) { foreach (var methodDispatchedAgainst in reasons.AllMethodsVirtuallyDispatchedAgainst()) { outfile.WriteLine(methodDispatchedAgainst); HashSet<DispatchReachedReason> dispatchReasons = reasons.GetReasonsVirtualDispatchWasReached(methodDispatchedAgainst); if (dispatchReasons.Count() == 0) { outfile.WriteLine("\t<UNKNOWN>"); } else { foreach (DispatchReachedReason reason in dispatchReasons) { outfile.WriteLine("\t" + reason); } } } } // Method reached reasons using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + MethodReachedReasonsFileName)) { foreach (var reachedMethod in rta.ReachableMethods()) { outfile.WriteLine(reachedMethod); HashSet<MethodReachedReason> methodReachedReason = reasons.GetReasonsMethodWasReached(reachedMethod); if (methodReachedReason.Count() == 0) { outfile.WriteLine("\t<UNKNOWN>"); } else { foreach (MethodReachedReason reason in methodReachedReason) { outfile.WriteLine("\t" + reason); } } } } }
private static void OutputWholeProgramReports(RapidTypeAnalysis rta, string reportingDirectory) { using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ConstructedTypesFileName)) { foreach (var constructedType in rta.ConstructedTypes()) { outfile.WriteLine(constructedType); } } using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ConstructedGenericParametersFileName)) { foreach (var constructedParameter in rta.ConstructedGenericParameters()) { if (constructedParameter is IGenericTypeParameter) { outfile.WriteLine("{0} from type {1}", constructedParameter, ((IGenericTypeParameter)constructedParameter).DefiningType); } else { outfile.WriteLine("{0} from method {1}", constructedParameter, ((IGenericMethodParameter)constructedParameter).DefiningMethod); } } } ISet<IMethodDefinition> methodsRequiringReflectionSummary = rta.MethodsRequiringReflectionSummary(); if (methodsRequiringReflectionSummary.Count() > 0) { Console.WriteLine("Found {0} methods requiring a reflection summary. List written in report directory to {1}", methodsRequiringReflectionSummary.Count(), ReflectionSummaryRequiredFileName); using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ReflectionSummaryRequiredFileName)) { foreach (var constructedType in methodsRequiringReflectionSummary) { outfile.WriteLine(constructedType); } } } ISet<IReference> unresolvedReferences = rta.UnresolvedReferences(); if (unresolvedReferences.Count() > 0) { Console.WriteLine("Found {0} unresolved references. List written in report directory to {1}", unresolvedReferences.Count(), UnresolvedReferencesFileName); using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + UnresolvedReferencesFileName)) { foreach (var reference in unresolvedReferences) { outfile.WriteLine(reference); } } } }
private static RapidTypeAnalysis RunRTA(WholeProgram wholeProgram, IEnumerable<ILGarbageCollect.Summaries.IMethodSummarizer> reflectionSummarizers, IEnumerable<IMethodReference> entryPoints, string reportPath, TargetProfile profile) { var rta = new RapidTypeAnalysis(wholeProgram, profile); rta.ReflectionSummarizers = reflectionSummarizers; Console.WriteLine("Running Rapid Type Analysis with {0} entry points", entryPoints.Count()); rta.Run(entryPoints); stopwatch.Stop(); OutputRTAStatistics(rta, reportPath); return rta; }
private static void OutputAnalysisReasons(RapidTypeAnalysis rta, string reportingDirectory) { // Clearly we could do better here with some factoring out, etc. AnalysisReasons reasons = rta.GetAnalysisReasons(); //Console.WriteLine("Calculating Best Reasons"); //reasons.CalculateBestReasons(); // Type reached reasons using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ConstructedTypesReasonsFileName)) { foreach (var constructedType in rta.ConstructedTypes()) { outfile.WriteLine(constructedType); HashSet <TypeConstructedReason> constructedReasons = reasons.GetReasonsTypeWasConstructed(constructedType); if (constructedReasons.Count() == 0) { outfile.WriteLine("\t<UNKNOWN>"); } else { foreach (TypeConstructedReason reason in constructedReasons) { outfile.WriteLine("\t" + reason); } } } } // Dispatch Reached Reasons (t-devinc: CLEAN THIS UP) using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ReachedNonVirtualDispatchReasonsFileName)) { foreach (var methodDispatchedAgainst in reasons.AllMethodsNonVirtuallyDispatchedAgainst()) { outfile.WriteLine(methodDispatchedAgainst); HashSet <DispatchReachedReason> dispatchReasons = reasons.GetReasonsNonVirtualDispatchWasReached(methodDispatchedAgainst); if (dispatchReasons.Count() == 0) { outfile.WriteLine("\t<UNKNOWN>"); } else { foreach (DispatchReachedReason reason in dispatchReasons) { outfile.WriteLine("\t" + reason); } } } } using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + ReachedVirtualDispatchReasonsFileName)) { foreach (var methodDispatchedAgainst in reasons.AllMethodsVirtuallyDispatchedAgainst()) { outfile.WriteLine(methodDispatchedAgainst); HashSet <DispatchReachedReason> dispatchReasons = reasons.GetReasonsVirtualDispatchWasReached(methodDispatchedAgainst); if (dispatchReasons.Count() == 0) { outfile.WriteLine("\t<UNKNOWN>"); } else { foreach (DispatchReachedReason reason in dispatchReasons) { outfile.WriteLine("\t" + reason); } } } } // Method reached reasons using (StreamWriter outfile = new StreamWriter(reportingDirectory + @"\" + MethodReachedReasonsFileName)) { foreach (var reachedMethod in rta.ReachableMethods()) { outfile.WriteLine(reachedMethod); HashSet <MethodReachedReason> methodReachedReason = reasons.GetReasonsMethodWasReached(reachedMethod); if (methodReachedReason.Count() == 0) { outfile.WriteLine("\t<UNKNOWN>"); } else { foreach (MethodReachedReason reason in methodReachedReason) { outfile.WriteLine("\t" + reason); } } } } }
static void AssertRTATypesNotDummy(RapidTypeAnalysis rta) { foreach (var typeDefinition in rta.ReachableTypes()) { Assert.IsTrue(typeDefinition != Dummy.Type); } }
static void RunRTAOnSources(string[] sources, RTAResultDelegate runDelegate) { //The last source in the array must have the Main entrypoint CompileSourcesAndRun(sources, ".exe", compilerResult => { var mainAssembly = compilerResult.MainAssembly; WholeProgram wholeProgram = new WholeProgram(new IAssembly[] { compilerResult.MainAssembly }, compilerResult.Host); var rta = new RapidTypeAnalysis(wholeProgram, TargetProfile.Desktop); rta.Run(new IMethodDefinition[1] { mainAssembly.EntryPoint.ResolvedMethod }); runDelegate(compilerResult, rta); }); }
internal IEnumerable<IMethodDefinition> getReachableMethodsFromMethod(IMethodReference method, IEnumerable<IModule> modules) { IEnumerable<IAssembly> assemblies = getAssembliesFromModules(modules); Microsoft.Cci.MetadataReaderHost readerHost = host as Microsoft.Cci.MetadataReaderHost; if (readerHost == null) return new List<IMethodDefinition>(); //? ILGarbageCollect.Mark.WholeProgram program = new ILGarbageCollect.Mark.WholeProgram(assemblies, readerHost); RapidTypeAnalysis analyzer = new RapidTypeAnalysis(program, TargetProfile.Phone); analyzer.Run(new IMethodReference[] { method }); return analyzer.ReachableMethods(); }