Skip to content

Commit 5ee8f4a

Browse files
Sergio0694jkotas
andauthored
Intrinsify typeof(T).GetGenericTypeDefinition() (#103528)
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
1 parent 767e416 commit 5ee8f4a

File tree

24 files changed

+457
-175
lines changed

24 files changed

+457
-175
lines changed

src/coreclr/inc/corinfo.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,6 +2082,22 @@ class ICorStaticInfo
20822082
CORINFO_METHOD_HANDLE meth1Hnd,
20832083
CORINFO_METHOD_HANDLE meth2Hnd) = 0;
20842084

2085+
//------------------------------------------------------------------------------
2086+
// getTypeDefinition: Get the (unconstructed) type definition from a given type handle.
2087+
//
2088+
// Arguments:
2089+
// type - The input type handle
2090+
//
2091+
// Return Value:
2092+
// The type handle for the (unconstructed) type definition from type.
2093+
//
2094+
// Remarks:
2095+
// This is equivalent of Type.GetGenericTypeDefinition(). Given a generic type handle, it will
2096+
// return the original type definition (eg. for Foo<int> it will return Foo<>). If called with
2097+
// an unconstructed generic type, the method returns the same type as the input. This method
2098+
// should only be called when the input type is in fact a generic type.
2099+
virtual CORINFO_CLASS_HANDLE getTypeDefinition(CORINFO_CLASS_HANDLE type) = 0;
2100+
20852101
// Decides if you have any limitations for inlining. If everything's OK, it will return
20862102
// INLINE_PASS.
20872103
//

src/coreclr/inc/icorjitinfoimpl_generated.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ bool haveSameMethodDefinition(
4848
CORINFO_METHOD_HANDLE meth1Hnd,
4949
CORINFO_METHOD_HANDLE meth2Hnd) override;
5050

51+
CORINFO_CLASS_HANDLE getTypeDefinition(
52+
CORINFO_CLASS_HANDLE type) override;
53+
5154
CorInfoInline canInline(
5255
CORINFO_METHOD_HANDLE callerHnd,
5356
CORINFO_METHOD_HANDLE calleeHnd) override;

src/coreclr/inc/jiteeversionguid.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
4343
#define GUID_DEFINED
4444
#endif // !GUID_DEFINED
4545

46-
constexpr GUID JITEEVersionIdentifier = { /* 64fe30fb-0a27-4b1d-b89e-306e552ac848 */
47-
0x64fe30fb,
48-
0x0a27,
49-
0x4b1d,
50-
{0xb8, 0x9e, 0x30, 0x6e, 0x55, 0x2a, 0xc8, 0x48}
46+
constexpr GUID JITEEVersionIdentifier = { /* 273ba350-32bf-4714-beb0-7fa46c11364d */
47+
0x273ba350,
48+
0x32bf,
49+
0x4714,
50+
{0xbe, 0xb0, 0x7f, 0xa4, 0x6c, 0x11, 0x36, 0x4d}
5151
};
5252

5353
//////////////////////////////////////////////////////////////////////////////////////////////////////////

src/coreclr/jit/ICorJitInfo_names_generated.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ DEF_CLR_API(setMethodAttribs)
1111
DEF_CLR_API(getMethodSig)
1212
DEF_CLR_API(getMethodInfo)
1313
DEF_CLR_API(haveSameMethodDefinition)
14+
DEF_CLR_API(getTypeDefinition)
1415
DEF_CLR_API(canInline)
1516
DEF_CLR_API(beginInlining)
1617
DEF_CLR_API(reportInliningDecision)

src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ bool WrapICorJitInfo::haveSameMethodDefinition(
7979
return temp;
8080
}
8181

82+
CORINFO_CLASS_HANDLE WrapICorJitInfo::getTypeDefinition(
83+
CORINFO_CLASS_HANDLE type)
84+
{
85+
API_ENTER(getTypeDefinition);
86+
CORINFO_CLASS_HANDLE temp = wrapHnd->getTypeDefinition(type);
87+
API_LEAVE(getTypeDefinition);
88+
return temp;
89+
}
90+
8291
CorInfoInline WrapICorJitInfo::canInline(
8392
CORINFO_METHOD_HANDLE callerHnd,
8493
CORINFO_METHOD_HANDLE calleeHnd)

src/coreclr/jit/compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4589,6 +4589,7 @@ class Compiler
45894589
#endif
45904590
void impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr);
45914591
GenTree* impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom);
4592+
GenTree* impGetGenericTypeDefinition(GenTree* type);
45924593

