xamarin-macios/tools/linker/CoreOptimizeGeneratedCode.cs

94 строки
3.0 KiB
C#

// Copyright 2012-2013 Xamarin Inc. All rights reserved.
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Linker;
using Mono.Tuner;
namespace Xamarin.Linker {
public class CoreOptimizeGeneratedCode : BaseSubStep {
protected bool HasGeneratedCode { get; private set; }
public override SubStepTargets Targets {
get { return SubStepTargets.Assembly | SubStepTargets.Type; }
}
public override bool IsActiveFor (AssemblyDefinition assembly)
{
// we're sure "pure" SDK assemblies don't use XamMac.dll (i.e. they are the Product assemblies)
if (Profile.IsSdkAssembly (assembly)) {
#if DEBUG
Console.WriteLine ("Assembly {0} : skipped (SDK)", assembly);
#endif
return false;
}
// process only assemblies where the linker is enabled (e.g. --linksdk, --linkskip)
AssemblyAction action = Annotations.GetAction (assembly);
if (action != AssemblyAction.Link) {
#if DEBUG
Console.WriteLine ("Assembly {0} : skipped ({1})", assembly, action);
#endif
return false;
}
// if the assembly does not refer to [CompilerGeneratedAttribute] then there's not much we can do
HasGeneratedCode = false;
foreach (TypeReference tr in assembly.MainModule.GetTypeReferences ()) {
if (tr.Is ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute")) {
#if DEBUG
Console.WriteLine ("Assembly {0} : processing", assembly);
#endif
HasGeneratedCode = true;
break;
}
}
#if DEBUG
if (!HasGeneratedCode)
Console.WriteLine ("Assembly {0} : no [CompilerGeneratedAttribute] present (applying basic optimizations)", assembly);
#endif
// we always apply the step
return true;
}
public override void ProcessType (TypeDefinition type)
{
// if 'type' inherits from NSObject inside an assembly that has [GeneratedCode]
// or for static types used for optional members (using extensions methods), they can be optimized too
bool extensions = type.IsSealed && type.IsAbstract && type.Name.EndsWith ("_Extensions", StringComparison.Ordinal);
if (!HasGeneratedCode && (type.IsNSObject () || !extensions))
return;
if (type.HasMethods)
ProcessMethods (type.Methods, extensions);
}
// [GeneratedCode] is not enough - e.g. it's used for anonymous delegates even if the
// code itself is not tool/compiler generated
static bool IsExport (ICustomAttributeProvider provider)
{
return provider.HasCustomAttribute (Namespaces.Foundation, "ExportAttribute");
}
void ProcessMethods (IEnumerable<MethodDefinition> c, bool extensions)
{
foreach (MethodDefinition m in c) {
// special processing on generated methods from NSObject-inherited types
// it would be too risky to apply on user-generated code
if (m.HasBody && m.IsGeneratedCode () && (extensions || IsExport (m)))
ProcessMethod (m);
}
}
// less risky to nop-ify if branches are pointing to this instruction
static protected void Nop (Instruction ins)
{
ins.OpCode = OpCodes.Nop;
ins.Operand = null;
}
}
}