예제 #1
0
        internal static void Reachable(
            IMetadataHost host,
            ISlice <MethodReferenceAdaptor, FieldReferenceAdaptor, TypeReferenceAdaptor, IAssemblyReference> slice,
            HashSet <object> thingsToKeep,
            HashSet <uint> methodsWhoseBodiesShouldBeKept,
            out Dictionary <IMethodDefinition, uint> contractOffsets
            )
        {
            Contract.Requires(host != null);
            Contract.Requires(slice != null);
            Contract.Requires(thingsToKeep != null);
            Contract.Requires(methodsWhoseBodiesShouldBeKept != null);

            var traverser = new MetadataTraverser();
            var me        = new FindReachable(host, traverser, slice, thingsToKeep, methodsWhoseBodiesShouldBeKept);

            traverser.TraverseIntoMethodBodies = true;
            traverser.PreorderVisitor          = me;

            var methodsToTraverse = slice.Methods;

            foreach (var m in methodsToTraverse)
            {
                var methodDefinition = m.reference.ResolvedMethod;
                traverser.Traverse(methodDefinition);
            }

            foreach (var c in slice.Chains)
            {
                VisitChain(c, traverser);
            }
            contractOffsets = me.contractOffsets;
            return;
        }
예제 #2
0
    internal static void Reachable(
      IMetadataHost host,
      ISlice<MethodReferenceAdaptor, FieldReferenceAdaptor, TypeReferenceAdaptor, IAssemblyReference> slice,
      HashSet<object> thingsToKeep,
      HashSet<uint> methodsWhoseBodiesShouldBeKept,
      out Dictionary<IMethodDefinition, uint> contractOffsets
      ) {

      Contract.Requires(host != null);
      Contract.Requires(slice != null);
      Contract.Requires(thingsToKeep != null);
      Contract.Requires(methodsWhoseBodiesShouldBeKept != null);

      var traverser = new MetadataTraverser();
      var me = new FindReachable(host, traverser, slice, thingsToKeep, methodsWhoseBodiesShouldBeKept);
      traverser.TraverseIntoMethodBodies = true;
      traverser.PreorderVisitor = me;

      var methodsToTraverse = slice.Methods;
      foreach (var m in methodsToTraverse) {
        var methodDefinition = m.reference.ResolvedMethod;
        traverser.Traverse(methodDefinition);
      }

      foreach (var c in slice.Chains) {
        VisitChain(c, traverser);
      }
      contractOffsets = me.contractOffsets;
      return;
    }
예제 #3
0
        public static Assembly PruneAssembly(HostEnvironment host, ISlice <MethodReferenceAdaptor, FieldReferenceAdaptor, TypeReferenceAdaptor, IAssemblyReference> slice)
        {
            Contract.Requires(host != null);
            Contract.Requires(slice != null);

            var newAssemblyName  = slice.Name;
            var originalAssembly = slice.ContainingAssembly.ResolvedAssembly;

            Contract.Assume(!(originalAssembly is Dummy));
            var methodDefsToKeep = new HashSet <uint>();

            foreach (var m in slice.Methods)
            {
                methodDefsToKeep.Add(m.reference.InternedKey);
            }


            var copier               = new MetadataDeepCopier(host);
            var thingsToKeep         = new HashSet <object>();
            var methodHashAttributes = new Dictionary <IMethodDefinition, MethodHashAttribute>();
            var me = new Prune(host, copier, thingsToKeep, methodDefsToKeep, methodHashAttributes);

            // 1. everything that is specified in the slice should definitely be kept.
            foreach (var c in slice.Chains)
            {
                me.VisitChain(c);
            }

            // 2. everything reachable from the initial set of things to keep should be kept
            Dictionary <IMethodDefinition, uint> contractOffsets;

            FindReachable.Reachable(host, slice, thingsToKeep, methodDefsToKeep, out contractOffsets);
            me.contractOffsets = contractOffsets;

            // 3. copy the original assembly --- entirely!
            var a_prime   = copier.Copy(originalAssembly);
            var nameTable = host.NameTable;

            a_prime.ModuleName = nameTable.GetNameFor(newAssemblyName + ".dll");
            a_prime.Name       = nameTable.GetNameFor(newAssemblyName);

            var mutableRoot             = (RootUnitNamespace)(a_prime.UnitNamespaceRoot);
            var methodHashAttributeType = DefineMethodHashAttributeType(host, mutableRoot);

            me.methodHashAttributeCtor = new Microsoft.Cci.MethodReference(
                host,
                methodHashAttributeType,
                CallingConvention.HasThis,
                host.PlatformType.SystemVoid,
                host.NameTable.Ctor,
                0,
                me.systemString,
                me.systemInt);

            // 4. delete all unwanted things from the mutable copy
            me.RewriteChildren(a_prime);

            var remainingTypes = new List <INamedTypeDefinition>(a_prime.AllTypes.Count); // will only shrink

            remainingTypes.Add(a_prime.AllTypes[0]);                                      // <Module> class is always kept
            for (int i = 1, n = a_prime.AllTypes.Count; i < n; i++)
            {
                var t = a_prime.AllTypes[i];
                Contract.Assume(t != null);
                Contract.Assume(copier.OriginalFor.ContainsKey(t));
                var orig = copier.OriginalFor[t];
                if (thingsToKeep.Contains(orig))
                {
                    remainingTypes.Add(t);
                }
            }
            a_prime.AllTypes = remainingTypes;
            // do this afterwards so it doesn't get visited.
            mutableRoot.Members.Add(methodHashAttributeType);
            a_prime.AllTypes.Add(methodHashAttributeType);

            return(a_prime);
        }