Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Wrighton <davidwr@microsoft.com>2021-03-19 18:51:00 +0300
committerGitHub <noreply@github.com>2021-03-19 18:51:00 +0300
commitcea6fbdaff1548a43fc0fa1127fc8a05446b5a1a (patch)
treeb89a88bbcfb01586148f839317dd081cac16b7e0 /src/coreclr/tools
parent7a94064774a19abea6f1f32c8b47373f7de9a01b (diff)
Fix signature generation for devirtualization (#49854)
- Crossgen2 computes its signatures from slightly different data than the VM does - Tweak the jit interface to specify that the resolved token comes from devirtualization to detect this special case - The extra tokenType information is ignored by the VM - Pass the devirtualization specified owning type through when necessary - Check that it meets the requirements of being defined on a a derived type from the method target
Diffstat (limited to 'src/coreclr/tools')
-rw-r--r--src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs3
-rw-r--r--src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs53
2 files changed, 48 insertions, 8 deletions
diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
index 76763e22c71..ea37d078b63 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
@@ -1266,6 +1266,9 @@ namespace Internal.JitInterface
// token comes from CEE_LDVIRTFTN
CORINFO_TOKENKIND_Ldvirtftn = 0x400 | CORINFO_TOKENKIND_Method,
+
+ // token comes from devirtualizing a method
+ CORINFO_TOKENKIND_DevirtualizedMethod = 0x800 | CORINFO_TOKENKIND_Method,
};
// These are error codes returned by CompileMethod
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
index d50e2416b7f..469b47e429b 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
@@ -47,17 +47,17 @@ namespace Internal.JitInterface
public readonly TypeDesc OwningType;
- public MethodWithToken(MethodDesc method, ModuleToken token, TypeDesc constrainedType, bool unboxing, object context)
+ public MethodWithToken(MethodDesc method, ModuleToken token, TypeDesc constrainedType, bool unboxing, object context, TypeDesc devirtualizedMethodOwner = null)
{
Debug.Assert(!method.IsUnboxingThunk());
Method = method;
Token = token;
ConstrainedType = constrainedType;
Unboxing = unboxing;
- OwningType = GetMethodTokenOwningType(this, constrainedType, context, out OwningTypeNotDerivedFromToken);
+ OwningType = GetMethodTokenOwningType(this, constrainedType, context, devirtualizedMethodOwner, out OwningTypeNotDerivedFromToken);
}
- private static TypeDesc GetMethodTokenOwningType(MethodWithToken methodToken, TypeDesc constrainedType, object context, out bool owningTypeNotDerivedFromToken)
+ private static TypeDesc GetMethodTokenOwningType(MethodWithToken methodToken, TypeDesc constrainedType, object context, TypeDesc devirtualizedMethodOwner, out bool owningTypeNotDerivedFromToken)
{
ModuleToken moduleToken = methodToken.Token;
owningTypeNotDerivedFromToken = false;
@@ -72,7 +72,7 @@ namespace Internal.JitInterface
if (moduleToken.TokenType == CorTokenType.mdtMethodDef)
{
var methodDefinition = moduleToken.MetadataReader.GetMethodDefinition((MethodDefinitionHandle)moduleToken.Handle);
- return HandleContext(moduleToken.Module, methodDefinition.GetDeclaringType(), methodToken.Method.OwningType, constrainedType, context, ref owningTypeNotDerivedFromToken);
+ return HandleContext(moduleToken.Module, methodDefinition.GetDeclaringType(), methodToken.Method.OwningType, constrainedType, context, devirtualizedMethodOwner, ref owningTypeNotDerivedFromToken);
}
// At this point moduleToken must point at a MemberRef.
@@ -84,14 +84,15 @@ namespace Internal.JitInterface
case HandleKind.TypeReference:
case HandleKind.TypeSpecification:
{
- return HandleContext(moduleToken.Module, memberRef.Parent, methodToken.Method.OwningType, constrainedType, context, ref owningTypeNotDerivedFromToken);
+ Debug.Assert(devirtualizedMethodOwner == null); // Devirtualization is expected to always use a methoddef token
+ return HandleContext(moduleToken.Module, memberRef.Parent, methodToken.Method.OwningType, constrainedType, context, null, ref owningTypeNotDerivedFromToken);
}
default:
return methodToken.Method.OwningType;
}
- TypeDesc HandleContext(EcmaModule module, EntityHandle handle, TypeDesc methodTargetOwner, TypeDesc constrainedType, object context, ref bool owningTypeNotDerivedFromToken)
+ TypeDesc HandleContext(EcmaModule module, EntityHandle handle, TypeDesc methodTargetOwner, TypeDesc constrainedType, object context, TypeDesc devirtualizedMethodOwner, ref bool owningTypeNotDerivedFromToken)
{
var tokenOnlyOwningType = module.GetType(handle);
TypeDesc actualOwningType;
@@ -116,7 +117,36 @@ namespace Internal.JitInterface
typeInstantiation = typeContext.Instantiation;
}
- var instantiatedOwningType = tokenOnlyOwningType.InstantiateSignature(typeInstantiation, methodInstantiation);
+ TypeDesc instantiatedOwningType = null;
+
+ if (devirtualizedMethodOwner != null)
+ {
+ // We might be in a situation where we use the passed in type (devirtualization scenario)
+ // Check to see if devirtualizedMethodOwner actually is a type derived from the type definition in some way.
+ bool derivesFromTypeDefinition = false;
+ TypeDesc currentType = devirtualizedMethodOwner;
+ do
+ {
+ derivesFromTypeDefinition = currentType.GetTypeDefinition() == tokenOnlyOwningType;
+ currentType = currentType.BaseType;
+ } while(currentType != null && !derivesFromTypeDefinition);
+
+ if (derivesFromTypeDefinition)
+ {
+ instantiatedOwningType = devirtualizedMethodOwner;
+ }
+ else
+ {
+ Debug.Assert(false); // This is expected to fire if and only if we implement devirtualization to default interface methods
+ throw new RequiresRuntimeJitException(methodTargetOwner.ToString());
+ }
+ }
+
+ if (instantiatedOwningType == null)
+ {
+ instantiatedOwningType = tokenOnlyOwningType.InstantiateSignature(typeInstantiation, methodInstantiation);
+ }
+
var canonicalizedOwningType = instantiatedOwningType.ConvertToCanonForm(CanonicalFormKind.Specific);
if ((instantiatedOwningType == canonicalizedOwningType) || (constrainedType != null))
{
@@ -884,7 +914,14 @@ namespace Internal.JitInterface
private MethodWithToken ComputeMethodWithToken(MethodDesc method, ref CORINFO_RESOLVED_TOKEN pResolvedToken, TypeDesc constrainedType, bool unboxing)
{
ModuleToken token = HandleToModuleToken(ref pResolvedToken, method, out object context, ref constrainedType);
- return new MethodWithToken(method, token, constrainedType: constrainedType, unboxing: unboxing, context: context);
+
+ TypeDesc devirtualizedMethodOwner = null;
+ if (pResolvedToken.tokenType == CorInfoTokenKind.CORINFO_TOKENKIND_DevirtualizedMethod)
+ {
+ devirtualizedMethodOwner = HandleToObject(pResolvedToken.hClass);
+ }
+
+ return new MethodWithToken(method, token, constrainedType: constrainedType, unboxing: unboxing, context: context, devirtualizedMethodOwner: devirtualizedMethodOwner);
}
private ModuleToken HandleToModuleToken(ref CORINFO_RESOLVED_TOKEN pResolvedToken, MethodDesc methodDesc, out object context, ref TypeDesc constrainedType)