xamarin-macios/tools/linker/ObjCExtensions.cs

217 строки
8.0 KiB
C#
Исходник Обычный вид История

2016-04-21 15:57:02 +03:00
// Copyright 2013 Xamarin Inc. All rights reserved.
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Tuner;
using Xamarin.Tuner;
2016-04-21 15:57:02 +03:00
namespace Xamarin.Linker {
static class Namespaces {
internal static void Initialize ()
{
if (AddressBook != null)
return;
var profile = (Profile.Current as BaseProfile);
AddressBook = profile.GetNamespace ("AddressBook");
AVFoundation = profile.GetNamespace ("AVFoundation");
CoreAnimation = profile.GetNamespace ("CoreAnimation");
CoreBluetooth = profile.GetNamespace ("CoreBluetooth");
CoreFoundation = profile.GetNamespace ("CoreFoundation");
CoreLocation = profile.GetNamespace ("CoreLocation");
CoreText = profile.GetNamespace ("CoreText");
Foundation = profile.GetNamespace ("Foundation");
GameKit = profile.GetNamespace ("GameKit");
ObjCRuntime = profile.GetNamespace ("ObjCRuntime");
Security = profile.GetNamespace ("Security");
StoreKit = profile.GetNamespace ("StoreKit");
GameController = profile.GetNamespace ("GameController");
JavaScriptCore = profile.GetNamespace ("JavaScriptCore");
CoreAudioKit = profile.GetNamespace ("CoreAudioKit");
InputMethodKit = profile.GetNamespace ("InputMethodKit");
OpenAL = profile.GetNamespace ("OpenAL");
MediaAccessibility = profile.GetNamespace ("MediaAccessibility");
CoreMIDI = profile.GetNamespace ("CoreMIDI");
MediaLibrary = profile.GetNamespace ("MediaLibrary");
GLKit = profile.GetNamespace ("GLKit");
SpriteKit = profile.GetNamespace ("SpriteKit");
CloudKit = profile.GetNamespace ("CloudKit");
LocalAuthentication = profile.GetNamespace ("LocalAuthentication");
Accounts = profile.GetNamespace ("Accounts");
Contacts = profile.GetNamespace ("Contacts");
ContactsUI = profile.GetNamespace ("ContactsUI");
MapKit = profile.GetNamespace ("MapKit");
EventKit = profile.GetNamespace ("EventKit");
Social = profile.GetNamespace ("Social");
AVKit = profile.GetNamespace ("AVKit");
VideoToolbox = profile.GetNamespace ("VideoToolbox");
GameplayKit = profile.GetNamespace ("GameplayKit");
NetworkExtension = profile.GetNamespace ("NetworkExtension");
MultipeerConnectivity = profile.GetNamespace ("MultipeerConnectivity");
MetalKit = profile.GetNamespace ("MetalKit");
[MetalPerformanceShaders] Xcode 9 bindings (#3005) * [MetalPerformanceShaders] Activate bindings for Xamarin.Mac and add n… (#2816) * [MetalPerformaceShaders] Several MPSCnnKernel properties should be readonly (#2938) The subclasses versions of the properties need Override, cannot be removed since it would break visibility for iOS 10 * Remove some [Model] attributes that sholdn't be needed * Fix introspection test crashes * More introspection fixes * NN does not need to be PascalCased Remove unneeded Models and BaseTypes * PR Whitespace fixes and renamings * Paste fail * More fixes from PR comments * [MPS] Adds new intro test, fixes ctors and xtro output * Removes duplicated availability attributes. * Removes obsoleted API from macOS since mps is new to it. * Fixes xtro output. * Adds missing API. * Fixes parameterless ctors, some of them do not really work, found by our new intro test and disabled the one that seem to not make sense due to the presence of DesignatedInitializers. * Fixes a selector typo. * Adds new `ShouldNotExposeDefaultCtorTest` to intro. ShouldNotExposeDefaultCtorTest ============================== This test checks for types with a parameterless ctor that are subclasses of `NSObject` and then cheks if the BaseType of said objects also expose a parameterless ctor (all in .NET land), if this is not the case it reports them and so they can manually audited. Also this test has the ability to print alloc/init ObjC code by setting `genObjCTestCode` to `true` so you can take this code into an Xcode project and easily tests the ctors. It seems that xtro (sharpie) does not have a complete picture of when a ctor must be exposed hence the hability to generate this code and manually test. Right now this test is just enabled for MPS since it is the scope of this PR. In the future it should be enabled for all other frameworks and the output be manually audited. * [MPS] Fixes premature collection possible in bindings (bug 59547) and implements feedback. https://bugzilla.xamarin.com/show_bug.cgi?id=59547 * Fixes premature collection possible in bindings im MPSKernel.cs * Fixes MPSImageHistogramTest from using deprecated API. * Removes renamed selectors and typos from ApiSelectorTest and ApiTypoTest. * [MPS] Reenable Copy API and DesignatedInitializer xtro feedback * Implement more feedback * More feedback
2017-11-28 23:29:05 +03:00
MetalPerformanceShaders = profile.GetNamespace ("MetalPerformanceShaders");
ModelIO = profile.GetNamespace ("ModelIO");
Intents = profile.GetNamespace ("Intents");
Photos = profile.GetNamespace ("Photos");
CoreML = profile.GetNamespace ("CoreML");
Vision = profile.GetNamespace ("Vision");
IOSurface = profile.GetNamespace ("IOSurface");
PdfKit = profile.GetNamespace ("PdfKit");
[linker] Improve inlining of IsDirectBinding check to inline both true and false values. (#3214) Previous behavior ================= * The linker would determine if a class is a generated binding class or not. This was determined by the presence of a constructor taking a single IntPtr argument, and with a [CompilerGenerated] attribute. * If a class was not a generated binding class, then that class and all its superclasses were marked as not optimizable (in the context of inlining the IsDirectBinding check). * The end result was that all classes with a [CompilerGenerated] IntPtr constructor that weren't subclassed, were optimized (the IsDirectBinding value was implied to be 'true'). Unfortunately this does not match how the IsDirectBinding value is actually computed, and is in many cases quite wrong. Background ========== The authorative value for the IsDirectBinding value is the register attribute: ```csharp [Register ("MyClass", true)] // the second parameter specifies the IsDirectBinding value class MyClass : NSObject {} ``` Due to history this second parameter is called `IsWrapper` and not `IsDirectBinding`, but it's the exact same thing. Unfortunately looking up this attribute every time a class is instantiated is slow (since fetching attributes is slow), so we guess this value in NSObject's initialization: if the actual type of the object is in the platform assembly, then we assume IsDirectBinding=true: ```csharp IsDirectBinding = (this.GetType ().Assembly == PlatformAssembly); ``` and any subclasses in the platform assembly which is not a direct binding have to set the correct value in their constructors. New behavior ============ In the linker we now track three states for the IsDirectBinding value for each class: if it can be inlined into a constant true or false, or if it has to be checked at runtime (a nullable bool is used, and null corresponds with this last undetermined state). * The linker will look at the `[Register]` attribute for a class, and: * If the type is CIFilter, store that IsDirectBinding=undetermined. * If IsWrapper=False, store that IsDirectBinding=False for that class, and that IsDirectBinding=undetermined for all super classes where IsWrapper=True. * If IsWrapper=True, tentatively assume IsDirectBinding=True in that class unless already determined to be undetermined (which will be overruled if a non-wrapper subclass is found later). Results ======= For monotouch-test, the changes are as follows: * Classes we can now assume IsDirectBinding=true: https://gist.github.com/rolfbjarne/acd6a8cf1236562a832d6db9400afee9#file-foo-diff-L1-L25 * Classes we previously assumed incorrectly that IsDirectBinding=true: https://gist.github.com/rolfbjarne/acd6a8cf1236562a832d6db9400afee9#file-foo-diff-L27-L645 * Classes we can now assume IsDirectBinding=false: https://gist.github.com/rolfbjarne/acd6a8cf1236562a832d6db9400afee9#file-foo-diff-L647-L2281 There are also minor size improvements (in the iPhone/Debug64 configuration): The executable is 17.632 bytes smaller: -rwxr-xr-x 1 rolf staff 73038384 Jan 12 12:40 /Users/rolf/test/old/monotouchtest.app/monotouchtest -rwxr-xr-x 1 rolf staff 73020752 Jan 12 12:50 /Users/rolf/test/new/monotouchtest.app/monotouchtest Xamarin.iOS.dll is 3.072 bytes smaller (this will probably be 0 on a release (stripped) build). -rw-r--r-- 1 rolf staff 2522624 Jan 12 12:40 /Users/rolf/test/old/monotouchtest.app/Xamarin.iOS.dll -rw-r--r-- 1 rolf staff 2519552 Jan 12 12:50 /Users/rolf/test/new/monotouchtest.app/Xamarin.iOS.dll CIFilter ======== There's a complication with CIFilters [1] [2], their implementation is somewhat special, so we do not want to optimize anything for those classes to not risk getting anything wrong. [1] https://github.com/xamarin/xamarin-macios/pull/3055 [2] https://bugzilla.xamarin.com/show_bug.cgi?id=15465
2018-01-15 14:28:34 +03:00
CoreImage = profile.GetNamespace ("CoreImage");
2016-04-21 15:57:02 +03:00
#if MONOMAC
PhotosUI = profile.GetNamespace ("PhotosUI");
IOBluetooth = profile.GetNamespace ("IOBluetooth");
IOBluetoothUI = profile.GetNamespace ("IOBluetoothUI");
FinderSync = profile.GetNamespace ("FinderSync");
NotificationCenter = profile.GetNamespace ("NotificationCenter");
2016-04-21 15:57:02 +03:00
AppKit = profile.GetNamespace ("AppKit");
CoreWlan = profile.GetNamespace ("CoreWlan");
ImageKit = profile.GetNamespace ("ImageKit");
QTKit = profile.GetNamespace ("QTKit");
QuartzComposer = profile.GetNamespace ("QuartzComposer");
SceneKit = profile.GetNamespace ("SceneKit");
ScriptingBridge = profile.GetNamespace ("ScriptingBridge");
WebKit = profile.GetNamespace ("WebKit");
MediaPlayer = profile.GetNamespace ("MediaPlayer");
PrintCore = profile.GetNamespace ("PrintCore");
ExternalAccessory = profile.GetNamespace ("ExternalAccessory");
2016-04-21 15:57:02 +03:00
#else
Registrar = profile.GetNamespace ("Registrar");
UIKit = profile.GetNamespace ("UIKit");
#endif
}
public static string JavaScriptCore { get; private set; }
public static string CoreAudioKit { get; private set; }
public static string InputMethodKit { get; private set; }
public static string OpenAL { get; private set; }
public static string MediaAccessibility { get; private set; }
public static string CoreMIDI { get; private set; }
public static string MediaLibrary { get; private set; }
public static string GLKit { get; private set; }
public static string SpriteKit { get; private set; }
public static string CloudKit { get; private set; }
public static string LocalAuthentication { get; private set; }
public static string Accounts { get; private set; }
public static string Contacts { get; private set; }
public static string ContactsUI { get; private set; }
public static string MapKit { get; private set; }
public static string EventKit { get; private set; }
public static string Social { get; private set; }
public static string AVKit { get; private set; }
public static string VideoToolbox { get; private set; }
public static string GameplayKit { get; private set; }
public static string NetworkExtension { get; private set; }
public static string MultipeerConnectivity { get; private set; }
public static string MetalKit { get; private set; }
[MetalPerformanceShaders] Xcode 9 bindings (#3005) * [MetalPerformanceShaders] Activate bindings for Xamarin.Mac and add n… (#2816) * [MetalPerformaceShaders] Several MPSCnnKernel properties should be readonly (#2938) The subclasses versions of the properties need Override, cannot be removed since it would break visibility for iOS 10 * Remove some [Model] attributes that sholdn't be needed * Fix introspection test crashes * More introspection fixes * NN does not need to be PascalCased Remove unneeded Models and BaseTypes * PR Whitespace fixes and renamings * Paste fail * More fixes from PR comments * [MPS] Adds new intro test, fixes ctors and xtro output * Removes duplicated availability attributes. * Removes obsoleted API from macOS since mps is new to it. * Fixes xtro output. * Adds missing API. * Fixes parameterless ctors, some of them do not really work, found by our new intro test and disabled the one that seem to not make sense due to the presence of DesignatedInitializers. * Fixes a selector typo. * Adds new `ShouldNotExposeDefaultCtorTest` to intro. ShouldNotExposeDefaultCtorTest ============================== This test checks for types with a parameterless ctor that are subclasses of `NSObject` and then cheks if the BaseType of said objects also expose a parameterless ctor (all in .NET land), if this is not the case it reports them and so they can manually audited. Also this test has the ability to print alloc/init ObjC code by setting `genObjCTestCode` to `true` so you can take this code into an Xcode project and easily tests the ctors. It seems that xtro (sharpie) does not have a complete picture of when a ctor must be exposed hence the hability to generate this code and manually test. Right now this test is just enabled for MPS since it is the scope of this PR. In the future it should be enabled for all other frameworks and the output be manually audited. * [MPS] Fixes premature collection possible in bindings (bug 59547) and implements feedback. https://bugzilla.xamarin.com/show_bug.cgi?id=59547 * Fixes premature collection possible in bindings im MPSKernel.cs * Fixes MPSImageHistogramTest from using deprecated API. * Removes renamed selectors and typos from ApiSelectorTest and ApiTypoTest. * [MPS] Reenable Copy API and DesignatedInitializer xtro feedback * Implement more feedback * More feedback
2017-11-28 23:29:05 +03:00
public static string MetalPerformanceShaders { get; private set; }
public static string ModelIO { get; private set; }
2016-04-21 15:57:02 +03:00
public static string AddressBook { get; private set; }
public static string AVFoundation { get; private set; }
public static string CoreAnimation { get; private set; }
public static string CoreBluetooth { get; private set; }
public static string CoreFoundation { get; private set; }
public static string CoreLocation { get; private set; }
public static string CoreText { get; private set; }
public static string Foundation { get; private set; }
public static string GameKit { get; private set; }
public static string GameController { get; private set; }
2016-04-21 15:57:02 +03:00
public static string ObjCRuntime { get; private set; }
public static string Security { get; private set; }
public static string StoreKit { get; private set; }
public static string Intents { get; private set; }
public static string Photos { get; private set; }
public static string CoreML { get; private set; }
public static string Vision { get; private set; }
public static string IOSurface { get; private set; }
public static string PdfKit { get; private set; }
[linker] Improve inlining of IsDirectBinding check to inline both true and false values. (#3214) Previous behavior ================= * The linker would determine if a class is a generated binding class or not. This was determined by the presence of a constructor taking a single IntPtr argument, and with a [CompilerGenerated] attribute. * If a class was not a generated binding class, then that class and all its superclasses were marked as not optimizable (in the context of inlining the IsDirectBinding check). * The end result was that all classes with a [CompilerGenerated] IntPtr constructor that weren't subclassed, were optimized (the IsDirectBinding value was implied to be 'true'). Unfortunately this does not match how the IsDirectBinding value is actually computed, and is in many cases quite wrong. Background ========== The authorative value for the IsDirectBinding value is the register attribute: ```csharp [Register ("MyClass", true)] // the second parameter specifies the IsDirectBinding value class MyClass : NSObject {} ``` Due to history this second parameter is called `IsWrapper` and not `IsDirectBinding`, but it's the exact same thing. Unfortunately looking up this attribute every time a class is instantiated is slow (since fetching attributes is slow), so we guess this value in NSObject's initialization: if the actual type of the object is in the platform assembly, then we assume IsDirectBinding=true: ```csharp IsDirectBinding = (this.GetType ().Assembly == PlatformAssembly); ``` and any subclasses in the platform assembly which is not a direct binding have to set the correct value in their constructors. New behavior ============ In the linker we now track three states for the IsDirectBinding value for each class: if it can be inlined into a constant true or false, or if it has to be checked at runtime (a nullable bool is used, and null corresponds with this last undetermined state). * The linker will look at the `[Register]` attribute for a class, and: * If the type is CIFilter, store that IsDirectBinding=undetermined. * If IsWrapper=False, store that IsDirectBinding=False for that class, and that IsDirectBinding=undetermined for all super classes where IsWrapper=True. * If IsWrapper=True, tentatively assume IsDirectBinding=True in that class unless already determined to be undetermined (which will be overruled if a non-wrapper subclass is found later). Results ======= For monotouch-test, the changes are as follows: * Classes we can now assume IsDirectBinding=true: https://gist.github.com/rolfbjarne/acd6a8cf1236562a832d6db9400afee9#file-foo-diff-L1-L25 * Classes we previously assumed incorrectly that IsDirectBinding=true: https://gist.github.com/rolfbjarne/acd6a8cf1236562a832d6db9400afee9#file-foo-diff-L27-L645 * Classes we can now assume IsDirectBinding=false: https://gist.github.com/rolfbjarne/acd6a8cf1236562a832d6db9400afee9#file-foo-diff-L647-L2281 There are also minor size improvements (in the iPhone/Debug64 configuration): The executable is 17.632 bytes smaller: -rwxr-xr-x 1 rolf staff 73038384 Jan 12 12:40 /Users/rolf/test/old/monotouchtest.app/monotouchtest -rwxr-xr-x 1 rolf staff 73020752 Jan 12 12:50 /Users/rolf/test/new/monotouchtest.app/monotouchtest Xamarin.iOS.dll is 3.072 bytes smaller (this will probably be 0 on a release (stripped) build). -rw-r--r-- 1 rolf staff 2522624 Jan 12 12:40 /Users/rolf/test/old/monotouchtest.app/Xamarin.iOS.dll -rw-r--r-- 1 rolf staff 2519552 Jan 12 12:50 /Users/rolf/test/new/monotouchtest.app/Xamarin.iOS.dll CIFilter ======== There's a complication with CIFilters [1] [2], their implementation is somewhat special, so we do not want to optimize anything for those classes to not risk getting anything wrong. [1] https://github.com/xamarin/xamarin-macios/pull/3055 [2] https://bugzilla.xamarin.com/show_bug.cgi?id=15465
2018-01-15 14:28:34 +03:00
public static string CoreImage { get; private set; }
2016-04-21 15:57:02 +03:00
#if MONOMAC
public static string PhotosUI { get; private set; }
public static string IOBluetooth { get; private set; }
public static string IOBluetoothUI { get; private set; }
public static string FinderSync { get; private set; }
public static string NotificationCenter { get; private set; }
2016-04-21 15:57:02 +03:00
public static string AppKit { get; private set; }
public static string CoreWlan { get; private set; }
public static string ImageKit { get; private set; }
public static string QTKit { get; private set; }
public static string QuartzComposer { get; private set; }
public static string SceneKit { get; private set; }
public static string ScriptingBridge { get; private set; }
public static string WebKit { get; private set; }
public static string MediaPlayer { get; private set; }
public static string PrintCore { get; private set; }
public static string ExternalAccessory { get; private set; }
2016-04-21 15:57:02 +03:00
#else
public static string Registrar { get; private set; }
public static string UIKit { get; private set; }
#endif
}
static class ObjCExtensions {
static string inativeobject;
static string INativeObject {
get {
if (inativeobject == null)
inativeobject = Namespaces.ObjCRuntime + ".INativeObject";
return inativeobject;
}
}
public static bool IsNSObject (this TypeReference type, DerivedLinkContext link_context)
2016-04-21 15:57:02 +03:00
{
return type.Resolve ().IsNSObject (link_context);
2016-04-21 15:57:02 +03:00
}
// warning: *Is* means does 'type' inherits from MonoTouch.Foundation.NSObject ?
public static bool IsNSObject (this TypeDefinition type, DerivedLinkContext link_context)
2016-04-21 15:57:02 +03:00
{
if (link_context?.CachedIsNSObject != null)
return link_context.CachedIsNSObject.Contains (type);
2016-04-21 15:57:02 +03:00
return type.Inherits (Namespaces.Foundation, "NSObject");
}
public static bool IsNativeObject (this TypeDefinition type)
{
return type.Implements (INativeObject);
}
}
}