public override ReachabilitySummary SummarizeMethod(IMethodDefinition methodDefinition, WholeProgram wholeProgram) { // Console.WriteLine("Running ReachabilityBasedLocalFlowMethodSummarizer on {0}", methodDefinition); ReachabilityStateAbstraction stateAbstraction = new ReachabilityStateAbstraction(); ReachabilityStateInterpreter stateInterpreter = new ReachabilityStateInterpreter(stateAbstraction); var algorithm = new WorkListAlgorithm <ReachabilityStateInterpreter, ReachabilityStateAbstraction, bool>(stateInterpreter); algorithm.RunOnMethod(methodDefinition, wholeProgram.Host()); SimpleBytecodeMethodSummarizer.BytecodeVisitor visitor = new SimpleBytecodeMethodSummarizer.BytecodeVisitor(); foreach (BasicBlock <Instruction> block in algorithm.ControlFlowGraph.AllBlocks) { bool blockIsReachable = algorithm.GetBlockPostState(block); if (blockIsReachable) { foreach (Instruction instruction in block.Instructions) { visitor.Visit(instruction.Operation); } } } return(visitor.GetSummary()); }
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()); }
private static StubMethodBodyEmitter GetStubMethodBodyEmitterForProfile(TargetProfile profile, WholeProgram wholeProgram) { StubMethodBodyEmitter emitter; switch (profile) { case TargetProfile.Desktop: emitter = new DotNetDesktopStubMethodBodyEmitter(wholeProgram.Host()); break; case TargetProfile.Phone: emitter = new WindowsPhoneStubMethodBodyEmitter(wholeProgram.Host()); break; default: emitter = new DotNetDesktopStubMethodBodyEmitter(wholeProgram.Host()); break; } return(emitter); }
private static void TransformProgram(WholeProgram wholeProgram, string transformedBinariesPath, string reportsPath, MethodRemoval methodRemoval, TargetProfile profile) { System.IO.Directory.CreateDirectory(transformedBinariesPath); StubMethodBodyEmitter stubEmitter = GetStubMethodBodyEmitterForProfile(profile, wholeProgram); foreach (IAssembly assembly in wholeProgram.AllAssemblies()) { if (AssemblyShouldBeRewritten(assembly)) { if (assembly.PublicKeyToken.Count() > 0) { Console.WriteLine("Warning: rewriting assembly with a public key token. {0}", assembly); } string outputBinary = transformedBinariesPath + @"\" + Path.GetFileName(assembly.Location); var copy = new MetadataDeepCopier(wholeProgram.Host()).Copy(assembly); DocumentationCommentDefinitionIdStringMap idMap = new DocumentationCommentDefinitionIdStringMap(new IAssembly[] { copy }); AssemblyReport assemblyReport = AssemblyReport.CreateAssemblyReportFromPath(copy, reportsPath, idMap); stopwatch.Start(); RewriteBinary(copy, assemblyReport, wholeProgram.Host(), outputBinary, methodRemoval, stubEmitter); stopwatch.Start(); } else { //Console.WriteLine("Skipping rewrite of of assembly {0}", assembly.Name.Value); } } }
private static void InterpretConstructAttributes(ReachabilitySummary summary, string fieldIdentifier, WholeProgram wholeProgram) { if (summary != null) { // For now we assume the argument is a field -- we really should support types and methods too IFieldDefinition fieldWithAttributes = LookupFieldWithIdentifier(fieldIdentifier, wholeProgram); foreach (ICustomAttribute customAttribute in fieldWithAttributes.Attributes) { IMethodDefinition constructorDefinition = GarbageCollectHelper.UnspecializeAndResolveMethodReference(customAttribute.Constructor); ITypeDefinition constructorType = constructorDefinition.ContainingTypeDefinition; // Mark attribute constructor reachable summary.NonvirtuallyCalledMethods.Add(constructorDefinition); // Mark named argument property setters reachable foreach (IMetadataNamedArgument namedArgument in customAttribute.NamedArguments) { IName setterName = wholeProgram.Host().NameTable.GetNameFor("set_" + namedArgument.ArgumentName.Value); IMethodDefinition setterMethod = TypeHelper.GetMethod(constructorType, setterName, namedArgument.ArgumentValue.Type); if (setterMethod != Dummy.Method) { // We treat this as a non-virtual call because we know the exact runtime-type of the attribute summary.NonvirtuallyCalledMethods.Add(setterMethod); } else { // Note this won't find a property defined in a super class of the attribute (unsound). // We'll want to fix this if try to generalize this code to handle arbitrary attributes throw new Exception("Couldn't find setter " + setterName + " for type " + namedArgument.ArgumentValue.Type + " in " + constructorType); } } } } else { throw new Exception("Cannot construct subtypes outside of a summarized method."); } }
public RapidTypeAnalysis(WholeProgram wholeProgram, TargetProfile profile) { 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()); }
public override ReachabilitySummary SummarizeMethod(IMethodDefinition methodDefinition, WholeProgram wholeProgram) { //Console.WriteLine("Running AlwaysTopLocalFlowMethodSummarizer on {0}", methodDefinition); // hack to analyze on Foo<T> rather than Foo // since we need this for data flow // Unfortunately, this makes the CFG barf. Need to revisit later. /* * ITypeReference fullyInstantiatedSpecializedTypeReference; * * if (TypeHelper.TryGetFullyInstantiatedSpecializedTypeReference(methodDefinition.ContainingTypeDefinition, out fullyInstantiatedSpecializedTypeReference)) { * foreach (IMethodDefinition instantiatedMethod in fullyInstantiatedSpecializedTypeReference.ResolvedType.Methods) { * if (GarbageCollectHelper.UnspecializeAndResolveMethodReference(instantiatedMethod).InternedKey == methodDefinition.InternedKey) { * methodDefinition = instantiatedMethod; * break; * } * } * } */ var valueAbstraction = new TypesValueAbstraction(wholeProgram.Host()); var stateInterpreter = new VirtualCallRecordingStateInterpreter <TypesValueAbstraction, ITypeDefinition>(valueAbstraction); var algorithm = new WorkListAlgorithm <VirtualCallRecordingStateInterpreter <TypesValueAbstraction, ITypeDefinition>, LocalsAndOperandsStateAbstraction <TypesValueAbstraction, ITypeDefinition>, LocalsAndOperands <ITypeDefinition> >(stateInterpreter); try { algorithm.RunOnMethod(methodDefinition, wholeProgram.Host()); } catch (Exception e) { if (e.GetType().FullName.Contains("ContractException")) { // Very hokey, but it is what it is. // Sometimes we fail because building the CFG fails, and occasionally // we fail because of something in the analysis. In either event, // we pick ourselves up and fall back on the regular summarization // Need to record statistics on how often this happens. Console.WriteLine("Got contract exception running local flow for " + methodDefinition); return(new SimpleBytecodeMethodSummarizer().SummarizeMethod(methodDefinition, wholeProgram)); } else { throw; } } LocalFlowEnhancedBytecodeVisitor bytecodeVisitor = new LocalFlowEnhancedBytecodeVisitor(); foreach (BasicBlock <Instruction> block in algorithm.ControlFlowGraph.AllBlocks) { foreach (Instruction instruction in block.Instructions) { if (instruction.Operation.OperationCode == OperationCode.Callvirt) { ITypeDefinition valueAtReceiver = algorithm.StateInterpreter.ReceiverValueForVirtualCallInstruction(instruction.Operation); Contract.Assert(valueAtReceiver != null); //t-devinc: handle not resolving method gracefully. IMethodDefinition compileTimeTargetMethod = (instruction.Operation.Value as IMethodReference).ResolvedMethod; // The only way we allow the analysis to return a type that is a supertype of the type being dispatched upon is // if we've gone to top (System.Object). // // This is really just a sanity check. ITypeDefinition compileTimeType = compileTimeTargetMethod.ContainingTypeDefinition; Contract.Assert(valueAtReceiver == wholeProgram.Host().PlatformType.SystemObject.ResolvedType || TypeHelper.Type1DerivesFromOrIsTheSameAsType2(valueAtReceiver, compileTimeType) || (compileTimeType.IsInterface && TypeHelper.Type1ImplementsType2(valueAtReceiver, compileTimeType)) || (valueAtReceiver.IsInterface && compileTimeType == wholeProgram.Host().PlatformType.SystemObject.ResolvedType) ); bytecodeVisitor.NoteReceiverTypeForCallVirtual(valueAtReceiver, instruction.Operation); } } } foreach (IOperation operation in methodDefinition.Body.Operations) { bytecodeVisitor.Visit(operation); } return(bytecodeVisitor.GetSummary()); }
private static StubMethodBodyEmitter GetStubMethodBodyEmitterForProfile(TargetProfile profile, WholeProgram wholeProgram) { StubMethodBodyEmitter emitter; switch (profile) { case TargetProfile.Desktop: emitter = new DotNetDesktopStubMethodBodyEmitter(wholeProgram.Host()); break; case TargetProfile.Phone: emitter = new WindowsPhoneStubMethodBodyEmitter(wholeProgram.Host()); break; default: emitter = new DotNetDesktopStubMethodBodyEmitter(wholeProgram.Host()); break; } return emitter; }
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); } } } } }