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