Imported Upstream version 5.10.0.47

Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-24 17:04:36 +00:00
parent 88ff76fe28
commit e46a49ecf1
5927 changed files with 226314 additions and 129848 deletions

View File

@@ -0,0 +1,120 @@
//
// AddBypassNGenStep.cs
//
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Collections.Generic;
using Mono.Cecil.Cil;
namespace Mono.Linker.Steps {
public class AddBypassNGenStep : BaseStep{
AssemblyDefinition coreLibAssembly;
CustomAttribute bypassNGenAttribute;
protected override void ProcessAssembly (AssemblyDefinition assembly)
{
if (Annotations.GetAction (assembly) == AssemblyAction.AddBypassNGen) {
coreLibAssembly = Context.Resolve (assembly.MainModule.TypeSystem.CoreLibrary);
bypassNGenAttribute = null;
if (assembly == coreLibAssembly) {
EnsureBypassNGenAttribute (assembly.MainModule);
}
foreach (var type in assembly.MainModule.Types)
ProcessType (type);
}
}
void ProcessType (TypeDefinition type)
{
if (type.HasMethods)
ProcessMethods (type.Methods, type.Module);
if (type.HasNestedTypes)
ProcessNestedTypes (type);
}
void ProcessMethods (Collection<MethodDefinition> methods, ModuleDefinition module)
{
foreach (var method in methods)
if (!Annotations.IsMarked (method)) {
EnsureBypassNGenAttribute (module);
method.CustomAttributes.Add (bypassNGenAttribute);
}
}
void ProcessNestedTypes (TypeDefinition type)
{
for (int i = 0; i < type.NestedTypes.Count; i++) {
var nested = type.NestedTypes [i];
ProcessType (nested);
}
}
private void EnsureBypassNGenAttribute (ModuleDefinition targetModule)
{
if (bypassNGenAttribute != null) {
return;
}
ModuleDefinition corelibMainModule = coreLibAssembly.MainModule;
TypeReference bypassNGenAttributeRef = new TypeReference ("System.Runtime", "BypassNGenAttribute", corelibMainModule, targetModule.TypeSystem.CoreLibrary);
TypeDefinition bypassNGenAttributeDef = corelibMainModule.MetadataResolver.Resolve (bypassNGenAttributeRef);
MethodDefinition bypassNGenAttributeDefaultConstructor = null;
if (bypassNGenAttributeDef == null) {
// System.Runtime.BypassNGenAttribute is not found in corelib. Add it.
TypeReference systemAttributeRef = new TypeReference ("System", "Attribute", corelibMainModule, targetModule.TypeSystem.CoreLibrary);
TypeReference systemAttribute = corelibMainModule.MetadataResolver.Resolve (systemAttributeRef);
systemAttribute = corelibMainModule.ImportReference (systemAttribute);
if (systemAttribute == null)
throw new System.ApplicationException ("System.Attribute is not found in " + targetModule.TypeSystem.CoreLibrary.Name);
MethodReference systemAttributeDefaultConstructorRef = new MethodReference (".ctor", corelibMainModule.TypeSystem.Void, systemAttributeRef);
MethodReference systemAttributeDefaultConstructor = corelibMainModule.MetadataResolver.Resolve (systemAttributeDefaultConstructorRef);
systemAttributeDefaultConstructor = corelibMainModule.ImportReference (systemAttributeDefaultConstructor);
if (systemAttributeDefaultConstructor == null)
throw new System.ApplicationException ("System.Attribute has no default constructor");
bypassNGenAttributeDef = new TypeDefinition ("System.Runtime", "BypassNGenAttribute", TypeAttributes.NotPublic | TypeAttributes.Sealed, systemAttribute);
coreLibAssembly.MainModule.Types.Add (bypassNGenAttributeDef);
if (Annotations.GetAction (coreLibAssembly) == AssemblyAction.Copy) {
Annotations.SetAction (coreLibAssembly, AssemblyAction.Save);
}
const MethodAttributes ctorAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
bypassNGenAttributeDefaultConstructor = new MethodDefinition (".ctor", ctorAttributes, coreLibAssembly.MainModule.TypeSystem.Void);
var instructions = bypassNGenAttributeDefaultConstructor.Body.Instructions;
instructions.Add (Instruction.Create (OpCodes.Ldarg_0));
instructions.Add (Instruction.Create (OpCodes.Call, systemAttributeDefaultConstructor));
instructions.Add (Instruction.Create (OpCodes.Ret));
bypassNGenAttributeDef.Methods.Add (bypassNGenAttributeDefaultConstructor);
}
else {
foreach (MethodDefinition method in bypassNGenAttributeDef.Methods) {
if (method.IsConstructor && !method.IsStatic && !method.HasParameters) {
bypassNGenAttributeDefaultConstructor = method;
break;
}
}
if (bypassNGenAttributeDefaultConstructor == null) {
throw new System.ApplicationException ("System.Runtime.BypassNGenAttribute has no default constructor");
}
}
MethodReference defaultConstructorReference = targetModule.ImportReference (bypassNGenAttributeDefaultConstructor);
bypassNGenAttribute = new CustomAttribute (defaultConstructorReference);
}
}
}

