xamarin-macios/tools/linker/CoreOptimizeGeneratedCode.cs

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

[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 18:46:14 +03:00
// Copyright 2012-2013, 2016 Xamarin Inc. All rights reserved.
2016-04-21 15:57:02 +03:00
using System;
using System.Collections.Generic;
using System.Linq;
using ObjCRuntime;
2016-04-21 15:57:02 +03:00
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Linker;
using Mono.Tuner;
[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 09:24:13 +03:00
using Xamarin.Bundler;
2016-04-21 15:57:02 +03:00
[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 13:33:48 +03:00
using MonoTouch.Tuner;
#if NET
using Mono.Linker.Steps;
#endif
[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 13:33:48 +03:00
2016-04-21 15:57:02 +03:00
namespace Xamarin.Linker {
[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 18:46:14 +03:00
#if NET
public class OptimizeGeneratedCodeHandler : ExceptionalMarkHandler {
#else
public class OptimizeGeneratedCodeSubStep : ExceptionalSubStep {
[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 13:33:48 +03:00
// If the type currently being processed is a direct binding or not.
// A null value means it's not a constant value, and can't be inlined.
bool? isdirectbinding_constant;
#endif
[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 18:46:14 +03:00
protected override string Name { get; } = "Binding Optimizer";
protected override int ErrorCode { get; } = 2020;
[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 18:46:14 +03:00
#if NET
Dictionary<AssemblyDefinition, bool?> _hasOptimizableCode;
Dictionary<AssemblyDefinition, bool?> HasOptimizableCode {
get {
if (_hasOptimizableCode == null)
_hasOptimizableCode = new Dictionary<AssemblyDefinition, bool?> ();
return _hasOptimizableCode;
}
}
Dictionary<AssemblyDefinition, bool> _inlineIntPtrSize;
Dictionary<AssemblyDefinition, bool> InlineIntPtrSize {
get {
if (_inlineIntPtrSize == null)
_inlineIntPtrSize = new Dictionary<AssemblyDefinition, bool> ();
return _inlineIntPtrSize;
}
}
#else
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 20:38:23 +03:00
protected bool HasOptimizableCode { get; private set; }
[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 18:46:14 +03:00
protected bool IsExtensionType { get; private set; }
[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 13:33:48 +03:00
// This is per assembly, so we set it in 'void Process (AssemblyDefinition)'
bool InlineIntPtrSize { get; set; }
#endif
[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 13:33:48 +03:00
public bool IsDualBuild {
get { return LinkContext.App.IsDualBuild; }
[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 13:33:48 +03:00
}
public bool Device {
get { return LinkContext.App.IsDeviceBuild; }
}
[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 13:33:48 +03:00
public int Arch {
get { return LinkContext.Target.Is64Build ? 8 : 4; }
[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 13:33:48 +03:00
}
protected Optimizations Optimizations {
get {
return LinkContext.App.Optimizations;
[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 13:33:48 +03:00
}
}
bool? is_arm64_calling_convention;
#if NET
public override void Initialize (LinkContext context, MarkContext markContext)
#else
public override void Initialize (LinkContext context)
#endif
[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 13:33:48 +03:00
{
base.Initialize (context);
if (Optimizations.InlineIsARM64CallingConvention == true) {
var target = LinkContext.Target;
if (target.Abis.Count == 1) {
// We can usually inline Runtime.InlineIsARM64CallingConvention if the generated code will execute on a single architecture
switch ((target.Abis [0] & Abi.ArchMask)) {
case Abi.i386:
case Abi.ARMv7:
case Abi.ARMv7s:
case Abi.x86_64:
is_arm64_calling_convention = false;
break;
case Abi.ARM64:
case Abi.ARM64e:
case Abi.ARM64_32:
is_arm64_calling_convention = true;
break;
case Abi.ARMv7k:
// ARMv7k binaries can run on ARM64_32, so this can't be inlined :/
break;
default:
LinkContext.Exceptions.Add (ErrorHelper.CreateWarning (99, Errors.MX0099, $"unknown abi: {target.Abis [0]}"));
break;
}
} else if (target.Abis.Count == 2 && target.Is32Build && target.Abis.Contains (Abi.ARMv7) && target.Abis.Contains (Abi.ARMv7s)) {
// We know we won't be running on arm64 if we're building for armv7+armv7s.
is_arm64_calling_convention = false;
}
}
#if NET
markContext.RegisterMarkMethodAction (ProcessMethod);
#endif
[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 13:33:48 +03:00
}
2016-04-21 15:57:02 +03:00
#if !NET
2016-04-21 15:57:02 +03:00
public override SubStepTargets Targets {
[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 18:46:14 +03:00
get { return SubStepTargets.Assembly | SubStepTargets.Type | SubStepTargets.Method; }
2016-04-21 15:57:02 +03:00
}
#endif
#if NET
bool IsActiveFor (AssemblyDefinition assembly, out bool hasOptimizableCode)
#else
2016-04-21 15:57:02 +03:00
public override bool IsActiveFor (AssemblyDefinition assembly)
#endif
2016-04-21 15:57:02 +03:00
{
#if NET
hasOptimizableCode = false;
if (HasOptimizableCode.TryGetValue (assembly, out bool? optimizable)) {
if (optimizable == true)
hasOptimizableCode = true;
return optimizable != null;
}
#else
bool hasOptimizableCode = false;
#endif
2016-04-21 15:57:02 +03:00
// 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
#if NET
HasOptimizableCode.Add (assembly, null);
2016-04-21 15:57:02 +03:00
#endif
return false;
}
2016-04-21 15:57:02 +03:00
// 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
#if NET
HasOptimizableCode.Add (assembly, null);
2016-04-21 15:57:02 +03:00
#endif
return false;
}
2016-04-21 15:57:02 +03:00
// if the assembly does not refer to [CompilerGeneratedAttribute] then there's not much we can do
foreach (TypeReference tr in assembly.MainModule.GetTypeReferences ()) {
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 20:38:23 +03:00
if (tr.Is (Namespaces.ObjCRuntime, "BindingImplAttribute")) {
hasOptimizableCode = true;
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 20:38:23 +03:00
break;
}
if (tr.Is ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute")) {
2016-04-21 15:57:02 +03:00
#if DEBUG
Console.WriteLine ("Assembly {0} : processing", assembly);
#endif
hasOptimizableCode = true;
2016-04-21 15:57:02 +03:00
break;
}
}
#if DEBUG
if (!hasOptimizableCode)
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 20:38:23 +03:00
Console.WriteLine ("Assembly {0} : no [CompilerGeneratedAttribute] nor [BindingImplAttribute] present (applying basic optimizations)", assembly);
2016-04-21 15:57:02 +03:00
#endif
// we always apply the step
#if NET
HasOptimizableCode.Add (assembly, hasOptimizableCode);
#else
HasOptimizableCode = hasOptimizableCode;
#endif
2016-04-21 15:57:02 +03:00
return true;
}
#if !NET
[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 18:46:14 +03:00
protected override void Process (TypeDefinition type)
2016-04-21 15:57:02 +03:00
{
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 20:38:23 +03:00
if (!HasOptimizableCode)
[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 13:33:48 +03:00
return;
isdirectbinding_constant = IsDirectBindingConstant (type);
[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 13:33:48 +03:00
IsExtensionType = GetIsExtensionType (type);
2016-04-21 15:57:02 +03:00
}
#endif
2016-04-21 15:57:02 +03:00
// [GeneratedCode] is not enough - e.g. it's used for anonymous delegates even if the
// code itself is not tool/compiler generated
[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 18:46:14 +03:00
static protected bool IsExport (ICustomAttributeProvider provider)
2016-04-21 15:57:02 +03:00
{
return provider.HasCustomAttribute (Namespaces.Foundation, "ExportAttribute");
}
// less risky to nop-ify if branches are pointing to this instruction
static protected void Nop (Instruction ins)
{
// Leave 'leave' instructions in place, they might be required for the resulting IL to be correct/verifiable.
switch (ins.OpCode.Code) {
case Code.Leave:
case Code.Leave_S:
return;
}
2016-04-21 15:57:02 +03:00
ins.OpCode = OpCodes.Nop;
ins.Operand = null;
}
[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 09:24:13 +03:00
[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 16:03:25 +03:00
internal static bool ValidateInstruction (MethodDefinition caller, Instruction ins, string operation, Code expected)
[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 09:24:13 +03:00
{
if (ins.OpCode.Code != expected) {
Driver.Log (1, "Could not {0} in {1} at offset {2}, expected {3} got {4}", operation, caller, ins.Offset, expected, ins);
return false;
}
return true;
}
[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 16:03:25 +03:00
internal static bool ValidateInstruction (MethodDefinition caller, Instruction ins, string operation, params Code [] expected)
[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 09:24:13 +03:00
{
foreach (var code in expected) {
if (ins.OpCode.Code == code)
return true;
}
Driver.Log (1, "Could not {0} in {1} at offset {2}, expected any of [{3}] got {4}", operation, caller, ins.Offset, string.Join (", ", expected), ins);
return false;
}
static int? GetConstantValue (Instruction ins)
{
if (ins == null)
return null;
[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 09:24:13 +03:00
switch (ins.OpCode.Code) {
case Code.Ldc_I4_0:
return 0;
case Code.Ldc_I4_1:
return 1;
case Code.Ldc_I4_2:
return 2;
case Code.Ldc_I4_3:
return 3;
case Code.Ldc_I4_4:
return 4;
case Code.Ldc_I4_5:
return 5;
case Code.Ldc_I4_6:
return 6;
case Code.Ldc_I4_7:
return 7;
case Code.Ldc_I4_8:
return 8;
case Code.Ldc_I4:
case Code.Ldc_I4_S:
if (ins.Operand is int)
return (int) ins.Operand;
[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 13:33:48 +03:00
if (ins.Operand is sbyte)
return (sbyte) ins.Operand;
[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 09:24:13 +03:00
return null;
#if DEBUG
case Code.Isinst: // We might be able to calculate a constant value here in the future
case Code.Ldloc:
case Code.Ldloca:
case Code.Ldloc_0:
case Code.Ldloc_1:
case Code.Ldloc_2:
case Code.Ldloc_3:
case Code.Ldloc_S:
case Code.Ldloca_S:
case Code.Ldarg:
case Code.Ldarg_0:
case Code.Ldarg_1:
case Code.Ldarg_2:
case Code.Ldarg_3:
case Code.Ldarg_S:
case Code.Ldarga:
case Code.Call:
case Code.Calli:
case Code.Callvirt:
case Code.Box:
case Code.Ldsfld:
case Code.Dup: // You might think we could get the constant of the previous instruction, but this instruction might be the target of a branch, in which case the question becomes: which instruction was the previous instruction? And that's not a question easily answered without a much more thorough analysis of the code.
case Code.Ldlen:
case Code.Ldind_U1:
case Code.Ldind_U2:
case Code.Ldind_U4:
case Code.Ldind_Ref:
case Code.Conv_I:
case Code.Conv_I1:
case Code.Conv_I2:
case Code.Conv_I4:
case Code.Conv_U:
case Code.Sizeof:
case Code.Ldfld:
case Code.Ldflda:
[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 09:24:13 +03:00
return null; // just to not hit the CWL below
#endif
default:
#if DEBUG
Driver.Log (9, "Unknown conditional instruction: {0}", ins);
#endif
return null;
}
}
static bool MarkInstructions (MethodDefinition method, Mono.Collections.Generic.Collection<Instruction> instructions, bool [] reachable, int start, int end)
{
if (reachable [start])
return true; // We've already marked this section of code
for (int i = start; i < end; i++) {
reachable [i] = true;
[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 09:24:13 +03:00
var ins = instructions [i];
switch (ins.OpCode.FlowControl) {
case FlowControl.Branch:
// Unconditional branch, we continue marking from the instruction that we branch to.
var br_target = (Instruction) ins.Operand;
return MarkInstructions (method, instructions, reachable, instructions.IndexOf (br_target), end);
case FlowControl.Cond_Branch:
// Conditional instruction, we need to check if we can calculate a constant value for the condition
var cond_target = ins.Operand as Instruction;
[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 09:24:13 +03:00
bool? branch = null; // did we get a constant value for the condition, and if so, did we branch or not?
var cond_instruction_count = 0; // The number of instructions that compose the condition
if (ins.OpCode.Code == Code.Switch) {
// Treat all branches of the switch statement as reachable.
// FIXME: calculate the potential constant branch (currently there are no optimizable methods where the switch condition is constant, so this is not needed for now)
var targets = ins.Operand as Instruction [];
if (targets == null) {
Driver.Log (4, $"Can't optimize {0} because of unknown target of branch instruction {1} {2}", method, ins, ins.Operand);
return false;
}
foreach (var target in targets) {
// not constant, continue marking both this code sequence and the branched sequence
if (!MarkInstructions (method, instructions, reachable, instructions.IndexOf (target), end))
return false;
}
return MarkInstructions (method, instructions, reachable, instructions.IndexOf (ins.Next), end);
}
if (cond_target == null) {
Driver.Log (4, $"Can't optimize {0} because of unknown target of branch instruction {1} {2}", method, ins, ins.Operand);
return false;
}
[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 09:24:13 +03:00
switch (ins.OpCode.Code) {
case Code.Brtrue:
case Code.Brtrue_S: {
var v = GetConstantValue (ins?.Previous);
if (v.HasValue)
branch = v.Value != 0;
cond_instruction_count = 2;
break;
}
[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 09:24:13 +03:00
case Code.Brfalse:
case Code.Brfalse_S: {
var v = GetConstantValue (ins?.Previous);
if (v.HasValue)
branch = v.Value == 0;
cond_instruction_count = 2;
break;
}
[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 09:24:13 +03:00
case Code.Beq:
case Code.Beq_S: {
var x1 = GetConstantValue (ins?.Previous?.Previous);
var x2 = GetConstantValue (ins?.Previous);
if (x1.HasValue && x2.HasValue)
branch = x1.Value == x2.Value;
cond_instruction_count = 3;
break;
}
[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 09:24:13 +03:00
case Code.Bne_Un:
case Code.Bne_Un_S: {
var x1 = GetConstantValue (ins?.Previous?.Previous);
var x2 = GetConstantValue (ins?.Previous);
if (x1.HasValue && x2.HasValue)
branch = x1.Value != x2.Value;
cond_instruction_count = 3;
break;
}
[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 09:24:13 +03:00
case Code.Ble:
case Code.Ble_S:
case Code.Ble_Un:
case Code.Ble_Un_S: {
var x1 = GetConstantValue (ins?.Previous?.Previous);
var x2 = GetConstantValue (ins?.Previous);
if (x1.HasValue && x2.HasValue)
branch = x1.Value <= x2.Value;
cond_instruction_count = 3;
break;
}
[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 09:24:13 +03:00
case Code.Blt:
case Code.Blt_S:
case Code.Blt_Un:
case Code.Blt_Un_S: {
var x1 = GetConstantValue (ins?.Previous?.Previous);
var x2 = GetConstantValue (ins?.Previous);
if (x1.HasValue && x2.HasValue)
branch = x1.Value < x2.Value;
cond_instruction_count = 3;
break;
}
[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 09:24:13 +03:00
case Code.Bge:
case Code.Bge_S:
case Code.Bge_Un:
case Code.Bge_Un_S: {
var x1 = GetConstantValue (ins?.Previous?.Previous);
var x2 = GetConstantValue (ins?.Previous);
if (x1.HasValue && x2.HasValue)
branch = x1.Value >= x2.Value;
cond_instruction_count = 3;
break;
}
[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 09:24:13 +03:00
case Code.Bgt:
case Code.Bgt_S:
case Code.Bgt_Un:
case Code.Bgt_Un_S: {
var x1 = GetConstantValue (ins?.Previous?.Previous);
var x2 = GetConstantValue (ins?.Previous);
if (x1.HasValue && x2.HasValue)
branch = x1.Value > x2.Value;
cond_instruction_count = 3;
break;
}
[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 09:24:13 +03:00
default:
Driver.Log ($"Can't optimize {0} because of unknown branch instruction: {1}", method, ins);
break;
}
if (branch.HasValue) {
// Make sure nothing else in the method branches into the middle of our supposedly constant condition,
// bypassing our constant calculation. Note that it's not a bad to branch to the _first_ instruction in
// the sequence (thus the +2 here), just into the middle of it.
if (AnyBranchTo (instructions, instructions [i - cond_instruction_count + 2], ins))
branch = null;
}
if (!branch.HasValue) {
// not constant, continue marking both this code sequence and the branched sequence
if (!MarkInstructions (method, instructions, reachable, instructions.IndexOf (cond_target), end))
return false;
} else {
// we can remove the branch (and the code that loads the condition), so we mark those instructions as dead.
for (int a = 0; a < cond_instruction_count; a++)
reachable [i - a] = false;
// Now continue marking according to whether we branched or not
if (branch.Value) {
// branch always taken
return MarkInstructions (method, instructions, reachable, instructions.IndexOf (cond_target), end);
} else {
// branch never taken
// continue looping
}
}
break;
case FlowControl.Call:
case FlowControl.Next:
// Nothing special, continue marking
break;
case FlowControl.Return:
case FlowControl.Throw:
// Control flow returns here, so stop marking
return true;
case FlowControl.Break:
case FlowControl.Meta:
case FlowControl.Phi:
default:
Driver.Log (4, "Can't optimize {0} because of unknown flow control for: {1}", method, ins);
return false;
}
}
return true;
}
// Check if there are any branches in the instructions that branch to anywhere between 'first' and 'last' instructions (both inclusive).
static bool AnyBranchTo (Mono.Collections.Generic.Collection<Instruction> instructions, Instruction first, Instruction last)
{
if (first.Offset > last.Offset) {
Driver.Log ($"Broken assumption: {first} is after {last}");
return true; // This is the safe thing to do, since it will prevent inlining
}
for (int i = 0; i < instructions.Count; i++) {
var ins = instructions [i];
switch (ins.OpCode.FlowControl) {
case FlowControl.Branch:
case FlowControl.Cond_Branch:
var target = ins.Operand as Instruction;
if (target != null && target.Offset >= first.Offset && target.Offset <= last.Offset)
return true;
break;
}
}
return false;
}
[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 13:33:48 +03:00
protected void EliminateDeadCode (MethodDefinition caller)
[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 09:24:13 +03:00
{
[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 13:33:48 +03:00
if (Optimizations.DeadCodeElimination != true)
return;
[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 09:24:13 +03:00
var instructions = caller.Body.Instructions;
var reachable = new bool [instructions.Count];
// We walk the instructions in the method, starting with the first instruction,
// marking all reachable instructions. Any non-reachable instructions at the end
// can be removed.
if (!MarkInstructions (caller, instructions, reachable, 0, instructions.Count))
return;
// Handle exception handlers specially, they do not follow normal code flow.
bool [] reachableExceptionHandlers = null;
[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 09:24:13 +03:00
if (caller.Body.HasExceptionHandlers) {
reachableExceptionHandlers = new bool [caller.Body.ExceptionHandlers.Count];
for (var e = 0; e < reachableExceptionHandlers.Length; e++) {
var eh = caller.Body.ExceptionHandlers [e];
// First check if the protected region is reachable
var startI = instructions.IndexOf (eh.TryStart);
var endI = instructions.IndexOf (eh.TryEnd);
for (int i = startI; i < endI; i++) {
if (reachable [i]) {
reachableExceptionHandlers [e] = true;
break;
}
}
// The protected code isn't reachable, none of the handlers will be executed
if (!reachableExceptionHandlers [e])
continue;
[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 09:24:13 +03:00
switch (eh.HandlerType) {
case ExceptionHandlerType.Catch:
// We don't need catch handlers the reachable instructions are all nops
var allNops = true;
[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 09:24:13 +03:00
for (int i = startI; i < endI; i++) {
if (instructions [i].OpCode.Code != Code.Nop) {
allNops = false;
[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 09:24:13 +03:00
break;
}
}
if (!allNops) {
[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 09:24:13 +03:00
if (!MarkInstructions (caller, instructions, reachable, instructions.IndexOf (eh.HandlerStart), instructions.IndexOf (eh.HandlerEnd)))
return;
}
break;
case ExceptionHandlerType.Finally:
// finally clauses are always executed, even if the protected region is empty
if (!MarkInstructions (caller, instructions, reachable, instructions.IndexOf (eh.HandlerStart), instructions.IndexOf (eh.HandlerEnd)))
return;
break;
case ExceptionHandlerType.Fault:
case ExceptionHandlerType.Filter:
// FIXME: and until fixed, exit gracefully without doing anything
Driver.Log (4, "Unhandled exception handler: {0}, skipping dead code elimination for {1}", eh.HandlerType, caller);
return;
}
}
}
if (Array.IndexOf (reachable, false) == -1)
return; // entire method is reachable
// Kill branch instructions when there are only dead instructions between the branch instruction and the target of the branch
for (int i = 0; i < instructions.Count; i++) {
if (!reachable [i])
continue;
var ins = instructions [i];
if (ins.OpCode.Code != Code.Br && ins.OpCode.Code != Code.Br_S)
continue;
var target = ins.Operand as Instruction;
if (target == null)
continue;
if (target.Offset < ins.Offset)
continue; // backwards branch, keep those
var start = i + 1;
var end = instructions.IndexOf (target);
var any_reachable = false;
for (int k = start; k < end; k++) {
if (reachable [k]) {
any_reachable = true;
break;
}
}
if (any_reachable)
continue;
// The branch instruction just branches over unreachable instructions, so it can be considered unreachable too.
reachable [i] = false;
}
// Check if there are unreachable instructions at the end.
var last_reachable = Array.LastIndexOf (reachable, true);
if (last_reachable < reachable.Length - 1) {
// There are unreachable instructions at the end.
// We must verify that there are no branches into these instructions.
// In theory there shouldn't be any (if there are branches into these instructions,
// they're reachable), but let's still verify just in case.
var last_reachable_offset = instructions [last_reachable].Offset;
for (int i = 0; i < last_reachable; i++) {
if (!reachable [i])
continue; // Unreachable instructions don't branch anywhere, because they'll be removed.
var ins = instructions [i];
switch (ins.OpCode.FlowControl) {
case FlowControl.Break:
case FlowControl.Cond_Branch:
var target = (Instruction) ins.Operand;
if (target.Offset > last_reachable_offset) {
Driver.Log (4, "Can't optimize {0} because of branching beyond last instruction alive: {1}", caller, ins);
return;
}
break;
}
}
}
#if false
[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 09:24:13 +03:00
Console.WriteLine ($"{caller.FullName}:");
for (int i = 0; i < reachable.Length; i++) {
Console.WriteLine ($"{(reachable [i] ? " " : "- ")} {instructions [i]}");
if (!reachable [i])
Nop (instructions [i]);
}
Console.WriteLine ();
#endif
// Exterminate, exterminate, exterminate
for (int i = 0; i < reachable.Length; i++) {
if (!reachable [i])
Nop (instructions [i]);
}
// Remove exception handlers
if (reachableExceptionHandlers != null) {
for (int i = reachableExceptionHandlers.Length - 1; i >= 0; i--) {
if (reachableExceptionHandlers [i])
continue;
caller.Body.ExceptionHandlers.RemoveAt (i);
}
}
[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 09:24:13 +03:00
// Remove unreachable instructions (nops) at the end, because the last instruction can only be ret/throw/backwards branch.
for (int i = last_reachable + 1; i < reachable.Length; i++)
instructions.RemoveAt (last_reachable + 1);
}
bool GetInlineIntPtrSize (AssemblyDefinition assembly)
[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 13:33:48 +03:00
{
#if NET
if (InlineIntPtrSize.TryGetValue (assembly, out bool inlineIntPtrSize))
return inlineIntPtrSize;
#else
bool inlineIntPtrSize;
#endif
[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 13:33:48 +03:00
// The "get_Size" is a performance (over size) optimization.
// It always makes sense for platform assemblies because:
// * Xamarin.TVOS.dll only ship the 64 bits code paths (all 32 bits code is extra weight better removed)
// * Xamarin.WatchOS.dll only ship the 32 bits code paths (all 64 bits code is extra weight better removed)
// * Xamarin.iOS.dll ship different 32/64 bits versions of the assembly anyway (nint... support)
// Each is better to be optimized (it will be smaller anyway)
//
// However for fat (32/64) apps (i.e. iOS only right now) the optimization can duplicate the assembly
// (metadata) for 3rd parties binding projects, increasing app size for very minimal performance gains.
// For non-fat apps (the AppStore allows 64bits only iOS apps) then it's better to be applied
//
// TODO: we could make this an option "optimize for size vs optimize for speed" in the future
if (Optimizations.InlineIntPtrSize.HasValue) {
inlineIntPtrSize = Optimizations.InlineIntPtrSize.Value;
[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 13:33:48 +03:00
} else if (!IsDualBuild) {
inlineIntPtrSize = true;
[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 13:33:48 +03:00
} else {
inlineIntPtrSize = (Profile.Current as BaseProfile).ProductAssembly == assembly.Name.Name;
[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 13:33:48 +03:00
}
if (inlineIntPtrSize)
Driver.Log (4, "Optimization 'inline-intptr-size' enabled for assembly '{0}'.", assembly.Name);
#if NET
InlineIntPtrSize.Add (assembly, inlineIntPtrSize);
#else
InlineIntPtrSize = inlineIntPtrSize;
#endif
return inlineIntPtrSize;
}
#if !NET
protected override void Process (AssemblyDefinition assembly)
{
GetInlineIntPtrSize (assembly);
[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 13:33:48 +03:00
base.Process (assembly);
}
#endif
bool GetIsExtensionType (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
return type.IsSealed && type.IsAbstract && type.Name.EndsWith ("_Extensions", StringComparison.Ordinal);
}
[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 13:33:48 +03:00
protected override void Process (MethodDefinition method)
{
#if NET
if (!IsActiveFor (method.DeclaringType.Module.Assembly, out bool hasOptimizableCode))
return;
#endif
[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 13:33:48 +03:00
if (!method.HasBody)
return;
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 20:38:23 +03:00
if (method.IsBindingImplOptimizableCode (LinkContext)) {
// We optimize all methods that have the [BindingImpl (BindingImplAttributes.Optimizable)] attribute.
} else if ((method.IsGeneratedCode (LinkContext) && (
#if NET
GetIsExtensionType (method.DeclaringType)
#else
IsExtensionType
#endif
|| IsExport (method)))) {
[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 13:33:48 +03:00
// We optimize methods that have the [GeneratedCodeAttribute] and is either an extension type or an exported method
} else {
// but it would be too risky to apply on user-generated code
return;
}
if (Optimizations.InlineIsARM64CallingConvention == true && is_arm64_calling_convention.HasValue && method.Name == "GetIsARM64CallingConvention" && method.DeclaringType.Is (Namespaces.ObjCRuntime, "Runtime")) {
// Rewrite to return the constant value
var instr = method.Body.Instructions;
instr.Clear ();
instr.Add (Instruction.Create (is_arm64_calling_convention.Value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0));
instr.Add (Instruction.Create (OpCodes.Ret));
return; // nothing else to do here.
}
[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 13:33:48 +03:00
var instructions = method.Body.Instructions;
for (int i = 0; i < instructions.Count; i++) {
var ins = instructions [i];
switch (ins.OpCode.Code) {
case Code.Newobj:
[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 13:33:48 +03:00
case Code.Call:
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 09:08:15 +03:00
i += ProcessCalls (method, ins);
[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 13:33:48 +03:00
break;
case Code.Ldsfld:
ProcessLoadStaticField (method, ins);
break;
}
}
EliminateDeadCode (method);
}
// Returns the number of instructions added (or removed).
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 09:08:15 +03:00
protected virtual int ProcessCalls (MethodDefinition caller, Instruction ins)
[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 13:33:48 +03:00
{
var mr = ins.Operand as MethodReference;
switch (mr?.Name) {
case "EnsureUIThread":
ProcessEnsureUIThread (caller, ins);
break;
case "get_Size":
ProcessIntPtrSize (caller, ins);
break;
case "get_IsDirectBinding":
ProcessIsDirectBinding (caller, ins);
break;
#if !NET
// ILLink does this optimization since the property returns a constant `true` (built time)
// or `false` - if `RegistrarRemovalTrackingStep` decide it's possible to do without
case "get_DynamicRegistrationSupported":
ProcessIsDynamicSupported (caller, ins);
break;
#endif
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 09:08:15 +03:00
case "SetupBlock":
case "SetupBlockUnsafe":
return ProcessSetupBlock (caller, ins);
case ".ctor":
if (!mr.DeclaringType.Is (Namespaces.ObjCRuntime, "BlockLiteral"))
break;
return ProcessBlockLiteralConstructor (caller, ins);
[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 13:33:48 +03:00
}
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 09:08:15 +03:00
return 0;
[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 13:33:48 +03:00
}
protected virtual void ProcessLoadStaticField (MethodDefinition caller, Instruction ins)
{
FieldReference fr = ins.Operand as FieldReference;
switch (fr?.Name) {
case "IsARM64CallingConvention":
ProcessIsARM64CallingConvention (caller, ins);
break;
case "Arch":
// https://app.asana.com/0/77259014252/77812690163
ProcessRuntimeArch (caller, ins);
break;
}
[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 13:33:48 +03:00
}
void ProcessEnsureUIThread (MethodDefinition caller, Instruction ins)
{
if (Optimizations.RemoveUIThreadChecks != true)
return;
// Verify we're checking the right get_EnsureUIThread call
var declaringTypeNamespace = LinkContext.App.Platform == Utils.ApplePlatform.MacOSX ? Namespaces.AppKit : Namespaces.UIKit;
var declaringTypeName = LinkContext.App.Platform == Utils.ApplePlatform.MacOSX ? "NSApplication" : "UIApplication";
[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 13:33:48 +03:00
var mr = ins.Operand as MethodReference;
if (!mr.DeclaringType.Is (declaringTypeNamespace, declaringTypeName))
[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 13:33:48 +03:00
return;
// Verify a few assumptions before doing anything
const string operation = "remove calls to [NS|UI]Application::EnsureUIThread";
[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 13:33:48 +03:00
if (!ValidateInstruction (caller, ins, operation, Code.Call))
return;
// This is simple: just remove the call
Nop (ins); // call void UIKit.UIApplication::EnsureUIThread()
}
void ProcessIntPtrSize (MethodDefinition caller, Instruction ins)
{
#if NET
if (!GetInlineIntPtrSize (caller.Module.Assembly))
return;
#else
[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 13:33:48 +03:00
if (!InlineIntPtrSize)
return;
#endif
[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 13:33:48 +03:00
// This will inline IntPtr.Size to load the corresponding constant value instead
// Verify we're checking the right get_Size call
var mr = ins.Operand as MethodReference;
if (!mr.DeclaringType.Is ("System", "IntPtr"))
return;
// We're fine, inline the get_Size call
ins.OpCode = Arch == 8 ? OpCodes.Ldc_I4_8 : OpCodes.Ldc_I4_4;
ins.Operand = null;
}
bool? IsDirectBindingConstant (TypeDefinition type)
{
return type.IsNSObject (LinkContext) ? type.GetIsDirectBindingConstant (LinkContext) : null;
}
[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 13:33:48 +03:00
void ProcessIsDirectBinding (MethodDefinition caller, Instruction ins)
{
const string operation = "inline IsDirectBinding";
if (Optimizations.InlineIsDirectBinding != true)
return;
#if NET
bool? isdirectbinding_constant = IsDirectBindingConstant (caller.DeclaringType);
#endif
[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 13:33:48 +03:00
// If we don't know the constant isdirectbinding value, then we can't inline anything
if (!isdirectbinding_constant.HasValue)
return;
// Verify we're checking the right get_IsDirectBinding call
var mr = ins.Operand as MethodReference;
if (!mr.DeclaringType.Is (Namespaces.Foundation, "NSObject"))
return;
// Verify a few assumptions before doing anything
if (!ValidateInstruction (caller, ins.Previous, operation, Code.Ldarg_0))
return;
if (!ValidateInstruction (caller, ins, operation, Code.Call))
return;
// Clearing the branch succeeded, so clear the condition too
// ldarg.0
Nop (ins.Previous);
// call System.Boolean Foundation.NSObject::get_IsDirectBinding()
ins.OpCode = isdirectbinding_constant.Value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0;
ins.Operand = null;
}
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 09:08:15 +03:00
#if !NET
void ProcessIsDynamicSupported (MethodDefinition caller, Instruction ins)
{
const string operation = "inline Runtime.DynamicRegistrationSupported";
if (Optimizations.InlineDynamicRegistrationSupported != true)
return;
// Verify we're checking the right Runtime.IsDynamicSupported call
var mr = ins.Operand as MethodReference;
if (!mr.DeclaringType.Is (Namespaces.ObjCRuntime, "Runtime"))
return;
if (!ValidateInstruction (caller, ins, operation, Code.Call))
return;
// We're fine, inline the Runtime.IsDynamicSupported condition
ins.OpCode = LinkContext.App.DynamicRegistrationSupported ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0;
ins.Operand = null;
}
#endif
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 09:08:15 +03:00
int ProcessSetupBlock (MethodDefinition caller, Instruction ins)
{
if (Optimizations.OptimizeBlockLiteralSetupBlock != true)
return 0;
// This will optimize calls to SetupBlock and SetupBlockUnsafe by calculating the signature for the block
// (which both SetupBlock and SetupBlockUnsafe do), and then rewrite the code to call SetupBlockImpl instead
// (which takes the block signature as an argument instead of calculating it). This is required to
// remove the dynamic registrar, because calculating the block signature is done in the dynamic registrar.
//
// This code is a mirror of the code in BlockLiteral.SetupBlock (to calculate the block signature).
var mr = ins.Operand as MethodReference;
if (!mr.DeclaringType.Is (Namespaces.ObjCRuntime, "BlockLiteral"))
return 0;
if (caller.Name == "GetBlockForDelegate" && caller.DeclaringType.Is ("ObjCRuntime", "BlockLiteral"))
return 0; // BlockLiteral.GetBlockForDelegate contains a non-optimizable call to SetupBlock, and this way we don't show any warnings to users about things they can't do anything about.
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 09:08:15 +03:00
string signature = null;
try {
// We need to figure out the type of the first argument to the call to SetupBlock[Impl].
//
// Example sequence:
//
// ldsfld ObjCRuntime.Trampolines/DJSContextExceptionHandler ObjCRuntime.Trampolines/SDJSContextExceptionHandler::Handler
// ldarg.1
// call System.Void ObjCRuntime.BlockLiteral::SetupBlockUnsafe(System.Delegate, System.Delegate)
//
// Locating the instruction that loads the first argument can be complicated, so we simplify by making a few assumptions:
// 1. The instruction immediately before the call instruction (which would load the last argument) is a Push1/Pop0 instruction.
// This avoids running into trouble when the instruction does something else (it could be a any other instruction, which would throw off the next calculations)
// 2. We have a whitelist of instructions we know how to calculate the type for, and which we use on the second to last instruction before the call instruction
// First verify the Push1/Pop0 behavior in point 1.
var prev = ins.Previous;
while (prev.OpCode.Code == Code.Nop)
prev = prev.Previous; // Skip any nops.
if (prev.OpCode.StackBehaviourPush != StackBehaviour.Push1) {
2020-01-31 23:02:52 +03:00
//todo: localize mmp error 2106
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MM2106, caller, ins.Offset, mr.Name, prev));
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 09:08:15 +03:00
return 0;
} else if (prev.OpCode.StackBehaviourPop != StackBehaviour.Pop0) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MM2106, caller, ins.Offset, mr.Name, prev));
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 09:08:15 +03:00
return 0;
}
var loadTrampolineInstruction = prev.Previous;
while (loadTrampolineInstruction.OpCode.Code == Code.Nop)
loadTrampolineInstruction = loadTrampolineInstruction.Previous; // Skip any nops.
// Then find the type of the previous instruction (the first argument to SetupBlock[Unsafe])
var trampolineDelegateType = GetPushedType (caller, loadTrampolineInstruction);
if (trampolineDelegateType == null) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MM2106_A, caller, ins.Offset, mr.Name, loadTrampolineInstruction));
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 09:08:15 +03:00
return 0;
}
if (trampolineDelegateType.Is ("System", "Delegate") || trampolineDelegateType.Is ("System", "MulticastDelegate")) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MM2106_B, caller, trampolineDelegateType.FullName, mr.Name));
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 09:08:15 +03:00
return 0;
}
// Calculate the block signature.
var blockSignature = false;
MethodReference userMethod = null;
// First look for any [UserDelegateType] attributes on the trampoline delegate type.
var userDelegateType = GetUserDelegateType (trampolineDelegateType);
if (userDelegateType != null) {
var userMethodDefinition = GetDelegateInvoke (userDelegateType);
userMethod = InflateMethod (userDelegateType, userMethodDefinition);
blockSignature = true;
} else {
// Couldn't find a [UserDelegateType] attribute, use the type of the actual trampoline instead.
var userMethodDefinition = GetDelegateInvoke (trampolineDelegateType);
userMethod = InflateMethod (trampolineDelegateType, userMethodDefinition);
blockSignature = false;
}
// No luck finding the signature, so give up.
if (userMethod == null) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MM2106_C, caller, ins.Offset, trampolineDelegateType.FullName));
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 09:08:15 +03:00
return 0;
}
var parameters = new TypeReference [userMethod.Parameters.Count];
for (int p = 0; p < parameters.Length; p++)
parameters [p] = userMethod.Parameters [p].ParameterType;
signature = LinkContext.Target.StaticRegistrar.ComputeSignature (userMethod.DeclaringType, false, userMethod.ReturnType, parameters, userMethod.Resolve (), isBlockSignature: blockSignature);
} catch (Exception e) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, e, caller, ins, Errors.MM2106_D, caller, ins.Offset, e.Message));
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 09:08:15 +03:00
return 0;
}
// We got the information we need: rewrite the IL.
var instructions = caller.Body.Instructions;
var index = instructions.IndexOf (ins);
// Inject the extra arguments
instructions.Insert (index, Instruction.Create (OpCodes.Ldstr, signature));
instructions.Insert (index, Instruction.Create (mr.Name == "SetupBlockUnsafe" ? OpCodes.Ldc_I4_0 : OpCodes.Ldc_I4_1));
// Change the call to call SetupBlockImpl instead
ins.Operand = GetBlockSetupImpl (caller, ins);
//Driver.Log (4, "Optimized call to BlockLiteral.SetupBlock in {0} at offset {1} with delegate type {2} and signature {3}", caller, ins.Offset, delegateType.FullName, signature);
return 2;
}
internal static bool IsBlockLiteralCtor_Type_String (MethodDefinition md)
{
if (!md.HasParameters)
return false;
if (md.Parameters.Count != 4)
return false;
if (!(md.Parameters [0].ParameterType is PointerType pt) || !pt.ElementType.Is ("System", "Void"))
return false;
if (!md.Parameters [1].ParameterType.Is ("System", "Object"))
return false;
if (!md.Parameters [2].ParameterType.Is ("System", "Type"))
return false;
if (!md.Parameters [3].ParameterType.Is ("System", "String"))
return false;
return true;
}
int ProcessBlockLiteralConstructor (MethodDefinition caller, Instruction ins)
{
if (Optimizations.OptimizeBlockLiteralSetupBlock != true)
return 0;
// This will optimize calls to this BlockLiteral constructor:
// (void* ptr, object context, Type trampolineType, string trampolineMethod)
// by calculating the signature for the block using the last two arguments,
// and then rewrite the code to call this constructor overload instead:
// (void* ptr, object context, string signature)
// This is required to remove the dynamic registrar, because calculating the block signature
// is done in the dynamic registrar.
//
// This code is a mirror of the code in BlockLiteral.SetupBlock (to calculate the block signature).
var mr = ins.Operand as MethodReference;
if (!mr.DeclaringType.Is (Namespaces.ObjCRuntime, "BlockLiteral"))
return 0;
var md = mr.Resolve ();
if (!IsBlockLiteralCtor_Type_String (md))
return 0;
string signature = null;
Instruction sequenceStart;
try {
// We need to figure out the last argument to the call to the ctor
//
// Example sequence:
//
// ldarg.0
// ldarg.1
// ldtoken ...
// call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
// ldstr ...
// newobj BlockLiteral (void*, System.Object, System.Type, System.String)
//
// Verify 'ldstr ...'
var loadString = GetPreviousSkippingNops (ins);
if (loadString.OpCode != OpCodes.Ldstr) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MM2106 /* Could not optimize the call to BlockLiteral.{2} in {0} at offset {1} because the previous instruction was unexpected ({3}) */, caller, ins.Offset, mr.Name, loadString));
return 0;
}
// Verify 'call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)'
var callGetTypeFromHandle = GetPreviousSkippingNops (loadString);
if (callGetTypeFromHandle.OpCode != OpCodes.Call || !(callGetTypeFromHandle.Operand is MethodReference methodOperand) || methodOperand.Name != "GetTypeFromHandle" || !methodOperand.DeclaringType.Is ("System", "Type")) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MM2106 /* Could not optimize the call to BlockLiteral.{2} in {0} at offset {1} because the previous instruction was unexpected ({3}) */, caller, ins.Offset, mr.Name, callGetTypeFromHandle));
return 0;
}
// Verify 'ldtoken ...'
var loadType = GetPreviousSkippingNops (callGetTypeFromHandle);
if (loadType.OpCode != OpCodes.Ldtoken) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MM2106 /* Could not optimize the call to BlockLiteral.{2} in {0} at offset {1} because the previous instruction was unexpected ({3}) */, caller, ins.Offset, mr.Name, loadType));
return 0;
}
// Then find the type of the previous instruction
var trampolineContainerTypeReference = loadType.Operand as TypeReference;
if (trampolineContainerTypeReference is null) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MM2106 /* Could not optimize the call to BlockLiteral.{2} in {0} at offset {1} because the previous instruction was unexpected ({3}) */, caller, ins.Offset, mr.Name, loadType.Operand));
return 0;
}
var trampolineContainerType = trampolineContainerTypeReference.Resolve ();
if (trampolineContainerType is null) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MM2106 /* Could not optimize the call to BlockLiteral.{2} in {0} at offset {1} because the previous instruction was unexpected ({3}) */, caller, ins.Offset, mr.Name, trampolineContainerTypeReference));
return 0;
}
// Find the trampoline method
var trampolineMethodName = (string) loadString.Operand;
var trampolineMethods = trampolineContainerType.Methods.Where (v => v.Name == trampolineMethodName).ToArray ();
if (trampolineMethods.Count () != 1) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MX2106_E /* Could not optimize the call to BlockLiteral.{2} in {0} at offset {1} because the more than one method named '{3}' was found in the type '{4}. /* Errors.MM2106 */, caller, ins.Offset, mr.Name, trampolineMethodName, trampolineContainerType.FullName));
return 0;
}
var trampolineMethod = trampolineMethods [0];
if (!trampolineMethod.HasParameters || trampolineMethod.Parameters.Count < 1) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MX2106_F /* Could not optimize the call to BlockLiteral.{2} in {0} at offset {1} because the method '{3}' must have at least one parameter. */, caller, ins.Offset, mr.Name, trampolineContainerType.FullName + "::" + trampolineMethodName));
return 0;
}
// Check that the method's first parameter is either IntPtr, void* or BlockLiteral*
var firstParameterType = trampolineMethod.Parameters [0].ParameterType;
if (firstParameterType.Is ("System", "IntPtr")) {
// ok
} else if (firstParameterType is PointerType ptrType) {
var ptrTargetType = ptrType.ElementType;
if (!(ptrTargetType.Is ("System", "Void") || ptrTargetType.Is ("ObjCRuntime", "BlockLiteral"))) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MX2106_G /* Could not optimize the call to BlockLiteral.{2} in {0} at offset {1} because the first parameter in the method '{3}' isn't 'System.IntPtr', 'void*' or 'ObjCRuntime.BlockLiteral*' (it's '{4}') */, caller, ins.Offset, mr.Name, trampolineContainerType.FullName + "::" + trampolineMethodName, firstParameterType.FullName));
return 0;
}
// ok
} else {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MX2106_G /* Could not optimize the call to BlockLiteral.{2} in {0} at offset {1} because the first parameter in the method '{3}' isn't 'System.IntPtr', 'void*' or 'ObjCRuntime.BlockLiteral*' (it's '{4}') */, caller, ins.Offset, mr.Name, trampolineContainerType.FullName + "::" + trampolineMethodName, firstParameterType.FullName));
return 0;
}
// Check that the method has [UnmanagedCallersOnly]
if (!trampolineMethod.HasCustomAttributes || !trampolineMethod.CustomAttributes.Any (v => v.AttributeType.Is ("System.Runtime.InteropServices", "UnmanagedCallersOnlyAttribute"))) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, caller, ins, Errors.MX2106_H /* Could not optimize the call to BlockLiteral.{2} in {0} at offset {1} because the method '{3}' does not have an [UnmanagedCallersOnly] attribute. */, caller, ins.Offset, mr.Name, trampolineContainerType.FullName + "::" + trampolineMethodName));
return 0;
}
// Calculate the block signature.
var blockSignature = true;
var parameters = new TypeReference [trampolineMethod.Parameters.Count];
for (int p = 0; p < parameters.Length; p++)
parameters [p] = trampolineMethod.Parameters [p].ParameterType;
signature = LinkContext.Target.StaticRegistrar.ComputeSignature (trampolineMethod.DeclaringType, false, trampolineMethod.ReturnType, parameters, trampolineMethod.Resolve (), isBlockSignature: blockSignature);
sequenceStart = loadType;
} catch (Exception e) {
ErrorHelper.Show (ErrorHelper.CreateWarning (LinkContext.App, 2106, e, caller, ins, Errors.MM2106_D, caller, ins.Offset, e.Message));
return 0;
}
// We got the information we need: rewrite the IL.
var instructions = caller.Body.Instructions;
var index = instructions.IndexOf (sequenceStart);
int instructionDiff = 0;
while (instructions [index] != ins) {
instructions.RemoveAt (index);
instructionDiff--;
}
// Inject the extra arguments
instructions.Insert (index, Instruction.Create (OpCodes.Ldstr, signature));
instructionDiff++;
// Change the call to call the ctor with the string signature parameter instead
ins.Operand = GetBlockLiteralConstructor (caller, ins);
Driver.Log (4, "Optimized call to BlockLiteral..ctor in {0} at offset {1} with signature {2}", caller, ins.Offset, signature);
return instructionDiff;
}
static Instruction GetPreviousSkippingNops (Instruction ins)
{
do {
ins = ins.Previous;
} while (ins.OpCode == OpCodes.Nop);
return ins;
}
int ProcessIsARM64CallingConvention (MethodDefinition caller, Instruction ins)
{
const string operation = "inline Runtime.IsARM64CallingConvention";
if (Optimizations.InlineIsARM64CallingConvention != true)
return 0;
if (!is_arm64_calling_convention.HasValue)
return 0;
// Verify we're checking the right IsARM64CallingConvention field
var fr = ins.Operand as FieldReference;
if (!fr.DeclaringType.Is (Namespaces.ObjCRuntime, "Runtime"))
return 0;
if (!ValidateInstruction (caller, ins, operation, Code.Ldsfld))
return 0;
// We're fine, inline the Runtime.IsARM64CallingConvention value
ins.OpCode = is_arm64_calling_convention.Value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0;
ins.Operand = null;
return 0;
}
void ProcessRuntimeArch (MethodDefinition caller, Instruction ins)
{
const string operation = "inline Runtime.Arch";
if (Optimizations.InlineRuntimeArch != true)
return;
// Verify we're checking the right Arch field
var fr = ins.Operand as FieldReference;
if (!fr.DeclaringType.Is (Namespaces.ObjCRuntime, "Runtime"))
return;
// Verify a few assumptions before doing anything
if (!ValidateInstruction (caller, ins, operation, Code.Ldsfld))
return;
// We're fine, inline the Runtime.Arch condition
// The enum values are Runtime.DEVICE = 0 and Runtime.SIMULATOR = 1,
ins.OpCode = Device ? OpCodes.Ldc_I4_0 : OpCodes.Ldc_I4_1;
ins.Operand = null;
}
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 09:08:15 +03:00
// Returns the type of the value pushed on the stack by the given instruction.
// Returns null for unknown instructions, or for instructions that don't push anything on the stack.
TypeReference GetPushedType (MethodDefinition method, Instruction ins)
{
var index = 0;
switch (ins.OpCode.Code) {
case Code.Ldloc_0:
case Code.Ldarg_0:
index = 0;
break;
case Code.Ldloc_1:
case Code.Ldarg_1:
index = 1;
break;
case Code.Ldloc_2:
case Code.Ldarg_2:
index = 2;
break;
case Code.Ldloc_3:
case Code.Ldarg_3:
index = 3;
break;
case Code.Ldloc:
case Code.Ldloc_S:
return ((VariableDefinition) ins.Operand).VariableType;
case Code.Ldarg:
case Code.Ldarg_S:
return ((ParameterDefinition) ins.Operand).ParameterType;
case Code.Ldfld:
case Code.Ldsfld:
return ((FieldReference) ins.Operand).FieldType;
case Code.Call:
case Code.Calli:
case Code.Callvirt:
return ((MethodReference) ins.Operand).ReturnType;
default:
return null;
}
switch (ins.OpCode.Code) {
case Code.Ldloc:
case Code.Ldloc_0:
case Code.Ldloc_1:
case Code.Ldloc_2:
case Code.Ldloc_3:
return method.Body.Variables [index].VariableType;
case Code.Ldarg:
case Code.Ldarg_0:
case Code.Ldarg_1:
case Code.Ldarg_2:
case Code.Ldarg_3:
if (method.IsStatic) {
return method.Parameters [index].ParameterType;
} else if (index == 0) {
return method.DeclaringType;
} else {
return method.Parameters [index - 1].ParameterType;
}
default:
return null;
}
}
// Find the value of the [UserDelegateType] attribute on the specified delegate
TypeReference GetUserDelegateType (TypeReference delegateType)
{
var delegateTypeDefinition = delegateType.Resolve ();
foreach (var attrib in delegateTypeDefinition.CustomAttributes) {
var attribType = attrib.AttributeType;
if (!attribType.Is (Namespaces.ObjCRuntime, "UserDelegateTypeAttribute"))
continue;
return attrib.ConstructorArguments [0].Value as TypeReference;
}
return null;
}
MethodDefinition GetDelegateInvoke (TypeReference delegateType)
{
var td = delegateType.Resolve ();
foreach (var method in td.Methods) {
if (method.Name == "Invoke")
return method;
}
return null;
}
MethodDefinition setupblock_def;
MethodReference GetBlockSetupImpl (MethodDefinition caller, Instruction ins)
{
if (setupblock_def == null) {
var type = LinkContext.GetAssembly (Driver.GetProductAssembly (LinkContext.Target.App)).MainModule.GetType (Namespaces.ObjCRuntime, "BlockLiteral");
foreach (var method in type.Methods) {
if (method.Name != "SetupBlockImpl")
continue;
setupblock_def = method;
setupblock_def.IsPublic = true; // Make sure the method is callable from the optimized code.
break;
}
if (setupblock_def == null)
throw ErrorHelper.CreateError (LinkContext.App, 99, caller, ins, Errors.MX0099, $"could not find the method {Namespaces.ObjCRuntime}.BlockLiteral.SetupBlockImpl");
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 09:08:15 +03:00
}
return caller.Module.ImportReference (setupblock_def);
}
MethodDefinition block_ctor_def;
MethodReference GetBlockLiteralConstructor (MethodDefinition caller, Instruction ins)
{
if (block_ctor_def is null) {
var type = LinkContext.GetAssembly (Driver.GetProductAssembly (LinkContext.Target.App)).MainModule.GetType (Namespaces.ObjCRuntime, "BlockLiteral");
foreach (var method in type.Methods) {
if (!method.IsConstructor)
continue;
if (method.IsStatic)
continue;
if (!method.HasParameters || method.Parameters.Count != 3)
continue;
if (!(method.Parameters [0].ParameterType is PointerType pt) || !pt.ElementType.Is ("System", "Void"))
continue;
if (!method.Parameters [1].ParameterType.Is ("System", "Object"))
continue;
if (!method.Parameters [2].ParameterType.Is ("System", "String"))
continue;
block_ctor_def = method;
break;
}
if (block_ctor_def is null)
throw ErrorHelper.CreateError (LinkContext.App, 99, caller, ins, Errors.MX0099, $"could not find the constructor ObjCRuntime.BlockLiteral (void*, object, string)");
}
return caller.Module.ImportReference (block_ctor_def);
}
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 09:08:15 +03:00
MethodReference InflateMethod (TypeReference inflatedDeclaringType, MethodDefinition openMethod)
{
var git = inflatedDeclaringType as GenericInstanceType;
if (git == null)
return openMethod;
var inflatedReturnType = TypeReferenceExtensions.InflateGenericType (git, openMethod.ReturnType);
var mr = new MethodReference (openMethod.Name, inflatedReturnType, git);
if (openMethod.HasParameters) {
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 09:08:15 +03:00
for (int i = 0; i < openMethod.Parameters.Count; i++) {
var inflatedParameterType = TypeReferenceExtensions.InflateGenericType (git, openMethod.Parameters [i].ParameterType);
var p = new ParameterDefinition (openMethod.Parameters [i].Name, openMethod.Parameters [i].Attributes, inflatedParameterType);
mr.Parameters.Add (p);
}
}
return mr;
}
2016-04-21 15:57:02 +03:00
}
}