Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crossgen2 support for static virtual method resolution (take 2) #87438

Merged
merged 21 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0e68a2f
WIP: Crossgen2 support for static virtual method resolution
trylek Jun 11, 2021
8c69fcf
Rebase against latest main; address parts of Michal's PR feedback
trylek Jun 12, 2023
8513e6b
Address additional Michal's PR feedback
trylek Jun 12, 2023
475c190
Revert changes to MetadataVirtualMethodAlgorithm per Michal's PR feed…
trylek Jun 14, 2023
9fee598
Fix module token resolution in the presence of SVM devirtualization
trylek Jun 15, 2023
8940fd1
Fix a few bugs found in TypeHierarchy tests
trylek Jun 23, 2023
af42831
Fix two Crossgen2 codegen bugs found via SVM testing
trylek Jun 29, 2023
a6785a4
Fix bugs, address PR feedback
trylek Jul 10, 2023
bc60009
Remove instrumentation; fix instantiation stub flag in getCallInfo
trylek Jul 12, 2023
c75a1b0
Revert change to Argiterator that turned out to be incorrect
trylek Jul 16, 2023
c1d0603
Subtle fixes for SVM handling in ceeInfoGetCallInfo
trylek Jul 16, 2023
0916bfc
Fix delegate ctor and module token construction for SVMs
trylek Jul 17, 2023
168908f
Remove instrumentation and more fixes for special SVM cases
trylek Jul 18, 2023
ad44935
Fix assertion failure seen in readytorun/tests/generic tests
trylek Jul 18, 2023
5bad02e
Rebase against main; remove unused resource
trylek Jul 19, 2023
5ddc43c
Address Michal's PR feedback towards MethodImpl body lookup
trylek Jul 20, 2023
f5f530c
Fix typo and merge error
trylek Jul 20, 2023
56754ea
Add versioning resiliency test as suggested by DavidWr
trylek Jul 20, 2023
8d642c6
Remove superfluous blank lines
trylek Jul 20, 2023
26dd5cf
Fix composite issues by introducing a new token kind
trylek Jul 21, 2023
1374c32
Address David Wrighton's PR feedback
trylek Jul 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,9 @@ public enum CorInfoTokenKind

// token comes from devirtualizing a method
CORINFO_TOKENKIND_DevirtualizedMethod = 0x800 | CORINFO_TOKENKIND_Method,

// token comes from resolved static virtual method
CORINFO_TOKENKIND_ResolvedStaticVirtualMethod = 0x1000 | CORINFO_TOKENKIND_Method,
};

// These are error codes returned by CompileMethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,20 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
SignatureContext innerContext = builder.EmitFixup(factory, ReadyToRunFixupKind.DelegateCtor, _methodToken.Token.Module, factory.SignatureContext);

bool needsInstantiatingStub = _targetMethod.Method.HasInstantiation;
if (_targetMethod.Method.IsVirtual && _targetMethod.Method.Signature.IsStatic)
{
// For static virtual methods, we always require an instantiating stub as the method may resolve to a canonical representation
// at runtime without us being able to detect that at compile time.
needsInstantiatingStub |= (_targetMethod.Method.OwningType.HasInstantiation || _methodToken.ConstrainedType != null);
}

builder.EmitMethodSignature(
_methodToken,
enforceDefEncoding: false,
enforceOwningType: false,
innerContext,
isInstantiatingStub: _targetMethod.Method.HasInstantiation);
isInstantiatingStub: needsInstantiatingStub);

