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

Commit e83991c

Browse files
MichalStrehovskyjkotas
authored andcommitted
Stop treating all calls to instance interface methods as callvirt (#15925)
Fixes #15827.
1 parent 09ac422 commit e83991c

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

src/vm/jitinterface.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5397,7 +5397,8 @@ void CEEInfo::getCallInfo(
53975397
directCall = true;
53985398
}
53995399
else
5400-
if (pTargetMD->GetMethodTable()->IsInterface() && pTargetMD->IsVirtual())
5400+
// Backwards compat: calls to abstract interface methods are treated as callvirt
5401+
if (pTargetMD->GetMethodTable()->IsInterface() && pTargetMD->IsAbstract())
54015402
{
54025403
directCall = false;
54035404
}
@@ -5439,6 +5440,12 @@ void CEEInfo::getCallInfo(
54395440
}
54405441
else
54415442
#endif
5443+
if (pTargetMD->GetMethodTable()->IsInterface())
5444+
{
5445+
// Handle interface methods specially because the Sealed bit has no meaning on interfaces.
5446+
devirt = !IsMdVirtual(pTargetMD->GetAttrs());
5447+
}
5448+
else
54425449
{
54435450
DWORD dwMethodAttrs = pTargetMD->GetAttrs();
54445451
devirt = !IsMdVirtual(dwMethodAttrs) || IsMdFinal(dwMethodAttrs) || pTargetMD->GetMethodTable()->IsSealed();
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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+
//
6+
// Verifies that we're able to call virtual interface methods non-virtually.
7+
// Corresponds to the C# "base(IFoo).Frob()" syntax.
8+
//
9+
10+
.assembly extern System.Runtime { }
11+
12+
.assembly nonvirtualcall { }
13+
14+
.class interface private abstract auto ansi IFoo
15+
{
16+
.method public hidebysig newslot virtual instance int32 Frob() cil managed
17+
{
18+
ldc.i4 99
19+
ret
20+
}
21+
}
22+
23+
.class interface private abstract auto ansi IBar
24+
implements IFoo
25+
{
26+
.method public hidebysig newslot virtual final instance int32 Frob() cil managed
27+
{
28+
.override IFoo::Frob
29+
ldarg.0
30+
call instance int32 class IFoo::Frob()
31+
ldc.i4.1
32+
add
33+
ret
34+
}
35+
}
36+
37+
.class private auto ansi beforefieldinit Fooer
38+
extends [System.Runtime]System.Object
39+
implements IBar
40+
{
41+
.method public hidebysig specialname rtspecialname
42+
instance void .ctor() cil managed
43+
{
44+
ldarg.0
45+
call instance void [System.Runtime]System.Object::.ctor()
46+
ret
47+
}
48+
}
49+
50+
.method public hidebysig static int32 RunTest() cil managed
51+
{
52+
newobj instance void Fooer::.ctor()
53+
callvirt instance int32 IFoo::Frob()
54+
ret
55+
}
56+
57+
.method public hidebysig static int32 Main() cil managed
58+
{
59+
.entrypoint
60+
61+
ldstr "DefaultImplementationsOfInterfaces"
62+
call bool [System.Runtime]System.Runtime.CompilerServices.RuntimeFeature::IsSupported(string)
63+
64+
// If default interfaces are not supported, consider the test successful.
65+
brtrue DoRunTest
66+
ldc.i4 100
67+
ret
68+
69+
DoRunTest:
70+
call int32 RunTest()
71+
ret
72+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
4+
<PropertyGroup>
5+
<AssemblyName>nonvirtualcall</AssemblyName>
6+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
7+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
8+
<SchemaVersion>2.0</SchemaVersion>
9+
<ProjectGuid>{85DFC527-4DB1-595E-A7D7-E94EE1F8140D}</ProjectGuid>
10+
<FileAlignment>512</FileAlignment>
11+
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
12+
<NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
13+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
14+
<ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
15+
<OutputType>Exe</OutputType>
16+
<CLRTestKind>BuildAndRun</CLRTestKind>
17+
<CLRTestPriority>0</CLRTestPriority>
18+
</PropertyGroup>
19+
20+
<ItemGroup>
21+
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
22+
<Visible>False</Visible>
23+
</CodeAnalysisDependentAssemblyPaths>
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<Compile Include="nonvirtualcall.il" />
28+
</ItemGroup>
29+
30+
31+
<ItemGroup>
32+
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
33+
</ItemGroup>
34+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
35+
</Project>

0 commit comments

Comments
 (0)