Skip to content

Commit

Permalink
Get rid of EETypePtr (dotnet#97207)
Browse files Browse the repository at this point in the history
Resolves dotnet/runtimelab#232.

This wrapper served two purposes over `MethodTable*`:

* Make sure equality semantics were enforced at the time where we could have multiple `MethodTable*` representing the same type. This is no longer the case and we don't need it for this purpose.
* Save us from typing `unsafe`

Apart from this, it also pessimized codegen (see the linked issue). Bye `EETypePtr`.

I didn't fully delete it because the `CorElementType` conversion is still there. We can deal with that later.
  • Loading branch information
MichalStrehovsky authored and tmds committed Jan 23, 2024
1 parent f07039b commit 7a6c786
Show file tree
Hide file tree
Showing 44 changed files with 437 additions and 923 deletions.
9 changes: 0 additions & 9 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2788,7 +2788,6 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
case NI_Internal_Runtime_MethodTable_Of:
case NI_System_Activator_AllocatorOf:
case NI_System_Activator_DefaultConstructorOf:
case NI_System_EETypePtr_EETypePtrOf:
betterToExpand = true;
break;

Expand Down Expand Up @@ -2981,7 +2980,6 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
case NI_Internal_Runtime_MethodTable_Of:
case NI_System_Activator_AllocatorOf:
case NI_System_Activator_DefaultConstructorOf:
case NI_System_EETypePtr_EETypePtrOf:
{
assert(IsTargetAbi(CORINFO_NATIVEAOT_ABI)); // Only NativeAOT supports it.
CORINFO_RESOLVED_TOKEN resolvedToken;
Expand Down Expand Up @@ -8830,13 +8828,6 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
result = NI_System_Enum_HasFlag;
}
}
else if (strcmp(className, "EETypePtr") == 0)
{
if (strcmp(methodName, "EETypePtrOf") == 0)
{
result = NI_System_EETypePtr_EETypePtrOf;
}
}
break;
}

Expand Down
1 change: 0 additions & 1 deletion src/coreclr/jit/namedintrinsiclist.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ enum NamedIntrinsic : unsigned short

NI_System_Activator_AllocatorOf,
NI_System_Activator_DefaultConstructorOf,
NI_System_EETypePtr_EETypePtrOf,

NI_Internal_Runtime_MethodTable_Of,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private static IntPtr RhpResolveInterfaceMethod(object pObject, IntPtr pCell)
}

[RuntimeExport("RhResolveDispatch")]
private static IntPtr RhResolveDispatch(object pObject, EETypePtr interfaceType, ushort slot)
private static IntPtr RhResolveDispatch(object pObject, MethodTable* interfaceType, ushort slot)
{
DispatchCellInfo cellInfo = default;
cellInfo.CellType = DispatchCellType.InterfaceAndSlot;
Expand All @@ -84,18 +84,12 @@ private static IntPtr RhResolveDispatch(object pObject, EETypePtr interfaceType,
}

[RuntimeExport("RhResolveDispatchOnType")]
private static IntPtr RhResolveDispatchOnType(EETypePtr instanceType, EETypePtr interfaceType, ushort slot, EETypePtr* pGenericContext)
private static IntPtr RhResolveDispatchOnType(MethodTable* pInstanceType, MethodTable* pInterfaceType, ushort slot, MethodTable** ppGenericContext)
{
// Type of object we're dispatching on.
MethodTable* pInstanceType = instanceType.ToPointer();

// Type of interface
MethodTable* pInterfaceType = interfaceType.ToPointer();

return DispatchResolve.FindInterfaceMethodImplementationTarget(pInstanceType,
pInterfaceType,
slot,
(MethodTable**)pGenericContext);
ppGenericContext);
}

private static unsafe IntPtr RhResolveDispatchWorker(object pObject, void* cell, ref DispatchCellInfo cellInfo)
Expand All @@ -110,7 +104,7 @@ private static unsafe IntPtr RhResolveDispatchWorker(object pObject, void* cell,
MethodTable* pResolvingInstanceType = pInstanceType;

IntPtr pTargetCode = DispatchResolve.FindInterfaceMethodImplementationTarget(pResolvingInstanceType,
cellInfo.InterfaceType.ToPointer(),
cellInfo.InterfaceType,
cellInfo.InterfaceSlot,
ppGenericContext: null);
if (pTargetCode == IntPtr.Zero && pInstanceType->IsIDynamicInterfaceCastable)
Expand All @@ -119,7 +113,7 @@ private static unsafe IntPtr RhResolveDispatchWorker(object pObject, void* cell,
// This will either give us the appropriate result, or throw.
var pfnGetInterfaceImplementation = (delegate*<object, MethodTable*, ushort, IntPtr>)
pInstanceType->GetClasslibFunction(ClassLibFunctionId.IDynamicCastableGetInterfaceImplementation);
pTargetCode = pfnGetInterfaceImplementation(pObject, cellInfo.InterfaceType.ToPointer(), cellInfo.InterfaceSlot);
pTargetCode = pfnGetInterfaceImplementation(pObject, cellInfo.InterfaceType, cellInfo.InterfaceSlot);
Diagnostics.Debug.Assert(pTargetCode != IntPtr.Zero);
}
return pTargetCode;
Expand Down
48 changes: 0 additions & 48 deletions src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/EETypePtr.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -386,14 +386,14 @@ public static void ThrowClasslibDivideByZeroException(IntPtr address)
}