builder.EmitTypeSignature(_delegateType, innerContext);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,13 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
}
else
{
bool isUnboxingStub = false;
bool isStub = false;
if (methodNode is DelayLoadHelperImport methodImport)
{
isUnboxingStub = ((MethodFixupSignature)methodImport.ImportSignature.Target).IsUnboxingStub;
MethodFixupSignature signature = (MethodFixupSignature)methodImport.ImportSignature.Target;
isStub = signature.IsUnboxingStub || signature.IsInstantiatingStub;
}
builder.GetCallRefMap(methodNode.Method, isUnboxingStub);
builder.GetCallRefMap(methodNode.Method, isStub);
}
if (methodIndex >= nextMethodIndex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public class Import : EmbeddedObjectNode, ISymbolDefinitionNode, ISortableSymbol

internal readonly MethodDesc CallingMethod;

public Signature Signature => ImportSignature.Target;

public Import(ImportSectionNode tableNode, Signature importSignature, MethodDesc callingMethod = null)
{
Table = tableNode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public MethodFixupSignature(
compilerContext.EnsureLoadableMethod(method.Method);
compilerContext.EnsureLoadableType(_method.OwningType);

if (method.ConstrainedType != null)
if (method.ConstrainedType != null && !method.ConstrainedType.IsRuntimeDeterminedSubtype)
compilerContext.EnsureLoadableType(method.ConstrainedType);
}

Expand All @@ -46,6 +46,10 @@ public MethodFixupSignature(

public bool IsUnboxingStub => _method.Unboxing;

public TypeDesc ConstrainedType => _method.ConstrainedType;

public bool NeedsInstantiationArg => _method.ConstrainedType?.IsCanonicalSubtype(CanonicalFormKind.Any) ?? false;

protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
DependencyList list = base.ComputeNonRelocationBasedDependencies(factory);
Expand Down

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/coreclr/vm/methodtable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9242,7 +9242,7 @@ MethodTable::TryResolveConstraintMethodApprox(
{
_ASSERTE(!thInterfaceType.IsTypeDesc());
_ASSERTE(thInterfaceType.IsInterface());
BOOL uniqueResolution;
BOOL uniqueResolution = TRUE;

ResolveVirtualStaticMethodFlags flags = ResolveVirtualStaticMethodFlags::AllowVariantMatches
| ResolveVirtualStaticMethodFlags::InstantiateResultOverFinalMethodDesc;
Expand All @@ -9255,7 +9255,8 @@ MethodTable::TryResolveConstraintMethodApprox(
thInterfaceType.GetMethodTable(),
pInterfaceMD,
flags,
&uniqueResolution);
(pfForceUseRuntimeLookup != NULL ? &uniqueResolution : NULL));

if (result == NULL || !uniqueResolution)
{
_ASSERTE(pfForceUseRuntimeLookup != NULL);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk.IL">
<PropertyGroup>
<OutputType>Exe</OutputType>

<!-- Crossgen2 currently doesn't support this negative check - that should be fine as runtime behavior is undefined in the presence of invalid IL. -->
<CrossGenTest>false</CrossGenTest>
</PropertyGroup>
<PropertyGroup>
<DebugType>Full</DebugType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 7:0:0:0
}
.assembly RecursiveGeneric
.assembly GitHub_70385
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [System.Runtime]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
Expand All @@ -27,7 +27,7 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module RecursiveGeneric.dll
.module GitHub_70385.dll
// MVID: {10541B0F-16D6-4F9A-B0EB-E793F524F163}
.imagebase 0x00400000
.file alignment 0x00000200
Expand Down
17 changes: 17 additions & 0 deletions src/tests/readytorun/tests/main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,19 @@ static void TestILBodyChange()
Assert.AreEqual(ILInliningTest.TestDifferentIntValue(), actualMethodCallResult);
}

private class CallDefaultVsExactStaticVirtual<T> where T : IDefaultVsExactStaticVirtual
{
public static string CallMethodOnGenericType() => T.Method();
}

[MethodImplAttribute(MethodImplOptions.NoInlining)]
static void TestDefaultVsExactStaticVirtualMethodImplementation()
{
Assert.AreEqual(CallDefaultVsExactStaticVirtual<DefaultVsExactStaticVirtualClass>.CallMethodOnGenericType(), "DefaultVsExactStaticVirtualMethod");
// Naively one would expect that the following should do, however Roslyn fails to compile it claiming that the type DVESVC doesn't contain 'Method':
// Assert.AreEqual(DefaultVsExactStaticVirtualClass.Method(), "DefaultVsExactStaticVirtualMethod");
}

static void RunAllTests()
{
Console.WriteLine("TestVirtualMethodCalls");
Expand Down Expand Up @@ -527,6 +540,10 @@ static void RunAllTests()

Console.WriteLine("TestILBodyChange");
TestILBodyChange();

Console.WriteLine("TestDefaultVsExactStaticVirtualMethodImplementation");
TestDefaultVsExactStaticVirtualMethodImplementation();

ILInliningVersioningTest<LocallyDefinedStructure>.RunAllTests(typeof(Program).Assembly);
}

Expand Down
18 changes: 18 additions & 0 deletions src/tests/readytorun/tests/test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,24 @@ public static string OpenClosedDelegateTarget(this string x, string foo)
}
}

public interface IDefaultVsExactStaticVirtual
{
static virtual string Method() =>
#if V2
"Error - IDefaultVsExactStaticVirtual.Method shouldn't be used in V2"
#else
"DefaultVsExactStaticVirtualMethod"
#endif
;
}

public class DefaultVsExactStaticVirtualClass : IDefaultVsExactStaticVirtual
{
#if V2
static string IDefaultVsExactStaticVirtual.Method() => "DefaultVsExactStaticVirtualMethod";
#endif
}

// Test dependent versioning details
public class ILInliningVersioningTest<T>
{
Expand Down