summaryrefslogtreecommitdiff
path: root/src/System.Private.CoreLib/shared/System
diff options
context:
space:
mode:
authorBen Adams <thundercat@illyriad.co.uk>2019-01-04 20:38:22 +0100
committerJan Kotas <jkotas@microsoft.com>2019-01-04 11:38:21 -0800
commit4e82a5801bd804bff0bf6294d7135bbb63df92f6 (patch)
tree7fc2c08beb367453d17c430662d7ea8900de250a /src/System.Private.CoreLib/shared/System
parentdf4a1854aa42c1e97874b00fe49339e216e30af9 (diff)
downloadcoreclr-4e82a5801bd804bff0bf6294d7135bbb63df92f6.tar.gz
coreclr-4e82a5801bd804bff0bf6294d7135bbb63df92f6.tar.bz2
coreclr-4e82a5801bd804bff0bf6294d7135bbb63df92f6.zip
Support faster null checks (#21765)
Diffstat (limited to 'src/System.Private.CoreLib/shared/System')
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs19
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/ConstructorInfo.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/EventInfo.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/FieldInfo.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/MemberInfo.cs35
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/MethodBase.cs26
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/MethodInfo.cs21
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Module.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/PropertyInfo.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Version.cs13
11 files changed, 134 insertions, 96 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs b/src/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs
index 46e9a833ec..cb0d4c4fe1 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/SortVersion.cs
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Runtime.CompilerServices;
+
namespace System.Globalization
{
[Serializable]
@@ -75,20 +77,19 @@ namespace System.Globalization
return m_NlsVersion * 7 | m_SortId.GetHashCode();
}
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(SortVersion left, SortVersion right)
{
- if (((object)left) != null)
- {
- return left.Equals(right);
- }
-
- if (((object)right) != null)
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (right is null)
{
- return right.Equals(left);
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (left is null) ? true : false;
}
- // Both null.
- return true;
+ return right.Equals(left);
}
public static bool operator !=(SortVersion left, SortVersion right)
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs b/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
index 516f81d370..c7b39ff8df 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Configuration.Assemblies;
using System.Runtime.Serialization;
using System.Security;
+using System.Runtime.CompilerServices;
namespace System.Reflection
{
@@ -147,15 +148,20 @@ namespace System.Reflection
public override bool Equals(object o) => base.Equals(o);
public override int GetHashCode() => base.GetHashCode();
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Assembly left, Assembly right)
{
- if (object.ReferenceEquals(left, right))
- return true;
-
- if ((object)left == null || (object)right == null)
- return false;
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (right is null)
+ {
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (left is null) ? true : false;
+ }
- return left.Equals(right);
+ // Quick reference equality test prior to calling the virtual Equality
+ return ReferenceEquals(right, left) ? true : right.Equals(left);
}
public static bool operator !=(Assembly left, Assembly right)
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/ConstructorInfo.cs b/src/System.Private.CoreLib/shared/System/Reflection/ConstructorInfo.cs
index 3ee1dbf855..3d8750cbba 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/ConstructorInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/ConstructorInfo.cs
@@ -4,6 +4,7 @@
using System.Diagnostics;
using System.Globalization;
+using System.Runtime.CompilerServices;
namespace System.Reflection
{
@@ -21,15 +22,20 @@ namespace System.Reflection
public override bool Equals(object obj) => base.Equals(obj);
public override int GetHashCode() => base.GetHashCode();
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(ConstructorInfo left, ConstructorInfo right)
{
- if (object.ReferenceEquals(left, right))
- return true;
-
- if ((object)left == null || (object)right == null)
- return false;
-
- return left.Equals(right);
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (right is null)
+ {
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (left is null) ? true : false;
+ }
+
+ // Quick reference equality test prior to calling the virtual Equality
+ return ReferenceEquals(right, left) ? true : right.Equals(left);
}
public static bool operator !=(ConstructorInfo left, ConstructorInfo right) => !(left == right);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/EventInfo.cs b/src/System.Private.CoreLib/shared/System/Reflection/EventInfo.cs
index ccd9acf648..e35261339c 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/EventInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/EventInfo.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Runtime.CompilerServices;
#if FEATURE_COMINTEROP
using EventRegistrationToken = System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken;
@@ -99,15 +100,20 @@ namespace System.Reflection
public override bool Equals(object obj) => base.Equals(obj);
public override int GetHashCode() => base.GetHashCode();
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(EventInfo left, EventInfo right)
{
- if (object.ReferenceEquals(left, right))
- return true;
-
- if ((object)left == null || (object)right == null)
- return false;
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (right is null)
+ {
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (left is null) ? true : false;
+ }
- return left.Equals(right);
+ // Quick reference equality test prior to calling the virtual Equality
+ return ReferenceEquals(right, left) ? true : right.Equals(left);
}
public static bool operator !=(EventInfo left, EventInfo right) => !(left == right);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/FieldInfo.cs b/src/System.Private.CoreLib/shared/System/Reflection/FieldInfo.cs
index 0863c2b019..53bcf17c2c 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/FieldInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/FieldInfo.cs
@@ -4,6 +4,7 @@
using System.Diagnostics;
using System.Globalization;
+using System.Runtime.CompilerServices;
namespace System.Reflection
{
@@ -39,15 +40,20 @@ namespace System.Reflection
public override bool Equals(object obj) => base.Equals(obj);
public override int GetHashCode() => base.GetHashCode();
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(FieldInfo left, FieldInfo right)
{
- if (object.ReferenceEquals(left, right))
- return true;
-
- if ((object)left == null || (object)right == null)
- return false;
-
- return left.Equals(right);
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (right is null)
+ {
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (left is null) ? true : false;
+ }
+
+ // Quick reference equality test prior to calling the virtual Equality
+ return ReferenceEquals(right, left) ? true : right.Equals(left);
}
public static bool operator !=(FieldInfo left, FieldInfo right) => !(left == right);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/MemberInfo.cs b/src/System.Private.CoreLib/shared/System/Reflection/MemberInfo.cs
index c61198db62..2f439d8c8c 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/MemberInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/MemberInfo.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Runtime.CompilerServices;
namespace System.Reflection
{
@@ -44,32 +45,20 @@ namespace System.Reflection
public override bool Equals(object obj) => base.Equals(obj);
public override int GetHashCode() => base.GetHashCode();
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(MemberInfo left, MemberInfo right)
{
- if (object.ReferenceEquals(left, right))
- return true;
-
- if ((object)left == null || (object)right == null)
- return false;
-
- Type type1, type2;
- MethodBase method1, method2;
- FieldInfo field1, field2;
- EventInfo event1, event2;
- PropertyInfo property1, property2;
-
- if ((type1 = left as Type) != null && (type2 = right as Type) != null)
- return type1 == type2;
- else if ((method1 = left as MethodBase) != null && (method2 = right as MethodBase) != null)
- return method1 == method2;
- else if ((field1 = left as FieldInfo) != null && (field2 = right as FieldInfo) != null)
- return field1 == field2;
- else if ((event1 = left as EventInfo) != null && (event2 = right as EventInfo) != null)
- return event1 == event2;
- else if ((property1 = left as PropertyInfo) != null && (property2 = right as PropertyInfo) != null)
- return property1 == property2;
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (right is null)
+ {
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (left is null) ? true : false;
+ }
- return false;
+ // Quick reference equality test prior to calling the virtual Equality
+ return ReferenceEquals(right, left) ? true : right.Equals(left);
}
public static bool operator !=(MemberInfo left, MemberInfo right) => !(left == right);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/MethodBase.cs b/src/System.Private.CoreLib/shared/System/Reflection/MethodBase.cs
index 0037c74f4c..e5ca0d5de1 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/MethodBase.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/MethodBase.cs
@@ -4,6 +4,7 @@
using System.Globalization;
using System.Diagnostics;
+using System.Runtime.CompilerServices;
namespace System.Reflection
{
@@ -62,23 +63,20 @@ namespace System.Reflection
public override bool Equals(object obj) => base.Equals(obj);
public override int GetHashCode() => base.GetHashCode();
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(MethodBase left, MethodBase right)
{
- if (object.ReferenceEquals(left, right))
- return true;
-
- if ((object)left == null || (object)right == null)
- return false;
-
- MethodInfo method1, method2;
- ConstructorInfo constructor1, constructor2;
-
- if ((method1 = left as MethodInfo) != null && (method2 = right as MethodInfo) != null)
- return method1 == method2;
- else if ((constructor1 = left as ConstructorInfo) != null && (constructor2 = right as ConstructorInfo) != null)
- return constructor1 == constructor2;
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (right is null)
+ {
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (left is null) ? true : false;
+ }
- return false;
+ // Quick reference equality test prior to calling the virtual Equality
+ return ReferenceEquals(right, left) ? true : right.Equals(left);
}
public static bool operator !=(MethodBase left, MethodBase right) => !(left == right);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/MethodInfo.cs b/src/System.Private.CoreLib/shared/System/Reflection/MethodInfo.cs
index 95c62ba7f0..920a9a2da8 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/MethodInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/MethodInfo.cs
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Runtime.CompilerServices;
+
namespace System.Reflection
{
public abstract partial class MethodInfo : MethodBase
@@ -27,15 +29,20 @@ namespace System.Reflection
public override bool Equals(object obj) => base.Equals(obj);
public override int GetHashCode() => base.GetHashCode();
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(MethodInfo left, MethodInfo right)
{
- if (object.ReferenceEquals(left, right))
- return true;
-
- if ((object)left == null || (object)right == null)
- return false;
-
- return left.Equals(right);
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (right is null)
+ {
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (left is null) ? true : false;
+ }
+
+ // Quick reference equality test prior to calling the virtual Equality
+ return ReferenceEquals(right, left) ? true : right.Equals(left);
}
public static bool operator !=(MethodInfo left, MethodInfo right) => !(left == right);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Module.cs b/src/System.Private.CoreLib/shared/System/Reflection/Module.cs
index d290f78033..5d2e418f06 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/Module.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Module.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace System.Reflection
@@ -114,16 +115,21 @@ namespace System.Reflection
public override bool Equals(object o) => base.Equals(o);
public override int GetHashCode() => base.GetHashCode();
-
+
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Module left, Module right)
{
- if (object.ReferenceEquals(left, right))
- return true;
-
- if ((object)left == null || (object)right == null)
- return false;
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (right is null)
+ {
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (left is null) ? true : false;
+ }
- return left.Equals(right);
+ // Quick reference equality test prior to calling the virtual Equality
+ return ReferenceEquals(right, left) ? true : right.Equals(left);
}
public static bool operator !=(Module left, Module right) => !(left == right);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/PropertyInfo.cs b/src/System.Private.CoreLib/shared/System/Reflection/PropertyInfo.cs
index ff8a02e96d..562907f485 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/PropertyInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/PropertyInfo.cs
@@ -4,6 +4,7 @@
using System.Diagnostics;
using System.Globalization;
+using System.Runtime.CompilerServices;
namespace System.Reflection
{
@@ -58,15 +59,20 @@ namespace System.Reflection
public override bool Equals(object obj) => base.Equals(obj);
public override int GetHashCode() => base.GetHashCode();
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(PropertyInfo left, PropertyInfo right)
{
- if (object.ReferenceEquals(left, right))
- return true;
-
- if ((object)left == null || (object)right == null)
- return false;
-
- return left.Equals(right);
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (right is null)
+ {
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (left is null) ? true : false;
+ }
+
+ // Quick reference equality test prior to calling the virtual Equality
+ return ReferenceEquals(right, left) ? true : right.Equals(left);
}
public static bool operator !=(PropertyInfo left, PropertyInfo right) => !(left == right);
diff --git a/src/System.Private.CoreLib/shared/System/Version.cs b/src/System.Private.CoreLib/shared/System/Version.cs
index 444ee48858..359837f348 100644
--- a/src/System.Private.CoreLib/shared/System/Version.cs
+++ b/src/System.Private.CoreLib/shared/System/Version.cs
@@ -5,6 +5,7 @@
using System.Globalization;
using System.Diagnostics;
using System.Text;
+using System.Runtime.CompilerServices;
namespace System
{
@@ -405,14 +406,20 @@ namespace System
return int.TryParse(component, NumberStyles.Integer, CultureInfo.InvariantCulture, out parsedComponent) && parsedComponent >= 0;
}
+ // Force inline as the true/false ternary takes it above ALWAYS_INLINE size even though the asm ends up smaller
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Version v1, Version v2)
{
- if (v1 is null)
+ // Test "right" first to allow branch elimination when inlined for null checks (== null)
+ // so it can become a simple test
+ if (v2 is null)
{
- return v2 is null;
+ // return true/false not the test result https://github.com/dotnet/coreclr/issues/914
+ return (v1 is null) ? true : false;
}
- return v1.Equals(v2);
+ // Quick reference equality test prior to calling the virtual Equality
+ return ReferenceEquals(v2, v1) ? true : v2.Equals(v1);
}
public static bool operator !=(Version v1, Version v2)