Skip to content

Commit d5b5419

Browse files
authored
[FixAbstractMethodsStep] Speedup the step (#4020)
By checking whether the assembly has a type reference to `Java.Lang.Object` first. `ModuleDefinition::HasTypeReference` call is relatively fast in cecil and by using it we save a lot of further processing. Measurements of the `_LinkAssembliesNoShrink` target (XA template, rebuild after touching MainActivity.cs, 5 runs average): Before: 160ms After: 52ms Update FixAbstractMethodsStep_SkipDimMembers test Write and load generated assemblies so that the AssemblyDefinition has image and ModuleDefinition::HasTypeReference works. Context: https://github.com/mono/cecil/blob/09a316c202f4c295c0c86ddb5f6c77be457a5b14/Mono.Cecil/ModuleDefinition.cs#L634 That introduced I/O exception on Windows: System.IO.IOException : The process cannot access the file 'MyAssembly.dll' because it is being used by another process. at System.IO.Directory.DeleteHelper(String fullPath, String userPath, Boolean recursive, Boolean throwOnTopLevelDirectoryNotFound, WIN32_FIND_DATA& data) at System.IO.Directory.Delete(String fullPath, String userPath, Boolean recursive, Boolean checkHost) at Xamarin.Android.Build.Tests.LinkerTests.FixAbstractMethodsStep_SkipDimMembers() in F:\A\xamarin-v000001-1\_work\2\s\src\Xamarin.Android.Build.Tasks\Tests\Xamarin.Android.Build.Tests\Tasks\LinkerTests.cs:line 67 Resolution: Properly dispose context and assemblies. Also refactor the test code to avoid deep blocks.
1 parent 1045e63 commit d5b5419

File tree

2 files changed

+42
-23
lines changed

2 files changed

+42
-23
lines changed

src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ internal bool FixAbstractMethods (AssemblyDefinition assembly)
6969

7070
bool FixAbstractMethodsUnconditional (AssemblyDefinition assembly)
7171
{
72+
if (!assembly.MainModule.HasTypeReference ("Java.Lang.Object"))
73+
return false;
74+
7275
bool changed = false;
7376
foreach (var type in assembly.MainModule.Types) {
7477
if (MightNeedFix (type))

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,44 +14,60 @@ public class LinkerTests : BaseTest
1414
[Test]
1515
public void FixAbstractMethodsStep_SkipDimMembers ()
1616
{
17+
var path = Path.Combine (Path.GetFullPath (XABuildPaths.TestOutputDirectory), "temp", TestName);
1718
var step = new FixAbstractMethodsStep ();
1819
var pipeline = new Pipeline ();
19-
var context = new LinkContext (pipeline);
2020

21-
var android = CreateFauxMonoAndroidAssembly ();
22-
var jlo = android.MainModule.GetType ("Java.Lang.Object");
21+
Directory.CreateDirectory (path);
2322

24-
context.Resolver.CacheAssembly (android);
23+
using (var context = new LinkContext (pipeline)) {
2524

26-
var assm = AssemblyDefinition.CreateAssembly (new AssemblyNameDefinition ("DimTest", new Version ()), "DimTest", ModuleKind.Dll);
27-
var void_type = assm.MainModule.ImportReference (typeof (void));
25+
context.Resolver.AddSearchDirectory (path);
26+
27+
var myAssemblyPath = Path.Combine (path, "MyAssembly.dll");
28+
29+
using (var android = CreateFauxMonoAndroidAssembly ()) {
30+
android.Write (Path.Combine (path, "Mono.Android.dll"));
31+
CreateAbstractIfaceImplementation (myAssemblyPath, android);
32+
}
33+
34+
using (var assm = context.Resolve (myAssemblyPath)) {
35+
step.Process (context);
2836

29-
// Create interface
30-
var iface = new TypeDefinition ("MyNamespace", "IMyInterface", TypeAttributes.Interface);
37+
var impl = assm.MainModule.GetType ("MyNamespace.MyClass");
3138

32-
var abstract_method = new MethodDefinition ("MyAbstractMethod", MethodAttributes.Abstract, void_type);
33-
var default_method = new MethodDefinition ("MyDefaultMethod", MethodAttributes.Public, void_type);
39+
Assert.IsTrue (impl.Methods.Any (m => m.Name == "MyAbstractMethod"), "We should have generated an override for MyAbstractMethod");
40+
Assert.IsFalse (impl.Methods.Any (m => m.Name == "MyDefaultMethod"), "We should not have generated an override for MyDefaultMethod");
41+
}
42+
}
3443

35-
iface.Methods.Add (abstract_method);
36-
iface.Methods.Add (default_method);
44+
Directory.Delete (path, true);
45+
}
3746

38-
assm.MainModule.Types.Add (iface);
47+
static void CreateAbstractIfaceImplementation (string assemblyPath, AssemblyDefinition android)
48+
{
49+
using (var assm = AssemblyDefinition.CreateAssembly (new AssemblyNameDefinition ("DimTest", new Version ()), "DimTest", ModuleKind.Dll)) {
50+
var void_type = assm.MainModule.ImportReference (typeof (void));
3951

40-
// Create implementing class
41-
var impl = new TypeDefinition ("MyNamespace", "MyClass", TypeAttributes.Public, jlo);
42-
impl.Interfaces.Add (new InterfaceImplementation (iface));
52+
// Create interface
53+
var iface = new TypeDefinition ("MyNamespace", "IMyInterface", TypeAttributes.Interface);
4354

44-
assm.MainModule.Types.Add (impl);
55+
var abstract_method = new MethodDefinition ("MyAbstractMethod", MethodAttributes.Abstract, void_type);
56+
var default_method = new MethodDefinition ("MyDefaultMethod", MethodAttributes.Public, void_type);
4557

46-
context.Resolver.CacheAssembly (assm);
58+
iface.Methods.Add (abstract_method);
59+
iface.Methods.Add (default_method);
4760

48-
step.Process (context);
61+
assm.MainModule.Types.Add (iface);
4962

50-
// We should have generated an override for MyAbstractMethod
51-
Assert.IsTrue (impl.Methods.Any (m => m.Name == "MyAbstractMethod"));
63+
// Create implementing class
64+
var jlo = assm.MainModule.Import (android.MainModule.GetType ("Java.Lang.Object"));
65+
var impl = new TypeDefinition ("MyNamespace", "MyClass", TypeAttributes.Public, jlo);
66+
impl.Interfaces.Add (new InterfaceImplementation (iface));
5267

53-
// We should not have generated an override for MyDefaultMethod
54-
Assert.IsFalse (impl.Methods.Any (m => m.Name == "MyDefaultMethod"));
68+
assm.MainModule.Types.Add (impl);
69+
assm.Write (assemblyPath);
70+
}
5571
}
5672

5773
static AssemblyDefinition CreateFauxMonoAndroidAssembly ()

0 commit comments

Comments
 (0)