|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using Internal.Reflection.Augments;
using Internal.Runtime;
using Internal.Runtime.Augments;
using Internal.Runtime.CompilerServices;
namespace System
{
public abstract partial class Type : MemberInfo, IReflect
{
[Intrinsic]
public static unsafe Type? GetTypeFromHandle(RuntimeTypeHandle handle) => handle.IsNull ? null : GetTypeFromMethodTable(handle.ToMethodTable());
// Implementation of CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL
internal static unsafe RuntimeType? GetTypeFromMethodTableMaybeNull(MethodTable* pMT) => (pMT == null) ? null : GetTypeFromMethodTable(pMT);
// Implementation of CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, CORINFO_HELP_GETSYNCFROMCLASSHANDLE
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe RuntimeType GetTypeFromMethodTable(MethodTable* pMT)
{
ref RuntimeType? type = ref Unsafe.AsRef<RuntimeType?>(pMT->WritableData);
return type ?? GetTypeFromMethodTableSlow(pMT);
}
private static class AllocationLock
{
public static Lock Instance =>
field ?? Interlocked.CompareExchange(ref field, new Lock(useTrivialWaits: true), null) ?? field;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe RuntimeType GetTypeFromMethodTableSlow(MethodTable* pMT)
{
// Allocate and set the RuntimeType under a lock - there's no way to free it if there is a race.
lock (AllocationLock.Instance)
{
ref RuntimeType? runtimeTypeCache = ref Unsafe.AsRef<RuntimeType?>(pMT->WritableData);
if (runtimeTypeCache != null)
return runtimeTypeCache;
RuntimeType? type = FrozenObjectHeapManager.Instance.TryAllocateObject<RuntimeType>();
if (type == null)
throw new OutOfMemoryException();
type.DangerousSetUnderlyingEEType(pMT);
runtimeTypeCache = type;
return type;
}
}
[Intrinsic]
[RequiresUnreferencedCode("The type might be removed")]
public static Type GetType(string typeName) => GetType(typeName, throwOnError: false, ignoreCase: false);
[Intrinsic]
[RequiresUnreferencedCode("The type might be removed")]
public static Type GetType(string typeName, bool throwOnError) => GetType(typeName, throwOnError: throwOnError, ignoreCase: false);
[Intrinsic]
[RequiresUnreferencedCode("The type might be removed")]
public static Type GetType(string typeName, bool throwOnError, bool ignoreCase)
{
return TypeNameResolver.GetType(typeName, throwOnError: throwOnError, ignoreCase: ignoreCase);
}
[Intrinsic]
[RequiresUnreferencedCode("The type might be removed")]
public static Type GetType(string typeName, Func<AssemblyName, Assembly?>? assemblyResolver, Func<Assembly?, string, bool, Type?>? typeResolver) => GetType(typeName, assemblyResolver, typeResolver, throwOnError: false, ignoreCase: false);
[Intrinsic]
[RequiresUnreferencedCode("The type might be removed")]
public static Type GetType(string typeName, Func<AssemblyName, Assembly?>? assemblyResolver, Func<Assembly?, string, bool, Type?>? typeResolver, bool throwOnError) => GetType(typeName, assemblyResolver, typeResolver, throwOnError: throwOnError, ignoreCase: false);
[Intrinsic]
[RequiresUnreferencedCode("The type might be removed")]
public static Type GetType(string typeName, Func<AssemblyName, Assembly?>? assemblyResolver, Func<Assembly?, string, bool, Type?>? typeResolver, bool throwOnError, bool ignoreCase)
{
return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, throwOnError: throwOnError, ignoreCase: ignoreCase);
}
}
}
|