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

Commit 6320ede

Browse files
authored
Merge pull request #22418 from Tomius/release/2.2
Back patching #21804 to the 2.2 branch
2 parents 7f0cf2d + be662fb commit 6320ede

File tree

6 files changed

+199
-4
lines changed

6 files changed

+199
-4
lines changed

src/jit/compiler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2988,7 +2988,8 @@ class Compiler
29882988
CORINFO_METHOD_HANDLE* method,
29892989
unsigned* methodFlags,
29902990
CORINFO_CONTEXT_HANDLE* contextHandle,
2991-
CORINFO_CONTEXT_HANDLE* exactContextHandle);
2991+
CORINFO_CONTEXT_HANDLE* exactContextHandle,
2992+
bool isExplicitTailCall);
29922993

29932994
CORINFO_CLASS_HANDLE impGetSpecialIntrinsicExactReturnType(CORINFO_METHOD_HANDLE specialIntrinsicHandle);
29942995

src/jit/flowgraph.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22400,7 +22400,8 @@ Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder(GenTr
2240022400
CORINFO_METHOD_HANDLE method = call->gtCallMethHnd;
2240122401
unsigned methodFlags = 0;
2240222402
CORINFO_CONTEXT_HANDLE context = nullptr;
22403-
comp->impDevirtualizeCall(call, &method, &methodFlags, &context, nullptr);
22403+
bool explicitTailCall = (call->gtCall.gtCallMoreFlags & GTF_CALL_M_EXPLICIT_TAILCALL) != 0;
22404+
comp->impDevirtualizeCall(call, &method, &methodFlags, &context, nullptr, explicitTailCall);
2240422405
}
2240522406
}
2240622407
}

src/jit/importer.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7941,8 +7941,9 @@ var_types Compiler::impImportCall(OPCODE opcode,
79417941
assert(obj->gtType == TYP_REF);
79427942

79437943
// See if we can devirtualize.
7944+
bool explicitTailCall = (tailCall & PREFIX_TAILCALL_EXPLICIT) != 0;
79447945
impDevirtualizeCall(call->AsCall(), &callInfo->hMethod, &callInfo->methodFlags, &callInfo->contextHandle,
7945-
&exactContextHnd);
7946+
&exactContextHnd, explicitTailCall);
79467947
}
79477948

