Imported Upstream version 5.0.0.42

Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-04-10 11:41:01 +00:00
parent 1190d13a04
commit 6bdd276d05
19939 changed files with 3099680 additions and 93811 deletions

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Mono.Linker;
using Mono.Linker.Steps;
using Mono.Tuner;
using Mono.Cecil;
namespace MonoMac.Tuner {
public class ApplyPreserveAttribute : ApplyPreserveAttributeBase {
protected override string PreserveAttribute {
get { return "MonoMac.Foundation.PreserveAttribute"; }
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Linker;
using Mono.Tuner;
namespace MonoMac.Tuner {
static class Extensions {
const string NSObject = "MonoMac.Foundation.NSObject";
const string INativeObject = "MonoMac.ObjCRuntime.INativeObject";
public static bool IsNSObject (this TypeDefinition type)
{
return type.Inherits (NSObject);
}
public static bool IsNativeObject (this TypeDefinition type)
{
return type.Implements (INativeObject);
}
}
}

View File

@@ -0,0 +1,53 @@
//
// MarkNSObjects.cs
//
// Authors:
// Jb Evain (jbevain@novell.com)
// Sebastien Pouliot <sebastien@xamarin.com>
//
// (C) 2009 Novell, Inc.
// Copyright (C) 2011 Xamarin, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Mono.Tuner;
using Mono.Cecil;
namespace MonoMac.Tuner {
public class MarkNSObjects : MarkNSObjectsBase {
protected override string ExportAttribute {
get { return "MonoMac.Foundation.ExportAttribute"; }
}
public override void ProcessType (TypeDefinition type)
{
if (!type.IsNSObject () || !type.IsNativeObject ())
return;
base.ProcessType (type);
}
}
}

View File

@@ -0,0 +1,382 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Linker;
using Mono.Linker.Steps;
using Mono.Tuner;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace MonoMac.Tuner {
public class MethodMapInjection : BaseStep {
struct ExportedMethod {
public readonly CustomAttribute attribute;
public readonly MethodDefinition method;
public ExportedMethod (CustomAttribute attribute, MethodDefinition method)
{
this.attribute = attribute;
this.method = method;
}
}
ModuleDefinition module;
bool imported;
TypeReference void_type;
TypeReference dictionary_intptr_methoddesc;
MethodReference dictionary_intptr_methoddesc_ctor;
MethodReference dictionary_intptr_methoddesc_set_item;
MethodReference methoddesc_ctor;
MethodReference selector_get_handle;
MethodReference methodbase_get_method_from_handle;
MethodReference class_register_methods;
MethodReference type_get_type_from_handle;
FieldReference selector_init;
protected override void ProcessAssembly (AssemblyDefinition assembly)
{
if (Annotations.GetAction (assembly) != AssemblyAction.Link)
return;
module = assembly.MainModule;
foreach (TypeDefinition type in module.GetAllTypes ()) {
if (!type.IsNSObject ())
continue;
ProcessNSObject (type);
}
imported = false;
}
void PrepareImports ()
{
if (imported)
return;
var corlib = Context.GetAssembly ("mscorlib");
void_type = Import (corlib, "System.Void");
var monomac = Context.GetAssembly ("MonoMac");
var dictionary = Import (corlib, "System.Collections.Generic.Dictionary`2");
var intptr = Import (corlib, "System.IntPtr");
var method_desc = Import (monomac, "MonoMac.ObjCRuntime.MethodDescription");
var dic_i_md = new GenericInstanceType (dictionary);
dic_i_md.GenericArguments.Add (intptr);
dic_i_md.GenericArguments.Add (method_desc);
dictionary_intptr_methoddesc = dic_i_md;
dictionary_intptr_methoddesc_ctor = Import (".ctor", dic_i_md, false, void_type, Import (corlib, "System.Int32"));
dictionary_intptr_methoddesc_set_item = Import ("set_Item", dic_i_md, false, void_type,
dictionary.GenericParameters [0],
dictionary.GenericParameters [1]);
methoddesc_ctor = Import (".ctor", method_desc, false, void_type,
Import (corlib, "System.Reflection.MethodBase"),
Import (monomac, "MonoMac.ObjCRuntime.ArgumentSemantic"));
var selector = Import (monomac, "MonoMac.ObjCRuntime.Selector");
selector_get_handle = Import ("GetHandle", selector, true, intptr, Import (corlib, "System.String"));
selector_init = new FieldReference ("Init", selector, intptr);
var methodbase = Import (corlib, "System.Reflection.MethodBase");
methodbase_get_method_from_handle = Import ("GetMethodFromHandle", methodbase, true, methodbase, Import (corlib, "System.RuntimeMethodHandle"));
var type = Import (corlib, "System.Type");
type_get_type_from_handle = Import ("GetTypeFromHandle", type, true, type, Import (corlib, "System.RuntimeTypeHandle"));
var @class = Import (monomac, "MonoMac.ObjCRuntime.Class");
class_register_methods = Import ("RegisterMethods", @class, true, void_type, type, dic_i_md);
imported = true;
}
MethodReference Import (string name, TypeReference declaring_type, bool @static, TypeReference return_type, params TypeReference [] parameters_type)
{
var reference = new MethodReference (name, return_type, declaring_type) {
HasThis = !@static,
ExplicitThis = false,
CallingConvention = MethodCallingConvention.Default,
};
foreach (var parameter_type in parameters_type)
reference.Parameters.Add (new ParameterDefinition (parameter_type));
return reference;
}
TypeReference Import (TypeReference type)
{
return module.Import (type);
}
TypeReference Import (AssemblyDefinition assembly, string type_name)
{
return Import (assembly.MainModule.GetType (type_name));
}
void ProcessNSObject (TypeDefinition type)
{
var exported = new List<ExportedMethod> ();
if (type.HasMethods) {
ProcessMethods (type, exported);
ProcessConstructors (type, exported);
}
if (exported.Count == 0)
return;
InjectMethodMap (type, exported);
}
void InjectMethodMap (TypeDefinition type, List<ExportedMethod> exported_methods)
{
PrepareImports ();
var cctor = GetTypeConstructor (type);
var selectors = MapSelectors (cctor);
var map = new VariableDefinition (dictionary_intptr_methoddesc);
map.Name = "$method_map";
cctor.Body.Variables.Add (map);
cctor.Body.SimplifyMacros ();
var il = cctor.Body.GetILProcessor ();
var instructions = new List<Instruction> {
il.Create (OpCodes.Ldc_I4, exported_methods.Count),
il.Create (OpCodes.Newobj, dictionary_intptr_methoddesc_ctor),
il.Create (OpCodes.Stloc, map),
};
foreach (var exported in exported_methods) {
instructions.Add (il.Create (OpCodes.Ldloc, map));
if (!IsDefaultConstructor (exported)) {
var selector_name = GetSelectorName (exported);
FieldReference selector;
if (selectors != null && selectors.TryGetValue (selector_name, out selector)) {
instructions.Add (il.Create (OpCodes.Ldsfld, selector));
} else {
instructions.AddRange (new [] {
il.Create (OpCodes.Ldstr, selector_name),
il.Create (OpCodes.Call, selector_get_handle),
});
}
} else
instructions.Add (il.Create (OpCodes.Ldsfld, selector_init));
instructions.AddRange (new [] {
il.Create (OpCodes.Ldtoken, exported.method),
il.Create (OpCodes.Call, methodbase_get_method_from_handle),
il.Create (OpCodes.Ldc_I4, GetArgumentSemantic (exported)),
il.Create (OpCodes.Newobj, methoddesc_ctor),
il.Create (OpCodes.Callvirt, dictionary_intptr_methoddesc_set_item),
});
}
instructions.AddRange (new [] {
il.Create (OpCodes.Ldtoken, type),
il.Create (OpCodes.Call, type_get_type_from_handle),
il.Create (OpCodes.Ldloc, map),
il.Create (OpCodes.Call, class_register_methods),
});
Append (il, instructions);
cctor.Body.OptimizeMacros ();
}
static Dictionary<string, FieldReference> MapSelectors (MethodDefinition cctor)
{
var instructions = cctor.Body.Instructions;
Dictionary<string, FieldReference> selectors = null;
for (int i = 0; i < instructions.Count; i++) {
var instruction = instructions [i];
FieldReference field;
if (!IsCreateSelector (instruction, out field))
continue;
if (selectors == null)
selectors = new Dictionary<string, FieldReference> ();
selectors.Add ((string) instruction.Operand, field);
}
return selectors;
}
static bool IsCreateSelector (Instruction instruction, out FieldReference field)
{
field = null;
if (instruction.OpCode != OpCodes.Ldstr)
return false;
if (instruction.Next == null)
return false;
instruction = instruction.Next;
if (instruction.OpCode != OpCodes.Call)
return false;
var method = (MethodReference) instruction.Operand;
if (method.DeclaringType.Name != "Selector")
return false;
if (method.Name != "GetHandle" && method.Name != "sel_registerName")
return false;
if (instruction.Next == null)
return false;
instruction = instruction.Next;
if (instruction.OpCode != OpCodes.Stsfld)
return false;
field = instruction.Operand as FieldReference;
return true;
}
static bool IsDefaultConstructor (ExportedMethod exported)
{
return exported.attribute == null && exported.method.IsConstructor && !exported.method.IsStatic;
}
static void Append (ILProcessor il, IEnumerable<Instruction> instructions)
{
var method_instructions = il.Body.Instructions;
var last = method_instructions [method_instructions.Count - 1];
foreach (var instruction in instructions)
il.InsertBefore (last, instruction);
}
static int GetArgumentSemantic (ExportedMethod exported)
{
if (exported.attribute == null)
return 0; // Assign
var arguments = exported.attribute.ConstructorArguments;
if (arguments.Count == 2)
return (int) arguments [1].Value;
if (arguments.Count == 1)
return -1; // None
return 0; // Assign
}
static string GetSelectorName (ExportedMethod exported)
{
var arguments = exported.attribute.ConstructorArguments;
if (arguments.Count == 0)
return exported.method.Name;
return (string) arguments [0].Value;
}
MethodDefinition GetTypeConstructor (TypeDefinition type)
{
return type.GetTypeConstructor () ?? CreateTypeConstructor (type);
}
MethodDefinition CreateTypeConstructor (TypeDefinition type)
{
var cctor = new MethodDefinition (".cctor", MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, void_type);
cctor.Body.GetILProcessor ().Emit (OpCodes.Ret);
type.Methods.Add (cctor);
return cctor;
}
void ProcessConstructors (TypeDefinition type, List<ExportedMethod> exported)
{
foreach (MethodDefinition ctor in type.GetConstructors ()) {
if (!ctor.HasParameters && !ctor.IsStatic) {
exported.Add (new ExportedMethod (null, ctor));
continue;
}
CustomAttribute export;
if (!TryGetExportAttribute (ctor, out export))
continue;
exported.Add (new ExportedMethod (export, ctor));
}
}
static bool TryGetExportAttribute (MethodDefinition method, out CustomAttribute export)
{
export = null;
if (!method.HasCustomAttributes)
return false;
foreach (CustomAttribute attribute in method.CustomAttributes) {
if (attribute.AttributeType.FullName != "MonoMac.Foundation.ExportAttribute")
continue;
export = attribute;
return true;
}
return false;
}
void ProcessMethods (TypeDefinition type, List<ExportedMethod> exported)
{
foreach (MethodDefinition method in type.GetMethods ()) {
CustomAttribute attribute;
if (TryGetExportAttribute (method, out attribute)) {
exported.Add (new ExportedMethod (attribute, method));
continue;
}
if (!method.IsVirtual)
continue;
var bases = Annotations.GetBaseMethods (method);
if (bases == null)
continue;
foreach (MethodDefinition @base in bases) {
if (@base.DeclaringType.IsInterface)
continue;
if (TryGetExportAttribute (@base, out attribute)) {
exported.Add (new ExportedMethod (attribute, method));
break;
}
}
}
}
}
}

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8" ?>
<linker>
<assembly fullname="MonoMac">
<namespace fullname="MonoMac.ObjCRuntime" />
<!--
<type fullname="MonoMac.ObjCRuntime.Runtime" />
<type fullname="MonoMac.ObjCRuntime.Class" />
<type fullname="MonoMac.ObjCRuntime.Selector" />
<type fullname="MonoMac.ObjCRuntime.NativeConstructorBuilder" />
<type fullname="MonoMac.ObjCRuntime.NativeImplementationBuilder" />
<type fullname="MonoMac.ObjCRuntime.NativeMethodBuilder" />
<type fullname="MonoMac.ObjCRuntime.INativeObject" />
-->
<type fullname="MonoMac.Foundation.NSObject" preserve="fields">
<method name="NativeRelease" />
<method name="NativeRetain" />
<method name="Retain" />
</type>
<type fullname="MonoMac.Foundation.NSArray" preserve="fields">
<method name="ArrayFromHandle" />
<method name="StringArrayFromHandle" />
<method name="FromNSObjects" />
<method name="FromStrings" />
</type>
<type fullname="MonoMac.Foundation.ExportAttribute" />
</assembly>
<assembly fullname="mscorlib">
<type fullname="System.Runtime.Serialization.FormatterServices">
<method name="GetUninitializedObject" />
</type>
<type fullname="System.Runtime.InteropServices.Marshal">
<method name="StructureToPtr" />
</type>
<type fullname="System.Runtime.InteropServices.MarshalAsAttribute">
<field name="MarshalTypeRef" />
</type>
</assembly>
</linker>

View File

@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using Mono.Tuner;
using Mono.Cecil;
namespace MonoMac.Tuner {
class MonoMacProfile : Profile {
static readonly HashSet<string> Sdk = new HashSet<string> {
"mscorlib",
"I18N.CJK",
"I18N",
"I18N.MidEast",
"I18N.Other",
"I18N.Rare",
"I18N.West",
"Microsoft.Build.Engine",
"Microsoft.Build.Framework",
"Microsoft.Build.Tasks.v4.0",
"Microsoft.Build.Utilities.v4.0",
"Microsoft.CSharp",
"Microsoft.Web.Infrastructure",
"Mono.C5",
"Mono.Cairo",
"Mono.CodeContracts",
"Mono.CompilerServices.SymbolWriter",
"Mono.Configuration.Crypto",
"Mono.CSharp",
"Mono.Data.Sqlite",
"Mono.Data.Tds",
"Mono.Debugger.Soft",
"Mono.Http",
"Mono.Management",
"Mono.Messaging",
"Mono.Messaging.RabbitMQ",
"Mono.Options",
"Mono.Parallel",
"Mono.Posix",
"Mono.Security",
"Mono.Security.Win32",
"Mono.Simd",
"Mono.Tasklets",
"Mono.Tuner",
"Mono.WebBrowser",
"Mono.Web",
"Novell.Directory.Ldap",
"Npgsql",
"OpenSystem.C",
"PEAPI",
"System.ComponentModel.Composition",
"System.ComponentModel.DataAnnotations",
"System.Configuration",
"System.Configuration.Install",
"System.Core",
"System.Data.DataSetExtensions",
"System.Data",
"System.Data.Linq",
"System.Data.OracleClient",
"System.Data.Services.Client",
"System.Data.Services",
"System.Design",
"System.DirectoryServices",
"System",
"System.Drawing.Design",
"System.Drawing",
"System.Dynamic",
"System.EnterpriseServices",
"System.IdentityModel",
"System.IdentityModel.Selectors",
"System.Management",
"System.Messaging",
"System.Net",
"System.Numerics",
"System.Runtime.Caching",
"System.Runtime.DurableInstancing",
"System.Runtime.Remoting",
"System.Runtime.Serialization",
"System.Runtime.Serialization.Formatters.Soap",
"System.Security",
"System.ServiceModel.Discovery",
"System.ServiceModel",
"System.ServiceModel.Routing",
"System.ServiceModel.Web",
"System.ServiceProcess",
"System.Transactions",
"System.Web.Abstractions",
"System.Web.ApplicationServices",
"System.Web",
"System.Web.DynamicData",
"System.Web.Extensions.Design",
"System.Web.Extensions",
"System.Web.Routing",
"System.Web.Services",
"System.Windows.Forms.DataVisualization",
"System.Windows.Forms",
"System.Xaml",
"System.Xml",
"System.Xml.Linq",
"WebMatrix.Data",
"WindowsBase",
"Microsoft.VisualBasic",
};
protected override bool IsSdk (AssemblyDefinition assembly)
{
return Sdk.Contains (assembly.Name.Name);
}
protected override bool IsProduct (AssemblyDefinition assembly)
{
return assembly.Name.Name == "MonoMac";
}
}
}

View File

@@ -0,0 +1,189 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Linker;
using Mono.Linker.Steps;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Tuner;
namespace MonoMac.Tuner {
public class RemoveSelectors : IStep {
public void Process (LinkContext context)
{
AssemblyDefinition monomac;
if (!context.TryGetLinkedAssembly ("MonoMac", out monomac))
return;
foreach (TypeDefinition type in monomac.MainModule.Types) {
if (!type.IsNSObject ())
continue;
ProcessNSObject (type);
}
}
static void ProcessNSObject (TypeDefinition type)
{
var selectors = PopulateSelectors (type);
if (selectors == null)
return;
foreach (var method in CollectMethods (type))
CheckSelectorUsage (method, selectors);
if (selectors.Count == 0)
return;
PatchStaticConstructor (type, selectors);
RemoveUnusedSelectors (type, selectors);
}
static void CheckSelectorUsage (MethodDefinition method, HashSet<FieldDefinition> selectors)
{
if (!method.HasBody)
return;
foreach (Instruction instruction in method.Body.Instructions) {
switch (instruction.OpCode.OperandType) {
case OperandType.InlineTok:
case OperandType.InlineField:
var field = instruction.Operand as FieldDefinition;
if (field == null)
continue;
if (selectors.Contains (field))
selectors.Remove (field);
break;
}
}
}
static void PatchStaticConstructor (TypeDefinition type, HashSet<FieldDefinition> selectors)
{
var cctor = type.GetTypeConstructor ();
if (cctor == null || !cctor.HasBody)
return;
var instructions = cctor.Body.Instructions;
for (int i = 0; i < instructions.Count; i++) {
var instruction = instructions [i];
if (!IsCreateSelector (instruction, selectors))
continue;
instructions.RemoveAt (i--);
instructions.RemoveAt (i--);
instructions.RemoveAt (i--);
}
}
static bool IsCreateSelector (Instruction instruction, HashSet<FieldDefinition> selectors)
{
if (instruction.OpCode != OpCodes.Stsfld)
return false;
var field = instruction.Operand as FieldDefinition;
if (field == null)
return false;
if (!selectors.Contains (field))
return false;
instruction = instruction.Previous;
if (instruction == null)
return false;
if (instruction.OpCode != OpCodes.Call)
return false;
if (!IsRegisterSelector (instruction.Operand as MethodReference))
return false;
instruction = instruction.Previous;
if (instruction == null)
return false;
if (instruction.OpCode != OpCodes.Ldstr)
return false;
return true;
}
static bool IsRegisterSelector (MethodReference method)
{
if (method == null)
return false;
if (method.Name != "GetHandle" && method.Name != "sel_registerName")
return false;
if (method.DeclaringType.FullName != "MonoMac.ObjCRuntime.Selector")
return false;
return true;
}
static void RemoveUnusedSelectors (TypeDefinition type, HashSet<FieldDefinition> selectors)
{
var fields = type.Fields;
for (int i = 0; i < fields.Count; i++)
if (selectors.Contains (fields [i]))
fields.RemoveAt (i--);
}
static HashSet<FieldDefinition> PopulateSelectors (TypeDefinition type)
{
if (!type.HasFields)
return null;
HashSet<FieldDefinition> selectors = null;
foreach (FieldDefinition field in type.Fields) {
if (!IsSelector (field))
continue;
if (selectors == null)
selectors = new HashSet<FieldDefinition> ();
selectors.Add (field);
}
return selectors;
}
static bool IsSelector (FieldDefinition field)
{
if (!field.IsStatic)
return false;
if (field.FieldType.FullName != "System.IntPtr")
return false;
if (!field.Name.StartsWith ("sel"))
return false;
return true;
}
static IEnumerable<MethodDefinition> CollectMethods (TypeDefinition type)
{
if (!type.HasMethods)
yield break;
foreach (MethodDefinition method in type.Methods) {
if (method.IsStatic && method.IsConstructor)
continue;
yield return method;
}
}
}
}