Imported Upstream version 4.2.0.179

Former-commit-id: 0a113cb3a6feb7873f632839b1307cc6033cd595
This commit is contained in:
Xamarin Public Jenkins
2015-08-26 07:17:56 -04:00
committed by Jo Shields
parent 183bba2c9a
commit 6992685b86
7507 changed files with 90259 additions and 657307 deletions

View File

@@ -26,8 +26,11 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Linq;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.XPath;
using Mono.Cecil;
@@ -44,10 +47,37 @@ namespace Mono.Linker.Steps {
protected override void Process ()
{
foreach (string name in Assembly.GetExecutingAssembly ().GetManifestResourceNames ()) {
if (!IsReferenced (GetAssemblyName (name)))
if (Path.GetExtension (name) != ".xml" || !IsReferenced (GetAssemblyName (name)))
continue;
Context.Pipeline.AddStepAfter (typeof (TypeMapStep), GetResolveStep (name));
try {
if (Context.LogInternalExceptions)
Console.WriteLine ("Processing resource linker descriptor: {0}", name);
Context.Pipeline.AddStepAfter (typeof (TypeMapStep), GetResolveStep (name));
} catch (XmlException ex) {
/* This could happen if some broken XML file is included. */
if (Context.LogInternalExceptions)
Console.WriteLine ("Error processing {0}: {1}", name, ex);
}
}
foreach (var rsc in Context.GetAssemblies ()
.SelectMany (asm => asm.Modules)
.SelectMany (mod => mod.Resources)
.Where (res => res.ResourceType == ResourceType.Embedded)
.Where (res => Path.GetExtension (res.Name) == ".xml")
.Where (res => IsReferenced (GetAssemblyName (res.Name)))
.Cast<EmbeddedResource> ()) {
try {
if (Context.LogInternalExceptions)
Console.WriteLine ("Processing embedded resource linker descriptor: {0}", rsc.Name);
Context.Pipeline.AddStepAfter (typeof (TypeMapStep), GetExternalResolveStep (rsc));
} catch (XmlException ex) {
/* This could happen if some broken XML file is embedded. */
if (Context.LogInternalExceptions)
Console.WriteLine ("Error processing {0}: {1}", rsc.Name, ex);
}
}
}
@@ -69,11 +99,23 @@ namespace Mono.Linker.Steps {
return false;
}
static ResolveFromXmlStep GetExternalResolveStep (EmbeddedResource resource)
{
return new ResolveFromXmlStep (GetExternalDescriptor (resource));
}
static ResolveFromXmlStep GetResolveStep (string descriptor)
{
return new ResolveFromXmlStep (GetDescriptor (descriptor));
}
static XPathDocument GetExternalDescriptor (EmbeddedResource resource)
{
using (var sr = new StreamReader (resource.GetResourceStream ())) {
return new XPathDocument (new StringReader (sr.ReadToEnd ()));
}
}
static XPathDocument GetDescriptor (string descriptor)
{
using (StreamReader sr = new StreamReader (GetResource (descriptor))) {

View File

@@ -346,9 +346,25 @@ namespace Mono.Linker.Steps {
// even if we (just before saving) will resolve all type references (bug #26752)
void MarkWithResolvedScope (TypeReference type)
{
// we cannot set the Scope of a TypeSpecification so there's no point in resolving it
if ((type == null) || (type is TypeSpecification))
if (type == null)
return;
// a GenericInstanceType can could contains generic arguments with scope that
// needs to be updated out of the PCL facade (bug #28823)
var git = (type as GenericInstanceType);
if ((git != null) && git.HasGenericArguments) {
foreach (var ga in git.GenericArguments)
MarkWithResolvedScope (ga);
return;
}
// we cannot set the Scope of a TypeSpecification but it's element type can be set
// e.g. System.String[] -> System.String
var ts = (type as TypeSpecification);
if (ts != null) {
MarkWithResolvedScope (ts.GetElementType ());
return;
}
var td = type.Resolve ();
if (td != null)
type.Scope = td.Scope;
@@ -498,6 +514,8 @@ namespace Mono.Linker.Steps {
MarkMethodsIf (type.Methods, IsStaticConstructorPredicate);
}
DoAdditionalTypeProcessing (type);
Annotations.Mark (type);
ApplyPreserveInfo (type);
@@ -505,6 +523,11 @@ namespace Mono.Linker.Steps {
return type;
}
// Allow subclassers to mark additional things when marking a method
protected virtual void DoAdditionalTypeProcessing (TypeDefinition method)
{
}
void MarkTypeSpecialCustomAttributes (TypeDefinition type)
{
if (!type.HasCustomAttributes)
@@ -554,17 +577,21 @@ namespace Mono.Linker.Steps {
return argument != null;
}
protected void MarkNamedMethod (TypeDefinition type, string method_name)
protected int MarkNamedMethod (TypeDefinition type, string method_name)
{
if (!type.HasMethods)
return;
return 0;
int count = 0;
foreach (MethodDefinition method in type.Methods) {
if (method.Name != method_name)
continue;
MarkMethod (method);
count++;
}
return count;
}
void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute)
@@ -941,11 +968,18 @@ namespace Mono.Linker.Steps {
if (ShouldParseMethodBody (method))
MarkMethodBody (method.Body);
DoAdditionalMethodProcessing (method);
Annotations.Mark (method);
ApplyPreserveMethods (method);
}
// Allow subclassers to mark additional things when marking a method
protected virtual void DoAdditionalMethodProcessing (MethodDefinition method)
{
}
void MarkBaseMethods (MethodDefinition method)
{
IList base_methods = Annotations.GetBaseMethods (method);

View File

@@ -57,6 +57,12 @@ namespace Mono.Linker.Steps {
{
XPathNavigator nav = _document.CreateNavigator ();
nav.MoveToFirstChild ();
// This step can be created with XML files that aren't necessarily
// linker descriptor files. So bail if we don't have a <linker> element.
if (nav.LocalName != "linker")
return;
ProcessAssemblies (Context, nav.SelectChildren ("assembly", _ns));
}

View File

@@ -42,8 +42,17 @@ namespace Mono.Linker.Steps {
protected override void Process ()
{
assemblies = Context.GetAssemblies ();
foreach (var assembly in assemblies)
foreach (var assembly in assemblies) {
SweepAssembly (assembly);
if (Annotations.GetAction (assembly) == AssemblyAction.Copy) {
// Copy assemblies can still contain Type references with
// type forwarders from Delete assemblies
// thus try to resolve all the type references and see
// if some changed the scope. if yes change the action to Save
if (ResolveAllTypeReferences (assembly))
Annotations.SetAction (assembly, AssemblyAction.Save);
}
}
}
void SweepAssembly (AssemblyDefinition assembly)
@@ -124,15 +133,16 @@ namespace Mono.Linker.Steps {
}
}
void ResolveAllTypeReferences (AssemblyDefinition assembly)
bool ResolveAllTypeReferences (AssemblyDefinition assembly)
{
if (resolvedTypeReferences == null)
resolvedTypeReferences = new HashSet<AssemblyDefinition> ();
if (resolvedTypeReferences.Contains (assembly))
return;
return false;
resolvedTypeReferences.Add (assembly);
var hash = new Dictionary<TypeReference,IMetadataScope> ();
bool changes = false;
foreach (TypeReference tr in assembly.MainModule.GetTypeReferences ()) {
if (hash.ContainsKey (tr))
@@ -141,8 +151,11 @@ namespace Mono.Linker.Steps {
IMetadataScope scope = tr.Scope;
// at this stage reference might include things that can't be resolved
// and if it is (resolved) it needs to be kept only if marked (#16213)
if ((td != null) && Annotations.IsMarked (td))
if ((td != null) && Annotations.IsMarked (td)) {
scope = assembly.MainModule.Import (td).Scope;
if (tr.Scope != scope)
changes = true;
}
hash.Add (tr, scope);
}
if (assembly.MainModule.HasExportedTypes) {
@@ -163,6 +176,8 @@ namespace Mono.Linker.Steps {
foreach (var e in hash) {
e.Key.Scope = e.Value;
}
return changes;
}
void SweepType (TypeDefinition type)

View File

@@ -179,81 +179,118 @@ namespace Mono.Linker.Steps {
if (!type.HasMethods)
return null;
foreach (MethodDefinition candidate in type.Methods)
if (MethodMatch (candidate, method))
Dictionary<string,string> gp = null;
foreach (MethodDefinition candidate in type.Methods) {
if (MethodMatch (candidate, method, ref gp))
return candidate;
if (gp != null)
gp.Clear ();
}
return null;
}
static bool MethodMatch (MethodDefinition candidate, MethodDefinition method)
static bool MethodMatch (MethodDefinition candidate, MethodDefinition method, ref Dictionary<string,string> genericParameters)
{
if (!candidate.IsVirtual)
return false;
if (candidate.HasParameters != method.HasParameters)
return false;
if (candidate.Name != method.Name)
return false;
if (!TypeMatch (candidate.ReturnType, method.ReturnType))
if (candidate.HasGenericParameters != method.HasGenericParameters)
return false;
if (candidate.Parameters.Count != method.Parameters.Count)
// we need to track what the generic parameter represent - as we cannot allow it to
// differ between the return type or any parameter
if (!TypeMatch (candidate.ReturnType, method.ReturnType, ref genericParameters))
return false;
for (int i = 0; i < candidate.Parameters.Count; i++)
if (!TypeMatch (candidate.Parameters [i].ParameterType, method.Parameters [i].ParameterType))
if (!candidate.HasParameters)
return true;
var cp = candidate.Parameters;
var mp = method.Parameters;
if (cp.Count != mp.Count)
return false;
for (int i = 0; i < cp.Count; i++) {
if (!TypeMatch (cp [i].ParameterType, mp [i].ParameterType, ref genericParameters))
return false;
}
return true;
}
static bool TypeMatch (IModifierType a, IModifierType b)
static bool TypeMatch (IModifierType a, IModifierType b, ref Dictionary<string,string> gp)
{
if (!TypeMatch (a.ModifierType, b.ModifierType))
if (!TypeMatch (a.ModifierType, b.ModifierType, ref gp))
return false;
return TypeMatch (a.ElementType, b.ElementType);
return TypeMatch (a.ElementType, b.ElementType, ref gp);
}
static bool TypeMatch (TypeSpecification a, TypeSpecification b)
static bool TypeMatch (TypeSpecification a, TypeSpecification b, ref Dictionary<string,string> gp)
{
if (a is GenericInstanceType)
return TypeMatch ((GenericInstanceType) a, (GenericInstanceType) b);
var gita = a as GenericInstanceType;
if (gita != null)
return TypeMatch (gita, (GenericInstanceType) b, ref gp);
if (a is IModifierType)
return TypeMatch ((IModifierType) a, (IModifierType) b);
var mta = a as IModifierType;
if (mta != null)
return TypeMatch (mta, (IModifierType) b, ref gp);
return TypeMatch (a.ElementType, b.ElementType);
return TypeMatch (a.ElementType, b.ElementType, ref gp);
}
static bool TypeMatch (GenericInstanceType a, GenericInstanceType b)
static bool TypeMatch (GenericInstanceType a, GenericInstanceType b, ref Dictionary<string,string> gp)
{
if (!TypeMatch (a.ElementType, b.ElementType))
if (!TypeMatch (a.ElementType, b.ElementType, ref gp))
return false;
if (a.GenericArguments.Count != b.GenericArguments.Count)
if (a.HasGenericArguments != b.HasGenericArguments)
return false;
if (a.GenericArguments.Count == 0)
if (!a.HasGenericArguments)
return true;
for (int i = 0; i < a.GenericArguments.Count; i++)
if (!TypeMatch (a.GenericArguments [i], b.GenericArguments [i]))
var gaa = a.GenericArguments;
var gab = b.GenericArguments;
if (gaa.Count != gab.Count)
return false;
for (int i = 0; i < gaa.Count; i++) {
if (!TypeMatch (gaa [i], gab [i], ref gp))
return false;
}
return true;
}
static bool TypeMatch (TypeReference a, TypeReference b)
static bool TypeMatch (TypeReference a, TypeReference b, ref Dictionary<string,string> gp)
{
if (a is GenericParameter)
return true;
var gpa = a as GenericParameter;
if (gpa != null) {
if (gp == null)
gp = new Dictionary<string, string> ();
string match;
if (!gp.TryGetValue (gpa.FullName, out match)) {
// first use, we assume it will always be used this way
gp.Add (gpa.FullName, b.ToString ());
return true;
}
// re-use, it should match the previous usage
return match == b.ToString ();
}
if (a is TypeSpecification || b is TypeSpecification) {
if (a.GetType () != b.GetType ())
return false;
return TypeMatch ((TypeSpecification) a, (TypeSpecification) b);
return TypeMatch ((TypeSpecification) a, (TypeSpecification) b, ref gp);
}
return a.FullName == b.FullName;

View File

@@ -93,6 +93,8 @@ namespace Mono.Linker {
set { _symbolWriterProvider = value; }
}
public bool LogInternalExceptions { get; set; } = false;
public LinkContext (Pipeline pipeline)
: this (pipeline, new AssemblyResolver ())
{