45934594
// Mirrors StringComparison.cs
45944595
enum StringComparison

src/coreclr/jit/fgbasic.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
13871387
case NI_System_Type_get_IsByRefLike:
13881388
case NI_System_Type_get_IsGenericType:
13891389
case NI_System_Type_GetTypeFromHandle:
1390+
case NI_System_Type_GetGenericTypeDefinition:
13901391
case NI_System_String_get_Length:
13911392
case NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness:
13921393
#if defined(FEATURE_HW_INTRINSICS)

src/coreclr/jit/importer.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2490,6 +2490,42 @@ GenTree* Compiler::impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom)
24902490
return nullptr;
24912491
}
24922492

2493+
//------------------------------------------------------------------------
2494+
// impGetGenericTypeDefinition: gets the generic type definition from a 'typeof' expression.
2495+
//
2496+
// Arguments:
2497+
// type - The 'GenTree' node to inspect.
2498+
//
2499+
// Notes:
2500+
// If successful, this method will call 'impPopStack()' before returning.
2501+
//
2502+
GenTree* Compiler::impGetGenericTypeDefinition(GenTree* type)
2503+
{
2504+
// This intrinsic requires the first arg to be some `typeof()` expression,
2505+
// ie. it applies to cases such as `typeof(...).GetGenericTypeDefinition()`.
2506+
CORINFO_CLASS_HANDLE hClassType = NO_CLASS_HANDLE;
2507+
if (gtIsTypeof(type, &hClassType))
2508+
{
2509+
// Check that the 'typeof()' expression is being used on a type that is in fact generic.
2510+
// If that is not the case, we don't expand the intrinsic. This will end up using
2511+
// the usual Type.GetGenericTypeDefinition() at runtime, which will throw in this case.
2512+
if (info.compCompHnd->getTypeInstantiationArgument(hClassType, 0) != NO_CLASS_HANDLE)
2513+
{
2514+
CORINFO_CLASS_HANDLE hClassResult = info.compCompHnd->getTypeDefinition(hClassType);
2515+
2516+
GenTree* handle = gtNewIconEmbClsHndNode(hClassResult);
2517+
GenTree* retNode = gtNewHelperCallNode(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, TYP_REF, handle);
2518+
2519+
// Drop the typeof(T) node
2520+
impPopStack();
2521+
2522+
return retNode;
2523+
}
2524+
}
2525+
2526+
return nullptr;
2527+
}
2528+
24932529
/*****************************************************************************
24942530
* 'logMsg' is true if a log message needs to be logged. false if the caller has
24952531
* already logged it (presumably in a more detailed fashion than done here)

src/coreclr/jit/importercalls.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3321,6 +3321,9 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
33213321
case NI_System_Type_op_Equality:
33223322
case NI_System_Type_op_Inequality:
33233323

3324+
// This allows folding "typeof(...).GetGenericTypeDefinition() == typeof(...)"
3325+
case NI_System_Type_GetGenericTypeDefinition:
3326+
33243327
// These may lead to early dead code elimination
33253328
case NI_System_Type_get_IsValueType:
33263329
case NI_System_Type_get_IsPrimitive:
@@ -3856,6 +3859,14 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
38563859
break;
38573860
}
38583861

3862+
case NI_System_Type_GetGenericTypeDefinition:
3863+
{
3864+
GenTree* type = impStackTop(0).val;
3865+
3866+
retNode = impGetGenericTypeDefinition(type);
3867+
break;
3868+
}
3869+
38593870
case NI_System_Type_op_Equality:
38603871
case NI_System_Type_op_Inequality:
38613872
{
@@ -10220,6 +10231,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
1022010231
{
1022110232
result = NI_System_Type_GetTypeFromHandle;
1022210233
}
10234+
else if (strcmp(methodName, "GetGenericTypeDefinition") == 0)
10235+
{
10236+
result = NI_System_Type_GetGenericTypeDefinition;
10237+
}
1022310238
else if (strcmp(methodName, "IsAssignableFrom") == 0)
1022410239
{
1022510240
result = NI_System_Type_IsAssignableFrom;

src/coreclr/jit/namedintrinsiclist.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ enum NamedIntrinsic : unsigned short
8989
NI_System_Type_op_Equality,
9090
NI_System_Type_op_Inequality,
9191
NI_System_Type_GetTypeFromHandle,
92+
NI_System_Type_GetGenericTypeDefinition,
9293
NI_System_Array_Clone,
9394
NI_System_Array_GetLength,
9495
NI_System_Array_GetLowerBound,

0 commit comments

Comments
 (0)