Граф коммитов

24 Коммитов

Автор SHA1 Сообщение Дата
Rolf Bjarne Kvinge cd60fc7123
[tests] Add .NET version of link all for macOS. (#12436)
This also required changing some linker code to not have platform-specific conditional compilation,
because dotnet-linker is built only once for .NET (same binary for all platforms).
2021-08-17 16:39:43 +02:00
Sebastien Pouliot fccd43f0c2
[dotnet][linker] Remove unused backing fields (#12001)
Problems:

* `Dispose` set the generated backing fields to `null` which means
  the linker will mark every backing fields, even if not used
  elsewhere (generally properties) inside the class

* Backing fields increase the memory footprint of the managed peer
  instance (for the type and all it's subclasses)

* Backing fields also increase the app size. Not a huge problem as
  they are all declared _weakly_ as `NSObject` but still...

Solution:

* When the linker process a `Dispose` method of an `NSObject`
  subclass with the _optimizable_ attribute then we remove the
  method body. This way the linker cannot mark the fields.

* Before saving back the assemblies we replace the cached method
  body and NOP every field that were not marked by something else
  than the `Dispose` method.

```diff
--- a.cs	2021-06-22 16:56:57.000000000 -0400
+++ b.cs	2021-06-22 16:57:00.000000000 -0400
@@ -3107,8 +3107,6 @@

 		private static readonly IntPtr class_ptr = Class.GetHandle("UIApplication");

-		private object __mt_WeakDelegate_var;
-
 		public override IntPtr ClassHandle => class_ptr;

 		[DllImport("__Internal")]
@@ -3141,9 +3139,8 @@
 		protected override void Dispose(bool P_0)
 		{
 			base.Dispose(P_0);
-			if (base.Handle == IntPtr.Zero)
+			if (!(base.Handle == IntPtr.Zero))
 			{
-				__mt_WeakDelegate_var = null;
 			}
 		}
 	}
@@ -3209,10 +3206,6 @@
 	{
 		private static readonly IntPtr class_ptr = Class.GetHandle("UIScreen");

-		private object __mt_FocusedItem_var;
-
-		private object __mt_FocusedView_var;
-
 		public override IntPtr ClassHandle => class_ptr;

 		public virtual CGRect Bounds
@@ -3242,10 +3235,8 @@
 		protected override void Dispose(bool P_0)
 		{
 			base.Dispose(P_0);
-			if (base.Handle == IntPtr.Zero)
+			if (!(base.Handle == IntPtr.Zero))
 			{
-				__mt_FocusedItem_var = null;
-				__mt_FocusedView_var = null;
 			}
 		}
 	}
@@ -3254,10 +3245,6 @@
 	{
 		private static readonly IntPtr class_ptr = Class.GetHandle("UIView");

-		private object __mt_ParentFocusEnvironment_var;
-
-		private object __mt_PreferredFocusedView_var;
-
 		public override IntPtr ClassHandle => class_ptr;

 		public virtual CGRect Bounds
@@ -3303,10 +3290,8 @@
 		protected override void Dispose(bool P_0)
 		{
 			base.Dispose(P_0);
-			if (base.Handle == IntPtr.Zero)
+			if (!(base.Handle == IntPtr.Zero))
 			{
-				__mt_ParentFocusEnvironment_var = null;
-				__mt_PreferredFocusedView_var = null;
 			}
 		}
 	}
@@ -3315,12 +3300,6 @@
 	{
 		private static readonly IntPtr class_ptr = Class.GetHandle("UIViewController");

-		private object __mt_ParentFocusEnvironment_var;
-
-		private object __mt_PreferredFocusedView_var;
-
-		private object __mt_WeakTransitioningDelegate_var;
-
 		public override IntPtr ClassHandle => class_ptr;

 		public virtual UIView View
@@ -3363,11 +3342,8 @@
 		protected override void Dispose(bool P_0)
 		{
 			base.Dispose(P_0);
-			if (base.Handle == IntPtr.Zero)
+			if (!(base.Handle == IntPtr.Zero))
 			{
-				__mt_ParentFocusEnvironment_var = null;
-				__mt_PreferredFocusedView_var = null;
-				__mt_WeakTransitioningDelegate_var = null;
 			}
 		}
 	}
@@ -3376,8 +3352,6 @@
 	{
 		private static readonly IntPtr class_ptr = Class.GetHandle("UIWindow");

-		private object __mt_WindowScene_var;
-
 		public override IntPtr ClassHandle => class_ptr;

 		public virtual UIViewController RootViewController
@@ -3411,9 +3385,8 @@
 		protected override void Dispose(bool P_0)
 		{
 			base.Dispose(P_0);
-			if (base.Handle == IntPtr.Zero)
+			if (!(base.Handle == IntPtr.Zero))
 			{
-				__mt_WindowScene_var = null;
 			}
 		}
 	}
```

* Do not consider bindings with `[Dispose (...)]` as optimizable

Injected code makes it impossible for `bgen` to decide if it's optimizable (or not)
Filed https://github.com/xamarin/xamarin-macios/issues/12150 with more details (and for other similar attributes)
2021-07-21 09:03:25 -04:00
Sebastien Pouliot 6b94c43de6
[dotnet][linker] Fix the elimitation of calls for `UIApplication::EnsureUIThread` (#11523)
Lack of `MONOTOUCH` define in the dotnet csproj [1] made this look for
the AppKit (XM) version.

[1] defining `MONOTOUCH` would have required several more changes.
Simplicity won!

|    Size    | MySingleView.app |
| ----------:|------------------|
|  4,579,985 | legacy           |
| 10,787,541 | dotnet [before](https://gist.github.com/02e072567595088522f376e522e22899) |
| 10,786,829 | dotnet [after](https://gist.github.com/afa5b7d4f9bb281646f050257034be11) |

There are other ways to achieve this with ILLink [2] but again:
Simplicity (by re-using) won!

[2] https://github.com/xamarin/xamarin-macios/issues/11477

--- a.cs	2021-05-12 14:17:13.000000000 -0400
+++ b.cs	2021-05-12 14:17:17.000000000 -0400
@@ -3764,13 +3764,6 @@
 }
 namespace UIKit
 {
-	public class UIKitThreadAccessException : Exception
-	{
-		public UIKitThreadAccessException()
-			: base("UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.")
-		{
-		}
-	}
 	[Register("UIApplication", true)]
 	public class UIApplication : UIResponder
 	{
@@ -3824,14 +3817,6 @@
 			UIApplicationMain(args.Length, args, principal, @delegate);
 		}

-		public static void EnsureUIThread()
-		{
-			if (CheckForIllegalCrossThreadCalls && mainThread != null && mainThread != Thread.CurrentThread)
-			{
-				throw new UIKitThreadAccessException();
-			}
-		}
-
 		protected internal UIApplication(IntPtr handle)
 			: base(handle)
 		{
@@ -3862,7 +3847,6 @@
 		public UIButton(CGRect frame)
 			: base(NSObjectFlag.Empty)
 		{
-			UIApplication.EnsureUIThread();
 			if (base.IsDirectBinding)
 			{
 				InitializeHandle(Messaging.IntPtr_objc_msgSend_CGRect(base.Handle, Selector.GetHandle("initWithFrame:"), frame), "initWithFrame:");
@@ -3876,7 +3860,6 @@
 		[Export("setTitle:forState:")]
 		public virtual void SetTitle(string title, UIControlState forState)
 		{
-			UIApplication.EnsureUIThread();
 			IntPtr arg = NSString.CreateNative(title);
 			if (base.IsDirectBinding)
 			{
@@ -3948,8 +3931,7 @@
 			[Export("bounds")]
 			get
 			{
-				//Discarded unreachable code: IL_002f
-				UIApplication.EnsureUIThread();
+				//Discarded unreachable code: IL_002b
 				if (base.IsDirectBinding)
 				{
 					_ = 8;
@@ -3965,7 +3947,6 @@
 			[Export("mainScreen")]
 			get
 			{
-				UIApplication.EnsureUIThread();
 				return Runtime.GetNSObject<UIScreen>(Messaging.IntPtr_objc_msgSend(class_ptr, Selector.GetHandle("mainScreen")));
 			}
 		}
@@ -4025,7 +4006,6 @@
 		[Export("addSubview:")]
 		public virtual void AddSubview(UIView view)
 		{
-			UIApplication.EnsureUIThread();
 			IntPtr nonNullHandle = NativeObjectExtensions.GetNonNullHandle(view, "view");
 			if (base.IsDirectBinding)
 			{
@@ -4065,7 +4045,6 @@
 			[Export("view", ArgumentSemantic.Retain)]
 			get
 			{
-				UIApplication.EnsureUIThread();
 				if (base.IsDirectBinding)
 				{
 					return Runtime.GetNSObject<UIView>(Messaging.IntPtr_objc_msgSend(base.Handle, Selector.GetHandle("view")));
@@ -4083,7 +4062,6 @@
 		public UIViewController()
 			: base(NSObjectFlag.Empty)
 		{
-			UIApplication.EnsureUIThread();
 			if (base.IsDirectBinding)
 			{
 				InitializeHandle(Messaging.IntPtr_objc_msgSend(base.Handle, Selector.GetHandle("init")), "init");
@@ -4124,7 +4102,6 @@
 			[Export("setRootViewController:", ArgumentSemantic.Retain)]
 			set
 			{
-				UIApplication.EnsureUIThread();
 				IntPtr arg = NativeObjectExtensions.GetHandle(value);
 				if (base.IsDirectBinding)
 				{
@@ -4146,7 +4123,6 @@
 		public UIWindow(CGRect frame)
 			: base(NSObjectFlag.Empty)
 		{
-			UIApplication.EnsureUIThread();
 			if (base.IsDirectBinding)
 			{
 				InitializeHandle(Messaging.IntPtr_objc_msgSend_CGRect(base.Handle, Selector.GetHandle("initWithFrame:"), frame), "initWithFrame:");
@@ -4160,7 +4136,6 @@
 		[Export("makeKeyAndVisible")]
 		public virtual void MakeKeyAndVisible()
 		{
-			UIApplication.EnsureUIThread();
 			if (base.IsDirectBinding)
 			{
 				Messaging.void_objc_msgSend(base.Handle, Selector.GetHandle("makeKeyAndVisible"));
@@ -4188,7 +4163,6 @@
 		public UIApplicationDelegate()
 			: base(NSObjectFlag.Empty)
 		{
-			UIApplication.EnsureUIThread();
 			base.IsDirectBinding = false;
 			InitializeHandle(Messaging.IntPtr_objc_msgSendSuper(base.SuperHandle, Selector.GetHandle("init")), "init");
 		}
```

Co-authored-by: Sebastien Pouliot <sebastien.pouliot@microsoft.com>
2021-05-12 20:18:49 -04:00
Sven Boemer dc320a3606
Update to new linker custom steps API (#11374)
* Update to new linker custom steps API

* PR feedback

- Fix indentation
- Add Initialize(LinkContext) to ExceptionalMarkHandler
- Remove unnecessary ifdef
- Use IsSetter/IsGetter
- Use [0] instead of Single()
- Avoid allocating empty collections

* Note override issue

* Clean up comments

* Move `DynamicRegistrationSupported` change earlier, along with the
detection code.

This solve the issue that `ILLink` does a similar job _before_ we have
the chance to disable the dynamic registrar.

* ILLink does not support considering other attributes as `[Preserve]`

when it is itself preserved at the assembly-level.

This ignored test is checking that feature so it cannot be enabled
for `NET`

Added to known breaking changes https://github.com/xamarin/xamarin-macios/issues/8900

* Fix removal of the dynamic registrar on legacy

* Fix IntPtr size inlining

Co-authored-by: Sebastien Pouliot <sebastien.pouliot@microsoft.com>
2021-05-12 12:26:54 -04:00
Rolf Bjarne Kvinge eb5206f082
[dotnet-linker] Add OptimizeGeneratedCodeSubStep into the pipeline. (#9608)
Fixes these linkall tests:

    Linker.Shared.OptimizeGeneratedCodeTest
        [FAIL] IsARM64CallingConvention :   optimized: no ldsfld instruction
        Expected: 0
        But was:  1
            at Linker.Shared.BaseOptimizeGeneratedCodeTest.IsARM64CallingConvention() in /Users/rolf/work/maccore/main/xamarin-macios/tests/linker/BaseOptimizeGeneratedCodeTest.cs:line 527
    
    [FAIL] SetupBlockPerfTest :   At least 6x speedup
        Expected: greater than 6
        But was:  1.0876440665344851d
            at Linker.Shared.BaseOptimizeGeneratedCodeTest.SetupBlockPerfTest() in /Users/rolf/work/maccore/main/xamarin-macios/tests/linker/BaseOptimizeGeneratedCodeTest.cs:line 120

And linkall is now green for .NET/Debug.
2020-09-10 08:30:45 +02:00
Rolf Bjarne Kvinge 819f5f95e0
[mtouch/mmp] Unify OptimizeGeneratedCodeSubStep into a single class. (#9549)
This makes it easier to use this code from dotnet-linker.
2020-08-31 18:56:23 +02:00
Rolf Bjarne Kvinge 6978026454
[mtouch/mmp] Add a few instructions to the list of instructions that we don't know how to calculate a constant value for. (#9260)
This improves (shrinks) the debug spew when running mtouch or mmp in the IDE.
2020-08-03 18:49:23 +02:00
Rolf Bjarne Kvinge 17ac227fb3 [linker] Stop passing data to the OptimizeGeneratedCode steps using a constructor. 2020-05-07 15:51:47 +02:00
Rolf Bjarne Kvinge 22f4418d2f
[linker] Update the list of opcodes we can't compute a constant value for. (#8143)
Teach the linker about more opcodes it can't compute a constant value for.
This way a debug version of mmp/mtouch doesn't print out these opcodes for
someone to check.

This code is only executed when debugging mtouch/mmp in the IDE, so no change
to released bits.
2020-03-19 09:26:24 +01:00
Waleed Chaudhry 00985a55e2
[Localization] mtouch/mmp C# (#7710) 2020-01-31 15:02:52 -05:00
Rolf Bjarne Kvinge d02c9bc8e0
Add a Runtime.IsARM64CallingConvention property. (#5569)
* Add a Runtime.IsARM64CallingConvention property.

Determining whether we should use the ARM64 calling convention in P/Invokes
gets more complicated with ARM64_32 (which for our purposes is a 32-bit
architecture).

So add a property on the Runtime class to avoid code duplication, and teach
the linker to optimize any calls to this property to a constant value whenever
possible (and the method is marked as optimizable).

Also change our code to use this new property, and make the corresponding
methods optimizable.

Some shuffling in mmp was required, which meant a little bit more code is now
shared between mtouch and mmp.

* Coding style.

* Test tweaks.

* Improve comment.

* Document new optimization

* Move ILReader to shared linker test code location.

* Disable inlining on armv7k.

* Change IsARM64CallingConvention to a read-only field.

We can give the AOT compiler a constant value for a read-only field, so that
the AOT compiler optimizes away the call to the field by using the constant
value.

This commit does not implement this change for the AOT compiler, but using a
read-only field makes it easy to implement it in the future.
2019-02-11 17:29:13 +01:00
Chris Hamons 3119129ab7 Remove references to bugzilla and replace with github (#4920)
https://github.com/xamarin/xamarin-macios/issues/3647
2018-10-04 09:43:55 -04:00
Rolf Bjarne Kvinge fafd0fa151 [ObjCRuntime] BlockLiteral.GetBlockForDelegate must be optimizable because it calls Runtime.DynamicRegistrationSupported.
Fixes this test:

    Xamarin.ApiTest.ApiTest.AlwaysOptimizable(iOS) : All methods calling optimizable API must be optimizable
    	The method System.IntPtr ObjCRuntime.BlockLiteral::GetBlockForDelegate(System.Reflection.MethodInfo,System.Object,System.String) calls System.Boolean ObjCRuntime.Runtime::get_DynamicRegistrationSupported(), but it does not have a [BindingImpl (BindingImplOptions.Optimizable)] attribute.

Also skip the BlockLiteral.SetupBlock optimization for this method, because
it's not optimizable (and thus produces a warning users can't ignore).
2018-02-15 15:58:02 +01:00
Rolf Bjarne Kvinge ff737fe294 [linker] Add support for marking switch statements in the code optimizer. 2018-02-15 10:26:22 +01:00
Rolf Bjarne Kvinge 9cec7d3d59 [linker] Add support for removing exception handlers from optimized code.
It seems LLVM freaks out if it finds unreachable exception handlers:

    * Assertion at ../../../../external/mono/mono/mini/mini-llvm.c:7406, condition `err == 0' not met
    Basic Block in function 'Xamarin_iOS_ObjCRuntime_Class_GetClassHandle_System_Type' does not have terminator!
    label %BB7_CALL_HANDLER_TARGET
2018-02-15 10:24:31 +01:00
Rolf Bjarne Kvinge 92f8fab14b [mtouch/mmp] Add support for inlining calls to Runtime.DynamicRegistrarSupported and removal of the dynamic registrar. 2018-02-15 10:18:27 +01:00
Rolf Bjarne Kvinge 97230c28e1
Optimize calls to BlockLiteral.SetupBlock to inject the block signature. (#3391)
* [linker] Optimize calls to BlockLiteral.SetupBlock to inject the block signature.

Optimize calls to BlockLiteral.SetupBlock[Unsafe] to calculate the block
signature at build time, and inject it into the call site.

This makes block invocations 10-15x faster (I've added tests that asserts at
least an 8x increase).

It's also required in order to be able to remove the dynamic registrar code in
the future (since calculating the block signature at runtime requires the
dynamic registrar).

* [mtouch/mmp] Add support for reporting errors/warnings that point to the code line causing the error/warning.

Add support for reporting errors/warnings that point to the code line causing
the error/warning by adding ErrorHelper overloads that take the exact
instruction to report (previously we defaulted to the first line/instruction
in a method).

* [tests] Add support for asserting filename/linenumber in warning messages.

* Make all methods that manually create BlockLiterals optimizable.

* [tests] Create a BaseOptimizeGeneratedCodeTest test that's included in both XI's and XM's link all test.

* [tests] Add link all test (for both XI and XM) to test the BlockLiteral.SetupBlock optimization.

* [tests] Add mtouch/mmp tests for the BlockLiteral.SetupBlock optimization.

* [tests][linker] Make the base test class abstract, so tests in the base class aren't executed twice.

* [tests][linker] Don't execute linkall-only tests in linksdk.

The optimization tests only apply when the test assembly is linked, and that
only happens in linkall, so exclude those tests in linksdk.

* [tests][mmptest] Update test according to mmp changes.

Fixes these test failures:

    1) Failed : Xamarin.MMP.Tests.MMPTests.MM0132("inline-runtime-arch")
    The warning 'MM0132: Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.' was not found in the output:
    	Message #1 did not match:
    		actual:   'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.'
    		expected: 'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.'
    	Message #2 did not match:
    		actual:   'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.'
    		expected: 'Unknown optimization: 'inline-runtime-arch'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.'

    2) Failed : Xamarin.MMP.Tests.MMPTests.MM0132("foo")
    The warning 'MM0132: Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.' was not found in the output:
    	Message #1 did not match:
    		actual:   'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.'
    		expected: 'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.'
    	Message #2 did not match:
    		actual:   'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size, blockliteral-setupblock.'
    		expected: 'Unknown optimization: 'foo'. Valid optimizations are: remove-uithread-checks, dead-code-elimination, inline-isdirectbinding, inline-intptr-size.'

* [tests][linker] Fix typo.

Fixes this test failure:

    1) SetupBlock_CustomDelegate (Linker.Shared.BaseOptimizeGeneratedCodeTest.SetupBlock_CustomDelegate)
         Counter
      Expected: 1
      But was:  2

* [registrar] Minor adjustment to error message to match previous (and better) behavior.

Fixes this test failure:

    1) Failed : Xamarin.Registrar.GenericType_WithInvalidParameterTypes
    The error 'MT4136: The registrar cannot marshal the parameter type 'System.Collections.Generic.List`1<U>' of the parameter 'arg' in the method 'Open`1.Bar(System.Collections.Generic.List`1<U>)'' was not found in the output:
    	Message #1 did not match:
    		actual:   'The registrar cannot marshal the parameter type 'System.Collections.Generic.List`1<Foundation.NSObject>' of the parameter 'arg' in the method 'Open`1.Bar(System.Collections.Generic.List`1<U>)''
    		expected: 'The registrar cannot marshal the parameter type 'System.Collections.Generic.List`1<U>' of the parameter 'arg' in the method 'Open`1.Bar(System.Collections.Generic.List`1<U>)''

* [docs] mmp shows MM errors/warnings.

* [docs] Improve according to reviews.

* [tests] Fix merge failure causing test duplication.
2018-02-06 07:08:15 +01:00
Rolf Bjarne Kvinge b2bcad7a94
Add a BindingImpl attribute and use to to teach the linker look for it to search for optimizable code. (#3299)
* [ObjCRuntime] Add a BindingImplAttribute.

* [linker] Make ProviderToString an extension method on ICustomAttributeProvider to make it more discoverable.

* [generator] Use [BindingImpl] instead of [CompilerGenerated].

The entire diff is big (89MB), so it can't be gisted. However, most of it is
either removal of `using System.Runtime.CompilerServices;` or the change from
`[CompilerGenerated]` to `[BindingImpl (...)]` like this:
https://gist.github.com/rolfbjarne/8bfda3ed37b956d0342a1c1e9b079244

If I remove those parts of the diff, there's nothing significant left:
https://gist.github.com/rolfbjarne/4156164d6bdb1376366200394eb8a091

* [linker] Teach the linker about the new [BindingImpl] attribute.

In addition to the existing logic where the linker would optimize some
[CompilerGenerated] code (sometimes with additional requirements), it will now
also optimize all [BindingImpl (Optimizable)] code (without any additional
requirements).

* [tests] Add tests to make sure [BindingImpl (Optimizable)] works as expected.

* [linker] Check for [BindingImpl] before [CompilerGenerated] and stop checking for [CompilerGenerated] in XAMCORE_4_0.

Check for [BindingImpl] before checking for [CompilerGenerated], since the
former is more common.

Also stop checking for [CompilerGenerated] (at least to mean that code is
optimizable) in our next non-compatible evolutionary leap (XAMCORE_4_0):

* [introspection] Impl a better typo check.
2018-01-26 18:38:23 +01:00
Rolf Bjarne Kvinge af03020eef
[mtouch/mmp] Give users more control over optimizations, and share more code between mtouch and mmp. (#3242)
* [mtouch/mmp] Give users more control over optimizations, and share more code between mtouch and mmp.

1. Add an --optimize flag to mtouch/mmp that allows users to select which
   optimizations to apply (or not). This makes it easier to add future
   optimizations, and allow users to disable any optimization that causes
   problems without having to disable many other features.

2. Share as much optimization code as possible between mtouch and mmp. This
   immediately gives a benefit to mmp, which has three new optimizations only
   mtouch had: NSObject.IsDirectBinding inlining, IntPtr.Size inlining and
   dead code elimination.

   This results in ~6kb of disk space saved for a linked Xamarin.Mac app:

   * link sdk: [Debug][1], [Release][2]
   * link all: [Debug][3], [Release][4]

Testing also verifies that monotouchtest ([Debug][5], [Release][6]) has not
changed size at all, which means that no default optimizations have changed
inadvertedly.

[1]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#link-sdk-mac--debug
[2]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#link-sdk-mac--release
[3]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#link-all-mac--debug
[4]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#link-all-mac--release
[5]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#monotouchtest-iphonedebug64
[6]: https://gist.github.com/rolfbjarne/6b731e3b5ca6170355662e6505c3d492#monotouchtest-iphonerelease64

* [tools] Don't enable the IsDirectBinding optimization by default for Xamarin.Mac apps, it's not safe.

* Fix whitespace issues.

* [doc] Document optimizations.

* Officially support optimizations by adding them to the Versions.plist.

* [linker] Improve IntPtr.Size inliner + dead code eliminatior and add tests.

* Properly handle operands for the ldc_i4_s instruction (they're sbyte).
* Fix less-than condition to actually do a less-than comparison.
* Make sure to look up the bitness in the Target, not the Application, since
  the Application's value will be incorrect when building fat apps (both
  Is32Build and Is64Build will be true).
* Remove unnecessary checks for the IntPtr.Size inliner: this optimization
  does not depend on other instructions than the IntPtr.get_Size call, so
  remove the checks that verify surrounding instructions. This makes the
  IntPtr.Size inliner kick in in more scenarios (such as the new tests).
* Add tests.

* [tests] Add mmp tests for optimizations.

* [tests] Fix XM optimization tests.

* [tests] Fix test build error.
2018-01-23 11:33:48 +01:00
Rolf Bjarne Kvinge 49d3a50f26
[linker] Refactor and simplify code optimizations. (#3078)
* [linker] Refactor and simplify code optimizations.

We had several types of code optimizations, where we'd determine a particular
expression is a constant, then remove the condition and the code for any
dead branches.

Unfortunately each type of expression had its own logic to determine the
sequence of code to remove, each slightly different depending on the actual
conditional expression. This has led to bugs in the past, either when
switching between compilers (mcs/csc), or compilers have changed their emitted
code.

So implement a more generic version where each optimization just changes the
specific condition to a constant value, and then at the end we have a dead-
code-elimination pass that eliminates dead code based on those constant
conditions.

This version is also a lot more defensive than the previous code, it will bail
out without doing anything if it finds a code sequence it doesn't understand.

This also makes it easier to implement other similar code optimizations.

Simple time measuring shows no slowdown in the linker, and the size difference for monotouch-test is negligable at best:

256 bytes more for the exectuable:

    -rwxr-xr-x  1 rolf  staff  72890464 Dec  1 14:39 /Users/rolf/test/old/monotouchtest.app/monotouchtest
    -rwxr-xr-x  1 rolf  staff  72890720 Dec  1 14:44 /Users/rolf/test/new/monotouchtest.app/monotouchtest

3584 bytes less for Xamarin.iOS.dll:

    -rw-r--r--  1 rolf  staff   2506240 Dec  1 14:39 /Users/rolf/test/old/monotouchtest.app/Xamarin.iOS.dll
    -rw-r--r--  1 rolf  staff   2502656 Dec  1 14:44 /Users/rolf/test/new/monotouchtest.app/Xamarin.iOS.dll

I don't know why the executable grew slightly, the IL diff for Xamarin.iOS.dll
shows nothing out of the ordinary:
https://gist.github.com/rolfbjarne/33590ad651a21f9a9352ac9b97b9dc06

* [linker] NewRefcount is constantly true for Unified, so trying to inline it is useless.

* [linker] Remove redundant code.

* [linker] Remove nops at the end of methods.

It's not legal IL to have a nop as the last instruction of a method, peverify complains:

> [IL]: Error: [D:\Documentos\Rolf\Xamarin\Xamarin.iOS.dll : AVFoundation.AVAssetImageGenerator::get_AppliesPreferredTrackTransform][offset 0x0000001E] fall through end of the method without returning

so detect and remove nops at the end of methods.

Also add a sanity check to ensure we don't remove nops that are targets for
branch instructions (should never happen, but it doesn't hurt to be safe).

PEVerify shows much fewer errors now, [1721][1] vs [2581][2], although the [IL diff][3]
is bigger (due to the removed nops).

Updated timing measurements show no slowdown in the linker, and the size
difference for monotouch-test is negligable:

32 bytes less for the exectuable:

    -rwxr-xr-x  1 rolf  staff  72890880 Jan 12 00:54:49 2018 /Users/rolf/test/old/monotouchtest.app/monotouchtest*
    -rwxr-xr-x  1 rolf  staff  72890848 Jan 12 00:56:57 2018 /Users/rolf/test/new/monotouchtest.app/monotouchtest*

12288 bytes less for Xamarin.iOS.dll (this is a debug build, a release build
would probably not show any difference at all):

    -rw-r--r--  1 rolf  staff  2506240 Jan 12 00:54:49 2018 /Users/rolf/test/old/monotouchtest.app/Xamarin.iOS.dll
    -rw-r--r--  1 rolf  staff  2493952 Jan 12 00:56:57 2018 /Users/rolf/test/new/monotouchtest.app/Xamarin.iOS.dll

[1]: https://gist.github.com/rolfbjarne/9c8fa519a6f8e1718b125472f05ded07#file-peverify-new-txt-L1726
[2]: https://gist.github.com/rolfbjarne/9c8fa519a6f8e1718b125472f05ded07#file-peverify-old-txt-L2586
[3]: https://gist.github.com/rolfbjarne/35d5bfec1809ad2a80a7781cebe5b574
2018-01-12 07:24:13 +01:00
Rolf Bjarne Kvinge 5fb09b1b84 [linker] Remove static state, and put the state inside DerivedLinkContext instead. (#1657)
Remove the usage of static variables in the linker so that one day we can run
the linker in parallel over multiple assembly sets.
2017-02-10 07:45:42 +01:00
Sebastien Pouliot 9fda816230 [mtouch][linker] Use correct error code for CoreOptimizeGeneratedCode (#915)
Previous PR [1] has the right documentation but the wrong source code.

[1] https://github.com/xamarin/xamarin-macios/pull/903
2016-09-28 23:16:03 -04:00
Sebastien Pouliot 5b80e7f85c [mtouch][linker] Provide a more specific error code when OptimizeGeneratedCodeSubStep fails (#903)
The MT2001 error is a general, something went bad, in the linker code
base. The stack trace is often enough to track down issues but in some
cases it would be easier to ask customers for a specific assembly
(rather than their complete project) to investigate an issue.

Example:

error MT2103: Binding Optimizer failed processing `System.Void GoogleConversionTracking.Unified.GoogleConversionPing::.ctor()`.
--- inner exception
System.NullReferenceException: Object reference not set to an instance of an object
  at MonoTouch.Tuner.OptimizeGeneratedCodeSubStep.ProcessIsDirectBinding (Mono.Cecil.MethodDefinition caller, Mono.Cecil.Cil.Instruction ins) [0x00026] in /Users/poupou/git/xamarin/xamarin-macios/tools/linker/MonoTouch.Tuner/OptimizeGeneratedCodeSubStep.cs:264
  at MonoTouch.Tuner.OptimizeGeneratedCodeSubStep.ProcessCalls (Mono.Cecil.MethodDefinition caller, Int32 i) [0x00337] in /Users/poupou/git/xamarin/xamarin-macios/tools/linker/MonoTouch.Tuner/OptimizeGeneratedCodeSubStep.cs:197
  at MonoTouch.Tuner.OptimizeGeneratedCodeSubStep.Process (Mono.Cecil.MethodDefinition method) [0x0007b] in /Users/poupou/git/xamarin/xamarin-macios/tools/linker/MonoTouch.Tuner/OptimizeGeneratedCodeSubStep.cs:81
  at Xamarin.Linker.StateSubStep.ProcessMethod (Mono.Cecil.MethodDefinition method) [0x00004] in /Users/poupou/git/xamarin/xamarin-macios/tools/linker/CoreOptimizeGeneratedCode.cs:48
---
  at Xamarin.Linker.StateSubStep.ProcessMethod (Mono.Cecil.MethodDefinition method) [0x00014] in /Users/poupou/git/xamarin/xamarin-macios/tools/linker/CoreOptimizeGeneratedCode.cs:50
  at Mono.Tuner.SubStepDispatcher.DispatchMethod (Mono.Cecil.MethodDefinition method) [0x0001d] in /Users/poupou/git/xamarin/xamarin-macios/external/mono/mcs/tools/tuner/Mono.Tuner/Dispatcher.cs:215
  at Mono.Tuner.SubStepDispatcher.BrowseMethods (ICollection methods) [0x0001c] in /Users/poupou/git/xamarin/xamarin-macios/external/mono/mcs/tools/tuner/Mono.Tuner/Dispatcher.cs:167
  at Mono.Tuner.SubStepDispatcher.BrowseTypes (ICollection types) [0x0006b] in /Users/poupou/git/xamarin/xamarin-macios/external/mono/mcs/tools/tuner/Mono.Tuner/Dispatcher.cs:145
  at Mono.Tuner.SubStepDispatcher.BrowseAssemblies (IEnumerable`1 assemblies) [0x00050] in /Users/poupou/git/xamarin/xamarin-macios/external/mono/mcs/tools/tuner/Mono.Tuner/Dispatcher.cs:123
  at Mono.Tuner.SubStepDispatcher.Process (Mono.Linker.LinkContext context) [0x0000f] in /Users/poupou/git/xamarin/xamarin-macios/external/mono/mcs/tools/tuner/Mono.Tuner/Dispatcher.cs:104
  at Mono.Linker.Pipeline.Process (Mono.Linker.LinkContext context) [0x00027] in /Users/poupou/git/xamarin/xamarin-macios/external/mono/mcs/tools/linker/Mono.Linker/Pipeline.cs:118
  at MonoTouch.Tuner.Linker.Process (MonoTouch.Tuner.LinkerOptions options, MonoTouch.Tuner.MonoTouchLinkContext& context, System.Collections.Generic.List`1& assemblies) [0x000ac] in /Users/poupou/git/xamarin/xamarin-macios/tools/mtouch/Tuning.cs:79

Right now the MT2001 would only include the inner exception, which does
not include any clue to which assembly caused the exception.

Note: The same pattern to be applied to other BaseSubStep subclasses in
separate commits.

Related to (but not the fix for) https://bugzilla.xamarin.com/show_bug.cgi?id=44701
2016-09-28 11:46:14 -04:00
Rolf Bjarne Kvinge 82ab3fc106 Build mmp. 2016-04-24 14:47:26 -04:00