Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NativeAOT] Make casting logic closer to CoreCLR #89548

Closed
wants to merge 12 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@ internal static unsafe class CastHelpers
return ChkCastClassSpecial(toTypeHnd, obj);
}

// Optimized helper for classes. Assumes that the trivial cases
// has been taken care of by the inlined check
[DebuggerHidden]
[StackTraceHidden]
[DebuggerStepThrough]
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,12 +429,10 @@ enum CorInfoHelpFunc
// the right helper to use
jkotas marked this conversation as resolved.
Show resolved Hide resolved

CORINFO_HELP_ISINSTANCEOFINTERFACE, // Optimized helper for interfaces
CORINFO_HELP_ISINSTANCEOFARRAY, // Optimized helper for arrays
CORINFO_HELP_ISINSTANCEOFCLASS, // Optimized helper for classes
CORINFO_HELP_ISINSTANCEOFANY, // Slow helper for any type

CORINFO_HELP_CHKCASTINTERFACE,
CORINFO_HELP_CHKCASTARRAY,
CORINFO_HELP_CHKCASTCLASS,
CORINFO_HELP_CHKCASTANY,
CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases
Expand Down Expand Up @@ -858,6 +856,7 @@ enum CorInfoFlag
CORINFO_FLG_ARRAY = 0x00080000, // class is an array class (initialized differently)
CORINFO_FLG_OVERLAPPING_FIELDS = 0x00100000, // struct or class has fields that overlap (aka union)
CORINFO_FLG_INTERFACE = 0x00200000, // it is an interface
CORINFO_FLG_TYPE_EQUIVALENCE = 0x00400000, // this type participates in type equivalence
CORINFO_FLG_CONTAINS_GC_PTR = 0x01000000, // does the class contain a gc ptr ?
CORINFO_FLG_DELEGATE = 0x02000000, // is this a subclass of delegate or multicast delegate ?
CORINFO_FLG_INDEXABLE_FIELDS = 0x04000000, // struct fields may be accessed via indexing (used for inline arrays)
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 = { /* a20effd6-2cd4-4657-8d2f-1d3e5d7eeab9 */
0xa20effd6,
0x2cd4,
0x4657,
{0x8d, 0x2f, 0x1d, 0x3e, 0x5d, 0x7e, 0xea, 0xb9}
constexpr GUID JITEEVersionIdentifier = { /* 2c447f91-74be-4f02-a836-0cfd35224a1d */
0x2c447f91,
0x74be,
0x4f02,
{0xa8, 0x36, 0x0c, 0xfd, 0x35, 0x22, 0x4a, 0x1d}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/inc/jithelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,9 @@

// Casting helpers
DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFINTERFACE, NULL, CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFARRAY, NULL, CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFCLASS, NULL, CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFANY, NULL, CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_CHKCASTINTERFACE, NULL, CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_CHKCASTARRAY, NULL, CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS, NULL, CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_CHKCASTANY, NULL, CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS_SPECIAL, NULL, CORINFO_HELP_SIG_REG_ONLY)
Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2171,7 +2171,6 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree)
// Also note The CASTCLASS helpers won't appear in predicates as they throw on failure.
// So the helper list here is smaller than the one in optAssertionProp_Call.
if ((call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_ISINSTANCEOFINTERFACE)) ||
(call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_ISINSTANCEOFARRAY)) ||
(call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_ISINSTANCEOFCLASS)) ||
(call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_ISINSTANCEOFANY)))
{
Expand Down Expand Up @@ -4483,11 +4482,9 @@ GenTree* Compiler::optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCal
else if (!optLocalAssertionProp && (call->gtCallType == CT_HELPER))
{
if (call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_ISINSTANCEOFINTERFACE) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_ISINSTANCEOFARRAY) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_ISINSTANCEOFCLASS) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_ISINSTANCEOFANY) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_CHKCASTINTERFACE) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_CHKCASTARRAY) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_CHKCASTCLASS) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_CHKCASTANY) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_CHKCASTCLASS_SPECIAL))
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18316,11 +18316,9 @@ CORINFO_CLASS_HANDLE Compiler::gtGetHelperCallClassHandle(GenTreeCall* call, boo

case CORINFO_HELP_CHKCASTCLASS:
case CORINFO_HELP_CHKCASTANY:
case CORINFO_HELP_CHKCASTARRAY:
case CORINFO_HELP_CHKCASTINTERFACE:
case CORINFO_HELP_CHKCASTCLASS_SPECIAL:
case CORINFO_HELP_ISINSTANCEOFINTERFACE:
case CORINFO_HELP_ISINSTANCEOFARRAY:
case CORINFO_HELP_ISINSTANCEOFCLASS:
case CORINFO_HELP_ISINSTANCEOFANY:
{
Expand Down
12 changes: 6 additions & 6 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5469,8 +5469,8 @@ GenTree* Compiler::impCastClassOrIsInstToTree(
}
else if (isCastClass)
{
// Jit can only inline expand CHKCASTCLASS and CHKCASTARRAY helpers.
canExpandInline = (helper == CORINFO_HELP_CHKCASTCLASS) || (helper == CORINFO_HELP_CHKCASTARRAY);
// Jit can always inline expand CHKCASTCLASS
canExpandInline = (helper == CORINFO_HELP_CHKCASTCLASS);

// For ChkCastAny we ignore cases where the class is known to be abstract or is an interface.
if (helper == CORINFO_HELP_CHKCASTANY)
Expand All @@ -5480,7 +5480,7 @@ GenTree* Compiler::impCastClassOrIsInstToTree(
canExpandInline = !isAbstract;
}
}
else if ((helper == CORINFO_HELP_ISINSTANCEOFCLASS) || (helper == CORINFO_HELP_ISINSTANCEOFARRAY))
else if ((helper == CORINFO_HELP_ISINSTANCEOFCLASS) || (helper == CORINFO_HELP_ISINSTANCEOFANY))
{
// If the class is exact, the jit can expand the IsInst check inline.
jkotas marked this conversation as resolved.
Show resolved Hide resolved
canExpandInline = isClassExact;
Expand Down Expand Up @@ -5616,8 +5616,8 @@ GenTree* Compiler::impCastClassOrIsInstToTree(
GenTree* condTrue;
if (isCastClass)
{
assert((helper == CORINFO_HELP_CHKCASTCLASS) || (helper == CORINFO_HELP_CHKCASTARRAY) ||
(helper == CORINFO_HELP_CHKCASTANY) || (helper == CORINFO_HELP_CHKCASTINTERFACE));
assert((helper == CORINFO_HELP_CHKCASTCLASS) || (helper == CORINFO_HELP_CHKCASTANY) ||
(helper == CORINFO_HELP_CHKCASTINTERFACE));

CorInfoHelpFunc specialHelper = helper;
if ((helper == CORINFO_HELP_CHKCASTCLASS) &&
Expand Down Expand Up @@ -13612,7 +13612,7 @@ methodPointerInfo* Compiler::impAllocateMethodPointerInfo(const CORINFO_RESOLVED
bool Compiler::impIsClassExact(CORINFO_CLASS_HANDLE classHnd)
{
DWORD flags = info.compCompHnd->getClassAttribs(classHnd);
DWORD flagsMask = CORINFO_FLG_FINAL | CORINFO_FLG_VARIANCE | CORINFO_FLG_ARRAY;
DWORD flagsMask = CORINFO_FLG_FINAL | CORINFO_FLG_VARIANCE | CORINFO_FLG_TYPE_EQUIVALENCE | CORINFO_FLG_ARRAY;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both CORINFO_FLG_VARIANCE and CORINFO_FLG_TYPE_EQUIVALENCE are only computed to make the impIsClassExact work. Computing these flags is a waste in all other cases. It is the kind of pattern that calls for introduction of dedicated JIT/EE interface API that replaces the flags.


if ((flags & flagsMask) == CORINFO_FLG_FINAL)
{
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/jit/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1390,7 +1390,6 @@ void HelperCallProperties::init()

// type casting helpers
case CORINFO_HELP_ISINSTANCEOFINTERFACE:
case CORINFO_HELP_ISINSTANCEOFARRAY:
case CORINFO_HELP_ISINSTANCEOFCLASS:
case CORINFO_HELP_ISINSTANCEOFANY:
case CORINFO_HELP_READYTORUN_ISINSTANCEOF:
Expand All @@ -1408,7 +1407,6 @@ void HelperCallProperties::init()

// type casting helpers that throw
case CORINFO_HELP_CHKCASTINTERFACE:
case CORINFO_HELP_CHKCASTARRAY:
case CORINFO_HELP_CHKCASTCLASS:
case CORINFO_HELP_CHKCASTANY:
case CORINFO_HELP_CHKCASTCLASS_SPECIAL:
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12755,7 +12755,6 @@ VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc)

case CORINFO_HELP_CHKCASTCLASS:
case CORINFO_HELP_CHKCASTCLASS_SPECIAL:
case CORINFO_HELP_CHKCASTARRAY:
case CORINFO_HELP_CHKCASTINTERFACE:
case CORINFO_HELP_CHKCASTANY:
vnf = VNF_CastClass;
Expand All @@ -12767,7 +12766,6 @@ VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc)

case CORINFO_HELP_ISINSTANCEOFCLASS:
case CORINFO_HELP_ISINSTANCEOFINTERFACE:
case CORINFO_HELP_ISINSTANCEOFARRAY:
case CORINFO_HELP_ISINSTANCEOFANY:
vnf = VNF_IsInstanceOf;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public static unsafe void RhUnboxAny(object? o, ref byte data, EETypePtr pUnboxT
}
else
{
if (o != null && (TypeCast.IsInstanceOf(ptrUnboxToEEType, o) == null))
if (o != null && (TypeCast.IsInstanceOfAny(ptrUnboxToEEType, o) == null))
{
throw ptrUnboxToEEType->GetClasslibException(ExceptionIDs.InvalidCast);
}
Expand Down Expand Up @@ -392,26 +392,18 @@ internal static unsafe IntPtr RhGetRuntimeHelperForType(MethodTable* pEEType, Ru
return (IntPtr)(delegate*<MethodTable*, object>)&InternalCalls.RhpNewFast;

case RuntimeHelperKind.IsInst:
if (pEEType->IsArray)
return (IntPtr)(delegate*<MethodTable*, object, object>)&TypeCast.IsInstanceOfArray;
else if (pEEType->HasGenericVariance)
return (IntPtr)(delegate*<MethodTable*, object, object>)&TypeCast.IsInstanceOf;
if (pEEType->HasGenericVariance || pEEType->IsParameterizedType || pEEType->IsFunctionPointerType)
return (IntPtr)(delegate*<MethodTable*, object, object?>)&TypeCast.IsInstanceOfAny;
else if (pEEType->IsInterface)
return (IntPtr)(delegate*<MethodTable*, object?, object?>)&TypeCast.IsInstanceOfInterface;
else if (pEEType->IsParameterizedType || pEEType->IsFunctionPointerType)
return (IntPtr)(delegate*<MethodTable*, object, object>)&TypeCast.IsInstanceOf; // Array handled above; pointers and byrefs handled here
else
return (IntPtr)(delegate*<MethodTable*, object?, object?>)&TypeCast.IsInstanceOfClass;

case RuntimeHelperKind.CastClass:
if (pEEType->IsArray)
return (IntPtr)(delegate*<MethodTable*, object, object>)&TypeCast.CheckCastArray;
else if (pEEType->HasGenericVariance)
return (IntPtr)(delegate*<MethodTable*, object, object>)&TypeCast.CheckCast;
if (pEEType->HasGenericVariance || pEEType->IsParameterizedType || pEEType->IsFunctionPointerType)
return (IntPtr)(delegate*<MethodTable*, object, object>)&TypeCast.CheckCastAny;
else if (pEEType->IsInterface)
return (IntPtr)(delegate*<MethodTable*, object, object>)&TypeCast.CheckCastInterface;
else if (pEEType->IsParameterizedType || pEEType->IsFunctionPointerType)
return (IntPtr)(delegate*<MethodTable*, object, object>)&TypeCast.CheckCast; // Array handled above; pointers and byrefs handled here
else
return (IntPtr)(delegate*<MethodTable*, object, object>)&TypeCast.CheckCastClass;

Expand Down
Loading