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 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()); }