Skip to content

Commit

Permalink
Intrinsify typeof(T).GetGenericTypeDefinition() (#103528)
Browse files Browse the repository at this point in the history
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
  • Loading branch information
Sergio0694 and jkotas authored Jul 19, 2024
1 parent 767e416 commit 5ee8f4a
Show file tree
Hide file tree
Showing 24 changed files with 457 additions and 175 deletions.
16 changes: 16 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2082,6 +2082,22 @@ 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<>). If called with
// an unconstructed generic type, the method returns the same type as the input. 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 = { /* 64fe30fb-0a27-4b1d-b89e-306e552ac848 */
0x64fe30fb,
0x0a27,
0x4b1d,
{0xb8, 0x9e, 0x30, 0x6e, 0x55, 0x2a, 0xc8, 0x48}
constexpr GUID JITEEVersionIdentifier = { /* 273ba350-32bf-4714-beb0-7fa46c11364d */
0x273ba350,
0x32bf,
0x4714,
{0xbe, 0xb0, 0x7f, 0xa4, 0x6c, 0x11, 0x36, 0x4d}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
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 @@ -4589,6 +4589,7 @@ class Compiler
#endif
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 @@ -1387,6 +1387,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
case NI_System_Type_get_IsByRefLike:
case NI_System_Type_get_IsGenericType:
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
36 changes: 36 additions & 0 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2490,6 +2490,42 @@ GenTree* Compiler::impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom)
return nullptr;
}

//------------------------------------------------------------------------
// impGetGenericTypeDefinition: gets the generic type definition from a 'typeof' expression.
//
// Arguments:
// type - The 'GenTree' node to inspect.
//
// Notes:
// If successful, this method will call 'impPopStack()' before returning.
//
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* handle = gtNewIconEmbClsHndNode(hClassResult);
GenTree* retNode = gtNewHelperCallNode(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, TYP_REF, handle);

// 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 @@ -3321,6 +3321,9 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
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 @@ -3856,6 +3859,14 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
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 @@ -10220,6 +10231,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 @@ -89,6 +89,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 @@ -1248,6 +1248,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

0 comments on commit 5ee8f4a

Please sign in to comment.