The existing code would incorrectly inhibit codegen from generating instantiation argument in non-virtual calls to default interface methods (i.e. those that can happen with the `base` syntax in C#).
Fixes #16775.
pResult->classFlags = getClassAttribsInternal(pResolvedToken->hClass);
pResult->methodFlags = getMethodAttribsInternal(pResult->hMethod);
- getMethodSigInternal(pResult->hMethod, &pResult->sig, (pResult->hMethod == pResolvedToken->hMethod) ? pResolvedToken->hClass : NULL, /* isCallSite = */ TRUE);
+
+ SignatureKind signatureKind = flags & CORINFO_CALLINFO_CALLVIRT ? SK_VIRTUAL_CALLSITE : SK_CALLSITE;
+ getMethodSigInternal(pResult->hMethod, &pResult->sig, (pResult->hMethod == pResolvedToken->hMethod) ? pResolvedToken->hClass : NULL, signatureKind);
if (flags & CORINFO_CALLINFO_VERIFICATION)
{
CORINFO_METHOD_HANDLE ftnHnd,
CORINFO_SIG_INFO * sigRet,
CORINFO_CLASS_HANDLE owner,
- BOOL isCallSite)
+ SignatureKind signatureKind)
{
STANDARD_VM_CONTRACT;
if (ftn->RequiresInstArg())
{
//
- // If we are making an interface call that is a default interface method, we need to lie to the JIT.
+ // If we are making a virtual call to an instance method on an interface, we need to lie to the JIT.
// The reason being that we already made sure target is always directly callable (through instantiation stubs),
// JIT should not generate shared generics aware call code and insert the secret argument again at the callsite.
// Otherwise we would end up with two secret generic dictionary arguments (since the stub also provides one).
//
- BOOL isDefaultInterfaceMethodCallSite = isCallSite && ftn->IsDefaultInterfaceMethod();
- if (!isDefaultInterfaceMethodCallSite)
+ BOOL isCallSiteThatGoesThroughInstantiatingStub =
+ signatureKind == SK_VIRTUAL_CALLSITE &&
+ !ftn->IsStatic() &&
+ ftn->GetMethodTable()->IsInterface();
+ if (!isCallSiteThatGoesThroughInstantiatingStub)
sigRet->callConv = (CorInfoCallConv) (sigRet->callConv | CORINFO_CALLCONV_PARAMTYPE);
}
SWB_EE_RESTART = 0x2
};
+enum SignatureKind
+{
+ SK_NOT_CALLSITE,
+ SK_CALLSITE,
+ SK_VIRTUAL_CALLSITE,
+};
+
class Stub;
class MethodDesc;
class FieldDesc;
CORINFO_METHOD_HANDLE ftnHnd,
CORINFO_SIG_INFO* sigInfo,
CORINFO_CLASS_HANDLE owner = NULL,
- BOOL isCallSite = FALSE
+ SignatureKind signatureKind = SK_NOT_CALLSITE
);
void getEHinfo(
--- /dev/null
+.assembly extern System.Runtime { }
+
+.assembly sharedinterfacemethod { }
+
+.class interface private abstract auto ansi IFoo`1<T>
+{
+ .method public hidebysig virtual newslot instance class [System.Runtime]System.Type Frob() cil managed
+ {
+ ldtoken !0
+ call class [System.Runtime]System.Type class [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle)
+ ret
+ }
+}
+
+.class private auto ansi beforefieldinit Fooer
+ extends [System.Runtime]System.Object
+ implements class IFoo`1<class [System.Runtime]System.Object>,
+ class IFoo`1<valuetype [System.Runtime]System.Int32>
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+}
+
+.method public hidebysig static int32 Main() cil managed
+{
+ .entrypoint
+
+ // Callvirt to a shared interface method
+
+ newobj instance void Fooer::.ctor()
+ callvirt instance class [System.Runtime]System.Type class IFoo`1<valuetype [System.Runtime]System.Int32>::Frob()
+ ldtoken valuetype [System.Runtime]System.Int32
+ call class [System.Runtime]System.Type class [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle)
+ ceq
+ brtrue UnsharedCallvirtIsGood
+
+ ldc.i4.1
+ ret
+
+UnsharedCallvirtIsGood:
+
+ // Call to a shared interface
+
+ newobj instance void Fooer::.ctor()
+ call instance class [System.Runtime]System.Type class IFoo`1<valuetype [System.Runtime]System.Int32>::Frob()
+ ldtoken valuetype [System.Runtime]System.Int32
+ call class [System.Runtime]System.Type class [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle)
+ ceq
+ brtrue UnsharedCallIsGood
+
+ ldc.i4.2
+ ret
+
+UnsharedCallIsGood:
+
+ // Callvirt to an unshared interface method
+
+ newobj instance void Fooer::.ctor()
+ callvirt instance class [System.Runtime]System.Type class IFoo`1<class [System.Runtime]System.Object>::Frob()
+ ldtoken class [System.Runtime]System.Object
+ call class [System.Runtime]System.Type class [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle)
+ ceq
+ brtrue SharedCallvirtIsGood
+
+ ldc.i4.3
+ ret
+
+SharedCallvirtIsGood:
+
+ // Call to an unshared interface method
+
+ newobj instance void Fooer::.ctor()
+ call instance class [System.Runtime]System.Type class IFoo`1<class [System.Runtime]System.Object>::Frob()
+ ldtoken class [System.Runtime]System.Object
+ call class [System.Runtime]System.Type class [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle)
+ ceq
+ brtrue SharedCallIsGood
+
+ ldc.i4.4
+ ret
+
+SharedCallIsGood:
+
+ ldc.i4 100
+ ret
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{85DFC527-4DB1-595E-A7D7-E94EE1F8140D}</ProjectGuid>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
+ <OutputType>Exe</OutputType>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <CLRTestPriority>0</CLRTestPriority>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="sharedinterfacemethod.il" />
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>