Skip to content

Commit 723f6c9

Browse files
committed
[dotnet-linker] Use [DynamicDependency] attributes instead of manual marking when optimizing generated code.
This makes it easier to move this code out of a custom linker step in the future. Also simplify a few things: * There's no need to compute whether the code is optimizable, because the result is never used. * Unify code to determine whether the InlineIsARM64CallingConvention optimization is to be applied. * Any code that modifies the current assembly now returns a boolean saying so (so that we know if the current assembly has to be saved). This even found a bug in NWWebSocketResponse, so fix that as well. Contributes towards #17693.
1 parent 4b3e065 commit 723f6c9

File tree

9 files changed

+314
-245
lines changed

9 files changed

+314
-245
lines changed

dotnet/targets/Xamarin.Shared.Sdk.targets

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@
550550
<_UseDynamicDependenciesForProtocolPreservation Condition="'$(_UseDynamicDependenciesForProtocolPreservation)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseDynamicDependenciesForProtocolPreservation>
551551
<_UseDynamicDependenciesForSmartEnumPreservation Condition="'$(_UseDynamicDependenciesForSmartEnumPreservation)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseDynamicDependenciesForSmartEnumPreservation>
552552
<_UseDynamicDependenciesForBlockCodePreservation Condition="'$(_UseDynamicDependenciesForBlockCodePreservation)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseDynamicDependenciesForBlockCodePreservation>
553+
<_UseDynamicDependenciesForGeneratedCodeOptimizations Condition="'$(_UseDynamicDependenciesForGeneratedCodeOptimizations)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseDynamicDependenciesForGeneratedCodeOptimizations>
553554
</PropertyGroup>
554555

555556
<PropertyGroup>
@@ -754,6 +755,7 @@
754755
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.PreserveProtocolsStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForProtocolPreservation)' == 'true'" />
755756
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.PreserveSmartEnumConversionsStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForSmartEnumPreservation)' == 'true'" />
756757
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.PreserveBlockCodeStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForBlockCodePreservation)' == 'true'" />
758+
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="Xamarin.Linker.Steps.OptimizeGeneratedCodeStep" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForGeneratedCodeOptimizations)' == 'true'" />
757759
<!-- The final decision to remove/keep the dynamic registrar must be done before the linking step -->
758760
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" BeforeStep="MarkStep" Type="MonoTouch.Tuner.RegistrarRemovalTrackingStep" />
759761
<!-- TODO: these steps should probably run after mark. -->
@@ -764,7 +766,7 @@
764766
IMarkHandlers which run during Mark
765767
-->
766768
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForBlockCodePreservation)' != 'true'" Type="Xamarin.Linker.Steps.PreserveBlockCodeHandler" />
767-
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true'" Type="Xamarin.Linker.OptimizeGeneratedCodeHandler" />
769+
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForGeneratedCodeOptimizations)' != 'true'" Type="Xamarin.Linker.OptimizeGeneratedCodeHandler" />
768770
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true'" Type="Xamarin.Linker.BackingFieldDelayHandler" />
769771
<_TrimmerCustomSteps Include="$(_AdditionalTaskAssembly)" Condition="'$(_AreAnyAssembliesTrimmed)' == 'true' And '$(_UseDynamicDependenciesForProtocolPreservation)' != 'true'" Type="Xamarin.Linker.MarkIProtocolHandler" />
770772
<!-- MarkDispatcher substeps will run for all marked assemblies. -->

src/Network/NWWebSocketResponse.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public bool EnumerateAdditionalHeaders (Action<string?, string?> handler)
7474

7575
unsafe {
7676
delegate* unmanaged<IntPtr, IntPtr, IntPtr, void> trampoline = &TrampolineEnumerateHeadersHandler;
77-
using var block = new BlockLiteral (trampoline, handler, typeof (NWWebSocketResponseStatus), nameof (TrampolineEnumerateHeadersHandler));
77+
using var block = new BlockLiteral (trampoline, handler, typeof (NWWebSocketResponse), nameof (TrampolineEnumerateHeadersHandler));
7878
return nw_ws_response_enumerate_additional_headers (GetCheckedHandle (), &block) != 0;
7979
}
8080
}

tools/common/Target.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,33 @@ static bool IsBoundAssembly (Assembly s)
507507

