зеркало из https://github.com/mono/ikvm-fork.git
Added caching for Type.__ContainsMissingType property to simplify the prevention of infinite recursion while evaluating generic parameter constraints.
This commit is contained in:
Родитель
d7517acd1a
Коммит
fdcf287e2e
|
@ -88,59 +88,21 @@ 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())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[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
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче