Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/coreclr/jit/fgbasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed

// These are foldable if the first argument is a constant
case NI_System_Type_get_IsValueType:
case NI_System_Type_get_IsByRefLike:
case NI_System_Type_GetTypeFromHandle:
case NI_System_String_get_Length:
case NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness:
Expand Down
34 changes: 26 additions & 8 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4282,14 +4282,16 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
}

case NI_System_Type_get_IsValueType:
case NI_System_Type_get_IsByRefLike:
{
// Optimize
//
// call Type.GetTypeFromHandle (which is replaced with CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE)
// call Type.IsValueType
// call Type.IsXXX
//
// to `true` or `false`
// e.g. `typeof(int).IsValueType` => `true`
// e.g., `typeof(int).IsValueType` => `true`
// e.g., `typeof(Span<int>).IsByRefLike` => `true`
if (impStackTop().val->IsCall())
{
GenTreeCall* call = impStackTop().val->AsCall();
Expand All @@ -4298,12 +4300,24 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
CORINFO_CLASS_HANDLE hClass = gtGetHelperArgClassHandle(call->gtCallArgs->GetNode());
if (hClass != NO_CLASS_HANDLE)
{
retNode =
gtNewIconNode((eeIsValueClass(hClass) &&
// pointers are not value types (e.g. typeof(int*).IsValueType is false)
info.compCompHnd->asCorInfoType(hClass) != CORINFO_TYPE_PTR)
? 1
: 0);
switch (ni)
{
case NI_System_Type_get_IsValueType:
retNode = gtNewIconNode(
(eeIsValueClass(hClass) &&
// pointers are not value types (e.g. typeof(int*).IsValueType is false)
info.compCompHnd->asCorInfoType(hClass) != CORINFO_TYPE_PTR)
? 1
: 0);
break;
case NI_System_Type_get_IsByRefLike:
retNode = gtNewIconNode(
(info.compCompHnd->getClassAttribs(hClass) & CORINFO_FLG_BYREF_LIKE) ? 1 : 0);
break;
default:
NO_WAY("Intrinsic not supported in this path.");
}

impPopStack(); // drop CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE call
}
}
Expand Down Expand Up @@ -5251,6 +5265,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
{
result = NI_System_Type_get_IsValueType;
}
else if (strcmp(methodName, "get_IsByRefLike") == 0)
{
result = NI_System_Type_get_IsByRefLike;
}
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 @@ -56,6 +56,7 @@ enum NamedIntrinsic : unsigned short
NI_System_Threading_Thread_get_CurrentThread,
NI_System_Threading_Thread_get_ManagedThreadId,
NI_System_Type_get_IsValueType,
NI_System_Type_get_IsByRefLike,
NI_System_Type_IsAssignableFrom,
NI_System_Type_IsAssignableTo,
NI_System_Type_op_Equality,
Expand Down
4 changes: 2 additions & 2 deletions src/libraries/System.Private.CoreLib/src/System/Type.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ protected Type() { }
public virtual bool IsSZArray => throw NotImplemented.ByDesign;
public virtual bool IsVariableBoundArray => IsArray && !IsSZArray;

public virtual bool IsByRefLike => throw new NotSupportedException(SR.NotSupported_SubclassOverride);
public virtual bool IsByRefLike { [Intrinsic] get => throw new NotSupportedException(SR.NotSupported_SubclassOverride); }

public bool HasElementType => HasElementTypeImpl();
protected abstract bool HasElementTypeImpl();
Expand Down Expand Up @@ -110,10 +110,10 @@ public virtual Type[] GetGenericParameterConstraints()
public bool IsPrimitive => IsPrimitiveImpl();
protected abstract bool IsPrimitiveImpl();
public bool IsValueType { [Intrinsic] get => IsValueTypeImpl(); }
protected virtual bool IsValueTypeImpl() => IsSubclassOf(typeof(ValueType));

[Intrinsic]
public bool IsAssignableTo([NotNullWhen(true)] Type? targetType) => targetType?.IsAssignableFrom(this) ?? false;
protected virtual bool IsValueTypeImpl() => IsSubclassOf(typeof(ValueType));

public virtual bool IsSignatureType => false;

Expand Down