Skip to content

Commit

Permalink
Intrinsify typeof(T).IsGenericType (#99555)
Browse files Browse the repository at this point in the history
* Make Type.IsGenericType a JIT intrinsic

* Add Type.IsGenericType intrinsic tests

* Add intrinsic tests for nested types too

* Skip expanding the intrinsic for __Canon

* Add 'isGenericType' generated thunk

Fix vtable in CorInfoImpl_generated.cs

* Implement 'isGenericType' JIT/EE method

* Plug 'isGenericType' in importer

* Fix superPMI build

* Use 'TypeCompareState' for 'isGenericType'

* Add more test cases for shared generics

* Remove ref struct type from 'IsGenericType' tests

* Make __Canon type check less conservative

Co-authored-by: Jan Kotas <jkotas@microsoft.com>

* Update __Canon check in managed impl too

Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>

* Update tests, make them no inline

* Update generated code

* Fix rebase errors

* Fix more rebase errors

* Update jitinterface.cpp

* Make `isGenericType` use _LEAF transition

Co-authored-by: Jan Kotas <jkotas@microsoft.com>

* Make `isNullableType` use _LEAF transition

* Remove unnecessary shared generic check

---------

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
Co-authored-by: Miha Zupan <mihazupan.zupan1@gmail.com>
Co-authored-by: Egor Bogatov <egorbo@gmail.com>
  • Loading branch information
5 people committed Jun 16, 2024
1 parent eb455ec commit f4fd3ea
Show file tree
Hide file tree
Showing 22 changed files with 376 additions and 111 deletions.
5 changes: 5 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2718,6 +2718,11 @@ class ICorStaticInfo
CORINFO_CLASS_HANDLE cls
) = 0;

// Returns whether a class handle represents a generic type, if that can be statically determined.
virtual TypeCompareState isGenericType(
CORINFO_CLASS_HANDLE cls
) = 0;

// Returns whether a class handle represents a Nullable type, if that can be statically determined.
virtual TypeCompareState isNullableType(
CORINFO_CLASS_HANDLE cls
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 @@ -345,6 +345,9 @@ bool isMoreSpecificType(
bool isExactType(
CORINFO_CLASS_HANDLE cls) override;

TypeCompareState isGenericType(
CORINFO_CLASS_HANDLE cls) override;

TypeCompareState isNullableType(
CORINFO_CLASS_HANDLE cls) 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 = { /* de0cd36d-3094-4110-af7d-31eb36234e46 */
0xde0cd36d,
0x3094,
0x4110,
{0xaf, 0x7d, 0x31, 0xeb, 0x36, 0x23, 0x4e, 0x46}
constexpr GUID JITEEVersionIdentifier = { /* e428e66d-5e0e-4320-ad8a-fa5a50f6da07 */
0xe428e66d,
0x5e0e,
0x4320,
{0xad, 0x8a, 0xfa, 0x5a, 0x50, 0xf6, 0xda, 0x07}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
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 @@ -86,6 +86,7 @@ DEF_CLR_API(compareTypesForCast)
DEF_CLR_API(compareTypesForEquality)
DEF_CLR_API(isMoreSpecificType)
DEF_CLR_API(isExactType)
DEF_CLR_API(isGenericType)
DEF_CLR_API(isNullableType)
DEF_CLR_API(isEnum)
DEF_CLR_API(getParentType)
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 @@ -811,6 +811,15 @@ bool WrapICorJitInfo::isExactType(
return temp;
}

TypeCompareState WrapICorJitInfo::isGenericType(
CORINFO_CLASS_HANDLE cls)
{
API_ENTER(isGenericType);
TypeCompareState temp = wrapHnd->isGenericType(cls);
API_LEAVE(isGenericType);
return temp;
}

TypeCompareState WrapICorJitInfo::isNullableType(
CORINFO_CLASS_HANDLE cls)
{
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 @@ -1382,6 +1382,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
case NI_System_Type_get_IsValueType:
case NI_System_Type_get_IsPrimitive:
case NI_System_Type_get_IsByRefLike:
case NI_System_Type_get_IsGenericType:
case NI_System_Type_GetTypeFromHandle:
case NI_System_String_get_Length:
case NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness:
Expand Down
18 changes: 17 additions & 1 deletion src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3165,6 +3165,7 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
case NI_System_Type_get_IsByRefLike:
case NI_System_Type_IsAssignableFrom:
case NI_System_Type_IsAssignableTo:
case NI_System_Type_get_IsGenericType:

// Lightweight intrinsics
case NI_System_String_get_Chars:
Expand Down Expand Up @@ -3785,6 +3786,7 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
case NI_System_Type_get_IsValueType:
case NI_System_Type_get_IsPrimitive:
case NI_System_Type_get_IsByRefLike:
case NI_System_Type_get_IsGenericType:
{
// Optimize
//
Expand Down Expand Up @@ -3831,7 +3833,17 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
retNode = gtNewFalse();
}
break;

case NI_System_Type_get_IsGenericType:
{
TypeCompareState state = info.compCompHnd->isGenericType(hClass);
if (state == TypeCompareState::May)
{
retNode = nullptr;
break;
}
retNode = state == TypeCompareState::Must ? gtNewTrue() : gtNewFalse();
break;
}
default:
NO_WAY("Intrinsic not supported in this path.");
}
Expand Down Expand Up @@ -10015,6 +10027,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
{
result = NI_System_Type_get_IsPrimitive;
}
else if (strcmp(methodName, "get_IsGenericType") == 0)
{
result = NI_System_Type_get_IsGenericType;
}
else if (strcmp(methodName, "get_IsByRefLike") == 0)
{
result = NI_System_Type_get_IsByRefLike;
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 @@ -81,6 +81,7 @@ enum NamedIntrinsic : unsigned short
NI_System_Type_get_IsPrimitive,
NI_System_Type_get_IsByRefLike,
NI_System_Type_get_TypeHandle,
NI_System_Type_get_IsGenericType,
NI_System_Type_IsAssignableFrom,
NI_System_Type_IsAssignableTo,
NI_System_Type_op_Equality,
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2938,6 +2938,18 @@ private bool isExactType(CORINFO_CLASS_STRUCT_* cls)
return _compilation.IsEffectivelySealed(type);
}

private TypeCompareState isGenericType(CORINFO_CLASS_STRUCT_* cls)
{
TypeDesc type = HandleToObject(cls);

if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any))
{
return TypeCompareState.May;
}

return type.HasInstantiation ? TypeCompareState.Must : TypeCompareState.MustNot;
}

private TypeCompareState isNullableType(CORINFO_CLASS_STRUCT_* cls)
{
TypeDesc type = HandleToObject(cls);
Expand Down
Loading

0 comments on commit f4fd3ea

Please sign in to comment.