View File

@@ -42,6 +42,12 @@ namespace Mono.Linker.Steps {
get { return _context.Annotations; }
}
public Tracer Tracer {
get { return _context.Tracer; }
}
public MarkingHelpers MarkingHelpers => _context.MarkingHelpers;
public void Process (LinkContext context)
{
_context = context;

View File

@@ -51,6 +51,12 @@ namespace Mono.Linker.Steps {
get { return _context.Annotations; }
}
public Tracer Tracer {
get { return _context.Tracer; }
}
private MarkingHelpers MarkingHelpers => _context.MarkingHelpers;
public MarkStep ()
{
_methods = new Queue<MethodDefinition> ();
@@ -77,14 +83,14 @@ namespace Mono.Linker.Steps {
protected virtual void InitializeAssembly (AssemblyDefinition assembly)
{
Annotations.Push (assembly);
Tracer.Push (assembly);
try {
MarkAssembly (assembly);
foreach (TypeDefinition type in assembly.MainModule.Types)
InitializeType (type);
} finally {
Annotations.Pop ();
Tracer.Pop ();
}
}
@@ -125,13 +131,7 @@ namespace Mono.Linker.Steps {
if (QueueIsEmpty ())
throw new InvalidOperationException ("No entry methods");
ProcessEntireQueue ();
// After all types have been processed then we can process the lazily marked attributes
ProcessLazyAttributes ();
// We need to process the queue again in case marking the attributes enqueued more work
ProcessEntireQueue ();
while (ProcessPrimaryQueue () || ProcessLazyAttributes ())
// deal with [TypeForwardedTo] pseudo-attributes
foreach (AssemblyDefinition assembly in _context.GetAssemblies ()) {
@@ -157,39 +157,41 @@ namespace Mono.Linker.Steps {
}
if (!Annotations.IsMarked (type))
continue;
Annotations.Push (type);
Tracer.Push (type);
try {
Annotations.Mark (exported);
if (_context.KeepTypeForwarderOnlyAssemblies) {
Annotations.Mark (assembly.MainModule);
}
MarkingHelpers.MarkExportedType (exported, assembly.MainModule);
} finally {
Annotations.Pop ();
Tracer.Pop ();
}
}
}
}
void ProcessEntireQueue ()
bool ProcessPrimaryQueue ()
{
if (QueueIsEmpty ())
return false;
while (!QueueIsEmpty ()) {
ProcessQueue ();
ProcessVirtualMethods ();
DoAdditionalProcessing ();
}
return true;
}
void ProcessQueue ()
{
while (!QueueIsEmpty ()) {
MethodDefinition method = _methods.Dequeue ();
Annotations.Push (method);
Tracer.Push (method);
try {
ProcessMethod (method);
} catch (Exception e) {
throw new MarkException (string.Format ("Error processing method: '{0}' in assembly: '{1}'", method.FullName, method.Module.Name), e, method);
} finally {
Annotations.Pop ();
Tracer.Pop ();
}
}
}
@@ -207,9 +209,9 @@ namespace Mono.Linker.Steps {
void ProcessVirtualMethods ()
{
foreach (MethodDefinition method in _virtual_methods) {
Annotations.Push (method);
Tracer.Push (method);
ProcessVirtualMethod (method);
Annotations.Pop ();
Tracer.Pop ();
}
}
@@ -255,12 +257,16 @@ namespace Mono.Linker.Steps {
if (!provider.HasCustomAttributes)
return;
Annotations.Push (provider);
Tracer.Push (provider);
try {
foreach (CustomAttribute ca in provider.CustomAttributes)
foreach (CustomAttribute ca in provider.CustomAttributes) {
if (!ShouldMarkCustomAttribute (ca))
continue;
MarkCustomAttribute (ca);
}
} finally {
Annotations.Pop ();
Tracer.Pop ();
}
}
@@ -275,8 +281,9 @@ namespace Mono.Linker.Steps {
protected virtual void MarkCustomAttribute (CustomAttribute ca)
{
Annotations.Push ((object)ca.AttributeType ?? (object)ca);
Tracer.Push ((object)ca.AttributeType ?? (object)ca);
try {
Annotations.Mark (ca);
MarkMethod (ca.Constructor);
MarkCustomAttributeArguments (ca);
@@ -292,10 +299,25 @@ namespace Mono.Linker.Steps {
MarkCustomAttributeProperties (ca, type);
MarkCustomAttributeFields (ca, type);
} finally {
Annotations.Pop ();
Tracer.Pop ();
}
}
protected virtual bool ShouldMarkCustomAttribute (CustomAttribute ca)
{
return true;
}
protected virtual bool ShouldMarkTopLevelCustomAttribute (CustomAttribute ca, MethodDefinition resolvedConstructor)
{
// If an attribute's module has not been marked after processing all types in all assemblies and the attribute itself has not been marked,
// then surely nothing is using this attribute and there is no need to mark it
if (!Annotations.IsMarked (resolvedConstructor.Module) && !Annotations.IsMarked (ca.AttributeType))
return false;
return true;
}
protected void MarkSecurityDeclarations (ISecurityDeclarationProvider provider)
{
// most security declarations are removed (if linked) but user code might still have some
@@ -358,12 +380,12 @@ namespace Mono.Linker.Steps {
protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute)
{
PropertyDefinition property = GetProperty (attribute, namedArgument.Name);
Annotations.Push (property);
Tracer.Push (property);
if (property != null)
MarkMethod (property.SetMethod);
MarkIfType (namedArgument.Argument);
Annotations.Pop ();
Tracer.Pop ();
}
PropertyDefinition GetProperty (TypeDefinition type, string propertyname)
@@ -518,24 +540,38 @@ namespace Mono.Linker.Steps {
}
}
void ProcessLazyAttributes ()
bool ProcessLazyAttributes ()
{
var startingQueueCount = _topLevelAttributes.Count;
if (startingQueueCount == 0)
return false;
var skippedItems = new List<CustomAttribute> ();
var markOccurred = false;
while (_topLevelAttributes.Count != 0) {
var customAttribute = _topLevelAttributes.Dequeue ();
var resolved = customAttribute.AttributeType.Resolve ();
var resolved = customAttribute.Constructor.Resolve ();
if (resolved == null) {
HandleUnresolvedType (customAttribute.AttributeType);
HandleUnresolvedMethod (customAttribute.Constructor);
continue;
}
// If an attribute's module has not been marked after processing all types in all assemblies and the attribute itself has not been marked,
// then surely nothing is using this attribute and there is no need to mark it
if (!Annotations.IsMarked (resolved.Module) && !Annotations.IsMarked (customAttribute.AttributeType))
if (!ShouldMarkTopLevelCustomAttribute (customAttribute, resolved)) {
skippedItems.Add (customAttribute);
continue;
}
markOccurred = true;
MarkCustomAttribute (customAttribute);
}
// requeue the items we skipped in case we need to make another pass
foreach (var item in skippedItems)
_topLevelAttributes.Enqueue (item);
return markOccurred;
}
protected void MarkField (FieldReference reference)
@@ -618,7 +654,7 @@ namespace Mono.Linker.Steps {
if (CheckProcessed (type))
return null;
Annotations.Push (type);
Tracer.Push (type);
MarkScope (type.Scope);
MarkType (type.BaseType);
@@ -659,7 +695,7 @@ namespace Mono.Linker.Steps {
DoAdditionalTypeProcessing (type);
Annotations.Pop ();
Tracer.Pop ();
Annotations.Mark (type);
@@ -926,10 +962,10 @@ namespace Mono.Linker.Steps {
if (property.Name != property_name)
continue;
Annotations.Push (property);
Tracer.Push (property);
MarkMethod (property.GetMethod);
MarkMethod (property.SetMethod);
Annotations.Pop ();
Tracer.Pop ();
}
}
@@ -1215,7 +1251,7 @@ namespace Mono.Linker.Steps {
if (!includeStatic && field.IsStatic)
continue;
if (markBackingFieldsOnlyIfPropertyMarked && field.Name.EndsWith (">k__BackingField")) {
if (markBackingFieldsOnlyIfPropertyMarked && field.Name.EndsWith (">k__BackingField", StringComparison.Ordinal)) {
// We can't reliably construct the expected property name from the backing field name for all compilers
// because csc shortens the name of the backing field in some cases
// For example:
@@ -1234,8 +1270,12 @@ namespace Mono.Linker.Steps {
static PropertyDefinition SearchPropertiesForMatchingFieldDefinition (FieldDefinition field)
{
foreach (var property in field.DeclaringType.Properties) {
foreach (var ins in property.GetMethod.Body.Instructions) {
if (ins.Operand != null && ins.Operand == field)
var instr = property.GetMethod?.Body?.Instructions;
if (instr == null)
continue;
foreach (var ins in instr) {
if (ins?.Operand == field)
return property;
}
}
@@ -1273,7 +1313,7 @@ namespace Mono.Linker.Steps {
if (reference.DeclaringType is ArrayType)
return null;
Annotations.Push (reference);
Tracer.Push (reference);
if (reference.DeclaringType is GenericInstanceType)
MarkType (reference.DeclaringType);
@@ -1293,9 +1333,9 @@ namespace Mono.Linker.Steps {
EnqueueMethod (method);
} finally {
Annotations.Pop ();
Tracer.Pop ();
}
Annotations.AddDependency (method);
Tracer.AddDependency (method);
return method;
}
@@ -1334,7 +1374,7 @@ namespace Mono.Linker.Steps {
if (CheckProcessed (method))
return;
Annotations.Push (method);
Tracer.Push (method);
MarkType (method.DeclaringType);
MarkCustomAttributes (method);
MarkSecurityDeclarations (method);
@@ -1382,7 +1422,7 @@ namespace Mono.Linker.Steps {
Annotations.Mark (method);
ApplyPreserveMethods (method);
Annotations.Pop ();
Tracer.Pop ();
}
// Allow subclassers to mark additional things when marking a method
@@ -1433,7 +1473,7 @@ namespace Mono.Linker.Steps {
}
}
bool ShouldParseMethodBody (MethodDefinition method)
protected virtual bool ShouldParseMethodBody (MethodDefinition method)
{
if (!method.HasBody)
return false;
@@ -1447,6 +1487,8 @@ namespace Mono.Linker.Steps {
case AssemblyAction.Link:
case AssemblyAction.Copy:
case AssemblyAction.CopyUsed:
case AssemblyAction.AddBypassNGen:
case AssemblyAction.AddBypassNGenUsed:
return true;
default:
return false;

View File

@@ -71,7 +71,7 @@ namespace Mono.Linker.Steps {
protected override void Process ()
{
CheckOutputDirectory ();
Annotations.SaveDependencies ();
Tracer.Finish ();
}
void CheckOutputDirectory ()
@@ -113,14 +113,18 @@ namespace Mono.Linker.Steps {
CopyConfigFileIfNeeded (assembly, directory);
switch (Annotations.GetAction (assembly)) {
var action = Annotations.GetAction (assembly);
Context.LogMessage (MessageImportance.Low, $"Output action: {action,8} assembly: {assembly}");
switch (action) {
case AssemblyAction.Save:
case AssemblyAction.Link:
Context.Annotations.AddDependency (assembly);
case AssemblyAction.AddBypassNGen:
Context.Tracer.AddDependency (assembly);
WriteAssembly (assembly, directory);
break;
case AssemblyAction.Copy:
Context.Annotations.AddDependency (assembly);
Context.Tracer.AddDependency (assembly);
CloseSymbols (assembly);
CopyAssembly (GetOriginalAssemblyFileInfo (assembly), directory, Context.LinkSymbols);
break;

View File

@@ -101,7 +101,7 @@ namespace Mono.Linker.Steps
var action = rootVisibility == RootVisibility.Any ? AssemblyAction.Copy : AssemblyAction.Link;
SetAction (context, assembly, action);
context.Annotations.Push (assembly);
context.Tracer.Push (assembly);
foreach (TypeDefinition type in assembly.MainModule.Types)
MarkType (context, type, rootVisibility);
@@ -144,14 +144,11 @@ namespace Mono.Linker.Steps
context.Resolve (resolvedExportedType.Scope);
MarkType (context, resolvedExportedType, rootVisibility);
context.Annotations.Mark (exported);
if (context.KeepTypeForwarderOnlyAssemblies) {
context.Annotations.Mark (assembly.MainModule);
}
context.MarkingHelpers.MarkExportedType (exported, assembly.MainModule);
}
}
context.Annotations.Pop ();
context.Tracer.Pop ();
}
static void MarkType (LinkContext context, TypeDefinition type, RootVisibility rootVisibility)
@@ -175,9 +172,7 @@ namespace Mono.Linker.Steps
return;
}
context.Annotations.Mark (type);
context.Annotations.Push (type);
context.Annotations.MarkAndPush (type);
if (type.HasFields)
MarkFields (context, type.Fields, rootVisibility);
@@ -187,20 +182,20 @@ namespace Mono.Linker.Steps
foreach (var nested in type.NestedTypes)
MarkType (context, nested, rootVisibility);
context.Annotations.Pop ();
context.Tracer.Pop ();
}
void ProcessExecutable (AssemblyDefinition assembly)
{
SetAction (Context, assembly, AssemblyAction.Link);
Annotations.Push (assembly);
Tracer.Push (assembly);
Annotations.Mark (assembly.EntryPoint.DeclaringType);
MarkMethod (Context, assembly.EntryPoint, MethodAction.Parse, RootVisibility.Any);
Annotations.Pop ();
Tracer.Pop ();
}
static void MarkFields (LinkContext context, Collection<FieldDefinition> fields, RootVisibility rootVisibility)

View File

@@ -95,25 +95,32 @@ namespace Mono.Linker.Steps {
if (!string.IsNullOrEmpty (_resourceName))
Context.Annotations.AddResourceToRemove (_resourceAssembly, _resourceName);
} catch (Exception ex) {
} catch (Exception ex) when (!(ex is XmlResolutionException)) {
throw new XmlResolutionException (string.Format ("Failed to process XML description: {0}", _xmlDocumentLocation), ex);
}
}
void ProcessAssemblies (LinkContext context, XPathNodeIterator iterator)
protected virtual void ProcessAssemblies (LinkContext context, XPathNodeIterator iterator)
{
while (iterator.MoveNext ()) {
AssemblyDefinition assembly = GetAssembly (context, GetFullName (iterator.Current));
if (GetTypePreserve (iterator.Current) == TypePreserve.All) {
foreach (var type in assembly.MainModule.Types)
MarkAndPreserveAll (type);
} else {
ProcessTypes (assembly, iterator.Current.SelectChildren ("type", _ns));
ProcessNamespaces (assembly, iterator.Current.SelectChildren ("namespace", _ns));
}
AssemblyDefinition assembly = GetAssembly (context, GetAssemblyName (iterator.Current));
ProcessAssembly (assembly, iterator);
}
}
protected void ProcessAssembly (AssemblyDefinition assembly, XPathNodeIterator iterator)
{
Tracer.Push (assembly);
if (GetTypePreserve (iterator.Current) == TypePreserve.All) {
foreach (var type in assembly.MainModule.Types)
MarkAndPreserveAll (type);
} else {
ProcessTypes (assembly, iterator.Current.SelectChildren ("type", _ns));
ProcessNamespaces (assembly, iterator.Current.SelectChildren ("namespace", _ns));
}
Tracer.Pop ();
}
void ProcessNamespaces (AssemblyDefinition assembly, XPathNodeIterator iterator)
{
while (iterator.MoveNext ()) {
@@ -129,14 +136,18 @@ namespace Mono.Linker.Steps {
void MarkAndPreserveAll (TypeDefinition type)
{
Annotations.Mark (type);
Annotations.MarkAndPush (type);
Annotations.SetPreserve (type, TypePreserve.All);
if (!type.HasNestedTypes)
if (!type.HasNestedTypes) {
Tracer.Pop ();
return;
}
foreach (TypeDefinition nested in type.NestedTypes)
MarkAndPreserveAll (nested);
Tracer.Pop ();
}
void ProcessTypes (AssemblyDefinition assembly, XPathNodeIterator iterator)
@@ -156,9 +167,10 @@ namespace Mono.Linker.Steps {
if (assembly.MainModule.HasExportedTypes) {
foreach (var exported in assembly.MainModule.ExportedTypes) {
if (fullname == exported.FullName) {
Annotations.Mark (exported);
Annotations.Mark (assembly.MainModule);
Tracer.Push (exported);
MarkingHelpers.MarkExportedType (exported, assembly.MainModule);
var resolvedExternal = exported.Resolve ();
Tracer.Pop ();
if (resolvedExternal != null) {
type = resolvedExternal;
break;
@@ -200,8 +212,7 @@ namespace Mono.Linker.Steps {
void MatchExportedType (ExportedType exportedType, ModuleDefinition module, Regex regex, XPathNavigator nav)
{
if (regex.Match (exportedType.FullName).Success) {
Annotations.Mark (exportedType);
Annotations.Mark (module);
MarkingHelpers.MarkExportedType (exportedType, module);
TypeDefinition type = null;
try {
type = exportedType.Resolve ();
@@ -239,7 +250,8 @@ namespace Mono.Linker.Steps {
return;
}
Annotations.Mark (type);
Annotations.MarkAndPush (type);
Tracer.AddDirectDependency (this, type);
if (type.IsNested) {
var parent = type;
@@ -258,6 +270,7 @@ namespace Mono.Linker.Steps {
MarkSelectedEvents (nav, type);
MarkSelectedProperties (nav, type);
}
Tracer.Pop ();
}
void MarkSelectedFields (XPathNavigator nav, TypeDefinition type)
@@ -302,11 +315,10 @@ namespace Mono.Linker.Steps {
if (attribute == null || attribute.Length == 0)
return nav.HasChildren ? TypePreserve.Nothing : TypePreserve.All;
try {
return (TypePreserve) Enum.Parse (typeof (TypePreserve), attribute, true);
} catch {
return TypePreserve.Nothing;
}
TypePreserve result;
if (Enum.TryParse (attribute, true, out result))
return result;
return TypePreserve.Nothing;
}
void ProcessFields (TypeDefinition type, XPathNodeIterator iterator)
@@ -363,17 +375,21 @@ namespace Mono.Linker.Steps {
return field.FieldType.FullName + " " + field.Name;
}
void ProcessMethods (TypeDefinition type, XPathNodeIterator iterator)
protected virtual void ProcessMethods (TypeDefinition type, XPathNodeIterator iterator)
{
while (iterator.MoveNext ()) {
string value = GetSignature (iterator.Current);
if (!String.IsNullOrEmpty (value))
ProcessMethodSignature (type, value);
while (iterator.MoveNext ())
ProcessMethod (type, iterator);
}
value = GetAttribute (iterator.Current, "name");
if (!String.IsNullOrEmpty (value))
ProcessMethodName (type, value);
}
protected void ProcessMethod(TypeDefinition type, XPathNodeIterator iterator)
{
string value = GetSignature (iterator.Current);
if (!String.IsNullOrEmpty (value))
ProcessMethodSignature (type, value);
value = GetAttribute (iterator.Current, "name");
if (!String.IsNullOrEmpty (value))
ProcessMethodName (type, value);
}
void ProcessMethodSignature (TypeDefinition type, string signature)
@@ -393,6 +409,7 @@ namespace Mono.Linker.Steps {
void MarkMethod (MethodDefinition method)
{
Annotations.Mark (method);
Tracer.AddDirectDependency (this, method);
Annotations.SetAction (method, MethodAction.Parse);
}
@@ -414,7 +431,7 @@ namespace Mono.Linker.Steps {
MarkMethod (type, method, name);
}
static MethodDefinition GetMethod (TypeDefinition type, string signature)
protected static MethodDefinition GetMethod (TypeDefinition type, string signature)
{
if (type.HasMethods)
foreach (MethodDefinition meth in type.Methods)
@@ -578,17 +595,18 @@ namespace Mono.Linker.Steps {
return property.PropertyType.FullName + " " + property.Name;
}
static AssemblyDefinition GetAssembly (LinkContext context, string assemblyName)
protected AssemblyDefinition GetAssembly (LinkContext context, AssemblyNameReference assemblyName)
{
AssemblyNameReference reference = AssemblyNameReference.Parse (assemblyName);
AssemblyDefinition assembly;
assembly = context.Resolve (reference);
var assembly = context.Resolve (assemblyName);
ProcessReferences (assembly, context);
return assembly;
}
protected virtual AssemblyNameReference GetAssemblyName (XPathNavigator nav)
{
return AssemblyNameReference.Parse (GetFullName (nav));
}
static void ProcessReferences (AssemblyDefinition assembly, LinkContext context)
{
context.ResolveReferences (assembly);
@@ -600,19 +618,13 @@ namespace Mono.Linker.Steps {
if (attribute == null || attribute.Length == 0)
return true;
return TryParseBool (attribute);
bool result;
if (bool.TryParse (attribute, out result))
return result;
return false;
}
static bool TryParseBool (string s)
{
try {
return bool.Parse (s);
} catch {
return false;
}
}
static string GetSignature (XPathNavigator nav)
protected static string GetSignature (XPathNavigator nav)
{
return GetAttribute (nav, _signature);
}
@@ -640,7 +652,7 @@ namespace Mono.Linker.Steps {
return _accessorsAll;
}
static string GetAttribute (XPathNavigator nav, string attribute)
protected static string GetAttribute (XPathNavigator nav, string attribute)
{
return nav.GetAttribute (attribute, _ns);
}

View File

@@ -61,14 +61,14 @@ namespace Mono.Linker.Steps {
Annotations.SetAction (assembly, AssemblyAction.Save);
}
AssemblyAction currentAction = Annotations.GetAction(assembly);
AssemblyAction currentAction = Annotations.GetAction (assembly);
if ((currentAction == AssemblyAction.Link) || (currentAction == AssemblyAction.Save)) {
// if we save (only or by linking) then unmarked exports (e.g. forwarders) must be cleaned
// or they can point to nothing which will break later (e.g. when re-loading for stripping IL)
// reference: https://bugzilla.xamarin.com/show_bug.cgi?id=36577
if (assembly.MainModule.HasExportedTypes)
SweepCollection(assembly.MainModule.ExportedTypes);
SweepCollectionNonAttributable (assembly.MainModule.ExportedTypes);
}
}
}
@@ -83,6 +83,14 @@ namespace Mono.Linker.Steps {
}
break;
case AssemblyAction.AddBypassNGenUsed:
if (!IsMarkedAssembly (assembly)) {
RemoveAssembly (assembly);
} else {
Annotations.SetAction (assembly, AssemblyAction.AddBypassNGen);
}
return;
case AssemblyAction.CopyUsed:
if (!IsMarkedAssembly (assembly)) {
RemoveAssembly (assembly);
@@ -115,6 +123,7 @@ namespace Mono.Linker.Steps {
assembly.MainModule.Types.Add (type);
SweepResources (assembly);
SweepCustomAttributes (assembly);
}
bool IsMarkedAssembly (AssemblyDefinition assembly)
@@ -184,8 +193,17 @@ namespace Mono.Linker.Steps {
}
break;
case AssemblyAction.CopyUsed:
if (IsMarkedAssembly (assembly) && !Context.KeepTypeForwarderOnlyAssemblies) {
Annotations.SetAction (assembly, AssemblyAction.Save);
ResolveAllTypeReferences (assembly);
}
break;
case AssemblyAction.Save:
case AssemblyAction.Link:
case AssemblyAction.AddBypassNGen:
case AssemblyAction.AddBypassNGenUsed:
if (!Context.KeepTypeForwarderOnlyAssemblies) {
ResolveAllTypeReferences (assembly);
}
@@ -258,6 +276,12 @@ namespace Mono.Linker.Steps {
if (type.HasInterfaces)
SweepInterfaces (type);
if (type.HasCustomAttributes)
SweepCustomAttributes (type);
if (type.HasProperties)
SweepCustomAttributeCollection (type.Properties);
}
protected void SweepNestedTypes (TypeDefinition type)
@@ -284,7 +308,24 @@ namespace Mono.Linker.Steps {
}
}
void SweepMethods (Collection<MethodDefinition> methods)
protected void SweepCustomAttributes (ICustomAttributeProvider provider)
{
for (int i = provider.CustomAttributes.Count - 1; i >= 0; i--) {
var attribute = provider.CustomAttributes [i];
if (!Annotations.IsMarked (attribute)) {
CustomAttributeUsageRemoved (provider, attribute);
provider.CustomAttributes.RemoveAt (i);
}
}
}
protected void SweepCustomAttributeCollection<T> (Collection<T> providers) where T : ICustomAttributeProvider
{
foreach (var provider in providers)
SweepCustomAttributes (provider);
}
protected virtual void SweepMethods (Collection<MethodDefinition> methods)
{
SweepCollection (methods);
if (sweepSymbols)
@@ -336,15 +377,31 @@ namespace Mono.Linker.Steps {
}
}
protected void SweepCollection<T> (IList<T> list) where T : IMetadataTokenProvider
protected void SweepCollection<T> (IList<T> list) where T : ICustomAttributeProvider
{
for (int i = 0; i < list.Count; i++)
if (!Annotations.IsMarked (list [i])) {
if (ShouldRemove (list [i])) {
ElementRemoved (list [i]);
list.RemoveAt (i--);
} else {
SweepCustomAttributes (list [i]);
}
}
protected void SweepCollectionNonAttributable<T> (IList<T> list) where T : IMetadataTokenProvider
{
for (int i = 0; i < list.Count; i++)
if (ShouldRemove (list [i])) {
ElementRemoved (list [i]);
list.RemoveAt (i--);
}
}
protected virtual bool ShouldRemove<T> (T element) where T : IMetadataTokenProvider
{
return !Annotations.IsMarked (element);
}
static bool AreSameReference (AssemblyNameReference a, AssemblyNameReference b)
{
if (a == b)
@@ -370,5 +427,9 @@ namespace Mono.Linker.Steps {
protected virtual void InterfaceRemoved (TypeDefinition type, InterfaceImplementation iface)
{
}
protected virtual void CustomAttributeUsageRemoved (ICustomAttributeProvider provider, CustomAttribute attribute)
{
}
}
}

View File

@@ -28,8 +28,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using Mono.Cecil;
using Mono.Cecil.Cil;
@@ -38,6 +36,8 @@ namespace Mono.Linker {
public class AnnotationStore {
protected readonly LinkContext context;
readonly Dictionary<AssemblyDefinition, AssemblyAction> assembly_actions = new Dictionary<AssemblyDefinition, AssemblyAction> ();
readonly Dictionary<MethodDefinition, MethodAction> method_actions = new Dictionary<MethodDefinition, MethodAction> ();
readonly HashSet<IMetadataTokenProvider> marked = new HashSet<IMetadataTokenProvider> ();
@@ -51,31 +51,27 @@ namespace Mono.Linker {
readonly Dictionary<object, Dictionary<IMetadataTokenProvider, object>> custom_annotations = new Dictionary<object, Dictionary<IMetadataTokenProvider, object>> ();
readonly Dictionary<AssemblyDefinition, HashSet<string>> resources_to_remove = new Dictionary<AssemblyDefinition, HashSet<string>> ();
readonly HashSet<CustomAttribute> marked_attributes = new HashSet<CustomAttribute> ();
Stack<object> dependency_stack;
System.Xml.XmlWriter writer;
GZipStream zipStream;
public AnnotationStore (LinkContext context) => this.context = context;
public void PrepareDependenciesDump ()
{
PrepareDependenciesDump ("linker-dependencies.xml.gz");
protected Tracer Tracer {
get {
return context.Tracer;
}
}
[Obsolete ("Use Tracer in LinkContext directly")]
public void PrepareDependenciesDump ()
{
Tracer.Start ();
}
[Obsolete ("Use Tracer in LinkContext directly")]
public void PrepareDependenciesDump (string filename)
{
dependency_stack = new Stack<object> ();
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = "\t";
var depsFile = File.OpenWrite (filename);
zipStream = new GZipStream (depsFile, CompressionMode.Compress);
writer = System.Xml.XmlWriter.Create (zipStream, settings);
writer.WriteStartDocument ();
writer.WriteStartElement ("dependencies");
writer.WriteStartAttribute ("version");
writer.WriteString ("1.0");
writer.WriteEndAttribute ();
Tracer.DependenciesFileName = filename;
Tracer.Start ();
}
public ICollection<AssemblyDefinition> GetAssemblies ()
@@ -119,7 +115,18 @@ namespace Mono.Linker {
public void Mark (IMetadataTokenProvider provider)
{
marked.Add (provider);
AddDependency (provider);
Tracer.AddDependency (provider, true);
}
public void Mark (CustomAttribute attribute)
{
marked_attributes.Add (attribute);
}
public void MarkAndPush (IMetadataTokenProvider provider)
{
Mark (provider);
Tracer.Push (provider, false);
}
public bool IsMarked (IMetadataTokenProvider provider)
@@ -127,6 +134,11 @@ namespace Mono.Linker {
return marked.Contains (provider);
}
public bool IsMarked (CustomAttribute attribute)
{
return marked_attributes.Contains (attribute);
}
public void Processed (IMetadataTokenProvider provider)
{
processed.Add (provider);
@@ -315,64 +327,5 @@ namespace Mono.Linker {
custom_annotations.Add (key, slots);
return slots;
}
public void AddDependency (object o)
{
if (writer == null)
return;
KeyValuePair<object, object> pair = new KeyValuePair<object, object> (dependency_stack.Count > 0 ? dependency_stack.Peek () : null, o);
if (pair.Key != pair.Value)
{
writer.WriteStartElement ("edge");
writer.WriteAttributeString ("b", TokenString (pair.Key));
writer.WriteAttributeString ("e", TokenString (pair.Value));
writer.WriteEndElement ();
}
}
public void Push (object o)
{
if (writer == null)
return;
if (dependency_stack.Count > 0)
AddDependency (o);
dependency_stack.Push (o);
}
public void Pop ()
{
if (writer == null)
return;
dependency_stack.Pop ();
}
string TokenString (object o)
{
if (o == null)
return "N:null";
if (o is IMetadataTokenProvider)
return (o as IMetadataTokenProvider).MetadataToken.TokenType + ":" + o;
return "Other:" + o;
}
public void SaveDependencies ()
{
if (writer == null)
return;
writer.WriteEndElement ();
writer.WriteEndDocument ();
writer.Flush ();
writer.Dispose ();
zipStream.Dispose ();
writer = null;
zipStream = null;
dependency_stack = null;
}
}
}

View File

@@ -45,6 +45,11 @@ namespace Mono.Linker {
// Save the assembly/symbols in memory without linking it.
// E.g. useful to remove unneeded assembly references (as done in SweepStep),
// resolving [TypeForwardedTo] attributes (like PCL) to their final location
Save
Save,
// Keep all types, methods, and fields but add System.Runtime.BypassNGenAttribute to unmarked methods.
AddBypassNGen,
// Keep all types, methods, and fields in marked assemblies but add System.Runtime.BypassNGenAttribute to unmarked methods.
// Delete unmarked assemblies.
AddBypassNGenUsed
}
}

Some files were not shown because too many files have changed in this diff Show More