From 8969f39132cd2b43bed3aaf65d9c8ae9f13aeb04 Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Tue, 1 Oct 2019 18:26:50 -0400 Subject: [PATCH] [linker] Ensure we can remove NSUrlSessionHandler if unused Moving `NSUrlSessionHandler` into the platform assemblies (e.g. Xamarin.iOS.dll) instead of System.Net.Http.dll was not optimal as it prevented the linker to remove it when the application did not use it. This shows a lot in an "helloworld" type of application (see below) but in real life most of the removed code gets used by something else (and is included. ``` Directories / Files helloworld-d16-4.app helloworld-fixed.app diff % ./ AppIcon60x60@2x.png 2,632 2,632 0 0.00 % AppIcon76x76@2x~ipad.png 3,125 3,125 0 0.00 % archived-expanded-entitlements.xcent 181 181 0 0.00 % Assets.car 75,688 75,688 0 0.00 % embedded.mobileprovision 8,456 8,456 0 0.00 % helloworld 4,700,256 3,915,936 -784,320 -16.69 % helloworld.aotdata.arm64 1,448 1,432 -16 -1.10 % helloworld.exe 6,144 6,144 0 0.00 % Info.plist 1,712 1,712 0 0.00 % mscorlib.aotdata.arm64 406,080 364,104 -41,976 -10.34 % mscorlib.dll 561,664 501,760 -59,904 -10.67 % NOTICE 159 159 0 0.00 % PkgInfo 8 8 0 0.00 % System.aotdata.arm64 17,008 936 -16,072 -94.50 % System.Core.aotdata.arm64 2,432 0 -2,432 -100.00 % System.Core.dll 4,608 0 -4,608 -100.00 % System.dll 32,768 5,120 -27,648 -84.38 % System.Net.Http.aotdata.arm64 31,648 0 -31,648 -100.00 % System.Net.Http.dll 29,184 0 -29,184 -100.00 % Xamarin.iOS.aotdata.arm64 62,544 33,464 -29,080 -46.50 % Xamarin.iOS.dll 92,672 53,248 -39,424 -42.54 % ./_CodeSignature CodeResources 7,575 6,655 -920 -12.15 % ./LaunchScreen.storyboardc 01J-lp-oVM-view-Ze5-6b-2t3.nib 1,831 1,835 4 0.22 % Info.plist 258 258 0 0.00 % UIViewController-01J-lp-oVM.nib 896 896 0 0.00 % ./Main.storyboardc BYZ-38-t0r-view-8bC-Xf-vdC.nib 1,836 1,832 -4 -0.22 % Info.plist 258 258 0 0.00 % UIViewController-BYZ-38-t0r.nib 916 916 0 0.00 % Statistics Native subtotal 4,700,256 3,915,936 -784,320 -16.69 % Executable 4,700,256 3,915,936 -784,320 -16.69 % AOT data *.aotdata 0 0 0 - Managed *.dll/exe 727,040 566,272 -160,768 -22.11 % TOTAL 6,053,987 4,986,755 -1,067,232 -17.63 % ``` --- src/Foundation/NSUrlSessionHandler.cs | 16 ++++++---------- src/ObjCRuntime/RuntimeOptions.cs | 1 - tools/linker/MarkNSObjects.cs | 4 +--- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/Foundation/NSUrlSessionHandler.cs b/src/Foundation/NSUrlSessionHandler.cs index b559c2f8fabb..20bb46b6f5c9 100644 --- a/src/Foundation/NSUrlSessionHandler.cs +++ b/src/Foundation/NSUrlSessionHandler.cs @@ -459,8 +459,6 @@ protected override async Task SendAsync (HttpRequestMessage return await tcs.Task.ConfigureAwait (false); } - // Needed since we strip during linking since we're inside a product assembly. - [Preserve (AllMembers = true)] partial class NSUrlSessionHandlerDelegate : NSUrlSessionDataDelegate { readonly NSUrlSessionHandler sessionHandler; @@ -487,6 +485,7 @@ InflightData GetInflightData (NSUrlSessionTask task) return null; } + [Preserve (Conditional = true)] public override void DidReceiveResponse (NSUrlSession session, NSUrlSessionDataTask dataTask, NSUrlResponse response, Action completionHandler) { var inflight = GetInflightData (dataTask); @@ -549,6 +548,7 @@ public override void DidReceiveResponse (NSUrlSession session, NSUrlSessionDataT completionHandler (NSUrlSessionResponseDisposition.Allow); } + [Preserve (Conditional = true)] public override void DidReceiveData (NSUrlSession session, NSUrlSessionDataTask dataTask, NSData data) { var inflight = GetInflightData (dataTask); @@ -560,6 +560,7 @@ public override void DidReceiveData (NSUrlSession session, NSUrlSessionDataTask SetResponse (inflight); } + [Preserve (Conditional = true)] public override void DidCompleteWithError (NSUrlSession session, NSUrlSessionTask task, NSError error) { var inflight = GetInflightData (task); @@ -608,16 +609,19 @@ void SetResponse (InflightData inflight) } } + [Preserve (Conditional = true)] public override void WillCacheResponse (NSUrlSession session, NSUrlSessionDataTask dataTask, NSCachedUrlResponse proposedResponse, Action completionHandler) { completionHandler (sessionHandler.DisableCaching ? null : proposedResponse); } + [Preserve (Conditional = true)] public override void WillPerformHttpRedirection (NSUrlSession session, NSUrlSessionTask task, NSHttpUrlResponse response, NSUrlRequest newRequest, Action completionHandler) { completionHandler (sessionHandler.AllowAutoRedirect ? newRequest : null); } + [Preserve (Conditional = true)] public override void DidReceiveChallenge (NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action completionHandler) { var inflight = GetInflightData (task); @@ -705,8 +709,6 @@ static bool TryGetAuthenticationType (NSUrlProtectionSpace protectionSpace, out } } - // Needed since we strip during linking since we're inside a product assembly. - [Preserve (AllMembers = true)] class InflightData : IDisposable { public readonly object Lock = new object (); @@ -745,8 +747,6 @@ protected virtual void Dispose (bool disposing) } - // Needed since we strip during linking since we're inside a product assembly. - [Preserve (AllMembers = true)] class NSUrlSessionDataTaskStreamContent : MonoStreamContent { Action disposed; @@ -857,8 +857,6 @@ protected internal override bool TryComputeLength (out long length) } } - // Needed since we strip during linking since we're inside a product assembly. - [Preserve (AllMembers = true)] class NSUrlSessionDataTaskStream : Stream { readonly Queue data; @@ -1004,8 +1002,6 @@ public override void Write (byte [] buffer, int offset, int count) } } - // Needed since we strip during linking since we're inside a product assembly. - [Preserve (AllMembers = true)] class WrappedNSInputStream : NSInputStream { NSStreamStatus status; diff --git a/src/ObjCRuntime/RuntimeOptions.cs b/src/ObjCRuntime/RuntimeOptions.cs index 0be4980ca743..bbcbaecb8d57 100644 --- a/src/ObjCRuntime/RuntimeOptions.cs +++ b/src/ObjCRuntime/RuntimeOptions.cs @@ -150,7 +150,6 @@ internal static RuntimeOptions Read () } } - [Preserve] // always present but re-written by the linker internal static HttpMessageHandler GetHttpMessageHandler () { var options = RuntimeOptions.Read (); diff --git a/tools/linker/MarkNSObjects.cs b/tools/linker/MarkNSObjects.cs index eca84e849ff2..af4c10942f2f 100644 --- a/tools/linker/MarkNSObjects.cs +++ b/tools/linker/MarkNSObjects.cs @@ -29,7 +29,6 @@ // using System; -using System.Collections.Generic; using Mono.Cecil; using Mono.Linker; @@ -154,8 +153,7 @@ static bool IsProductMethod (MethodDefinition method) static bool IsProductType (TypeDefinition type) { - var name = type.Module.Assembly.Name.Name; - return name == ProductAssembly || name == "System.Net.Http"; + return type.Module.Assembly.Name.Name == ProductAssembly; } } }