-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Optimize type check efficiency with .IsValueType #82305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ internal static bool IsValueType<T>() | |
#if NETCOREAPP | ||
return typeof(T).IsValueType; | ||
#else | ||
if (default(T) != null) | ||
if (typeof(T).IsValueType) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a downlevel path. This may be used in runtimes where typeof(T).IsValueType isn't an intrinsic and isn't optimized. Note that this is part of an |
||
{ | ||
return true; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,7 +78,7 @@ public void Comparer_IComparerCompareWithObjectsNotOfMatchingTypeShouldThrow() | |
// throw if both inputs are non-null and one of them is not of type T | ||
IComparer comparer = Comparer<T>.Default; | ||
StrongBox<T> notOfTypeT = new StrongBox<T>(default(T)); | ||
if (default(T) != null) // if default(T) is null these asserts will fail as IComparer.Compare returns early if either side is null | ||
if (typeof(T).IsValueType) // if default(T) is null these asserts will fail as IComparer.Compare returns early if either side is null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a test and doesn't need to be changed. (The comment would also be stale if it were changed.) |
||
{ | ||
AssertExtensions.Throws<ArgumentException>(null, () => comparer.Compare(notOfTypeT, default(T))); // lhs is the problem | ||
AssertExtensions.Throws<ArgumentException>(null, () => comparer.Compare(default(T), notOfTypeT)); // rhs is the problem | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,7 +85,7 @@ public void EqualityComparer_IEqualityComparerEqualsWithObjectsNotOfMatchingType | |
Assert.Equal(default(T) == null, comparer.Equals(null, default(T))); | ||
Assert.True(comparer.Equals(null, null)); | ||
|
||
if (default(T) != null) // if default(T) is null this assert will fail as IEqualityComparer.Equals returns early if either input is null | ||
if (typeof(T).IsValueType) // if default(T) is null this assert will fail as IEqualityComparer.Equals returns early if either input is null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a test and doesn't need to be changed. |
||
{ | ||
AssertExtensions.Throws<ArgumentException>(null, () => comparer.Equals(notOfTypeT, default(T))); // lhs is the problem | ||
AssertExtensions.Throws<ArgumentException>(null, () => comparer.Equals(default(T), notOfTypeT)); // rhs is the problem | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -451,7 +451,7 @@ private static bool IsCompatibleObject(object? value) | |
|
||
private static void ValidateNullValue(object? value, string argument) | ||
{ | ||
if (value == null && default(T) != null) | ||
if (value == null && typeof(T).IsValueType) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be wrong for |
||
{ | ||
throw Error.InvalidNullValue(typeof(T), argument); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,7 @@ internal static class AggregationMinMaxHelpers<T> | |
|
||
AssociativeAggregationOperator<T, Pair<bool, T>, T> aggregation = | ||
new AssociativeAggregationOperator<T, Pair<bool, T>, T>(source, new Pair<bool, T>(false, default!), null, | ||
true, intermediateReduce, finalReduce, resultSelector, default(T) != null, QueryAggregationOptions.AssociativeCommutative); | ||
true, intermediateReduce, finalReduce, resultSelector, typeof(T).IsValueType, QueryAggregationOptions.AssociativeCommutative); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||
|
||
return aggregation.Aggregate(); | ||
} | ||
|
@@ -71,7 +71,7 @@ private static Func<Pair<bool, T>, T, Pair<bool, T>> MakeIntermediateReduceFunct | |
// the existing accumulated result is equal to the sign requested by the function factory, | ||
// we will return a new pair that contains the current element as the best item. We will | ||
// ignore null elements (for reference and nullable types) in the input stream. | ||
if ((default(T) != null || element != null) && | ||
if ((typeof(T).IsValueType || element != null) && | ||
(!accumulator.First || Util.Sign(comparer.Compare(element, accumulator.Second)) == sign)) | ||
{ | ||
return new Pair<bool, T>(true, element); | ||
|
@@ -98,7 +98,7 @@ private static Func<Pair<bool, T>, Pair<bool, T>, Pair<bool, T>> MakeFinalReduce | |
if (element.First && | ||
(!accumulator.First || Util.Sign(comparer.Compare(element.Second, accumulator.Second)) == sign)) | ||
{ | ||
Debug.Assert(default(T) != null || element.Second != null, "nulls unexpected in final reduce"); | ||
Debug.Assert(typeof(T).IsValueType || element.Second != null, "nulls unexpected in final reduce"); | ||
return new Pair<bool, T>(true, element.Second); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -232,7 +232,7 @@ public static unsafe bool Contains<T>(ref T searchSpace, T value, int length) wh | |
|
||
nint index = 0; // Use nint for arithmetic to avoid unnecessary 64->32->64 truncations | ||
|
||
if (default(T) != null || (object?)value != null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do these changes really have a material impact on the codegen? I wouldn't expect them to. The before/after in the opening post where there's poorer code gen isn't for this case. |
||
if (typeof(T).IsValueType || (object?)value != null) | ||
{ | ||
Debug.Assert(value is not null); | ||
|
||
|
@@ -303,7 +303,7 @@ public static unsafe int IndexOf<T>(ref T searchSpace, T value, int length) wher | |
Debug.Assert(length >= 0); | ||
|
||
nint index = 0; // Use nint for arithmetic to avoid unnecessary 64->32->64 truncations | ||
if (default(T) != null || (object?)value != null) | ||
if (typeof(T).IsValueType || (object?)value != null) | ||
{ | ||
Debug.Assert(value is not null); | ||
|
||
|
@@ -393,7 +393,7 @@ public static int IndexOfAny<T>(ref T searchSpace, T value0, T value1, int lengt | |
|
||
T lookUp; | ||
int index = 0; | ||
if (default(T) != null || ((object?)value0 != null && (object?)value1 != null)) | ||
if (typeof(T).IsValueType || ((object?)value0 != null && (object?)value1 != null)) | ||
{ | ||
Debug.Assert(value0 is not null && value1 is not null); | ||
|
||
|
@@ -499,7 +499,7 @@ public static int IndexOfAny<T>(ref T searchSpace, T value0, T value1, T value2, | |
|
||
T lookUp; | ||
int index = 0; | ||
if (default(T) != null || ((object?)value0 != null && (object?)value1 != null && (object?)value2 != null)) | ||
if (typeof(T).IsValueType || ((object?)value0 != null && (object?)value1 != null && (object?)value2 != null)) | ||
{ | ||
Debug.Assert(value0 is not null && value1 is not null && value2 is not null); | ||
|
||
|
@@ -713,7 +713,7 @@ public static int LastIndexOf<T>(ref T searchSpace, T value, int length) where T | |
{ | ||
Debug.Assert(length >= 0); | ||
|
||
if (default(T) != null || (object?)value != null) | ||
if (typeof(T).IsValueType || (object?)value != null) | ||
{ | ||
Debug.Assert(value is not null); | ||
|
||
|
@@ -797,7 +797,7 @@ public static int LastIndexOfAny<T>(ref T searchSpace, T value0, T value1, int l | |
Debug.Assert(length >= 0); | ||
|
||
T lookUp; | ||
if (default(T) != null || ((object?)value0 != null && (object?)value1 != null)) | ||
if (typeof(T).IsValueType || ((object?)value0 != null && (object?)value1 != null)) | ||
{ | ||
Debug.Assert(value0 is not null && value1 is not null); | ||
|
||
|
@@ -902,7 +902,7 @@ public static int LastIndexOfAny<T>(ref T searchSpace, T value0, T value1, T val | |
Debug.Assert(length >= 0); | ||
|
||
T lookUp; | ||
if (default(T) != null || ((object?)value0 != null && (object?)value1 != null && (object?)value2 != null)) | ||
if (typeof(T).IsValueType || ((object?)value0 != null && (object?)value1 != null && (object?)value2 != null)) | ||
{ | ||
Debug.Assert(value0 is not null && value1 is not null && value2 is not null); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a test; it doesn't need to be changed.