Skip to content

Commit

Permalink
[NativeAOT] Miscellaneous cleanup (#93446)
Browse files Browse the repository at this point in the history
* [NativeAOT] Miscellaneous cleanup

- Delete unnecessary abstractions
- Simplify ifdefs
- Use more derived types

* Apply suggestions from code review

Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
  • Loading branch information
jkotas and MichalStrehovsky authored Oct 14, 2023
1 parent d7c8198 commit 765798c
Show file tree
Hide file tree
Showing 19 changed files with 80 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,29 @@ namespace Internal.Runtime
// Extensions to MethodTable that are specific to the use in Runtime.Base.
internal unsafe partial struct MethodTable
{
#pragma warning disable CA1822
#if !INPLACE_RUNTIME
internal MethodTable* GetArrayEEType()
{
#if INPLACE_RUNTIME
return MethodTable.Of<Array>();
#else
MethodTable* pThis = (MethodTable*)Unsafe.Pointer(ref this);
void* pGetArrayEEType = InternalCalls.RhpGetClasslibFunctionFromEEType(pThis, ClassLibFunctionId.GetSystemArrayEEType);
return ((delegate* <MethodTable*>)pGetArrayEEType)();
#endif
}

internal Exception GetClasslibException(ExceptionIDs id)
{
#if INPLACE_RUNTIME
return RuntimeExceptionHelpers.GetRuntimeException(id);
#else
if (IsParameterizedType)
{
return RelatedParameterType->GetClasslibException(id);
}

return EH.GetClasslibExceptionFromEEType(id, (MethodTable*)Unsafe.AsPointer(ref this));
#endif
}
#pragma warning restore CA1822
#endif

internal IntPtr GetClasslibFunction(ClassLibFunctionId id)
{
return (IntPtr)InternalCalls.RhpGetClasslibFunctionFromEEType((MethodTable*)Unsafe.AsPointer(ref this), id);
}

internal static bool AreSameType(MethodTable* mt1, MethodTable* mt2)
{
return mt1 == mt2;
}
}

internal static class WellKnownEETypes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,27 +117,27 @@ public Type GetNamedTypeForHandle(RuntimeTypeHandle typeHandle)

public Type GetArrayTypeForHandle(RuntimeTypeHandle typeHandle)
{
RuntimeTypeHandle elementTypeHandle = ExecutionEnvironment.GetArrayTypeElementType(typeHandle);
RuntimeTypeHandle elementTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(typeHandle);
return elementTypeHandle.GetTypeForRuntimeTypeHandle().GetArrayType(typeHandle);
}

public Type GetMdArrayTypeForHandle(RuntimeTypeHandle typeHandle, int rank)
{
RuntimeTypeHandle elementTypeHandle = ExecutionEnvironment.GetArrayTypeElementType(typeHandle);
RuntimeTypeHandle elementTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(typeHandle);
return elementTypeHandle.GetTypeForRuntimeTypeHandle().GetMultiDimArrayType(rank, typeHandle);
}

public Type GetPointerTypeForHandle(RuntimeTypeHandle typeHandle)
{
RuntimeTypeHandle targetTypeHandle = ExecutionEnvironment.GetPointerTypeTargetType(typeHandle);
RuntimeTypeHandle targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(typeHandle);
return targetTypeHandle.GetTypeForRuntimeTypeHandle().GetPointerType(typeHandle);
}

public Type GetFunctionPointerTypeForHandle(RuntimeTypeHandle typeHandle)
{
ExecutionEnvironment.GetFunctionPointerTypeComponents(typeHandle, out RuntimeTypeHandle returnTypeHandle,
out RuntimeTypeHandle[] parameterHandles,
out bool isUnmanaged);
RuntimeTypeHandle returnTypeHandle = RuntimeAugments.GetFunctionPointerReturnType(typeHandle);
RuntimeTypeHandle[] parameterHandles = RuntimeAugments.GetFunctionPointerParameterTypes(typeHandle);
bool isUnmanaged = RuntimeAugments.IsUnmanagedFunctionPointerType(typeHandle);

RuntimeTypeInfo returnType = returnTypeHandle.GetTypeForRuntimeTypeHandle();
int count = parameterHandles.Length;
Expand All @@ -152,7 +152,7 @@ public Type GetFunctionPointerTypeForHandle(RuntimeTypeHandle typeHandle)

public Type GetByRefTypeForHandle(RuntimeTypeHandle typeHandle)
{
RuntimeTypeHandle targetTypeHandle = ExecutionEnvironment.GetByRefTypeTargetType(typeHandle);
RuntimeTypeHandle targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(typeHandle);
return targetTypeHandle.GetTypeForRuntimeTypeHandle().GetByRefType(typeHandle);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,14 @@ public abstract class ExecutionEnvironment
public abstract bool TryGetNamedTypeForMetadata(QTypeDefinition qTypeDefinition, out RuntimeTypeHandle runtimeTypeHandle);

public abstract bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, out RuntimeTypeHandle arrayTypeHandle);
public abstract RuntimeTypeHandle GetArrayTypeElementType(RuntimeTypeHandle arrayTypeHandle);

public abstract bool TryGetMultiDimArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, int rank, out RuntimeTypeHandle arrayTypeHandle);

public abstract bool TryGetFunctionPointerTypeForComponents(RuntimeTypeHandle returnTypeHandle, RuntimeTypeHandle[] parameterHandles, bool isUnmanaged, out RuntimeTypeHandle functionPointerTypeHandle);
public abstract void GetFunctionPointerTypeComponents(RuntimeTypeHandle functionPointerHandle, out RuntimeTypeHandle returnTypeHandle, out RuntimeTypeHandle[] parameterHandles, out bool isUnmanaged);

public abstract bool TryGetPointerTypeForTargetType(RuntimeTypeHandle targetTypeHandle, out RuntimeTypeHandle pointerTypeHandle);
public abstract RuntimeTypeHandle GetPointerTypeTargetType(RuntimeTypeHandle pointerTypeHandle);

public abstract bool TryGetByRefTypeForTargetType(RuntimeTypeHandle targetTypeHandle, out RuntimeTypeHandle byRefTypeHandle);
public abstract RuntimeTypeHandle GetByRefTypeTargetType(RuntimeTypeHandle byRefTypeHandle);

public abstract bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle);
public abstract bool TryGetConstructedGenericTypeForComponentsNoConstraintCheck(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;

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

namespace Internal.Reflection.Core.NonPortable
Expand Down Expand Up @@ -42,12 +43,12 @@ internal static partial class RuntimeTypeUnifier
//
// Retrieves the unified Type object for given RuntimeTypeHandle (this is basically the Type.GetTypeFromHandle() api without the input validation.)
//
internal static Type GetRuntimeTypeForEEType(EETypePtr eeType)
internal static unsafe RuntimeType GetRuntimeTypeForMethodTable(MethodTable* eeType)
{
// If writable data is supported, we shouldn't be using the hashtable - the runtime type
// is accessible through a couple indirections from the EETypePtr which is much faster.
// is accessible through a couple indirections from the MethodTable which is much faster.
Debug.Assert(!Internal.Runtime.MethodTable.SupportsWritableData);
return RuntimeTypeHandleToTypeCache.Table.GetOrAdd(eeType.RawValue);
return RuntimeTypeHandleToTypeCache.Table.GetOrAdd((IntPtr)eeType);
}

//
Expand All @@ -59,14 +60,14 @@ internal static Type GetRuntimeTypeForEEType(EETypePtr eeType)
// does a second lookup in the true unifying tables rather than creating the Type itself.
// Thus, the one-to-one relationship between Type reference identity and Type semantic identity is preserved.
//
private sealed class RuntimeTypeHandleToTypeCache : ConcurrentUnifierW<IntPtr, Type>
private sealed class RuntimeTypeHandleToTypeCache : ConcurrentUnifierW<IntPtr, RuntimeType>
{
private RuntimeTypeHandleToTypeCache() { }

protected sealed override Type Factory(IntPtr rawRuntimeTypeHandleKey)
protected sealed override RuntimeType Factory(IntPtr rawRuntimeTypeHandleKey)
{
EETypePtr eeType = new EETypePtr(rawRuntimeTypeHandleKey);
return GetRuntimeTypeBypassCache(eeType);
return (RuntimeType)GetRuntimeTypeBypassCache(eeType);
}

public static readonly RuntimeTypeHandleToTypeCache Table = new RuntimeTypeHandleToTypeCache();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ public static bool IsFunctionPointerType(RuntimeTypeHandle typeHandle)

public static unsafe RuntimeTypeHandle GetFunctionPointerReturnType(RuntimeTypeHandle typeHandle)
{
return new RuntimeTypeHandle(new EETypePtr(typeHandle.ToMethodTable()->FunctionPointerReturnType));
return new RuntimeTypeHandle(typeHandle.ToMethodTable()->FunctionPointerReturnType);
}

public static unsafe int GetFunctionPointerParameterCount(RuntimeTypeHandle typeHandle)
Expand All @@ -613,7 +613,7 @@ public static unsafe int GetFunctionPointerParameterCount(RuntimeTypeHandle type
public static unsafe RuntimeTypeHandle GetFunctionPointerParameterType(RuntimeTypeHandle typeHandle, int argumentIndex)
{
Debug.Assert(argumentIndex < GetFunctionPointerParameterCount(typeHandle));
return new RuntimeTypeHandle(new EETypePtr(typeHandle.ToMethodTable()->FunctionPointerParameters[argumentIndex]));
return new RuntimeTypeHandle(typeHandle.ToMethodTable()->FunctionPointerParameters[argumentIndex]);
}

public static unsafe RuntimeTypeHandle[] GetFunctionPointerParameterTypes(RuntimeTypeHandle typeHandle)
Expand All @@ -626,7 +626,7 @@ public static unsafe RuntimeTypeHandle[] GetFunctionPointerParameterTypes(Runtim
MethodTableList parameters = typeHandle.ToMethodTable()->FunctionPointerParameters;
for (int i = 0; i < result.Length; i++)
{
result[i] = new RuntimeTypeHandle(new EETypePtr(parameters[i]));
result[i] = new RuntimeTypeHandle(parameters[i]);
}

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private static unsafe RuntimeFieldHandle GetRuntimeFieldHandle(IntPtr pHandleSig
return returnValue;
}

private static unsafe Type GetRuntimeType(MethodTable* pMT)
private static unsafe RuntimeType GetRuntimeType(MethodTable* pMT)
{
return Type.GetTypeFromMethodTable(pMT);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ private static unsafe void MonitorExitStatic(MethodTable* pMT, ref bool lockTake
lockTaken = false;
}

private static unsafe Type GetStaticLockObject(MethodTable* pMT)
private static unsafe RuntimeType GetStaticLockObject(MethodTable* pMT)
{
return Type.GetTypeFromMethodTable(pMT);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ static unsafe class IDynamicCastableSupport
[RuntimeExport("IDynamicCastableIsInterfaceImplemented")]
internal static bool IDynamicCastableIsInterfaceImplemented(IDynamicInterfaceCastable instance, MethodTable* interfaceType, bool throwIfNotImplemented)
{
return instance.IsInterfaceImplemented(new RuntimeTypeHandle(new EETypePtr(interfaceType)), throwIfNotImplemented);
return instance.IsInterfaceImplemented(new RuntimeTypeHandle(interfaceType), throwIfNotImplemented);
}

[RuntimeExport("IDynamicCastableGetInterfaceImplementation")]
internal static IntPtr IDynamicCastableGetInterfaceImplementation(IDynamicInterfaceCastable instance, MethodTable* interfaceType, ushort slot)
{
RuntimeTypeHandle handle = instance.GetInterfaceImplementation(new RuntimeTypeHandle(new EETypePtr(interfaceType)));
RuntimeTypeHandle handle = instance.GetInterfaceImplementation(new RuntimeTypeHandle(interfaceType));
MethodTable* implType = handle.ToMethodTable();
if (implType == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,43 @@ namespace Internal.Runtime
// Extensions to MethodTable that are specific to the use in the CoreLib.
internal unsafe partial struct MethodTable
{
#if !INPLACE_RUNTIME
internal static MethodTable* GetArrayEEType()
#pragma warning disable CA1822
internal MethodTable* GetArrayEEType()
{

return MethodTable.Of<Array>();
}

internal Exception GetClasslibException(ExceptionIDs id)
{
return RuntimeExceptionHelpers.GetRuntimeException(id);
}
#pragma warning restore CA1822

internal static bool AreSameType(MethodTable* mt1, MethodTable* mt2)
{
return mt1 == mt2;
}
#endif

internal bool IsEnum
{
get
{
// Q: When is an enum type a constructed generic type?
// A: When it's nested inside a generic type.

// Generic type definitions that return true for IsPrimitive are type definitions of generic enums.
// Otherwise check the base type.
return IsPrimitive && (IsGenericTypeDefinition || NonArrayBaseType == MethodTable.Of<Enum>());
}
}

// Returns true for actual primitives only, returns false for enums
internal bool IsActualPrimitive
{
get
{
return IsPrimitive && NonArrayBaseType == MethodTable.Of<ValueType>();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -156,20 +156,11 @@ internal bool IsPrimitive
}
}

// WARNING: Never call unless the MethodTable came from an instanced object. Nested enums can be open generics (typeof(Outer<>).NestedEnum)
// and this helper has undefined behavior when passed such as a enum.
internal bool IsEnum
{
get
{
// Q: When is an enum type a constructed generic type?
// A: When it's nested inside a generic type.
if (!IsDefType)
return false;

// Generic type definitions that return true for IsPrimitive are type definitions of generic enums.
// Otherwise check the base type.
return (IsGenericTypeDefinition && IsPrimitive) || this.BaseType == EETypePtr.EETypePtrOf<Enum>();
return _value->IsEnum;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ internal sealed unsafe class ManagedObjectWrapperHolder
static ManagedObjectWrapperHolder()
{
delegate* unmanaged<IntPtr, bool> callback = &IsRootedCallback;
if (!RuntimeImports.RhRegisterRefCountedHandleCallback((nint)callback, typeof(ManagedObjectWrapperHolder).GetEEType()))
if (!RuntimeImports.RhRegisterRefCountedHandleCallback((nint)callback, EETypePtr.EETypePtrOf<ManagedObjectWrapperHolder>()))
{
throw new OutOfMemoryException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private UnsafeGCHandle(object value, GCHandleType type)
_handle = RuntimeImports.RhHandleAlloc(value, type);
}

public static UnsafeGCHandle Alloc(object value, GCHandleType type)
public static UnsafeGCHandle Alloc(object value, GCHandleType type = GCHandleType.Normal)
{
return new UnsafeGCHandle(value, type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,10 +391,10 @@ internal static unsafe bool AreTypesAssignable(EETypePtr pSourceType, EETypePtr

[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhTypeCast_IsInstanceOfAny")]
private static extern unsafe object IsInstanceOfAny(MethodTable* pTargetType, object obj);
internal static extern unsafe object IsInstanceOf(MethodTable* pTargetType, object obj);

internal static unsafe object IsInstanceOf(EETypePtr pTargetType, object obj)
=> IsInstanceOfAny(pTargetType.ToPointer(), obj);
=> IsInstanceOf(pTargetType.ToPointer(), obj);

//
// calls to runtime for allocation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ public unsafe struct RuntimeTypeHandle : IEquatable<RuntimeTypeHandle>, ISeriali
{
private IntPtr _value;

internal unsafe RuntimeTypeHandle(MethodTable* pEEType)
=> _value = (IntPtr)pEEType;

internal RuntimeTypeHandle(EETypePtr pEEType)
: this(pEEType.RawValue)
{
}
=> _value = pEEType.RawValue;

private RuntimeTypeHandle(IntPtr value)
{
_value = value;
}
=> _value = value;

public override bool Equals(object? obj)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ public abstract partial class Type : MemberInfo, IReflect
public static unsafe Type? GetTypeFromHandle(RuntimeTypeHandle handle) => handle.IsNull ? null : GetTypeFromMethodTable(handle.ToMethodTable());

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe Type GetTypeFromMethodTable(MethodTable* pMT)
internal static unsafe RuntimeType GetTypeFromMethodTable(MethodTable* pMT)
{
// If we support the writable data section on MethodTables, the runtime type associated with the MethodTable
// is cached there. If writable data is not supported, we need to do a lookup in the runtime type
// unifier's hash table.
if (MethodTable.SupportsWritableData)
{
ref GCHandle handle = ref Unsafe.AsRef<GCHandle>(pMT->WritableData);
ref UnsafeGCHandle handle = ref Unsafe.AsRef<UnsafeGCHandle>(pMT->WritableData);
if (handle.IsAllocated)
{
return Unsafe.As<Type>(handle.Target);
return Unsafe.As<RuntimeType>(handle.Target);
}
else
{
Expand All @@ -42,26 +42,26 @@ internal static unsafe Type GetTypeFromMethodTable(MethodTable* pMT)
}
else
{
return RuntimeTypeUnifier.GetRuntimeTypeForEEType(new EETypePtr(pMT));
return RuntimeTypeUnifier.GetRuntimeTypeForMethodTable(pMT);
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe Type GetTypeFromMethodTableSlow(MethodTable* pMT, ref GCHandle handle)
private static unsafe RuntimeType GetTypeFromMethodTableSlow(MethodTable* pMT, ref UnsafeGCHandle handle)
{
// Note: this is bypassing the "fast" unifier cache (based on a simple IntPtr
// identity of MethodTable pointers). There is another unifier behind that cache
// that ensures this code is race-free.
Type result = RuntimeTypeUnifier.GetRuntimeTypeBypassCache(new EETypePtr(pMT));
GCHandle tempHandle = GCHandle.Alloc(result);
UnsafeGCHandle tempHandle = UnsafeGCHandle.Alloc(result);

// We don't want to leak a handle if there's a race
if (Interlocked.CompareExchange(ref Unsafe.As<GCHandle, IntPtr>(ref handle), (IntPtr)tempHandle, default) != default)
if (Interlocked.CompareExchange(ref Unsafe.As<UnsafeGCHandle, IntPtr>(ref handle), Unsafe.As<UnsafeGCHandle, IntPtr>(ref tempHandle), default) != default)
{
tempHandle.Free();
}

return result;
return Unsafe.As<RuntimeType>(handle.Target);
}

internal EETypePtr GetEEType()
Expand Down
Loading

0 comments on commit 765798c

Please sign in to comment.