[RuntimeExport("RhExceptionHandling_FailedAllocation")]
public static void FailedAllocation(EETypePtr pEEType, bool fIsOverflow)
public static void FailedAllocation(MethodTable* pEEType, bool fIsOverflow)
{
ExceptionIDs exID = fIsOverflow ? ExceptionIDs.Overflow : ExceptionIDs.OutOfMemory;

// Throw the out of memory exception defined by the classlib, using the input MethodTable*
// to find the correct classlib.

throw pEEType.ToPointer()->GetClasslibException(exID);
throw pEEType->GetClasslibException(exID);
}

#if !INPLACE_RUNTIME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ internal enum DispatchCellType
VTableOffset = 0x2,
}

internal struct DispatchCellInfo
internal unsafe struct DispatchCellInfo
{
public DispatchCellType CellType;
public EETypePtr InterfaceType;
public MethodTable* InterfaceType;
public ushort InterfaceSlot;
public byte HasCache;
public uint MetadataToken;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,20 +164,19 @@ private static unsafe bool UnboxAnyTypeCompare(MethodTable* pEEType, MethodTable
}

[RuntimeExport("RhUnboxAny")]
public static unsafe void RhUnboxAny(object? o, ref byte data, EETypePtr pUnboxToEEType)
public static unsafe void RhUnboxAny(object? o, ref byte data, MethodTable* pUnboxToEEType)
{
MethodTable* ptrUnboxToEEType = (MethodTable*)pUnboxToEEType.ToPointer();
if (ptrUnboxToEEType->IsValueType)
if (pUnboxToEEType->IsValueType)
{
bool isValid = false;

if (ptrUnboxToEEType->IsNullable)
if (pUnboxToEEType->IsNullable)
{
isValid = (o == null) || o.GetMethodTable() == ptrUnboxToEEType->NullableType;
isValid = (o == null) || o.GetMethodTable() == pUnboxToEEType->NullableType;
}
else
{
isValid = (o != null) && UnboxAnyTypeCompare(o.GetMethodTable(), ptrUnboxToEEType);
isValid = (o != null) && UnboxAnyTypeCompare(o.GetMethodTable(), pUnboxToEEType);
}

if (!isValid)
Expand All @@ -187,16 +186,16 @@ public static unsafe void RhUnboxAny(object? o, ref byte data, EETypePtr pUnboxT

ExceptionIDs exID = o == null ? ExceptionIDs.NullReference : ExceptionIDs.InvalidCast;

throw ptrUnboxToEEType->GetClasslibException(exID);
throw pUnboxToEEType->GetClasslibException(exID);
}

RhUnbox(o, ref data, ptrUnboxToEEType);
RhUnbox(o, ref data, pUnboxToEEType);
}
else
{
if (o != null && (TypeCast.IsInstanceOfAny(ptrUnboxToEEType, o) == null))
if (o != null && (TypeCast.IsInstanceOfAny(pUnboxToEEType, o) == null))
{
throw ptrUnboxToEEType->GetClasslibException(ExceptionIDs.InvalidCast);
throw pUnboxToEEType->GetClasslibException(ExceptionIDs.InvalidCast);
}

Unsafe.As<byte, object?>(ref data) = o;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe

[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhNewObject")]
internal static extern object RhNewObject(EETypePtr pEEType);
internal static extern unsafe object RhNewObject(MethodTable* pEEType);

// Move memory which may be on the heap which may have object references in it.
// In general, a memcpy on the heap is unsafe, but this is able to perform the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,38 @@
using System.Runtime;
using System.Runtime.CompilerServices;

using Internal.Runtime;
using Internal.Runtime.Augments;

namespace Internal.IntrinsicSupport
{
internal static class ComparerHelpers
{
private static bool ImplementsIComparable(RuntimeTypeHandle t)
private static unsafe bool ImplementsIComparable(RuntimeTypeHandle t)
{
EETypePtr objectType = t.ToEETypePtr();
EETypePtr icomparableType = typeof(IComparable<>).TypeHandle.ToEETypePtr();
int interfaceCount = objectType.Interfaces.Count;
MethodTable* objectType = t.ToMethodTable();
MethodTable* icomparableType = typeof(IComparable<>).TypeHandle.ToMethodTable();
int interfaceCount = objectType->NumInterfaces;
for (int i = 0; i < interfaceCount; i++)
{
EETypePtr interfaceType = objectType.Interfaces[i];
MethodTable* interfaceType = objectType->InterfaceMap[i];

if (!interfaceType.IsGeneric)
if (!interfaceType->IsGeneric)
continue;

if (interfaceType.GenericDefinition == icomparableType)
if (interfaceType->GenericDefinition == icomparableType)
{
var instantiation = interfaceType.Instantiation;
if (instantiation.Length != 1)
if (interfaceType->GenericArity != 1)
continue;

if (objectType.IsValueType)
if (objectType->IsValueType)
{
if (instantiation[0] == objectType)
if (interfaceType->GenericArguments[0] == objectType)
{
return true;
}
}
else if (RuntimeImports.AreTypesAssignable(objectType, instantiation[0]))
else if (RuntimeImports.AreTypesAssignable(objectType, interfaceType->GenericArguments[0]))
{
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,31 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;

using Internal.Runtime;
using Internal.Runtime.Augments;

namespace Internal.IntrinsicSupport
{
internal static class EqualityComparerHelpers
{
private static bool ImplementsIEquatable(RuntimeTypeHandle t)
private static unsafe bool ImplementsIEquatable(RuntimeTypeHandle t)
{
EETypePtr objectType = t.ToEETypePtr();
EETypePtr iequatableType = typeof(IEquatable<>).TypeHandle.ToEETypePtr();
int interfaceCount = objectType.Interfaces.Count;
MethodTable* objectType = t.ToMethodTable();
MethodTable* iequatableType = typeof(IEquatable<>).TypeHandle.ToMethodTable();
int interfaceCount = objectType->NumInterfaces;
for (int i = 0; i < interfaceCount; i++)
{
EETypePtr interfaceType = objectType.Interfaces[i];
MethodTable* interfaceType = objectType->InterfaceMap[i];

if (!interfaceType.IsGeneric)
if (!interfaceType->IsGeneric)
continue;

if (interfaceType.GenericDefinition == iequatableType)
if (interfaceType->GenericDefinition == iequatableType)
{
var instantiation = interfaceType.Instantiation;

if (instantiation.Length != 1)
if (interfaceType->GenericArity != 1)
continue;

if (instantiation[0] == objectType)
if (interfaceType->GenericArguments[0] == objectType)
{
return true;
}
Expand All @@ -47,9 +46,9 @@ private static bool ImplementsIEquatable(RuntimeTypeHandle t)
return false;
}

internal static bool IsEnum(RuntimeTypeHandle t)
internal static unsafe bool IsEnum(RuntimeTypeHandle t)
{
return t.ToEETypePtr().IsEnum;
return t.ToMethodTable()->IsEnum;
}

// this function utilizes the template type loader to generate new
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
using System.Numerics;
using System.Reflection;

using Internal.Runtime;

using EETypeElementType = Internal.Runtime.EETypeElementType;

namespace Internal.Reflection.Augments
Expand All @@ -39,24 +41,24 @@ public static void Initialize(ReflectionCoreCallbacks reflectionCoreCallbacks)
s_reflectionCoreCallbacks = reflectionCoreCallbacks;
}

internal static TypeCode GetRuntimeTypeCode(RuntimeType type)
internal static unsafe TypeCode GetRuntimeTypeCode(RuntimeType type)
{
Debug.Assert(type != null);

EETypePtr eeType = type.ToEETypePtrMayBeNull();
if (eeType.IsNull)
MethodTable* eeType = type.ToMethodTableMayBeNull();
if (eeType == null)
{
// Type exists in metadata only. Aside from the enums, there is no chance a type with a TypeCode would not have an MethodTable,
// so if it's not an enum, return the default.
if (!type.IsActualEnum)
return TypeCode.Object;
Type underlyingType = Enum.GetUnderlyingType(type);
eeType = underlyingType.TypeHandle.ToEETypePtr();
eeType = underlyingType.TypeHandle.ToMethodTable();
}

// Note: Type.GetTypeCode() is expected to return the underlying type's TypeCode for enums. EETypePtr.CorElementType does the same,
// so this one switch handles both cases.
EETypeElementType rhType = eeType.ElementType;
EETypeElementType rhType = eeType->ElementType;
switch (rhType)
{
case EETypeElementType.Boolean: return TypeCode.Boolean;
Expand Down
Loading

0 comments on commit 7a6c786

Please sign in to comment.