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;
|
|
|
|
|
2017-02-10 09:45:42 +03:00
|
|
|
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");
|
2016-07-21 20:58:54 +03:00
|
|
|
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");
|
2017-11-28 23:29:05 +03:00
|
|
|
MetalPerformanceShaders = profile.GetNamespace ("MetalPerformanceShaders");
|
2016-07-21 20:58:54 +03:00
|
|
|
ModelIO = profile.GetNamespace ("ModelIO");
|
2017-04-11 15:18:25 +03:00
|
|
|
Intents = profile.GetNamespace ("Intents");
|
|
|
|
Photos = profile.GetNamespace ("Photos");
|
2017-07-01 01:35:30 +03:00
|
|
|
CoreML = profile.GetNamespace ("CoreML");
|
2017-07-18 19:12:10 +03:00
|
|
|
Vision = profile.GetNamespace ("Vision");
|
2017-09-05 15:57:58 +03:00
|
|
|
IOSurface = profile.GetNamespace ("IOSurface");
|
2017-08-04 16:06:21 +03:00
|
|
|
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
|
2017-10-03 20:59:13 +03:00
|
|
|
PhotosUI = profile.GetNamespace ("PhotosUI");
|
2016-07-21 20:58:54 +03:00
|
|
|
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");
|
2016-12-28 17:46:46 +03:00
|
|
|
MediaPlayer = profile.GetNamespace ("MediaPlayer");
|
2017-04-05 22:38:40 +03:00
|
|
|
PrintCore = profile.GetNamespace ("PrintCore");
|
2017-08-23 22:22:23 +03:00
|
|
|
ExternalAccessory = profile.GetNamespace ("ExternalAccessory");
|
2016-04-21 15:57:02 +03:00
|
|
|
#else
|
|
|
|
Registrar = profile.GetNamespace ("Registrar");
|
|
|
|
UIKit = profile.GetNamespace ("UIKit");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-07-21 20:58:54 +03:00
|
|
|
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; }
|
2017-11-28 23:29:05 +03:00
|
|
|
public static string MetalPerformanceShaders { get; private set; }
|
2016-07-21 20:58:54 +03:00
|
|
|
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; }
|
2016-07-21 20:58:54 +03:00
|
|
|
|
|
|
|
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; }
|
|
|
|
|
2017-04-11 15:18:25 +03:00
|
|
|
public static string Intents { get; private set; }
|
|
|
|
|
|
|
|
public static string Photos { get; private set; }
|
|
|
|
|
2017-07-01 01:35:30 +03:00
|
|
|
public static string CoreML { get; private set; }
|
|
|
|
|
2017-07-18 19:12:10 +03:00
|
|
|
public static string Vision { get; private set; }
|
|
|
|
|
2017-09-05 15:57:58 +03:00
|
|
|
public static string IOSurface { get; private set; }
|
|
|
|
|
2017-08-04 16:06:21 +03:00
|
|
|
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
|
2017-10-03 20:59:13 +03:00
|
|
|
public static string PhotosUI { get; private set; }
|
2016-07-21 20:58:54 +03:00
|
|
|
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; }
|
2016-12-28 17:46:46 +03:00
|
|
|
public static string MediaPlayer { get; private set; }
|
2017-04-05 22:38:40 +03:00
|
|
|
public static string PrintCore { get; private set; }
|
2017-08-23 22:22:23 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-10 09:45:42 +03:00
|
|
|
public static bool IsNSObject (this TypeReference type, DerivedLinkContext link_context)
|
2016-04-21 15:57:02 +03:00
|
|
|
{
|
2017-02-10 09:45:42 +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 ?
|
2017-02-10 09:45:42 +03:00
|
|
|
public static bool IsNSObject (this TypeDefinition type, DerivedLinkContext link_context)
|
2016-04-21 15:57:02 +03:00
|
|
|
{
|
2017-02-10 09:45:42 +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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|