You've already forked linux-packaging-mono
Imported Upstream version 5.0.0.42
Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
This commit is contained in:
parent
1190d13a04
commit
6bdd276d05
21
external/linker/tuner/MonoMac.Tuner/ApplyPreserveAttribute.cs
vendored
Normal file
21
external/linker/tuner/MonoMac.Tuner/ApplyPreserveAttribute.cs
vendored
Normal 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"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
27
external/linker/tuner/MonoMac.Tuner/Extensions.cs
vendored
Normal file
27
external/linker/tuner/MonoMac.Tuner/Extensions.cs
vendored
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
external/linker/tuner/MonoMac.Tuner/MarkNSObjects.cs
vendored
Normal file
53
external/linker/tuner/MonoMac.Tuner/MarkNSObjects.cs
vendored
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
382
external/linker/tuner/MonoMac.Tuner/MethodMapInjection.cs
vendored
Normal file
382
external/linker/tuner/MonoMac.Tuner/MethodMapInjection.cs
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
external/linker/tuner/MonoMac.Tuner/MonoMac.xml
vendored
Normal file
38
external/linker/tuner/MonoMac.Tuner/MonoMac.xml
vendored
Normal 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>
|
||||
117
external/linker/tuner/MonoMac.Tuner/MonoMacProfile.cs
vendored
Normal file
117
external/linker/tuner/MonoMac.Tuner/MonoMacProfile.cs
vendored
Normal 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
189
external/linker/tuner/MonoMac.Tuner/RemoveSelectors.cs
vendored
Normal file
189
external/linker/tuner/MonoMac.Tuner/RemoveSelectors.cs
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user