Skip to content
Closed
15 changes: 15 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2134,6 +2134,21 @@ class ICorStaticInfo
CORINFO_METHOD_HANDLE meth1Hnd,
CORINFO_METHOD_HANDLE meth2Hnd) = 0;

//------------------------------------------------------------------------------
// getTypeDefinition: Get the (unconstructed) type definition from a given type handle.
//
// Arguments:
// type - The input type handle
//
// Return Value:
// The type handle for the (unconstructed) type definition from type.
//
// Remarks:
// This is equivalent of Type.GetGenericTypeDefinition(). Given a generic type handle, it will
// return the original type definition (eg. for Foo<int> it will return Foo<>). This method
// should only be called when the input type is in fact a generic type.
virtual CORINFO_CLASS_HANDLE getTypeDefinition(CORINFO_CLASS_HANDLE type) = 0;

// Decides if you have any limitations for inlining. If everything's OK, it will return
// INLINE_PASS.
//
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/inc/icorjitinfoimpl_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ bool haveSameMethodDefinition(
CORINFO_METHOD_HANDLE meth1Hnd,
CORINFO_METHOD_HANDLE meth2Hnd) override;

CORINFO_CLASS_HANDLE getTypeDefinition(
CORINFO_CLASS_HANDLE type) override;

CorInfoInline canInline(
CORINFO_METHOD_HANDLE callerHnd,
CORINFO_METHOD_HANDLE calleeHnd) override;
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED

constexpr GUID JITEEVersionIdentifier = { /* 86eab154-5d93-4fad-bc07-e94fd9268b70 */
0x86eab154,
0x5d93,
0x4fad,
{0xbc, 0x07, 0xe9, 0x4f, 0xd9, 0x26, 0x8b, 0x70}
constexpr GUID JITEEVersionIdentifier = { /* dbcd6414-2c05-4414-9086-6417cffb94d1 */
0xdbcd6414,
0x2c05,
0x4414,
{0x90, 0x86, 0x64, 0x17, 0xcf, 0xfb, 0x94, 0xd1}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/ICorJitInfo_names_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ DEF_CLR_API(setMethodAttribs)
DEF_CLR_API(getMethodSig)
DEF_CLR_API(getMethodInfo)
DEF_CLR_API(haveSameMethodDefinition)
DEF_CLR_API(getTypeDefinition)
DEF_CLR_API(canInline)
DEF_CLR_API(beginInlining)
DEF_CLR_API(reportInliningDecision)
Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,15 @@ bool WrapICorJitInfo::haveSameMethodDefinition(
return temp;
}

CORINFO_CLASS_HANDLE WrapICorJitInfo::getTypeDefinition(
CORINFO_CLASS_HANDLE type)
{
API_ENTER(getTypeDefinition);
CORINFO_CLASS_HANDLE temp = wrapHnd->getTypeDefinition(type);
API_LEAVE(getTypeDefinition);
return temp;
}

CorInfoInline WrapICorJitInfo::canInline(
CORINFO_METHOD_HANDLE callerHnd,
CORINFO_METHOD_HANDLE calleeHnd)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4429,6 +4429,7 @@ class Compiler
void impImportLeave(BasicBlock* block);
void impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr);
GenTree* impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom);
GenTree* impGetGenericTypeDefinition(GenTree* type);

// Mirrors StringComparison.cs
enum StringComparison
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/fgbasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
case NI_System_Type_get_IsPrimitive:
case NI_System_Type_get_IsByRefLike:
case NI_System_Type_GetTypeFromHandle:
case NI_System_Type_GetGenericTypeDefinition:
case NI_System_String_get_Length:
case NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness:
#if defined(FEATURE_HW_INTRINSICS)
Expand Down
27 changes: 27 additions & 0 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2486,6 +2486,33 @@ GenTree* Compiler::impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom)
return nullptr;
}


GenTree* Compiler::impGetGenericTypeDefinition(GenTree* type)
{
// This intrinsic requires the first arg to be some `typeof()` expression,
// ie. it applies to cases such as `typeof(...).GetGenericTypeDefinition()`.
CORINFO_CLASS_HANDLE hClassType = NO_CLASS_HANDLE;
if (gtIsTypeof(type, &hClassType))
{
// Check that the 'typeof()' expression is being used on a type that is in fact generic.
// If that is not the case, we don't expand the intrinsic. This will end up using
// the usual Type.GetGenericTypeDefinition() at runtime, which will throw in this case.
if (info.compCompHnd->getTypeInstantiationArgument(hClassType, 0) != NO_CLASS_HANDLE)
{
CORINFO_CLASS_HANDLE hClassResult = info.compCompHnd->getTypeDefinition(hClassType);

GenTree* retNode = gtNewIconEmbClsHndNode(hClassResult);

// Drop the typeof(T) node
impPopStack();

return retNode;
}
}

return nullptr;
}

/*****************************************************************************
* 'logMsg' is true if a log message needs to be logged. false if the caller has
* already logged it (presumably in a more detailed fashion than done here)
Expand Down
15 changes: 15 additions & 0 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2874,6 +2874,9 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
case NI_System_Type_op_Equality:
case NI_System_Type_op_Inequality:

// This allows folding "typeof(...).GetGenericTypeDefinition() == typeof(...)"
case NI_System_Type_GetGenericTypeDefinition:

// These may lead to early dead code elimination
case NI_System_Type_get_IsValueType:
case NI_System_Type_get_IsPrimitive:
Expand Down Expand Up @@ -3391,6 +3394,14 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
break;
}

case NI_System_Type_GetGenericTypeDefinition:
{
GenTree* type = impStackTop(0).val;

retNode = impGetGenericTypeDefinition(type);
break;
}

case NI_System_Type_op_Equality:
case NI_System_Type_op_Inequality:
{
Expand Down Expand Up @@ -9250,6 +9261,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
{
result = NI_System_Type_GetTypeFromHandle;
}
else if (strcmp(methodName, "GetGenericTypeDefinition") == 0)
{
result = NI_System_Type_GetGenericTypeDefinition;
}
else if (strcmp(methodName, "IsAssignableFrom") == 0)
{
result = NI_System_Type_IsAssignableFrom;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/namedintrinsiclist.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum NamedIntrinsic : unsigned short
NI_System_Type_op_Equality,
NI_System_Type_op_Inequality,
NI_System_Type_GetTypeFromHandle,
NI_System_Type_GetGenericTypeDefinition,
NI_System_Array_Clone,
NI_System_Array_GetLength,
NI_System_Array_GetLowerBound,
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,11 @@ private bool haveSameMethodDefinition(CORINFO_METHOD_STRUCT_* methHnd1, CORINFO_
return meth1.GetTypicalMethodDefinition() == meth2.GetTypicalMethodDefinition();
}

private CORINFO_CLASS_STRUCT_* getTypeDefinition(CORINFO_CLASS_STRUCT_* type)
{
return ObjectToHandle(HandleToObject(type).GetTypeDefinition());
}

private CorInfoInline canInline(CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUCT_* calleeHnd)
{
MethodDesc callerMethod = HandleToObject(callerHnd);
Expand Down
Loading