Skip to content

Commit

Permalink
Move DynamicRegistrationSupported change earlier, along with the
Browse files Browse the repository at this point in the history
detection code.

This solve the issue that `ILLink` does a similar job _before_ we have
the chance to disable the dynamic registrar.
  • Loading branch information
Sebastien Pouliot committed May 7, 2021
1 parent 975e045 commit 224c3d4
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 15 deletions.
13 changes: 4 additions & 9 deletions tools/linker/CoreOptimizeGeneratedCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -711,15 +711,6 @@ protected override void Process (MethodDefinition method)
return;
}

if (!LinkContext.App.DynamicRegistrationSupported && method.Name == "get_DynamicRegistrationSupported" && method.DeclaringType.Is (Namespaces.ObjCRuntime, "Runtime")) {
// Rewrite to return 'false'
var instr = method.Body.Instructions;
instr.Clear ();
instr.Add (Instruction.Create (OpCodes.Ldc_I4_0));
instr.Add (Instruction.Create (OpCodes.Ret));
return; // nothing else to do here.
}

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;
Expand Down Expand Up @@ -759,9 +750,13 @@ protected virtual int ProcessCalls (MethodDefinition caller, Instruction ins)
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
case "SetupBlock":
case "SetupBlockUnsafe":
return ProcessSetupBlock (caller, ins);
Expand Down
29 changes: 23 additions & 6 deletions tools/linker/RegistrarRemovalTrackingStep.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Linker;
using Mono.Linker.Steps;

using Xamarin.Bundler;
using Xamarin.Linker;
#if !NET
using Mono.Linker.Steps;
using Mono.Tuner;
using Xamarin.Tuner;
#endif
Expand All @@ -25,7 +26,7 @@ public class RegistrarRemovalTrackingStep : ConfigurationAwareStep {

Optimizations Optimizations => Configuration.Application.Optimizations;

string PlatformAssembly => Configuration.PlatformAssembly;
string PlatformAssemblyName => Configuration.PlatformAssembly;

protected override void TryProcessAssembly (AssemblyDefinition assembly)
{
Expand All @@ -36,7 +37,7 @@ public class RegistrarRemovalTrackingStep : BaseStep {

Optimizations Optimizations => ((DerivedLinkContext) Context).App.Optimizations;

string PlatformAssembly => ((MobileProfile) Profile.Current).ProductAssembly;
string PlatformAssemblyName => ((MobileProfile) Profile.Current).ProductAssembly;

int WarnCode => 2107; // for compatibility

Expand All @@ -46,6 +47,7 @@ protected override void ProcessAssembly (AssemblyDefinition assembly)
base.ProcessAssembly (assembly);
}
#endif
AssemblyDefinition PlatformAssembly;

bool dynamic_registration_support_required;

Expand All @@ -63,8 +65,11 @@ bool RequiresDynamicRegistrar (AssemblyDefinition assembly, bool warnIfRequired)
return false;

// The product assembly itself is safe as long as it's linked
if (Profile.IsProductAssembly (assembly))
return Annotations.GetAction (assembly) != AssemblyAction.Link;
if (Profile.IsProductAssembly (assembly)) {
if (Annotations.GetAction (assembly) != AssemblyAction.Link)
return false;
PlatformAssembly = assembly;
}

// Can't touch the forbidden fruit in the product assembly unless there's a reference to it
var hasProductReference = false;
Expand All @@ -78,7 +83,7 @@ bool RequiresDynamicRegistrar (AssemblyDefinition assembly, bool warnIfRequired)
return false;

// Check if the assembly references any methods that require the dynamic registrar
var productAssemblyName = PlatformAssembly;
var productAssemblyName = PlatformAssemblyName;
var requires = false;
foreach (var mr in assembly.MainModule.GetMemberReferences ()) {
if (mr.DeclaringType == null || string.IsNullOrEmpty (mr.DeclaringType.Namespace))
Expand Down Expand Up @@ -170,6 +175,18 @@ protected override void EndProcess ()
// If dynamic registration is not required, and removal of the dynamic registrar hasn't already
// been disabled, then we can remove it!
Optimizations.RemoveDynamicRegistrar = !dynamic_registration_support_required;
// ILLink will optimize `Runtime.Initialize` based on `DynamicRegistrationSupported` returning a constant (`true`)
// and this will runs before we have the chance to set it to `false` in `CoreOptimizedGeneratedCode` so we instead
// do the change here so the linker can do this without further ado
// note: it does not matter for _legacy_ so we apply the change (to earlier) to minimize the difference between them
if (PlatformAssembly != null) {
var method = PlatformAssembly.MainModule.GetType ("ObjCRuntime.Runtime").Methods.First ((n) => n.Name == "get_DynamicRegistrationSupported");
// Rewrite to return 'false'
var instr = method.Body.Instructions;
instr.Clear ();
instr.Add (Instruction.Create (OpCodes.Ldc_I4_0));
instr.Add (Instruction.Create (OpCodes.Ret));
}
Driver.Log (4, "Optimization dynamic registrar removal: {0}", Optimizations.RemoveDynamicRegistrar.Value ? "enabled" : "disabled");
#if MTOUCH
var app = (Context as DerivedLinkContext).App;
Expand Down

0 comments on commit 224c3d4

Please sign in to comment.