508508
return false;
509509
}
510+
511+
bool _set_arm64_calling_convention;
512+
bool? _is_arm64_calling_convention;
513+
public bool? InlineIsArm64CallingConventionForCurrentAbi {
514+
get {
515+
if (!_set_arm64_calling_convention) {
516+
if (Optimizations.InlineIsARM64CallingConvention == true) {
517+
// We can usually inline Runtime.InlineIsARM64CallingConvention if the generated code will execute on a single architecture
518+
switch (Abi & Abi.ArchMask) {
519+
case Abi.x86_64:
520+
_is_arm64_calling_convention = false;
521+
break;
522+
case Abi.ARM64:
523+
case Abi.ARM64e:
524+
_is_arm64_calling_convention = true;
525+
break;
526+
default:
527+
LinkContext.Exceptions.Add (Xamarin.Bundler.ErrorHelper.CreateWarning (99, Xamarin.Bundler.Errors.MX0099, $"unknown abi: {Abi}"));
528+
break;
529+
}
530+
}
531+
_set_arm64_calling_convention = true;
532+
}
533+
return _is_arm64_calling_convention;
534+
}
535+
}
536+
510537
#endif // !LEGACY_TOOLS
511538
}
512539
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using Mono.Cecil;
5+
6+
#nullable enable
7+
8+
namespace Xamarin.Linker.Steps {
9+
public class OptimizeGeneratedCodeStep : AssemblyModifierStep {
10+
protected override string Name { get; } = "Binding Optimizer";
11+
protected override int ErrorCode { get; } = 2020;
12+
13+
OptimizeGeneratedCodeData? data;
14+
15+
protected override bool IsActiveFor (AssemblyDefinition assembly)
16+
{
17+
return OptimizeGeneratedCodeHandler.IsActiveFor (assembly, Configuration.Profile, DerivedLinkContext.Annotations);
18+
}
19+
20+
protected override bool ProcessType (TypeDefinition type)
21+
{
22+
return ProcessMethods (type);
23+
}
24+
25+
protected override bool ProcessMethod (MethodDefinition method)
26+
{
27+
if (data is null) {
28+
data = new OptimizeGeneratedCodeData {
29+
LinkContext = DerivedLinkContext,
30+
InlineIsArm64CallingConvention = App.InlineIsArm64CallingConventionForCurrentAbi,
31+
Optimizations = App.Optimizations,
32+
Device = App.IsDeviceBuild,
33+
};
34+
}
35+
return OptimizeGeneratedCodeHandler.OptimizeMethod (data, method);
36+
}
37+
}
38+
}

tools/dotnet-linker/PreserveSmartEnumConversionsStep.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,10 @@ bool Preserve (Tuple<MethodDefinition, MethodDefinition> pair, bool alreadyProce
6161

6262
protected override bool ProcessType (TypeDefinition type)
6363
{
64-
var modified = false;
65-
66-
if (!type.HasMethods)
67-
return modified;
68-
69-
foreach (var method in type.Methods)
70-
modified |= ProcessMethod (method);
71-
72-
return modified;
64+
return base.ProcessMethods (type);
7365
}
7466

75-
bool ProcessMethod (MethodDefinition method)
67+
protected override bool ProcessMethod (MethodDefinition method)
7668
{
7769
static bool IsPropertyMethod (MethodDefinition method)
7870
{

tools/dotnet-linker/Steps/AssemblyModifierStep.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ protected virtual bool ProcessType (TypeDefinition type)
3535
return false;
3636
}
3737

38+
protected virtual bool ProcessMethod (MethodDefinition method)
39+
{
40+
return false;
41+
}
42+
3843
bool ProcessTypeImpl (TypeDefinition type)
3944
{
4045
var modified = ProcessType (type);
@@ -44,4 +49,15 @@ bool ProcessTypeImpl (TypeDefinition type)
4449
}
4550
return modified;
4651
}
52+
53+
protected bool ProcessMethods (TypeDefinition type)
54+
{
55+
if (!type.HasMethods)
56+
return false;
57+
58+
var modified = false;
59+
foreach (var method in type.Methods)
60+
modified |= ProcessMethod (method);
61+
return modified;
62+
}
4763
}

0 commit comments

Comments
 (0)