Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 016d9d6

Browse files
Non virtual calls to instance methods non-virtual dispatch on instance interface methods (#27756) (#27868)
* est for non_virtual_calls_to_instance_methods * Fix handling of callvirt to instance methods on interface types that are not virtual - Use call type to indicate if its non-virtual or not, instead of opcode * Use ilproj to protect against future C# compiler changes - This test needs to test the use of specific opcodes, and so an IL proj is required
1 parent ff9dd56 commit 016d9d6

File tree

4 files changed

+509
-1
lines changed

4 files changed

+509
-1
lines changed

src/vm/jitinterface.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5772,7 +5772,7 @@ void CEEInfo::getCallInfo(
57725772

57735773
pResult->methodFlags = getMethodAttribsInternal(pResult->hMethod);
57745774

5775-
SignatureKind signatureKind = flags & CORINFO_CALLINFO_CALLVIRT ? SK_VIRTUAL_CALLSITE : SK_CALLSITE;
5775+
SignatureKind signatureKind = flags & CORINFO_CALLINFO_CALLVIRT && !(pResult->kind == CORINFO_CALL) ? SK_VIRTUAL_CALLSITE : SK_CALLSITE;
57765776
getMethodSigInternal(pResult->hMethod, &pResult->sig, (pResult->hMethod == pResolvedToken->hMethod) ? pResolvedToken->hClass : NULL, signatureKind);
57775777

57785778
if (flags & CORINFO_CALLINFO_VERIFICATION)
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Runtime.CompilerServices;
7+
8+
namespace Sample
9+
{
10+
public sealed class C1 : I1<string>, I2
11+
{
12+
}
13+
14+
class Program
15+
{
16+
static int Main(string[] args)
17+
{
18+
CallOpcodeNonGenericInterface();
19+
CallOpcodeNonGenericInterfaceGenericMethod();
20+
CallOpcodeGenericInterface();
21+
CallOpcodeGenericInterfaceGenericMethod();
22+
CallVirtOpcodeNonGenericInterface();
23+
CallVirtOpcodeNonGenericInterfaceGenericMethod();
24+
CallVirtOpcodeGenericInterface();
25+
CallVirtOpcodeGenericInterfaceGenericMethod();
26+
27+
return 100;
28+
}
29+
30+
private static void CallOpcodeNonGenericInterface()
31+
{
32+
Console.WriteLine("Testing call opcode for calling DIM on non-generic interface non-generic method");
33+
if (((I2)new C1()).GetItemTypeNonGeneric(typeof(string)) != typeof(string))
34+
throw new Exception("CallOpcodeGenericInterface failed");
35+
}
36+
37+
private static void CallOpcodeNonGenericInterfaceGenericMethod()
38+
{
39+
Console.WriteLine("Testing call opcode for calling DIM on non-generic interface non-generic method");
40+
if (((I2)new C1()).GetItemTypeGeneric<object>() != typeof(object))
41+
throw new Exception("CallOpcodeGenericInterface failed");
42+
}
43+
44+
private static void CallOpcodeGenericInterface()
45+
{
46+
Console.WriteLine("Testing call opcode for calling DIM on generic interface");
47+
if (((I1<string>)new C1()).GetItemType() != typeof(string))
48+
throw new Exception("CallOpcodeGenericInterface failed");
49+
}
50+
51+
private static void CallOpcodeGenericInterfaceGenericMethod()
52+
{
53+
Console.WriteLine("Testing call opcode for calling generic method on DIM on generic interface");
54+
if (((I1<string>)new C1()).GetItemTypeMethod<object>() != typeof(object))
55+
throw new Exception("CallOpcodeGenericInterface failed");
56+
}
57+
58+
private static void CallVirtOpcodeNonGenericInterface()
59+
{
60+
Console.WriteLine("Testing callvirt opcode for calling DIM on non-generic interface non-generic method");
61+
I2 c1 = new C1();
62+
if (c1.GetItemTypeNonGeneric(typeof(string)) != typeof(string))
63+
throw new Exception("CallOpcodeGenericInterface failed");
64+
}
65+
66+
private static void CallVirtOpcodeNonGenericInterfaceGenericMethod()
67+
{
68+
Console.WriteLine("Testing callvirt opcode for calling DIM on non-generic interface non-generic method");
69+
I2 c1 = new C1();
70+
if (c1.GetItemTypeGeneric<object>() != typeof(object))
71+
throw new Exception("CallOpcodeGenericInterface failed");
72+
}
73+
74+
private static void CallVirtOpcodeGenericInterface()
75+
{
76+
Console.WriteLine("Testing callvirt opcode for calling DIM on generic interface");
77+
I1<string> c1 = new C1();
78+
if (c1.GetItemType() != typeof(string))
79+
throw new Exception("CallVirtOpcodeGenericInterface failed");
80+
}
81+
82+
private static void CallVirtOpcodeGenericInterfaceGenericMethod()
83+
{
84+
Console.WriteLine("Testing callvirt opcode for calling generic method on DIM on generic interface");
85+
I1<string> c1 = new C1();
86+
if (c1.GetItemTypeMethod<object>() != typeof(object))
87+
throw new Exception("CallVirtOpcodeGenericInterfaceGenericMethod failed");
88+
}
89+
}
90+
}
91+
92+
public interface I1<T>
93+
{
94+
[MethodImpl(MethodImplOptions.NoInlining)]
95+
sealed Type GetItemType() => typeof(T);
96+
[MethodImpl(MethodImplOptions.NoInlining)]
97+
sealed Type GetItemTypeMethod<U>() => typeof(U);
98+
}
99+
100+
public interface I2
101+
{
102+
[MethodImpl(MethodImplOptions.NoInlining)]
103+
sealed Type GetItemTypeNonGeneric(Type t) => t;
104+
[MethodImpl(MethodImplOptions.NoInlining)]
105+
sealed Type GetItemTypeGeneric<U>() => typeof(U);
106+
}

0 commit comments

Comments
 (0)