示例#1
0
        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());
        }
示例#2
0
        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());
        }
示例#3
0
        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);
        }
示例#4
0
        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());

    }
示例#7
0
        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 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 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;
    }
示例#10
0
        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);
                        }
                    }
                }
            }
        }