1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using Internal.TypeSystem;
using Xunit;
namespace ILCompiler.Compiler.Tests
{
public class DevirtualizationTests
{
private readonly CompilerTypeSystemContext _context;
private readonly ModuleDesc _testModule;
public DevirtualizationTests()
{
var target = new TargetDetails(TargetArchitecture.X64, TargetOS.Windows, TargetAbi.CoreRT);
_context = new CompilerTypeSystemContext(target, SharedGenericsMode.CanonicalReferenceTypes);
_context.InputFilePaths = new Dictionary<string, string> {
{ "Test.CoreLib", @"Test.CoreLib.dll" },
{ "ILCompiler.Compiler.Tests.Assets", @"ILCompiler.Compiler.Tests.Assets.dll" },
};
_context.ReferenceFilePaths = new Dictionary<string, string>();
_context.SetSystemModule(_context.GetModuleForSimpleName("Test.CoreLib"));
_testModule = _context.GetModuleForSimpleName("ILCompiler.Compiler.Tests.Assets");
}
private DevirtualizationManager GetDevirtualizationManagerFromScan(MethodDesc method)
{
CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup();
CompilationBuilder builder = new RyuJitCompilationBuilder(_context, compilationGroup);
IILScanner scanner = builder.GetILScannerBuilder()
.UseCompilationRoots(new ICompilationRootProvider[] { new SingleMethodRootProvider(method) })
.ToILScanner();
return scanner.Scan().GetDevirtualizationManager();
}
[Fact]
public void TestDevirtualizeWithUnallocatedType()
{
MetadataType testType = _testModule.GetType("Devirtualization", "DevirtualizeWithUnallocatedType");
DevirtualizationManager scanDevirt = GetDevirtualizationManagerFromScan(testType.GetMethod("Run", null));
MethodDesc decl = testType.GetNestedType("Base").GetMethod("Unreachable", null);
MetadataType impl = testType.GetNestedType("Derived");
// Base::Unreachable should resolve into Derived::Unreachable on Derived.
MethodDesc resolvedMethod = scanDevirt.ResolveVirtualMethod(decl, impl);
Assert.Same(impl.GetMethod("Unreachable", null), resolvedMethod);
// The resolved method should not be treated as sealed
Assert.False(scanDevirt.IsEffectivelySealed(resolvedMethod));
// Even though the metadata based algorithm would say it's sealed
var devirt = new DevirtualizationManager();
Assert.True(devirt.IsEffectivelySealed(resolvedMethod));
}
[Fact]
public void TestDevirtualizeWithOtherUnallocatedType()
{
MetadataType testType = _testModule.GetType("Devirtualization", "DevirtualizeWithOtherUnallocatedType");
DevirtualizationManager scanDevirt = GetDevirtualizationManagerFromScan(testType.GetMethod("Run", null));
MetadataType impl = testType.GetNestedType("Derived");
// The resolved method should not be treated as sealed
Assert.False(scanDevirt.IsEffectivelySealed(impl.GetMethod("Unreachable", null)));
}
[Fact]
public void TestDevirtualizeSimple()
{
MetadataType testType = _testModule.GetType("Devirtualization", "DevirtualizeSimple");
DevirtualizationManager scanDevirt = GetDevirtualizationManagerFromScan(testType.GetMethod("Run", null));
MethodDesc implMethod = testType.GetNestedType("Derived").GetMethod("Virtual", null);
// The impl method should be treated as sealed
Assert.True(scanDevirt.IsEffectivelySealed(implMethod));
// Even though the metadata based algorithm would say it isn't
var devirt = new DevirtualizationManager();
Assert.False(devirt.IsEffectivelySealed(implMethod));
}
[Fact]
public void TestDevirtualizeAbstract()
{
MetadataType testType = _testModule.GetType("Devirtualization", "DevirtualizeAbstract");
DevirtualizationManager scanDevirt = GetDevirtualizationManagerFromScan(testType.GetMethod("Run", null));
Assert.False(scanDevirt.IsEffectivelySealed(testType.GetNestedType("Abstract")));
}
}
}
|