Skip to content

Commit d1691e1

Browse files
authored
[MONO] Partially revert "Add TypeName APIs to simplify metadata lookup" (#118761)
Mono specific changes in #111598 regressed Mono runtime performance significantly. Reverting the changes for now. Fixes #112763
1 parent 9068296 commit d1691e1

File tree

4 files changed

+47
-46
lines changed

4 files changed

+47
-46
lines changed

src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Type/TypeTests.cs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,29 @@ public void GetTypeByName_ValidType_ReturnsExpected(string typeName, Type expect
509509
Assert.Equal(expectedType, Type.GetType(typeName.ToLower(), throwOnError: false, ignoreCase: true));
510510
}
511511

512+
public static IEnumerable<object[]> GetTypeByName_InvalidElementType()
513+
{
514+
Type expectedException = PlatformDetection.IsMonoRuntime
515+
? typeof(ArgumentException) // https://github.com/dotnet/runtime/issues/45033
516+
: typeof(TypeLoadException);
517+
518+
yield return new object[] { "System.Int32&&", expectedException, true };
519+
yield return new object[] { "System.Int32&*", expectedException, true };
520+
yield return new object[] { "System.Int32&[]", expectedException, true };
521+
yield return new object[] { "System.Int32&[*]", expectedException, true };
522+
yield return new object[] { "System.Int32&[,]", expectedException, true };
523+
524+
// https://github.com/dotnet/runtime/issues/45033
525+
if (!PlatformDetection.IsMonoRuntime)
526+
{
527+
yield return new object[] { "..Outside`1", expectedException, false };
528+
yield return new object[] { ".Outside`1+.Inside`1", expectedException, false };
529+
530+
yield return new object[] { "System.Void[]", expectedException, true };
531+
yield return new object[] { "System.TypedReference[]", expectedException, true };
532+
}
533+
}
534+
512535
[Theory]
513536
[InlineData("system.nullable`1[system.int32]", typeof(TypeLoadException), false)]
514537
[InlineData("System.NonExistingType", typeof(TypeLoadException), false)]
@@ -517,15 +540,7 @@ public void GetTypeByName_ValidType_ReturnsExpected(string typeName, Type expect
517540
[InlineData("Outside`2", typeof(TypeLoadException), false)]
518541
[InlineData("Outside`1[System.Boolean, System.Int32]", typeof(ArgumentException), true)]
519542
[InlineData(".System.Int32", typeof(TypeLoadException), false)]
520-
[InlineData("..Outside`1", typeof(TypeLoadException), false)]
521-
[InlineData(".Outside`1+.Inside`1", typeof(TypeLoadException), false)]
522-
[InlineData("System.Int32&&", typeof(TypeLoadException), true)]
523-
[InlineData("System.Int32&*", typeof(TypeLoadException), true)]
524-
[InlineData("System.Int32&[]", typeof(TypeLoadException), true)]
525-
[InlineData("System.Int32&[*]", typeof(TypeLoadException), true)]
526-
[InlineData("System.Int32&[,]", typeof(TypeLoadException), true)]
527-
[InlineData("System.Void[]", typeof(TypeLoadException), true)]
528-
[InlineData("System.TypedReference[]", typeof(TypeLoadException), true)]
543+
[MemberData(nameof(GetTypeByName_InvalidElementType))]
529544
public void GetTypeByName_Invalid(string typeName, Type expectedException, bool alwaysThrowsException)
530545
{
531546
if (!alwaysThrowsException)

src/mono/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.Mono.cs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ internal unsafe ref partial struct TypeNameResolver
1818
private Func<Assembly?, string, bool, Type?>? _typeResolver;
1919
private bool _throwOnError;
2020
private bool _ignoreCase;
21-
private bool _extensibleParser;
2221
private ref StackCrawlMark _stackMark;
2322

2423
[RequiresUnreferencedCode("The type might be removed")]
@@ -28,7 +27,6 @@ internal unsafe ref partial struct TypeNameResolver
2827
Func<Assembly?, string, bool, Type?>? typeResolver,
2928
bool throwOnError,
3029
bool ignoreCase,
31-
bool extensibleParser,
3230
ref StackCrawlMark stackMark)
3331
{
3432
ArgumentNullException.ThrowIfNull(typeName);
@@ -54,7 +52,6 @@ internal unsafe ref partial struct TypeNameResolver
5452
_typeResolver = typeResolver,
5553
_throwOnError = throwOnError,
5654
_ignoreCase = ignoreCase,
57-
_extensibleParser = extensibleParser,
5855
_stackMark = ref stackMark
5956
}.Resolve(parsed);
6057
}
@@ -144,16 +141,7 @@ internal unsafe ref partial struct TypeNameResolver
144141
if (_ignoreCase)
145142
bindingFlags |= BindingFlags.IgnoreCase;
146143

147-
if (type is RuntimeType rt)
148-
{
149-
// Compat: Non-extensible parser allows ambiguous matches with ignore case lookup
150-
bool ignoreAmbiguousMatch = !_extensibleParser && _ignoreCase;
151-
type = rt.GetNestedType(nestedTypeNames[i], bindingFlags, ignoreAmbiguousMatch);
152-
}
153-
else
154-
{
155-
type = type.GetNestedType(nestedTypeNames[i], bindingFlags);
156-
}
144+
type = type.GetNestedType(nestedTypeNames[i], bindingFlags);
157145

158146
if (type is null)
159147
{

src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -679,17 +679,21 @@ private ListBuilder<FieldInfo> GetFieldCandidates(string? name, BindingFlags bin
679679
return candidates;
680680
}
681681

682-
private ListBuilder<Type> GetNestedTypeCandidates(string? name, BindingFlags bindingAttr, bool allowPrefixLookup)
682+
private ListBuilder<Type> GetNestedTypeCandidates(string? fullname, BindingFlags bindingAttr, bool allowPrefixLookup)
683683
{
684+
bool prefixLookup;
684685
bindingAttr &= ~BindingFlags.Static;
685-
FilterHelper(bindingAttr, ref name, allowPrefixLookup, out bool prefixLookup, out _, out MemberListType listType);
686+
string? name, ns;
687+
MemberListType listType;
688+
SplitName(fullname, out name, out ns);
689+
FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out _, out listType);
686690

687691
RuntimeType[] cache = GetNestedTypes_internal(name, bindingAttr, listType);
688692
ListBuilder<Type> candidates = new ListBuilder<Type>(cache.Length);
689693
for (int i = 0; i < cache.Length; i++)
690694
{
691695
RuntimeType nestedClass = cache[i];
692-
if (FilterApplyType(nestedClass, bindingAttr, name, prefixLookup, null))
696+
if (FilterApplyType(nestedClass, bindingAttr, name, prefixLookup, ns))
693697
{
694698
candidates.Add(nestedClass);
695699
}
@@ -1000,39 +1004,33 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
10001004
}
10011005

10021006
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
1003-
internal Type? GetNestedType([MaybeNull] string name, BindingFlags bindingAttr, bool ignoreAmbiguousMatch)
1007+
public override Type? GetNestedType(string fullname, BindingFlags bindingAttr)
10041008
{
1005-
ArgumentNullException.ThrowIfNull(name);
1009+
ArgumentNullException.ThrowIfNull(fullname);
10061010

10071011
bindingAttr &= ~BindingFlags.Static;
1008-
FilterHelper(bindingAttr, ref name, out _, out MemberListType listType);
1012+
string? name, ns;
1013+
MemberListType listType;
1014+
SplitName(fullname, out name, out ns);
1015+
FilterHelper(bindingAttr, ref name, out _, out listType);
10091016
RuntimeType[] cache = GetNestedTypes_internal(name, bindingAttr, listType);
10101017
RuntimeType? match = null;
10111018

10121019
for (int i = 0; i < cache.Length; i++)
10131020
{
10141021
RuntimeType nestedType = cache[i];
1015-
if (FilterApplyType(nestedType, bindingAttr, name, false, null))
1022+
if (FilterApplyType(nestedType, bindingAttr, name, false, ns))
10161023
{
10171024
if (match != null)
10181025
throw ThrowHelper.GetAmbiguousMatchException(match);
10191026

10201027
match = nestedType;
1021-
1022-
if (ignoreAmbiguousMatch)
1023-
break;
10241028
}
10251029
}
10261030

10271031
return match;
10281032
}
10291033

1030-
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
1031-
public override Type? GetNestedType(string name, BindingFlags bindingAttr)
1032-
{
1033-
return GetNestedType(name, bindingAttr, ignoreAmbiguousMatch: false);
1034-
}
1035-
10361034
[DynamicallyAccessedMembers(GetAllMembers)]
10371035
public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
10381036
{

src/mono/System.Private.CoreLib/src/System/Type.Mono.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,53 +30,53 @@ internal IntPtr GetUnderlyingNativeHandle()
3030
public static Type? GetType(string typeName, bool throwOnError, bool ignoreCase)
3131
{
3232
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
33-
return GetType(typeName, null, null, throwOnError, ignoreCase, false, ref stackMark);
33+
return RuntimeType.GetType(typeName, throwOnError, ignoreCase, ref stackMark);
3434
}
3535

3636
[RequiresUnreferencedCode("The type might be removed")]
3737
[System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod
3838
public static Type? GetType(string typeName, bool throwOnError)
3939
{
4040
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
41-
return GetType(typeName, null, null, throwOnError, false, false, ref stackMark);
41+
return RuntimeType.GetType(typeName, throwOnError, false, ref stackMark);
4242
}
4343

4444
[RequiresUnreferencedCode("The type might be removed")]
4545
[System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod
4646
public static Type? GetType(string typeName)
4747
{
4848
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
49-
return GetType(typeName, null, null, false, false, false, ref stackMark);
49+
return RuntimeType.GetType(typeName, false, false, ref stackMark);
5050
}
5151

5252
[RequiresUnreferencedCode("The type might be removed")]
5353
[System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod
5454
public static Type? GetType(string typeName, Func<AssemblyName, Assembly?>? assemblyResolver, Func<Assembly?, string, bool, Type?>? typeResolver)
5555
{
5656
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
57-
return GetType(typeName, assemblyResolver, typeResolver, false, false, true, ref stackMark);
57+
return GetType(typeName, assemblyResolver, typeResolver, false, false, ref stackMark);
5858
}
5959

6060
[RequiresUnreferencedCode("The type might be removed")]
6161
[System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod
6262
public static Type? GetType(string typeName, Func<AssemblyName, Assembly?>? assemblyResolver, Func<Assembly?, string, bool, Type?>? typeResolver, bool throwOnError)
6363
{
6464
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
65-
return GetType(typeName, assemblyResolver, typeResolver, throwOnError, false, true, ref stackMark);
65+
return GetType(typeName, assemblyResolver, typeResolver, throwOnError, false, ref stackMark);
6666
}
6767

6868
[RequiresUnreferencedCode("The type might be removed")]
6969
[System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod
7070
public static Type? GetType(string typeName, Func<AssemblyName, Assembly?>? assemblyResolver, Func<Assembly?, string, bool, Type?>? typeResolver, bool throwOnError, bool ignoreCase)
7171
{
7272
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
73-
return GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, true, ref stackMark);
73+
return GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
7474
}
7575

7676
[RequiresUnreferencedCode("The type might be removed")]
77-
private static Type? GetType(string typeName, Func<AssemblyName, Assembly?>? assemblyResolver, Func<Assembly?, string, bool, Type?>? typeResolver, bool throwOnError, bool ignoreCase, bool extensibleParser, ref StackCrawlMark stackMark)
77+
private static Type? GetType(string typeName, Func<AssemblyName, Assembly?>? assemblyResolver, Func<Assembly?, string, bool, Type?>? typeResolver, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark)
7878
{
79-
return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, extensibleParser, ref stackMark);
79+
return TypeNameResolver.GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
8080
}
8181

8282
public static Type? GetTypeFromHandle(RuntimeTypeHandle handle)

0 commit comments

Comments
 (0)