Added caching for Type.__ContainsMissingType property to simplify the prevention of infinite recursion while evaluating generic parameter constraints.

This commit is contained in:
jfrijters 2012-12-23 10:48:25 +00:00
Родитель d7517acd1a
Коммит fdcf287e2e
2 изменённых файлов: 30 добавлений и 46 удалений

Просмотреть файл

@ -88,58 +88,20 @@ namespace IKVM.Reflection.Reader
get { return true; }
}
public sealed override bool __ContainsMissingType
protected sealed override bool ContainsMissingTypeImpl
{
get
{
bool freeList = false;
try
foreach (Type type in GetGenericParameterConstraints())
{
foreach (Type type in GetGenericParameterConstraints())
if (type.__ContainsMissingType)
{
if (type.__IsMissing)
{
return true;
}
else if (type.IsConstructedGenericType || type.HasElementType || type.__IsFunctionPointer)
{
// if a constructed type contains generic parameters,
// it might contain this type parameter again and
// to prevent infinite recurssion, we keep a thread local
// list of type parameters we've already processed
if (type.ContainsGenericParameters)
{
if (containsMissingTypeHack == null)
{
freeList = true;
containsMissingTypeHack = new List<Type>();
}
else if (containsMissingTypeHack.Contains(this))
{
return false;
}
containsMissingTypeHack.Add(this);
}
if (type.__ContainsMissingType)
{
return true;
}
}
}
return false;
}
finally
{
if (freeList)
{
containsMissingTypeHack = null;
return true;
}
}
return false;
}
}
[ThreadStatic]
private static List<Type> containsMissingTypeHack;
}
sealed class UnboundGenericMethodParameter : TypeParameterType

Просмотреть файл

@ -67,6 +67,13 @@ namespace IKVM.Reflection
// for use by TypeDefImpl
NotGenericTypeDefinition = 128,
// used to cache __ContainsMissingType
ContainsMissingType_Unknown = 0,
ContainsMissingType_Pending = 256,
ContainsMissingType_Yes = 512,
ContainsMissingType_No = 1024,
ContainsMissingType_Mask = 256 | 512 | 1024,
}
// prevent subclassing by outsiders
@ -1342,7 +1349,22 @@ namespace IKVM.Reflection
get { return this.DeclaringType != null; }
}
public virtual bool __ContainsMissingType
public bool __ContainsMissingType
{
get
{
if ((typeFlags & TypeFlags.ContainsMissingType_Mask) == TypeFlags.ContainsMissingType_Unknown)
{
// Generic parameter constraints can refer back to the type parameter they are part of,
// so to prevent infinite recursion, we set the Pending flag during computation.
typeFlags |= TypeFlags.ContainsMissingType_Pending;
typeFlags = (typeFlags & ~TypeFlags.ContainsMissingType_Mask) | (ContainsMissingTypeImpl ? TypeFlags.ContainsMissingType_Yes : TypeFlags.ContainsMissingType_No);
}
return (typeFlags & TypeFlags.ContainsMissingType_Mask) == TypeFlags.ContainsMissingType_Yes;
}
}
protected virtual bool ContainsMissingTypeImpl
{
get
{
@ -2136,7 +2158,7 @@ namespace IKVM.Reflection
}
}
public sealed override bool __ContainsMissingType
protected sealed override bool ContainsMissingTypeImpl
{
get
{
@ -2898,7 +2920,7 @@ namespace IKVM.Reflection
}
}
public override bool __ContainsMissingType
protected override bool ContainsMissingTypeImpl
{
get
{