Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Prev Previous commit
Next Next commit
Use seperate cache field for the type definition
There is a risk of activator cache and generic type definition cache colliding
  • Loading branch information
jkotas committed Nov 20, 2022
commit 05afc329b61ce517d263997a77a36a579a194eaa
19 changes: 1 addition & 18 deletions src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -682,24 +682,7 @@ internal RuntimeType MakePointer()
internal static partial Interop.BOOL IsCollectible(QCallTypeHandle handle);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_GetGenericTypeDefinition")]
private static partial void GetGenericTypeDefinition(QCallTypeHandle type, ObjectHandleOnStack retType);

internal static RuntimeType GetGenericTypeDefinition(RuntimeType type)
{
Debug.Assert(type.IsGenericType);

return type.IsGenericTypeDefinition ? type :
type.GenericCache is RuntimeType genericDefinition ? genericDefinition : CacheGenericDefinition(type);

[MethodImpl(MethodImplOptions.NoInlining)]
static RuntimeType CacheGenericDefinition(RuntimeType type)
{
RuntimeType genericDefinition = null!;
GetGenericTypeDefinition(new QCallTypeHandle(ref type), ObjectHandleOnStack.Create(ref genericDefinition));
type.GenericCache = genericDefinition;
return genericDefinition;
}
}
internal static partial void GetGenericTypeDefinition(QCallTypeHandle type, ObjectHandleOnStack retType);

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool IsGenericVariable(RuntimeType type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1492,9 +1492,9 @@ internal T[] GetMemberList(MemberListType listType, string? name, CacheType cach
// - Enum names and values (EnumInfo)
// - Activator.CreateInstance (ActivatorCache)
// - Array.Initialize (ArrayInitializeCache)
// - RuntimeType.GetGenericTypeDefinition (RuntimeType)
private object? m_genericCache;
private object[]? _emptyArray; // Object array cache for Attribute.GetCustomAttributes() pathological no-result case.
private RuntimeType? _genericTypeDefinition;
#endregion

#region Constructor
Expand Down Expand Up @@ -1648,6 +1648,29 @@ internal TypeCode TypeCode
}

internal object[] GetEmptyArray() => _emptyArray ??= (object[])Array.CreateInstance(m_runtimeType, 0);

internal RuntimeType GetGenericTypeDefinition()
{
Debug.Assert(m_runtimeType.IsGenericType);

return _genericTypeDefinition ?? CacheGenericDefinition();

[MethodImpl(MethodImplOptions.NoInlining)]
RuntimeType CacheGenericDefinition()
{
RuntimeType genericDefinition = null!;
if (m_runtimeType.IsGenericTypeDefinition)
{
genericDefinition = m_runtimeType;
}
else
{
RuntimeType type = m_runtimeType;
RuntimeTypeHandle.GetGenericTypeDefinition(new QCallTypeHandle(ref type), ObjectHandleOnStack.Create(ref genericDefinition));
}
return _genericTypeDefinition = genericDefinition;
}
}
#endregion

#region Caches Accessors
Expand Down Expand Up @@ -3454,6 +3477,14 @@ public override unsafe bool IsGenericTypeDefinition
}
}

public override Type GetGenericTypeDefinition()
{
if (!IsGenericType)
throw new InvalidOperationException(SR.InvalidOperation_NotGenericType);

return Cache.GetGenericTypeDefinition();
}

public override GenericParameterAttributes GenericParameterAttributes
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,14 +245,6 @@ public override Type GetEnumUnderlyingType()
return Enum.InternalGetUnderlyingType(this);
}

public override Type GetGenericTypeDefinition()
{
if (!IsGenericType)
throw new InvalidOperationException(SR.InvalidOperation_NotGenericType);

return RuntimeTypeHandle.GetGenericTypeDefinition(this);
}

public override int GetHashCode() => RuntimeHelpers.GetHashCode(this);

internal RuntimeModule GetRuntimeModule() => RuntimeTypeHandle.GetModule(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,14 @@ protected override bool IsValueTypeImpl()
public override bool IsGenericType => RuntimeTypeHandle.HasInstantiation(this);
public override bool IsGenericTypeDefinition => RuntimeTypeHandle.IsGenericTypeDefinition(this);

public override Type GetGenericTypeDefinition()
{
if (!IsGenericType)
throw new InvalidOperationException(SR.InvalidOperation_NotGenericType);

return RuntimeTypeHandle.GetGenericTypeDefinition(this);
}

public override GenericParameterAttributes GenericParameterAttributes
{
get
Expand Down