79487949
if (impIsThis(obj))
@@ -19275,6 +19276,7 @@ bool Compiler::IsMathIntrinsic(GenTree* tree)
1927519276
// methodFlags -- [IN/OUT] flags for the method to call. Updated iff call devirtualized.
1927619277
// contextHandle -- [IN/OUT] context handle for the call. Updated iff call devirtualized.
1927719278
// exactContextHnd -- [OUT] updated context handle iff call devirtualized
19279+
// isExplicitTailCalll -- [IN] true if we plan on using an explicit tail call
1927819280
//
1927919281
// Notes:
1928019282
// Virtual calls in IL will always "invoke" the base class method.
@@ -19303,7 +19305,8 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
1930319305
CORINFO_METHOD_HANDLE* method,
1930419306
unsigned* methodFlags,
1930519307
CORINFO_CONTEXT_HANDLE* contextHandle,
19306-
CORINFO_CONTEXT_HANDLE* exactContextHandle)
19308+
CORINFO_CONTEXT_HANDLE* exactContextHandle,
19309+
bool isExplicitTailCall)
1930719310
{
1930819311
assert(call != nullptr);
1930919312
assert(method != nullptr);
@@ -19598,6 +19601,12 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
1959819601
{
1959919602
JITDUMP("Now have direct call to boxed entry point, looking for unboxed entry point\n");
1960019603

19604+
if (isExplicitTailCall)
19605+
{
19606+
JITDUMP("Call is an explicit tail call, we cannot perform an unbox\n");
19607+
return;
19608+
}
19609+
1960119610
// Note for some shared methods the unboxed entry point requires an extra parameter.
1960219611
bool requiresInstMethodTableArg = false;
1960319612
CORINFO_METHOD_HANDLE unboxedEntryMethod =
@@ -19678,6 +19687,18 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
1967819687
call->gtCallObjp = localCopyThis;
1967919688
call->gtCallMethHnd = unboxedEntryMethod;
1968019689
derivedMethod = unboxedEntryMethod;
19690+
19691+
#if FEATURE_TAILCALL_OPT
19692+
if (call->IsImplicitTailCall())
19693+
{
19694+
JITDUMP("Clearing the implicit tail call flag\n");
19695+
19696+
// If set, we clear the implicit tail call flag
19697+
// as we just introduced a new address taken local variable
19698+
//
19699+
call->gtCallMoreFlags &= ~GTF_CALL_M_IMPLICIT_TAILCALL;
19700+
}
19701+
#endif // FEATURE_TAILCALL_OPT
1968119702
}
1968219703
else
1968319704
{
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+
6+
// Metadata version: v4.0.30319
7+
.assembly extern mscorlib
8+
{
9+
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
10+
.ver 4:0:0:0
11+
}
12+
.assembly test
13+
{
14+
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
15+
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
16+
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
17+
.hash algorithm 0x00008004
18+
.ver 0:0:0:0
19+
}
20+
.module test.exe
21+
// MVID: {A80A87C4-1DDB-4F93-AB31-444266FDFA55}
22+
.imagebase 0x00400000
23+
.file alignment 0x00000200
24+
.stackreserve 0x00100000
25+
.subsystem 0x0003 // WINDOWS_CUI
26+
.corflags 0x00000001 // ILONLY
27+
// Image base: 0x0000024A58020000
28+
29+
30+
// =============== CLASS MEMBERS DECLARATION ===================
31+
32+
.class private auto ansi beforefieldinit Program
33+
extends [mscorlib]System.Object
34+
{
35+
.method public hidebysig instance string
36+
Test(int32 val) cil managed noinlining
37+
{
38+
// This testcase ensures that we don't perform devirtualization
39+
// via an unboxing optimization, for the callvirt below.
40+
41+
// Code size 12 (0xc)
42+
.maxstack 8
43+
IL_0000: ldarg.1
44+
IL_0001: box [mscorlib]System.Int32
45+
tail.
46+
IL_0006: callvirt instance string [mscorlib]System.Object::ToString()
47+
IL_000b: ret
48+
} // end of method Program::Test
49+
50+
.method private hidebysig static int32
51+
Main(string[] args) cil managed
52+
{
53+
.entrypoint
54+
// Code size 73 (0x49)
55+
.maxstack 2
56+
.locals init (int32 V_0,
57+
class Program V_1,
58+
string V_2)
59+
IL_0000: ldc.i4.m1
60+
IL_0001: stloc.0
61+
IL_0002: newobj instance void Program::.ctor()
62+
IL_0007: stloc.1
63+
IL_0008: ldloc.1
64+
IL_0009: ldc.i4.s 42
65+
IL_000b: callvirt instance string Program::Test(int32)
66+
IL_0010: stloc.2
67+
IL_0011: ldloc.2
68+
IL_0012: ldstr "42"
69+
IL_0017: call bool [mscorlib]System.String::op_Equality(string,
70+
string)
71+
IL_001c: brfalse.s IL_002d
72+
73+
IL_001e: ldstr "=== PASSED ==="
74+
IL_0023: call void [mscorlib]System.Console::WriteLine(string)
75+
IL_0028: ldc.i4.s 100
76+
IL_002a: stloc.0
77+
IL_002b: br.s IL_0047
78+
79+
IL_002d: ldstr "result shoudl be 42, is= "
80+
IL_0032: ldloc.2
81+
IL_0033: call string [mscorlib]System.String::Concat(string,
82+
string)
83+
IL_0038: call void [mscorlib]System.Console::WriteLine(string)
84+
IL_003d: ldstr "+++ FAILED +++"
85+
IL_0042: call void [mscorlib]System.Console::WriteLine(string)
86+
IL_0047: ldloc.0
87+
IL_0048: ret
88+
} // end of method Program::Main
89+
90+
.method public hidebysig specialname rtspecialname
91+
instance void .ctor() cil managed
92+
{
93+
// Code size 7 (0x7)
94+
.maxstack 8
95+
IL_0000: ldarg.0
96+
IL_0001: call instance void [mscorlib]System.Object::.ctor()
97+
IL_0006: ret
98+
} // end of method Program::.ctor
99+
100+
} // end of class Program
101+
102+
103+
// =============================================================
104+
105+
// *********** DISASSEMBLY COMPLETE ***********************
106+
// WARNING: Created Win32 resource file test2.res
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+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<AssemblyName>$(MSBuildProjectName)</AssemblyName>
8+
<SchemaVersion>2.0</SchemaVersion>
9+
<ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
10+
<OutputType>Exe</OutputType>
11+
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
12+
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
13+
<CLRTestPriority>0</CLRTestPriority>
14+
</PropertyGroup>
15+
<!-- Default configurations to help VS understand the configurations -->
16+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
17+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "></PropertyGroup>
18+
<PropertyGroup>
19+
<DebugType>PdbOnly</DebugType>
20+
<Optimize>True</Optimize>
21+
</PropertyGroup>
22+
<ItemGroup>
23+
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
24+
<Visible>False</Visible>
25+
</CodeAnalysisDependentAssemblyPaths>
26+
</ItemGroup>
27+
<ItemGroup>
28+
<Compile Include="DevDiv_754566.il" />
29+
</ItemGroup>
30+
<ItemGroup>
31+
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
32+
</ItemGroup>
33+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
34+
<PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
35+
</Project>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Runtime.CompilerServices;
3+
4+
class Program
5+
{
6+
[MethodImpl(MethodImplOptions.NoInlining)]
7+
public String Test(int val)
8+
{
9+
return ((Object) val).ToString();
10+
}
11+
12+
static int Main(string[] args)
13+
{
14+
int exitStatus = -1;
15+
16+
Program p = new Program();
17+
18+
String result = p.Test(42);
19+
if (result == "42")
20+
{
21+
Console.WriteLine("=== PASSED ===");
22+
exitStatus = 100;
23+
}
24+
else
25+
{
26+
Console.WriteLine("result shoudl be 42, is= " + result);
27+
Console.WriteLine("+++ FAILED +++");
28+
}
29+
return exitStatus;
30+
}
31+
}

0 commit comments

Comments
 (0)