From: Michal Strehovský Date: Fri, 5 Oct 2018 10:51:06 +0000 (+0200) Subject: Report instantiation argument in non-virtual interface calls (#20257) X-Git-Tag: accepted/tizen/unified/20190422.045933~1075 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=27c848e37e9998142b60e776cf5b5d08a3543fe1;p=platform%2Fupstream%2Fcoreclr.git Report instantiation argument in non-virtual interface calls (#20257) 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. --- diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 293bab9..5067a36 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -5730,7 +5730,9 @@ void CEEInfo::getCallInfo( 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) { @@ -8510,7 +8512,7 @@ CEEInfo::getMethodSigInternal( CORINFO_METHOD_HANDLE ftnHnd, CORINFO_SIG_INFO * sigRet, CORINFO_CLASS_HANDLE owner, - BOOL isCallSite) + SignatureKind signatureKind) { STANDARD_VM_CONTRACT; @@ -8537,13 +8539,16 @@ CEEInfo::getMethodSigInternal( 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); } diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index c609237..a4f6576 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -30,6 +30,13 @@ enum StompWriteBarrierCompletionAction SWB_EE_RESTART = 0x2 }; +enum SignatureKind +{ + SK_NOT_CALLSITE, + SK_CALLSITE, + SK_VIRTUAL_CALLSITE, +}; + class Stub; class MethodDesc; class FieldDesc; @@ -745,7 +752,7 @@ public: CORINFO_METHOD_HANDLE ftnHnd, CORINFO_SIG_INFO* sigInfo, CORINFO_CLASS_HANDLE owner = NULL, - BOOL isCallSite = FALSE + SignatureKind signatureKind = SK_NOT_CALLSITE ); void getEHinfo( diff --git a/tests/src/Regressions/coreclr/16775/sharedinterfacemethod.il b/tests/src/Regressions/coreclr/16775/sharedinterfacemethod.il new file mode 100644 index 0000000..308ead9 --- /dev/null +++ b/tests/src/Regressions/coreclr/16775/sharedinterfacemethod.il @@ -0,0 +1,91 @@ +.assembly extern System.Runtime { } + +.assembly sharedinterfacemethod { } + +.class interface private abstract auto ansi IFoo`1 +{ + .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 IFoo`1 +{ + .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::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::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::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::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 +} diff --git a/tests/src/Regressions/coreclr/16775/sharedinterfacemethod.ilproj b/tests/src/Regressions/coreclr/16775/sharedinterfacemethod.ilproj new file mode 100644 index 0000000..7521917 --- /dev/null +++ b/tests/src/Regressions/coreclr/16775/sharedinterfacemethod.ilproj @@ -0,0 +1,35 @@ + + + + + $(MSBuildProjectName) + Debug + AnyCPU + 2.0 + {85DFC527-4DB1-595E-A7D7-E94EE1F8140D} + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 7a9bfb7d + true + true + Exe + BuildAndRun + 0 + + + + + False + + + + + + + + + + + + +