From dc73562d3d057547eaba8ff8313b4c58a157f48d Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Fri, 5 Mar 2021 14:13:37 +0000 Subject: [PATCH 01/83] Misc PriorityQueue fixes (#48539) * PriorityQueue fixes * add missing enumerator invalidations * Update src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs Co-authored-by: Stephen Toub * add Debug assertion for heap arity * presize buffer if EnqueueRange input is ICollection * move capacity check outside of the core Grow method * remove ICollection detection from EnumerableHelpers * address feedback Co-authored-by: Stephen Toub --- .../Collections/Generic/EnumerableHelpers.cs | 18 ++ .../Collections/Generic/PriorityQueue.cs | 239 ++++++++---------- .../PriorityQueue/PriorityQueue.Tests.cs | 65 +++-- 3 files changed, 170 insertions(+), 152 deletions(-) diff --git a/src/libraries/Common/src/System/Collections/Generic/EnumerableHelpers.cs b/src/libraries/Common/src/System/Collections/Generic/EnumerableHelpers.cs index b5bebedb3af16..256fad2a1d5ed 100644 --- a/src/libraries/Common/src/System/Collections/Generic/EnumerableHelpers.cs +++ b/src/libraries/Common/src/System/Collections/Generic/EnumerableHelpers.cs @@ -8,6 +8,24 @@ namespace System.Collections.Generic /// internal static partial class EnumerableHelpers { + /// Attempt to determine the count of the source enumerable without forcing an enumeration. + /// The source enumerable. + /// The count determined by the type test. + /// + /// True if the source enumerable could be determined without enumerating, false otherwise. + /// + internal static bool TryGetCount(IEnumerable source, out int count) + { + if (source is ICollection ict) + { + count = ict.Count; + return true; + } + + count = 0; + return false; + } + /// Converts an enumerable to an array using the same logic as List{T}. /// The enumerable to convert. /// The number of items stored in the resulting array, 0-indexed. diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs index 5ddc1f16fee84..85c48ba9b88cc 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs @@ -40,19 +40,9 @@ public class PriorityQueue /// private int _version; - /// - /// When the underlying buffer for the heap nodes grows to accomodate more nodes, - /// this is the minimum the capacity will grow by. - /// - private const int MinimumElementsToGrowBy = 4; - - /// - /// The index at which the heap root is maintained. - /// - private const int RootIndex = 0; - /// /// Specifies the arity of the d-ary heap, which here is quaternary. + /// It is assumed that this value is a power of 2. /// private const int Arity = 4; @@ -61,6 +51,13 @@ public class PriorityQueue /// private const int Log2Arity = 2; +#if DEBUG + static PriorityQueue() + { + Debug.Assert(Log2Arity > 0 && Math.Pow(2, Log2Arity) == Arity); + } +#endif + /// /// Creates an empty priority queue. /// @@ -151,23 +148,25 @@ public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> items, /// public void Enqueue(TElement element, TPriority priority) { - EnsureEnoughCapacityBeforeAddingNode(); - // Virtually add the node at the end of the underlying array. // Note that the node being enqueued does not need to be physically placed // there at this point, as such an assignment would be redundant. - _size++; + + int currentSize = _size++; _version++; - // Restore the heap order - int lastNodeIndex = GetLastNodeIndex(); + if (_nodes.Length == currentSize) + { + Grow(currentSize + 1); + } + if (_comparer == null) { - MoveUpDefaultComparer((element, priority), lastNodeIndex); + MoveUpDefaultComparer((element, priority), currentSize); } else { - MoveUpCustomComparer((element, priority), lastNodeIndex); + MoveUpCustomComparer((element, priority), currentSize); } } @@ -182,7 +181,7 @@ public TElement Peek() throw new InvalidOperationException(SR.InvalidOperation_EmptyQueue); } - return _nodes[RootIndex].Element; + return _nodes[0].Element; } /// @@ -196,7 +195,7 @@ public TElement Dequeue() throw new InvalidOperationException(SR.InvalidOperation_EmptyQueue); } - TElement element = _nodes[RootIndex].Element; + TElement element = _nodes[0].Element; RemoveRootNode(); return element; } @@ -211,7 +210,7 @@ public bool TryDequeue([MaybeNullWhen(false)] out TElement element, [MaybeNullWh { if (_size != 0) { - (element, priority) = _nodes[RootIndex]; + (element, priority) = _nodes[0]; RemoveRootNode(); return true; } @@ -231,7 +230,7 @@ public bool TryPeek([MaybeNullWhen(false)] out TElement element, [MaybeNullWhen( { if (_size != 0) { - (element, priority) = _nodes[RootIndex]; + (element, priority) = _nodes[0]; return true; } @@ -247,18 +246,14 @@ public TElement EnqueueDequeue(TElement element, TPriority priority) { if (_size != 0) { - (TElement Element, TPriority Priority) root = _nodes[RootIndex]; + (TElement Element, TPriority Priority) root = _nodes[0]; if (_comparer == null) { if (Comparer.Default.Compare(priority, root.Priority) > 0) { - (TElement Element, TPriority Priority) newRoot = (element, priority); - _nodes[RootIndex] = newRoot; - - MoveDownDefaultComparer(newRoot, RootIndex); + MoveDownDefaultComparer((element, priority), 0); _version++; - return root.Element; } } @@ -266,12 +261,8 @@ public TElement EnqueueDequeue(TElement element, TPriority priority) { if (_comparer.Compare(priority, root.Priority) > 0) { - (TElement Element, TPriority Priority) newRoot = (element, priority); - _nodes[RootIndex] = newRoot; - - MoveDownCustomComparer(newRoot, RootIndex); + MoveDownCustomComparer((element, priority), 0); _version++; - return root.Element; } } @@ -293,6 +284,7 @@ public void EnqueueRange(IEnumerable<(TElement Element, TPriority Priority)> ite if (_size == 0) { _nodes = EnumerableHelpers.ToArray(items, out _size); + _version++; if (_size > 1) { @@ -301,6 +293,11 @@ public void EnqueueRange(IEnumerable<(TElement Element, TPriority Priority)> ite } else { + if (EnumerableHelpers.TryGetCount(items, out int count) && _nodes.Length - _size < count) + { + Grow(_size + count); + } + foreach ((TElement element, TPriority priority) in items) { Enqueue(element, priority); @@ -318,27 +315,30 @@ public void EnqueueRange(IEnumerable elements, TPriority priority) throw new ArgumentNullException(nameof(elements)); } + if (EnumerableHelpers.TryGetCount(elements, out int count) && _nodes.Length - _size < count) + { + Grow(_size + count); + } + if (_size == 0) { - using (IEnumerator enumerator = elements.GetEnumerator()) + int i = 0; + foreach (TElement element in elements) { - if (enumerator.MoveNext()) + if (_nodes.Length == i) { - _nodes = new (TElement, TPriority)[MinimumElementsToGrowBy]; - _nodes[0] = (enumerator.Current, priority); - _size = 1; - - while (enumerator.MoveNext()) - { - EnsureEnoughCapacityBeforeAddingNode(); - _nodes[_size++] = (enumerator.Current, priority); - } - - if (_size > 1) - { - Heapify(); - } + Grow(i + 1); } + + _nodes[i++] = (element, priority); + } + + _size = i; + _version++; + + if (i > 1) + { + Heapify(); } } else @@ -377,7 +377,8 @@ public int EnsureCapacity(int capacity) if (_nodes.Length < capacity) { - SetCapacity(Math.Max(capacity, ComputeCapacityForNextGrowth())); + Grow(capacity); + _version++; } return _nodes.Length; @@ -392,50 +393,37 @@ public void TrimExcess() int threshold = (int)(_nodes.Length * 0.9); if (_size < threshold) { - SetCapacity(_size); + Array.Resize(ref _nodes, _size); + _version++; } } /// - /// Ensures the queue has enough space to add another item. + /// Grows the priority queue to match the specified min capacity. /// - private void EnsureEnoughCapacityBeforeAddingNode() + private void Grow(int minCapacity) { - Debug.Assert(_size <= _nodes.Length); - if (_size == _nodes.Length) - { - SetCapacity(ComputeCapacityForNextGrowth()); - } - } + Debug.Assert(_nodes.Length < minCapacity); - /// - /// Determines how large to size the queue when it expands. - /// - private int ComputeCapacityForNextGrowth() - { - const int GrowthFactor = 2; + // Array.MaxArrayLength is internal to S.P.CoreLib, replicate here. const int MaxArrayLength = 0X7FEFFFFF; + const int GrowFactor = 2; + const int MinimumGrow = 4; - int newCapacity = Math.Max(_nodes.Length * GrowthFactor, _nodes.Length + MinimumElementsToGrowBy); + int newcapacity = GrowFactor * _nodes.Length; - // Allow the structure to grow to maximum possible capacity (~2G elements) before encountering overflow. - // Note that this check works even when _nodes.Length overflowed thanks to the (uint) cast. + // Allow the queue to grow to maximum possible capacity (~2G elements) before encountering overflow. + // Note that this check works even when _nodes.Length overflowed thanks to the (uint) cast + if ((uint)newcapacity > MaxArrayLength) newcapacity = MaxArrayLength; - if ((uint)newCapacity > MaxArrayLength) - { - newCapacity = MaxArrayLength; - } + // Ensure minimum growth is respected. + newcapacity = Math.Max(newcapacity, _nodes.Length + MinimumGrow); - return newCapacity; - } + // If the computed capacity is still less than specified, set to the original argument. + // Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize. + if (newcapacity < minCapacity) newcapacity = minCapacity; - /// - /// Grows or shrinks the array holding nodes. Capacity must be >= _size. - /// - private void SetCapacity(int capacity) - { - Array.Resize(ref _nodes, capacity); - _version++; + Array.Resize(ref _nodes, newcapacity); } /// @@ -443,10 +431,9 @@ private void SetCapacity(int capacity) /// private void RemoveRootNode() { - // The idea is to replace the specified node by the very last + // The idea is to replace the root node by the very last // node and shorten the array by one. - - int lastNodeIndex = GetLastNodeIndex(); + int lastNodeIndex = _size - 1; (TElement Element, TPriority Priority) lastNode = _nodes[lastNodeIndex]; if (RuntimeHelpers.IsReferenceOrContainsReferences<(TElement, TPriority)>()) { @@ -458,19 +445,14 @@ private void RemoveRootNode() if (_comparer == null) { - MoveDownDefaultComparer(lastNode, RootIndex); + MoveDownDefaultComparer(lastNode, 0); } else { - MoveDownCustomComparer(lastNode, RootIndex); + MoveDownCustomComparer(lastNode, 0); } } - /// - /// Gets the index of the last node in the heap. - /// - private int GetLastNodeIndex() => _size - 1; - /// /// Gets the index of an element's parent. /// @@ -479,7 +461,7 @@ private void RemoveRootNode() /// /// Gets the index of the first child of an element. /// - private int GetFirstChildIndex(int index) => Arity * index + 1; + private int GetFirstChildIndex(int index) => (index << Log2Arity) + 1; /// /// Converts an unordered list into a heap. @@ -491,21 +473,21 @@ private void Heapify() // only for higher nodes, starting from the first node that has children. // It is the parent of the very last element in the array. - int lastNodeIndex = GetLastNodeIndex(); - int lastParentWithChildren = GetParentIndex(lastNodeIndex); + (TElement Element, TPriority Priority)[] nodes = _nodes; + int lastParentWithChildren = GetParentIndex(_size - 1); if (_comparer == null) { for (int index = lastParentWithChildren; index >= 0; --index) { - MoveDownDefaultComparer(_nodes[index], index); + MoveDownDefaultComparer(nodes[index], index); } } else { for (int index = lastParentWithChildren; index >= 0; --index) { - MoveDownCustomComparer(_nodes[index], index); + MoveDownCustomComparer(nodes[index], index); } } } @@ -590,33 +572,31 @@ private void MoveDownDefaultComparer((TElement Element, TPriority Priority) node int i; while ((i = GetFirstChildIndex(nodeIndex)) < size) { - // Check if the current node (pointed by 'nodeIndex') should really be extracted - // first, or maybe one of its children should be extracted earlier. - (TElement Element, TPriority Priority) topChild = nodes[i]; - int childrenIndexesLimit = Math.Min(i + Arity, size); - int topChildIndex = i; + // Find the child node with the minimal priority + (TElement Element, TPriority Priority) minChild = nodes[i]; + int minChildIndex = i; - while (++i < childrenIndexesLimit) + int childIndexUpperBound = Math.Min(i + Arity, size); + while (++i < childIndexUpperBound) { - (TElement Element, TPriority Priority) child = nodes[i]; - if (Comparer.Default.Compare(child.Priority, topChild.Priority) < 0) + (TElement Element, TPriority Priority) nextChild = nodes[i]; + if (Comparer.Default.Compare(nextChild.Priority, minChild.Priority) < 0) { - topChild = child; - topChildIndex = i; + minChild = nextChild; + minChildIndex = i; } } - // In case no child needs to be extracted earlier than the current node, - // there is nothing more to do - the right spot was found. - if (Comparer.Default.Compare(node.Priority, topChild.Priority) <= 0) + // Heap property is satisfied; insert node in this location. + if (Comparer.Default.Compare(node.Priority, minChild.Priority) <= 0) { break; } - // Move the top child up by one node and now investigate the - // node that was considered to be the top child (recursive). - nodes[nodeIndex] = topChild; - nodeIndex = topChildIndex; + // Move the minimal child up by one node and + // continue recursively from its location. + nodes[nodeIndex] = minChild; + nodeIndex = minChildIndex; } nodes[nodeIndex] = node; @@ -640,36 +620,33 @@ private void MoveDownCustomComparer((TElement Element, TPriority Priority) node, int i; while ((i = GetFirstChildIndex(nodeIndex)) < size) { - // Check if the current node (pointed by 'nodeIndex') should really be extracted - // first, or maybe one of its children should be extracted earlier. - (TElement Element, TPriority Priority) topChild = nodes[i]; - int childrenIndexesLimit = Math.Min(i + Arity, size); - int topChildIndex = i; + // Find the child node with the minimal priority + (TElement Element, TPriority Priority) minChild = nodes[i]; + int minChildIndex = i; - while (++i < childrenIndexesLimit) + int childIndexUpperBound = Math.Min(i + Arity, size); + while (++i < childIndexUpperBound) { - (TElement Element, TPriority Priority) child = nodes[i]; - if (comparer.Compare(child.Priority, topChild.Priority) < 0) + (TElement Element, TPriority Priority) nextChild = nodes[i]; + if (comparer.Compare(nextChild.Priority, minChild.Priority) < 0) { - topChild = child; - topChildIndex = i; + minChild = nextChild; + minChildIndex = i; } } - // In case no child needs to be extracted earlier than the current node, - // there is nothing more to do - the right spot was found. - if (comparer.Compare(node.Priority, topChild.Priority) <= 0) + // Heap property is satisfied; insert node in this location. + if (comparer.Compare(node.Priority, minChild.Priority) <= 0) { break; } - // Move the top child up by one node and now investigate the - // node that was considered to be the top child (recursive). - nodes[nodeIndex] = topChild; - nodeIndex = topChildIndex; + // Move the minimal child up by one node and continue recursively from its location. + nodes[nodeIndex] = minChild; + nodeIndex = minChildIndex; } - _nodes[nodeIndex] = node; + nodes[nodeIndex] = node; } /// diff --git a/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.cs b/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.cs index 4201e90de8c59..12472626c7f2e 100644 --- a/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Tests.cs @@ -246,35 +246,58 @@ private static int GetUnderlyingBufferCapacity(PriorityQueu #endregion + #region Enumeration + [Theory] - [MemberData(nameof(ValidPositiveCollectionSizes))] - public void PriorityQueue_Enumeration_InvalidateOnModifiedCollection(int count) + [MemberData(nameof(GetNonModifyingOperations))] + public void PriorityQueue_Enumeration_ValidOnNonModifyingOperation(Action> nonModifyingOperation, int count) { - IReadOnlyCollection<(int, int)> itemsToEnqueue = Enumerable.Range(1, count).Select(i => (i, i)).ToArray(); - PriorityQueue queue = new PriorityQueue(); - queue.EnqueueRange(itemsToEnqueue.Take(count - 1)); - var enumerator = queue.UnorderedItems.GetEnumerator(); - - (int element, int priority) = itemsToEnqueue.Last(); - queue.Enqueue(element, priority); - Assert.Throws(() => enumerator.MoveNext()); + PriorityQueue queue = CreatePriorityQueue(initialCapacity: count, count: count); + using var enumerator = queue.UnorderedItems.GetEnumerator(); + nonModifyingOperation(queue); + enumerator.MoveNext(); } - #region Enumeration - [Theory] - [MemberData(nameof(ValidPositiveCollectionSizes))] - public void PriorityQueue_Enumeration_InvalidationOnModifiedCapacity(int count) + [MemberData(nameof(GetModifyingOperations))] + public void PriorityQueue_Enumeration_InvalidationOnModifyingOperation(Action> modifyingOperation, int count) { - PriorityQueue queue = CreatePriorityQueue(initialCapacity: 0, count); - var enumerator = queue.UnorderedItems.GetEnumerator(); + PriorityQueue queue = CreatePriorityQueue(initialCapacity: count, count: count); + using var enumerator = queue.UnorderedItems.GetEnumerator(); + modifyingOperation(queue); + Assert.Throws(() => enumerator.MoveNext()); + } - int capacityBefore = GetUnderlyingBufferCapacity(queue); - queue.EnsureCapacity(count * 2 + 4); - int capacityAfter = GetUnderlyingBufferCapacity(queue); + public static IEnumerable GetModifyingOperations() + { + yield return WrapArg(queue => queue.Enqueue(42, 0), 0); + yield return WrapArg(queue => queue.Dequeue(), 5); + yield return WrapArg(queue => queue.TryDequeue(out _, out _), 5); + yield return WrapArg(queue => queue.EnqueueDequeue(5, priority: int.MaxValue), 5); + yield return WrapArg(queue => queue.EnqueueDequeue(5, priority: int.MaxValue), 5); + yield return WrapArg(queue => queue.EnqueueRange(new[] { (1,2) }), 0); + yield return WrapArg(queue => queue.EnqueueRange(new[] { (1, 2) }), 10); + yield return WrapArg(queue => queue.EnqueueRange(new[] { 1, 2 }, 42), 0); + yield return WrapArg(queue => queue.EnqueueRange(new[] { 1, 2 }, 42), 10); + yield return WrapArg(queue => queue.EnsureCapacity(2 * queue.Count), 4); + yield return WrapArg(queue => queue.Clear(), 5); + yield return WrapArg(queue => queue.Clear(), 0); + + static object[] WrapArg(Action> arg, int queueCount) => new object[] { arg, queueCount }; + } - Assert.NotEqual(capacityBefore, capacityAfter); - Assert.Throws(() => enumerator.MoveNext()); + public static IEnumerable GetNonModifyingOperations() + { + yield return WrapArg(queue => queue.Peek(), 1); + yield return WrapArg(queue => queue.TryPeek(out _, out _), 1); + yield return WrapArg(queue => queue.TryDequeue(out _, out _), 0); + yield return WrapArg(queue => queue.EnqueueDequeue(5, priority: int.MinValue), 1); + yield return WrapArg(queue => queue.EnqueueDequeue(5, priority: int.MaxValue), 0); + yield return WrapArg(queue => queue.EnqueueRange(Array.Empty<(int, int)>()), 5); + yield return WrapArg(queue => queue.EnqueueRange(Array.Empty(), 42), 5); + yield return WrapArg(queue => queue.EnsureCapacity(5), 5); + + static object[] WrapArg(Action> arg, int queueCount) => new object[] { arg, queueCount }; } #endregion From b76f17e0a270818a2795f91661c0d0ec8ffca97a Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 5 Mar 2021 10:10:55 -0500 Subject: [PATCH 02/83] Fix nullable annotations on TraceSource/Listener (#49176) --- .../ref/System.Diagnostics.TextWriterTraceListener.cs | 4 ++-- .../src/System/Diagnostics/DelimitedListTraceListener.cs | 4 ++-- .../src/System/Diagnostics/XmlWriterTraceListener.cs | 4 ++-- .../ref/System.Diagnostics.TraceSource.cs | 8 ++++---- .../src/System/Diagnostics/TraceListener.cs | 4 ++-- .../src/System/Diagnostics/TraceSource.cs | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/ref/System.Diagnostics.TextWriterTraceListener.cs b/src/libraries/System.Diagnostics.TextWriterTraceListener/ref/System.Diagnostics.TextWriterTraceListener.cs index bcbf59625e14f..a0d7e704a98ee 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/ref/System.Diagnostics.TextWriterTraceListener.cs +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/ref/System.Diagnostics.TextWriterTraceListener.cs @@ -25,7 +25,7 @@ public DelimitedListTraceListener(string? fileName, string? name) { } public override void TraceData(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, object? data) { } public override void TraceData(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, params object?[]? data) { } public override void TraceEvent(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string? message) { } - public override void TraceEvent(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string format, params object?[]? args) { } + public override void TraceEvent(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string? format, params object?[]? args) { } } public partial class TextWriterTraceListener : System.Diagnostics.TraceListener { @@ -56,7 +56,7 @@ public override void Fail(string? message, string? detailMessage) { } public override void TraceData(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, object? data) { } public override void TraceData(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, params object?[]? data) { } public override void TraceEvent(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string? message) { } - public override void TraceEvent(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string format, params object?[]? args) { } + public override void TraceEvent(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string? format, params object?[]? args) { } public override void TraceTransfer(System.Diagnostics.TraceEventCache? eventCache, string source, int id, string? message, System.Guid relatedActivityId) { } public override void Write(string? message) { } public override void WriteLine(string? message) { } diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs index 4397987761b29..6c399ae77bc40 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs @@ -86,7 +86,7 @@ public string Delimiter // warning would be hitted. protected override string[] GetSupportedAttributes() => new string[] { DelimiterKey }; - public override void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, string format, params object?[]? args) + public override void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, string? format, params object?[]? args) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, format, args, null, null)) return; @@ -94,7 +94,7 @@ public override void TraceEvent(TraceEventCache? eventCache, string source, Trac WriteHeader(source, eventType, id); if (args != null) - WriteEscaped(string.Format(CultureInfo.InvariantCulture, format, args)); + WriteEscaped(string.Format(CultureInfo.InvariantCulture, format!, args)); else WriteEscaped(format); Write(Delimiter); // Use get_Delimiter diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/XmlWriterTraceListener.cs b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/XmlWriterTraceListener.cs index 798968dfce17a..a4820d96289f9 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/XmlWriterTraceListener.cs +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/XmlWriterTraceListener.cs @@ -84,13 +84,13 @@ public override void Fail(string? message, string? detailMessage) })); } - public override void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, string format, params object?[]? args) + public override void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, string? format, params object?[]? args) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, format, args, null, null)) return; WriteHeader(source, eventType, id, eventCache); - WriteEscaped(args != null && args.Length != 0 ? string.Format(CultureInfo.InvariantCulture, format, args) : format); + WriteEscaped(args != null && args.Length != 0 ? string.Format(CultureInfo.InvariantCulture, format!, args) : format); WriteFooter(eventCache); } diff --git a/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs b/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs index d7e1a884de45b..62e82e3e09c3b 100644 --- a/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs +++ b/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs @@ -228,7 +228,7 @@ public virtual void TraceData(System.Diagnostics.TraceEventCache? eventCache, st public virtual void TraceData(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, params object?[]? data) { } public virtual void TraceEvent(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id) { } public virtual void TraceEvent(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string? message) { } - public virtual void TraceEvent(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string format, params object?[]? args) { } + public virtual void TraceEvent(System.Diagnostics.TraceEventCache? eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string? format, params object?[]? args) { } public virtual void TraceTransfer(System.Diagnostics.TraceEventCache? eventCache, string source, int id, string? message, System.Guid relatedActivityId) { } public virtual void Write(object? o) { } public virtual void Write(object? o, string? category) { } @@ -301,11 +301,11 @@ public void TraceEvent(System.Diagnostics.TraceEventType eventType, int id) { } [System.Diagnostics.ConditionalAttribute("TRACE")] public void TraceEvent(System.Diagnostics.TraceEventType eventType, int id, string? message) { } [System.Diagnostics.ConditionalAttribute("TRACE")] - public void TraceEvent(System.Diagnostics.TraceEventType eventType, int id, string format, params object?[]? args) { } + public void TraceEvent(System.Diagnostics.TraceEventType eventType, int id, string? format, params object?[]? args) { } [System.Diagnostics.ConditionalAttribute("TRACE")] - public void TraceInformation(string message) { } + public void TraceInformation(string? message) { } [System.Diagnostics.ConditionalAttribute("TRACE")] - public void TraceInformation(string format, params object?[]? args) { } + public void TraceInformation(string? format, params object?[]? args) { } [System.Diagnostics.ConditionalAttribute("TRACE")] public void TraceTransfer(int id, string? message, System.Guid relatedActivityId) { } } diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListener.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListener.cs index b19d1aa333abf..b32f885854543 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListener.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceListener.cs @@ -394,14 +394,14 @@ public virtual void TraceEvent(TraceEventCache? eventCache, string source, Trace WriteFooter(eventCache); } - public virtual void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, string format, params object?[]? args) + public virtual void TraceEvent(TraceEventCache? eventCache, string source, TraceEventType eventType, int id, string? format, params object?[]? args) { if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, format, args)) return; WriteHeader(source, eventType, id); if (args != null) - WriteLine(string.Format(CultureInfo.InvariantCulture, format, args)); + WriteLine(string.Format(CultureInfo.InvariantCulture, format!, args)); else WriteLine(format); diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs index 97c8d2912cfec..aa786154cbb56 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs @@ -260,7 +260,7 @@ public void TraceEvent(TraceEventType eventType, int id, string? message) } [Conditional("TRACE")] - public void TraceEvent(TraceEventType eventType, int id, string format, params object?[]? args) + public void TraceEvent(TraceEventType eventType, int id, string? format, params object?[]? args) { Initialize(); @@ -395,14 +395,14 @@ public void TraceData(TraceEventType eventType, int id, params object?[]? data) } [Conditional("TRACE")] - public void TraceInformation(string message) + public void TraceInformation(string? message) { // eventType= TraceEventType.Info, id=0 // No need to call Initialize() TraceEvent(TraceEventType.Information, 0, message, null); } [Conditional("TRACE")] - public void TraceInformation(string format, params object?[]? args) + public void TraceInformation(string? format, params object?[]? args) { // No need to call Initialize() TraceEvent(TraceEventType.Information, 0, format, args); From 62f6c0829d994781724a453600a339951f4c8fc7 Mon Sep 17 00:00:00 2001 From: Newell Clark Date: Fri, 5 Mar 2021 10:36:31 -0500 Subject: [PATCH 03/83] Add Memory Overrides to Streams (#47125) * System.IO.Compression.DeflateStream.CopyToStream -Implemented memory-based WriteAsync in DeflateStream.CopyToStream class. This required implementing a memory-based overload of System.IO.Inflater.SetInput(). Previously, Inflater used a GCHandle to pin the array that was passed into SetInput. I converted it to use a MemoryHandle, and changed the array-based overload of SetInput to delegate to the new Memory-based overload. * Implement suggested changes * Memorify RequestStream - Memory overrides for System.Net.RequestStream - Memory overrides for System.Net.NetworkStreamWrapper * Spanified ChunkedMemoryStream WriteAsync is implemented in terms of Write, so I went ahead and implemented Write(ReadOnlySpan). For some reason, AsSpan() isn't available in this file. * Apply suggested changes * Apply suggestions from code review Co-authored-by: Adam Sitnik --- .../src/System/IO/ChunkedMemoryStream.cs | 28 +++++++++++---- .../Compression/DeflateZLib/DeflateStream.cs | 25 +++++++++---- .../IO/Compression/DeflateZLib/Inflater.cs | 35 ++++++++++++------- .../src/System/Net/NetworkStreamWrapper.cs | 10 ++++++ .../src/System/Net/RequestStream.cs | 5 +++ 5 files changed, 79 insertions(+), 24 deletions(-) diff --git a/src/libraries/Common/src/System/IO/ChunkedMemoryStream.cs b/src/libraries/Common/src/System/IO/ChunkedMemoryStream.cs index 30f05d3f83b45..585ad878c2c1d 100644 --- a/src/libraries/Common/src/System/IO/ChunkedMemoryStream.cs +++ b/src/libraries/Common/src/System/IO/ChunkedMemoryStream.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using System; namespace System.IO { @@ -34,24 +35,28 @@ public byte[] ToArray() public override void Write(byte[] buffer, int offset, int count) { - while (count > 0) + Write(new ReadOnlySpan(buffer, offset, count)); + } + + public override void Write(ReadOnlySpan buffer) + { + while (!buffer.IsEmpty) { if (_currentChunk != null) { int remaining = _currentChunk._buffer.Length - _currentChunk._freeOffset; if (remaining > 0) { - int toCopy = Math.Min(remaining, count); - Buffer.BlockCopy(buffer, offset, _currentChunk._buffer, _currentChunk._freeOffset, toCopy); - count -= toCopy; - offset += toCopy; + int toCopy = Math.Min(remaining, buffer.Length); + buffer.Slice(0, toCopy).CopyTo(new Span(_currentChunk._buffer, _currentChunk._freeOffset, toCopy)); + buffer = buffer.Slice(toCopy); _totalLength += toCopy; _currentChunk._freeOffset += toCopy; continue; } } - AppendChunk(count); + AppendChunk(buffer.Length); } } @@ -66,6 +71,17 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati return Task.CompletedTask; } + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + { + if (cancellationToken.IsCancellationRequested) + { + return ValueTask.FromCanceled(cancellationToken); + } + + Write(buffer.Span); + return ValueTask.CompletedTask; + } + private void AppendChunk(long count) { int nextChunkLength = _currentChunk != null ? _currentChunk._buffer.Length * 2 : InitialChunkDefaultSize; diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs index c8cd4071f5bc0..d9739b087b704 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs @@ -907,25 +907,38 @@ public void CopyFromSourceToDestination() } } - public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { // Validate inputs Debug.Assert(buffer != _arrayPoolBuffer); _deflateStream.EnsureNotDisposed(); if (count <= 0) { - return; + return Task.CompletedTask; } else if (count > buffer.Length - offset) { // The buffer stream is either malicious or poorly implemented and returned a number of // bytes larger than the buffer supplied to it. - throw new InvalidDataException(SR.GenericInvalidData); + return Task.FromException(new InvalidDataException(SR.GenericInvalidData)); } - Debug.Assert(_deflateStream._inflater != null); - // Feed the data from base stream into the decompression engine. - _deflateStream._inflater.SetInput(buffer, offset, count); + return WriteAsyncCore(buffer.AsMemory(offset, count), cancellationToken).AsTask(); + } + + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + { + _deflateStream.EnsureNotDisposed(); + + return WriteAsyncCore(buffer, cancellationToken); + } + + private async ValueTask WriteAsyncCore(ReadOnlyMemory buffer, CancellationToken cancellationToken) + { + Debug.Assert(_deflateStream._inflater is not null); + + // Feed the data from base stream into decompression engine. + _deflateStream._inflater.SetInput(buffer); // While there's more decompressed data available, forward it to the buffer stream. while (!_deflateStream._inflater.Finished()) diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs index f6d17eb58559d..4544353ac5406 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/Inflater.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; @@ -20,7 +21,7 @@ internal sealed class Inflater : IDisposable private bool _isDisposed; // Prevents multiple disposals private readonly int _windowBits; // The WindowBits parameter passed to Inflater construction private ZLibNative.ZLibStreamHandle _zlibStream; // The handle to the primary underlying zlib stream - private GCHandle _inputBufferHandle; // The handle to the buffer that provides input to _zlibStream + private MemoryHandle _inputBufferHandle; // The handle to the buffer that provides input to _zlibStream private readonly long _uncompressedSize; private long _currentInflatedCount; @@ -110,7 +111,7 @@ public unsafe int InflateVerified(byte* bufPtr, int length) finally { // Before returning, make sure to release input buffer if necessary: - if (0 == _zlibStream.AvailIn && _inputBufferHandle.IsAllocated) + if (0 == _zlibStream.AvailIn && IsInputBufferHandleAllocated) { DeallocateInputBufferHandle(); } @@ -121,7 +122,7 @@ private unsafe void ReadOutput(byte* bufPtr, int length, out int bytesRead) { if (ReadInflateOutput(bufPtr, length, ZLibNative.FlushCode.NoFlush, out bytesRead) == ZLibNative.ErrorCode.StreamEnd) { - if (!NeedsInput() && IsGzipStream() && _inputBufferHandle.IsAllocated) + if (!NeedsInput() && IsGzipStream() && IsInputBufferHandleAllocated) { _finished = ResetStreamForLeftoverInput(); } @@ -142,7 +143,7 @@ private unsafe bool ResetStreamForLeftoverInput() { Debug.Assert(!NeedsInput()); Debug.Assert(IsGzipStream()); - Debug.Assert(_inputBufferHandle.IsAllocated); + Debug.Assert(IsInputBufferHandleAllocated); lock (SyncLock) { @@ -180,16 +181,24 @@ public void SetInput(byte[] inputBuffer, int startIndex, int count) Debug.Assert(NeedsInput(), "We have something left in previous input!"); Debug.Assert(inputBuffer != null); Debug.Assert(startIndex >= 0 && count >= 0 && count + startIndex <= inputBuffer.Length); - Debug.Assert(!_inputBufferHandle.IsAllocated); + Debug.Assert(!IsInputBufferHandleAllocated); - if (0 == count) + SetInput(inputBuffer.AsMemory(startIndex, count)); + } + + public unsafe void SetInput(ReadOnlyMemory inputBuffer) + { + Debug.Assert(NeedsInput(), "We have something left in previous input!"); + Debug.Assert(!IsInputBufferHandleAllocated); + + if (inputBuffer.IsEmpty) return; lock (SyncLock) { - _inputBufferHandle = GCHandle.Alloc(inputBuffer, GCHandleType.Pinned); - _zlibStream.NextIn = _inputBufferHandle.AddrOfPinnedObject() + startIndex; - _zlibStream.AvailIn = (uint)count; + _inputBufferHandle = inputBuffer.Pin(); + _zlibStream.NextIn = (IntPtr)_inputBufferHandle.Pointer; + _zlibStream.AvailIn = (uint)inputBuffer.Length; _finished = false; } } @@ -201,7 +210,7 @@ private void Dispose(bool disposing) if (disposing) _zlibStream.Dispose(); - if (_inputBufferHandle.IsAllocated) + if (IsInputBufferHandleAllocated) DeallocateInputBufferHandle(); _isDisposed = true; @@ -313,14 +322,16 @@ private ZLibNative.ErrorCode Inflate(ZLibNative.FlushCode flushCode) /// private void DeallocateInputBufferHandle() { - Debug.Assert(_inputBufferHandle.IsAllocated); + Debug.Assert(IsInputBufferHandleAllocated); lock (SyncLock) { _zlibStream.AvailIn = 0; _zlibStream.NextIn = ZLibNative.ZNullPtr; - _inputBufferHandle.Free(); + _inputBufferHandle.Dispose(); } } + + private unsafe bool IsInputBufferHandleAllocated => _inputBufferHandle.Pointer != default; } } diff --git a/src/libraries/System.Net.Requests/src/System/Net/NetworkStreamWrapper.cs b/src/libraries/System.Net.Requests/src/System/Net/NetworkStreamWrapper.cs index f4799c227ed4f..9f2cc673c5ffd 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/NetworkStreamWrapper.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/NetworkStreamWrapper.cs @@ -189,6 +189,11 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel return _networkStream.ReadAsync(buffer, offset, count, cancellationToken); } + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + { + return _networkStream.ReadAsync(buffer, cancellationToken); + } + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback? callback, object? state) { return _networkStream.BeginWrite(buffer, offset, size, callback, state); @@ -204,6 +209,11 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati return _networkStream.WriteAsync(buffer, offset, count, cancellationToken); } + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + { + return _networkStream.WriteAsync(buffer, cancellationToken); + } + public override void Flush() { _networkStream.Flush(); diff --git a/src/libraries/System.Net.Requests/src/System/Net/RequestStream.cs b/src/libraries/System.Net.Requests/src/System/Net/RequestStream.cs index d5f5a26fe85e1..5323c2ac836f0 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/RequestStream.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/RequestStream.cs @@ -105,6 +105,11 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati return _buffer.WriteAsync(buffer, offset, count, cancellationToken); } + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + { + return _buffer.WriteAsync(buffer, cancellationToken); + } + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? asyncCallback, object? asyncState) { ValidateBufferArguments(buffer, offset, count); From 87f25614176ce803bd43a177024ad8e4691e34fa Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 5 Mar 2021 10:55:56 -0500 Subject: [PATCH 04/83] Add debugger attributes for PriorityQueue (#49188) --- .../src/System.Collections.csproj | 1 + .../Collections/Generic/PriorityQueue.cs | 6 ++- .../Generic/PriorityQueueDebugView.cs | 38 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueueDebugView.cs diff --git a/src/libraries/System.Collections/src/System.Collections.csproj b/src/libraries/System.Collections/src/System.Collections.csproj index c8fd9f78b68ec..3011056121696 100644 --- a/src/libraries/System.Collections/src/System.Collections.csproj +++ b/src/libraries/System.Collections/src/System.Collections.csproj @@ -14,6 +14,7 @@ Link="Common\System\Collections\Generic\IDictionaryDebugView.cs" /> + diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs index 85c48ba9b88cc..554f7f0e84c40 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs @@ -13,6 +13,8 @@ namespace System.Collections.Generic /// /// The type of the element. /// The type of the priority. + [DebuggerDisplay("Count = {Count}")] + [DebuggerTypeProxy(typeof(PriorityQueueDebugView<,>))] public class PriorityQueue { /// @@ -677,9 +679,11 @@ private void MoveDownCustomComparer((TElement Element, TPriority Priority) node, /// /// Represents the contents of a without ordering. /// + [DebuggerDisplay("Count = {Count}")] + [DebuggerTypeProxy(typeof(PriorityQueueDebugView<,>))] public sealed class UnorderedItemsCollection : IReadOnlyCollection<(TElement Element, TPriority Priority)>, ICollection { - private readonly PriorityQueue _queue; + internal readonly PriorityQueue _queue; internal UnorderedItemsCollection(PriorityQueue queue) => _queue = queue; diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueueDebugView.cs b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueueDebugView.cs new file mode 100644 index 0000000000000..0a99e8c2b534f --- /dev/null +++ b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueueDebugView.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; + +namespace System.Collections.Generic +{ + internal sealed class PriorityQueueDebugView + { + private readonly PriorityQueue _queue; + private readonly bool _sort; + + public PriorityQueueDebugView(PriorityQueue queue) + { + _queue = queue ?? throw new ArgumentNullException(nameof(queue)); + _sort = true; + } + + public PriorityQueueDebugView(PriorityQueue.UnorderedItemsCollection collection) + { + _queue = collection?._queue ?? throw new ArgumentNullException(nameof(collection)); + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public (TElement Element, TPriority Priority)[] Items + { + get + { + var list = new List<(TElement Element, TPriority Priority)>(_queue.UnorderedItems); + if (_sort) + { + list.Sort((i1, i2) => _queue.Comparer.Compare(i1.Priority, i2.Priority)); + } + return list.ToArray(); + } + } + } +} From f46bb21a4780bde18d0b6d34683efd1cee3276de Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 5 Mar 2021 10:56:55 -0500 Subject: [PATCH 05/83] Fix nullable attributes on ProcessStartInfo (#49175) --- .../ref/System.Diagnostics.Process.cs | 6 ++++++ .../src/System/Diagnostics/ProcessStartInfo.Unix.cs | 9 +++++---- .../src/System/Diagnostics/ProcessStartInfo.Windows.cs | 4 +++- .../src/System/Diagnostics/ProcessStartInfo.cs | 6 ++++++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs b/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs index 3ff66cd763934..599378b6ea04d 100644 --- a/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs +++ b/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs @@ -167,9 +167,11 @@ public ProcessStartInfo() { } public ProcessStartInfo(string fileName) { } public ProcessStartInfo(string fileName, string arguments) { } public System.Collections.ObjectModel.Collection ArgumentList { get { throw null; } } + [System.Diagnostics.CodeAnalysis.AllowNullAttribute] public string Arguments { get { throw null; } set { } } public bool CreateNoWindow { get { throw null; } set { } } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + [System.Diagnostics.CodeAnalysis.AllowNullAttribute] public string Domain { get { throw null; } set { } } public System.Collections.Generic.IDictionary Environment { get { throw null; } } [System.ComponentModel.EditorAttribute("System.Diagnostics.Design.StringDictionaryEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] @@ -177,6 +179,7 @@ public ProcessStartInfo(string fileName, string arguments) { } public bool ErrorDialog { get { throw null; } set { } } public System.IntPtr ErrorDialogParentHandle { get { throw null; } set { } } [System.ComponentModel.EditorAttribute("System.Diagnostics.Design.StartFileNameEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] + [System.Diagnostics.CodeAnalysis.AllowNullAttribute] public string FileName { get { throw null; } set { } } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public bool LoadUserProfile { get { throw null; } set { } } @@ -191,14 +194,17 @@ public ProcessStartInfo(string fileName, string arguments) { } public System.Text.Encoding? StandardErrorEncoding { get { throw null; } set { } } public System.Text.Encoding? StandardInputEncoding { get { throw null; } set { } } public System.Text.Encoding? StandardOutputEncoding { get { throw null; } set { } } + [System.Diagnostics.CodeAnalysis.AllowNullAttribute] public string UserName { get { throw null; } set { } } public bool UseShellExecute { get { throw null; } set { } } [System.ComponentModel.DefaultValueAttribute("")] + [System.Diagnostics.CodeAnalysis.AllowNullAttribute] public string Verb { get { throw null; } set { } } public string[] Verbs { get { throw null; } } [System.ComponentModel.DefaultValueAttribute(System.Diagnostics.ProcessWindowStyle.Normal)] public System.Diagnostics.ProcessWindowStyle WindowStyle { get { throw null; } set { } } [System.ComponentModel.EditorAttribute("System.Diagnostics.Design.WorkingDirectoryEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] + [System.Diagnostics.CodeAnalysis.AllowNullAttribute] public string WorkingDirectory { get { throw null; } set { } } } [System.ComponentModel.DesignerAttribute("System.Diagnostics.Design.ProcessThreadDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Unix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Unix.cs index 380b6ad0fcfd0..bcfa52548a99e 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Unix.cs @@ -1,9 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Security; +using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; +using System.Security; namespace System.Diagnostics { @@ -13,13 +13,14 @@ namespace System.Diagnostics public sealed partial class ProcessStartInfo { [SupportedOSPlatform("windows")] - public string PasswordInClearText + public string? PasswordInClearText { get { throw new PlatformNotSupportedException(SR.Format(SR.ProcessStartSingleFeatureNotSupported, nameof(PasswordInClearText))); } set { throw new PlatformNotSupportedException(SR.Format(SR.ProcessStartSingleFeatureNotSupported, nameof(PasswordInClearText))); } } [SupportedOSPlatform("windows")] + [AllowNull] public string Domain { get { throw new PlatformNotSupportedException(SR.Format(SR.ProcessStartSingleFeatureNotSupported, nameof(Domain))); } @@ -39,7 +40,7 @@ public bool LoadUserProfile [CLSCompliant(false)] [SupportedOSPlatform("windows")] - public SecureString Password + public SecureString? Password { get { throw new PlatformNotSupportedException(SR.Format(SR.ProcessStartSingleFeatureNotSupported, nameof(Password))); } set { throw new PlatformNotSupportedException(SR.Format(SR.ProcessStartSingleFeatureNotSupported, nameof(Password))); } diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Windows.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Windows.cs index c66ea64cfcd4d..b80b61326983e 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Windows.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Windows.cs @@ -1,8 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Security; +using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; +using System.Security; namespace System.Diagnostics { @@ -14,6 +15,7 @@ public sealed partial class ProcessStartInfo public string? PasswordInClearText { get; set; } [SupportedOSPlatform("windows")] + [AllowNull] public string Domain { get => _domain ?? string.Empty; diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs index 49ff18d43ec6f..761f1cd3b46d0 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs @@ -6,6 +6,7 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Text; namespace System.Diagnostics @@ -57,6 +58,7 @@ public ProcessStartInfo(string fileName, string arguments) /// /// Specifies the set of command line arguments to use when starting the application. /// + [AllowNull] public string Arguments { get => _arguments ?? string.Empty; @@ -115,6 +117,7 @@ public string Arguments /// [Editor("System.Diagnostics.Design.StartFileNameEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] + [AllowNull] public string FileName { get => _fileName ?? string.Empty; @@ -127,6 +130,7 @@ public string FileName /// [Editor("System.Diagnostics.Design.WorkingDirectoryEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] + [AllowNull] public string WorkingDirectory { get => _directory ?? string.Empty; @@ -136,6 +140,7 @@ public string WorkingDirectory public bool ErrorDialog { get; set; } public IntPtr ErrorDialogParentHandle { get; set; } + [AllowNull] public string UserName { get => _userName ?? string.Empty; @@ -143,6 +148,7 @@ public string UserName } [DefaultValue("")] + [AllowNull] public string Verb { get => _verb ?? string.Empty; From 7665d4a9a42d94f89a7f66b3fded9939e2ce09b1 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 5 Mar 2021 08:08:37 -0800 Subject: [PATCH 06/83] Delete unused define (#49190) --- .../src/System.Threading.Tasks.Parallel.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj b/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj index 84566e7f073db..fc06ab309921c 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj +++ b/src/libraries/System.Threading.Tasks.Parallel/src/System.Threading.Tasks.Parallel.csproj @@ -1,6 +1,5 @@ - $(DefineConstants);FEATURE_TRACING true $(NetCoreAppCurrent) enable From 7e658d7e22e9e05aa91b34b96f8cc1f03a98255f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Fri, 5 Mar 2021 17:10:21 +0100 Subject: [PATCH 07/83] [main] Update dependencies from dotnet/llvm-project (#49208) runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.win-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.osx.10.12-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk , runtime.linux-x64.Microsoft.NETCore.Runtime.Mono.LLVM.Tools From Version 9.0.1-alpha.1.21151.1 -> To Version 9.0.1-alpha.1.21154.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 32 ++++++++++++++++---------------- eng/Versions.props | 16 ++++++++-------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0d73e7e91cffc..be496d19a6417 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -130,37 +130,37 @@ https://github.com/dotnet/runtime-assets ad3e62eb902b7ab02a12ea40d35e0d35e067afe3 - + https://github.com/dotnet/llvm-project - 380f74637f22577be108919689a6536b395b4a3e + f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf - + https://github.com/dotnet/llvm-project - 380f74637f22577be108919689a6536b395b4a3e + f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf - + https://github.com/dotnet/llvm-project - 380f74637f22577be108919689a6536b395b4a3e + f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf - + https://github.com/dotnet/llvm-project - 380f74637f22577be108919689a6536b395b4a3e + f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf - + https://github.com/dotnet/llvm-project - 380f74637f22577be108919689a6536b395b4a3e + f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf - + https://github.com/dotnet/llvm-project - 380f74637f22577be108919689a6536b395b4a3e + f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf - + https://github.com/dotnet/llvm-project - 380f74637f22577be108919689a6536b395b4a3e + f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf - + https://github.com/dotnet/llvm-project - 380f74637f22577be108919689a6536b395b4a3e + f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index 15d7235ef41e8..27dbe8e98f172 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -159,14 +159,14 @@ 6.0.0-preview.3.21151.1 - 9.0.1-alpha.1.21151.1 - 9.0.1-alpha.1.21151.1 - 9.0.1-alpha.1.21151.1 - 9.0.1-alpha.1.21151.1 - 9.0.1-alpha.1.21151.1 - 9.0.1-alpha.1.21151.1 - 9.0.1-alpha.1.21151.1 - 9.0.1-alpha.1.21151.1 + 9.0.1-alpha.1.21154.1 + 9.0.1-alpha.1.21154.1 + 9.0.1-alpha.1.21154.1 + 9.0.1-alpha.1.21154.1 + 9.0.1-alpha.1.21154.1 + 9.0.1-alpha.1.21154.1 + 9.0.1-alpha.1.21154.1 + 9.0.1-alpha.1.21154.1 From 04ff9bd1c1cdd0046af652c74821e73668207cac Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Fri, 5 Mar 2021 08:22:20 -0800 Subject: [PATCH 08/83] Fix stress apple arm64 assertion '(thisFieldOffset + EA_SIZE_IN_BYTES(attr)) <= areaSize' (#48936) * Fix a stress Arm64 apple issue. * fix issue. --- src/coreclr/jit/codegenarm64.cpp | 9 +-------- src/coreclr/jit/codegenlinear.cpp | 31 ++++++++++++++++++++++--------- src/coreclr/jit/emitarm64.h | 26 ++++++++++++++++++++++++++ src/coreclr/jit/lsraarmarch.cpp | 14 ++++++++++++-- src/coreclr/jit/lsrabuild.cpp | 3 ++- 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index a92367389bc72..737db8dc424a6 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -4821,14 +4821,7 @@ void CodeGen::genStoreLclTypeSIMD12(GenTree* treeNode) // Need an additional integer register to extract upper 4 bytes from data. regNumber tmpReg = lclVar->GetSingleTempReg(); - // store lower 8 bytes - GetEmitter()->emitIns_S_R(INS_str, EA_8BYTE, operandReg, varNum, offs); - - // Extract upper 4-bytes from data - GetEmitter()->emitIns_R_R_I(INS_mov, EA_4BYTE, tmpReg, operandReg, 2); - - // 4-byte write - GetEmitter()->emitIns_S_R(INS_str, EA_4BYTE, tmpReg, varNum, offs + 8); + GetEmitter()->emitStoreSIMD12ToLclOffset(varNum, offs, operandReg, tmpReg); } #endif // FEATURE_SIMD diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index 215e3c04f75b5..4260548d9ab14 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1841,20 +1841,33 @@ void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk, unsigned outArg // Evaluate each of the GT_FIELD_LIST items into their register // and store their register into the outgoing argument area. - unsigned argOffset = putArgStk->getArgOffset(); + const unsigned argOffset = putArgStk->getArgOffset(); for (GenTreeFieldList::Use& use : putArgStk->gtOp1->AsFieldList()->Uses()) { GenTree* nextArgNode = use.GetNode(); genConsumeReg(nextArgNode); - regNumber reg = nextArgNode->GetRegNum(); - var_types type = nextArgNode->TypeGet(); - emitAttr attr = emitTypeSize(type); + regNumber reg = nextArgNode->GetRegNum(); + var_types type = use.GetType(); + unsigned thisFieldOffset = argOffset + use.GetOffset(); - // Emit store instructions to store the registers produced by the GT_FIELD_LIST into the outgoing - // argument area. - unsigned thisFieldOffset = argOffset + use.GetOffset(); - GetEmitter()->emitIns_S_R(ins_Store(type), attr, reg, outArgVarNum, thisFieldOffset); +// Emit store instructions to store the registers produced by the GT_FIELD_LIST into the outgoing +// argument area. + +#if defined(FEATURE_SIMD) && defined(OSX_ARM64_ABI) + // storing of TYP_SIMD12 (i.e. Vector3) argument. + if (type == TYP_SIMD12) + { + // Need an additional integer register to extract upper 4 bytes from data. + regNumber tmpReg = nextArgNode->GetSingleTempReg(); + GetEmitter()->emitStoreSIMD12ToLclOffset(outArgVarNum, thisFieldOffset, reg, tmpReg); + } + else +#endif // FEATURE_SIMD && OSX_ARM64_ABI + { + emitAttr attr = emitTypeSize(type); + GetEmitter()->emitIns_S_R(ins_Store(type), attr, reg, outArgVarNum, thisFieldOffset); + } // We can't write beyond the arg area unless this is a tail call, in which case we use // the first stack arg as the base of the incoming arg area. @@ -1867,7 +1880,7 @@ void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk, unsigned outArg } #endif - assert((thisFieldOffset + EA_SIZE_IN_BYTES(attr)) <= areaSize); + assert((thisFieldOffset + genTypeSize(type)) <= areaSize); #endif } } diff --git a/src/coreclr/jit/emitarm64.h b/src/coreclr/jit/emitarm64.h index 8b8c812aacfc4..2ab236282623c 100644 --- a/src/coreclr/jit/emitarm64.h +++ b/src/coreclr/jit/emitarm64.h @@ -935,4 +935,30 @@ inline bool emitIsLoadConstant(instrDesc* jmp) (jmp->idInsFmt() == IF_LARGELDC)); } +#if defined(FEATURE_SIMD) +//----------------------------------------------------------------------------------- +// emitStoreSIMD12ToLclOffset: store SIMD12 value from opReg to varNum+offset. +// +// Arguments: +// varNum - the variable on the stack to use as a base; +// offset - the offset from the varNum; +// opReg - the src reg with SIMD12 value; +// tmpReg - a tmp reg to use for the write, can be general or float. +// +void emitStoreSIMD12ToLclOffset(unsigned varNum, unsigned offset, regNumber opReg, regNumber tmpReg) +{ + assert(varNum != BAD_VAR_NUM); + assert(isVectorRegister(opReg)); + + // store lower 8 bytes + emitIns_S_R(INS_str, EA_8BYTE, opReg, varNum, offset); + + // Extract upper 4-bytes from data + emitIns_R_R_I(INS_mov, EA_4BYTE, tmpReg, opReg, 2); + + // 4-byte write + emitIns_S_R(INS_str, EA_4BYTE, tmpReg, varNum, offset + 8); +} +#endif // FEATURE_SIMD + #endif // TARGET_ARM64 diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index 59d64329b4562..8fb7ca7992f4b 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -398,11 +398,11 @@ int LinearScan::BuildPutArgStk(GenTreePutArgStk* argNode) int srcCount = 0; // Do we have a TYP_STRUCT argument (or a GT_FIELD_LIST), if so it must be a multireg pass-by-value struct - if ((putArgChild->TypeGet() == TYP_STRUCT) || (putArgChild->OperGet() == GT_FIELD_LIST)) + if (putArgChild->TypeIs(TYP_STRUCT) || putArgChild->OperIs(GT_FIELD_LIST)) { // We will use store instructions that each write a register sized value - if (putArgChild->OperGet() == GT_FIELD_LIST) + if (putArgChild->OperIs(GT_FIELD_LIST)) { assert(putArgChild->isContained()); // We consume all of the items in the GT_FIELD_LIST @@ -410,6 +410,16 @@ int LinearScan::BuildPutArgStk(GenTreePutArgStk* argNode) { BuildUse(use.GetNode()); srcCount++; + +#if defined(FEATURE_SIMD) && defined(OSX_ARM64_ABI) + if (use.GetType() == TYP_SIMD12) + { + // Vector3 is read/written as two reads/writes: 8 byte and 4 byte. + // To assemble the vector properly we would need an additional int register. + // The other platforms can write it as 16-byte using 1 write. + buildInternalIntRegisterDefForNode(use.GetNode()); + } +#endif // FEATURE_SIMD && OSX_ARM64_ABI } } else diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 88430f70fe771..f8c9948d8190b 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -3342,7 +3342,8 @@ int LinearScan::BuildStoreLoc(GenTreeLclVarCommon* storeLoc) RefPosition* internalFloatDef = nullptr; if (varTypeIsSIMD(storeLoc) && !op1->IsCnsIntOrI() && (storeLoc->TypeGet() == TYP_SIMD12)) { - // Need an additional register to extract upper 4 bytes of Vector3. + // Need an additional register to extract upper 4 bytes of Vector3, + // it has to be float for x86. internalFloatDef = buildInternalFloatRegisterDefForNode(storeLoc, allSIMDRegs()); } #endif // FEATURE_SIMD From 630d47873dc36736aafe6ab17129c9e36311e3bf Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Fri, 5 Mar 2021 18:42:25 +0100 Subject: [PATCH 09/83] Fix code coverage instrumentation and representation (#49181) When upgrading to the 6.0 SDK, the "dotnet tool run" command doesn't work anymore with passing in arguments. Instead using the short form which is just dotnet . Also disabling code coverage collection for .NETFramework as it isn't supported. --- eng/testing/coverage.targets | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/testing/coverage.targets b/eng/testing/coverage.targets index 6f8ac2648f06e..02426851c0bc6 100644 --- a/eng/testing/coverage.targets +++ b/eng/testing/coverage.targets @@ -37,17 +37,17 @@ + Condition="'$(Coverage)' == 'true' and '$(TargetFrameworkIdentifier)' == '.NETCoreApp'"> coverage.opencover.xml $(CoverageOutputPath) $([MSBuild]::NormalizeDirectory('$(OutDir)', 'report')) - "$(DotNetTool)" tool run coverlet "$(TargetFileName)" --target "$(RunScriptHost)" --targetargs "$(RunScriptCommand.Replace('"$(RunScriptHost)"', ''))" --format "opencover" --output "$(CoverageOutputPath)" --verbosity "normal" --use-source-link + "$(DotNetTool)" coverlet "$(TargetFileName)" --target "$(RunScriptHost)" --targetargs "$(RunScriptCommand.Replace('"$(RunScriptHost)"', ''))" --format "opencover" --output "$(CoverageOutputPath)" --verbosity "normal" --use-source-link $(RunScriptCommand) --exclude-by-file @(CoverageExcludeByFile -> '"%(Identity)"', ' --exclude-by-file ') $(RunScriptCommand) --include-directory @(CoverageIncludeDirectory -> '"$(RunScriptHostDir)%(Identity)"', ' --include-directory ') $(RunScriptCommand) --include @(CoverageInclude -> '"[%(Identity)]*"', ' --include ') - "$(DotNetTool)" tool run reportgenerator "-reports:$(CoverageReportInputPath)" "-targetdir:$(CoverageReportDir.TrimEnd('\/'))" "-reporttypes:Html" "-verbosity:Info" + "$(DotNetTool)" reportgenerator "-reports:$(CoverageReportInputPath)" "-targetdir:$(CoverageReportDir.TrimEnd('\/'))" "-reporttypes:Html" "-verbosity:Info" @@ -69,7 +69,7 @@ Html Info $([MSBuild]::NormalizeDirectory('$(OutDir)', 'TestResults', 'report')) - "$(DotNetTool)" tool run reportgenerator "-reports:$(CoverageReportInputPath)" "-targetdir:$(CoverageReportDir.TrimEnd('\/'))" "-reporttypes:$(CoverageReportTypes)" "-verbosity:$(CoverageReportVerbosity)" + "$(DotNetTool)" reportgenerator "-reports:$(CoverageReportInputPath)" "-targetdir:$(CoverageReportDir.TrimEnd('\/'))" "-reporttypes:$(CoverageReportTypes)" "-verbosity:$(CoverageReportVerbosity)" From b6050d2b4668162a4da2f3ecbd45065442d1a23f Mon Sep 17 00:00:00 2001 From: Steve MacLean Date: Fri, 5 Mar 2021 12:52:06 -0500 Subject: [PATCH 10/83] Disable IsAtLeastLibgdiplus6 for Apple Silicon (#49173) * Disable IsAtLeastLibgdiplus6 if !IsDrawingSupported * PR feedback --- src/libraries/System.Drawing.Common/tests/GdiplusTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Drawing.Common/tests/GdiplusTests.cs b/src/libraries/System.Drawing.Common/tests/GdiplusTests.cs index 286227b86d086..4e885b2d99dfc 100644 --- a/src/libraries/System.Drawing.Common/tests/GdiplusTests.cs +++ b/src/libraries/System.Drawing.Common/tests/GdiplusTests.cs @@ -8,6 +8,7 @@ namespace System.Drawing.Tests public class GdiplusTests { [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsOSX))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49111", typeof(PlatformDetection), nameof(PlatformDetection.IsNotMacOsAppleSilicon))] public void IsAtLeastLibgdiplus6() { Assert.True(Helpers.GetIsWindowsOrAtLeastLibgdiplus6()); From bd7630dee87742594f1d8ec40cb5116c8b34528b Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Fri, 5 Mar 2021 09:52:49 -0800 Subject: [PATCH 11/83] Remove the exclusion for a fixed test. (#49223) --- src/tests/issues.targets | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 48df18ebf8006..8cbaa5e5cacbd 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -715,9 +715,6 @@ https://github.com/dotnet/runtime/issues/47294 - - https://github.com/dotnet/runtime/issues/48787 - https://github.com/dotnet/runtime/issues/48791 From a6ac510cb238b322d8ca21d71b6270f586f4d785 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Fri, 5 Mar 2021 12:53:53 -0800 Subject: [PATCH 12/83] [AndroidCrypto] Make RC2 transform explicitly throw PlatformNotSupportedException (#49195) --- .../pal_cipher.c | 40 ++----------------- .../pal_cipher.h | 2 - .../Cryptography/RC2Implementation.Android.cs | 26 ++++++++++++ .../src/Resources/Strings.resx | 3 ++ ...em.Security.Cryptography.Algorithms.csproj | 3 +- 5 files changed, 35 insertions(+), 39 deletions(-) create mode 100644 src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Android.cs diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.c index f9c624aa83076..99b2fd59131cd 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.c @@ -7,9 +7,8 @@ enum { CIPHER_NONE = 0, - CIPHER_IS_SUPPORTED = 1, - CIPHER_HAS_TAG = 2, - CIPHER_REQUIRES_IV = 4, + CIPHER_HAS_TAG = 1, + CIPHER_REQUIRES_IV = 2, }; typedef uint32_t CipherFlags; @@ -23,14 +22,7 @@ typedef struct CipherInfo #define DEFINE_CIPHER(cipherId, width, javaName, flags) \ CipherInfo* AndroidCryptoNative_ ## cipherId() \ { \ - static CipherInfo info = { flags | CIPHER_IS_SUPPORTED, width, javaName }; \ - return &info; \ -} - -#define DEFINE_UNSUPPORTED_CIPHER(cipherId) \ -CipherInfo* AndroidCryptoNative_ ## cipherId() \ -{ \ - static CipherInfo info = { CIPHER_NONE, 0, NULL }; \ + static CipherInfo info = { flags, width, javaName }; \ return &info; \ } @@ -59,14 +51,6 @@ DEFINE_CIPHER(Des3Ecb, 128, "DESede/ECB/NoPadding", CIPHER_NONE) DEFINE_CIPHER(Des3Cbc, 128, "DESede/CBC/NoPadding", CIPHER_REQUIRES_IV) DEFINE_CIPHER(Des3Cfb8, 128, "DESede/CFB8/NoPadding", CIPHER_REQUIRES_IV) DEFINE_CIPHER(Des3Cfb64, 128, "DESede/CFB/NoPadding", CIPHER_REQUIRES_IV) -DEFINE_UNSUPPORTED_CIPHER(RC2Ecb) -DEFINE_UNSUPPORTED_CIPHER(RC2Cbc) - - -static bool IsSupported(CipherInfo* type) -{ - return (type->flags & CIPHER_IS_SUPPORTED) == CIPHER_IS_SUPPORTED; -} static bool HasTag(CipherInfo* type) { @@ -78,24 +62,8 @@ static bool RequiresIV(CipherInfo* type) return (type->flags & CIPHER_REQUIRES_IV) == CIPHER_REQUIRES_IV; } -static int32_t GetAlgorithmDefaultWidth(CipherInfo* type) -{ - if (!IsSupported(type)) - { - assert(false); - return FAIL; - } - return type->width; -} - static jobject GetAlgorithmName(JNIEnv* env, CipherInfo* type) { - if (!IsSupported(type)) - { - LOG_ERROR("This cipher is not supported"); - assert(false); - return FAIL; - } return JSTRING(type->name); } @@ -118,7 +86,7 @@ CipherCtx* AndroidCryptoNative_CipherCreatePartial(CipherInfo* type) ctx->cipher = cipher; ctx->type = type; ctx->tagLength = TAG_MAX_LENGTH; - ctx->keySizeInBits = GetAlgorithmDefaultWidth(type); + ctx->keySizeInBits = type->width; ctx->ivLength = 0; ctx->encMode = 0; ctx->key = NULL; diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.h index 0a79c488dcdf9..b9b9e1e45e29b 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.h @@ -60,5 +60,3 @@ PALEXPORT CipherInfo* AndroidCryptoNative_Des3Cfb64(void); PALEXPORT CipherInfo* AndroidCryptoNative_DesEcb(void); PALEXPORT CipherInfo* AndroidCryptoNative_DesCfb8(void); PALEXPORT CipherInfo* AndroidCryptoNative_DesCbc(void); -PALEXPORT CipherInfo* AndroidCryptoNative_RC2Ecb(void); -PALEXPORT CipherInfo* AndroidCryptoNative_RC2Cbc(void); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Android.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Android.cs new file mode 100644 index 0000000000000..fa5604a71262c --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Android.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Security.Cryptography; + +namespace Internal.Cryptography +{ + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "We are providing the implementation for RC2, not consuming it.")] + internal sealed partial class RC2Implementation : RC2 + { + private static ICryptoTransform CreateTransformCore( + CipherMode cipherMode, + PaddingMode paddingMode, + byte[] key, + int effectiveKeyLength, + byte[]? iv, + int blockSize, + int feedbackSizeInBytes, + int paddingSize, + bool encrypting) + { + throw new PlatformNotSupportedException(SR.Format(SR.Cryptography_AlgorithmNotSupported, nameof(RC2))); + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx index a0008c802c991..9d07bd5d7367f 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx @@ -96,6 +96,9 @@ The KDF for algorithm '{0}' requires a char-based password input. + + Algorithm '{0}' is not supported on this platform. + The keys from both parties must be the same size to generate a secret agreement. diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj index c05dd9a412200..465a7575d3e47 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj @@ -482,7 +482,6 @@ - @@ -606,6 +605,7 @@ Link="Common\Microsoft\Win32\SafeHandles\SafeRsaHandle.Unix.cs" /> + @@ -639,6 +639,7 @@ Link="Common\System\Security\Cryptography\ECDsaAndroid.cs" /> + From 197ce0fc3ab773dbe5e0a7b89364c516ae82a556 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 5 Mar 2021 13:05:32 -0800 Subject: [PATCH 13/83] Capture Reverse P/Invoke frame offset in x86 GC info and disallow return hijacking of reverse P/Invokes on x86. (#49066) * Capture Reverse P/Invoke frame offset in x86 GC info and disallow return hijacking of reverse P/Invokes on x86. * Check reverse p/invoke frame in exception handling. * Fix formatting. * Change sentinel values since 0 is a valid offset for the reverse P/Invoke frame variable. * Fix decoding setting flip to actually flip the new sentinel values. --- src/coreclr/inc/eetwain.h | 4 ++++ src/coreclr/inc/gcdecoder.cpp | 2 +- src/coreclr/inc/gcinfotypes.h | 6 ++++-- src/coreclr/jit/gcencode.cpp | 16 ++++++++++++++ src/coreclr/vm/eetwain.cpp | 12 ++++++++--- src/coreclr/vm/exceptionhandling.cpp | 32 ++++++++++++++++++++++++++-- 6 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/coreclr/inc/eetwain.h b/src/coreclr/inc/eetwain.h index dd3e430f59d3d..b7f288b0cdb27 100644 --- a/src/coreclr/inc/eetwain.h +++ b/src/coreclr/inc/eetwain.h @@ -654,6 +654,10 @@ bool UnwindStackFrame(PREGDISPLAY pContext, unsigned flags, CodeManState *pState, StackwalkCacheUnwindInfo *pUnwindInfo); + +size_t DecodeGCHdrInfo(GCInfoToken gcInfoToken, + unsigned curOffset, + hdrInfo * infoPtr); #endif /***************************************************************************** diff --git a/src/coreclr/inc/gcdecoder.cpp b/src/coreclr/inc/gcdecoder.cpp index 3d929ec7e1146..73873acc2540d 100644 --- a/src/coreclr/inc/gcdecoder.cpp +++ b/src/coreclr/inc/gcdecoder.cpp @@ -197,7 +197,7 @@ PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header header->syncStartOffset ^= HAS_SYNC_OFFSET; break; case FLIP_REV_PINVOKE_FRAME: - header->revPInvokeOffset ^= HAS_REV_PINVOKE_FRAME_OFFSET; + header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET ? HAS_REV_PINVOKE_FRAME_OFFSET : INVALID_REV_PINVOKE_OFFSET; break; case NEXT_OPCODE: diff --git a/src/coreclr/inc/gcinfotypes.h b/src/coreclr/inc/gcinfotypes.h index 65506d5cbc179..2ac8902283de6 100644 --- a/src/coreclr/inc/gcinfotypes.h +++ b/src/coreclr/inc/gcinfotypes.h @@ -421,8 +421,10 @@ enum infoHdrAdjust2 { #define HAS_UNTRACKED ((unsigned int) -1) #define HAS_VARPTR ((unsigned int) -1) -#define INVALID_REV_PINVOKE_OFFSET 0 -#define HAS_REV_PINVOKE_FRAME_OFFSET ((unsigned int) -1) +// 0 is a valid offset for the Reverse P/Invoke block +// So use -1 as the sentinel for invalid and -2 as the sentinel for present. +#define INVALID_REV_PINVOKE_OFFSET ((unsigned int) -1) +#define HAS_REV_PINVOKE_FRAME_OFFSET ((unsigned int) -2) // 0 is not a valid offset for EBP-frames as all locals are at a negative offset // For ESP frames, the cookie is above (at a higher address than) the buffers, // and so cannot be at offset 0. diff --git a/src/coreclr/jit/gcencode.cpp b/src/coreclr/jit/gcencode.cpp index bfe9dbe3ee918..9ce6456a391cc 100644 --- a/src/coreclr/jit/gcencode.cpp +++ b/src/coreclr/jit/gcencode.cpp @@ -1623,6 +1623,13 @@ size_t GCInfo::gcInfoBlockHdrSave( #endif header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET; + if (compiler->opts.IsReversePInvoke()) + { + assert(compiler->lvaReversePInvokeFrameVar != BAD_VAR_NUM); + int stkOffs = compiler->lvaTable[compiler->lvaReversePInvokeFrameVar].GetStackOffset(); + header->revPInvokeOffset = compiler->isFramePointerUsed() ? -stkOffs : stkOffs; + assert(header->revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET); + } assert((compiler->compArgSize & 0x3) == 0); @@ -1726,6 +1733,15 @@ size_t GCInfo::gcInfoBlockHdrSave( } } + if (header->revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET) + { + assert(mask == 0 || state.revPInvokeOffset == HAS_REV_PINVOKE_FRAME_OFFSET); + unsigned offset = header->revPInvokeOffset; + unsigned sz = encodeUnsigned(mask ? dest : NULL, offset); + size += sz; + dest += (sz & mask); + } + if (header->epilogCount) { /* Generate table unless one epilog at the end of the method */ diff --git a/src/coreclr/vm/eetwain.cpp b/src/coreclr/vm/eetwain.cpp index 77d231ceb5afe..5c48a13535336 100644 --- a/src/coreclr/vm/eetwain.cpp +++ b/src/coreclr/vm/eetwain.cpp @@ -157,9 +157,9 @@ __forceinline int decodeSigned(PTR_CBYTE& src) * computation of PrologOffs/EpilogOffs. * Returns the size of the header (number of bytes decoded). */ -static size_t DecodeGCHdrInfo(GCInfoToken gcInfoToken, - unsigned curOffset, - hdrInfo * infoPtr) +size_t DecodeGCHdrInfo(GCInfoToken gcInfoToken, + unsigned curOffset, + hdrInfo * infoPtr) { CONTRACTL { NOTHROW; @@ -5892,6 +5892,12 @@ bool EECodeManager::GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKi DecodeGCHdrInfo(gcInfoToken, 0, &info); + if (info.revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET) + { + // Hijacking of UnmanagedCallersOnly method is not allowed + return false; + } + *returnKind = info.returnKind; return true; #else // !USE_GC_INFO_DECODER diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 7c3f935fe2d6b..478eb2c7a42f6 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -1202,12 +1202,12 @@ lExit: ; if ((ExceptionContinueSearch == returnDisposition)) { -#ifdef USE_GC_INFO_DECODER if (dwExceptionFlags & EXCEPTION_UNWINDING) { EECodeInfo codeInfo(pDispatcherContext->ControlPc); if (codeInfo.IsValid()) { +#ifdef USE_GC_INFO_DECODER GcInfoDecoder gcInfoDecoder(codeInfo.GetGCInfoToken(), DECODE_REVERSE_PINVOKE_VAR); if (gcInfoDecoder.GetReversePInvokeFrameStackSlot() != NO_REVERSE_PINVOKE_FRAME) { @@ -1216,9 +1216,21 @@ lExit: ; bool fIsSO = pExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW; CleanUpForSecondPass(pThread, fIsSO, (void*)MemoryStackFp, (void*)MemoryStackFp); } +#else // USE_GC_INFO_DECODER + hdrInfo gcHdrInfo; + + DecodeGCHdrInfo(gcInfoToken, 0, &gcHdrInfo); + + if (gcHdrInfo.revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET) + { + // Exception is being propagated from a method marked UnmanagedCallersOnlyAttribute into its native caller. + // The explicit frame chain needs to be unwound at this boundary. + bool fIsSO = pExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW; + CleanUpForSecondPass(pThread, fIsSO, (void*)MemoryStackFp, (void*)MemoryStackFp); + } +#endif // USE_GC_INFO_DECODER } } -#endif // USE_GC_INFO_DECODER GCX_PREEMP_NO_DTOR(); } @@ -4571,6 +4583,22 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT CrashDumpAndTerminateProcess(1); UNREACHABLE(); } +#else // USE_GC_INFO_DECODER + hdrInfo gcHdrInfo; + + DecodeGCHdrInfo(gcInfoToken, 0, &gcHdrInfo); + + if (gcHdrInfo.revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET) + { + // Propagating exception from a method marked by UnmanagedCallersOnly attribute is prohibited on Unix + if (!GetThread()->HasThreadStateNC(Thread::TSNC_ProcessedUnhandledException)) + { + LONG disposition = InternalUnhandledExceptionFilter_Worker(&ex.ExceptionPointers); + _ASSERTE(disposition == EXCEPTION_CONTINUE_SEARCH); + } + CrashDumpAndTerminateProcess(1); + UNREACHABLE(); + } #endif // USE_GC_INFO_DECODER // Check whether we are crossing managed-to-native boundary From 69f5fdff1c970f290e2722d32dab70a1dae3688b Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Fri, 5 Mar 2021 16:15:30 -0500 Subject: [PATCH 14/83] Serialize Dns async-over-sync requests for the same host (#49171) * Serialize Dns async-over-sync requests for the same host * Update src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs --- .../src/System/Net/Dns.cs | 69 ++++++++++++++++++- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs b/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs index f684e9b871d0d..b4ca39ab4536b 100644 --- a/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs +++ b/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs @@ -628,9 +628,6 @@ static async Task CompleteAsync(Task task, string hostName, ValueStopwatch st } } - private static Task RunAsync(Func func, object arg, CancellationToken cancellationToken) => - Task.Factory.StartNew(func!, arg, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); - private static IPHostEntry CreateHostEntryForAddress(IPAddress address) => new IPHostEntry { @@ -656,5 +653,71 @@ private static bool LogFailure(ValueStopwatch stopwatch) NameResolutionTelemetry.Log.AfterResolution(stopwatch, successful: false); return false; } + + /// Mapping from key to current task in flight for that key. + private static readonly Dictionary s_tasks = new Dictionary(); + + /// Queue the function to be invoked asynchronously. + /// + /// Since this is doing synchronous work on a thread pool thread, we want to limit how many threads end up being + /// blocked. We could employ a semaphore to limit overall usage, but a common case is that DNS requests are made + /// for only a handful of endpoints, and a reasonable compromise is to ensure that requests for a given host are + /// serialized. Once the data for that host is cached locally by the OS, the subsequent requests should all complete + /// very quickly, and if the head-of-line request is taking a long time due to the connection to the server, we won't + /// block lots of threads all getting data for that one host. We also still want to issue the request to the OS, rather + /// than having all concurrent requests for the same host share the exact same task, so that any shuffling of the results + /// by the OS to enable round robin is still perceived. + /// + private static Task RunAsync(Func func, object key, CancellationToken cancellationToken) + { + Task? task = null; + + lock (s_tasks) + { + // Get the previous task for this key, if there is one. + s_tasks.TryGetValue(key, out Task? prevTask); + prevTask ??= Task.CompletedTask; + + // Invoke the function in a queued work item when the previous task completes. Note that some callers expect the + // returned task to have the key as the task's AsyncState. + task = prevTask.ContinueWith(delegate + { + Debug.Assert(!Monitor.IsEntered(s_tasks)); + try + { + return func(key); + } + finally + { + // When the work is done, remove this key/task pair from the dictionary if this is still the current task. + // Because the work item is created and stored into both the local and the dictionary while the lock is + // held, and since we take the same lock here, inside this lock it's guaranteed to see the changes + // made by the call site. + lock (s_tasks) + { + ((ICollection>)s_tasks).Remove(new KeyValuePair(key!, task!)); + } + } + }, key, cancellationToken, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default); + + // If it's possible the task may end up getting canceled, it won't have a chance to remove itself from + // the dictionary if it is canceled, so use a separate continuation to do so. + if (cancellationToken.CanBeCanceled) + { + task.ContinueWith((task, key) => + { + lock (s_tasks) + { + ((ICollection>)s_tasks).Remove(new KeyValuePair(key!, task)); + } + }, key, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); + } + + // Finally, store the task into the dictionary as the current task for this key. + s_tasks[key] = task; + } + + return task; + } } } From 62e9f046b0a8dedcb6898c8922404e5273209167 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Fri, 5 Mar 2021 14:38:08 -0800 Subject: [PATCH 15/83] Allow using SupportedOSPlatform, UnsupportedOSPlatform attributes on interfaces (#48838) * Allow OSPlatform attributes for interfaces --- .../src/System/Runtime/Versioning/PlatformAttributes.cs | 4 +++- src/libraries/System.Runtime/ref/System.Runtime.cs | 4 ++-- src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/PlatformAttributes.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/PlatformAttributes.cs index 060727f8f91df..2c25123bf90ad 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/PlatformAttributes.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/PlatformAttributes.cs @@ -55,6 +55,7 @@ public TargetPlatformAttribute(string platformName) : base(platformName) AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | + AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | @@ -85,6 +86,7 @@ public SupportedOSPlatformAttribute(string platformName) : base(platformName) AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | + AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | @@ -101,4 +103,4 @@ public UnsupportedOSPlatformAttribute(string platformName) : base(platformName) { } } -} \ No newline at end of file +} diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index eecd357deb63e..3f4866a6d05c8 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -10126,7 +10126,7 @@ public FrameworkName(string identifier, System.Version version, string? profile) public static bool operator !=(System.Runtime.Versioning.FrameworkName? left, System.Runtime.Versioning.FrameworkName? right) { throw null; } public override string ToString() { throw null; } } - [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Enum | System.AttributeTargets.Event | System.AttributeTargets.Field | System.AttributeTargets.Method | System.AttributeTargets.Module | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple = true, Inherited = false)] + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Enum | System.AttributeTargets.Event | System.AttributeTargets.Field | System.AttributeTargets.Interface | System.AttributeTargets.Method | System.AttributeTargets.Module | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple = true, Inherited = false)] public sealed class SupportedOSPlatformAttribute : System.Runtime.Versioning.OSPlatformAttribute { public SupportedOSPlatformAttribute(string platformName) : base(platformName) { } @@ -10136,7 +10136,7 @@ public abstract class OSPlatformAttribute : System.Attribute private protected OSPlatformAttribute(string platformName) { } public string PlatformName { get; } } - [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Enum | System.AttributeTargets.Event | System.AttributeTargets.Field | System.AttributeTargets.Method | System.AttributeTargets.Module | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple = true, Inherited = false)] + [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Constructor | System.AttributeTargets.Enum | System.AttributeTargets.Event | System.AttributeTargets.Field | System.AttributeTargets.Interface | System.AttributeTargets.Method | System.AttributeTargets.Module | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple = true, Inherited = false)] public sealed class UnsupportedOSPlatformAttribute : System.Runtime.Versioning.OSPlatformAttribute { public UnsupportedOSPlatformAttribute(string platformName) : base(platformName) { } diff --git a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt index 79b1df2eb7416..4a52f75424847 100644 --- a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt +++ b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt @@ -109,4 +109,6 @@ CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatfo CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Net.HttpListenerResponse.Close()' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Net.HttpListenerResponse.Close(System.Byte[], System.Boolean)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.CryptoConfig' in the contract but not the implementation. -Total Issues: 102 +CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.Versioning.SupportedOSPlatformAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the implementation. +CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the implementation. +Total Issues: 104 From e0b4fc6b4e655fe2af9090f75701e09f4beedfd5 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Fri, 5 Mar 2021 14:55:26 -0800 Subject: [PATCH 16/83] [AndroidCrypto] Implement IExportPal for X509 certs (#49196) --- .../Interop.Crypto.cs | 27 ----- .../Interop.X509.cs | 37 ++++++- .../Security/Cryptography/RSAAndroid.cs | 2 +- .../pal_jni.c | 33 ++++-- .../pal_jni.h | 12 ++- .../pal_x509.c | 100 ++++++++++++------ .../pal_x509.h | 29 ++++- .../Pal.Android/StorePal.ExportPal.cs | 71 +++++++++++++ .../Cryptography/Pal.Android/StorePal.cs | 4 +- ...urity.Cryptography.X509Certificates.csproj | 3 +- 10 files changed, 234 insertions(+), 84 deletions(-) delete mode 100644 src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Crypto.cs create mode 100644 src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Crypto.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Crypto.cs deleted file mode 100644 index b0f50f5b988b1..0000000000000 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Crypto.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Runtime.InteropServices; -using System.Security.Cryptography; - -internal static partial class Interop -{ - internal static partial class AndroidCrypto - { - private delegate int NegativeSizeReadMethod(THandle handle, byte[]? buf, int cBuf); - private static byte[] GetDynamicBuffer(NegativeSizeReadMethod method, THandle handle) - { - int negativeSize = method(handle, null, 0); - if (negativeSize > 0) - throw new CryptographicException(); - - byte[] bytes = new byte[-negativeSize]; - int ret = method(handle, bytes, bytes.Length); - if (ret != 1) - throw new CryptographicException(); - - return bytes; - } - } -} diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.X509.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.X509.cs index eaaa9a6d0e0df..2ec104f11690d 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.X509.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.X509.cs @@ -10,23 +10,33 @@ internal static partial class Interop { internal static partial class AndroidCrypto { + private const int INSUFFICIENT_BUFFER = -1; + private const int SUCCESS = 1; + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_X509Decode")] internal static extern SafeX509Handle X509Decode(ref byte buf, int len); [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_X509Encode")] - private static extern int X509Encode(SafeX509Handle x, [Out] byte[]? buf, int len); + private static extern int X509Encode(SafeX509Handle x, [Out] byte[]? buf, ref int len); internal static byte[] X509Encode(SafeX509Handle x) { - return GetDynamicBuffer((ptr, buf, i) => X509Encode(ptr, buf, i), x); + int len = 0; + int ret = X509Encode(x, null, ref len); + if (ret != INSUFFICIENT_BUFFER) + throw new CryptographicException(); + + byte[] encoded = new byte[len]; + ret = X509Encode(x, encoded, ref len); + if (ret != SUCCESS) + throw new CryptographicException(); + + return encoded; } [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_X509DecodeCollection")] private static extern int X509DecodeCollection(ref byte buf, int bufLen, IntPtr[]? ptrs, ref int handlesLen); internal static SafeX509Handle[] X509DecodeCollection(ReadOnlySpan data) { - const int INSUFFICIENT_BUFFER = -1; - const int SUCCESS = 1; - ref byte buf = ref MemoryMarshal.GetReference(data); int size = 0; int ret = X509DecodeCollection(ref buf, data.Length, null, ref size); @@ -50,6 +60,23 @@ internal static SafeX509Handle[] X509DecodeCollection(ReadOnlySpan data) return handles; } + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_X509ExportPkcs7")] + private static extern int X509ExportPkcs7(IntPtr[] certs, int certsLen, [Out] byte[]? buf, ref int len); + internal static byte[] X509ExportPkcs7(IntPtr[] certHandles) + { + int len = 0; + int ret = X509ExportPkcs7(certHandles, certHandles.Length, null, ref len); + if (ret != INSUFFICIENT_BUFFER) + throw new CryptographicException(); + + byte[] encoded = new byte[len]; + ret = X509ExportPkcs7(certHandles, certHandles.Length, encoded, ref len); + if (ret != SUCCESS) + throw new CryptographicException(); + + return encoded; + } + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_X509GetContentType")] private static extern X509ContentType X509GetContentType(ref byte buf, int len); internal static X509ContentType X509GetContentType(ReadOnlySpan data) diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs b/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs index 2c79cfa9e8423..2fa748a23ace0 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs @@ -32,7 +32,7 @@ public RSAAndroid(int keySize) internal RSAAndroid(SafeRsaHandle key) { - _key = new Lazy(key); + _key = new Lazy(key.DuplicateHandle()); SetKeySizeFromHandle(key); } diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c index e5a3535651ebd..48bea370911f9 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c @@ -114,14 +114,20 @@ jmethodID g_SignatureInitVerify; jmethodID g_SignatureUpdate; jmethodID g_SignatureSign; jmethodID g_SignatureVerify; + // java/security/cert/CertificateFactory jclass g_CertFactoryClass; jmethodID g_CertFactoryGetInstance; jmethodID g_CertFactoryGenerateCertificate; jmethodID g_CertFactoryGenerateCertificates; -jmethodID g_CertFactoryGenerateCertPath; +jmethodID g_CertFactoryGenerateCertPathFromList; +jmethodID g_CertFactoryGenerateCertPathFromStream; jmethodID g_CertFactoryGenerateCRL; +// java/security/cert/CertPath +jclass g_CertPathClass; +jmethodID g_CertPathGetEncoded; + // java/security/cert/X509Certificate jclass g_X509CertClass; jmethodID g_X509CertGetEncoded; @@ -221,6 +227,11 @@ jmethodID g_X509EncodedKeySpecCtor; jclass g_DestroyableClass; jmethodID g_destroy; +// java/util/ArrayList +jclass g_ArrayListClass; +jmethodID g_ArrayListCtor; +jmethodID g_ArrayListAdd; + // java/util/Collection jclass g_CollectionClass; jmethodID g_CollectionIterator; @@ -491,12 +502,16 @@ JNI_OnLoad(JavaVM *vm, void *reserved) g_sslCtxGetDefaultMethod = GetMethod(env, true, g_sslCtxClass, "getDefault", "()Ljavax/net/ssl/SSLContext;"); g_sslCtxGetDefaultSslParamsMethod = GetMethod(env, false, g_sslCtxClass, "getDefaultSSLParameters", "()Ljavax/net/ssl/SSLParameters;"); - g_CertFactoryClass = GetClassGRef(env, "java/security/cert/CertificateFactory"); - g_CertFactoryGetInstance = GetMethod(env, true, g_CertFactoryClass, "getInstance", "(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"); - g_CertFactoryGenerateCertificate = GetMethod(env, false, g_CertFactoryClass, "generateCertificate", "(Ljava/io/InputStream;)Ljava/security/cert/Certificate;"); - g_CertFactoryGenerateCertificates = GetMethod(env, false, g_CertFactoryClass, "generateCertificates", "(Ljava/io/InputStream;)Ljava/util/Collection;"); - g_CertFactoryGenerateCertPath = GetMethod(env, false, g_CertFactoryClass, "generateCertPath", "(Ljava/io/InputStream;Ljava/lang/String;)Ljava/security/cert/CertPath;"); - g_CertFactoryGenerateCRL = GetMethod(env, false, g_CertFactoryClass, "generateCRL", "(Ljava/io/InputStream;)Ljava/security/cert/CRL;"); + g_CertFactoryClass = GetClassGRef(env, "java/security/cert/CertificateFactory"); + g_CertFactoryGetInstance = GetMethod(env, true, g_CertFactoryClass, "getInstance", "(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"); + g_CertFactoryGenerateCertificate = GetMethod(env, false, g_CertFactoryClass, "generateCertificate", "(Ljava/io/InputStream;)Ljava/security/cert/Certificate;"); + g_CertFactoryGenerateCertificates = GetMethod(env, false, g_CertFactoryClass, "generateCertificates", "(Ljava/io/InputStream;)Ljava/util/Collection;"); + g_CertFactoryGenerateCertPathFromList = GetMethod(env, false, g_CertFactoryClass, "generateCertPath", "(Ljava/util/List;)Ljava/security/cert/CertPath;"); + g_CertFactoryGenerateCertPathFromStream = GetMethod(env, false, g_CertFactoryClass, "generateCertPath", "(Ljava/io/InputStream;Ljava/lang/String;)Ljava/security/cert/CertPath;"); + g_CertFactoryGenerateCRL = GetMethod(env, false, g_CertFactoryClass, "generateCRL", "(Ljava/io/InputStream;)Ljava/security/cert/CRL;"); + + g_CertPathClass = GetClassGRef(env, "java/security/cert/CertPath"); + g_CertPathGetEncoded = GetMethod(env, false, g_CertPathClass, "getEncoded", "(Ljava/lang/String;)[B"); g_X509CertClass = GetClassGRef(env, "java/security/cert/X509Certificate"); g_X509CertGetEncoded = GetMethod(env, false, g_X509CertClass, "getEncoded", "()[B"); @@ -604,6 +619,10 @@ JNI_OnLoad(JavaVM *vm, void *reserved) g_DestroyableClass = GetClassGRef(env, "javax/security/auth/Destroyable"); g_destroy = GetMethod(env, false, g_DestroyableClass, "destroy", "()V"); + g_ArrayListClass = GetClassGRef(env, "java/util/ArrayList"); + g_ArrayListCtor = GetMethod(env, false, g_ArrayListClass, "", "(I)V"); + g_ArrayListAdd = GetMethod(env, false, g_ArrayListClass, "add", "(Ljava/lang/Object;)Z"); + g_CollectionClass = GetClassGRef(env, "java/util/Collection"); g_CollectionIterator = GetMethod(env, false, g_CollectionClass, "iterator", "()Ljava/util/Iterator;"); g_CollectionSize = GetMethod(env, false, g_CollectionClass, "size", "()I"); diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h index c9c86c111a771..972bc2d317c2b 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h @@ -99,9 +99,14 @@ extern jclass g_CertFactoryClass; extern jmethodID g_CertFactoryGetInstance; extern jmethodID g_CertFactoryGenerateCertificate; extern jmethodID g_CertFactoryGenerateCertificates; -extern jmethodID g_CertFactoryGenerateCertPath; +extern jmethodID g_CertFactoryGenerateCertPathFromList; +extern jmethodID g_CertFactoryGenerateCertPathFromStream; extern jmethodID g_CertFactoryGenerateCRL; +// java/security/cert/CertPath +extern jclass g_CertPathClass; +extern jmethodID g_CertPathGetEncoded; + // java/security/cert/X509Certificate extern jclass g_X509CertClass; extern jmethodID g_X509CertGetEncoded; @@ -231,6 +236,11 @@ extern jmethodID g_X509EncodedKeySpecCtor; extern jclass g_DestroyableClass; extern jmethodID g_destroy; +// java/util/Collection +extern jclass g_ArrayListClass; +extern jmethodID g_ArrayListCtor; +extern jmethodID g_ArrayListAdd; + // java/util/Collection extern jclass g_CollectionClass; extern jmethodID g_CollectionIterator; diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c index 6001bfc4b9f87..7c31b18c1e3ec 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c @@ -26,14 +26,13 @@ #define INSUFFICIENT_BUFFER -1 -static int32_t PopulateByteArray(JNIEnv *env, jbyteArray source, uint8_t *dest, int32_t len); -static int32_t PopulateString(JNIEnv *env, jstring source, char *dest, int32_t len); +static int32_t PopulateByteArray(JNIEnv* env, jbyteArray source, uint8_t* dest, int32_t* len); // Handles both DER and PEM formats -jobject /*X509Certificate*/ AndroidCryptoNative_X509Decode(const uint8_t *buf, int32_t len) +jobject /*X509Certificate*/ AndroidCryptoNative_X509Decode(const uint8_t* buf, int32_t len) { assert(buf != NULL && len > 0); - JNIEnv *env = GetJNIEnv(); + JNIEnv* env = GetJNIEnv(); jobject ret = NULL; INIT_LOCALS(loc, bytes, stream, certType, certFactory) @@ -63,28 +62,30 @@ jobject /*X509Certificate*/ AndroidCryptoNative_X509Decode(const uint8_t *buf, i } // Encodes as DER format -int32_t AndroidCryptoNative_X509Encode(jobject /*X509Certificate*/ cert, uint8_t *buf, int32_t len) +int32_t AndroidCryptoNative_X509Encode(jobject /*X509Certificate*/ cert, uint8_t* out, int32_t* outLen) { assert(cert != NULL); - JNIEnv *env = GetJNIEnv(); + JNIEnv* env = GetJNIEnv(); int32_t ret = FAIL; // byte[] encoded = cert.getEncoded(); - // return encoded.length jbyteArray encoded = (*env)->CallObjectMethod(env, cert, g_X509CertGetEncoded); ON_EXCEPTION_PRINT_AND_GOTO(cleanup); - ret = PopulateByteArray(env, encoded, buf, len); + ret = PopulateByteArray(env, encoded, out, outLen); cleanup: (*env)->DeleteLocalRef(env, encoded); return ret; } -int32_t AndroidCryptoNative_X509DecodeCollection(const uint8_t *buf, int32_t bufLen, jobject /*X509Certificate*/ *out, int32_t *outLen) +int32_t AndroidCryptoNative_X509DecodeCollection(const uint8_t* buf, + int32_t bufLen, + jobject /*X509Certificate*/* out, + int32_t* outLen) { assert(buf != NULL && bufLen > 0); assert(outLen != NULL); - JNIEnv *env = GetJNIEnv(); + JNIEnv* env = GetJNIEnv(); int32_t ret = FAIL; INIT_LOCALS(loc, bytes, stream, certType, certFactory, certs, iter) @@ -92,7 +93,7 @@ int32_t AndroidCryptoNative_X509DecodeCollection(const uint8_t *buf, int32_t buf // byte[] bytes = new byte[] { ... } // InputStream stream = new ByteArrayInputStream(bytes); loc[bytes] = (*env)->NewByteArray(env, bufLen); - (*env)->SetByteArrayRegion(env, loc[bytes], 0, bufLen, (const jbyte *)buf); + (*env)->SetByteArrayRegion(env, loc[bytes], 0, bufLen, (const jbyte*)buf); loc[stream] = (*env)->NewObject(env, g_ByteArrayInputStreamClass, g_ByteArrayInputStreamCtor, loc[bytes]); ON_EXCEPTION_PRINT_AND_GOTO(cleanup); @@ -153,10 +154,52 @@ int32_t AndroidCryptoNative_X509DecodeCollection(const uint8_t *buf, int32_t buf return ret; } -PAL_X509ContentType AndroidCryptoNative_X509GetContentType(const uint8_t *buf, int32_t len) +int32_t AndroidCryptoNative_X509ExportPkcs7(jobject* /*X509Certificate[]*/ certs, + int32_t certsLen, + uint8_t* out, + int32_t* outLen) +{ + assert(certs != NULL && certsLen > 0); + assert(outLen != NULL); + JNIEnv* env = GetJNIEnv(); + + int32_t ret = FAIL; + INIT_LOCALS(loc, certList, certType, certFactory, certPath, pkcs7Type, encoded) + + // ArrayList certList = new ArrayList(); + // foreach (Certificate cert in certs) + // certList.add(cert); + loc[certList] = (*env)->NewObject(env, g_ArrayListClass, g_ArrayListCtor, certsLen); + for (int i = 0; i < certsLen; ++i) + { + (*env)->CallBooleanMethod(env, loc[certList], g_ArrayListAdd, certs[i]); + ON_EXCEPTION_PRINT_AND_GOTO(cleanup); + } + + // CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + loc[certType] = JSTRING("X.509"); + loc[certFactory] = (*env)->CallStaticObjectMethod(env, g_CertFactoryClass, g_CertFactoryGetInstance, loc[certType]); + ON_EXCEPTION_PRINT_AND_GOTO(cleanup); + + // CertPath certPath = certFactory.generateCertPath(certList); + // byte[] encoded = certPath.getEncoded("PKCS7"); + loc[certPath] = (*env)->CallObjectMethod(env, loc[certFactory], g_CertFactoryGenerateCertPathFromList, loc[certList]); + ON_EXCEPTION_PRINT_AND_GOTO(cleanup); + loc[pkcs7Type] = JSTRING("PKCS7"); + loc[encoded] = (*env)->CallObjectMethod(env, loc[certPath], g_CertPathGetEncoded, loc[pkcs7Type]); + ON_EXCEPTION_PRINT_AND_GOTO(cleanup); + + ret = PopulateByteArray(env, loc[encoded], out, outLen); + +cleanup: + RELEASE_LOCALS(loc, env) + return ret; +} + +PAL_X509ContentType AndroidCryptoNative_X509GetContentType(const uint8_t* buf, int32_t len) { assert(buf != NULL && len > 0); - JNIEnv *env = GetJNIEnv(); + JNIEnv* env = GetJNIEnv(); PAL_X509ContentType ret = PAL_X509Unknown; INIT_LOCALS(loc, bytes, stream, certType, certFactory, pkcs7Type, certPath, cert) @@ -170,7 +213,7 @@ PAL_X509ContentType AndroidCryptoNative_X509GetContentType(const uint8_t *buf, i // byte[] bytes = new byte[] { ... } // InputStream stream = new ByteArrayInputStream(bytes); loc[bytes] = (*env)->NewByteArray(env, len); - (*env)->SetByteArrayRegion(env, loc[bytes], 0, len, (const jbyte *)buf); + (*env)->SetByteArrayRegion(env, loc[bytes], 0, len, (const jbyte*)buf); loc[stream] = (*env)->NewObject(env, g_ByteArrayInputStreamClass, g_ByteArrayInputStreamCtor, loc[bytes]); ON_EXCEPTION_PRINT_AND_GOTO(cleanup); @@ -181,7 +224,7 @@ PAL_X509ContentType AndroidCryptoNative_X509GetContentType(const uint8_t *buf, i // CertPath certPath = certFactory.generateCertPath(stream, "PKCS7"); loc[pkcs7Type] = JSTRING("PKCS7"); - loc[certPath] = (*env)->CallObjectMethod(env, loc[certFactory], g_CertFactoryGenerateCertPath, loc[stream], loc[pkcs7Type]); + loc[certPath] = (*env)->CallObjectMethod(env, loc[certFactory], g_CertFactoryGenerateCertPathFromStream, loc[stream], loc[pkcs7Type]); if (!CheckJNIExceptions(env)) { ret = PAL_Pkcs7; @@ -207,9 +250,9 @@ void* AndroidCryptoNative_X509PublicKey(jobject /*X509Certificate*/ cert, PAL_Ke { assert(cert != NULL); - JNIEnv *env = GetJNIEnv(); + JNIEnv* env = GetJNIEnv(); - void *keyHandle; + void* keyHandle; jobject key = (*env)->CallObjectMethod(env, cert, g_X509CertGetPublicKey); switch (algorithm) { @@ -231,28 +274,15 @@ void* AndroidCryptoNative_X509PublicKey(jobject /*X509Certificate*/ cert, PAL_Ke return keyHandle; } -static int32_t PopulateByteArray(JNIEnv *env, jbyteArray source, uint8_t *dest, int32_t len) +static int32_t PopulateByteArray(JNIEnv* env, jbyteArray source, uint8_t* dest, int32_t* len) { jsize bytesLen = (*env)->GetArrayLength(env, source); - // Insufficient buffer - if (len < bytesLen) - return -bytesLen; + bool insufficientBuffer = *len < bytesLen; + *len = bytesLen; + if (insufficientBuffer) + return INSUFFICIENT_BUFFER; (*env)->GetByteArrayRegion(env, source, 0, bytesLen, (jbyte*)dest); return CheckJNIExceptions(env) ? FAIL : SUCCESS; } - -static int32_t PopulateString(JNIEnv *env, jstring source, char *dest, int32_t len) -{ - // Length with null terminator - jsize bytesLen = (*env)->GetStringUTFLength(env, source) + 1; - - // Insufficient buffer - if (len < bytesLen) - return -bytesLen; - - jsize strLen = (*env)->GetStringLength(env, source); - (*env)->GetStringUTFRegion(env, source, 0, strLen, dest); - return CheckJNIExceptions(env) ? FAIL : SUCCESS; -} diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.h index eeccd4da93b9f..476d0dedeaf35 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.h @@ -4,8 +4,15 @@ #include "pal_jni.h" // Creation and lifetime -PALEXPORT jobject /*X509Certificate*/ AndroidCryptoNative_X509Decode(const uint8_t *buf, int32_t len); -PALEXPORT int32_t AndroidCryptoNative_X509Encode(jobject /*X509Certificate*/ cert, uint8_t *buf, int32_t len); +PALEXPORT jobject /*X509Certificate*/ AndroidCryptoNative_X509Decode(const uint8_t* buf, int32_t len); + +/* +Encode a certificate in ASN.1 DER format + +Returns 1 on success, -1 on insufficient buffer, 0 otherwise. +The outLen parameter will be set to the length required for encoding the certificate. +*/ +PALEXPORT int32_t AndroidCryptoNative_X509Encode(jobject /*X509Certificate*/ cert, uint8_t* out, int32_t* outLen); /* Decodes a collection of certificates. @@ -13,7 +20,21 @@ Decodes a collection of certificates. Returns 1 on success, -1 on insufficient buffer, 0 otherwise. The outLen parameter will be set to the length required for decoding the collection. */ -PALEXPORT int32_t AndroidCryptoNative_X509DecodeCollection(const uint8_t *buf, int32_t bufLen, jobject /*X509Certificate*/ *out, int32_t *outLen); +PALEXPORT int32_t AndroidCryptoNative_X509DecodeCollection(const uint8_t* buf, + int32_t bufLen, + jobject /*X509Certificate*/* out, + int32_t* outLen); + +/* +Exports a collection of certificates in PKCS#7 format + +Returns 1 on success, -1 on insufficient buffer, 0 otherwise. +The outLen parameter will be set to the length required for exporting the collection. +*/ +PALEXPORT int32_t AndroidCryptoNative_X509ExportPkcs7(jobject* /*X509Certificate[]*/ certs, + int32_t certsLen, + uint8_t* out, + int32_t* outLen); // Matches managed X509ContentType enum enum @@ -27,7 +48,7 @@ enum PAL_Authenticode = 6, }; typedef uint32_t PAL_X509ContentType; -PALEXPORT PAL_X509ContentType AndroidCryptoNative_X509GetContentType(const uint8_t *buf, int32_t len); +PALEXPORT PAL_X509ContentType AndroidCryptoNative_X509GetContentType(const uint8_t* buf, int32_t len); // Matches managed PAL_KeyAlgorithm enum enum diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs new file mode 100644 index 0000000000000..f5b52d78bf0ce --- /dev/null +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; + +namespace Internal.Cryptography.Pal +{ + internal sealed partial class StorePal + { + private sealed class AndroidExportProvider : UnixExportProvider + { + public AndroidExportProvider(ICertificatePalCore cert) + : base(cert) + { + } + + public AndroidExportProvider(X509Certificate2Collection certs) + : base(certs) + { + } + + protected override byte[] ExportPkcs7() + { + IntPtr[] certHandles; + if (_singleCertPal != null) + { + certHandles = new[] { _singleCertPal.Handle }; + } + else + { + Debug.Assert(_certs != null); + certHandles = new IntPtr[_certs!.Count]; + for (int i = 0; i < _certs.Count; i++) + { + certHandles[i] = _certs[i].Pal.Handle; + } + } + + Debug.Assert(certHandles.Length > 0); + return Interop.AndroidCrypto.X509ExportPkcs7(certHandles); + } + + protected override byte[] ExportPkcs8(ICertificatePalCore certificatePal, ReadOnlySpan password) + { + Debug.Assert(certificatePal.HasPrivateKey); + SafeKeyHandle? privateKey = ((AndroidCertificatePal)certificatePal).PrivateKeyHandle; + + AsymmetricAlgorithm algorithm; + switch (privateKey) + { + case SafeEcKeyHandle ec: + algorithm = new ECDsaImplementation.ECDsaAndroid(ec); + break; + case SafeRsaHandle rsa: + algorithm = new RSAImplementation.RSAAndroid(rsa); + break; + default: + throw new NotSupportedException(SR.NotSupported_KeyAlgorithm); + } + + using (algorithm) + { + return algorithm.ExportEncryptedPkcs8PrivateKey(password, s_windowsPbe); + } + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.cs index e389c9f66a77d..3fe90285a8c1a 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.cs @@ -43,12 +43,12 @@ public static ILoaderPal FromFile(string fileName, SafePasswordHandle password, public static IExportPal FromCertificate(ICertificatePalCore cert) { - throw new NotImplementedException(nameof(FromCertificate)); + return new AndroidExportProvider(cert); } public static IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates) { - throw new NotImplementedException(nameof(LinkFromCertificateCollection)); + return new AndroidExportProvider(certificates); } public static IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj b/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj index 5af753bacc8e9..b2e55f5bd0304 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj @@ -400,6 +400,7 @@ + @@ -409,8 +410,6 @@ Link="Common\Interop\Android\Interop.JObjectLifetime.cs" /> - Date: Fri, 5 Mar 2021 15:04:56 -0800 Subject: [PATCH 17/83] Do not create R2R in memory hashes if profiler is not present or hasn't added types (#49177) * only create lazy map if profiler added types * also don't create for ApplyMetadata if they haven't added new types * add check to skip call if no profiler was called * Update src/coreclr/vm/ceeload.cpp Co-authored-by: Brian Robbins Co-authored-by: Brian Robbins --- src/coreclr/vm/ceeload.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index e121270dd7249..4a71037c89c65 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -220,6 +220,14 @@ void Module::UpdateNewlyAddedTypes() DWORD countExportedTypesAfterProfilerUpdate = GetMDImport()->GetCountWithTokenKind(mdtExportedType); DWORD countCustomAttributeCount = GetMDImport()->GetCountWithTokenKind(mdtCustomAttribute); + if (m_dwTypeCount == countTypesAfterProfilerUpdate + && m_dwExportedTypeCount == countExportedTypesAfterProfilerUpdate + && m_dwCustomAttributeCount == countCustomAttributeCount) + { + // The profiler added no new types, do not create the in memory hashes + return; + } + // R2R pre-computes an export table and tries to avoid populating a class hash at runtime. However the profiler can // still add new types on the fly by calling here. If that occurs we fallback to the slower path of creating the // in memory hashtable as usual. @@ -280,6 +288,7 @@ void Module::NotifyProfilerLoadFinished(HRESULT hr) m_dwCustomAttributeCount = GetMDImport()->GetCountWithTokenKind(mdtCustomAttribute); } + BOOL profilerCallbackHappened = FALSE; // Notify the profiler, this may cause metadata to be updated { BEGIN_PIN_PROFILER(CORProfilerTrackModuleLoads()); @@ -292,13 +301,15 @@ void Module::NotifyProfilerLoadFinished(HRESULT hr) g_profControlBlock.pProfInterface->ModuleAttachedToAssembly((ModuleID) this, (AssemblyID)m_pAssembly); } + + profilerCallbackHappened = TRUE; } END_PIN_PROFILER(); } // If there are more types than before, add these new types to the // assembly - if (!IsResource()) + if (profilerCallbackHappened && !IsResource()) { UpdateNewlyAddedTypes(); } @@ -13832,4 +13843,3 @@ void EEConfig::DebugCheckAndForceIBCFailure(BitForMask bitForMask) } } #endif // defined(_DEBUG) && !defined(DACCESS_COMPILE) - From e1e46a8d2ca9c2c932c8ceb61f884c7c82351442 Mon Sep 17 00:00:00 2001 From: Drew Scoggins Date: Fri, 5 Mar 2021 15:12:06 -0800 Subject: [PATCH 18/83] Add pip upgrade step inside venv to fix crypto issue (#49250) --- eng/pipelines/coreclr/templates/run-performance-job.yml | 4 ++-- eng/pipelines/coreclr/templates/run-scenarios-job.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index 7a12fd8dae44c..17ef611519b25 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -52,8 +52,8 @@ jobs: - IsInternal: '' - HelixApiAccessToken: '' - - HelixPreCommandStemWindows: 'py -m pip install -U pip;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install --user azure.storage.blob==12.0.0;py -3 -m pip install --user azure.storage.queue==12.0.0;set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' - - HelixPreCommandStemLinux: 'python3 -m pip install -U pip;sudo apt-get -y install python3-venv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/Scripts/activate;export PYTHONPATH=;pip3 install --user azure.storage.blob==12.0.0;pip3 install --user azure.storage.queue==12.0.0;sudo apt-get update;sudo apt -y install curl dirmngr apt-transport-https lsb-release ca-certificates;curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -;sudo apt-get -y install nodejs;sudo apt-get -y install npm;npm install --prefix $HELIX_WORKITEM_PAYLOAD jsvu -g;$HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 --engines=v8;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - HelixPreCommandStemWindows: 'py -m pip install -U pip;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install azure.storage.blob==12.0.0;py -3 -m pip install azure.storage.queue==12.0.0;set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' + - HelixPreCommandStemLinux: 'python3 -m pip install -U pip;sudo apt-get -y install python3-venv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/Scripts/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.0.0;pip3 install azure.storage.queue==12.0.0;sudo apt-get update;sudo apt -y install curl dirmngr apt-transport-https lsb-release ca-certificates;curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -;sudo apt-get -y install nodejs;sudo apt-get -y install npm;npm install --prefix $HELIX_WORKITEM_PAYLOAD jsvu -g;$HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 --engines=v8;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' - HelixPreCommandStemMsul: 'sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib;sudo apk add cargo --repository http://sjc.edge.kernel.org/alpine/edge/community ;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.7.1;pip3 install azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' - ExtraMSBuildLogsWindows: 'set MSBUILDDEBUGCOMM=1;set "MSBUILDDEBUGPATH=%HELIX_WORKITEM_UPLOAD_ROOT%"' - ExtraMSBuildLogsLinux: 'export MSBUILDDEBUGCOMM=1;export "MSBUILDDEBUGPATH=$HELIX_WORKITEM_UPLOAD_ROOT"' diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index b3a9bea009d15..23f2b4600fd2d 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -63,13 +63,13 @@ jobs: # extra private job settings - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - ${{ if eq(parameters.osGroup, 'windows') }}: - - AdditionalHelixPreCommands: 'py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install --user azure.storage.blob==12.0.0 --force-reinstall;py -3 -m pip install --user azure.storage.queue==12.0.0 --force-reinstall;set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' + - AdditionalHelixPreCommands: 'py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install --user azure.storage.blob==12.0.0 --force-reinstall;py -3 -m pip install --user azure.storage.queue==12.0.0 --force-reinstall;set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' - IsInternal: -Internal - ${{ if and(ne(parameters.osGroup, 'windows'), ne(parameters.osSubGroup, '_musl')) }}: - - AdditionalHelixPreCommands: 'sudo apt-get -y install python3-venv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/Scripts/activate;export PYTHONPATH=;pip3 install --user azure.storage.blob==12.0.0 --force-reinstall;pip3 install --user azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - AdditionalHelixPreCommands: 'sudo apt-get -y install python3-venv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/Scripts/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install --user azure.storage.blob==12.0.0 --force-reinstall;pip3 install --user azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' - IsInternal: --internal - ${{ if and(ne(parameters.osGroup, 'windows'), eq(parameters.osSubGroup, '_musl')) }}: - - AdditionalHelixPreCommands: 'sudo apk add py3-virtualenv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/Scripts/activate;export PYTHONPATH=;pip3 install --user azure.storage.blob==12.0.0 --force-reinstall;pip3 install --user azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - AdditionalHelixPreCommands: 'sudo apk add py3-virtualenv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/Scripts/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install --user azure.storage.blob==12.0.0 --force-reinstall;pip3 install --user azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' - IsInternal: --internal - group: DotNet-HelixApi-Access - group: dotnet-benchview From 30206750ee5c56e7beb1563c37a4a2aeda1712dd Mon Sep 17 00:00:00 2001 From: Drew Scoggins Date: Fri, 5 Mar 2021 17:39:30 -0800 Subject: [PATCH 19/83] Move scenario to float (#49255) * Remove version parsing * Remove version macro from yml file --- eng/pipelines/coreclr/templates/run-scenarios-job.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index 23f2b4600fd2d..0e98ed830f29e 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -96,16 +96,11 @@ jobs: displayName: Performance Setup (Linux) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} - # parse Version.props to get the latest stable sdk version on master - - script: $(Python) scripts/parse_props.py --branch-name master # defaults to master branch of sdk so we can get the latest - displayName: Parse Version.props - workingDirectory: $(PerformanceDirectory) - continueOnError: ${{ parameters.continueOnError }} # run ci-setup - - script: $(Python) $(PerformanceDirectory)\scripts\ci_setup.py $(DotnetVersion) $(SetupArguments) --install-dir $(PayloadDirectory)\dotnet --output-file $(WorkItemDirectory)\machine-setup.cmd + - script: $(Python) $(PerformanceDirectory)\scripts\ci_setup.py $(SetupArguments) --install-dir $(PayloadDirectory)\dotnet --output-file $(WorkItemDirectory)\machine-setup.cmd displayName: Run ci setup script (Windows) condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) - - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(DotnetVersion) $(SetupArguments) --install-dir $(PayloadDirectory)/dotnet --output-file $(WorkItemDirectory)/machine-setup.sh + - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments) --install-dir $(PayloadDirectory)/dotnet --output-file $(WorkItemDirectory)/machine-setup.sh displayName: Run ci setup script (Linux) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) # copy wasm packs if running on wasm From 2338123c1c7a7471ebe8afa81719132d83a1b61b Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Fri, 5 Mar 2021 18:49:34 -0800 Subject: [PATCH 20/83] JIT: fix prejit entry PGO instrumentation (#49154) Don't assume the entry block is `fgFirstBB`. Make sure to put the entry probe in the scratch bb. Closes #49108. --- src/coreclr/jit/fgprofile.cpp | 36 +++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index 479ea37de5dcb..9e9e3faa7a05a 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -281,8 +281,11 @@ class NonInstrumentor : public Instrumentor // class BlockCountInstrumentor : public Instrumentor { +private: + BasicBlock* m_entryBlock; + public: - BlockCountInstrumentor(Compiler* comp) : Instrumentor(comp) + BlockCountInstrumentor(Compiler* comp) : Instrumentor(comp), m_entryBlock(nullptr) { } bool ShouldProcess(BasicBlock* block) override @@ -349,6 +352,15 @@ void BlockCountInstrumentor::BuildSchemaElements(BasicBlock* block, Schema& sche schema.push_back(schemaElem); m_schemaCount++; + + // If this is the entry block, remember it for later. + // Note it might not be fgFirstBB, if we have a scratchBB. + // + if (offset == 0) + { + assert(m_entryBlock == nullptr); + m_entryBlock = block; + } } //------------------------------------------------------------------------ @@ -407,11 +419,14 @@ void BlockCountInstrumentor::InstrumentMethodEntry(Schema& schema, BYTE* profile // Find the address of the entry block's counter. // - BasicBlock* const block = m_comp->fgFirstBB; - const int firstSchemaIndex = block->bbCountSchemaIndex; - assert(block->bbCodeOffs == (IL_OFFSET)schema[firstSchemaIndex].ILOffset); + assert(m_entryBlock != nullptr); + assert(m_entryBlock->bbCodeOffs == 0); + + const int firstSchemaIndex = (int)m_entryBlock->bbCountSchemaIndex; + assert((IL_OFFSET)schema[firstSchemaIndex].ILOffset == 0); assert(schema[firstSchemaIndex].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::BasicBlockIntCount); - size_t addrOfFirstExecutionCount = (size_t)(schema[firstSchemaIndex].Offset + profileMemory); + + const size_t addrOfFirstExecutionCount = (size_t)(schema[firstSchemaIndex].Offset + profileMemory); GenTree* arg; @@ -436,20 +451,29 @@ void BlockCountInstrumentor::InstrumentMethodEntry(Schema& schema, BYTE* profile arg = m_comp->gtNewIconEmbMethHndNode(info.compMethodHnd); } + // We want to call CORINFO_HELP_BBT_FCN_ENTER just one time, + // the first time this method is called. So make the call conditional + // on the entry block's profile count. + // GenTreeCall::Use* args = m_comp->gtNewCallArgs(arg); GenTree* call = m_comp->gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, args); // Read Basic-Block count value + // GenTree* valueNode = m_comp->gtNewIndOfIconHandleNode(TYP_INT, addrOfFirstExecutionCount, GTF_ICON_BBC_PTR, false); // Compare Basic-Block count value against zero + // GenTree* relop = m_comp->gtNewOperNode(GT_NE, TYP_INT, valueNode, m_comp->gtNewIconNode(0, TYP_INT)); GenTree* colon = new (m_comp, GT_COLON) GenTreeColon(TYP_VOID, m_comp->gtNewNothingNode(), call); GenTree* cond = m_comp->gtNewQmarkNode(TYP_VOID, relop, colon); Statement* stmt = m_comp->gtNewStmt(cond); + // Add this check into the scratch block entry so we only do the check once per call. + // If we put it in block we may be putting it inside a loop. + // m_comp->fgEnsureFirstBBisScratch(); - m_comp->fgInsertStmtAtEnd(block, stmt); + m_comp->fgInsertStmtAtEnd(m_comp->fgFirstBB, stmt); } //------------------------------------------------------------------------ From 11cd2721a9bb3fe0c21e20979a3e670f61e3507d Mon Sep 17 00:00:00 2001 From: Santiago Fernandez Madero Date: Fri, 5 Mar 2021 21:15:29 -0800 Subject: [PATCH 21/83] Update debug dump template after runfo update to include dumps (#49183) * Update debug dump template after runfo update to include dumps * Fix workitem param and generate a dump command per dump found * PR Feedback --- eng/testing/debug-dump-template.md | 17 +++++++++-------- eng/testing/gen-debug-dump-docs.py | 24 +++++++++++++++++++----- src/libraries/sendtohelixhelp.proj | 4 ++-- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/eng/testing/debug-dump-template.md b/eng/testing/debug-dump-template.md index 02d3897236712..d96ce6058f588 100644 --- a/eng/testing/debug-dump-template.md +++ b/eng/testing/debug-dump-template.md @@ -1,10 +1,6 @@ -# Get the dump - -Click the link to the dump on the `Helix Test Logs` tab in Azure DevOps. This is the same place you got these instructions from. - # Get the Helix payload -[Runfo](https://github.com/jaredpar/runfo/tree/master/runfo#runfo) helps get information about helix test runs and azure devops builds. We will use it to download the payload and symbols: +[Runfo](https://github.com/jaredpar/runfo/tree/master/runfo#runfo) helps get information about helix test runs and azure devops builds. We will use it to download the payload and symbols (recommended version 0.6.4 or later): ```sh dotnet tool install --global runfo dotnet tool update --global runfo @@ -19,6 +15,8 @@ runfo get-helix-payload -j %JOBID% -w %WORKITEM% -o %WOUTDIR% runfo get-helix-payload -j %JOBID% -w %WORKITEM% -o %LOUTDIR% ``` +Any dump files published by helix will be downloaded. + > NOTE: if the helix job is an internal job, you need to pass down a [helix authentication token](https://helix.dot.net/Account/Tokens) using the `--helix-token` argument. Now extract the files: @@ -55,6 +53,9 @@ dotnet sos install --architecture x64 Install or update WinDbg if necessary ([external](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools), [internal](https://osgwiki.com/wiki/Installing_WinDbg)). If you don't have a recent WinDbg you may have to do `.update sos`. Open WinDbg and open the dump with `File>Open Dump`. +``` + +``` ``` !setclrpath %WOUTDIR%\shared\Microsoft.NETCore.App\6.0.0 @@ -76,7 +77,7 @@ dotnet tool update --global dotnet-dump ``` If prompted, open a new command prompt to pick up the updated PATH. ```sh -dotnet-dump analyze +dotnet-dump analyze ``` Within dotnet-dump: ```sh @@ -106,7 +107,7 @@ Install or update LLDB if necessary ([instructions here](https://github.com/dotn Load the dump: ```sh -lldb --core %LOUTDIR%/shared/Microsoft.NETCore.App/6.0.0/dotnet +lldb --core %LOUTDIR%/shared/Microsoft.NETCore.App/6.0.0/dotnet ``` Within lldb: @@ -129,7 +130,7 @@ dotnet tool update --global dotnet-dump ``` If prompted, open a new command prompt to pick up the updated PATH. ```sh -dotnet-dump analyze +dotnet-dump analyze ``` Within dotnet-dump: ```sh diff --git a/eng/testing/gen-debug-dump-docs.py b/eng/testing/gen-debug-dump-docs.py index 8aeb844db3514..9fca98d8b2df8 100644 --- a/eng/testing/gen-debug-dump-docs.py +++ b/eng/testing/gen-debug-dump-docs.py @@ -61,14 +61,13 @@ dump_dir = sys.argv[idx] idx += 1 -found_dumps = False +dump_names = [] if dump_dir != '': for filename in os.listdir(dump_dir): if filename.endswith('.dmp') or 'core.' in filename: - found_dumps = True - break + dump_names.append(filename) -if not found_dumps: +if len(dump_names) == 0: print("Did not find dumps, skipping dump docs generation.") exit(0) @@ -103,6 +102,21 @@ output_file = out_dir + dir_separator + 'how-to-debug-dump.md' with open(output_file, 'w+') as output: print('writing output file: ' + output_file) - write_file = output.write(replace_string) + + lines = replace_string.split(os.linesep) + lin_dump_dir= workitem + "/workitems/" + workitem + "/" + win_dump_dir= workitem + "\\workitems\\" + workitem + "\\" + for line in lines: + # write dump debugging commands for each dump found. + if "" in line: + for dump_name in dump_names: + output.write(line.replace("", unix_user_folder + lin_dump_dir + dump_name)) + output.write(os.linesep) + elif "" in line: + for dump_name in dump_names: + output.write(line.replace("", windows_user_folder + win_dump_dir + dump_name)) + output.write(os.linesep) + else: + output.write(line + os.linesep) print('done writing debug dump information') diff --git a/src/libraries/sendtohelixhelp.proj b/src/libraries/sendtohelixhelp.proj index e9ac5fbefbc89..3269b7c389500 100644 --- a/src/libraries/sendtohelixhelp.proj +++ b/src/libraries/sendtohelixhelp.proj @@ -229,11 +229,11 @@ $(HelixPostCommands); - %HELIX_PYTHONPATH% %HELIX_CORRELATION_PAYLOAD%\gen-debug-dump-docs.py -buildid $(BUILD_BUILDID) -workitem %HELIX_WORKITEM_ID% -jobid %HELIX_CORRELATION_ID% -outdir %HELIX_WORKITEM_UPLOAD_ROOT% -templatedir %HELIX_CORRELATION_PAYLOAD% -dumpdir %HELIX_DUMP_FOLDER% + %HELIX_PYTHONPATH% %HELIX_CORRELATION_PAYLOAD%\gen-debug-dump-docs.py -buildid $(BUILD_BUILDID) -workitem %HELIX_WORKITEM_FRIENDLYNAME% -jobid %HELIX_CORRELATION_ID% -outdir %HELIX_WORKITEM_UPLOAD_ROOT% -templatedir %HELIX_CORRELATION_PAYLOAD% -dumpdir %HELIX_DUMP_FOLDER% $(HelixPostCommands); - $HELIX_PYTHONPATH $HELIX_CORRELATION_PAYLOAD/gen-debug-dump-docs.py -buildid $(BUILD_BUILDID) -workitem $HELIX_WORKITEM_ID -jobid $HELIX_CORRELATION_ID -outdir $HELIX_WORKITEM_UPLOAD_ROOT -templatedir $HELIX_CORRELATION_PAYLOAD -dumpdir $HELIX_DUMP_FOLDER + $HELIX_PYTHONPATH $HELIX_CORRELATION_PAYLOAD/gen-debug-dump-docs.py -buildid $(BUILD_BUILDID) -workitem $HELIX_WORKITEM_FRIENDLYNAME -jobid $HELIX_CORRELATION_ID -outdir $HELIX_WORKITEM_UPLOAD_ROOT -templatedir $HELIX_CORRELATION_PAYLOAD -dumpdir $HELIX_DUMP_FOLDER From 50494e0118829b6f0ba762c0854bf8c060e73c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Andr=C3=A9?= <2341261+manandre@users.noreply.github.com> Date: Sat, 6 Mar 2021 12:56:24 +0100 Subject: [PATCH 22/83] Add DataflowBlock.ReceiveAllAsync extension method (#37876) --- .../System.Threading.Tasks.Dataflow.csproj | 7 +- ....Threading.Tasks.Dataflow.netstandard21.cs | 13 + .../Base/DataflowBlock.IAsyncEnumerable.cs | 38 +++ .../src/Base/DataflowBlock.cs | 2 +- .../System.Threading.Tasks.Dataflow.csproj | 5 +- ...lowBlockExtensionTests.IAsyncEnumerable.cs | 264 ++++++++++++++++++ .../Dataflow/DataflowBlockExtensionTests.cs | 2 +- ...stem.Threading.Tasks.Dataflow.Tests.csproj | 3 + 8 files changed, 329 insertions(+), 5 deletions(-) create mode 100644 src/libraries/System.Threading.Tasks.Dataflow/ref/System.Threading.Tasks.Dataflow.netstandard21.cs create mode 100644 src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.IAsyncEnumerable.cs create mode 100644 src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.IAsyncEnumerable.cs diff --git a/src/libraries/System.Threading.Tasks.Dataflow/ref/System.Threading.Tasks.Dataflow.csproj b/src/libraries/System.Threading.Tasks.Dataflow/ref/System.Threading.Tasks.Dataflow.csproj index 7c65f89d1bf10..d24314b3be17e 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/ref/System.Threading.Tasks.Dataflow.csproj +++ b/src/libraries/System.Threading.Tasks.Dataflow/ref/System.Threading.Tasks.Dataflow.csproj @@ -1,9 +1,12 @@ - netstandard2.0;netstandard1.0;netstandard1.1;net461 + netstandard2.1;netstandard2.0;netstandard1.0;netstandard1.1;net461 enable - \ No newline at end of file + + + + diff --git a/src/libraries/System.Threading.Tasks.Dataflow/ref/System.Threading.Tasks.Dataflow.netstandard21.cs b/src/libraries/System.Threading.Tasks.Dataflow/ref/System.Threading.Tasks.Dataflow.netstandard21.cs new file mode 100644 index 0000000000000..ed789646e93f4 --- /dev/null +++ b/src/libraries/System.Threading.Tasks.Dataflow/ref/System.Threading.Tasks.Dataflow.netstandard21.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +namespace System.Threading.Tasks.Dataflow +{ + public static partial class DataflowBlock + { + public static System.Collections.Generic.IAsyncEnumerable ReceiveAllAsync(this System.Threading.Tasks.Dataflow.IReceivableSourceBlock source, System.Threading.CancellationToken cancellationToken = default) { throw null; } + } +} diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.IAsyncEnumerable.cs b/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.IAsyncEnumerable.cs new file mode 100644 index 0000000000000..972a5c939f02b --- /dev/null +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.IAsyncEnumerable.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace System.Threading.Tasks.Dataflow +{ + public static partial class DataflowBlock + { + /// Creates an that enables receiving all of the data from the source. + /// Specifies the type of data contained in the source. + /// The source from which to asynchronously receive. + /// The which may be used to cancel the receive operation. + /// The created async enumerable. + /// The is null (Nothing in Visual Basic). + public static IAsyncEnumerable ReceiveAllAsync(this IReceivableSourceBlock source, CancellationToken cancellationToken = default) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + return ReceiveAllAsyncCore(source, cancellationToken); + + static async IAsyncEnumerable ReceiveAllAsyncCore(IReceivableSourceBlock source, [EnumeratorCancellation] CancellationToken cancellationToken) + { + while (await source.OutputAvailableAsync(cancellationToken).ConfigureAwait(false)) + { + while (source.TryReceive(out TOutput? item)) + { + yield return item; + } + } + } + } + } +} diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs b/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs index e3393d1c474c4..cfc2ebf4515b3 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/Base/DataflowBlock.cs @@ -25,7 +25,7 @@ namespace System.Threading.Tasks.Dataflow /// /// Provides a set of static (Shared in Visual Basic) methods for working with dataflow blocks. /// - public static class DataflowBlock + public static partial class DataflowBlock { #region LinkTo /// Links the to the specified . diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj b/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj index 7b324e8ca49c0..fa21b7c249f78 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);netstandard2.0;netstandard1.0;netstandard1.1;net461 + $(NetCoreAppCurrent);netstandard2.1;netstandard2.0;netstandard1.0;netstandard1.1;net461 true enable @@ -55,6 +55,9 @@ + + + diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.IAsyncEnumerable.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.IAsyncEnumerable.cs new file mode 100644 index 0000000000000..2990371029d38 --- /dev/null +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.IAsyncEnumerable.cs @@ -0,0 +1,264 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Xunit; + +namespace System.Threading.Tasks.Dataflow.Tests +{ + public partial class DataflowBlockExtensionTests + { + [Fact] + public void ReceiveAllAsync_ArgumentValidation() + { + AssertExtensions.Throws("source", () => ((IReceivableSourceBlock)null).ReceiveAllAsync()); + AssertExtensions.Throws("source", () => ((IReceivableSourceBlock)null).ReceiveAllAsync(new CancellationToken(true))); + } + + [Fact] + public void ReceiveAllAsync_NotIdempotent() + { + var source = new BufferBlock(); + IAsyncEnumerable e = source.ReceiveAllAsync(); + Assert.NotNull(e); + Assert.NotSame(e, source.ReceiveAllAsync()); + } + + [Fact] + public async Task ReceiveAllAsync_UseMoveNextAsyncAfterCompleted_ReturnsFalse() + { + var source = new BufferBlock(); + IAsyncEnumerator e = source.ReceiveAllAsync().GetAsyncEnumerator(); + + ValueTask vt = e.MoveNextAsync(); + Assert.False(vt.IsCompleted); + source.Complete(); + Assert.False(await vt); + + vt = e.MoveNextAsync(); + Assert.True(vt.IsCompletedSuccessfully); + Assert.False(vt.Result); + } + + [Fact] + public void ReceiveAllAsync_AvailableDataCompletesSynchronously() + { + var source = new BufferBlock(); + + IAsyncEnumerator e = source.ReceiveAllAsync().GetAsyncEnumerator(); + try + { + for (int i = 100; i < 110; i++) + { + Assert.True(source.Post(i)); + ValueTask vt = e.MoveNextAsync(); + Assert.True(vt.IsCompletedSuccessfully); + Assert.True(vt.Result); + Assert.Equal(i, e.Current); + } + } + finally + { + ValueTask vt = e.DisposeAsync(); + Assert.True(vt.IsCompletedSuccessfully); + vt.GetAwaiter().GetResult(); + } + } + + [Fact] + public async Task ReceiveAllAsync_UnavailableDataCompletesAsynchronously() + { + var source = new BufferBlock(); + + IAsyncEnumerator e = source.ReceiveAllAsync().GetAsyncEnumerator(); + try + { + for (int i = 100; i < 110; i++) + { + ValueTask vt = e.MoveNextAsync(); + Assert.False(vt.IsCompleted); + Task producer = Task.Run(() => source.Post(i)); + Assert.True(await vt); + await producer; + Assert.Equal(i, e.Current); + } + } + finally + { + ValueTask vt = e.DisposeAsync(); + Assert.True(vt.IsCompletedSuccessfully); + vt.GetAwaiter().GetResult(); + } + } + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(128)] + public async Task ReceiveAllAsync_ProducerConsumer_ConsumesAllData(int items) + { + var source = new BufferBlock(); + + int producedTotal = 0, consumedTotal = 0; + await Task.WhenAll( + Task.Run(async () => + { + for (int i = 0; i < items; i++) + { + await source.SendAsync(i); + producedTotal += i; + } + source.Complete(); + }), + Task.Run(async () => + { + IAsyncEnumerator e = source.ReceiveAllAsync().GetAsyncEnumerator(); + try + { + while (await e.MoveNextAsync()) + { + consumedTotal += e.Current; + } + } + finally + { + await e.DisposeAsync(); + } + })); + + Assert.Equal(producedTotal, consumedTotal); + } + + [Fact] + public async Task ReceiveAllAsync_MultipleEnumerationsToEnd() + { + var source = new BufferBlock(); + + Assert.True(source.Post(42)); + source.Complete(); + + IAsyncEnumerable enumerable = source.ReceiveAllAsync(); + IAsyncEnumerator e = enumerable.GetAsyncEnumerator(); + + Assert.True(await e.MoveNextAsync()); + Assert.Equal(42, e.Current); + + Assert.False(await e.MoveNextAsync()); + Assert.False(await e.MoveNextAsync()); + + await e.DisposeAsync(); + + e = enumerable.GetAsyncEnumerator(); + + Assert.False(await e.MoveNextAsync()); + Assert.False(await e.MoveNextAsync()); + } + + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public void ReceiveAllAsync_MultipleSingleElementEnumerations_AllItemsEnumerated(bool sameEnumerable, bool dispose) + { + var source = new BufferBlock(); + IAsyncEnumerable enumerable = source.ReceiveAllAsync(); + + for (int i = 0; i < 10; i++) + { + Assert.True(source.Post(i)); + IAsyncEnumerator e = (sameEnumerable ? enumerable : source.ReceiveAllAsync()).GetAsyncEnumerator(); + ValueTask vt = e.MoveNextAsync(); + Assert.True(vt.IsCompletedSuccessfully); + Assert.True(vt.Result); + Assert.Equal(i, e.Current); + if (dispose) + { + ValueTask dvt = e.DisposeAsync(); + Assert.True(dvt.IsCompletedSuccessfully); + dvt.GetAwaiter().GetResult(); + } + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task ReceiveAllAsync_DualConcurrentEnumeration_AllItemsEnumerated(bool sameEnumerable) + { + var source = new BufferBlock(); + + IAsyncEnumerable enumerable = source.ReceiveAllAsync(); + + IAsyncEnumerator e1 = enumerable.GetAsyncEnumerator(); + IAsyncEnumerator e2 = (sameEnumerable ? enumerable : source.ReceiveAllAsync()).GetAsyncEnumerator(); + Assert.NotSame(e1, e2); + + ValueTask vt1, vt2; + int producerTotal = 0, consumerTotal = 0; + for (int i = 0; i < 10; i++) + { + vt1 = e1.MoveNextAsync(); + vt2 = e2.MoveNextAsync(); + + await source.SendAsync(i); + producerTotal += i; + await source.SendAsync(i * 2); + producerTotal += i * 2; + + Assert.True(await vt1); + Assert.True(await vt2); + consumerTotal += e1.Current; + consumerTotal += e2.Current; + } + + vt1 = e1.MoveNextAsync(); + vt2 = e2.MoveNextAsync(); + source.Complete(); + Assert.False(await vt1); + Assert.False(await vt2); + + Assert.Equal(producerTotal, consumerTotal); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task ReceiveAllAsync_CanceledBeforeMoveNextAsync_Throws(bool dataAvailable) + { + var source = new BufferBlock(); + if (dataAvailable) + { + Assert.True(source.Post(42)); + } + + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + IAsyncEnumerator e = source.ReceiveAllAsync(cts.Token).GetAsyncEnumerator(); + ValueTask vt = e.MoveNextAsync(); + Assert.True(vt.IsCompleted); + Assert.False(vt.IsCompletedSuccessfully); + OperationCanceledException oce = await Assert.ThrowsAnyAsync(async () => await vt); + Assert.Equal(cts.Token, oce.CancellationToken); + } + + [Fact] + public async Task ReceiveAllAsync_CanceledAfterMoveNextAsync_Throws() + { + var source = new BufferBlock(); + using var cts = new CancellationTokenSource(); + + IAsyncEnumerator e = source.ReceiveAllAsync(cts.Token).GetAsyncEnumerator(); + ValueTask vt = e.MoveNextAsync(); + Assert.False(vt.IsCompleted); + + cts.Cancel(); + OperationCanceledException oce = await Assert.ThrowsAnyAsync(async () => await vt); + + vt = e.MoveNextAsync(); + Assert.True(vt.IsCompletedSuccessfully); + Assert.False(vt.Result); + } + } +} diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.cs b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.cs index be3d0060b45de..d761c6be0f756 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/Dataflow/DataflowBlockExtensionTests.cs @@ -8,7 +8,7 @@ namespace System.Threading.Tasks.Dataflow.Tests { - public class DataflowBlockExtensionsTests + public partial class DataflowBlockExtensionsTests { [Fact] public void TestDataflowMessageHeader() diff --git a/src/libraries/System.Threading.Tasks.Dataflow/tests/System.Threading.Tasks.Dataflow.Tests.csproj b/src/libraries/System.Threading.Tasks.Dataflow/tests/System.Threading.Tasks.Dataflow.Tests.csproj index f817822131366..d78224779d494 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/tests/System.Threading.Tasks.Dataflow.Tests.csproj +++ b/src/libraries/System.Threading.Tasks.Dataflow/tests/System.Threading.Tasks.Dataflow.Tests.csproj @@ -26,6 +26,9 @@ + + + From 17799a5a4dc2fcd5c4ba89819e2a105882f7a31f Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Sat, 6 Mar 2021 03:58:54 -0800 Subject: [PATCH 23/83] [AndroidCrypto] Implement DSA import/export and signing/verification. (#49153) Co-authored-by: Jeremy Barton --- .../Interop.Bignum.cs | 15 - .../Interop.Dsa.cs | 184 +++++++++ .../Interop.EcDsa.ImportExport.cs | 238 +++++------ .../Interop.Rsa.cs | 94 +++-- .../Security/Cryptography/DSAAndroid.cs | 389 ++++++++++++++++++ .../DSA/DSAImportExport.cs | 2 +- .../DSA/DSASignVerify.cs | 2 +- .../CMakeLists.txt | 1 + .../pal_dsa.c | 331 +++++++++++++++ .../pal_dsa.h | 81 ++++ .../pal_jni.c | 24 ++ .../pal_jni.h | 13 + .../pal_signature.c | 5 +- ...em.Security.Cryptography.Algorithms.csproj | 17 +- .../Cryptography/DSA.Create.Android.cs | 13 + .../tests/DSACreateTests.cs | 1 + 16 files changed, 1211 insertions(+), 199 deletions(-) create mode 100644 src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Dsa.cs create mode 100644 src/libraries/Common/src/System/Security/Cryptography/DSAAndroid.cs create mode 100644 src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_dsa.c create mode 100644 src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_dsa.h create mode 100644 src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.Create.Android.cs diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Bignum.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Bignum.cs index 30d5754627af8..0ceb04a871572 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Bignum.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Bignum.cs @@ -37,16 +37,6 @@ internal static SafeBignumHandle CreateBignum(ReadOnlySpan bigEndianValue) } } - internal static byte[]? ExtractBignum(IntPtr bignum, int targetSize) - { - // Given that the only reference held to bignum is an IntPtr, create an unowned SafeHandle - // to ensure that we don't destroy the key after extraction. - using (SafeBignumHandle handle = new SafeBignumHandle(bignum, ownsHandle: false)) - { - return ExtractBignum(handle, targetSize); - } - } - internal static unsafe byte[]? ExtractBignum(SafeBignumHandle? bignum, int targetSize) { if (bignum == null || bignum.IsInvalid) @@ -84,10 +74,5 @@ internal sealed class SafeBignumHandle : Interop.JObjectLifetime.SafeJObjectHand public SafeBignumHandle() { } - - internal SafeBignumHandle(IntPtr handle, bool ownsHandle) - : base(handle, ownsHandle) - { - } } } diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Dsa.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Dsa.cs new file mode 100644 index 0000000000000..4a9016729b565 --- /dev/null +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Dsa.cs @@ -0,0 +1,184 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class AndroidCrypto + { + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_DsaGenerateKey")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool DsaGenerateKey(out SafeDsaHandle dsa, int bits); + + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_DsaSizeSignature")] + private static extern int DsaSizeSignature(SafeDsaHandle dsa); + + /// + /// Return the maximum size of the DER-encoded key in bytes. + /// + internal static int DsaEncodedSignatureSize(SafeDsaHandle dsa) + { + int size = DsaSizeSignature(dsa); + return size; + } + + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_DsaSignatureFieldSize")] + private static extern int AndroidCryptoNative_DsaSignatureFieldSize(SafeDsaHandle dsa); + + /// + /// Return the size of the 'r' or 's' signature fields in bytes. + /// + internal static int DsaSignatureFieldSize(SafeDsaHandle dsa) + { + // Add another byte for the leading zero byte. + int size = AndroidCryptoNative_DsaSignatureFieldSize(dsa); + Debug.Assert(size * 2 < DsaEncodedSignatureSize(dsa)); + return size; + } + + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_DsaSizeP")] + private static extern int DsaSizeP(SafeDsaHandle dsa); + + /// + /// Return the size of the key in bytes. + /// + internal static int DsaKeySize(SafeDsaHandle dsa) + { + int keySize = DsaSizeP(dsa); + + // Assume an even multiple of 8 bytes \ 64 bits + keySize = (keySize + 7) / 8 * 8; + return keySize; + } + + internal static bool DsaSign(SafeDsaHandle dsa, ReadOnlySpan hash, Span refSignature, out int outSignatureLength) => + DsaSign(dsa, ref MemoryMarshal.GetReference(hash), hash.Length, ref MemoryMarshal.GetReference(refSignature), out outSignatureLength); + + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_DsaSign")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool DsaSign(SafeDsaHandle dsa, ref byte hash, int hashLength, ref byte refSignature, out int outSignatureLength); + + internal static bool DsaVerify(SafeDsaHandle dsa, ReadOnlySpan hash, ReadOnlySpan signature) + { + int ret = DsaVerify( + dsa, + ref MemoryMarshal.GetReference(hash), + hash.Length, + ref MemoryMarshal.GetReference(signature), + signature.Length); + + if (ret == -1) + { + throw new CryptographicException(); + } + + return ret == 1; + } + + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_DsaVerify")] + private static extern int DsaVerify(SafeDsaHandle dsa, ref byte hash, int hashLength, ref byte signature, int signatureLength); + + internal static DSAParameters ExportDsaParameters(SafeDsaHandle key, bool includePrivateParameters) + { + Debug.Assert( + key != null && !key.IsInvalid, + "Callers should check the key is invalid and throw an exception with a message"); + + if (key == null || key.IsInvalid) + { + throw new CryptographicException(); + } + + SafeBignumHandle p_bn, q_bn, g_bn, y_bn, x_bn; + int p_cb, q_cb, g_cb, y_cb, x_cb; + + if (!GetDsaParameters(key, + out p_bn, out p_cb, + out q_bn, out q_cb, + out g_bn, out g_cb, + out y_bn, out y_cb, + out x_bn, out x_cb)) + { + p_bn.Dispose(); + q_bn.Dispose(); + g_bn.Dispose(); + y_bn.Dispose(); + x_bn.Dispose(); + throw new CryptographicException(); + } + + using (p_bn) + using (q_bn) + using (g_bn) + using (y_bn) + using (x_bn) + { + // Match Windows semantics where p, g and y have same length + int pgy_cb = GetMax(p_cb, g_cb, y_cb); + + // Match Windows semantics where q and x have same length + int qx_cb = GetMax(q_cb, x_cb); + + DSAParameters dsaParameters = new DSAParameters + { + P = Crypto.ExtractBignum(p_bn, pgy_cb)!, + Q = Crypto.ExtractBignum(q_bn, qx_cb)!, + G = Crypto.ExtractBignum(g_bn, pgy_cb)!, + Y = Crypto.ExtractBignum(y_bn, pgy_cb)!, + }; + + if (includePrivateParameters) + { + dsaParameters.X = Crypto.ExtractBignum(x_bn, qx_cb); + } + + return dsaParameters; + } + } + + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_GetDsaParameters")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool GetDsaParameters( + SafeDsaHandle key, + out SafeBignumHandle p, out int p_cb, + out SafeBignumHandle q, out int q_cb, + out SafeBignumHandle g, out int g_cb, + out SafeBignumHandle y, out int y_cb, + out SafeBignumHandle x, out int x_cb); + + [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_DsaKeyCreateByExplicitParameters")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool DsaKeyCreateByExplicitParameters( + out SafeDsaHandle dsa, + byte[] p, + int pLength, + byte[] q, + int qLength, + byte[] g, + int gLength, + byte[] y, + int yLength, + byte[]? x, + int xLength); + } +} + +namespace System.Security.Cryptography +{ + internal sealed class SafeDsaHandle : Interop.JObjectLifetime.SafeJObjectHandle + { + public SafeDsaHandle() + { + } + + internal SafeDsaHandle(IntPtr ptr) + : base(ptr) + { + } + } +} diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.EcDsa.ImportExport.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.EcDsa.ImportExport.cs index c213f8a323f22..1b757f8814b54 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.EcDsa.ImportExport.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.EcDsa.ImportExport.cs @@ -97,28 +97,27 @@ private static extern int AndroidCryptoNative_GetECKeyParameters( bool includePrivate, out SafeBignumHandle qx_bn, out int x_cb, out SafeBignumHandle qy_bn, out int y_cb, - out IntPtr d_bn_not_owned, out int d_cb); + out SafeBignumHandle d_bn, out int d_cb); internal static ECParameters GetECKeyParameters( SafeEcKeyHandle key, bool includePrivate) { SafeBignumHandle qx_bn, qy_bn, d_bn; - IntPtr d_bn_not_owned; int qx_cb, qy_cb, d_cb; ECParameters parameters = default; - bool refAdded = false; - try - { - key.DangerousAddRef(ref refAdded); // Protect access to d_bn_not_owned - int rc = AndroidCryptoNative_GetECKeyParameters( - key, - includePrivate, - out qx_bn, out qx_cb, - out qy_bn, out qy_cb, - out d_bn_not_owned, out d_cb); + int rc = AndroidCryptoNative_GetECKeyParameters( + key, + includePrivate, + out qx_bn, out qx_cb, + out qy_bn, out qy_cb, + out d_bn, out d_cb); + using (qx_bn) + using (qy_bn) + using (d_bn) + { if (rc == -1) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); @@ -128,33 +127,23 @@ internal static ECParameters GetECKeyParameters( throw new CryptographicException(); } - using (qx_bn) - using (qy_bn) - using (d_bn = new SafeBignumHandle(d_bn_not_owned, false)) + // Match Windows semantics where qx, qy, and d have same length + int keySizeBits = EcKeyGetSize(key); + int expectedSize = (keySizeBits + 7) / 8; + int cbKey = GetMax(qx_cb, qy_cb, d_cb); + + Debug.Assert( + cbKey <= expectedSize, + $"Expected output size was {expectedSize}, which a parameter exceeded. qx={qx_cb}, qy={qy_cb}, d={d_cb}"); + + cbKey = GetMax(cbKey, expectedSize); + + parameters.Q = new ECPoint { - // Match Windows semantics where qx, qy, and d have same length - int keySizeBits = EcKeyGetSize(key); - int expectedSize = (keySizeBits + 7) / 8; - int cbKey = GetMax(qx_cb, qy_cb, d_cb); - - Debug.Assert( - cbKey <= expectedSize, - $"Expected output size was {expectedSize}, which a parameter exceeded. qx={qx_cb}, qy={qy_cb}, d={d_cb}"); - - cbKey = GetMax(cbKey, expectedSize); - - parameters.Q = new ECPoint - { - X = Crypto.ExtractBignum(qx_bn, cbKey), - Y = Crypto.ExtractBignum(qy_bn, cbKey) - }; - parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_bn, cbKey); - } - } - finally - { - if (refAdded) - key.DangerousRelease(); + X = Crypto.ExtractBignum(qx_bn, cbKey), + Y = Crypto.ExtractBignum(qy_bn, cbKey) + }; + parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_bn, cbKey); } return parameters; @@ -167,7 +156,7 @@ private static extern int AndroidCryptoNative_GetECCurveParameters( out ECCurve.ECCurveType curveType, out SafeBignumHandle qx, out int x_cb, out SafeBignumHandle qy, out int y_cb, - out IntPtr d_bn_not_owned, out int d_cb, + out SafeBignumHandle d, out int d_cb, out SafeBignumHandle p, out int P_cb, out SafeBignumHandle a, out int A_cb, out SafeBignumHandle b, out int B_cb, @@ -182,30 +171,37 @@ internal static ECParameters GetECCurveParameters( bool includePrivate) { ECCurve.ECCurveType curveType; - SafeBignumHandle qx_bn, qy_bn, p_bn, a_bn, b_bn, gx_bn, gy_bn, order_bn, cofactor_bn, seed_bn; - IntPtr d_bn_not_owned; + SafeBignumHandle qx_bn, qy_bn, p_bn, a_bn, b_bn, gx_bn, gy_bn, order_bn, cofactor_bn, seed_bn, d_bn; int qx_cb, qy_cb, p_cb, a_cb, b_cb, gx_cb, gy_cb, order_cb, cofactor_cb, seed_cb, d_cb; - bool refAdded = false; - try + int rc = AndroidCryptoNative_GetECCurveParameters( + key, + includePrivate, + out curveType, + out qx_bn, out qx_cb, + out qy_bn, out qy_cb, + out d_bn, out d_cb, + out p_bn, out p_cb, + out a_bn, out a_cb, + out b_bn, out b_cb, + out gx_bn, out gx_cb, + out gy_bn, out gy_cb, + out order_bn, out order_cb, + out cofactor_bn, out cofactor_cb, + out seed_bn, out seed_cb); + + using (qx_bn) + using (qy_bn) + using (p_bn) + using (a_bn) + using (b_bn) + using (gx_bn) + using (gy_bn) + using (order_bn) + using (cofactor_bn) + using (seed_bn) + using (d_bn) { - key.DangerousAddRef(ref refAdded); // Protect access to d_bn_not_owned - int rc = AndroidCryptoNative_GetECCurveParameters( - key, - includePrivate, - out curveType, - out qx_bn, out qx_cb, - out qy_bn, out qy_cb, - out d_bn_not_owned, out d_cb, - out p_bn, out p_cb, - out a_bn, out a_cb, - out b_bn, out b_cb, - out gx_bn, out gx_cb, - out gy_bn, out gy_cb, - out order_bn, out order_cb, - out cofactor_bn, out cofactor_cb, - out seed_bn, out seed_cb); - if (rc == -1) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); @@ -215,78 +211,60 @@ internal static ECParameters GetECCurveParameters( throw new CryptographicException(); } - using (qx_bn) - using (qy_bn) - using (p_bn) - using (a_bn) - using (b_bn) - using (gx_bn) - using (gy_bn) - using (order_bn) - using (cofactor_bn) - using (seed_bn) - using (var d_h = new SafeBignumHandle(d_bn_not_owned, false)) + int cbFieldLength; + int pFieldLength; + if (curveType == ECCurve.ECCurveType.Characteristic2) { - int cbFieldLength; - int pFieldLength; - if (curveType == ECCurve.ECCurveType.Characteristic2) - { - // Match Windows semantics where a,b,gx,gy,qx,qy have same length - // Treat length of m separately as it is not tied to other fields for Char2 (Char2 not supported by Windows) - cbFieldLength = GetMax(new[] { a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb }); - pFieldLength = p_cb; - } - else - { - // Match Windows semantics where p,a,b,gx,gy,qx,qy have same length - cbFieldLength = GetMax(new[] { p_cb, a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb }); - pFieldLength = cbFieldLength; - } - - // Match Windows semantics where order and d have same length - int cbSubgroupOrder = GetMax(order_cb, d_cb); - - // Copy values to ECParameters - ECParameters parameters = default; - parameters.Q = new ECPoint - { - X = Crypto.ExtractBignum(qx_bn, cbFieldLength), - Y = Crypto.ExtractBignum(qy_bn, cbFieldLength) - }; - parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_h, cbSubgroupOrder); - - var curve = parameters.Curve; - curve.CurveType = curveType; - curve.A = Crypto.ExtractBignum(a_bn, cbFieldLength)!; - curve.B = Crypto.ExtractBignum(b_bn, cbFieldLength)!; - curve.G = new ECPoint - { - X = Crypto.ExtractBignum(gx_bn, cbFieldLength), - Y = Crypto.ExtractBignum(gy_bn, cbFieldLength) - }; - curve.Order = Crypto.ExtractBignum(order_bn, cbSubgroupOrder)!; - - if (curveType == ECCurve.ECCurveType.Characteristic2) - { - curve.Polynomial = Crypto.ExtractBignum(p_bn, pFieldLength)!; - } - else - { - curve.Prime = Crypto.ExtractBignum(p_bn, pFieldLength)!; - } - - // Optional parameters - curve.Cofactor = cofactor_cb == 0 ? null : Crypto.ExtractBignum(cofactor_bn, cofactor_cb); - curve.Seed = seed_cb == 0 ? null : Crypto.ExtractBignum(seed_bn, seed_cb); - - parameters.Curve = curve; - return parameters; + // Match Windows semantics where a,b,gx,gy,qx,qy have same length + // Treat length of m separately as it is not tied to other fields for Char2 (Char2 not supported by Windows) + cbFieldLength = GetMax(new[] { a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb }); + pFieldLength = p_cb; } - } - finally - { - if (refAdded) - key.DangerousRelease(); + else + { + // Match Windows semantics where p,a,b,gx,gy,qx,qy have same length + cbFieldLength = GetMax(new[] { p_cb, a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb }); + pFieldLength = cbFieldLength; + } + + // Match Windows semantics where order and d have same length + int cbSubgroupOrder = GetMax(order_cb, d_cb); + + // Copy values to ECParameters + ECParameters parameters = default; + parameters.Q = new ECPoint + { + X = Crypto.ExtractBignum(qx_bn, cbFieldLength), + Y = Crypto.ExtractBignum(qy_bn, cbFieldLength) + }; + parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_bn, cbSubgroupOrder); + + var curve = parameters.Curve; + curve.CurveType = curveType; + curve.A = Crypto.ExtractBignum(a_bn, cbFieldLength)!; + curve.B = Crypto.ExtractBignum(b_bn, cbFieldLength)!; + curve.G = new ECPoint + { + X = Crypto.ExtractBignum(gx_bn, cbFieldLength), + Y = Crypto.ExtractBignum(gy_bn, cbFieldLength) + }; + curve.Order = Crypto.ExtractBignum(order_bn, cbSubgroupOrder)!; + + if (curveType == ECCurve.ECCurveType.Characteristic2) + { + curve.Polynomial = Crypto.ExtractBignum(p_bn, pFieldLength)!; + } + else + { + curve.Prime = Crypto.ExtractBignum(p_bn, pFieldLength)!; + } + + // Optional parameters + curve.Cofactor = cofactor_cb == 0 ? null : Crypto.ExtractBignum(cofactor_bn, cofactor_cb); + curve.Seed = seed_cb == 0 ? null : Crypto.ExtractBignum(seed_bn, seed_cb); + + parameters.Curve = curve; + return parameters; } } diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Rsa.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Rsa.cs index 7604b14fe7248..38d7dcf755938 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Rsa.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Rsa.cs @@ -102,61 +102,65 @@ internal static RSAParameters ExportRsaParameters(SafeRsaHandle key, bool includ throw new CryptographicException(); } - bool addedRef = false; - - try + SafeBignumHandle n, e, d, p, dmp1, q, dmq1, iqmp; + if (!GetRsaParameters(key, + out n, + out e, + out d, + out p, + out dmp1, + out q, + out dmq1, + out iqmp)) { - key.DangerousAddRef(ref addedRef); - - IntPtr n, e, d, p, dmp1, q, dmq1, iqmp; - if (!GetRsaParameters(key, out n, out e, out d, out p, out dmp1, out q, out dmq1, out iqmp)) - { - throw new CryptographicException(); - } - - int modulusSize = RsaSize(key); - - // RSACryptoServiceProvider expects P, DP, Q, DQ, and InverseQ to all - // be padded up to half the modulus size. - int halfModulus = modulusSize / 2; - - RSAParameters rsaParameters = new RSAParameters - { - Modulus = Crypto.ExtractBignum(n, modulusSize)!, - Exponent = Crypto.ExtractBignum(e, 0)!, - }; - - if (includePrivateParameters) - { - rsaParameters.D = Crypto.ExtractBignum(d, modulusSize); - rsaParameters.P = Crypto.ExtractBignum(p, halfModulus); - rsaParameters.DP = Crypto.ExtractBignum(dmp1, halfModulus); - rsaParameters.Q = Crypto.ExtractBignum(q, halfModulus); - rsaParameters.DQ = Crypto.ExtractBignum(dmq1, halfModulus); - rsaParameters.InverseQ = Crypto.ExtractBignum(iqmp, halfModulus); - } - - return rsaParameters; + n.Dispose(); + e.Dispose(); + d.Dispose(); + p.Dispose(); + dmp1.Dispose(); + q.Dispose(); + dmq1.Dispose(); + iqmp.Dispose(); + throw new CryptographicException(); } - finally + + int modulusSize = RsaSize(key); + + // RSACryptoServiceProvider expects P, DP, Q, DQ, and InverseQ to all + // be padded up to half the modulus size. + int halfModulus = modulusSize / 2; + + RSAParameters rsaParameters = new RSAParameters + { + Modulus = Crypto.ExtractBignum(n, modulusSize)!, + Exponent = Crypto.ExtractBignum(e, 0)!, + }; + + if (includePrivateParameters) { - if (addedRef) - key.DangerousRelease(); + rsaParameters.D = Crypto.ExtractBignum(d, modulusSize); + rsaParameters.P = Crypto.ExtractBignum(p, halfModulus); + rsaParameters.DP = Crypto.ExtractBignum(dmp1, halfModulus); + rsaParameters.Q = Crypto.ExtractBignum(q, halfModulus); + rsaParameters.DQ = Crypto.ExtractBignum(dmq1, halfModulus); + rsaParameters.InverseQ = Crypto.ExtractBignum(iqmp, halfModulus); } + + return rsaParameters; } [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_GetRsaParameters")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetRsaParameters( SafeRsaHandle key, - out IntPtr n, - out IntPtr e, - out IntPtr d, - out IntPtr p, - out IntPtr dmp1, - out IntPtr q, - out IntPtr dmq1, - out IntPtr iqmp); + out SafeBignumHandle n, + out SafeBignumHandle e, + out SafeBignumHandle d, + out SafeBignumHandle p, + out SafeBignumHandle dmp1, + out SafeBignumHandle q, + out SafeBignumHandle dmq1, + out SafeBignumHandle iqmp); [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SetRsaParameters")] [return: MarshalAs(UnmanagedType.Bool)] diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSAAndroid.cs b/src/libraries/Common/src/System/Security/Cryptography/DSAAndroid.cs new file mode 100644 index 0000000000000..83403d36fdde4 --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/DSAAndroid.cs @@ -0,0 +1,389 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.IO; +using Internal.Cryptography; +using Microsoft.Win32.SafeHandles; + +namespace System.Security.Cryptography +{ + internal static partial class DSAImplementation + { + public sealed partial class DSAAndroid : DSA + { + // The biggest key allowed by FIPS 186-4 has N=256 (bit), which + // maximally produces a 72-byte DER signature. + // If a future version of the standard continues to enhance DSA, + // we may want to bump this limit to allow the max-1 (expected size) + // TryCreateSignature to pass. + // Future updates seem unlikely, though, as FIPS 186-5 October 2019 draft has + // DSA as a no longer supported/updated algorithm. + private const int SignatureStackBufSize = 72; + private const int BitsPerByte = 8; + + private Lazy _key = null!; + + public DSAAndroid() + : this(2048) + { + } + + public DSAAndroid(int keySize) + { + LegalKeySizesValue = s_legalKeySizes; + base.KeySize = keySize; + _key = new Lazy(GenerateKey); + } + + public override int KeySize + { + set + { + if (KeySize == value) + { + return; + } + + // Set the KeySize before FreeKey so that an invalid value doesn't throw away the key + base.KeySize = value; + + ThrowIfDisposed(); + FreeKey(); + _key = new Lazy(GenerateKey); + } + } + + private void ForceSetKeySize(int newKeySize) + { + // In the event that a key was loaded via ImportParameters or an IntPtr/SafeHandle + // it could be outside of the bounds that we currently represent as "legal key sizes". + // Since that is our view into the underlying component it can be detached from the + // component's understanding. If it said it has opened a key, and this is the size, trust it. + KeySizeValue = newKeySize; + } + + public override KeySizes[] LegalKeySizes + { + get + { + return base.LegalKeySizes; + } + } + + public override DSAParameters ExportParameters(bool includePrivateParameters) + { + // It's entirely possible that this line will cause the key to be generated in the first place. + SafeDsaHandle key = GetKey(); + + DSAParameters dsaParameters = Interop.AndroidCrypto.ExportDsaParameters(key, includePrivateParameters); + bool hasPrivateKey = dsaParameters.X != null; + + if (hasPrivateKey != includePrivateParameters) + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); + + return dsaParameters; + } + + public override void ImportParameters(DSAParameters parameters) + { + if (parameters.P == null || parameters.Q == null || parameters.G == null || parameters.Y == null) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MissingFields); + + // J is not required and is not even used on CNG blobs. It should however be less than P (J == (P-1) / Q). This validation check + // is just to maintain parity with DSACNG and DSACryptoServiceProvider, which also perform this check. + if (parameters.J != null && parameters.J.Length >= parameters.P.Length) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPJ); + + bool hasPrivateKey = parameters.X != null; + + int keySize = parameters.P.Length; + if (parameters.G.Length != keySize || parameters.Y.Length != keySize) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPGY); + + if (hasPrivateKey && parameters.X!.Length != parameters.Q.Length) + throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedQX); + + ThrowIfDisposed(); + + SafeDsaHandle key; + if (!Interop.AndroidCrypto.DsaKeyCreateByExplicitParameters( + out key, + parameters.P, parameters.P.Length, + parameters.Q, parameters.Q.Length, + parameters.G, parameters.G.Length, + parameters.Y, parameters.Y.Length, + parameters.X, parameters.X != null ? parameters.X.Length : 0)) + { + throw new CryptographicException(); + } + + SetKey(key); + } + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan passwordBytes, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead); + } + + public override void ImportEncryptedPkcs8PrivateKey( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead) + { + ThrowIfDisposed(); + base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + FreeKey(); + _key = null!; + } + + base.Dispose(disposing); + } + + private void FreeKey() + { + if (_key != null && _key.IsValueCreated) + { + SafeDsaHandle handle = _key.Value; + + if (handle != null) + { + handle.Dispose(); + } + } + } + + private static void CheckInvalidKey(SafeDsaHandle key) + { + if (key == null || key.IsInvalid) + { + throw new CryptographicException(SR.Cryptography_OpenInvalidHandle); + } + } + + private SafeDsaHandle GenerateKey() + { + SafeDsaHandle key; + + if (!Interop.AndroidCrypto.DsaGenerateKey(out key, KeySize)) + { + throw new CryptographicException(); + } + + return key; + } + + protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) + { + // we're sealed and the base should have checked this already + Debug.Assert(data != null); + Debug.Assert(offset >= 0 && offset <= data.Length); + Debug.Assert(count >= 0 && count <= data.Length); + Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name)); + + return AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm); + } + + protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) => + AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm); + + protected override bool TryHashData(ReadOnlySpan data, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) => + AsymmetricAlgorithmHelpers.TryHashData(data, destination, hashAlgorithm, out bytesWritten); + + public override byte[] CreateSignature(byte[] rgbHash) + { + if (rgbHash == null) + throw new ArgumentNullException(nameof(rgbHash)); + + SafeDsaHandle key = GetKey(); + int signatureSize = Interop.AndroidCrypto.DsaEncodedSignatureSize(key); + int signatureFieldSize = Interop.AndroidCrypto.DsaSignatureFieldSize(key) * BitsPerByte; + Span signDestination = stackalloc byte[SignatureStackBufSize]; + + ReadOnlySpan derSignature = SignHash(rgbHash, signDestination, signatureSize, key); + return AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, signatureFieldSize); + } + + public override bool TryCreateSignature( + ReadOnlySpan hash, + Span destination, + out int bytesWritten) + { + return TryCreateSignatureCore( + hash, + destination, + DSASignatureFormat.IeeeP1363FixedFieldConcatenation, + out bytesWritten); + } + + protected override bool TryCreateSignatureCore( + ReadOnlySpan hash, + Span destination, + DSASignatureFormat signatureFormat, + out int bytesWritten) + { + SafeDsaHandle key = GetKey(); + int maxSignatureSize = Interop.AndroidCrypto.DsaEncodedSignatureSize(key); + Span signDestination = stackalloc byte[SignatureStackBufSize]; + + if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) + { + int fieldSizeBytes = Interop.AndroidCrypto.DsaSignatureFieldSize(key); + int p1363SignatureSize = 2 * fieldSizeBytes; + + if (destination.Length < p1363SignatureSize) + { + bytesWritten = 0; + return false; + } + + int fieldSizeBits = fieldSizeBytes * 8; + ReadOnlySpan derSignature = SignHash(hash, signDestination, maxSignatureSize, key); + bytesWritten = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, fieldSizeBits, destination); + Debug.Assert(bytesWritten == p1363SignatureSize); + return true; + } + else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence) + { + if (destination.Length >= maxSignatureSize) + { + signDestination = destination; + } + else if (maxSignatureSize > signDestination.Length) + { + Debug.Fail($"Stack-based signDestination is insufficient ({maxSignatureSize} needed)"); + bytesWritten = 0; + return false; + } + + ReadOnlySpan derSignature = SignHash(hash, signDestination, maxSignatureSize, key); + + if (destination == signDestination) + { + bytesWritten = derSignature.Length; + return true; + } + + return Helpers.TryCopyToDestination(derSignature, destination, out bytesWritten); + } + else + { + Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); + throw new CryptographicException( + SR.Cryptography_UnknownSignatureFormat, + signatureFormat.ToString()); + } + } + + private static ReadOnlySpan SignHash( + ReadOnlySpan hash, + Span destination, + int signatureLength, + SafeDsaHandle key) + { + if (signatureLength > destination.Length) + { + Debug.Fail($"Stack-based signDestination is insufficient ({signatureLength} needed)"); + destination = new byte[signatureLength]; + } + + if (!Interop.AndroidCrypto.DsaSign(key, hash, destination, out int actualLength)) + { + throw new CryptographicException(); + } + + Debug.Assert( + actualLength <= signatureLength, + "DSA_sign reported an unexpected signature size", + "DSA_sign reported signatureSize was {0}, when <= {1} was expected", + actualLength, + signatureLength); + + return destination.Slice(0, actualLength); + } + + public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) + { + if (rgbHash == null) + throw new ArgumentNullException(nameof(rgbHash)); + if (rgbSignature == null) + throw new ArgumentNullException(nameof(rgbSignature)); + + return VerifySignature((ReadOnlySpan)rgbHash, (ReadOnlySpan)rgbSignature); + } + + + public override bool VerifySignature(ReadOnlySpan hash, ReadOnlySpan signature) => + VerifySignatureCore(hash, signature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation); + + protected override bool VerifySignatureCore( + ReadOnlySpan hash, + ReadOnlySpan signature, + DSASignatureFormat signatureFormat) + { + SafeDsaHandle key = GetKey(); + + if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation) + { + int expectedSignatureBytes = Interop.AndroidCrypto.DsaSignatureFieldSize(key) * 2; + if (signature.Length != expectedSignatureBytes) + { + // The input isn't of the right length (assuming no DER), so we can't sensibly re-encode it with DER. + return false; + } + + signature = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature); + } + else if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence) + { + Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}"); + throw new CryptographicException( + SR.Cryptography_UnknownSignatureFormat, + signatureFormat.ToString()); + } + return Interop.AndroidCrypto.DsaVerify(key, hash, signature); + } + + private void ThrowIfDisposed() + { + if (_key == null) + { + throw new ObjectDisposedException(nameof(DSA)); + } + } + + private SafeDsaHandle GetKey() + { + ThrowIfDisposed(); + + SafeDsaHandle key = _key.Value; + CheckInvalidKey(key); + + return key; + } + + private void SetKey(SafeDsaHandle newKey) + { + // Do not call ThrowIfDisposed here, as it breaks the SafeEvpPKey ctor + + // Use ForceSet instead of the property setter to ensure that LegalKeySizes doesn't interfere + // with the already loaded key. + ForceSetKeySize(BitsPerByte * Interop.AndroidCrypto.DsaKeySize(newKey)); + + _key = new Lazy(newKey); + } + + private static readonly KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(minSize: 1024, maxSize: 3072, skipSize: 1024) }; + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAImportExport.cs index 3e2a708fa9478..fc75cc836957d 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAImportExport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAImportExport.cs @@ -137,7 +137,7 @@ public static void ImportRoundTrip(bool includePrivate) [InlineData(true)] public static void ExportAfterDispose(bool importKey) { - DSA key = importKey ? DSAFactory.Create(DSATestData.GetDSA1024Params()) : DSAFactory.Create(512); + DSA key = importKey ? DSAFactory.Create(DSATestData.GetDSA1024Params()) : DSAFactory.Create(1024); byte[] hash = new byte[20]; // Ensure that the key got created, and then Dispose it. diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs index 5db9c9e88433d..559fa81fc248e 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs @@ -143,7 +143,7 @@ public void UseAfterDispose_ImportedKey() private void UseAfterDispose(bool importKey) { - DSA key = importKey ? DSAFactory.Create(DSATestData.GetDSA1024Params()) : DSAFactory.Create(512); + DSA key = importKey ? DSAFactory.Create(DSATestData.GetDSA1024Params()) : DSAFactory.Create(1024); byte[] data = { 1 }; byte[] sig; diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/CMakeLists.txt b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/CMakeLists.txt index 444f744f07f00..51b1466554dc1 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/CMakeLists.txt +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/CMakeLists.txt @@ -6,6 +6,7 @@ add_compile_options(-Wno-unused-function) set(NATIVECRYPTO_SOURCES pal_bignum.c + pal_dsa.c pal_ecdsa.c pal_ecc_import_export.c pal_eckey.c diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_dsa.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_dsa.c new file mode 100644 index 0000000000000..7fcf57658bf54 --- /dev/null +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_dsa.c @@ -0,0 +1,331 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "pal_dsa.h" +#include "pal_utilities.h" +#include "pal_signature.h" +#include "pal_bignum.h" + +#define INIT_LOCALS(name, ...) \ + enum { __VA_ARGS__, count_##name }; \ + jobject name[count_##name] = { 0 } \ + +#define RELEASE_LOCALS_ENV(name, releaseFn) \ +do { \ + for (int i = 0; i < count_##name; ++i) \ + { \ + releaseFn(env, name[i]); \ + } \ +} while(0) + +int32_t AndroidCryptoNative_DsaGenerateKey(jobject* dsa, int32_t bits) +{ + assert(dsa); + + // KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); + // kpg.initialize(bits); + // KeyPair kp = kpg.genKeyPair(); + + JNIEnv* env = GetJNIEnv(); + jobject dsaStr = JSTRING("DSA"); + jobject kpgObj = (*env)->CallStaticObjectMethod(env, g_keyPairGenClass, g_keyPairGenGetInstanceMethod, dsaStr); + (*env)->DeleteLocalRef(env, dsaStr); + if (CheckJNIExceptions(env)) + { + return FAIL; + } + + (*env)->CallVoidMethod(env, kpgObj, g_keyPairGenInitializeMethod, bits); + if (CheckJNIExceptions(env)) + { + (*env)->DeleteLocalRef(env, kpgObj); + return FAIL; + } + jobject keyPair = (*env)->CallObjectMethod(env, kpgObj, g_keyPairGenGenKeyPairMethod); + (*env)->DeleteLocalRef(env, kpgObj); + if (CheckJNIExceptions(env)) + { + return FAIL; + } + *dsa = ToGRef(env, keyPair); + return SUCCESS; +} + +static jobject GetQParameter(JNIEnv* env, jobject dsa) +{ + assert(dsa); + + INIT_LOCALS(loc, algName, keyFactory, publicKey, publicKeySpec); + loc[algName] = JSTRING("DSA"); + loc[keyFactory] = (*env)->CallStaticObjectMethod(env, g_KeyFactoryClass, g_KeyFactoryGetInstanceMethod, loc[algName]); + loc[publicKey] = (*env)->CallObjectMethod(env, dsa, g_keyPairGetPublicMethod); + loc[publicKeySpec] = (*env)->CallObjectMethod(env, loc[keyFactory], g_KeyFactoryGetKeySpecMethod, loc[publicKey], g_DSAPublicKeySpecClass); + ON_EXCEPTION_PRINT_AND_GOTO(error); + + jobject q = (*env)->CallObjectMethod(env, loc[publicKeySpec], g_DSAPublicKeySpecGetQ); + ON_EXCEPTION_PRINT_AND_GOTO(error); + + return q; + +error: + RELEASE_LOCALS_ENV(loc, ReleaseLRef); + return FAIL; +} + +int32_t AndroidCryptoNative_DsaSizeSignature(jobject dsa) +{ + assert(dsa); + + // The maximum size of a signature for the provided key is 2* bitlength of Q + extra bytes for the DER + // encoding. The DER encoding is as follows (with R and S being the components of the signature and all lengths + // being one byte width): + // - SEQUENCE INTEGER INTEGER + // As a result, we see that there are 6 additional bytes in the DER encoding than the lengths of R and S combined. + // As the DSA algorithm is defined, the maximum length of R and S each is the bitlength of Q, so as a + // result we get the maximum size as 2 * bitlength of Q + 6. + const int derEncodingBytes = 6; + JNIEnv* env = GetJNIEnv(); + jobject q = GetQParameter(env, dsa); + if (!q) + { + return -1; + } + // Add one for a possible leading zero byte to force the sign to positive. + int byteLength = AndroidCryptoNative_GetBigNumBytesIncludingPaddingByteForSign(q); + ReleaseLRef(env, q); + + return 2 * byteLength + derEncodingBytes; +} + +int32_t AndroidCryptoNative_DsaSizeP(jobject dsa) +{ + assert(dsa); + + JNIEnv* env = GetJNIEnv(); + INIT_LOCALS(loc, algName, keyFactory, publicKey, publicKeySpec, p); + loc[algName] = JSTRING("DSA"); + loc[keyFactory] = (*env)->CallStaticObjectMethod(env, g_KeyFactoryClass, g_KeyFactoryGetInstanceMethod, loc[algName]); + loc[publicKey] = (*env)->CallObjectMethod(env, dsa, g_keyPairGetPublicMethod); + loc[publicKeySpec] = (*env)->CallObjectMethod(env, loc[keyFactory], g_KeyFactoryGetKeySpecMethod, loc[publicKey], g_DSAPublicKeySpecClass); + ON_EXCEPTION_PRINT_AND_GOTO(error); + + loc[p] = (*env)->CallObjectMethod(env, loc[publicKeySpec], g_DSAPublicKeySpecGetP); + ON_EXCEPTION_PRINT_AND_GOTO(error); + + int32_t bytes = AndroidCryptoNative_GetBigNumBytes(loc[p]); + RELEASE_LOCALS_ENV(loc, ReleaseLRef); + return bytes; + +error: + RELEASE_LOCALS_ENV(loc, ReleaseLRef); + return -1; +} + +int32_t AndroidCryptoNative_DsaSignatureFieldSize(jobject dsa) +{ + JNIEnv* env = GetJNIEnv(); + jobject q = GetQParameter(env, dsa); + if (!q) + { + return -1; + } + int byteLength = AndroidCryptoNative_GetBigNumBytes(q); + ReleaseLRef(env, q); + return byteLength; +} + +static jobject GetDsaSignatureObject(JNIEnv* env) +{ + jstring algorithmName = JSTRING("NONEwithDSA"); + jobject signatureObject = + (*env)->CallStaticObjectMethod(env, g_SignatureClass, g_SignatureGetInstance, algorithmName); + (*env)->DeleteLocalRef(env, algorithmName); + if (CheckJNIExceptions(env)) + return NULL; + return signatureObject; +} + +int32_t AndroidCryptoNative_DsaSign( + jobject dsa, + const uint8_t* hash, + int32_t hashLength, + uint8_t* refsignature, + int32_t* outSignatureLength) +{ + assert(hash); + assert(refsignature); + assert(dsa); + if (!outSignatureLength) + { + return FAIL; + } + + JNIEnv* env = GetJNIEnv(); + + jobject signatureObject = GetDsaSignatureObject(env); + if (!signatureObject) + { + return FAIL; + } + + jobject privateKey = (*env)->CallObjectMethod(env, dsa, g_keyPairGetPrivateMethod); + if (!privateKey) + { + ReleaseLRef(env, signatureObject); + return FAIL; + } + + int32_t returnValue = AndroidCryptoNative_SignWithSignatureObject(env, signatureObject, privateKey, hash, hashLength, refsignature, outSignatureLength); + ReleaseLRef(env, privateKey); + ReleaseLRef(env, signatureObject); + return returnValue; +} + +int32_t AndroidCryptoNative_DsaVerify( + jobject dsa, + const uint8_t* hash, + int32_t hashLength, + uint8_t* signature, + int32_t signatureLength) +{ + assert(hash); + assert(signature); + assert(dsa); + JNIEnv* env = GetJNIEnv(); + + jobject signatureObject = GetDsaSignatureObject(env); + if (!signatureObject) + { + return FAIL; + } + + jobject publicKey = (*env)->CallObjectMethod(env, dsa, g_keyPairGetPublicMethod); + int32_t returnValue = AndroidCryptoNative_VerifyWithSignatureObject(env, signatureObject, publicKey, hash, hashLength, signature, signatureLength); + ReleaseLRef(env, publicKey); + ReleaseLRef(env, signatureObject); + return returnValue; +} + +int32_t AndroidCryptoNative_GetDsaParameters( + jobject dsa, + jobject* p, int32_t* pLength, + jobject* q, int32_t* qLength, + jobject* g, int32_t* gLength, + jobject* y, int32_t* yLength, + jobject* x, int32_t* xLength) +{ + assert(dsa); + assert(p); + assert(q); + assert(g); + assert(y); + assert(x); + assert(pLength); + assert(qLength); + assert(gLength); + assert(yLength); + assert(xLength); + + JNIEnv* env = GetJNIEnv(); + + INIT_LOCALS(loc, algName, keyFactory, publicKey, publicKeySpec, privateKey, privateKeySpec); + + loc[algName] = JSTRING("DSA"); + loc[keyFactory] = (*env)->CallStaticObjectMethod(env, g_KeyFactoryClass, g_KeyFactoryGetInstanceMethod, loc[algName]); + loc[publicKey] = (*env)->CallObjectMethod(env, dsa, g_keyPairGetPublicMethod); + loc[publicKeySpec] = (*env)->CallObjectMethod(env, loc[keyFactory], g_KeyFactoryGetKeySpecMethod, loc[publicKey], g_DSAPublicKeySpecClass); + ON_EXCEPTION_PRINT_AND_GOTO(error); + + *p = ToGRef(env, (*env)->CallObjectMethod(env, loc[publicKeySpec], g_DSAPublicKeySpecGetP)); + *q = ToGRef(env, (*env)->CallObjectMethod(env, loc[publicKeySpec], g_DSAPublicKeySpecGetQ)); + *g = ToGRef(env, (*env)->CallObjectMethod(env, loc[publicKeySpec], g_DSAPublicKeySpecGetG)); + *y = ToGRef(env, (*env)->CallObjectMethod(env, loc[publicKeySpec], g_DSAPublicKeySpecGetY)); + *pLength = AndroidCryptoNative_GetBigNumBytes(*p); + *qLength = AndroidCryptoNative_GetBigNumBytes(*q); + *gLength = AndroidCryptoNative_GetBigNumBytes(*g); + *yLength = AndroidCryptoNative_GetBigNumBytes(*y); + + *x = NULL; + *xLength = 0; + loc[privateKey] = (*env)->CallObjectMethod(env, dsa, g_keyPairGetPrivateMethod); + if (loc[privateKey]) + { + loc[privateKeySpec] = (*env)->CallObjectMethod(env, loc[keyFactory], g_KeyFactoryGetKeySpecMethod, loc[privateKey], g_DSAPrivateKeySpecClass); + ON_EXCEPTION_PRINT_AND_GOTO(error); + *x = ToGRef(env, (*env)->CallObjectMethod(env, loc[privateKeySpec], g_DSAPrivateKeySpecGetX)); + *xLength = AndroidCryptoNative_GetBigNumBytes(*x); + } + + RELEASE_LOCALS_ENV(loc, ReleaseLRef); + return CheckJNIExceptions(env) ? FAIL : SUCCESS; + +error: + RELEASE_LOCALS_ENV(loc, ReleaseLRef); + return FAIL; +} + +int32_t AndroidCryptoNative_DsaKeyCreateByExplicitParameters( + jobject* outDsa, + uint8_t* p, + int32_t pLength, + uint8_t* q, + int32_t qLength, + uint8_t* g, + int32_t gLength, + uint8_t* y, + int32_t yLength, + uint8_t* x, + int32_t xLength) +{ + if (!outDsa) + { + assert(false); + return 0; + } + + JNIEnv* env = GetJNIEnv(); + + INIT_LOCALS(bn, P, Q, G, Y, X); + INIT_LOCALS(loc, publicKeySpec, privateKeySpec, publicKey, privateKey, dsa, keyFactory); + + bn[P] = AndroidCryptoNative_BigNumFromBinary(p, pLength); + bn[Q] = AndroidCryptoNative_BigNumFromBinary(q, qLength); + bn[G] = AndroidCryptoNative_BigNumFromBinary(g, gLength); + bn[Y] = AndroidCryptoNative_BigNumFromBinary(y, yLength); + loc[publicKeySpec] = (*env)->NewObject(env, g_DSAPublicKeySpecClass, g_DSAPublicKeySpecCtor, bn[Y], bn[P], bn[Q], bn[G]); + + if (x) + { + bn[X] = AndroidCryptoNative_BigNumFromBinary(x, xLength); + loc[privateKeySpec] = (*env)->NewObject(env, g_DSAPrivateKeySpecClass, g_DSAPrivateKeySpecCtor, bn[X], bn[P], bn[Q], bn[G]); + } + + loc[dsa] = JSTRING("DSA"); + loc[keyFactory] = (*env)->CallStaticObjectMethod(env, g_KeyFactoryClass, g_KeyFactoryGetInstanceMethod, loc[dsa]); + loc[publicKey] = (*env)->CallObjectMethod(env, loc[keyFactory], g_KeyFactoryGenPublicMethod, loc[publicKeySpec]); + ON_EXCEPTION_PRINT_AND_GOTO(error); + + if (loc[privateKeySpec]) + { + loc[privateKey] = (*env)->CallObjectMethod(env, loc[keyFactory], g_KeyFactoryGenPrivateMethod, loc[privateKeySpec]); + ON_EXCEPTION_PRINT_AND_GOTO(error); + } + + jobject keyPair = (*env)->NewObject(env, g_keyPairClass, g_keyPairCtor, loc[publicKey], loc[privateKey]); + *outDsa = ToGRef(env, keyPair); + if (CheckJNIExceptions(env)) + { + ON_EXCEPTION_PRINT_AND_GOTO(error); + } + + int32_t returnValue = SUCCESS; + goto cleanup; + +error: + returnValue = FAIL; +cleanup: + RELEASE_LOCALS_ENV(bn, ReleaseGRef); + RELEASE_LOCALS_ENV(loc, ReleaseLRef); + + return returnValue; +} diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_dsa.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_dsa.h new file mode 100644 index 0000000000000..67b77ffc035ec --- /dev/null +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_dsa.h @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma once + +#include "pal_types.h" +#include "pal_compiler.h" +#include "pal_jni.h" + +/* +Generates a key pair of `bits` bits wide. + +Returns 1 upon success, otherwise 0. +*/ +PALEXPORT int32_t AndroidCryptoNative_DsaGenerateKey(jobject* dsa, int32_t bits); + +/* +Returns the size of the ASN.1 encoded signature. +*/ +PALEXPORT int32_t AndroidCryptoNative_DsaSizeSignature(jobject dsa); + +/* +Returns the size of the p parameter in bytes. +*/ +PALEXPORT int32_t AndroidCryptoNative_DsaSizeP(jobject dsa); + +/* +Returns the size of one of the biginteger fields in a P1363 signature in bytes. +*/ +PALEXPORT int32_t AndroidCryptoNative_DsaSignatureFieldSize(jobject dsa); + +/* +Returns 1 upon success, otherwise 0. +*/ +PALEXPORT int32_t +AndroidCryptoNative_DsaSign( + jobject dsa, + const uint8_t* hash, + int32_t hashLength, + uint8_t* signature, + int32_t* outSignatureLength); + +/* +Returns 1 upon success, 0 upon verification mismatch, -1 on internal failure. +*/ +PALEXPORT int32_t +AndroidCryptoNative_DsaVerify( + jobject dsa, + const uint8_t* hash, + int32_t hashLength, + uint8_t* signature, + int32_t signatureLength); + +/* +Gets all the parameters from the DSA instance. + +Returns 1 upon success, otherwise 0. +*/ +PALEXPORT int32_t AndroidCryptoNative_GetDsaParameters( + jobject dsa, + jobject* p, int32_t* pLength, + jobject* q, int32_t* qLength, + jobject* g, int32_t* gLength, + jobject* y, int32_t* yLength, + jobject* x, int32_t* xLength); + +/* +Sets all the parameters on the DSA instance. +*/ +PALEXPORT int32_t AndroidCryptoNative_DsaKeyCreateByExplicitParameters( + jobject* dsa, + uint8_t* p, + int32_t pLength, + uint8_t* q, + int32_t qLength, + uint8_t* g, + int32_t gLength, + uint8_t* y, + int32_t yLength, + uint8_t* x, + int32_t xLength); diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c index 48bea370911f9..5721eedc37b8b 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c @@ -159,6 +159,19 @@ jmethodID g_KeyFactoryGenPrivateMethod; jmethodID g_KeyFactoryGenPublicMethod; jmethodID g_KeyFactoryGetKeySpecMethod; +// java/security/spec/DSAPublicKeySpec +jclass g_DSAPublicKeySpecClass; +jmethodID g_DSAPublicKeySpecCtor; +jmethodID g_DSAPublicKeySpecGetY; +jmethodID g_DSAPublicKeySpecGetP; +jmethodID g_DSAPublicKeySpecGetQ; +jmethodID g_DSAPublicKeySpecGetG; + +// java/security/spec/DSAPrivateKeySpec +jclass g_DSAPrivateKeySpecClass; +jmethodID g_DSAPrivateKeySpecCtor; +jmethodID g_DSAPrivateKeySpecGetX; + // java/security/spec/ECParameterSpec jclass g_ECParameterSpecClass; jmethodID g_ECParameterSpecCtor; @@ -564,6 +577,17 @@ JNI_OnLoad(JavaVM *vm, void *reserved) g_KeyFactoryGenPublicMethod = GetMethod(env, false, g_KeyFactoryClass, "generatePublic", "(Ljava/security/spec/KeySpec;)Ljava/security/PublicKey;"); g_KeyFactoryGetKeySpecMethod = GetMethod(env, false, g_KeyFactoryClass, "getKeySpec", "(Ljava/security/Key;Ljava/lang/Class;)Ljava/security/spec/KeySpec;"); + g_DSAPublicKeySpecClass = GetClassGRef(env, "java/security/spec/DSAPublicKeySpec"); + g_DSAPublicKeySpecCtor = GetMethod(env, false, g_DSAPublicKeySpecClass, "", "(Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); + g_DSAPublicKeySpecGetY = GetMethod(env, false, g_DSAPublicKeySpecClass, "getY", "()Ljava/math/BigInteger;"); + g_DSAPublicKeySpecGetP = GetMethod(env, false, g_DSAPublicKeySpecClass, "getP", "()Ljava/math/BigInteger;"); + g_DSAPublicKeySpecGetQ = GetMethod(env, false, g_DSAPublicKeySpecClass, "getQ", "()Ljava/math/BigInteger;"); + g_DSAPublicKeySpecGetG = GetMethod(env, false, g_DSAPublicKeySpecClass, "getG", "()Ljava/math/BigInteger;"); + + g_DSAPrivateKeySpecClass = GetClassGRef(env, "java/security/spec/DSAPrivateKeySpec"); + g_DSAPrivateKeySpecGetX = GetMethod(env, false, g_DSAPrivateKeySpecClass, "getX", "()Ljava/math/BigInteger;"); + g_DSAPrivateKeySpecCtor = GetMethod(env, false, g_DSAPrivateKeySpecClass, "", "(Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;)V"); + g_ECGenParameterSpecClass = GetClassGRef(env, "java/security/spec/ECGenParameterSpec"); g_ECGenParameterSpecCtor = GetMethod(env, false, g_ECGenParameterSpecClass, "", "(Ljava/lang/String;)V"); diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h index 972bc2d317c2b..252565fb0c934 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h @@ -168,6 +168,19 @@ extern jmethodID g_KeyFactoryGenPrivateMethod; extern jmethodID g_KeyFactoryGenPublicMethod; extern jmethodID g_KeyFactoryGetKeySpecMethod; +// java/security/spec/DSAPublicKeySpec +extern jclass g_DSAPublicKeySpecClass; +extern jmethodID g_DSAPublicKeySpecCtor; +extern jmethodID g_DSAPublicKeySpecGetY; +extern jmethodID g_DSAPublicKeySpecGetP; +extern jmethodID g_DSAPublicKeySpecGetQ; +extern jmethodID g_DSAPublicKeySpecGetG; + +// java/security/spec/DSAPrivateKeySpec +extern jclass g_DSAPrivateKeySpecClass; +extern jmethodID g_DSAPrivateKeySpecCtor; +extern jmethodID g_DSAPrivateKeySpecGetX; + // java/security/spec/ECField extern jclass g_ECFieldClass; extern jmethodID g_ECFieldGetFieldSize; diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_signature.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_signature.c index 5a90c62daa722..50da0effb4d28 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_signature.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_signature.c @@ -67,10 +67,13 @@ int32_t AndroidCryptoNative_VerifyWithSignatureObject(JNIEnv* env, (*env)->SetByteArrayRegion(env, sigArray, 0, siglen, (const jbyte*)sig); jboolean verified = (*env)->CallBooleanMethod(env, signatureObject, g_SignatureVerify, sigArray); ReleaseLRef(env, sigArray); - ON_EXCEPTION_PRINT_AND_GOTO(error); + ON_EXCEPTION_PRINT_AND_GOTO(verifyFail); return verified ? SUCCESS : FAIL; error: return SIGNATURE_VERIFICATION_ERROR; + +verifyFail: + return FAIL; } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj index 465a7575d3e47..32c81f891e1b6 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj @@ -446,8 +446,6 @@ Link="Common\Interop\Unix\System.Security.Cryptography.Native\Interop.ASN1.cs" /> - - - @@ -607,12 +601,20 @@ Link="Common\System\Security\Cryptography\RSAOpenSsl.cs" /> + + + + + + Date: Sat, 6 Mar 2021 11:15:50 -0800 Subject: [PATCH 24/83] JIT: update non-null assertion prop to destructure VNs (#49238) In addition to checking for assertions based on the VN of an address, try and destructure the VN to find the "base" address, and check its VNs as well. This lets us get rid of some extra null checks, typically ones that are at an offset from an existing non-null pointer. Closes #49180. --- src/coreclr/jit/assertionprop.cpp | 124 ++++++++++++++++++++++-------- src/coreclr/jit/compiler.h | 2 +- 2 files changed, 95 insertions(+), 31 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 5d105881933fa..fd4eec7118ce4 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -3685,16 +3685,21 @@ GenTree* Compiler::optAssertionProp_Comma(ASSERT_VALARG_TP assertions, GenTree* return nullptr; } -/***************************************************************************** - * - * Given a tree consisting of a Ind and a set of available assertions, we try - * to propagate an assertion and modify the Ind tree if we can. We pass in the - * root of the tree via 'stmt', for local copy prop 'stmt' will be nullptr. - * - * Returns the modified tree, or nullptr if no assertion prop took place. - * - */ - +//------------------------------------------------------------------------ +// optAssertionProp_Ind: see if we can prove the indirection can't cause +// and exception. +// +// Arguments: +// assertions - set of live assertions +// tree - tree to possibly optimize +// stmt - statement containing the tree +// +// Returns: +// The modified tree, or nullptr if no assertion prop took place. +// +// Notes: +// stmt may be nullptr during local assertion prop +// GenTree* Compiler::optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt) { assert(tree->OperIsIndir()); @@ -3742,16 +3747,26 @@ GenTree* Compiler::optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tr return nullptr; } -/***************************************************************************** - * Check if a non-null assertion can be made about the input operand "op" - * from the set of "assertions," or implicitly from the value number on "op." - * - * Sets "pVnBased" if the assertion is value number based. If no matching - * assertions are found from the table, then returns "NO_ASSERTION_INDEX." - * - * Note: If both VN and assertion table yield a matching assertion, "pVnBased" - * is only set and the return value is "NO_ASSERTION_INDEX." - */ +//------------------------------------------------------------------------ +// optAssertionIsNonNull: see if we can prove a tree's value will be non-null +// based on assertions +// +// Arguments: +// op - tree to check +// assertions - set of live assertions +// pVnBased - [out] set to true if value numbers were used +// pIndex - [out] the assertion used in the proof +// +// Returns: +// true if the tree's value will be non-null +// +// Notes: +// Sets "pVnBased" if the assertion is value number based. If no matching +// assertions are found from the table, then returns "NO_ASSERTION_INDEX." +// +// If both VN and assertion table yield a matching assertion, "pVnBased" +// is only set and the return value is "NO_ASSERTION_INDEX." +// bool Compiler::optAssertionIsNonNull(GenTree* op, ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased) DEBUGARG(AssertionIndex* pIndex)) @@ -3769,20 +3784,35 @@ bool Compiler::optAssertionIsNonNull(GenTree* op, return true; } - AssertionIndex index = optAssertionIsNonNullInternal(op, assertions); + AssertionIndex index = optAssertionIsNonNullInternal(op, assertions DEBUGARG(pVnBased)); #ifdef DEBUG *pIndex = index; #endif return index != NO_ASSERTION_INDEX; } -/***************************************************************************** - * Check if a non-null assertion can be made about the input operand "op" - * from the set of "assertions." - * - */ -AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALARG_TP assertions) +//------------------------------------------------------------------------ +// optAssertionIsNonNullInternal: see if we can prove a tree's value will +// be non-null based on assertions +// +// Arguments: +// op - tree to check +// assertions - set of live assertions +// pVnBased - [out] set to true if value numbers were used +// +// Returns: +// index of assertion, or NO_ASSERTION_INDEX +// +AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, + ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased)) { + +#ifdef DEBUG + // Initialize the out param + // + *pVnBased = false; +#endif + // If local assertion prop use lcl comparison, else use VN comparison. if (!optLocalAssertionProp) { @@ -3791,9 +3821,32 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALAR return NO_ASSERTION_INDEX; } - ValueNum vn = op->gtVNPair.GetConservative(); + // Look at both the top-level vn, and + // the vn we get by stripping off any constant adds. + // + ValueNum vn = vnStore->VNConservativeNormalValue(op->gtVNPair); + ValueNum vnBase = vn; + VNFuncApp funcAttr; - // Check each assertion to find if we have a vn == or != null assertion. + while (vnStore->GetVNFunc(vnBase, &funcAttr) && (funcAttr.m_func == (VNFunc)GT_ADD)) + { + if (vnStore->IsVNConstant(funcAttr.m_args[1]) && varTypeIsIntegral(vnStore->TypeOfVN(funcAttr.m_args[1]))) + { + vnBase = funcAttr.m_args[0]; + } + else if (vnStore->IsVNConstant(funcAttr.m_args[0]) && + varTypeIsIntegral(vnStore->TypeOfVN(funcAttr.m_args[0]))) + { + vnBase = funcAttr.m_args[1]; + } + else + { + break; + } + } + + // Check each assertion to find if we have a vn != null assertion. + // BitVecOps::Iter iter(apTraits, assertions); unsigned index = 0; while (iter.NextElem(&index)) @@ -3808,10 +3861,21 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALAR { continue; } - if (curAssertion->op1.vn != vn || curAssertion->op2.vn != ValueNumStore::VNForNull()) + + if (curAssertion->op2.vn != ValueNumStore::VNForNull()) { continue; } + + if ((curAssertion->op1.vn != vn) && (curAssertion->op1.vn != vnBase)) + { + continue; + } + +#ifdef DEBUG + *pVnBased = true; +#endif + return assertionIndex; } } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index a38071f31a369..971fd105ea60a 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7259,7 +7259,7 @@ class Compiler var_types toType, ASSERT_VALARG_TP assertions); AssertionIndex optAssertionIsSubtype(GenTree* tree, GenTree* methodTableArg, ASSERT_VALARG_TP assertions); - AssertionIndex optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALARG_TP assertions); + AssertionIndex optAssertionIsNonNullInternal(GenTree* op, ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased)); bool optAssertionIsNonNull(GenTree* op, ASSERT_VALARG_TP assertions DEBUGARG(bool* pVnBased) DEBUGARG(AssertionIndex* pIndex)); From 6ce5878104d61cbdbfa6eb5db959bfc63e1e8596 Mon Sep 17 00:00:00 2001 From: Steve MacLean Date: Sat, 6 Mar 2021 17:10:29 -0500 Subject: [PATCH 25/83] Fix inverted active issues (#49265) --- src/libraries/System.Drawing.Common/tests/GdiplusTests.cs | 2 +- .../System.Runtime.Extensions/tests/System/EnvironmentTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Drawing.Common/tests/GdiplusTests.cs b/src/libraries/System.Drawing.Common/tests/GdiplusTests.cs index 4e885b2d99dfc..869f67af1622e 100644 --- a/src/libraries/System.Drawing.Common/tests/GdiplusTests.cs +++ b/src/libraries/System.Drawing.Common/tests/GdiplusTests.cs @@ -8,7 +8,7 @@ namespace System.Drawing.Tests public class GdiplusTests { [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsOSX))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49111", typeof(PlatformDetection), nameof(PlatformDetection.IsNotMacOsAppleSilicon))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49111", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public void IsAtLeastLibgdiplus6() { Assert.True(Helpers.GetIsWindowsOrAtLeastLibgdiplus6()); diff --git a/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs index c0916d4ac89f0..051c5e46f4e21 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs @@ -183,7 +183,7 @@ public void OSVersion_ParseVersion(string input, int major, int minor, int build [Fact] [PlatformSpecific(TestPlatforms.OSX)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49106", typeof(PlatformDetection), nameof(PlatformDetection.IsNotMacOsAppleSilicon))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49106", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public void OSVersion_ValidVersion_OSX() { Version version = Environment.OSVersion.Version; From 49eed0efd03fa09be1718cb67b1a7b38c8cfb95c Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Sat, 6 Mar 2021 16:45:10 -0800 Subject: [PATCH 26/83] Fix Activity.ParentId trace flags part (#49162) --- .../src/System/Diagnostics/Activity.cs | 10 ++++++- .../tests/ActivityTests.cs | 26 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs index ee225a14ae9b6..b93a715a10516 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs @@ -75,6 +75,7 @@ public partial class Activity : IDisposable private string? _spanId; private byte _w3CIdFlags; + private byte _parentTraceFlags; private TagsLinkedList? _tags; private BaggageLinkedList? _baggage; @@ -213,6 +214,9 @@ public string? Id /// public string? ParentId { +#if ALLOW_PARTIALLY_TRUSTED_CALLERS + [System.Security.SecuritySafeCriticalAttribute] +#endif get { // if we represented it as a traceId-spanId, convert it to a string. @@ -220,7 +224,9 @@ public string? ParentId { if (_parentSpanId != null) { - string parentId = "00-" + _traceId + "-" + _parentSpanId + "-00"; + Span flagsChars = stackalloc char[2]; + HexConverter.ToCharsBuffer((byte)((~ActivityTraceFlagsIsSet) & _parentTraceFlags), flagsChars, 0, HexConverter.Casing.Lower); + string parentId = "00-" + _traceId + "-" + _parentSpanId + "-" + flagsChars.ToString(); Interlocked.CompareExchange(ref _parentId, parentId, null); } else if (Parent != null) @@ -551,6 +557,7 @@ public Activity SetParentId(ActivityTraceId traceId, ActivitySpanId spanId, Acti _traceId = traceId.ToHexString(); // The child will share the parent's traceId. _parentSpanId = spanId.ToHexString(); ActivityTraceFlags = activityTraceFlags; + _parentTraceFlags = (byte) activityTraceFlags; } return this; } @@ -1072,6 +1079,7 @@ internal static Activity Create(ActivitySource source, string name, ActivityKind } activity.ActivityTraceFlags = parentContext.TraceFlags; + activity._parentTraceFlags = (byte) parentContext.TraceFlags; activity._traceState = parentContext.TraceState; } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs index bdf788bb098c5..accbf48fc30a0 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs @@ -1694,6 +1694,32 @@ public void StructEnumerator_TagsLinkedList() Assert.True(method.ReturnType.IsValueType); } + [Fact] + public void TestParentTraceFlags() + { + Activity a = new Activity("ParentFlagsA"); + a.SetIdFormat(ActivityIdFormat.W3C); + a.SetParentId(ActivityTraceId.CreateFromString("0123456789abcdef0123456789abcdef".AsSpan()), ActivitySpanId.CreateFromString("0123456789abcdef".AsSpan()), ActivityTraceFlags.Recorded); + Assert.Equal("00-0123456789abcdef0123456789abcdef-0123456789abcdef-01", a.ParentId); + + Activity b = new Activity("ParentFlagsB"); + b.SetIdFormat(ActivityIdFormat.W3C); + b.SetParentId(ActivityTraceId.CreateFromString("0123456789abcdef0123456789abcdef".AsSpan()), ActivitySpanId.CreateFromString("0123456789abcdef".AsSpan()), ActivityTraceFlags.None); + b.ActivityTraceFlags = ActivityTraceFlags.Recorded; // Setting ActivityTraceFlags shouldn't affect the parent + Assert.Equal("00-0123456789abcdef0123456789abcdef-0123456789abcdef-00", b.ParentId); + + using ActivitySource aSource = new ActivitySource("CheckParentTraceFlags"); + using ActivityListener listener = new ActivityListener(); + listener.ShouldListenTo = (activitySource) => object.ReferenceEquals(aSource, activitySource); + listener.Sample = (ref ActivityCreationOptions activityOptions) => ActivitySamplingResult.AllDataAndRecorded; + ActivitySource.AddActivityListener(listener); + + ActivityContext parentContext = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded); + a = aSource.CreateActivity("WithContext", ActivityKind.Internal, parentContext, default, default, ActivityIdFormat.W3C); + Assert.NotNull(a); + Assert.Equal("00-" + parentContext.TraceId + "-" + parentContext.SpanId + "-01", a.ParentId); + } + [Fact] public void TestStatus() { From bea0abbdf65eb928892d4de980db3095d12d2ec4 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 7 Mar 2021 19:54:19 +0000 Subject: [PATCH 27/83] Speed up interface checking and casting (#49257) * Reduce branches in IsInstanceOfInterface/ChkCastInterface * Drop extra var, lea; additional check for small counts * Feedback * Undo IsInstanceOfClass change * Tidy usings --- .../Runtime/CompilerServices/CastHelpers.cs | 121 ++++++++++++------ 1 file changed, 84 insertions(+), 37 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index 054551adf289c..cb8800994aa78 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -2,11 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using Internal.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; + +using Internal.Runtime.CompilerServices; namespace System.Runtime.CompilerServices { @@ -207,34 +206,57 @@ private static CastResult TryGet(nuint source, nuint target) [DebuggerStepThrough] private static object? IsInstanceOfInterface(void* toTypeHnd, object? obj) { + const int unrollSize = 4; + if (obj != null) { MethodTable* mt = RuntimeHelpers.GetMethodTable(obj); - nuint interfaceCount = mt->InterfaceCount; + nint interfaceCount = mt->InterfaceCount; if (interfaceCount != 0) { MethodTable** interfaceMap = mt->InterfaceMap; - for (nuint i = 0; ; i += 4) + if (interfaceCount < unrollSize) { - if (interfaceMap[i + 0] == toTypeHnd) - goto done; - if (--interfaceCount == 0) - break; - if (interfaceMap[i + 1] == toTypeHnd) - goto done; - if (--interfaceCount == 0) - break; - if (interfaceMap[i + 2] == toTypeHnd) - goto done; - if (--interfaceCount == 0) - break; - if (interfaceMap[i + 3] == toTypeHnd) + // If not enough for unrolled, jmp straight to small loop + // as we already know there is one or more interfaces so don't need to check again. + goto few; + } + + do + { + if (interfaceMap[0] == toTypeHnd || + interfaceMap[1] == toTypeHnd || + interfaceMap[2] == toTypeHnd || + interfaceMap[3] == toTypeHnd) + { goto done; - if (--interfaceCount == 0) - break; + } + + interfaceMap += unrollSize; + interfaceCount -= unrollSize; + } while (interfaceCount >= unrollSize); + + if (interfaceCount == 0) + { + // If none remaining, skip the short loop + goto extra; } + + few: + do + { + if (interfaceMap[0] == toTypeHnd) + { + goto done; + } + + // Assign next offset + interfaceMap++; + interfaceCount--; + } while (interfaceCount > 0); } + extra: if (mt->NonTrivialInterfaceCast) { goto slowPath; @@ -374,35 +396,60 @@ private static CastResult TryGet(nuint source, nuint target) [DebuggerStepThrough] private static object? ChkCastInterface(void* toTypeHnd, object? obj) { + const int unrollSize = 4; + if (obj != null) { MethodTable* mt = RuntimeHelpers.GetMethodTable(obj); - nuint interfaceCount = mt->InterfaceCount; + nint interfaceCount = mt->InterfaceCount; if (interfaceCount == 0) { goto slowPath; } MethodTable** interfaceMap = mt->InterfaceMap; - for (nuint i = 0; ; i += 4) + if (interfaceCount < unrollSize) { - if (interfaceMap[i + 0] == toTypeHnd) - goto done; - if (--interfaceCount == 0) - goto slowPath; - if (interfaceMap[i + 1] == toTypeHnd) - goto done; - if (--interfaceCount == 0) - goto slowPath; - if (interfaceMap[i + 2] == toTypeHnd) - goto done; - if (--interfaceCount == 0) - goto slowPath; - if (interfaceMap[i + 3] == toTypeHnd) + // If not enough for unrolled, jmp straight to small loop + // as we already know there is one or more interfaces so don't need to check again. + goto few; + } + + do + { + if (interfaceMap[0] == toTypeHnd || + interfaceMap[1] == toTypeHnd || + interfaceMap[2] == toTypeHnd || + interfaceMap[3] == toTypeHnd) + { goto done; - if (--interfaceCount == 0) - goto slowPath; + } + + // Assign next offset + interfaceMap += unrollSize; + interfaceCount -= unrollSize; + } while (interfaceCount >= unrollSize); + + if (interfaceCount == 0) + { + // If none remaining, skip the short loop + goto slowPath; } + + few: + do + { + if (interfaceMap[0] == toTypeHnd) + { + goto done; + } + + // Assign next offset + interfaceMap++; + interfaceCount--; + } while (interfaceCount > 0); + + goto slowPath; } done: From 027c093de1cc7d23a107e0594cebfb0216161dd4 Mon Sep 17 00:00:00 2001 From: Geoff Kizer Date: Sun, 7 Mar 2021 13:02:28 -0800 Subject: [PATCH 28/83] Improve zero-byte read handling in SslStream to reduce memory usage (#49123) * add ZeroByteRead_PerformsZeroByteReadOnUnderlyingStreamWhenDataNeeded to stream conformance tests * remove dead code * change SslStream zero byte read implementation to issue zero-byte read on underlying stream when appropriate * ensure buffer is always freed when not needed, and assert this * create StreamConformanceTests assembly and reference from appropriate test projects Co-authored-by: Geoffrey Kizer --- .../Common/tests/Common.Tests.csproj | 5 +- .../StreamConformanceTests.csproj | 26 ++++ .../System/IO/StreamConformanceTests.cs | 145 ++++++++++++++++++ .../tests/System/IO/CallTrackingStream.cs | 2 +- .../System.IO.Compression.Brotli.Tests.csproj | 6 +- .../tests/System.IO.Compression.Tests.csproj | 6 +- .../tests/System.IO.FileSystem.Tests.csproj | 12 +- .../System.IO.MemoryMappedFiles.Tests.csproj | 10 +- .../tests/System.IO.Pipelines.Tests.csproj | 9 +- .../tests/System.IO.Pipes.Tests.csproj | 10 +- ...stem.IO.UnmanagedMemoryStream.Tests.csproj | 10 +- .../System.IO/tests/System.IO.Tests.csproj | 5 +- .../System.Net.Http.Functional.Tests.csproj | 7 +- .../System.Net.Quic.Functional.Tests.csproj | 5 +- .../Net/Security/SslStream.Implementation.cs | 35 ++--- .../SslStreamConformanceTests.cs | 1 + .../System.Net.Security.Tests.csproj | 5 +- .../System.Net.Sockets.Tests.csproj | 9 +- ...urity.Cryptography.Primitives.Tests.csproj | 5 +- .../tests/System.Text.Encoding.Tests.csproj | 5 +- 20 files changed, 235 insertions(+), 83 deletions(-) create mode 100644 src/libraries/Common/tests/StreamConformanceTests/StreamConformanceTests.csproj rename src/libraries/Common/tests/{Tests => StreamConformanceTests}/System/IO/StreamConformanceTests.cs (94%) diff --git a/src/libraries/Common/tests/Common.Tests.csproj b/src/libraries/Common/tests/Common.Tests.csproj index a71e03147f88e..6cbd38febe7ad 100644 --- a/src/libraries/Common/tests/Common.Tests.csproj +++ b/src/libraries/Common/tests/Common.Tests.csproj @@ -105,11 +105,9 @@ Link="System\IO\PathInternal.cs" /> - - + + + diff --git a/src/libraries/Common/tests/StreamConformanceTests/StreamConformanceTests.csproj b/src/libraries/Common/tests/StreamConformanceTests/StreamConformanceTests.csproj new file mode 100644 index 0000000000000..b5dfa854512bf --- /dev/null +++ b/src/libraries/Common/tests/StreamConformanceTests/StreamConformanceTests.csproj @@ -0,0 +1,26 @@ + + + true + $(NetCoreAppCurrent) + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/Common/tests/Tests/System/IO/StreamConformanceTests.cs b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs similarity index 94% rename from src/libraries/Common/tests/Tests/System/IO/StreamConformanceTests.cs rename to src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs index 947c0b88d3290..bf2ac03377910 100644 --- a/src/libraries/Common/tests/Tests/System/IO/StreamConformanceTests.cs +++ b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs @@ -2612,6 +2612,11 @@ public abstract class WrappingConnectedStreamConformanceTests : ConnectedStreamC protected abstract Task CreateWrappedConnectedStreamsAsync(StreamPair wrapped, bool leaveOpen = false); protected virtual bool WrappedUsableAfterClose => true; protected virtual bool SupportsLeaveOpen => true; + /// + /// Indicates whether the stream will issue a zero byte read on the underlying stream when a user performs + /// a zero byte read and no data is currently available to return to the user. + /// + protected virtual bool ZeroByteReadPerformsZeroByteReadOnUnderlyingStream => false; [Theory] [InlineData(false)] @@ -2788,6 +2793,146 @@ await WhenAllOrAnyFailed( })); } } + + [Theory] + [InlineData(ReadWriteMode.SyncArray)] + [InlineData(ReadWriteMode.SyncSpan)] + [InlineData(ReadWriteMode.AsyncArray)] + [InlineData(ReadWriteMode.AsyncMemory)] + [InlineData(ReadWriteMode.SyncAPM)] + [InlineData(ReadWriteMode.AsyncAPM)] + public virtual async Task ZeroByteRead_PerformsZeroByteReadOnUnderlyingStreamWhenDataNeeded(ReadWriteMode mode) + { + if (!ZeroByteReadPerformsZeroByteReadOnUnderlyingStream) + { + return; + } + + // This is the data we will send across the connected streams. We assume this data will both + // (a) produce at least two readable bytes, so we can unblock the reader and read a single byte without clearing its buffer; and + // (b) produce no more than 1K of readable bytes, so we can clear the reader buffer below. + // If this isn't the case for some Stream(s), we can modify the data or parameterize it per Stream. + byte[] data = Encoding.UTF8.GetBytes("hello world"); + + using StreamPair innerStreams = ConnectedStreams.CreateBidirectional(); + (Stream innerWriteable, Stream innerReadable) = GetReadWritePair(innerStreams); + + var tracker = new ZeroByteReadTrackingStream(innerReadable); + using StreamPair streams = await CreateWrappedConnectedStreamsAsync((innerWriteable, tracker)); + + (Stream writeable, Stream readable) = GetReadWritePair(streams); + + for (int iter = 0; iter < 2; iter++) + { + // Register to be signalled for the zero byte read. + var signalTask = tracker.WaitForZeroByteReadAsync(); + + // Issue zero byte read against wrapper stream. + Task zeroByteRead = Task.Run(() => ReadAsync(mode, readable, Array.Empty(), 0, 0)); + + // The tracker stream will signal us when the zero byte read actually happens. + await signalTask; + + // Write some data (see notes above re 'data') + await writeable.WriteAsync(data); + if (FlushRequiredToWriteData) + { + await writeable.FlushAsync(); + } + + // Reader should be unblocked, and we should have issued a zero byte read against the underlying stream as part of unblocking. + int bytesRead = await zeroByteRead; + Assert.Equal(0, bytesRead); + + byte[] buffer = new byte[1024]; + + // Should be able to read one byte without blocking + var readTask = ReadAsync(mode, readable, buffer, 0, 1); + Assert.True(readTask.IsCompleted); + bytesRead = await readTask; + Assert.Equal(1, bytesRead); + + // Issue zero byte read against wrapper stream. Since there is still data available, this should complete immediately and not do another zero-byte read. + readTask = ReadAsync(mode, readable, Array.Empty(), 0, 0); + Assert.True(readTask.IsCompleted); + Assert.Equal(0, await readTask); + + // Clear the reader stream of any buffered data by doing a large read, which again should not block. + readTask = ReadAsync(mode, readable, buffer, 1, buffer.Length - 1); + Assert.True(readTask.IsCompleted); + bytesRead += await readTask; + + if (FlushGuaranteesAllDataWritten) + { + AssertExtensions.SequenceEqual(data, buffer.AsSpan().Slice(0, bytesRead)); + } + } + } + + private sealed class ZeroByteReadTrackingStream : DelegatingStream + { + private TaskCompletionSource? _signal; + + public ZeroByteReadTrackingStream(Stream innerStream) : base(innerStream) + { + } + + public Task WaitForZeroByteReadAsync() + { + if (_signal is not null) + { + throw new Exception("Already registered to wait"); + } + + _signal = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + return _signal.Task; + } + + private void CheckForZeroByteRead(int bufferLength) + { + if (bufferLength == 0) + { + var signal = _signal; + if (signal is null) + { + throw new Exception("Unexpected zero byte read"); + } + + _signal = null; + signal.SetResult(); + } + } + + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) + { + CheckForZeroByteRead(count); + return base.BeginRead(buffer, offset, count, callback, state); + } + + public override int Read(byte[] buffer, int offset, int count) + { + CheckForZeroByteRead(count); + return base.Read(buffer, offset, count); + } + + public override int Read(Span buffer) + { + CheckForZeroByteRead(buffer.Length); + return base.Read(buffer); + } + + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + CheckForZeroByteRead(count); + return base.ReadAsync(buffer, offset, count, cancellationToken); + } + + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + { + CheckForZeroByteRead(buffer.Length); + return base.ReadAsync(buffer, cancellationToken); + } + } } /// Provides a disposable, enumerable tuple of two streams. diff --git a/src/libraries/Common/tests/System/IO/CallTrackingStream.cs b/src/libraries/Common/tests/System/IO/CallTrackingStream.cs index d912545b01261..416ea2e186024 100644 --- a/src/libraries/Common/tests/System/IO/CallTrackingStream.cs +++ b/src/libraries/Common/tests/System/IO/CallTrackingStream.cs @@ -10,7 +10,7 @@ namespace System.IO { - public class CallTrackingStream : Stream + internal class CallTrackingStream : Stream { private readonly Dictionary _callCounts; // maps names of methods -> how many times they were called diff --git a/src/libraries/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj b/src/libraries/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj index f66427a6a7f07..60afa44f33d27 100644 --- a/src/libraries/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj +++ b/src/libraries/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj @@ -19,12 +19,12 @@ Link="Common\System\IO\TempFile.cs" /> - - - + + + diff --git a/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj b/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj index 7e56fb22dcd32..9b51d5b5d34ff 100644 --- a/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj +++ b/src/libraries/System.IO.Compression/tests/System.IO.Compression.Tests.csproj @@ -26,13 +26,13 @@ - - - + + + diff --git a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj index ffebd2dd38863..7a81b2e7b1f3d 100644 --- a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj +++ b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj @@ -159,15 +159,9 @@ - - - - - - - - - + + + diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/System.IO.MemoryMappedFiles.Tests.csproj b/src/libraries/System.IO.MemoryMappedFiles/tests/System.IO.MemoryMappedFiles.Tests.csproj index 2c69effa9e4a7..81fe94cf1e975 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/tests/System.IO.MemoryMappedFiles.Tests.csproj +++ b/src/libraries/System.IO.MemoryMappedFiles/tests/System.IO.MemoryMappedFiles.Tests.csproj @@ -19,13 +19,6 @@ - - - - - - - @@ -33,4 +26,7 @@ + + + \ No newline at end of file diff --git a/src/libraries/System.IO.Pipelines/tests/System.IO.Pipelines.Tests.csproj b/src/libraries/System.IO.Pipelines/tests/System.IO.Pipelines.Tests.csproj index f3f7dc6bfb9a3..d4b9d67b32f66 100644 --- a/src/libraries/System.IO.Pipelines/tests/System.IO.Pipelines.Tests.csproj +++ b/src/libraries/System.IO.Pipelines/tests/System.IO.Pipelines.Tests.csproj @@ -44,12 +44,6 @@ - - - - - - @@ -58,4 +52,7 @@ + + + \ No newline at end of file diff --git a/src/libraries/System.IO.Pipes/tests/System.IO.Pipes.Tests.csproj b/src/libraries/System.IO.Pipes/tests/System.IO.Pipes.Tests.csproj index b1c055cbd92e4..b639953aff844 100644 --- a/src/libraries/System.IO.Pipes/tests/System.IO.Pipes.Tests.csproj +++ b/src/libraries/System.IO.Pipes/tests/System.IO.Pipes.Tests.csproj @@ -21,13 +21,6 @@ - - - - - - - @@ -52,4 +45,7 @@ + + + diff --git a/src/libraries/System.IO.UnmanagedMemoryStream/tests/System.IO.UnmanagedMemoryStream.Tests.csproj b/src/libraries/System.IO.UnmanagedMemoryStream/tests/System.IO.UnmanagedMemoryStream.Tests.csproj index af24f7579e112..c3f6ad83ffb53 100644 --- a/src/libraries/System.IO.UnmanagedMemoryStream/tests/System.IO.UnmanagedMemoryStream.Tests.csproj +++ b/src/libraries/System.IO.UnmanagedMemoryStream/tests/System.IO.UnmanagedMemoryStream.Tests.csproj @@ -19,12 +19,8 @@ - - - - - - - + + + \ No newline at end of file diff --git a/src/libraries/System.IO/tests/System.IO.Tests.csproj b/src/libraries/System.IO/tests/System.IO.Tests.csproj index c3f821f0f5ad7..3bf8d260ba2ad 100644 --- a/src/libraries/System.IO/tests/System.IO.Tests.csproj +++ b/src/libraries/System.IO/tests/System.IO.Tests.csproj @@ -52,11 +52,12 @@ - - + + + diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj index 2799f14f74475..cb9fb649dfe9b 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj @@ -158,10 +158,6 @@ - - + + + diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/System.Net.Quic.Functional.Tests.csproj b/src/libraries/System.Net.Quic/tests/FunctionalTests/System.Net.Quic.Functional.Tests.csproj index 84ea8ff200410..fc7d6fb1986b1 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/System.Net.Quic.Functional.Tests.csproj +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/System.Net.Quic.Functional.Tests.csproj @@ -8,8 +8,6 @@ - - @@ -17,4 +15,7 @@ + + + diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs index 3b19cd600a823..0f7b5073c5a04 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs @@ -759,6 +759,8 @@ private async ValueTask ReadAsyncInternal(TIOAdapter adapter, M throw new NotSupportedException(SR.Format(SR.net_io_invalidnestedcall, nameof(SslStream.ReadAsync), "read")); } + Debug.Assert(_internalBuffer is null || _internalBufferCount > 0 || _decryptedBytesCount > 0, "_internalBuffer allocated when no data is buffered."); + try { while (true) @@ -768,6 +770,18 @@ private async ValueTask ReadAsyncInternal(TIOAdapter adapter, M return CopyDecryptedData(buffer); } + if (buffer.Length == 0 && _internalBuffer is null) + { + // User requested a zero-byte read, and we have no data available in the buffer for processing. + // This zero-byte read indicates their desire to trade off the extra cost of a zero-byte read + // for reduced memory consumption when data is not immediately available. + // So, we will issue our own zero-byte read against the underlying stream and defer buffer allocation + // until data is actually available from the underlying stream. + // Note that if the underlying stream does not supporting blocking on zero byte reads, then this will + // complete immediately and won't save any memory, but will still function correctly. + await adapter.ReadAsync(Memory.Empty).ConfigureAwait(false); + } + ResetReadBuffer(); // Read the next frame header. @@ -890,6 +904,7 @@ private async ValueTask ReadAsyncInternal(TIOAdapter adapter, M } finally { + ReturnReadBufferIfEmpty(); _nestedRead = 0; } } @@ -1010,8 +1025,6 @@ private void ConsumeBufferedBytes(int byteCount) _internalOffset += byteCount; _internalBufferCount -= byteCount; - - ReturnReadBufferIfEmpty(); } private int CopyDecryptedData(Memory buffer) @@ -1027,7 +1040,6 @@ private int CopyDecryptedData(Memory buffer) _decryptedBytesCount -= copyBytes; } - ReturnReadBufferIfEmpty(); return copyBytes; } @@ -1038,6 +1050,8 @@ private void ResetReadBuffer() if (_internalBuffer == null) { _internalBuffer = ArrayPool.Shared.Rent(ReadBufferSize); + Debug.Assert(_internalOffset == 0); + Debug.Assert(_internalBufferCount == 0); } else if (_internalOffset > 0) { @@ -1049,21 +1063,6 @@ private void ResetReadBuffer() } } - private static byte[] EnsureBufferSize(byte[] buffer, int copyCount, int size) - { - if (buffer == null || buffer.Length < size) - { - byte[]? saved = buffer; - buffer = new byte[size]; - if (saved != null && copyCount != 0) - { - Buffer.BlockCopy(saved, 0, buffer, 0, copyCount); - } - } - - return buffer; - } - // We need at least 5 bytes to determine what we have. private Framing DetectFraming(ReadOnlySpan bytes) { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamConformanceTests.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamConformanceTests.cs index eb8b302d4fdf0..d2caf198d8710 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamConformanceTests.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamConformanceTests.cs @@ -14,6 +14,7 @@ public abstract class SslStreamConformanceTests : WrappingConnectedStreamConform { protected override bool UsableAfterCanceledReads => false; protected override bool BlocksOnZeroByteReads => true; + protected override bool ZeroByteReadPerformsZeroByteReadOnUnderlyingStream => true; protected override Type UnsupportedConcurrentExceptionType => typeof(NotSupportedException); protected virtual SslProtocols GetSslProtocols() => SslProtocols.None; diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj index f35aa1a509197..7ceae63c09548 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj @@ -35,8 +35,6 @@ - + + + diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj index ffd474d4bcdb5..dbb949b29df17 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj @@ -96,12 +96,9 @@ Link="Common\System\Diagnostics\Tracing\TestEventListener.cs" /> - - - - - - + + + diff --git a/src/libraries/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj b/src/libraries/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj index c5769108a0ca4..b72afa4f5238e 100644 --- a/src/libraries/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Primitives/tests/System.Security.Cryptography.Primitives.Tests.csproj @@ -25,11 +25,12 @@ - - + + + diff --git a/src/libraries/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj b/src/libraries/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj index 0918f9d68a97a..9015b7c706959 100644 --- a/src/libraries/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj +++ b/src/libraries/System.Text.Encoding/tests/System.Text.Encoding.Tests.csproj @@ -80,8 +80,6 @@ - - @@ -93,4 +91,7 @@ + + + \ No newline at end of file From 3d2ecd0589f2e2097365b19d1ece6a20535a68b9 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Mon, 8 Mar 2021 00:56:02 +0000 Subject: [PATCH 29/83] Apply feedback to grow methods of generic collections (#49167) * Apply feedback to Grow methods of generic collections * add assertion --- .../src/System/Collections/Generic/Queue.cs | 39 +++++++++---------- .../src/System/Collections/Generic/Stack.cs | 31 +++++++-------- .../src/System/Collections/Generic/List.cs | 37 +++++++++--------- 3 files changed, 51 insertions(+), 56 deletions(-) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/Queue.cs b/src/libraries/System.Collections/src/System/Collections/Generic/Queue.cs index f4676282bf487..c8c01ab965e2a 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/Queue.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/Queue.cs @@ -180,7 +180,7 @@ public void Enqueue(T item) { if (_size == _array.Length) { - EnsureCapacityCore(_size + 1); + Grow(_size + 1); } _array[_tail] = item; @@ -390,38 +390,35 @@ public int EnsureCapacity(int capacity) if (_array.Length < capacity) { - EnsureCapacityCore(capacity); + Grow(capacity); } return _array.Length; } - private void EnsureCapacityCore(int capacity) + private void Grow(int capacity) { - Debug.Assert(capacity >= 0); + Debug.Assert(_array.Length < capacity); - if (_array.Length < capacity) - { - // Array.MaxArrayLength is internal to S.P.CoreLib, replicate here. - const int MaxArrayLength = 0X7FEFFFFF; - const int GrowFactor = 2; - const int MinimumGrow = 4; + // Array.MaxArrayLength is internal to S.P.CoreLib, replicate here. + const int MaxArrayLength = 0X7FEFFFFF; + const int GrowFactor = 2; + const int MinimumGrow = 4; - int newcapacity = GrowFactor * _array.Length; + int newcapacity = GrowFactor * _array.Length; - // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. - // Note that this check works even when _items.Length overflowed thanks to the (uint) cast - if ((uint)newcapacity > MaxArrayLength) newcapacity = MaxArrayLength; + // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast + if ((uint)newcapacity > MaxArrayLength) newcapacity = MaxArrayLength; - // Ensure minimum growth is respected. - newcapacity = Math.Max(newcapacity, _array.Length + MinimumGrow); + // Ensure minimum growth is respected. + newcapacity = Math.Max(newcapacity, _array.Length + MinimumGrow); - // If the computed capacity is still less than specified, set to the original argument. - // Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize. - if (newcapacity < capacity) newcapacity = capacity; + // If the computed capacity is still less than specified, set to the original argument. + // Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize. + if (newcapacity < capacity) newcapacity = capacity; - SetCapacity(newcapacity); - } + SetCapacity(newcapacity); } // Implements an enumerator for a Queue. The enumerator uses the diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs index 8c7889c2a6b46..b2ba4755958d3 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs @@ -283,7 +283,7 @@ public void Push(T item) private void PushWithResize(T item) { Debug.Assert(_size == _array.Length); - EnsureCapacityCore(_size + 1); + Grow(_size + 1); _array[_size] = item; _version++; _size++; @@ -304,34 +304,31 @@ public int EnsureCapacity(int capacity) if (_array.Length < capacity) { - EnsureCapacityCore(capacity); + Grow(capacity); _version++; } return _array.Length; } - private void EnsureCapacityCore(int capacity) + private void Grow(int capacity) { - Debug.Assert(capacity >= 0); + Debug.Assert(_array.Length < capacity); - if (_array.Length < capacity) - { - // Array.MaxArrayLength is internal to S.P.CoreLib, replicate here. - const int MaxArrayLength = 0X7FEFFFFF; + // Array.MaxArrayLength is internal to S.P.CoreLib, replicate here. + const int MaxArrayLength = 0X7FEFFFFF; - int newcapacity = _array.Length == 0 ? DefaultCapacity : 2 * _array.Length; + int newcapacity = _array.Length == 0 ? DefaultCapacity : 2 * _array.Length; - // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. - // Note that this check works even when _items.Length overflowed thanks to the (uint) cast. - if ((uint)newcapacity > MaxArrayLength) newcapacity = MaxArrayLength; + // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast. + if ((uint)newcapacity > MaxArrayLength) newcapacity = MaxArrayLength; - // If computed capacity is still less than specified, set to the original argument. - // Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize. - if (newcapacity < capacity) newcapacity = capacity; + // If computed capacity is still less than specified, set to the original argument. + // Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize. + if (newcapacity < capacity) newcapacity = capacity; - Array.Resize(ref _array, newcapacity); - } + Array.Resize(ref _array, newcapacity); } // Copies the Stack to an array, in the same order Pop would return the items. diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs index dba078158c66c..5bfc45d753b36 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs @@ -213,8 +213,9 @@ public void Add(T item) [MethodImpl(MethodImplOptions.NoInlining)] private void AddWithResize(T item) { + Debug.Assert(_size == _items.Length); int size = _size; - EnsureCapacityCore(size + 1); + Grow(size + 1); _size = size + 1; _items[size] = item; } @@ -405,7 +406,7 @@ public int EnsureCapacity(int capacity) } if (_items.Length < capacity) { - EnsureCapacityCore(capacity); + Grow(capacity); _version++; } @@ -413,27 +414,24 @@ public int EnsureCapacity(int capacity) } /// - /// Increase the capacity of this list to at least the specified by continuously twice current capacity. + /// Increase the capacity of this list to at least the specified . /// /// The minimum capacity to ensure. - private void EnsureCapacityCore(int capacity) + private void Grow(int capacity) { - Debug.Assert(capacity >= 0); + Debug.Assert(_items.Length < capacity); - if (_items.Length < capacity) - { - int newcapacity = _items.Length == 0 ? DefaultCapacity : 2 * _items.Length; + int newcapacity = _items.Length == 0 ? DefaultCapacity : 2 * _items.Length; - // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. - // Note that this check works even when _items.Length overflowed thanks to the (uint) cast - if ((uint)newcapacity > Array.MaxArrayLength) newcapacity = Array.MaxArrayLength; + // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. + // Note that this check works even when _items.Length overflowed thanks to the (uint) cast + if ((uint)newcapacity > Array.MaxArrayLength) newcapacity = Array.MaxArrayLength; - // If the computed capacity is still less than specified, set to the original argument. - // Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize. - if (newcapacity < capacity) newcapacity = capacity; + // If the computed capacity is still less than specified, set to the original argument. + // Capacities exceeding MaxArrayLength will be surfaced as OutOfMemoryException by Array.Resize. + if (newcapacity < capacity) newcapacity = capacity; - Capacity = newcapacity; - } + Capacity = newcapacity; } public bool Exists(Predicate match) @@ -695,7 +693,7 @@ public void Insert(int index, T item) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert); } - if (_size == _items.Length) EnsureCapacityCore(_size + 1); + if (_size == _items.Length) Grow(_size + 1); if (index < _size) { Array.Copy(_items, index, _items, index + 1, _size - index); @@ -741,7 +739,10 @@ public void InsertRange(int index, IEnumerable collection) int count = c.Count; if (count > 0) { - EnsureCapacityCore(_size + count); + if (_items.Length - _size < count) + { + Grow(_size + count); + } if (index < _size) { Array.Copy(_items, index, _items, index + count, _size - index); From e7688b9ff7a89512e6c2055bd549841ffc992bfd Mon Sep 17 00:00:00 2001 From: Tomas Weinfurt Date: Sun, 7 Mar 2021 16:57:49 -0800 Subject: [PATCH 30/83] fix proxy detection for websockets on Windows (#48734) * fix proxy detection for websockets on Windows' * feedback from review --- .../src/System/Net/Http/WinInetProxyHelper.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/libraries/Common/src/System/Net/Http/WinInetProxyHelper.cs b/src/libraries/Common/src/System/Net/Http/WinInetProxyHelper.cs index 1db443fbb5f66..c7271b65546ed 100644 --- a/src/libraries/Common/src/System/Net/Http/WinInetProxyHelper.cs +++ b/src/libraries/Common/src/System/Net/Http/WinInetProxyHelper.cs @@ -117,13 +117,25 @@ public bool GetProxyForUrl( // fAutoLogonIfChallenged member set to TRUE. // // We match behavior of WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY and ignore errors. + + string destination = uri.AbsoluteUri; + // Underlying code does not understand WebSockets so we need to convert it to http or https. + if (uri.Scheme == UriScheme.Wss) + { + destination = UriScheme.Https + destination.Substring(UriScheme.Wss.Length); + } + else if (uri.Scheme == UriScheme.Ws) + { + destination = UriScheme.Http + destination.Substring(UriScheme.Ws.Length); + } + var repeat = false; do { _autoDetectionFailed = false; if (Interop.WinHttp.WinHttpGetProxyForUrl( sessionHandle!, - uri.AbsoluteUri, + destination, ref autoProxyOptions, out proxyInfo)) { From acbbb505492244b4c07a4a368257ba86a1fc02e1 Mon Sep 17 00:00:00 2001 From: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Mon, 8 Mar 2021 08:48:48 +0300 Subject: [PATCH 31/83] Log the reason for importer's decision to reject the tail call in the dump (#49280) --- src/coreclr/jit/importer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 700d920d3fb99..4100eb7e29f94 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -9097,8 +9097,8 @@ var_types Compiler::impImportCall(OPCODE opcode, { // If this assert fires it means that canTailCall was set to false without setting a reason! assert(szCanTailCallFailReason != nullptr); - JITDUMP("\nRejecting %splicit tail call for [%06u]\n", isExplicitTailCall ? "ex" : "im", dspTreeID(call), - szCanTailCallFailReason); + JITDUMP("\nRejecting %splicit tail call for [%06u], reason: '%s'\n", isExplicitTailCall ? "ex" : "im", + dspTreeID(call), szCanTailCallFailReason); info.compCompHnd->reportTailCallDecision(info.compMethodHnd, methHnd, isExplicitTailCall, TAILCALL_FAIL, szCanTailCallFailReason); } From 108d82802754e81e972079fc17c5bcab283031b6 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 7 Mar 2021 22:58:05 -0800 Subject: [PATCH 32/83] Reduce the size of the pipe (#49270) - Use the pipe itself as the synchronization object - Store the options instance as a way to reference shared settings - Added a field to PipeOptions for storing if the Pool is the ArrayPool implementation of the MemoryPool - Shrink PipeAwaitable in the common case - Move the ExecutionContext and SynchronizationContext into a typed called the SchedulingContext. These types are mostly used with async await and it's extremely rare to have to capture any of this state. - Shrink the size of PipeCompletion - Since completion callbacks are deprecated they are rarely set. We remove the pool and the other fields and just store a list (which should be rarely used now). - Reduce the default segment pool size to 4 items = 16K buffered - The original size was optimized to avoid pool resizes but we need to balance idle memory and the potential resize cost of the resize. --- .../src/System.IO.Pipelines.csproj | 4 +- .../src/System/IO/Pipelines/Pipe.cs | 152 +++++++++--------- .../src/System/IO/Pipelines/PipeAwaitable.cs | 32 ++-- .../src/System/IO/Pipelines/PipeCompletion.cs | 94 +++-------- .../IO/Pipelines/PipeCompletionCallbacks.cs | 32 ++-- .../src/System/IO/Pipelines/PipeOptions.cs | 39 ++++- .../tests/BufferSegmentPoolTest.cs | 6 +- 7 files changed, 166 insertions(+), 193 deletions(-) diff --git a/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj b/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj index e2c35f4efca03..db4b9fb79535b 100644 --- a/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj +++ b/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj @@ -7,7 +7,7 @@ + Link="Common\System\Threading\Tasks\TaskToApm.cs" /> @@ -48,7 +48,7 @@ - diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs index 08837ce80b6b2..caf0767c2e14b 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; +using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading; @@ -13,9 +14,6 @@ namespace System.IO.Pipelines /// The default and implementation. public sealed partial class Pipe { - internal const int InitialSegmentPoolSize = 16; // 65K - internal const int MaxSegmentPoolSize = 256; // 1MB - private static readonly Action s_signalReaderAwaitable = state => ((Pipe)state!).ReaderCancellationRequested(); private static readonly Action s_signalWriterAwaitable = state => ((Pipe)state!).WriterCancellationRequested(); private static readonly Action s_invokeCompletionCallbacks = state => ((PipeCompletionCallbacks)state!).Execute(); @@ -26,24 +24,27 @@ public sealed partial class Pipe private static readonly SendOrPostCallback s_syncContextExecuteWithoutExecutionContextCallback = ExecuteWithoutExecutionContext!; private static readonly Action s_scheduleWithExecutionContextCallback = ExecuteWithExecutionContext!; - // This sync objects protects the shared state between the writer and reader (most of this class) - private readonly object _sync = new object(); - - private readonly MemoryPool? _pool; - private readonly int _minimumSegmentSize; - private readonly long _pauseWriterThreshold; - private readonly long _resumeWriterThreshold; - - private readonly PipeScheduler _readerScheduler; - private readonly PipeScheduler _writerScheduler; - // Mutable struct! Don't make this readonly private BufferSegmentStack _bufferSegmentPool; private readonly DefaultPipeReader _reader; private readonly DefaultPipeWriter _writer; - private readonly bool _useSynchronizationContext; + // The options instance + private readonly PipeOptions _options; + private readonly object _sync = new object(); + + // Computed state from the options instance + private bool UseSynchronizationContext => _options.UseSynchronizationContext; + private int MinimumSegmentSize => _options.MinimumSegmentSize; + private long PauseWriterThreshold => _options.PauseWriterThreshold; + private long ResumeWriterThreshold => _options.ResumeWriterThreshold; + + private PipeScheduler ReaderScheduler => _options.ReaderScheduler; + private PipeScheduler WriterScheduler => _options.WriterScheduler; + + // This sync objects protects the shared state between the writer and reader (most of this class) + private object SyncObj => _sync; // The number of bytes flushed but not consumed by the reader private long _unconsumedBytes; @@ -65,7 +66,6 @@ public sealed partial class Pipe private BufferSegment? _readHead; private int _readHeadIndex; - private readonly int _maxPooledBufferSize; private bool _disposed; // The extent of the bytes available to the PipeReader to consume @@ -80,7 +80,6 @@ public sealed partial class Pipe // Determines what current operation is in flight (reading/writing) private PipeOperationState _operationState; - internal long Length => _unconsumedBytes; /// Initializes a new instance of the class using as options. @@ -97,24 +96,15 @@ public Pipe(PipeOptions options) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.options); } - _bufferSegmentPool = new BufferSegmentStack(InitialSegmentPoolSize); + _bufferSegmentPool = new BufferSegmentStack(options.InitialSegmentPoolSize); _operationState = default; _readerCompletion = default; _writerCompletion = default; - // If we're using the default pool then mark it as null since we're just going to use the - // array pool under the covers - _pool = options.Pool == MemoryPool.Shared ? null : options.Pool; - _maxPooledBufferSize = _pool?.MaxBufferSize ?? -1; - _minimumSegmentSize = options.MinimumSegmentSize; - _pauseWriterThreshold = options.PauseWriterThreshold; - _resumeWriterThreshold = options.ResumeWriterThreshold; - _readerScheduler = options.ReaderScheduler; - _writerScheduler = options.WriterScheduler; - _useSynchronizationContext = options.UseSynchronizationContext; - _readerAwaitable = new PipeAwaitable(completed: false, _useSynchronizationContext); - _writerAwaitable = new PipeAwaitable(completed: true, _useSynchronizationContext); + _options = options; + _readerAwaitable = new PipeAwaitable(completed: false, UseSynchronizationContext); + _writerAwaitable = new PipeAwaitable(completed: true, UseSynchronizationContext); _reader = new DefaultPipeReader(this); _writer = new DefaultPipeWriter(this); } @@ -123,8 +113,8 @@ private void ResetState() { _readerCompletion.Reset(); _writerCompletion.Reset(); - _readerAwaitable = new PipeAwaitable(completed: false, _useSynchronizationContext); - _writerAwaitable = new PipeAwaitable(completed: true, _useSynchronizationContext); + _readerAwaitable = new PipeAwaitable(completed: false, UseSynchronizationContext); + _writerAwaitable = new PipeAwaitable(completed: true, UseSynchronizationContext); _readTailIndex = 0; _readHeadIndex = 0; _lastExaminedIndex = -1; @@ -180,7 +170,7 @@ private void AllocateWriteHeadIfNeeded(int sizeHint) private void AllocateWriteHeadSynchronized(int sizeHint) { - lock (_sync) + lock (SyncObj) { _operationState.BeginWrite(); @@ -220,11 +210,19 @@ private BufferSegment AllocateSegment(int sizeHint) Debug.Assert(sizeHint >= 0); BufferSegment newSegment = CreateSegmentUnsynchronized(); - int maxSize = _maxPooledBufferSize; + MemoryPool? pool = null; + int maxSize = -1; + + if (!_options.IsDefaultSharedMemoryPool) + { + pool = _options.Pool; + maxSize = pool.MaxBufferSize; + } + if (sizeHint <= maxSize) { // Use the specified pool as it fits. Specified pool is not null as maxSize == -1 if _pool is null. - newSegment.SetOwnedMemory(_pool!.Rent(GetSegmentSize(sizeHint, maxSize))); + newSegment.SetOwnedMemory(pool!.Rent(GetSegmentSize(sizeHint, maxSize))); } else { @@ -241,7 +239,7 @@ private BufferSegment AllocateSegment(int sizeHint) private int GetSegmentSize(int sizeHint, int maxBufferSize = int.MaxValue) { // First we need to handle case where hint is smaller than minimum segment size - sizeHint = Math.Max(_minimumSegmentSize, sizeHint); + sizeHint = Math.Max(MinimumSegmentSize, sizeHint); // After that adjust it to fit into pools max buffer size int adjustedToMaximumSize = Math.Min(maxBufferSize, sizeHint); return adjustedToMaximumSize; @@ -263,7 +261,7 @@ private void ReturnSegmentUnsynchronized(BufferSegment segment) Debug.Assert(segment != _readTail, "Returning _readTail segment that's in use!"); Debug.Assert(segment != _writingHead, "Returning _writingHead segment that's in use!"); - if (_bufferSegmentPool.Count < MaxSegmentPoolSize) + if (_bufferSegmentPool.Count < _options.MaxSegmentPoolSize) { _bufferSegmentPool.Push(segment); } @@ -291,9 +289,9 @@ internal bool CommitUnsynchronized() _unconsumedBytes += _unflushedBytes; // Do not reset if reader is complete - if (_pauseWriterThreshold > 0 && - oldLength < _pauseWriterThreshold && - _unconsumedBytes >= _pauseWriterThreshold && + if (PauseWriterThreshold > 0 && + oldLength < PauseWriterThreshold && + _unconsumedBytes >= PauseWriterThreshold && !_readerCompletion.IsCompleted) { _writerAwaitable.SetUncompleted(); @@ -307,7 +305,7 @@ internal bool CommitUnsynchronized() internal void Advance(int bytes) { - lock (_sync) + lock (SyncObj) { if ((uint)bytes > (uint)_writingHeadMemory.Length) { @@ -336,12 +334,12 @@ internal ValueTask FlushAsync(CancellationToken cancellationToken) { CompletionData completionData; ValueTask result; - lock (_sync) + lock (SyncObj) { PrepareFlush(out completionData, out result, cancellationToken); } - TrySchedule(_readerScheduler, completionData); + TrySchedule(ReaderScheduler, completionData); return result; } @@ -389,7 +387,7 @@ internal void CompleteWriter(Exception? exception) PipeCompletionCallbacks? completionCallbacks; bool readerCompleted; - lock (_sync) + lock (SyncObj) { // Commit any pending buffers CommitUnsynchronized(); @@ -406,10 +404,10 @@ internal void CompleteWriter(Exception? exception) if (completionCallbacks != null) { - ScheduleCallbacks(_readerScheduler, completionCallbacks); + ScheduleCallbacks(ReaderScheduler, completionCallbacks); } - TrySchedule(_readerScheduler, completionData); + TrySchedule(ReaderScheduler, completionData); } internal void AdvanceReader(in SequencePosition consumed) @@ -443,7 +441,7 @@ private void AdvanceReader(BufferSegment? consumedSegment, int consumedIndex, Bu CompletionData completionData = default; - lock (_sync) + lock (SyncObj) { var examinedEverything = false; if (examinedSegment == _readTail) @@ -468,8 +466,8 @@ private void AdvanceReader(BufferSegment? consumedSegment, int consumedIndex, Bu Debug.Assert(_unconsumedBytes >= 0, "Length has gone negative"); - if (oldLength >= _resumeWriterThreshold && - _unconsumedBytes < _resumeWriterThreshold) + if (oldLength >= ResumeWriterThreshold && + _unconsumedBytes < ResumeWriterThreshold) { _writerAwaitable.Complete(out completionData); } @@ -552,7 +550,7 @@ void MoveReturnEndToNextBlock() _operationState.EndRead(); } - TrySchedule(_writerScheduler, completionData); + TrySchedule(WriterScheduler, completionData); } internal void CompleteReader(Exception? exception) @@ -561,7 +559,7 @@ internal void CompleteReader(Exception? exception) CompletionData completionData; bool writerCompleted; - lock (_sync) + lock (SyncObj) { // If we're reading, treat clean up that state before continuting if (_operationState.IsReadingActive) @@ -584,10 +582,10 @@ internal void CompleteReader(Exception? exception) if (completionCallbacks != null) { - ScheduleCallbacks(_writerScheduler, completionCallbacks); + ScheduleCallbacks(WriterScheduler, completionCallbacks); } - TrySchedule(_writerScheduler, completionData); + TrySchedule(WriterScheduler, completionData); } internal void OnWriterCompleted(Action callback, object? state) @@ -598,35 +596,35 @@ internal void OnWriterCompleted(Action callback, object? st } PipeCompletionCallbacks? completionCallbacks; - lock (_sync) + lock (SyncObj) { completionCallbacks = _writerCompletion.AddCallback(callback, state); } if (completionCallbacks != null) { - ScheduleCallbacks(_readerScheduler, completionCallbacks); + ScheduleCallbacks(ReaderScheduler, completionCallbacks); } } internal void CancelPendingRead() { CompletionData completionData; - lock (_sync) + lock (SyncObj) { _readerAwaitable.Cancel(out completionData); } - TrySchedule(_readerScheduler, completionData); + TrySchedule(ReaderScheduler, completionData); } internal void CancelPendingFlush() { CompletionData completionData; - lock (_sync) + lock (SyncObj) { _writerAwaitable.Cancel(out completionData); } - TrySchedule(_writerScheduler, completionData); + TrySchedule(WriterScheduler, completionData); } internal void OnReaderCompleted(Action callback, object? state) @@ -637,14 +635,14 @@ internal void OnReaderCompleted(Action callback, object? st } PipeCompletionCallbacks? completionCallbacks; - lock (_sync) + lock (SyncObj) { completionCallbacks = _readerCompletion.AddCallback(callback, state); } if (completionCallbacks != null) { - ScheduleCallbacks(_writerScheduler, completionCallbacks); + ScheduleCallbacks(WriterScheduler, completionCallbacks); } } @@ -656,7 +654,7 @@ internal ValueTask ReadAsync(CancellationToken token) } ValueTask result; - lock (_sync) + lock (SyncObj) { _readerAwaitable.BeginOperation(token, s_signalReaderAwaitable, this); @@ -678,7 +676,7 @@ internal ValueTask ReadAsync(CancellationToken token) internal bool TryRead(out ReadResult result) { - lock (_sync) + lock (SyncObj) { if (_readerCompletion.IsCompleted) { @@ -776,7 +774,7 @@ private static void ExecuteWithExecutionContext(object state) private void CompletePipe() { - lock (_sync) + lock (SyncObj) { if (_disposed) { @@ -821,7 +819,7 @@ internal void OnReadAsyncCompleted(Action continuation, object? state, { CompletionData completionData; bool doubleCompletion; - lock (_sync) + lock (SyncObj) { _readerAwaitable.OnCompleted(continuation, state, flags, out completionData, out doubleCompletion); } @@ -829,7 +827,7 @@ internal void OnReadAsyncCompleted(Action continuation, object? state, { Writer.Complete(ThrowHelper.CreateInvalidOperationException_NoConcurrentOperation()); } - TrySchedule(_readerScheduler, completionData); + TrySchedule(ReaderScheduler, completionData); } internal ReadResult GetReadAsyncResult() @@ -839,7 +837,7 @@ internal ReadResult GetReadAsyncResult() CancellationToken cancellationToken = default; try { - lock (_sync) + lock (SyncObj) { if (!_readerAwaitable.IsCompleted) { @@ -914,7 +912,7 @@ internal FlushResult GetFlushAsyncResult() try { - lock (_sync) + lock (SyncObj) { if (!_writerAwaitable.IsCompleted) { @@ -963,7 +961,7 @@ internal ValueTask WriteAsync(ReadOnlyMemory source, Cancella CompletionData completionData; ValueTask result; - lock (_sync) + lock (SyncObj) { // Allocate whatever the pool gives us so we can write, this also marks the // state as writing @@ -984,7 +982,7 @@ internal ValueTask WriteAsync(ReadOnlyMemory source, Cancella PrepareFlush(out completionData, out result, cancellationToken); } - TrySchedule(_readerScheduler, completionData); + TrySchedule(ReaderScheduler, completionData); return result; } @@ -1024,7 +1022,7 @@ internal void OnFlushAsyncCompleted(Action continuation, object? state, { CompletionData completionData; bool doubleCompletion; - lock (_sync) + lock (SyncObj) { _writerAwaitable.OnCompleted(continuation, state, flags, out completionData, out doubleCompletion); } @@ -1032,27 +1030,27 @@ internal void OnFlushAsyncCompleted(Action continuation, object? state, { Reader.Complete(ThrowHelper.CreateInvalidOperationException_NoConcurrentOperation()); } - TrySchedule(_writerScheduler, completionData); + TrySchedule(WriterScheduler, completionData); } private void ReaderCancellationRequested() { CompletionData completionData; - lock (_sync) + lock (SyncObj) { _readerAwaitable.CancellationTokenFired(out completionData); } - TrySchedule(_readerScheduler, completionData); + TrySchedule(ReaderScheduler, completionData); } private void WriterCancellationRequested() { CompletionData completionData; - lock (_sync) + lock (SyncObj) { _writerAwaitable.CancellationTokenFired(out completionData); } - TrySchedule(_writerScheduler, completionData); + TrySchedule(WriterScheduler, completionData); } /// Gets the for this pipe. @@ -1066,7 +1064,7 @@ private void WriterCancellationRequested() /// Resets the pipe. public void Reset() { - lock (_sync) + lock (SyncObj) { if (!_disposed) { diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeAwaitable.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeAwaitable.cs index dab70646c1df4..17427bb0a1203 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeAwaitable.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeAwaitable.cs @@ -14,9 +14,9 @@ internal struct PipeAwaitable private AwaitableState _awaitableState; private Action? _completion; private object? _completionState; + // It's rare to have to capture custom context here + private SchedulingContext? _schedulingContext; private CancellationTokenRegistration _cancellationTokenRegistration; - private SynchronizationContext? _synchronizationContext; - private ExecutionContext? _executionContext; #if (!NETSTANDARD2_0 && !NETFRAMEWORK) private CancellationToken CancellationToken => _cancellationTokenRegistration.Token; @@ -32,8 +32,7 @@ public PipeAwaitable(bool completed, bool useSynchronizationContext) _completion = null; _completionState = null; _cancellationTokenRegistration = default; - _synchronizationContext = null; - _executionContext = null; + _schedulingContext = null; #if (NETSTANDARD2_0 || NETFRAMEWORK) _cancellationToken = CancellationToken.None; #endif @@ -73,13 +72,13 @@ private void ExtractCompletion(out CompletionData completionData) { Action? currentCompletion = _completion; object? currentState = _completionState; - ExecutionContext? executionContext = _executionContext; - SynchronizationContext? synchronizationContext = _synchronizationContext; + SchedulingContext? schedulingContext = _schedulingContext; + ExecutionContext? executionContext = schedulingContext?.ExecutionContext; + SynchronizationContext? synchronizationContext = schedulingContext?.SynchronizationContext; _completion = null; _completionState = null; - _synchronizationContext = null; - _executionContext = null; + _schedulingContext = null; completionData = currentCompletion != null ? new CompletionData(currentCompletion, currentState, executionContext, synchronizationContext) : @@ -91,8 +90,7 @@ public void SetUncompleted() { Debug.Assert(_completion == null); Debug.Assert(_completionState == null); - Debug.Assert(_synchronizationContext == null); - Debug.Assert(_executionContext == null); + Debug.Assert(_schedulingContext == null); _awaitableState &= ~AwaitableState.Completed; } @@ -104,7 +102,7 @@ public void OnCompleted(Action continuation, object? state, ValueTaskSo if (IsCompleted || doubleCompletion) { - completionData = new CompletionData(continuation, state, _executionContext, _synchronizationContext); + completionData = new CompletionData(continuation, state, _schedulingContext?.ExecutionContext, _schedulingContext?.SynchronizationContext); return; } @@ -118,14 +116,16 @@ public void OnCompleted(Action continuation, object? state, ValueTaskSo SynchronizationContext? sc = SynchronizationContext.Current; if (sc != null && sc.GetType() != typeof(SynchronizationContext)) { - _synchronizationContext = sc; + _schedulingContext ??= new SchedulingContext(); + _schedulingContext.SynchronizationContext = sc; } } // Capture the execution context if ((flags & ValueTaskSourceOnCompletedFlags.FlowExecutionContext) != 0) { - _executionContext = ExecutionContext.Capture(); + _schedulingContext ??= new SchedulingContext(); + _schedulingContext.ExecutionContext = ExecutionContext.Capture(); } } @@ -185,5 +185,11 @@ private enum AwaitableState Canceled = 4, UseSynchronizationContext = 8 } + + private class SchedulingContext + { + public SynchronizationContext? SynchronizationContext { get; set; } + public ExecutionContext? ExecutionContext { get; set; } + } } } diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeCompletion.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeCompletion.cs index a37292d52a44e..5c0ff7b591542 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeCompletion.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeCompletion.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers; +using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; @@ -11,51 +11,36 @@ namespace System.IO.Pipelines [DebuggerDisplay("IsCompleted: {" + nameof(IsCompleted) + "}")] internal struct PipeCompletion { - private static readonly ArrayPool s_completionCallbackPool = ArrayPool.Shared; + private static readonly object s_completedSuccessfully = new object(); - private const int InitialCallbacksSize = 1; + private object? _state; + private List? _callbacks; - private bool _isCompleted; - private ExceptionDispatchInfo? _exceptionInfo; + public bool IsCompleted => _state != null; - private PipeCompletionCallback _firstCallback; - private PipeCompletionCallback[]? _callbacks; - private int _callbackCount; - - public bool IsCompleted => _isCompleted; - - public bool IsFaulted => _exceptionInfo != null; + public bool IsFaulted => _state is ExceptionDispatchInfo; public PipeCompletionCallbacks? TryComplete(Exception? exception = null) { - if (!_isCompleted) + if (_state == null) { - _isCompleted = true; if (exception != null) { - _exceptionInfo = ExceptionDispatchInfo.Capture(exception); + _state = ExceptionDispatchInfo.Capture(exception); + } + else + { + _state = s_completedSuccessfully; } } + return GetCallbacks(); } public PipeCompletionCallbacks? AddCallback(Action callback, object? state) { - if (_callbackCount == 0) - { - _firstCallback = new PipeCompletionCallback(callback, state); - _callbackCount++; - } - else - { - EnsureSpace(); - - // -1 to adjust for _firstCallback - var callbackIndex = _callbackCount - 1; - _callbackCount++; - Debug.Assert(_callbacks != null); - _callbacks[callbackIndex] = new PipeCompletionCallback(callback, state); - } + _callbacks ??= new List(); + _callbacks.Add(new PipeCompletionCallback(callback, state)); if (IsCompleted) { @@ -65,35 +50,17 @@ internal struct PipeCompletion return null; } - private void EnsureSpace() - { - if (_callbacks == null) - { - _callbacks = s_completionCallbackPool.Rent(InitialCallbacksSize); - } - - int newLength = _callbackCount - 1; - - if (newLength == _callbacks.Length) - { - PipeCompletionCallback[] newArray = s_completionCallbackPool.Rent(_callbacks.Length * 2); - Array.Copy(_callbacks, newArray, _callbacks.Length); - s_completionCallbackPool.Return(_callbacks, clearArray: true); - _callbacks = newArray; - } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsCompletedOrThrow() { - if (!_isCompleted) + if (!IsCompleted) { return false; } - if (_exceptionInfo != null) + if (_state is ExceptionDispatchInfo edi) { - ThrowLatchedException(); + edi.Throw(); } return true; @@ -102,36 +69,23 @@ public bool IsCompletedOrThrow() private PipeCompletionCallbacks? GetCallbacks() { Debug.Assert(IsCompleted); - if (_callbackCount == 0) + + var callbacks = _callbacks; + if (callbacks == null) { return null; } - var callbacks = new PipeCompletionCallbacks(s_completionCallbackPool, - _callbackCount, - _exceptionInfo?.SourceException, - _firstCallback, - _callbacks); - - _firstCallback = default; _callbacks = null; - _callbackCount = 0; - return callbacks; + + return new PipeCompletionCallbacks(callbacks, _state as ExceptionDispatchInfo); } public void Reset() { Debug.Assert(IsCompleted); Debug.Assert(_callbacks == null); - _isCompleted = false; - _exceptionInfo = null; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private void ThrowLatchedException() - { - Debug.Assert(_exceptionInfo != null); - _exceptionInfo.Throw(); + _state = null; } public override string ToString() diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeCompletionCallbacks.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeCompletionCallbacks.cs index 9bba043440c02..47c9d064ac573 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeCompletionCallbacks.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeCompletionCallbacks.cs @@ -1,52 +1,38 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Buffers; using System.Collections.Generic; +using System.Runtime.ExceptionServices; namespace System.IO.Pipelines { internal sealed class PipeCompletionCallbacks { - private readonly ArrayPool _pool; - private readonly int _count; + private readonly List _callbacks; private readonly Exception? _exception; - private readonly PipeCompletionCallback _firstCallback; - private readonly PipeCompletionCallback[]? _callbacks; - public PipeCompletionCallbacks(ArrayPool pool, int count, Exception? exception, PipeCompletionCallback firstCallback, PipeCompletionCallback[]? callbacks) + public PipeCompletionCallbacks(List callbacks, ExceptionDispatchInfo? edi) { - _pool = pool; - _count = count; - _exception = exception; - _firstCallback = firstCallback; _callbacks = callbacks; + _exception = edi?.SourceException; } public void Execute() { - if (_count == 0) + var count = _callbacks.Count; + if (count == 0) { return; } List? exceptions = null; - Execute(_firstCallback, ref exceptions); - if (_callbacks != null) { - try - { - for (var i = 0; i < _count - 1; i++) - { - var callback = _callbacks[i]; - Execute(callback, ref exceptions); - } - } - finally + for (int i = 0; i < count; i++) { - _pool.Return(_callbacks, clearArray: true); + var callback = _callbacks[i]; + Execute(callback, ref exceptions); } } diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeOptions.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeOptions.cs index 6790f7ecf25f4..998845f804dd3 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeOptions.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeOptions.cs @@ -11,10 +11,6 @@ public class PipeOptions { private const int DefaultMinimumSegmentSize = 4096; - private const int DefaultResumeWriterThreshold = DefaultMinimumSegmentSize * Pipe.InitialSegmentPoolSize / 2; - - private const int DefaultPauseWriterThreshold = DefaultMinimumSegmentSize * Pipe.InitialSegmentPoolSize; - /// Gets the default instance of . /// A object initialized with default parameters. public static PipeOptions Default { get; } = new PipeOptions(); @@ -36,6 +32,24 @@ public PipeOptions( int minimumSegmentSize = -1, bool useSynchronizationContext = true) { + MinimumSegmentSize = minimumSegmentSize == -1 ? DefaultMinimumSegmentSize : minimumSegmentSize; + + // TODO: These *should* be computed based on how much users want to buffer and the minimum segment size. Today we don't have a way + // to let users specify the maximum buffer size, so we pick a reasonable number based on defaults. They can influence + // how much gets buffered by increasing the minimum segment size. + + // With a defaukt segment size of 4K this maps to 16K + InitialSegmentPoolSize = 4; + + // With a defaukt segment size of 4K this maps to 1MB. If the pipe has large segments this will be bigger than 1MB... + MaxSegmentPoolSize = 256; + + // By default, we'll throttle the writer at 64K of buffered data + const int DefaultPauseWriterThreshold = 65536; + + // Resume threshold is 1/2 of the pause threshold to prevent thrashing at the limit + const int DefaultResumeWriterThreshold = DefaultPauseWriterThreshold / 2; + if (pauseWriterThreshold == -1) { pauseWriterThreshold = DefaultPauseWriterThreshold; @@ -55,11 +69,11 @@ public PipeOptions( } Pool = pool ?? MemoryPool.Shared; + IsDefaultSharedMemoryPool = Pool == MemoryPool.Shared; ReaderScheduler = readerScheduler ?? PipeScheduler.ThreadPool; WriterScheduler = writerScheduler ?? PipeScheduler.ThreadPool; PauseWriterThreshold = pauseWriterThreshold; ResumeWriterThreshold = resumeWriterThreshold; - MinimumSegmentSize = minimumSegmentSize == -1 ? DefaultMinimumSegmentSize : minimumSegmentSize; UseSynchronizationContext = useSynchronizationContext; } @@ -90,5 +104,20 @@ public PipeOptions( /// Gets the object used for buffer management. /// A pool of memory blocks used for buffer management. public MemoryPool Pool { get; } + + /// + /// Returns true if Pool is .Shared + /// + internal bool IsDefaultSharedMemoryPool { get; } + + /// + /// The initialize size of the segment pool + /// + internal int InitialSegmentPoolSize { get; } + + /// + /// The maximum number of segments to pool + /// + internal int MaxSegmentPoolSize { get; } } } diff --git a/src/libraries/System.IO.Pipelines/tests/BufferSegmentPoolTest.cs b/src/libraries/System.IO.Pipelines/tests/BufferSegmentPoolTest.cs index 421c31c36ee77..c89ae0e8f2024 100644 --- a/src/libraries/System.IO.Pipelines/tests/BufferSegmentPoolTest.cs +++ b/src/libraries/System.IO.Pipelines/tests/BufferSegmentPoolTest.cs @@ -60,7 +60,7 @@ public async Task BufferSegmentsAreReused() [Fact] public async Task BufferSegmentsPooledUpToThreshold() { - int blockCount = Pipe.MaxSegmentPoolSize + 1; + int blockCount = PipeOptions.Default.MaxSegmentPoolSize + 1; // Write 256 blocks to ensure they get reused for (int i = 0; i < blockCount; i++) @@ -95,9 +95,9 @@ public async Task BufferSegmentsPooledUpToThreshold() _pipe.Reader.AdvanceTo(result.Buffer.End); // Assert Pipe.MaxSegmentPoolSize pooled segments - for (int i = 0; i < Pipe.MaxSegmentPoolSize; i++) + for (int i = 0; i < PipeOptions.Default.MaxSegmentPoolSize; i++) { - Assert.Same(oldSegments[i], newSegments[Pipe.MaxSegmentPoolSize - i - 1]); + Assert.Same(oldSegments[i], newSegments[PipeOptions.Default.MaxSegmentPoolSize - i - 1]); } // The last segment shouldn't exist in the new list of segments at all (it should be new) From 9a70e7a68889f4c593479f4c20495a7f8c4528e8 Mon Sep 17 00:00:00 2001 From: CadenJi <742655502@qq.com> Date: Mon, 8 Mar 2021 19:39:08 +0800 Subject: [PATCH 33/83] Rule number correction (#49288) --- docs/coding-guidelines/coding-style.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/coding-guidelines/coding-style.md b/docs/coding-guidelines/coding-style.md index 6181ee3dbe993..38cc58c620aa7 100644 --- a/docs/coding-guidelines/coding-style.md +++ b/docs/coding-guidelines/coding-style.md @@ -7,7 +7,7 @@ For other types of files (xml, bat, sh, etc), our current best guidance is consi The general rule we follow is "use Visual Studio defaults". -1. We use [Allman style](http://en.wikipedia.org/wiki/Indent_style#Allman_style) braces, where each brace begins on a new line. A single line statement block can go without braces but the block must be properly indented on its own line and must not be nested in other statement blocks that use braces (See rule 17 for more details). One exception is that a `using` statement is permitted to be nested within another `using` statement by starting on the following line at the same indentation level, even if the nested `using` contains a controlled block. +1. We use [Allman style](http://en.wikipedia.org/wiki/Indent_style#Allman_style) braces, where each brace begins on a new line. A single line statement block can go without braces but the block must be properly indented on its own line and must not be nested in other statement blocks that use braces (See rule 18 for more details). One exception is that a `using` statement is permitted to be nested within another `using` statement by starting on the following line at the same indentation level, even if the nested `using` contains a controlled block. 2. We use four spaces of indentation (no tabs). 3. We use `_camelCase` for internal and private fields and use `readonly` where possible. Prefix internal and private instance fields with `_`, static fields with `s_` and thread static fields with `t_`. When used on static fields, `readonly` should come after `static` (e.g. `static readonly` not `readonly static`). Public fields should be used sparingly and should use PascalCasing with no prefix when used. 4. We avoid `this.` unless absolutely necessary. From c392e0ade36f1a5ab312066724d77b595f6846ce Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 8 Mar 2021 10:46:24 -0500 Subject: [PATCH 34/83] Replace a couple FormatterServices uses in DataContractSerialization (#49290) --- .../src/System/Runtime/Serialization/SurrogateDataContract.cs | 2 +- .../System/Runtime/Serialization/XmlFormatReaderGenerator.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SurrogateDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SurrogateDataContract.cs index ebf41ee91263c..1cd727072f8c5 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SurrogateDataContract.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/SurrogateDataContract.cs @@ -47,7 +47,7 @@ public override void WriteXmlValue(XmlWriterDelegator xmlWriter, object obj, Xml [MethodImpl(MethodImplOptions.NoInlining)] private object GetUninitializedObject(Type objType) { - return FormatterServices.GetUninitializedObject(objType); + return RuntimeHelpers.GetUninitializedObject(objType); } [MethodImpl(MethodImplOptions.NoInlining)] diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs index 9c5d3cf710598..483f80392a910 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs @@ -942,7 +942,7 @@ private void ThrowValidationException() internal static object UnsafeGetUninitializedObject(Type type) { - return FormatterServices.GetUninitializedObject(type); + return RuntimeHelpers.GetUninitializedObject(type); } /// From 4c79d45edd899133cf6d36dc9b4de122ceca72cf Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 8 Mar 2021 15:51:14 +0000 Subject: [PATCH 35/83] Update dependencies from https://github.com/dotnet/runtime build 20210307.6 (#49296) [main] Update dependencies from dotnet/runtime --- eng/Version.Details.xml | 28 ++++++++++++++-------------- eng/Versions.props | 12 ++++++------ global.json | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index be496d19a6417..a064479ce7d93 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -166,33 +166,33 @@ https://github.com/dotnet/runtime 38017c3935de95d0335bac04f4901ddfc2718656 - + https://github.com/dotnet/runtime - 3553284bea7b650874c8dcc3f78d6be085a047bb + acbbb505492244b4c07a4a368257ba86a1fc02e1 - + https://github.com/dotnet/runtime - 3553284bea7b650874c8dcc3f78d6be085a047bb + acbbb505492244b4c07a4a368257ba86a1fc02e1 - + https://github.com/dotnet/runtime - 3553284bea7b650874c8dcc3f78d6be085a047bb + acbbb505492244b4c07a4a368257ba86a1fc02e1 - + https://github.com/dotnet/runtime - 3553284bea7b650874c8dcc3f78d6be085a047bb + acbbb505492244b4c07a4a368257ba86a1fc02e1 - + https://github.com/dotnet/runtime - 3553284bea7b650874c8dcc3f78d6be085a047bb + acbbb505492244b4c07a4a368257ba86a1fc02e1 - + https://github.com/dotnet/runtime - 3553284bea7b650874c8dcc3f78d6be085a047bb + acbbb505492244b4c07a4a368257ba86a1fc02e1 - + https://github.com/dotnet/runtime - 3553284bea7b650874c8dcc3f78d6be085a047bb + acbbb505492244b4c07a4a368257ba86a1fc02e1 https://github.com/mono/linker diff --git a/eng/Versions.props b/eng/Versions.props index 27dbe8e98f172..f6905d2916f0b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -65,11 +65,11 @@ 5.9.0-preview.2 6.0.0-alpha.1.20612.4 - 6.0.0-preview.3.21151.2 - 6.0.0-preview.3.21151.2 + 6.0.0-preview.3.21157.6 + 6.0.0-preview.3.21157.6 3.1.0 - 6.0.0-preview.3.21151.2 + 6.0.0-preview.3.21157.6 1.2.0-beta.304 4.5.1 @@ -97,14 +97,14 @@ 4.7.0 4.7.0 4.7.0 - 6.0.0-preview.3.21151.2 - 6.0.0-preview.3.21151.2 + 6.0.0-preview.3.21157.6 + 6.0.0-preview.3.21157.6 4.3.0 4.5.4 4.5.0 1.1.1 4.3.0 - 6.0.0-preview.3.21151.2 + 6.0.0-preview.3.21157.6 5.0.0-beta.21151.2 5.0.0-beta.21151.2 diff --git a/global.json b/global.json index 72cce5fec4fd8..28d854b09b734 100644 --- a/global.json +++ b/global.json @@ -18,6 +18,6 @@ "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21152.1", "Microsoft.Build.NoTargets": "2.0.17", "Microsoft.Build.Traversal": "2.1.1", - "Microsoft.NET.Sdk.IL": "6.0.0-preview.3.21151.2" + "Microsoft.NET.Sdk.IL": "6.0.0-preview.3.21157.6" } } From 3060060480753c98bc8e17768def166e0504a6dd Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 8 Mar 2021 15:10:03 -0500 Subject: [PATCH 36/83] Fix https://github.com/dotnet/runtime/issues/46698. (#49293) --- src/mono/mono/mini/method-to-ir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 1b900f43040c1..24a5b3ae84b02 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -3326,7 +3326,7 @@ mini_emit_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_us MonoMethod* method = get_method_nofail (klass, "Box", 1, 0); if (context_used) { - if (cfg->llvm_only && cfg->gsharedvt) { + if (cfg->llvm_only) { MonoInst *addr = emit_get_rgctx_method (cfg, context_used, method, MONO_RGCTX_INFO_METHOD_FTNDESC); return mini_emit_llvmonly_calli (cfg, mono_method_signature_internal (method), &val, addr); From df7a4e39dc0f820be3bf271b1023efa6759b8379 Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Mon, 8 Mar 2021 12:16:38 -0800 Subject: [PATCH 37/83] Do not bundle mscordaccore.dll in a singlefile package. (#49254) --- .../pkg/sfx/Microsoft.NETCore.App/Directory.Build.props | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index e255d5c50f99e..d165bf2c06efb 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -12,13 +12,18 @@ + - $(NuGetPackageRoot)\microsoft.targetingpack.netframework.v4.6.1\1.0.1\lib\net461\;$(AssemblySearchPaths) + + + diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs index 385d959770732..a008637271e1a 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpTelemetry.cs @@ -158,6 +158,10 @@ public void Http20ConnectionClosed() ConnectionClosed(versionMajor: 2, versionMinor: 0); } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "Parameters to this method are primitive and are trimmer safe")] +#endif [NonEvent] private unsafe void WriteEvent(int eventId, string? arg1, string? arg2, int arg3, string? arg4, byte arg5, byte arg6, HttpVersionPolicy arg7) { @@ -215,6 +219,10 @@ private unsafe void WriteEvent(int eventId, string? arg1, string? arg2, int arg3 } } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "Parameters to this method are primitive and are trimmer safe")] +#endif [NonEvent] private unsafe void WriteEvent(int eventId, double arg1, byte arg2, byte arg3) { @@ -243,6 +251,10 @@ private unsafe void WriteEvent(int eventId, double arg1, byte arg2, byte arg3) } } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "Parameters to this method are primitive and are trimmer safe")] +#endif [NonEvent] private unsafe void WriteEvent(int eventId, byte arg1, byte arg2) { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/NetEventSource.Http.cs b/src/libraries/System.Net.Http/src/System/Net/Http/NetEventSource.Http.cs index 5ba0eed91c17d..d1de2d9735399 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/NetEventSource.Http.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/NetEventSource.Http.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; namespace System.Net @@ -73,6 +74,10 @@ public static void AuthenticationError(Uri? uri, string message) public void AuthenticationError(string? uri, string message) => WriteEvent(AuthenticationErrorId, uri, message); +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "Parameters to this method are primitive and are trimmer safe")] +#endif [NonEvent] private unsafe void WriteEvent(int eventId, int arg1, int arg2, int arg3, string? arg4, string? arg5) { diff --git a/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionTelemetry.cs b/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionTelemetry.cs index 038b78bd6fc66..fd5d2d31a0118 100644 --- a/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionTelemetry.cs +++ b/src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionTelemetry.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Runtime.InteropServices; using System.Threading; @@ -142,6 +143,10 @@ private static Span FormatIPAddressNullTerminated(IPAddress address, Span< // WriteEvent overloads taking Span are imitating string arguments // Span arguments are expected to be null-terminated +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "Parameters to this method are primitive and are trimmer safe")] +#endif [NonEvent] private unsafe void WriteEvent(int eventId, Span arg1) { diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/NetEventSource.Security.Windows.cs b/src/libraries/System.Net.Security/src/System/Net/Security/NetEventSource.Security.Windows.cs index 3baef823c78d1..1d6b61bbf9191 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/NetEventSource.Security.Windows.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/NetEventSource.Security.Windows.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Net.Security; @@ -8,6 +9,10 @@ namespace System.Net { internal sealed partial class NetEventSource { +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "parameter intent is an enum and is trimmer safe")] +#endif [Event(AcquireDefaultCredentialId, Keywords = Keywords.Default, Level = EventLevel.Informational)] public void AcquireDefaultCredential(string packageName, Interop.SspiCli.CredentialUse intent) { @@ -59,6 +64,10 @@ public void AcceptSecurityContext(SafeFreeCredentials? credential, SafeDeleteCon private void AcceptSecurityContext(string credential, string context, Interop.SspiCli.ContextFlags inFlags) => WriteEvent(AcceptSecuritContextId, credential, context, (int)inFlags); +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "parameter errorCode is an enum and is trimmer safe")] +#endif [Event(OperationReturnedSomethingId, Keywords = Keywords.Default, Level = EventLevel.Informational)] public void OperationReturnedSomething(string operation, Interop.SECURITY_STATUS errorCode) { diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs b/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs index 0c393405bfc4c..eaeb6026dd86e 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/NetSecurityTelemetry.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Diagnostics.Tracing; +using System.Diagnostics.CodeAnalysis; using System.Security.Authentication; using System.Threading; using Microsoft.Extensions.Internal; @@ -12,6 +13,9 @@ namespace System.Net.Security [EventSource(Name = "System.Net.Security")] internal sealed class NetSecurityTelemetry : EventSource { +#if !ES_BUILD_STANDALONE + private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; +#endif public static readonly NetSecurityTelemetry Log = new NetSecurityTelemetry(); private IncrementingPollingCounter? _tlsHandshakeRateCounter; @@ -240,6 +244,10 @@ public void ConnectionClosed(SslProtocols protocol) } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [NonEvent] private unsafe void WriteEvent(int eventId, bool arg1, string? arg2) { @@ -268,6 +276,10 @@ private unsafe void WriteEvent(int eventId, bool arg1, string? arg2) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [NonEvent] private unsafe void WriteEvent(int eventId, SslProtocols arg1) { @@ -283,6 +295,10 @@ private unsafe void WriteEvent(int eventId, SslProtocols arg1) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [NonEvent] private unsafe void WriteEvent(int eventId, bool arg1, double arg2, string? arg3) { diff --git a/src/libraries/System.Private.CoreLib/generators/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/generators/System.Private.CoreLib.Generators.csproj index 9b241b14aaf42..17d98413268e5 100644 --- a/src/libraries/System.Private.CoreLib/generators/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/generators/System.Private.CoreLib.Generators.csproj @@ -10,7 +10,11 @@ - + + + + + diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.Shared.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.Shared.xml index 50960f8c7e113..0dc3b55fc8603 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.Shared.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.Shared.xml @@ -49,12 +49,6 @@ member M:Internal.Runtime.InteropServices.ComponentActivator.InternalGetFunctionPointer(System.Runtime.Loader.AssemblyLoadContext,System.String,System.String,System.IntPtr) - - ILLink - IL2070 - member - M:System.Diagnostics.Tracing.TypeAnalysis.#ctor(System.Type,System.Diagnostics.Tracing.EventDataAttribute,System.Collections.Generic.List{System.Type}) - ILLink IL2072 diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/ArrayPoolEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/ArrayPoolEventSource.cs index 39d6d313a6d37..7fb9e54b6bb85 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/ArrayPoolEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/ArrayPoolEventSource.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.Tracing; +using System.Diagnostics.CodeAnalysis; namespace System.Buffers { @@ -9,6 +10,9 @@ namespace System.Buffers [EventSourceAutoGenerate] internal sealed partial class ArrayPoolEventSource : EventSource { +#if !ES_BUILD_STANDALONE + private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; +#endif internal static readonly ArrayPoolEventSource Log = new ArrayPoolEventSource(); /// Bucket ID used when renting/returning an array that's too large for a pool. @@ -46,6 +50,10 @@ private ArrayPoolEventSource(int _) { } /// of BufferAllocated events being less than or equal to those numbers (ideally significantly /// less than). /// +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(1, Level = EventLevel.Verbose)] internal unsafe void BufferRented(int bufferId, int bufferSize, int poolId, int bucketId) { @@ -70,6 +78,10 @@ internal unsafe void BufferRented(int bufferId, int bufferSize, int poolId, int /// of BufferAllocated events is significantly smaller than the number of BufferRented and /// BufferReturned events. /// +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(2, Level = EventLevel.Informational)] internal unsafe void BufferAllocated(int bufferId, int bufferSize, int poolId, int bucketId, BufferAllocatedReason reason) { @@ -117,6 +129,10 @@ internal unsafe void BufferAllocated(int bufferId, int bufferSize, int poolId, i /// /// Event raised when a buffer returned to the pool is dropped. /// +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = EventSourceSuppressMessage)] +#endif [Event(6, Level = EventLevel.Informational)] internal unsafe void BufferDropped(int bufferId, int bufferSize, int poolId, int bucketId, BufferDroppedReason reason) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs index ecd1dcb3a1afe..a5ae224e4e589 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs @@ -95,6 +95,11 @@ internal void OnMetricWritten(double value) _count++; } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The DynamicDependency will preserve the properties of CounterPayload")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(CounterPayload))] +#endif internal override void WritePayload(float intervalSec, int pollingIntervalMillisec) { lock (this) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index d8bf7dcad1cc3..9e1d568f83279 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -765,12 +765,20 @@ protected virtual void OnEventCommand(EventCommandEventArgs command) { } #pragma warning disable 1591 // optimized for common signatures (no args) +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId) { WriteEventCore(eventId, 0, null); } // optimized for common signatures (ints) +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, int arg1) { if (IsEnabled()) @@ -783,6 +791,10 @@ protected unsafe void WriteEvent(int eventId, int arg1) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, int arg1, int arg2) { if (IsEnabled()) @@ -798,6 +810,10 @@ protected unsafe void WriteEvent(int eventId, int arg1, int arg2) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, int arg1, int arg2, int arg3) { if (IsEnabled()) @@ -817,6 +833,10 @@ protected unsafe void WriteEvent(int eventId, int arg1, int arg2, int arg3) } // optimized for common signatures (longs) +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, long arg1) { if (IsEnabled()) @@ -829,6 +849,10 @@ protected unsafe void WriteEvent(int eventId, long arg1) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, long arg1, long arg2) { if (IsEnabled()) @@ -844,6 +868,10 @@ protected unsafe void WriteEvent(int eventId, long arg1, long arg2) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, long arg1, long arg2, long arg3) { if (IsEnabled()) @@ -863,6 +891,10 @@ protected unsafe void WriteEvent(int eventId, long arg1, long arg2, long arg3) } // optimized for common signatures (strings) +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, string? arg1) { if (IsEnabled()) @@ -879,6 +911,10 @@ protected unsafe void WriteEvent(int eventId, string? arg1) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, string? arg1, string? arg2) { if (IsEnabled()) @@ -900,6 +936,10 @@ protected unsafe void WriteEvent(int eventId, string? arg1, string? arg2) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, string? arg1, string? arg2, string? arg3) { if (IsEnabled()) @@ -927,6 +967,10 @@ protected unsafe void WriteEvent(int eventId, string? arg1, string? arg2, string } // optimized for common signatures (string and ints) +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, string? arg1, int arg2) { if (IsEnabled()) @@ -946,6 +990,10 @@ protected unsafe void WriteEvent(int eventId, string? arg1, int arg2) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, string? arg1, int arg2, int arg3) { if (IsEnabled()) @@ -969,6 +1017,10 @@ protected unsafe void WriteEvent(int eventId, string? arg1, int arg2, int arg3) } // optimized for common signatures (string and longs) +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, string? arg1, long arg2) { if (IsEnabled()) @@ -989,6 +1041,10 @@ protected unsafe void WriteEvent(int eventId, string? arg1, long arg2) } // optimized for common signatures (long and string) +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, long arg1, string? arg2) { if (IsEnabled()) @@ -1009,6 +1065,10 @@ protected unsafe void WriteEvent(int eventId, long arg1, string? arg2) } // optimized for common signatures (int and string) +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, int arg1, string? arg2) { if (IsEnabled()) @@ -1028,6 +1088,10 @@ protected unsafe void WriteEvent(int eventId, int arg1, string? arg2) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, byte[]? arg1) { if (IsEnabled()) @@ -1061,6 +1125,10 @@ protected unsafe void WriteEvent(int eventId, byte[]? arg1) } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif protected unsafe void WriteEvent(int eventId, long arg1, byte[]? arg2) { if (IsEnabled()) @@ -1184,6 +1252,9 @@ internal unsafe void SetMetadata(byte* pointer, int size, int reserved) /// } /// /// +#if !ES_BUILD_STANDALONE + [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] +#endif [CLSCompliant(false)] protected unsafe void WriteEventCore(int eventId, int eventDataCount, EventSource.EventData* data) { @@ -1215,6 +1286,9 @@ protected unsafe void WriteEventCore(int eventId, int eventDataCount, EventSourc /// } /// /// +#if !ES_BUILD_STANDALONE + [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] +#endif [CLSCompliant(false)] protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* relatedActivityId, int eventDataCount, EventSource.EventData* data) { @@ -1311,6 +1385,9 @@ protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* rel /// method signature. Even if you use this for rare events, this call should be guarded by an /// check so that the varargs call is not made when the EventSource is not active. /// +#if !ES_BUILD_STANDALONE + [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] +#endif protected unsafe void WriteEvent(int eventId, params object?[] args) { WriteEventVarargs(eventId, null, args); @@ -1324,6 +1401,9 @@ protected unsafe void WriteEvent(int eventId, params object?[] args) /// particular method signature. Even if you use this for rare events, this call should be guarded by an /// check so that the varargs call is not made when the EventSource is not active. /// +#if !ES_BUILD_STANDALONE + [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] +#endif protected unsafe void WriteEventWithRelatedActivityId(int eventId, Guid relatedActivityId, params object?[] args) { WriteEventVarargs(eventId, &relatedActivityId, args); @@ -1761,6 +1841,9 @@ private static Guid GenerateGuidFromName(string name) return dispatcher; } +#if !ES_BUILD_STANDALONE + [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] +#endif private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object?[] args) { if (IsEnabled()) @@ -1886,6 +1969,9 @@ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object } } +#if !ES_BUILD_STANDALONE + [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] +#endif private unsafe object?[] SerializeEventArgs(int eventId, object?[] args) { Debug.Assert(m_eventData != null); @@ -2065,7 +2151,15 @@ private unsafe void WriteEventString(string msgString) Keywords = (EventKeywords)unchecked(keywords), Level = level }; - var tlet = new TraceLoggingEventTypes(EventName, EventTags.None, new Type[] { typeof(string) }); + +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The call to TraceLoggingEventTypes with the below parameter values are trim safe")] +#endif + static TraceLoggingEventTypes GetTrimSafeTraceLoggingEventTypes() => + new TraceLoggingEventTypes(EventName, EventTags.None, new Type[] { typeof(string) }); + + var tlet = GetTrimSafeTraceLoggingEventTypes(); WriteMultiMergeInner(EventName, ref opt, tlet, null, null, msgString); } else diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs index d1e3cfe154e27..700955e8cad4b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using Internal.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; namespace System.Diagnostics.Tracing { @@ -10,6 +11,9 @@ namespace System.Diagnostics.Tracing [EventSourceAutoGenerate] internal sealed partial class FrameworkEventSource : EventSource { +#if !ES_BUILD_STANDALONE + private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; +#endif public static readonly FrameworkEventSource Log = new FrameworkEventSource(); // Keyword definitions. These represent logical groups of events that can be turned on and off independently @@ -34,6 +38,10 @@ public static class Keywords private FrameworkEventSource(int _) { } // optimized for common signatures (used by the ThreadTransferSend/Receive events) +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [NonEvent] private unsafe void WriteEvent(int eventId, long arg1, int arg2, string? arg3, bool arg4, int arg5, int arg6) { @@ -67,6 +75,10 @@ private unsafe void WriteEvent(int eventId, long arg1, int arg2, string? arg3, b } // optimized for common signatures (used by the ThreadTransferSend/Receive events) +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [NonEvent] private unsafe void WriteEvent(int eventId, long arg1, int arg2, string? arg3) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingEventCounter.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingEventCounter.cs index 4b4d08ec738bf..633ab218a5e16 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingEventCounter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingEventCounter.cs @@ -9,6 +9,7 @@ #if ES_BUILD_STANDALONE namespace Microsoft.Diagnostics.Tracing #else +using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; namespace System.Diagnostics.Tracing @@ -56,6 +57,11 @@ public void Increment(double increment = 1) public override string ToString() => $"IncrementingEventCounter '{Name}' Increment {_increment}"; +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The DynamicDependency will preserve the properties of IncrementingCounterPayload")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(IncrementingCounterPayload))] +#endif internal override void WritePayload(float intervalSec, int pollingIntervalMillisec) { lock (this) // Lock the counter diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingPollingCounter.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingPollingCounter.cs index d18e5ad6f93c3..1097c38f80fe9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingPollingCounter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingPollingCounter.cs @@ -8,6 +8,7 @@ #if ES_BUILD_STANDALONE namespace Microsoft.Diagnostics.Tracing #else +using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; namespace System.Diagnostics.Tracing @@ -69,6 +70,11 @@ internal void UpdateMetric() } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The DynamicDependency will preserve the properties of IncrementingCounterPayload")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(IncrementingCounterPayload))] +#endif internal override void WritePayload(float intervalSec, int pollingIntervalMillisec) { UpdateMetric(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/PollingCounter.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/PollingCounter.cs index d2b88669b21ac..5b3063f934c31 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/PollingCounter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/PollingCounter.cs @@ -8,6 +8,7 @@ #if ES_BUILD_STANDALONE namespace Microsoft.Diagnostics.Tracing #else +using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; namespace System.Diagnostics.Tracing @@ -46,6 +47,11 @@ public PollingCounter(string name, EventSource eventSource, Func metricP private readonly Func _metricProvider; private double _lastVal; +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The DynamicDependency will preserve the properties of CounterPayload")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(CounterPayload))] +#endif internal override void WritePayload(float intervalSec, int pollingIntervalMillisec) { lock (this) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleEventTypes.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleEventTypes.cs index 4218aaec8f50d..4a90f83287d75 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleEventTypes.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleEventTypes.cs @@ -25,8 +25,17 @@ internal static class SimpleEventTypes { private static TraceLoggingEventTypes? instance; - public static TraceLoggingEventTypes Instance => instance ?? InitInstance(); + public static TraceLoggingEventTypes Instance + { +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")] +#endif + get { return instance ??= InitInstance(); } + } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")] +#endif private static TraceLoggingEventTypes InitInstance() { var info = TraceLoggingTypeInfo.GetInstance(typeof(T), null); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs index 76b94d9cbe68f..880c9a5941fd5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs @@ -271,6 +271,9 @@ internal sealed class NullableTypeInfo : TraceLoggingTypeInfo { private readonly TraceLoggingTypeInfo valueInfo; +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")] +#endif public NullableTypeInfo(Type type, List recursionCheck) : base(type) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/Statics.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/Statics.cs index b7ad6be87d6bf..04d6843d3dc45 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/Statics.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/Statics.cs @@ -381,6 +381,9 @@ public static bool IsGenericMatch(Type type, object? openType) return type.IsGenericType && type.GetGenericTypeDefinition() == (Type?)openType; } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")] +#endif public static TraceLoggingTypeInfo CreateDefaultTypeInfo( Type dataType, List recursionCheck) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs index 4087165e75b45..00dd8277fca5b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs @@ -17,6 +17,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Text; @@ -36,6 +37,8 @@ public partial class EventSource private byte[] ProviderMetadata => m_providerMetadata ?? Array.Empty(); #else private protected virtual ReadOnlySpan ProviderMetadata => m_providerMetadata; + private const string EventSourceRequiresUnreferenceMessage = "EventSource will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type"; + private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; #endif #endif @@ -102,6 +105,10 @@ public EventSource( /// (Native API: EventWriteTransfer) /// /// The name of the event. +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif public unsafe void Write(string? eventName) { if (!this.IsEnabled()) @@ -122,6 +129,10 @@ public unsafe void Write(string? eventName) /// Options for the event, such as the level, keywords, and opcode. Unset /// options will be set to default values. /// +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif public unsafe void Write(string? eventName, EventSourceOptions options) { if (!this.IsEnabled()) @@ -151,7 +162,12 @@ public unsafe void Write(string? eventName, EventSourceOptions options) /// public instance properties of data will be written recursively to /// create the fields of the event. /// +#if !ES_BUILD_STANDALONE + [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] + public unsafe void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>( +#else public unsafe void Write( +#endif string? eventName, T data) { @@ -187,7 +203,12 @@ public unsafe void Write( /// public instance properties of data will be written recursively to /// create the fields of the event. /// +#if !ES_BUILD_STANDALONE + [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] + public unsafe void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>( +#else public unsafe void Write( +#endif string? eventName, EventSourceOptions options, T data) @@ -225,7 +246,12 @@ public unsafe void Write( /// public instance properties of data will be written recursively to /// create the fields of the event. /// +#if !ES_BUILD_STANDALONE + [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] + public unsafe void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>( +#else public unsafe void Write( +#endif string? eventName, ref EventSourceOptions options, ref T data) @@ -270,7 +296,12 @@ public unsafe void Write( /// public instance properties of data will be written recursively to /// create the fields of the event. /// +#if !ES_BUILD_STANDALONE + [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] + public unsafe void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>( +#else public unsafe void Write( +#endif string? eventName, ref EventSourceOptions options, ref Guid activityId, diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs index feb96bf642222..c8367baf80f96 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs @@ -48,6 +48,9 @@ public class TraceLoggingEventTypes /// /// The types of the fields in the event. This value must not be null. /// +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")] +#endif internal TraceLoggingEventTypes( string name, EventTags tags, @@ -82,6 +85,9 @@ internal TraceLoggingEventTypes( { } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")] +#endif internal TraceLoggingEventTypes( string name, EventTags tags, @@ -180,6 +186,9 @@ internal NameInfo GetNameInfo(string name, EventTags tags) => this.nameInfos.TryGet(new KeyValuePair(name, tags)) ?? this.nameInfos.GetOrAdd(new NameInfo(name, tags, this.typeMetadata.Length)); +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")] +#endif private static TraceLoggingTypeInfo[] MakeArray(System.Reflection.ParameterInfo[] paramInfos) { if (paramInfos == null) @@ -197,6 +206,9 @@ private static TraceLoggingTypeInfo[] MakeArray(System.Reflection.ParameterInfo[ return result; } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")] +#endif private static TraceLoggingTypeInfo[] MakeArray(Type[] types) { if (types == null) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingTypeInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingTypeInfo.cs index 6f57f667dcc2c..8a699e243fc37 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingTypeInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingTypeInfo.cs @@ -153,6 +153,9 @@ public abstract void WriteMetadata( [ThreadStatic] // per-thread cache to avoid synchronization private static Dictionary? threadCache; +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")] +#endif public static TraceLoggingTypeInfo GetInstance(Type type, List? recursionCheck) { Dictionary cache = threadCache ??= new Dictionary(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TypeAnalysis.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TypeAnalysis.cs index 0324f31563bba..6fdbe7be20258 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TypeAnalysis.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TypeAnalysis.cs @@ -5,6 +5,7 @@ using System; #endif using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Reflection; #if ES_BUILD_STANDALONE @@ -25,6 +26,9 @@ internal sealed class TypeAnalysis internal readonly EventOpcode opcode = (EventOpcode)(-1); internal readonly EventTags tags; +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent will serialize the whole object graph. Trimmer will not safely handle this case because properties may be trimmed. This can be suppressed if the object is a primitive type")] +#endif public TypeAnalysis( Type dataType, EventDataAttribute? eventAttrib, diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.cs index 25a2cb33251b0..ae4cda4813595 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.cs @@ -20,6 +20,9 @@ public class Keywords public const EventKeywords ThreadTransferKeyword = (EventKeywords)0x80000000; } +#if !ES_BUILD_STANDALONE + private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; +#endif // This value does not seem to be used, leaving it as zero for now. It may be useful for a scenario that may involve // multiple instances of the runtime within the same process, but then it seems unlikely that both instances' thread // pools would be in moderate use. @@ -67,6 +70,10 @@ public enum ThreadAdjustmentReasonMap : uint ThreadTimedOut } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [NonEvent] private unsafe void WriteThreadEvent(int eventId, uint numExistingThreads) { @@ -123,6 +130,10 @@ public void ThreadPoolWorkerThreadWait( } } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(54, Level = EventLevel.Informational, Message = Messages.WorkerThreadAdjustmentSample, Task = Tasks.ThreadPoolWorkerThreadAdjustment, Opcode = Opcodes.Sample, Version = 0, Keywords = Keywords.ThreadingKeyword)] public unsafe void ThreadPoolWorkerThreadAdjustmentSample( double Throughput, @@ -142,6 +153,10 @@ public unsafe void ThreadPoolWorkerThreadAdjustmentSample( WriteEventCore(54, 2, data); } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(55, Level = EventLevel.Informational, Message = Messages.WorkerThreadAdjustmentAdjustment, Task = Tasks.ThreadPoolWorkerThreadAdjustment, Opcode = Opcodes.Adjustment, Version = 0, Keywords = Keywords.ThreadingKeyword)] public unsafe void ThreadPoolWorkerThreadAdjustmentAdjustment( double AverageThroughput, @@ -169,6 +184,10 @@ public unsafe void ThreadPoolWorkerThreadAdjustmentAdjustment( WriteEventCore(55, 4, data); } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(56, Level = EventLevel.Verbose, Message = Messages.WorkerThreadAdjustmentStats, Task = Tasks.ThreadPoolWorkerThreadAdjustment, Opcode = Opcodes.Stats, Version = 0, Keywords = Keywords.ThreadingKeyword)] public unsafe void ThreadPoolWorkerThreadAdjustmentStats( double Duration, @@ -224,6 +243,10 @@ public unsafe void ThreadPoolWorkerThreadAdjustmentStats( WriteEventCore(56, 11, data); } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(63, Level = EventLevel.Verbose, Message = Messages.IOEnqueue, Task = Tasks.ThreadPool, Opcode = Opcodes.IOEnqueue, Version = 0, Keywords = Keywords.ThreadingKeyword | Keywords.ThreadTransferKeyword)] private unsafe void ThreadPoolIOEnqueue( IntPtr NativeOverlapped, @@ -260,6 +283,10 @@ public void ThreadPoolIOEnqueue(RegisteredWaitHandle registeredWaitHandle) } } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(64, Level = EventLevel.Verbose, Message = Messages.IO, Task = Tasks.ThreadPool, Opcode = Opcodes.IODequeue, Version = 0, Keywords = Keywords.ThreadingKeyword | Keywords.ThreadTransferKeyword)] private unsafe void ThreadPoolIODequeue( IntPtr NativeOverlapped, @@ -291,6 +318,10 @@ public void ThreadPoolIODequeue(RegisteredWaitHandle registeredWaitHandle) } } +#if !ES_BUILD_STANDALONE + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(60, Level = EventLevel.Verbose, Message = Messages.WorkingThreadCount, Task = Tasks.ThreadPoolWorkingThreadCount, Opcode = EventOpcode.Start, Version = 0, Keywords = Keywords.ThreadingKeyword)] public unsafe void ThreadPoolWorkingThreadCount(uint Count, ushort ClrInstanceID = DefaultClrInstanceId) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs index 4d608bdbfcf5f..eea410711a367 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using System.Diagnostics.Tracing; +using System.Diagnostics.CodeAnalysis; using Internal.Runtime.CompilerServices; namespace System.Threading.Tasks @@ -21,6 +22,9 @@ namespace System.Threading.Tasks [EventSourceAutoGenerate] internal sealed partial class TplEventSource : EventSource { +#if !ES_BUILD_STANDALONE + private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; +#endif /// Used to determine if tasks should generate Activity IDs for themselves internal bool TasksSetActivityIds; // This keyword is set internal bool Debug; @@ -189,6 +193,10 @@ public enum TaskWaitBehavior : int /// The task ID /// The options used to create the task. /// The ID for the current AppDomain. +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(TASKSCHEDULED_ID, Task = Tasks.TaskScheduled, Version = 1, Opcode = EventOpcode.Send, Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer | Keywords.Tasks)] public void TaskScheduled( @@ -257,6 +265,10 @@ public void TaskStarted( /// The task ID. /// The task ID. /// Whether the task completed due to an error. +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(TASKCOMPLETED_ID, Version = 1, Level = EventLevel.Informational, Keywords = Keywords.TaskStops)] public void TaskCompleted( @@ -299,6 +311,10 @@ public void TaskCompleted( /// If known, if 'TaskID' has a 'continueWith' task, mention give its ID here. /// 0 means unknown. This allows better visualization of the common sequential chaining case. /// +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(TASKWAITBEGIN_ID, Version = 3, Task = TplEventSource.Tasks.TaskWait, Opcode = EventOpcode.Send, Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer | Keywords.Tasks)] public void TaskWaitBegin( @@ -388,6 +404,10 @@ public void TaskWaitContinuationStarted(int TaskID) /// The scheduler ID. /// The task ID. /// The ID of the continuation object. +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(AWAITTASKCONTINUATIONSCHEDULED_ID, Task = Tasks.AwaitTaskContinuationScheduled, Opcode = EventOpcode.Send, Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer | Keywords.Tasks)] public void AwaitTaskContinuationScheduled( @@ -419,6 +439,10 @@ public void AwaitTaskContinuationScheduled( } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(TRACEOPERATIONSTART_ID, Version = 1, Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalityOperation)] public void TraceOperationBegin(int TaskID, string OperationName, long RelatedContext) @@ -471,6 +495,10 @@ public void TraceSynchronousWorkBegin(int TaskID, CausalitySynchronousWork Work) WriteEvent(TRACESYNCHRONOUSWORKSTART_ID, TaskID, (int)Work); // optimized overload for this exists } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(TRACESYNCHRONOUSWORKSTOP_ID, Version = 1, Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalitySynchronousWork)] public void TraceSynchronousWorkEnd(CausalitySynchronousWork Work) @@ -514,6 +542,8 @@ public void RunningContinuationList(int TaskID, int Index, long Object) [Event(24, Keywords = Keywords.Debug)] public void DebugFacilityMessage1(string Facility, string Message, string Value1) { WriteEvent(24, Facility, Message, Value1); } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "Guid parameter is safe with WriteEvent")] [Event(25, Keywords = Keywords.DebugActivityId)] public void SetActivityId(Guid NewId) { diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs b/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs index b61b1e52590ce..9318c850a2688 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/Internal/DataflowEtwProvider.cs @@ -60,7 +60,7 @@ private DataflowEtwProvider() { } // Dataflow Events // - #region Block Creation +#region Block Creation /// Trace an event for when a new block is instantiated. /// The dataflow block that was created. /// The options with which the block was created. @@ -83,9 +83,9 @@ private void DataflowBlockCreated(string blockName, int blockId) { WriteEvent(DATAFLOWBLOCKCREATED_EVENTID, blockName, blockId); } - #endregion +#endregion - #region Task Launching +#region Task Launching /// Trace an event for a block launching a task to handle messages. /// The owner block launching a task. /// The task being launched for processing. @@ -105,6 +105,10 @@ internal void TaskLaunchedForMessageHandling( } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "WriteEvent Parameters are trimmer safe")] +#endif [Event(TASKLAUNCHED_EVENTID, Level = EventLevel.Informational)] private void TaskLaunchedForMessageHandling(int blockId, TaskLaunchedReason reason, int availableMessages, int taskId) { @@ -119,9 +123,9 @@ internal enum TaskLaunchedReason /// A task is being launched to offer outgoing messages to linked targets. OfferingOutputMessages = 2, } - #endregion +#endregion - #region Block Completion +#region Block Completion /// Trace an event for a block completing. /// The block that's completing. [NonEvent] @@ -160,14 +164,18 @@ internal enum BlockCompletionReason Canceled = (int)TaskStatus.Canceled } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "WriteEvent Parameters are trimmer safe")] +#endif [Event(BLOCKCOMPLETED_EVENTID, Level = EventLevel.Informational)] private void DataflowBlockCompleted(int blockId, BlockCompletionReason reason, string exceptionData) { WriteEvent(BLOCKCOMPLETED_EVENTID, blockId, reason, exceptionData); } - #endregion +#endregion - #region Linking +#region Linking /// Trace an event for a block linking. /// The source block linking to a target. /// The target block being linked from a source. @@ -187,9 +195,9 @@ private void DataflowBlockLinking(int sourceId, int targetId) { WriteEvent(BLOCKLINKED_EVENTID, sourceId, targetId); } - #endregion +#endregion - #region Unlinking +#region Unlinking /// Trace an event for a block unlinking. /// The source block unlinking from a target. /// The target block being unlinked from a source. @@ -210,7 +218,7 @@ private void DataflowBlockUnlinking(int sourceId, int targetId) { WriteEvent(BLOCKUNLINKED_EVENTID, sourceId, targetId); } - #endregion +#endregion } #endif } diff --git a/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj b/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj index fa21b7c249f78..0f879cda9781a 100644 --- a/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj +++ b/src/libraries/System.Threading.Tasks.Dataflow/src/System.Threading.Tasks.Dataflow.csproj @@ -64,6 +64,9 @@ + + + diff --git a/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/ParallelETWProvider.cs b/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/ParallelETWProvider.cs index 2770ba67993d8..aa5f6862da883 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/ParallelETWProvider.cs +++ b/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/ParallelETWProvider.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System.Text; using System.Security; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; namespace System.Threading.Tasks @@ -19,6 +20,9 @@ namespace System.Threading.Tasks [EventSource(Name = "System.Threading.Tasks.Parallel.EventSource")] internal sealed class ParallelEtwProvider : EventSource { +#if !ES_BUILD_STANDALONE + private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe"; +#endif /// /// Defines the singleton instance for the Task.Parallel ETW provider. /// @@ -97,6 +101,10 @@ public class Tasks /// The kind of fork/join operation. /// The lower bound of the loop. /// The upper bound of the loop. +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(PARALLELLOOPBEGIN_ID, Level = EventLevel.Informational, Task = ParallelEtwProvider.Tasks.Loop, Opcode = EventOpcode.Start)] public void ParallelLoopBegin(int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER int ForkJoinContextID, ForkJoinOperationType OperationType, // PFX_FORKJOIN_COMMON_EVENT_HEADER @@ -157,6 +165,10 @@ public void ParallelLoopBegin(int OriginatingTaskSchedulerID, int OriginatingTas /// The task ID. /// The loop ID. /// the total number of iterations processed. +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(PARALLELLOOPEND_ID, Level = EventLevel.Informational, Task = ParallelEtwProvider.Tasks.Loop, Opcode = EventOpcode.Stop)] public void ParallelLoopEnd(int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER int ForkJoinContextID, long TotalIterations) @@ -204,6 +216,10 @@ public void ParallelLoopEnd(int OriginatingTaskSchedulerID, int OriginatingTaskI /// The invoke ID. /// The kind of fork/join operation. /// The number of actions being invoked. +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = EventSourceSuppressMessage)] +#endif [Event(PARALLELINVOKEBEGIN_ID, Level = EventLevel.Informational, Task = ParallelEtwProvider.Tasks.Invoke, Opcode = EventOpcode.Start)] public void ParallelInvokeBegin(int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER int ForkJoinContextID, ForkJoinOperationType OperationType, // PFX_FORKJOIN_COMMON_EVENT_HEADER diff --git a/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs b/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs index 0837744cfb987..149839f8a5038 100644 --- a/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs +++ b/src/libraries/System.Threading/src/System/Threading/CDSsyncETWBCLProvider.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.Text; using System.Security; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; namespace System.Threading @@ -56,6 +57,10 @@ private CdsSyncEtwBCLProvider() { } // Barrier Events // +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + Justification = "Parameters to this method are primitive and are trimmer safe")] +#endif [Event(BARRIER_PHASEFINISHED_ID, Level = EventLevel.Verbose, Version = 1)] public void Barrier_PhaseFinished(bool currentSense, long phaseNum) { diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs index a22fee7dfad07..b97fb8f6a8ecb 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionsEtwProvider.cs @@ -6,6 +6,7 @@ using System.Text; using System.Threading.Tasks; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -838,6 +839,10 @@ internal void TransactionScopeCreated(TransactionTraceIdentifier transactionID, } } +#if !ES_BUILD_STANDALONE + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "TransactionScopeResult parameter is an enum and is trimmer safe")] +#endif [Event(TRANSACTIONSCOPE_CREATED_EVENTID, Keywords = Keywords.TraceBase, Level = EventLevel.Informational, Task = Tasks.TransactionScope, Opcode = Opcodes.Created, Message = "Transactionscope was created: Transaction ID is {0}, TransactionScope Result is {1}")] private void TransactionScopeCreated(string transactionID, TransactionScopeResult transactionScopeResult) { From e7eca5b3aa04ac8f74d4364db9dd7ce3eb043ff4 Mon Sep 17 00:00:00 2001 From: Santiago Fernandez Madero Date: Mon, 8 Mar 2021 16:43:07 -0800 Subject: [PATCH 40/83] Enable CheckDownloadedFiles on DownloadBuildArtifacts task (#49321) --- eng/pipelines/common/download-artifact-step.yml | 1 + eng/pipelines/coreclr/templates/crossdac-pack.yml | 1 + eng/pipelines/official/jobs/prepare-signed-artifacts.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/eng/pipelines/common/download-artifact-step.yml b/eng/pipelines/common/download-artifact-step.yml index b3f497392ed53..2470db19de70d 100644 --- a/eng/pipelines/common/download-artifact-step.yml +++ b/eng/pipelines/common/download-artifact-step.yml @@ -14,6 +14,7 @@ steps: downloadType: single downloadPath: '$(Build.SourcesDirectory)/__download__' artifactName: '${{ parameters.artifactName }}' + checkDownloadedFiles: true # Unzip artifact - task: ExtractFiles@1 diff --git a/eng/pipelines/coreclr/templates/crossdac-pack.yml b/eng/pipelines/coreclr/templates/crossdac-pack.yml index 77802a2bf40b3..40e375bb9375c 100644 --- a/eng/pipelines/coreclr/templates/crossdac-pack.yml +++ b/eng/pipelines/coreclr/templates/crossdac-pack.yml @@ -72,6 +72,7 @@ jobs: inputs: artifactName: $(buildCrossDacArtifactName) downloadPath: $(crossDacArtifactPath) + checkDownloadedFiles: true - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset crossdacpack -arch $(archType) $(osArg) -c $(buildConfig) $(officialBuildIdArg) $(crossDacArgs) -ci displayName: Build crossdac packaging diff --git a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml index 042ad8e2c7cf9..a5457d751ad03 100644 --- a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml +++ b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml @@ -43,6 +43,7 @@ jobs: inputs: artifactName: IntermediateArtifacts downloadPath: $(Build.SourcesDirectory)\artifacts\PackageDownload + checkDownloadedFiles: true - script: >- build.cmd -ci From 59a2e12edd4563e28b011ab480cca2d98adaafb8 Mon Sep 17 00:00:00 2001 From: Bruce Forstall Date: Mon, 8 Mar 2021 17:08:41 -0800 Subject: [PATCH 41/83] Re-enable windows JIT formatting jobs (#49025) Addresses https://github.com/dotnet/runtime/issues/40034 --- eng/pipelines/coreclr/ci.yml | 3 +-- eng/pipelines/runtime.yml | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/eng/pipelines/coreclr/ci.yml b/eng/pipelines/coreclr/ci.yml index a079ad7a72763..d0d461e24c326 100644 --- a/eng/pipelines/coreclr/ci.yml +++ b/eng/pipelines/coreclr/ci.yml @@ -172,5 +172,4 @@ jobs: jobTemplate: /eng/pipelines/coreclr/templates/format-job.yml platforms: - Linux_x64 - # Issue: https://github.com/dotnet/runtime/issues/40034 - #- windows_x64 + - windows_x64 diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 931da897d04d5..564cbdf04fd57 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -169,8 +169,7 @@ jobs: jobTemplate: /eng/pipelines/coreclr/templates/format-job.yml platforms: - Linux_x64 - # Issue: https://github.com/dotnet/runtime/issues/40034 - #- windows_x64 + - windows_x64 jobParameters: condition: >- and( From b93d2a220976d1a60a20b57161d1114912f1f4cd Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Mon, 8 Mar 2021 18:06:18 -0800 Subject: [PATCH 42/83] Fix null reference in pgo data merging (#49326) Profile schema data can be null, handle both cases correctly in merge algorithm --- .../aot/ILCompiler.ReadyToRun/Compiler/ProfileData.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ProfileData.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ProfileData.cs index 8dac43bd2c374..40cb6c3a68ec4 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ProfileData.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ProfileData.cs @@ -94,11 +94,15 @@ public static void MergeProfileData(ref bool partialNgen, Dictionary Date: Mon, 8 Mar 2021 19:46:36 -0800 Subject: [PATCH 43/83] [AndroidCrypto] Add certs that don't use RC2 in test data (#49312) --- .../RC2/RC2Factory.cs | 2 +- .../Security/Cryptography/PlatformSupport.cs | 4 + ...urity.Cryptography.Algorithms.Tests.csproj | 2 + ...tem.Security.Cryptography.Cng.Tests.csproj | 2 + ...tem.Security.Cryptography.Csp.Tests.csproj | 2 + ...Security.Cryptography.OpenSsl.Tests.csproj | 2 + .../Cryptography/Pal.Android/X509Pal.cs | 2 +- .../src/Resources/Strings.resx | 3 + .../tests/HostnameMatchTests.Unix.cs | 2 + ...Cryptography.X509Certificates.Tests.csproj | 2 + .../tests/TestData.cs | 551 +++++++++++++++++- 11 files changed, 564 insertions(+), 10 deletions(-) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2Factory.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2Factory.cs index ab4df33f7f915..760aff5c1fb1f 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2Factory.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2Factory.cs @@ -17,6 +17,6 @@ public static RC2 Create() return s_provider.Create(); } - public static bool IsSupported { get; } = !PlatformDetection.IsAndroid; + public static bool IsSupported { get; } = Test.Cryptography.PlatformSupport.IsRC2Supported; } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs b/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs index e23a7519905bc..b46fe55b0cafa 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/PlatformSupport.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using Xunit; namespace Test.Cryptography @@ -9,5 +10,8 @@ internal static class PlatformSupport { // Platforms that support OpenSSL - all Unix except OSX and Android internal const TestPlatforms OpenSSL = TestPlatforms.AnyUnix & ~(TestPlatforms.OSX | TestPlatforms.Android); + + // Whether or not the current platform supports RC2 + internal static readonly bool IsRC2Supported = !PlatformDetection.IsAndroid; } } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj b/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj index 2bb9d8ae82d35..d761bed32cac7 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj @@ -119,6 +119,8 @@ Link="Common\Interop\Unix\System.Security.Cryptography.Native\Interop.Initialization.cs" /> + + + + rawData) } // Throw on unknown type to match Unix and Windows - throw new CryptographicException(); + throw new CryptographicException(SR.Cryptography_UnknownCertContentType); } public X509ContentType GetCertContentType(string fileName) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx index 51329e19e03a4..6d619e428aa0b 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx @@ -445,4 +445,7 @@ The TLS key derivation function requires a seed value of exactly 64 bytes. + + The certificate content type could not be determined. + diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/HostnameMatchTests.Unix.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/HostnameMatchTests.Unix.cs index a83611cee154c..74cf7c8f18aef 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/HostnameMatchTests.Unix.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/HostnameMatchTests.Unix.cs @@ -4,10 +4,12 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; +using Test.Cryptography; using Xunit; namespace System.Security.Cryptography.X509Certificates.Tests { + [PlatformSpecific(PlatformSupport.OpenSSL)] public static class HostnameMatchTests { [Theory] diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj b/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj index 1ffcaefd56a99..e5ed696a97d1f 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj @@ -43,6 +43,8 @@ + diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs index 3d02169eccace..ad689987d3aec 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs @@ -179,7 +179,7 @@ public static SecureString CreatePfxDataPasswordSecureString() "e5a496413a6d55ea6309d0013e90657c83c6e40aa8fafeee66acbb6661c14190" + "11e1fde6f4fcc328bd7e537e4aa2dbe216d8f1f3aa7e5ec60eb9cfdca7a41d74").HexToByteArray(); - public static readonly byte[] PfxData = ( + private static readonly byte[] PfxData_RC2ContentEncryption = ( "3082063A020103308205F606092A864886F70D010701A08205E7048205E33082" + "05DF3082035806092A864886F70D010701A08203490482034530820341308203" + "3D060B2A864886F70D010C0A0102A08202B6308202B2301C060A2A864886F70D" + @@ -231,6 +231,66 @@ public static SecureString CreatePfxDataPasswordSecureString() "BC303B301F300706052B0E03021A04144DEAB829B57A3156AEBC8239C0E7E884" + "EFD96E680414E147930B932899741C92D7652268938770254A2B020207D0").HexToByteArray(); + private static readonly byte[] PfxData_TripleDESContentEncryption = ( + "308206980201033082065406092A864886F70D010701A0820645048206413082" + + "063D308203B606092A864886F70D010701A08203A7048203A33082039F308203" + + "9B060B2A864886F70D010C0A0102A08202B6308202B2301C060A2A864886F70D" + + "010C0103300E04083A55E19A8875CF7E020207D004820290C39707B6E15BC075" + + "62B296E37D44A4C3654F398528F51988932D4E78C96AC7E783A21DD306AEB4BB" + + "7490551F5CCB21DBF883B3D01D3CCFEB0148CC79C8C15AD7266BC0C0D23563FF" + + "A879DDB05ACC5B1F9A9BA5F8E32ECE05458A55DC91882750B0573315D843524D" + + "72E400C14E24B530A228B477DF60F01A1CBA22085350C72B8E871AEF219D1457" + + "3A660D71064D4226814B8D360A84FDF9B24578E61D62119C893DF1CB97C733BC" + + "D9CCA8C3FBA40B3E35F305AFCF1E24E720379FC94FB7103A27F817D98AF70D12" + + "0A357EB5840720F48AE6ED59990E80541CCA08B2B3F9FAE0F7554F491616E72B" + + "E2383478709947F5BD5AC8D2F74550A2C4260DAA789C66559DBC25D0D5657DEF" + + "FF491287E9E982C870732E6C1494F25FED513D2DF246EDABA1DEF8FE05A1C283" + + "676A0722961FBAD4B47E8D27D08E4129FACE86CAAB657A1899C7F9286DD534AC" + + "3AE6B1A100C90207B9A39857C1D9B7A061A5E8496F0E099F1323FA56DE85BF34" + + "96DBBE6FFEAAC0321F65A40BAE63503BB704553F1027700D15D12A20EC3A8FB9" + + "8D62D902FBDBD1BA9984242A6413CF243FE1C5A5A42083EA6E821D302CC4BE4D" + + "23C0D92247C027A6D5AE3D645F378916ACBD068F52A7772571F51F4AF46652E6" + + "D9821A24267F6A8CF9D69B3EF5FF33702B71CCDA87A3704DB815685F83E22C64" + + "B60D9B659EEA517BCACDD638DB2EF171692AA17176891901F2BB97F574908CCA" + + "943743C1E8D2520FE7B5E04C10E748A666EAAE81EF5DB3577F669E049BE57CCF" + + "7FFCF7583A9ABE0BC44F0D33EBE7F3BFC2F1F4012F588D0FC8CB0FFDF3BF1A43" + + "A962B0F9059FAAC0BD68B23275584180EDDE1F1703BFE977456079FF0890BFE5" + + "ED9CA93ABECF335C02DEBB7DB1A1E60B5B7746F6F152299A1DB983ACE6D9D5B9" + + "DBAF68A3DEDCCC013181D1301306092A864886F70D0109153106040401000000" + + "305B06092A864886F70D010914314E1E4C007B00430035004600430030003800" + + "350032002D0038004200410033002D0034003700460041002D00410045003400" + + "33002D004200440039003300420044003200350041004300440042007D305D06" + + "092B060104018237110131501E4E004D006900630072006F0073006F00660074" + + "0020005300740072006F006E0067002000430072007900700074006F00670072" + + "00610070006800690063002000500072006F007600690064006500723082027F" + + "06092A864886F70D010706A08202703082026C0201003082026506092A864886" + + "F70D010701301C060A2A864886F70D010C0103300E0408812EAA0D26B0151B02" + + "0207D080820238A471B31EBE90A6B540889297C09BFC73185C2C2676665DBAD2" + + "BC5759464079976B4C82DCB425289BCFABF9CD11AABF18B3CFA1879A958919E5" + + "05465E5B2DBCA5039990650F7D7490D322F2CCCD444ACE4625BE3C361FA5C096" + + "615ACDA3123A478340332961655C973D74EE64F32015194558F4B8148DED4671" + + "7EE0381E8A53B582F176DB914475FB57C2648DCC709D6153825F33F082B91EAB" + + "BB2236343CA919065B9D9112D301E6700CE8104035469EDF7874246373351E13" + + "DC1DAB74DF1DE1E076FE03869F494C0427DE55CA7C17536DEF40D0E3F1B7E5FF" + + "5A2050175624A1F2D9EF4069186424CC956B84997768E589E38D3D836592CF27" + + "881DB2EE51AB682B4F4C58ED14585C51B72CCF156BE3CD2EEC538AD15A598E84" + + "0CFCDF6CD4A151B7EA4BE5388EA903298B4D1A86E7371300A6242DD7A654E430" + + "2B4F849650230F467042CD328A4FD4B33803213C807C37F98024A718B40AD0BD" + + "3AC6279E47FBD27E50D743BC8F595B78F8805D8143EBB3119B919DFFBFAF606F" + + "A858C77C5E0526646B6AACC536A3B2FEA1E0A67CBAE166A8F85913F3600C55F7" + + "850EF48619B9E93FB15F21994BC9ABA8FF7156B68B1DAD472ED2FA3917E1F84D" + + "AD4EB34992493B7084F6490FB326697A0A52BA08BF7F537B3BDC09B421A0D47F" + + "DCB8BD0271963EC4CE4F9C21A45AC382E8AD7ED8D69824BD5C00BCEAF56D88B3" + + "F2D0D5A81CF1C14884040A8E522428154A9C752C0E64204FA849689739E5138F" + + "0F96C471C5FE026EA7EA68AA42DF0A693213ECF06555804A191637A8F7858A30" + + "3B301F300706052B0E03021A04146B4EDA4227EAFC85EDA331AC88761DD06D54" + + "60FD0414C8A2B10C67EAECB3D48BEC69616133185721613D020207D0").HexToByteArray(); + + public static readonly byte[] PfxData = + PlatformSupport.IsRC2Supported + ? PfxData_RC2ContentEncryption + : PfxData_TripleDESContentEncryption; + public static byte[] StoreSavedAsPfxData = ( "3082070406092a864886f70d010702a08206f5308206f10201013100300b0609" + "2a864886f70d010701a08206d9308201e530820152a0030201020210d5b5bc1c" + @@ -419,7 +479,7 @@ public static SecureString CreatePfxDataPasswordSecureString() "0ef9848b7f83eacbf83ffd021420e2ac47e656874633e01b0d207a99280c1127" + "01").HexToByteArray(); - public static byte[] Dsa1024Pfx = ( + private static readonly byte[] Dsa1024Pfx_RC2ContentEncryption = ( "308206EE020103308206B406092A864886F70D010701A08206A5048206A13082" + "069D3082043706092A864886F70D010706A0820428308204240201003082041D" + "06092A864886F70D010701301C060A2A864886F70D010C0106300E04084AF212" + @@ -477,6 +537,71 @@ public static SecureString CreatePfxDataPasswordSecureString() "313021300906052B0E03021A0500041466FD3518CEBBD69877BA663C9E8D7092" + "8E8A98F30408DFB5AE610308BCF802020800").HexToByteArray(); + private static readonly byte[] Dsa1024Pfx_TripleDESContentEncryption = ( + "30820736020103308206F206092A864886F70D010701A08206E3048206DF3082" + + "06DB308202AC06092A864886F70D010701A082029D0482029930820295308202" + + "91060B2A864886F70D010C0A0102A082017630820172301C060A2A864886F70D" + + "010C0103300E0408C5A45CCF58AA36E8020207D0048201505F9A735F0ECC3DB8" + + "43A79253BA3369D331D96D153D2C160C9DCDF0AF92A2AB58D64EF48634B70510" + + "7787365B69AFA79940932DCA1168EC2B035BEFEF317EAED68C34E4FE980D7296" + + "587C8E19E9D9ED87803008FE8A5D033050832FE5AB9BBBD6952E6C66D916CBA9" + + "DFEC4C01731AF8FC8D561585CC8F883578DE69E7C73F67A88229E81497556C8E" + + "F5ED1A0C5D3F523F0552EA42E8036C60B771AE8733C973A14DC2E00AA4A1E344" + + "3BBF4F7B03B164456D979B13EEBB377B67FE5E21776CEB3EF94D40D5D2FA6A18" + + "19743642C55CB1DD0C4330D8C9FB25ACA8A008E9A82F18623E3C66A704B7F0C7" + + "2FC37D71AD5ED411B75C36CB9EE2C43D98F475E4ED6D1DBAF5921E5AA074097B" + + "3878FBA0177F19CD5E55C2564053A53507AC2833CF556DDC7C20B20E057EB465" + + "E4028FED7BAC0CE76063CEC30E44F89E153E6834D8B32282978171C254008281" + + "5C06CEBF305A9FFD31820106301306092A864886F70D01091531060404010000" + + "00305B06092A864886F70D010914314E1E4C007B004100430037004500350036" + + "00340042002D0043003900310044002D0034003800330035002D004100440035" + + "0037002D003000420037003900300037003800320036004100340035007D3081" + + "9106092B06010401823711013181831E8180004D006900630072006F0073006F" + + "0066007400200045006E00680061006E00630065006400200044005300530020" + + "0061006E00640020004400690066006600690065002D00480065006C006C006D" + + "0061006E002000430072007900700074006F0067007200610070006800690063" + + "002000500072006F007600690064006500723082042706092A864886F70D0107" + + "06A0820418308204140201003082040D06092A864886F70D010701301C060A2A" + + "864886F70D010C0103300E040856D7BE7AEDC9F41A020207D0808203E06A8DE7" + + "017FF8B50B3833039A4DB904A31C34990D4EBDBD5B9D658CB00ED60A6C4B90B1" + + "BE3048A0A5B847F3554625F59A9FF61C029A58C841774A88293DAFF59647C551" + + "B10DE3FFA99ADF7FF681359DC4C49C1B65DCB76312D88AB0D324482023A523E3" + + "0D24B094CEEF4E07C8FBCD33F28B9D098155A5DB8388BECF344C4A7F52213111" + + "B678DC1DDDDA17124EB2C47ED370C0E6EAE9B0A1C8286D8545A8990623D9D973" + + "D9E6341884DE3D8DAA256D3514605BBEFDA3323C6DCFE22EEA43D3A4FC74848C" + + "AB33518CEE63D5A4BB9BA41DB0B21C105D895E1BED12BCECE7BF85A13166C01E" + + "11CB08EF41CA1B905ED4051EE398C1F256CB98435FA92811D8D2D3F02BB1AAD1" + + "1D5580CD870E21C9E1690D586446CBDBFFA00FE010327187DA78563916206042" + + "1DB4B8A10ECCC3B8B077C976367894FE1BB5A5CAC7BE00132595FA75B574FC23" + + "6DF9DCADBCE06ABA44BA7C385509C04279CFAE13B95FCE5ADBC0BBD41C492C7F" + + "D4BC2474751C48C6216EEE901545F27D03515F738A55EF6CB7B0B4E8CD04373F" + + "49487ECE6433C7535835D12C0970B73C148638FE19E95C621647B55A2986A317" + + "D518EFDE4676DEBB9D03C15611EE4F6D59EF01C3E1301080B2DCF836B01DCB68" + + "96CCA61D89D4F0CF3421198F4F3AD8175EF8CAE102DE8FD66399B11C8538F60D" + + "7E9CF57E6DEE7AC7742C7681B52517F4EE70B23D1DBD42AA33AFE02A900CA261" + + "2AF63FF59C9DE612D4880535709751A60FD567C457C76A0C325E6AB695E20154" + + "C2C3B347CFD704CFCD970B10BFC961B3E4ED39004C6C906A2EFF1DE6BAD59990" + + "F669B784E7FBF85BBD6FCB6CC74F0CE94E7D368F69EFA60B18B6702B0A540A66" + + "EB797061074C14927E597B9097161328971AD1F2A889768A94410785A4AC01D6" + + "62FB84A6A8D426EDF37E84D170FE448D9B3424276A2F807070A0B93C21E3D685" + + "045231F6CA9D7DDC183DC89F88B188BC2579BD9E4154B11CA0C4224EA8F1E92B" + + "D2DA2F02ECD4BB4FD75CC02343CAF1C73FC2009B416BF39B4652EBDB680C7B77" + + "DB226C611A823A03B7359E52D0C60347534867DB4F69815F69863F75B0556D97" + + "D6AF654A5C1D20964320D3716B40DFED2BEFA504B32910698240C517999DB2EB" + + "43F29BD5613C5872CD804DE8C60AFD164E426CC6D08E78C528651560994C61DE" + + "2A4A553B1273E3D3BA4BC9F3C29CD4FF3A5F1853FF6FE1B807035F84080A1543" + + "1F191A52BA2186923D2D0C70751AB617A89549575052A757DABD683B85685E82" + + "E86CDDC75FB3CBE8331306DFA311EBD627A21A8101D12486F7B0FEE116A980CD" + + "D595EF241061FA85C2DFB4EEF4D1C5F8A176C88D92A076FF57C371116BFE8C36" + + "819E20916A942B2B4D002FAB3EC4F9582F3A9A19C500D6028E783BFED5303B30" + + "1F300706052B0E03021A04143F1E5723BEBF22306EBF0DB2739B5E54BD5AB4C9" + + "0414F83662B2693DF36BA3583ABA17BDF6590C903841020207D0").HexToByteArray(); + + public static readonly byte[] Dsa1024Pfx = + PlatformSupport.IsRC2Supported + ? Dsa1024Pfx_RC2ContentEncryption + : Dsa1024Pfx_TripleDESContentEncryption; + // [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Unit test password.")] public const string Dsa1024PfxPassword = "1234"; @@ -586,7 +711,7 @@ public static SecureString CreatePfxDataPasswordSecureString() "AF4E2F4B9EE3FD0991EF305ADDA633C44EB5E4979751280B3F54F9CCD561AC27D" + "3426BC6FF32E8E1AAF9F7C0150A726B").HexToByteArray(); - internal static readonly byte[] MultiPrivateKeyPfx = ( + private static readonly byte[] MultiPrivateKeyPfx_RC2ContentEncryption = ( "30820F1602010330820ED606092A864886F70D010701A0820EC704820EC33082" + "0EBF308206A806092A864886F70D010701A08206990482069530820691308203" + "4C060B2A864886F70D010C0A0102A08202B6308202B2301C060A2A864886F70D" + @@ -709,6 +834,140 @@ public static SecureString CreatePfxDataPasswordSecureString() "343037301F300706052B0E03021A041454F0864331D9415EBA750C62FA93C97D" + "3402E1A40414B610EC75D16EA23BF253AAD061FAC376E1EAF684").HexToByteArray(); + private static readonly byte[] MultiPrivateKeyPfx_TripleDESContentEncryption = ( + "30820FD502010330820F9106092A864886F70D010701A0820F8204820F7E3082" + + "0F7A3082076306092A864886F70D010701A0820754048207503082074C308203" + + "A9060B2A864886F70D010C0A0102A08202B6308202B2301C060A2A864886F70D" + + "010C0103300E04081DFDCF1BC66474CA020207D0048202905D9D7D0A63C6AF2A" + + "5746A7601547EA1687B31CB19EE4858857728FF10A6D08C57B2DA97308F95E4E" + + "682DAEF4954CCAA26B41E6BF1EB28CB9FB8E7A65B5CE8F3D2A3A9022390BEC0F" + + "0197DAFB37DB8C029C31944311C96CEE14A1863830DF6A171EA39525AFB8E5E9" + + "654279F3A9575A70D9BF4DE4D8B43C57FEE8BFFEE25F4912E00FD0F4A0A910D4" + + "5B01CD3B0255D2BB720D982E94CCA5E5CF8D82A9B820FFAF34758FA455A90CC8" + + "17D1C1AD6407AC5B287C1D77FAEC59624C5604DEB0F70CB9EB61B29C3F1E46BE" + + "2C3BDB052DFA8120C2F84F98AB43E6AEC558F0C3575761159DE0A9EFE1CECDBB" + + "76D644C39A3894C77D3230C32D097EA456A0EE97696F573BEBD3833DBFF37A53" + + "83E80724E15FA0F35B32FD035A97CD2E1A2511DAA6D0A1B224250E71008C5F79" + + "75FE97EBF3F27864789ABF85BC9EC506CF5825D51FBAC8E0AEEEB9C7E9F6F7AF" + + "12284E0922CF3123864C5C627F98E2F11F69872E2DC4B838C3D8A283489ACFAB" + + "FAEDEB3432AA721343FC75800E8FA8EE58C72F5439D4191ADEE8101FB8939C18" + + "9CAF4453C46B6F2CD9E4BCD5B6DC643BEF35C1999D2AAC14E35877CF0B784BDF" + + "EE841478C7B031EDEC4B2BB50C30946B25462204059FC963464A3342C69166A2" + + "0221F46A231477A7DF73003CC546287C9B4AA80484B14DD65ECE1BB5F1AB48E3" + + "B331642455325B51E111A0F80AA89E083C29D2AC672B28C768696D7648A8DCCF" + + "DBED389CD303A8B9D6E50A6B4A46DE9D703B44759AC3826DC511F38CF914E224" + + "C6E8D63550AE8C3DD49968BED6A24AD16685CFE3028BC68BA2B28C83FF49C5B2" + + "56D70F9CF794F7DF1CD9EB24E5FB32C5337AD5B3797C6A38A612E9FF0497295E" + + "D8F4386BA8026C8EF965DA756AFC1BFEABE30B5111533D9CC1D4DC0AC3AAB6A1" + + "5B42007A6999C6CB3181DF301306092A864886F70D0109153106040401000000" + + "305B06092A864886F70D010914314E1E4C007B00300031003500350038003400" + + "350032002D0034003900350031002D0034004200380035002D00390037004300" + + "36002D003400430044004100410032004400340045004600360046007D306B06" + + "092B0601040182371101315E1E5C004D006900630072006F0073006F00660074" + + "00200045006E00680061006E006300650064002000430072007900700074006F" + + "0067007200610070006800690063002000500072006F00760069006400650072" + + "002000760031002E00303082039B060B2A864886F70D010C0A0102A08202B630" + + "8202B2301C060A2A864886F70D010C0103300E040804A1143A86597BF6020207" + + "D0048202904FE5224D130BF081597DC200F8AF9DCCFC33532DDF2A3B3B3D49E4" + + "DA4DADEF8289EC041382C56CDB204637ECCD7CBEA9B6B1DDBCE4F7EFF5464179" + + "AB975EF4DEA32C5E97ED12698F641B8BCF06F3FD91263BE4DAFB51E16236F39A" + + "822677465ADAAF363CCE47F68C3DECDE44261EFEDC7F6830551C55FD3851276C" + + "6CC03CBF67E9EC201CC3C287CDF1C6459A0E8A01B44D6FAC4128D02664501433" + + "5201E98CFDC90A4D25BE14CAF927FC01C033F2A48A3AE2A545EC8CB1E5A7929C" + + "BBFBD026642890F95EB3060576DE13D545B862BA87F25F75981ECCE9C23C2404" + + "E183B03F32CC1F3B1B6763F3A1EF6E02F25DFF0575516EC9473D718803ABD19A" + + "DE87025B458AE6C8D00FAF2C3CA8982B588E68EFF507630082A6237A2A4ABB13" + + "462CE9D30469250FC34A80CE54E93F48CC977D25845A1FE058D329FA172A456C" + + "CAB46CFDC6BE3B75BA2FE369A8F72EE502226B37E9D0D43AFB46FD4995AC960C" + + "7F3189C0BA19409B2D9ED43716BD45FC10BCB831CF972B6A9511D6C13AF205E5" + + "7729D392DC9F0FA8C2602FF50B94E095F9CBBB8C1191682C3927F4DE717096D6" + + "C04B9A3C9D7785FD048547AFC2BA9FBA3D4F590EE23FC491305D1BB24B339B71" + + "E3C217A47F3B4BDF952B7BDF2865639E8B112AEC8BA0AE4D45DBB9D8FD1661E0" + + "69139083F5C538A0081D319265BED9079CC11BABAC92456BC7770D128FA7D32C" + + "D50C69FA5253B9BEAA5EDA3F829F14122FC0936FE2A6D7CC3D8B9E140B139FF0" + + "33AEA5CF58353216602B6213A5B4E09B66FF95F56484F46A4378F4A6EE911597" + + "148FDC6230CF7BE99D4FE71298BE3CD21C7F50AF10102019BE7961B4AE3A4288" + + "429B24C62896F01914E586F508311016CD8F402F38E8D6EA82E3C8BCA7A21064" + + "B8D3DF80C1587667A45431E92C14E919A83270DE503181D1301306092A864886" + + "F70D0109153106040402000000305B06092A864886F70D010914314E1E4C007B" + + "00330037003100410033003000390037002D0034003900340045002D00340033" + + "00460036002D0038003600370044002D00310036004400310033003900310031" + + "0037004600460034007D305D06092B060104018237110131501E4E004D006900" + + "630072006F0073006F006600740020005300740072006F006E00670020004300" + + "72007900700074006F0067007200610070006800690063002000500072006F00" + + "7600690064006500723082080F06092A864886F70D010706A0820800308207FC" + + "020100308207F506092A864886F70D010701301C060A2A864886F70D010C0103" + + "300E0408DE5DDA46C47766A4020207D0808207C815E126FB76D95BC41340EC9B" + + "7C2B94D1AE77D6345E34B16530769596DE511E87E7E00590A967E4B8B6AD284B" + + "3BB3BF1E132A35018F644F5A04F307F993EAEBB8ED5AAB497602570451C404F7" + + "07EB6AA955A29363807B8C9762B9FA9D4F7720FFA941E6E7A456193E04ACB52B" + + "691F44DF2BF55D91A3A26752120DDDB61044A3FFFADE602337E5419916091B31" + + "0E2C40ED2905E32351A6C4FA77CB3D0BC802FC852986FEE41247A41ED49E2F27" + + "3516276D8A385C2332C171FB9BF9AB8EE17EF9914BCEDA9C062E3C235B165916" + + "10272829707F077577822C72ED516E8890671AD92CB266AC60B1F124E0A49EB1" + + "E65C38DC192AED49DC9E62B1435FA0AA2E25BE8455392327E5E0833CC189E47C" + + "406D11A2BC7DA9207E70F719C7E7DC636D119831AEB6740BC3397A9629505E71" + + "3623B18168BBE42179AF7C3865A7FA195EC79A4C1707B4755852A7D57E8FF797" + + "41883CE2F0D088C9F0ADB725D79C16D9FA474F540A6B9E461369D1AFF887DC1E" + + "0A000D5B9ADC6A39753CD9B9D98337417408AA6B5B3B9264D0BE7CF5B085100D" + + "81A7B22EE30036FB5A4D18DED4053C120930AD3004B118BF371A5D5288B71096" + + "6D45F41DB5CC9446AB7AE8C91D7CBB5C162793F5335F1D4EAF46045CD85C9CF5" + + "CF7CBE7797F181CE2BD1E45CF747697F91450975B3CB797A58833F91F332C75D" + + "FB17795C6C7C65EE5584B6C7A8B2C18133E2541FF145C46B823F5074CED24187" + + "CD1872F38ECF36EFBDFE090B8F1675A3D4B810DDD2A267F5F49892796E5B1335" + + "6CF71BD0DAF467C8A7A5FC9BC18E566FCD891DA69C8C0C1FFD5F534FA01EB47B" + + "166AFDD13ACE0BDE1FCC2F38F7F1371AEE2010B08F163C2310B3F922423B15F5" + + "50928EE09E9501CE887B532688FB598C1A1CD6C674587C54B4912EE8334268AC" + + "83BBFA02FB226288ACDAD2F53144076D1AE2A039834BBE8DA2DDA61FFBCA744D" + + "56591786C784159EE1D79A239472303EC73F7972819D762DD35B2BC2FB9C852B" + + "637E91149269F64CDB5243962DEDE1724D37A4D1AB9B928DA19E5BB118BBFBAC" + + "82F02A1D732A65E57C1F3E62FCE6B3D3861E6737582122CE37A99E9D44403EDE" + + "CB94AE00350758A8449641B3F0C97D630C3ABAF1A8A65ED22E847078FDA55026" + + "013B2B23F50006CC884F4818060B20D1EB572CB81D03E896EC29E358A94EC263" + + "39D58F2CFED79ABD7D50276ADAF978A463A38306420EE2C420F77B145FC0DCBF" + + "B6E324303BDD43E59466EB4FD98BB2494061A9E67DFC7CC4AA909375FAA446AD" + + "D7A95890A4969A017A02C3C84F9FF60F12F8F041E1AB3D0F1C4939134E894D0E" + + "58D9BEBF95732D7420F24E25A0DAB3FA7BC8F2016E8C78F65A50B5B86B8060CE" + + "34C36E59FF7DB623342BC20F5D99AD4FA064687B941CCFEB2B335A836DAE7320" + + "8435C4ED8C3629BC08D64C0BEEC00007D033A8E43371FEC83FCE50A87E3E4C5A" + + "5C8ABCD5AE53887A679E8A3065D820836237EA3D681AF268DB1FDE204CF2B293" + + "37D14D9B3933AEA923A454E91455109831DCEDC9ABDCA2A2970B35A9D3EAAC90" + + "9D0F39FAA9433E4857D84CC84395E4B92C48A6B207DA1FD4B0BF936BBE739106" + + "8EBF80B579C00FE3937C468B86137568FA4BD85DEF102FBF8FFCBDFF9B1BD23F" + + "A5647EF97A6F666AF3635C650382BC9186E3481D05AFFFC0B0F83CC761ADDFC1" + + "6044488A083F5CA0DD604118423F8F84BA643D146A0E801C072D6B0CC1B19D5B" + + "71E849707DA5AC8098C19377A7AA96DA53CC0DDA0650A3F200135236DA9D80A9" + + "41BF14F1C61DE7C80E2E2281EA238EBF4E0B1FEFA1AFF4C37822EF252E784F75" + + "635166E7C0D8DB07759264FA5DCE273B4D9773A42D020BA3BEBD6CA825F4E8E3" + + "E743CB88DFF6FAFABF40FF1BD8E7212687C9E283ACC9CED6C8DF1CA0C670FEE1" + + "F5621A1F1A2794043A3D3BD1B2FE2855B4C0C189A8127E4653D78D4D75F4E51B" + + "3944B167C826022A7FF46865BC816F8346BD6704CCF4CF8C87FF32EE08A06386" + + "30D7D8579593805B26E15C682D7AA9AD3C7D5A7BF8894BEA20530473F06E5D89" + + "8986BDB1FCBAE6013B10875F39980FC53CA3D7ACB3286CE194A6E04F8C62F2B2" + + "92485AD53BB9E9387563782AD618C0C94CE8514EA49A9C4456F6D6ED97920A85" + + "B835919BEEF4252159423980078ACE601F9D58399FD9824AAAFD5C6AF92BF410" + + "27C9DD077E007F0FC4D14F9324531716F6B2A54B7E8BDE6222FF68D9A9571F31" + + "45D6916ACC13F52F2CAB6421F80BA630E0EDD980E214F3D185959868858109D2" + + "613239A9891FC7F5C19A0E661F41C27D62DD502D7FDC6311824330354D9A7C76" + + "8C98562BE80213A71C3E054EBC5305915BCE59E2F4D34CF4174FD2F04C60E04E" + + "7D69896ECB6F65D7F15F22C6B7BE0ABA3A34A3C02FD79B29AE57557B00E3B19F" + + "41C9544435D4288DA02AE28B7D615596806C16D8EEC5E5C6F4AD540BEA51079E" + + "7772083FA1CE4C36DBBFAE822E56032076C1DF3831457326BC0859E2C358EDE6" + + "A465DC7662CA13A2A29607EFE230E9234DAED39C50F64D34D1902F9AE2619550" + + "8F714CBC6E6FC02DDEB716676CCF8674E04A933B255ADF36ED13C7E44857DD72" + + "68B9A0EF46DACEF7758DAE51D60A9A9E070CAD66E2B8FB67ECB31CDC0D4D3D00" + + "AE12C3679E83C2A15FBD7D008525C4C3F7172F33F70BBDA18BBAD562AB1501BE" + + "72FF0D71E1E2F65E8A6095670CCD809152F86B868A4087C1723A9EBA29044E61" + + "204980C5116FDAF83B565B09216F348ABBAD5A4867EB87CAC6E76E934B8C32DD" + + "277017226C810551C9DFFC7F2F713DE8A24BF892B07DA8651AD57CDA303B301F" + + "300706052B0E03021A0414AC44D277F1D7291B5A520398F597F6E3016174BA04" + + "140F226E1BFC1FED6205670D7C624A3A9C1C20470B020207D0").HexToByteArray(); + + internal static readonly byte[] MultiPrivateKeyPfx = + PlatformSupport.IsRC2Supported + ? MultiPrivateKeyPfx_RC2ContentEncryption + : MultiPrivateKeyPfx_TripleDESContentEncryption; + internal static readonly byte[] EmptyPfx = ( "304F020103301106092A864886F70D010701A004040230003037301F30070605" + "2B0E03021A0414822078BC83E955E314BDA908D76D4C5177CC94EB0414711018" + @@ -716,7 +975,7 @@ public static SecureString CreatePfxDataPasswordSecureString() internal const string ChainPfxPassword = "test"; - internal static readonly byte[] ChainPfxBytes = ( + private static readonly byte[] ChainPfxBytes_RC2ContentEncryption = ( "308213790201033082133506092A864886F70D010701A0821326048213223082" + "131E3082036706092A864886F70D010701A08203580482035430820350308203" + "4C060B2A864886F70D010C0A0102A08202B6308202B2301C060A2A864886F70D" + @@ -874,6 +1133,166 @@ public static SecureString CreatePfxDataPasswordSecureString() "303B301F300706052B0E03021A0414725663844329F8BF6DECA5873DDD8C96AA" + "8CA5D40414DF1D90CD18B3FBC72226B3C66EC2CB1AB351D4D2020207D0").HexToByteArray(); + private static readonly byte[] ChainPfxBytes_TripleDESContentEncryption = ( + "30821306020103308212C206092A864886F70D010701A08212B3048212AF3082" + + "12AB308203C406092A864886F70D010701A08203B5048203B1308203AD308203" + + "A9060B2A864886F70D010C0A0102A08202B6308202B2301C060A2A864886F70D" + + "010C0103300E0408B43CDBD7536FD7E2020207D0048202904EC18175B7B959AD" + + "8BF52CCEE41D754471CD84C99404E07672BA2F1BF60C59AFE7D32B64EF1EDB60" + + "326F06991D20797C598F2BD192C258C0ED726382C1B7B8A12781CA64AB72320F" + + "CAFD864D9E3CA580BA961DEF71477BA4463F8E56C9FDE471B7E0D252988256CE" + + "8780A6E843B46D9D829EF20321F8B207C1410D85E04F0CDD9CA2E7C25ED661F2" + + "820C76495A900A83D5485D0CA93E6B89D3088C727EF6A702F63C648C9271C292" + + "FCF716E755F23EB65376E1F413E12946E3A43B6AB419E5076ED523CE4DC6DF9B" + + "2C8E461A3243708764B8655AA2763A55011A558778E2A31072B33DDD4D04A86E" + + "89C416F4CFA65E6FADF390F2EE7DC8764428F85C3BB7553478A03F4807949722" + + "77077B65A799E862C7E67A4EEF0AAEC1C36ED7F1408E3B0B53DB24A76CE80966" + + "2DD472121B64740EDC3306AED1CD9E200011999B31A3EEB56F7B34880FD5918C" + + "7116607366E6C2514BAD741BBF25B10124B01F848162F405572C3781049E9AED" + + "A5294FB5AC6171E885311E7CB7001A8B83A86964B6D407096309322051ED60AF" + + "1E2D76A534D44ECC0895BF4984FA2F05625F2AF2B05B82794007705DE256914E" + + "F66AB1DD8726CE09E7950B8CE37D5138951620EEE7DF1F6957B62610BBCC53CA" + + "DE6FB33DBA5709DAC3D83E92028391132535B2C8A1B96E153FBF18D008A9F495" + + "E022B8B1DD77FE3456388D450E7026246F0246408B96F995C60930F912463E34" + + "45B6803F5BDBAC95C6CFF02893C8D57FFE091E7C520B971D24F6050D0ADA8E52" + + "F9F64D68DA38891A36AAF0231B35873CD90894393835623D6D3E898361AD17E3" + + "BC99FDBBDEF9F82763740468DE692A3FA094E1683E651DAEAD3267DBD030C930" + + "5C3A4E4AF5AB61B483BFFA4998C5F708FE4CF8D3435EA38B1512D56310ED58CD" + + "65AAADB6A64C7C623181DF301306092A864886F70D0109153106040401000000" + + "305B06092A864886F70D010914314E1E4C007B00340031003700380032003500" + + "340041002D0036003300440042002D0034003400380045002D00410030003700" + + "41002D003200320033003600420038003900450041003800350045007D306B06" + + "092B0601040182371101315E1E5C004D006900630072006F0073006F00660074" + + "00200045006E00680061006E006300650064002000430072007900700074006F" + + "0067007200610070006800690063002000500072006F00760069006400650072" + + "002000760031002E003030820EDF06092A864886F70D010706A0820ED030820E" + + "CC02010030820EC506092A864886F70D010701301C060A2A864886F70D010C01" + + "03300E040894BE093240AADB8A020207D080820E989C5F83126495753056D861" + + "A825CCB15575B04D71869B2A3685B26E535C4748F62EE23ED1C6ADC3D35DC39D" + + "0EB75C11742BBB7F36A7BA52D63EEA6F1398BBF1361EB98CC06C9EF405040888" + + "35B4063525FB2AA0715E88E62D44746404681304F38E5E2CD27BBB14571885CA" + + "DEAE50AB9F3956B3332B0C4CED90F0C8A7421532D938015861AC6EDF0F3007E7" + + "FFB9786DC56E299D5D9277BB7A29902863CD606CED8494932607AA202ECACB5F" + + "BB23AB7E824FEBED60CD76B462417ED099CAF56CE946FA5B5906341618ADA2EB" + + "3C739E332EE43ED6D16A971D2F0AF47941BABB3251250108BA6E4C0909B27808" + + "6CAA4509DFE267F9ED352330576EC22D28F11607B9805D5A82CF5A4B45C702F1" + + "A55B52D9A0E1A70543746ED457E39CAA42D66BF1EA8EE7C4DEE500E8B35849F4" + + "797583651465B5088C8F83665D05087DB9E68A5D6AFB0C489BA255A1E639E540" + + "977C53CA9F250E2C5F2B5822A7F706BD3C45DC8BCB546CB1184D7CB088701D0B" + + "53845736CCDC4BAD654108459415CC5DA8718E15E319473E5EF8107709B4EF68" + + "395E164987D467D39EAD4A049EB314F30505A072D52FB9902AF3FDC76F607D4C" + + "5068F4AD2CDB0E734E5EC18B72A44DD009EB02AB3C9531CF2BFBD6E3B40B3A4C" + + "2AE0AF8B04F6D2038102869A3952FEB7F4B82A03BC180D201FAC040785E02DA7" + + "261E1A2D74BBE95D13DA0C3F07744D2A159E4BBACB8FF4D7CC6306D0DE3E1D12" + + "6A9BDE0DFB9ED71D2C0B3827B0087D1FFBAE639AFD6EBB3C3C7138602C582F01" + + "404D997BB66EDC324CF43EB0315C13C8917EB88C318351E77CD5168EB8D05F04" + + "1F375ED6149E797497DDB6B549CDC7E24375E90746143F95474FC5A72E1B097C" + + "85C61BA7C5CCFC573B0DC308EA08BC1E21930DE314934CC4A7BBCB6C83165B1A" + + "2D7A34C94B165879FABCEA245919A9CE9681DB0FA6B4278B6E757047661C6604" + + "CB66E95BE6C5BE1F43CD6CCBC6CD9687310DB42C64E6BAE6224A219AD34E4918" + + "81007A7A69BCD4FC7077D0B469E90F4FE7FA584D8F7384C2013C94502AB0D61E" + + "24341FFC2894FBB0C807D8F9228E15DDE47E20C909B6BA802C1C3C4FF4E6FFE6" + + "7EAAC94290681A250FD681305C77FF881142C04FA1262D0B29E233AEB0DBAF7A" + + "70C8EAB8257BF553CDCCB5E3D06617410E6CABF19B24F6943597FA353D8861BE" + + "BF728864E17A54B37BE81FBF25FA5C3F5EDDADBD633274D226A6DD9BB2D427DC" + + "B283A29A691BC89BADFF80A5B852EA64521704974CDDC0599E94EF1BC259EC23" + + "3A1310F791878294DB5F8D7B2C890B6EBAE3E517EB1138D0A00AC762BD27D273" + + "2D66BDF971C8E87ED10CE4880D0460C9EFEBF58DE7C65AE59BF6FBAD9B5B32A2" + + "49DD6B9B3F9821F584004EA9DFB54C94B54B7A756D531F565A84A60747A47E6D" + + "D2A5A0F2F16BA15D4F5AD0CA110D26E629AD7CF4E6812948138FEB7DF3104AD1" + + "CFDC9F6FD6F64EB6A009D27E4D63C9A212ABF61CABEE2E290691913AE20E4966" + + "D0B8FF6E97342A6297A07A72796D7466AAA8E9336F8F7796EEB4CE624E83335C" + + "F3DC78C97A67BD868C9EE8C8CA3B756ACF93B7798DF470FAB7DE524C751631BC" + + "4040483C2C53CC691E13122C1BFDC36D83F0FEFD1DDC1ED9042613406FA476A0" + + "F97969213DE68568FA15F04F1AED1481BBDAC0BD9FDFF6FAB9C2E130024CEB6F" + + "358809FBCB94EC1454E46D2E369923D1B93F18F8B584B6CC2820E26C605C7BB1" + + "F50595DD9F0E724DB23359E9B7045DE35E46ACFE07AF27E1D111551689CC0352" + + "AD474F0159B8645408512B03E5EEDE3302513FD665666FB7D1D210F426E18E1E" + + "2B5616EBAB322A306338C784CAECA267F3592D217CE17D318A0A68A6D19CE60D" + + "90BEAC809F8F3DCEDB427B51CE604CBE814597A71311C9E650D64FA1BFECB801" + + "D8EE3C1607E02F641C31212AC6ABA56922A912A6E0C5284C547CA80A94B59C46" + + "443510EDEAB9388D422014C472394EAE7DC125C3A6C8B707AC3552EE52153B65" + + "F7FC989093721329910D4B5C92398FB13644A8C784380E82E73AF03A478C7875" + + "1A7E8E9B6E0D1ED589190ADF388C7A82BC451BAC4AD363C5B6889EED91DF2FB8" + + "A8DCC6810D188570CADDBA85BA935E272026AF23611D1FEE694E4475BF9E68E0" + + "8E8A88F2202A153259206FADAE4346D3BAEB59387715FC5D05E7D5F915184A38" + + "81609998068E7EB6A843A719A5ACD41A82364358F4B6867F6B9EA0175703A431" + + "00742F88AC0769B03071D7C3BF345C95806EC951F2B7C55AF7FE52174E37219B" + + "59309BAA09EEBA299F78E53F375D549C560E5D3F1848113A2E2C8B6CE65892C1" + + "F55E3822864E6D95E055BA5CBB0098BB922C3188E3EB56B9EAA93030B2E8587E" + + "9EF411F725D57F1A12D6F911413D91C78334963679083C308BCAD4C8DBE43116" + + "BCD5C74AA6B22FE9904329DF6E8EFF458BA7659ED9A043302009D6BBED2EC674" + + "EE661AB7789058CE56918A7F31A4827667338C7B12A958C239300FEE3D151F46" + + "D595707B76707B247BC37457DC1498818F6B56D9CABB72682F65BE500F74D00F" + + "A7B1144FD05FBAEB12DD83014F1A01367543761DA8FFF0B78072E5DCC14A561C" + + "5A08F509FEFF2DA20C5F342BC7E7C498417BF758B5DB26732DE45034FE952AC7" + + "6FDB80A526066505610E8753BC5521BB47333C2EBBD42B959010EA18FB5F8194" + + "A8BCD6FC6E5B8059F8C14DE002E3F78AC453C4E14FCA4DF09EFDBC992ABAEA34" + + "A7E6648B6E7F4B7D7676B2DFDFB780A275456ABC2E0C6409FBD017A10E08D3D7" + + "D8F37CF3C451BC73CD28C77F3BE2E1812D5FA6DBB842B60FBA1A5B718BC43A18" + + "2D9BAFC7C2899D8BCBBED51B2B252AC90EAADEFEA04E801F3AEB7766D92C70A5" + + "D4D05546F698B191B080135CE040A626F91589088E14E4AC494B2C4EB5CE6D1C" + + "0B827E412001F6C366A9FCD29C1663D4003AF2BE77733DA806787E4AC39DBE07" + + "9F13344B958A38EB6A0D7DB28F51241D1820316D33A23233766D57ADC6C7383A" + + "16FDC152C4100CFB459D37915478DE03A6BCF64CF513EB650D8390077C7EE12E" + + "0CC2EC447B1DECC5C675F0A0912FAD96727942E3F76490A319B65689D25212E6" + + "574AFE8AC6E558FA17D324E8ACAE80DA5803CC17C10BEB887F5B8783C37D1EF8" + + "4382D5DEEBCF3D2CBCD4420C1B5B304C56F60EF06A58C632CBB9435932E0C605" + + "C46291952EC08261C5847B2785E5E3FCCE6756BCE869E5E564FFA6D92F494099" + + "BCC08F2BB84ADAE91F000D134E918DE947DBB217EE5D24A42E68C1A6F14B3C37" + + "0F0E0E829FE29F91DF01B205BA209736A979D06DA905E52569D19F460CD3C9FB" + + "AC7D428554D7BE5766D246DAF927F32EEE76D88B29D24EBB8F20C0EE01661579" + + "568B20F08523893DA596F0418EF2565CFC90A2AE97860D77F43806B1493FB1B9" + + "873AF46DDCE8112CA98141AEB2A3CDCE6FB90545CDA7215CB5AFD0E1FA1CFA01" + + "9B8A95E552F7B4C174F4B5635430500DFF11851F5084233AE8D9CBB3416C7AF6" + + "128DAFA764C2032E4E6FD45C2C8ED83436CA673C7F0A1310B50A59E99A4DA328" + + "A179D29128C74B14FEACF2C6D0B0E079B7A700CD4D5D92E50CFEBB5633055C87" + + "5F57D2063CE4A5A4BDE5043F9F069C8051A5F2803D242A67F61FAAE19CB01827" + + "7132484137ED45B02FA919C399AA6F7DC4EC9D116C7A12803F8A6589AD801FD0" + + "154387C09072D48D4D9F4DD70E3319B61AE35F6B8BDF77C796C12FCFCA7D3F5B" + + "AB3C639D79AF8CA579944D2EA9F1D3F8B1E872C48384FA089EE74E044255BEA7" + + "79C79FE7826D7BAADD6CCA0B53912762CCE890A419E94B9CEC3152A46D1D1158" + + "84671CAF82DB53B3E1D23934C58AADC97E84589F2E0745DB62B757C4061416BB" + + "5DA650CAF0D687BAE96DF8521AE185B3122C13E342F7FFC985B4ADB2BE8E412E" + + "A4ABF9D39DDFAB7FACE1BC319F725F9982944F8B34B4F563BC4E138C99B7EA49" + + "05960529F79E4124B52508E7F20547FDBE7DE03692A5B249AD0E0739E34CE987" + + "9423CEEECBAFF243EA4EECAF7E7DA782306FA771AC2D4CF3EDB33255382CA410" + + "F8DA4B467012CF4322BBA86138A75D1252C1C08A5E24C8BFB57DF48C860B93A4" + + "55C6A428DEEA8EDB91272BFA03C73E80987BB94F8C0CB504552C8FB0C7A3003A" + + "62F678A4424C0B8AA1A9AAEC747786C051FCD407F1CE56A28F3ED28B2BCDADE0" + + "5724FE94FBF67EA6BA4030832D4B8DB97DEA9496CFEDC85E71AA35524DB4331E" + + "742BE36CC7EE1DB92AA57467F23AB8AA73FC23B32E5749C8A43915A8E5A1AC3D" + + "3E031CB786B4070195D88C98E0075B713BB71D77D6F9E50FB65F18B0552B1F83" + + "B4158B304014C94B266C52781521388E3469FF78E8128EB26D8FDFFF75FEF45B" + + "C0D2241851E976F3B0A75E6A9BED401095A093AEB7F6F8EFC8338F3CEC40B71B" + + "DB86433E7E0617FBB354D37ABBC4C998E8E4E3E9514C2BE06D65109772DCE808" + + "CDB9AE319F35E681B83D29E01BACFB0E02619DC8C1D390C35C87299D40D8396C" + + "0344242A963987ABAFA357634E8398C0CAFFCB5AB5F5EAF395B38CBBF87F6AB1" + + "0331837BB08FEEC14A16B22B1B8DECF5C79DB8F27D4DCE805FB15E8823E35529" + + "136BDB216A3E48EA042DF59237C65048DA7CA3E06FDE9EA8EF04124A8DBF4ED2" + + "720A4B9F99B93659B220072A4B88EC093E3E69CE964837E413A145EF08E9265A" + + "946653112C46CBA62D2425AF9A56B6F88A30802BF1174E854EEA5585AC4CAC24" + + "2A5BFDF5585659C2FF9EDFAF71594DB4A9D81188350AD5F30CBA9FED3B023ACC" + + "9424D1FBAB4FE8B1562544C90EA2599E8FAB028A244EAF3FC6FF72EE0029B277" + + "6E12786BD3783E51CF2AFC8AE484C205576F6E4EB216F7D4573D0EBCFA67BC3E" + + "999DE7390EE74F5E73B570DF80D8145DE6FE96A2D4D12D758A6B134303E7F361" + + "500377765CE0F5D3ACDB9ED3FEEC304CD10C0C19872A426A077B0D57D4CC8969" + + "81EAD835C2EAABDA8A6537E19B034638F1B57F544D8B5CAF9AB8754E45CBCCFB" + + "C1AC47A4AF3E225D96FCC828979B4A6923294E1E9F75C3F35354C9BE8C9FF95C" + + "805FF2E108FDC596965FC4837D0EC02C40F1C343B21C96110FB4AAB46A840984" + + "8AF62B81FA593FD49DA006B3B44CB16F7DAF32603742990FEE02569EEC8CC042" + + "EAEBAFC01F28DF096A3CD961D8F4975FD19CD8FE4F64D46D14A53BEFC60B3CC4" + + "8CD8DBADEDE41EFBF9DDDC5C583F0E66F577192D3B31D2254B6A6991B1BD684B" + + "6DECD4E8F232767A46BBBD83E9BA5CDE1EAA09BBEF497FAC94BE5DD435E364AA" + + "8A19E9413C47214C2D285A6B20303B301F300706052B0E03021A04147E4F196F" + + "6D0A4EF84A2C08674CDDF6899F7672A50414206C1AAAFFB1E282745C91F6BF5F" + + "0E87036AC61E020207D0").HexToByteArray(); + + public static readonly byte[] ChainPfxBytes = + PlatformSupport.IsRC2Supported + ? ChainPfxBytes_RC2ContentEncryption + : ChainPfxBytes_TripleDESContentEncryption; + internal static readonly byte[] Pkcs7ChainDerBytes = ( "30820E1606092A864886F70D010702A0820E0730820E030201013100300B0609" + "2A864886F70D010701A0820DEB3082050B30820474A003020102020A15EAA83A" + @@ -1548,7 +1967,7 @@ public static SecureString CreatePfxDataPasswordSecureString() "3B9DA2719A9588376E334811021C1AAC3CA829DA79CE223FA83283E6F0A5A59D" + "2399E140D957C1C9DDAF").HexToByteArray(); - internal static readonly byte[] ECDsaP256_DigitalSignature_Pfx_Windows = ( + private static readonly byte[] ECDsaP256_DigitalSignature_Pfx_Windows_RC2ContentEncryption = ( "308204470201033082040306092A864886F70D010701A08203F4048203F03082" + "03EC3082016D06092A864886F70D010701A082015E0482015A30820156308201" + "52060B2A864886F70D010C0A0102A081CC3081C9301C060A2A864886F70D010C" + @@ -1585,8 +2004,49 @@ public static SecureString CreatePfxDataPasswordSecureString() "ED140F5CA3CB92BEFCA32C690804576ABF0414B59D4FECA9944D40EEFDE7FB96" + "196D167B0FA511020207D0").HexToByteArray(); - // The PFX in ECDsaP256_DigitalSignature_Pfx_Windows washed through OpenSSL - internal static readonly byte[] ECDsaP256_DigitalSignature_Pfx_OpenSsl = ( + private static readonly byte[] ECDsaP256_DigitalSignature_Pfx_Windows_TripleDESContentEncryption = ( + "3082041D020103308203D906092A864886F70D010701A08203CA048203C63082" + + "03C2308201CB06092A864886F70D010701A08201BC048201B8308201B4308201" + + "B0060B2A864886F70D010C0A0102A081CC3081C9301C060A2A864886F70D010C" + + "0103300E04081DE327FA4C98D20D020207D00481A873FF8BEF537D3D09147413" + + "9C8DE1AE756D8932D5724A2CA5BA03060FB6FD8A62EBC0074958924ABEEFE40F" + + "A9F990DC9F554F1F4A1796CEF9267804B5D810974186136D40A864B124395321" + + "8A28EF057EB581403D4BEB59D78CFE7A3E0BB447FB84C3A430346720E9D420AA" + + "5CF510047B37FC605C1C9ACDCDCD29BDAE4A322FAB6DED4CF88DDCDD2415BC68" + + "5D755B2F7C4FAC7CB8432103748E946E8FB57A799A227E82834063AF1B3181D1" + + "301306092A864886F70D0109153106040401000000305B06092A864886F70D01" + + "0914314E1E4C007B00450039004100350045003100300044002D004200370035" + + "0032002D0034003700390034002D0039003800370031002D0037004100440046" + + "00450037004500460044003200350033007D305D06092B060104018237110131" + + "501E4E004D006900630072006F0073006F0066007400200053006F0066007400" + + "770061007200650020004B00650079002000530074006F007200610067006500" + + "2000500072006F00760069006400650072308201EF06092A864886F70D010706" + + "A08201E0308201DC020100308201D506092A864886F70D010701301C060A2A86" + + "4886F70D010C0103300E040864425808A9BD6600020207D0808201A855AC3396" + + "F8C4B26F71605DF7D89868094B973AA2FC3F94CBF0CD876EC8DA9D828BE05496" + + "5B90C91D8997A0B69908994F07E75BE4BB0CA9257BFC2C26EA3788BD85CEBBAF" + + "BFAB13EBCD1389DEE25666C76228D0845BDC3D03F4D1AED8BD6D10D2753AED6C" + + "BFF979E5B11F646EB26554324C7CD4BFDB0D9406EAB9BB177DDD2BEF5DDFF25D" + + "34A2256CF1444128B28DDD9758FEEC747E8BD453D69B6DD63FA3AFA65853D0B3" + + "D0C93BF95F9F6C4F8A92E3C6A5850BC3DC27C10F3596F73FE7EEDA3FF81C4493" + + "CD6D8564D5D3148AFC60029115ABFC4623A2662237F1FA4CF7E9E9FD26E18CD7" + + "1C6FA3D4020110E6CE1C62A9CB1ADF23AE8DEA8265C6A50325FB37F05F9AA408" + + "ED019F2A253ECAA24737511B8298BE651A97AE0BF67155FCFDDC8CF4700A8D81" + + "FDB27FD8162BCA60F25F265A3007A651F4DAE2539B4879689C594FB2FFCC5F70" + + "77DBD31E90844B7BB383BF6D71905988102A615096A8B056F405A87B15FCFC71" + + "F8EC9BDB83465D8DEC2A45ED973A06C7F155E2144FDD3F51A2F0D181684D8D5E" + + "0203C7DC33F2A27371496026FD49E83B67D1C16553440B56F215421863A14EA1" + + "98B1777F303B301F300706052B0E03021A041463C16FE8BB5114509BA9D023CB" + + "383E5DCE6904080414A1E1FBAD8DD3BDE73063DC6828C83C4B247E8F41020207" + + "D0").HexToByteArray(); + + internal static readonly byte[] ECDsaP256_DigitalSignature_Pfx_Windows = + PlatformSupport.IsRC2Supported + ? ECDsaP256_DigitalSignature_Pfx_Windows_RC2ContentEncryption + : ECDsaP256_DigitalSignature_Pfx_Windows_TripleDESContentEncryption; + + // The PFX in ECDsaP256_DigitalSignature_Pfx_Windows_RC2ContentEncryption washed through OpenSSL + private static readonly byte[] ECDsaP256_DigitalSignature_Pfx_OpenSsl_RC2ContentEncryption = ( "308203BE0201033082038406092A864886F70D010701A0820375048203713082" + "036D308201FF06092A864886F70D010706A08201F0308201EC020100308201E5" + "06092A864886F70D010701301C060A2A864886F70D010C0106300E040888F579" + @@ -1619,6 +2079,41 @@ public static SecureString CreatePfxDataPasswordSecureString() "96C2244022AB2B809E0F97270F7F4EA7769DD26F04084C0E2946D65F8F220202" + "0800").HexToByteArray(); + // The PFX in ECDsaP256_DigitalSignature_Pfx_Windows_TripleDESContentEncryption washed through OpenSSL + private static readonly byte[] ECDsaP256_DigitalSignature_Pfx_OpenSsl_TripleDESContentEncryption = ( + "308203530201033082030F06092A864886F70D010701A0820300048202FC3082" + + "02F83081FA06092A864886F70D010701A081EC0481E93081E63081E3060B2A86" + + "4886F70D010C0A0102A081BC3081B93024060A2A864886F70D010C0103301604" + + "108460E312803BC7452A54A463A320AA10020207D0048190246FA090D57DD7DE" + + "35F4EBFBE6FC75852637125874D59B7BDD61AAA617C7AC7F72CB08621A875061" + + "A0E1D362F4E2571F67BA5970264C79FD3D49CB12986E92E016326B710D7EC853" + + "70266F357DC6CA76E4878A29B93D90CA8C65D632A71ED9E5AEA78D48EE135DCA" + + "A68EAA5D229522873483523CB61F4644EA9DA46DBAA5D98B63EA494CF006B748" + + "7F1BC1CB11473AF63115301306092A864886F70D010915310604040000000030" + + "8201F706092A864886F70D010706A08201E8308201E4020100308201DD06092A" + + "864886F70D0107013024060A2A864886F70D010C010330160410C73C2C250B71" + + "DBDD1775F6E0DB924D64020207D0808201A81FF585B0354DFA72B861025E8114" + + "D5329CD4BEA43DAC69FB5B8D46372731184C9F96D56C53FA9A7201ACD1F56397" + + "0344B4656F5F90A3267F29C8D233D9544FD3596931F223908EEB33343565D11D" + + "296A5C32372C10FA71218D199C461A5B9011A996A02308C572F914599AA0D138" + + "F162B8AD7DCB67BCAC82FD858944426F657907310F63095868C05CED94243858" + + "95F2707B36D82C919AC40AC0DC0026D9159ECDB9CD48F71BAD82B234B0A2A631" + + "4DEE0221DE6DE4D27EF0FE654633AE90DAF86FF661FB0DA5C262FC5B38DE26C6" + + "5971057A22C081C5D95A25EAB12C655008254F7AC0B35BD1974BCF9EE78A4172" + + "879FFE771022F98F2BD67732BF0D318CD774BC3D89D7861C0D42AC24D0323F04" + + "7AAE0D64277FE037D8B12BCE2C51F1739CD39CBDB1AABD86374F213B1602DF6D" + + "F3A0AEFE14456FD1703D7DC90E111204FCAF1FBCBD94CACA097FF1B258CC0C23" + + "E4CD3BBFB66988A17279D048D8D344888C395F6F52D303FBEFF032985511E795" + + "3C345EE9B3B9043280A3CB1ABFF9127DD4431E8E88A8CCCF753BF822B0BBD9A9" + + "4B5C5C547D8B535B455F647180409C50F8379B46A6A96C5A9A96303B301F3007" + + "06052B0E03021A0414D38DEF52C1BA0A1BA96F04916183C4CAE0F9D8490414C2" + + "B3F3C6F9C1C07BA92E77D8016E51A7D38C04FF020207D0").HexToByteArray(); + + internal static readonly byte[] ECDsaP256_DigitalSignature_Pfx_OpenSsl = + PlatformSupport.IsRC2Supported + ? ECDsaP256_DigitalSignature_Pfx_OpenSsl_RC2ContentEncryption + : ECDsaP256_DigitalSignature_Pfx_OpenSsl_TripleDESContentEncryption; + internal static readonly byte[] EcDhP256_KeyAgree_Pfx_OpenSsl = ( "308203420201033082030806092a864886f70d010701a08202f9048202f53082" + "02f1308201e706092a864886f70d010706a08201d8308201d4020100308201cd" + @@ -1648,7 +2143,7 @@ public static SecureString CreatePfxDataPasswordSecureString() "05000414d82cbf4010f6e9e061f5837b6dff6a4f9cbcef0504087dacc651dd12" + "f86202020800").HexToByteArray(); - internal static readonly byte[] EcDhP256_KeyAgree_Pfx_Windows = ( + private static readonly byte[] EcDhP256_KeyAgree_Pfx_Windows_RC2ContentEncryption = ( "30820405020103308203c106092a864886f70d010701a08203b2048203ae" + "308203aa308201cb06092a864886f70d010701a08201bc048201b8308201" + "b4308201b0060b2a864886f70d010c0a0102a081cc3081c9301c060a2a86" + @@ -1685,6 +2180,46 @@ public static SecureString CreatePfxDataPasswordSecureString() "a7c08bafd5f9b98e28918201f4e2fc43fa0414fcb0ee0d7e9f504e754223" + "b786ccc551a220ba26020207d0").HexToByteArray(); + private static readonly byte[] EcDhP256_KeyAgree_Pfx_Windows_TripleDESContentEncryption = ( + "30820405020103308203C106092A864886F70D010701A08203B2048203AE3082" + + "03AA308201CB06092A864886F70D010701A08201BC048201B8308201B4308201" + + "B0060B2A864886F70D010C0A0102A081CC3081C9301C060A2A864886F70D010C" + + "0103300E040848F7290AA46B2312020207D00481A8A86B9A112AA5CCA4841E58" + + "5179D13261F3458710DD49D60F7EE45C3E80B9FEB74DEB88069A123E115F1782" + + "F100E2E871411334C3BB7288891F5ADAE79E99AC3A0A9C57A8267A0F4639C622" + + "8DB26A64E0C6AC6071ED39C9419024E2A53100416C95F00FAFBF0435EFFEFE44" + + "7940C9556D6A25807195C0F3B62B694A418D4C2010B2DD9C5D1F237B48F72809" + + "B7D99FE7E698DD8AF99FEE5B674D83962713AB882F1864C5D432EBAC033181D1" + + "301306092A864886F70D0109153106040401000000305B06092A864886F70D01" + + "0914314E1E4C007B00300039004400310043004400360038002D003200350030" + + "0045002D0034004100340041002D0038003100420046002D0035004100390043" + + "00410032003900420035004300380036007D305D06092B060104018237110131" + + "501E4E004D006900630072006F0073006F0066007400200053006F0066007400" + + "770061007200650020004B00650079002000530074006F007200610067006500" + + "2000500072006F00760069006400650072308201D706092A864886F70D010706" + + "A08201C8308201C4020100308201BD06092A864886F70D010701301C060A2A86" + + "4886F70D010C0103300E04087C40341C9DF40C5D020207D080820190644D3F66" + + "DAC98F21BB3D0E20BEFC7847CCF6DFAA5272D13B9930027705DA8CEC12FDAD28" + + "A184506A1DEC64C78442A0D4E320A32BF7A6F6C6C7F5A0C27FEF78D45C770978" + + "3DAF447B845E60935002F46C9B78A85ADDFB25D776017BCBBE839404F43E63E2" + + "25427874DE824EAA8FC87172D83B74C5676B5FFCCC4CCE7AECAD272167166A7D" + + "B72793E41635234E3B3D2D25A72F59C8580C73E0FF08370146FC208FE3C7DA97" + + "34527EAB978CD8B6F6EB758E7B0A066889E7A7CCDAC45AC271C90D673860C164" + + "5975B5755EBD94203F9F0F2E1F79F3089A43FA6BEF8F0B4FFF8A0946C31550CD" + + "9E00B0C0D8A11FC527CA819EA8B5109B8374C0C258AC6C0979B4090B225F6743" + + "5CA7729BFAD1ED500C63CE9B0041462217FAE93DFF6248E7F43E0E4AC6912750" + + "6B41CE1AAACD541ED7D41ABE738132D10BE54A16707B70C554A1D011BAC2AF76" + + "FD3012EFBDDC820D8DB6801BB53742AD7A0CF3240B42CABA6EAF0BE79CF13DBD" + + "DFD06156C4FDFDFD5C408F9ECCF0F154E563438533603C0A9A531C98F0894721" + + "B0FC90D1A0FCA39A80C4BFF8303B301F300706052B0E03021A041469ED25801A" + + "54E840547E4DD26ABDBBE7FBE329320414B77DAD6004C21BEF736BC9AC28CE55" + + "C61FF7C3D0020207D0").HexToByteArray(); + + public static readonly byte[] EcDhP256_KeyAgree_Pfx_Windows = + PlatformSupport.IsRC2Supported + ? EcDhP256_KeyAgree_Pfx_Windows_RC2ContentEncryption + : EcDhP256_KeyAgree_Pfx_Windows_TripleDESContentEncryption; + internal struct ECDsaCngKeyValues { public byte[] QX; From c990d593b58e0793acbedc09d79927d42a812ed0 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Mon, 8 Mar 2021 19:46:53 -0800 Subject: [PATCH 44/83] Move test_fx_ver under test folder (#49313) --- src/native/corehost/CMakeLists.txt | 1 - src/native/corehost/test/CMakeLists.txt | 1 + .../corehost/test/fx_ver/CMakeLists.txt | 18 +++++++++ .../fx_ver}/test_fx_ver.cpp | 0 .../corehost/test_fx_ver/CMakeLists.txt | 38 ------------------- 5 files changed, 19 insertions(+), 39 deletions(-) create mode 100644 src/native/corehost/test/fx_ver/CMakeLists.txt rename src/native/corehost/{test_fx_ver => test/fx_ver}/test_fx_ver.cpp (100%) delete mode 100644 src/native/corehost/test_fx_ver/CMakeLists.txt diff --git a/src/native/corehost/CMakeLists.txt b/src/native/corehost/CMakeLists.txt index 548936120d14f..3ce1d78bec72c 100644 --- a/src/native/corehost/CMakeLists.txt +++ b/src/native/corehost/CMakeLists.txt @@ -31,7 +31,6 @@ if (NOT RUNTIME_FLAVOR STREQUAL Mono) add_subdirectory(apphost) add_subdirectory(dotnet) add_subdirectory(nethost) - add_subdirectory(test_fx_ver) add_subdirectory(test) if(CLR_CMAKE_TARGET_WIN32) diff --git a/src/native/corehost/test/CMakeLists.txt b/src/native/corehost/test/CMakeLists.txt index 7f56fad3693da..72ba29f816925 100644 --- a/src/native/corehost/test/CMakeLists.txt +++ b/src/native/corehost/test/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(fx_ver) add_subdirectory(mockcoreclr) add_subdirectory(mockhostfxr) add_subdirectory(mockhostpolicy) diff --git a/src/native/corehost/test/fx_ver/CMakeLists.txt b/src/native/corehost/test/fx_ver/CMakeLists.txt new file mode 100644 index 0000000000000..e2849e9dddce5 --- /dev/null +++ b/src/native/corehost/test/fx_ver/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (c) .NET Foundation and contributors. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. + +project(test_fx_ver) + +set(DOTNET_PROJECT_NAME "test_fx_ver") + +include_directories(../../fxr) + +set(SOURCES + test_fx_ver.cpp +) + +include(${CMAKE_CURRENT_LIST_DIR}/../../hostmisc/hostmisc.cmake) + +include(../testexe.cmake) + +target_link_libraries(${DOTNET_PROJECT_NAME} libhostcommon) diff --git a/src/native/corehost/test_fx_ver/test_fx_ver.cpp b/src/native/corehost/test/fx_ver/test_fx_ver.cpp similarity index 100% rename from src/native/corehost/test_fx_ver/test_fx_ver.cpp rename to src/native/corehost/test/fx_ver/test_fx_ver.cpp diff --git a/src/native/corehost/test_fx_ver/CMakeLists.txt b/src/native/corehost/test_fx_ver/CMakeLists.txt deleted file mode 100644 index d68eea66656fe..0000000000000 --- a/src/native/corehost/test_fx_ver/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) .NET Foundation and contributors. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. - -project(test_fx_ver) - -set(EXE_NAME "test_fx_ver") - -include_directories(../../) -include_directories(../) -include_directories(../fxr) -include_directories(../hostmisc) - -set(SOURCES - test_fx_ver.cpp -) - -include(${CMAKE_CURRENT_LIST_DIR}/../hostmisc/hostmisc.cmake) - -if(CLR_CMAKE_HOST_WIN32) - add_compile_options($<$:/MT>) - add_compile_options($<$:/MT>) - add_compile_options($<$:/MTd>) -else() - add_compile_options(-fvisibility=hidden) -endif() - -add_executable(${EXE_NAME} ${SOURCES}) -target_link_libraries(${EXE_NAME} libhostcommon) - -install(TARGETS ${EXE_NAME} DESTINATION corehost_test) - -if(CLR_CMAKE_TARGET_LINUX) - target_link_libraries (${EXE_NAME} "dl") -endif() - -if(CLR_CMAKE_TARGET_LINUX AND CLR_CMAKE_TARGET_ARCH_ARM) - target_link_libraries (${EXE_NAME} "atomic") -endif() From 3eca9e12b54518f84910fb25a89573e97cafffb4 Mon Sep 17 00:00:00 2001 From: Bruce Forstall Date: Mon, 8 Mar 2021 21:51:14 -0800 Subject: [PATCH 45/83] Remove no longer needed `usenmakemakefiles` option (#49327) After https://github.com/dotnet/jitutils/pull/318, we no longer need this option. --- src/coreclr/build-runtime.cmd | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreclr/build-runtime.cmd b/src/coreclr/build-runtime.cmd index 61e3793dd4efd..7373015d11150 100644 --- a/src/coreclr/build-runtime.cmd +++ b/src/coreclr/build-runtime.cmd @@ -181,8 +181,6 @@ if /i "%1" == "skipnative" (set __BuildNative=0&set processedArgs=!proc if /i "%1" == "skipcrossarchnative" (set __SkipCrossArchNative=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "skipgenerateversion" (set __SkipGenerateVersion=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "skiprestoreoptdata" (set __RestoreOptData=0&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) -REM Keep around usenmakemakefiles for usage by the jit-format tool -if /i "%1" == "usenmakemakefiles" (set __Ninja=1&set __BuildNative=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "pgoinstrument" (set __PgoInstrument=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "nopgooptimize" (set __PgoOptimize=0&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "enforcepgo" (set __EnforcePgo=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) From 3e21dfcc41407fb34e9e2ea9ba7630d519a2c36b Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 8 Mar 2021 23:29:15 -0800 Subject: [PATCH 46/83] Fix EC key file import tests (#49253) * Fix cofactor import and disable tests that require the ability to derive a new public key from a private key + curve + generator, order, and cofactor. * Add missing member. * Disable more tests against CanDeriveNewPublicKey. * Use isSupported instead of ConditionalFact. * Fix net47 build. --- .../EC/ECKeyFileTests.LimitedPrivate.cs | 27 ++++++++++--------- .../EC/ECKeyFileTests.cs | 2 ++ .../ECDiffieHellman/ECDiffieHellmanFactory.cs | 3 +++ .../ECDiffieHellmanTests.ImportExport.cs | 5 +++- .../ECDsa/ECDsaImportExport.cs | 5 +++- .../pal_ecc_import_export.c | 2 +- .../DefaultECDiffieHellmanProvider.Android.cs | 13 ++------- .../DefaultECDiffieHellmanProvider.Unix.cs | 2 ++ .../DefaultECDiffieHellmanProvider.Windows.cs | 2 ++ .../tests/ECDiffieHellmanCngProvider.cs | 2 ++ ...tem.Security.Cryptography.Cng.Tests.csproj | 6 ++--- .../tests/EcDiffieHellmanOpenSslProvider.cs | 2 ++ 12 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.LimitedPrivate.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.LimitedPrivate.cs index ee8355669526a..5b6b786fcab77 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.LimitedPrivate.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.LimitedPrivate.cs @@ -47,7 +47,7 @@ public void ReadWriteNistP521Pkcs8_LimitedPrivate() f9ZNiwTM6lfv1ZYeaPM/q0NUUWbKZVPNOP9xPRKJxpi9fQhrVeAbW9XtJ+NjA3ax FmY="; - ReadWriteBase64Pkcs8(base64, EccTestData.GetNistP521Key2()); + ReadWriteBase64Pkcs8(base64, EccTestData.GetNistP521Key2(), CanDeriveNewPublicKey); } [Fact] @@ -67,7 +67,8 @@ public void ReadNistP521EncryptedPkcs8_Pbes2_Aes128_LimitedPrivateKey() PbeEncryptionAlgorithm.TripleDes3KeyPkcs12, HashAlgorithmName.SHA1, 12321), - EccTestData.GetNistP521Key2()); + EccTestData.GetNistP521Key2(), + CanDeriveNewPublicKey); } [Fact] @@ -87,7 +88,8 @@ public void ReadNistP521EncryptedPkcs8_Pbes2_Aes128_LimitedPrivateKey_PasswordBy PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA1, 12321), - EccTestData.GetNistP521Key2()); + EccTestData.GetNistP521Key2(), + CanDeriveNewPublicKey); } [Fact] @@ -99,7 +101,8 @@ public void ReadWriteNistP256ECPrivateKey_LimitedPrivateKey() ReadWriteBase64ECPrivateKey( base64, - EccTestData.GetNistP256ReferenceKey()); + EccTestData.GetNistP256ReferenceKey(), + CanDeriveNewPublicKey); } [Fact] @@ -115,7 +118,7 @@ public void ReadWriteNistP256ExplicitECPrivateKey_LimitedPrivate() K84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8 YyVRAgEB", EccTestData.GetNistP256ReferenceKeyExplicit(), - SupportsExplicitCurves); + SupportsExplicitCurves && CanDeriveNewPublicKey); } [Fact] @@ -154,7 +157,7 @@ public void ReadWriteNistP256ExplicitEncryptedPkcs8_LimitedPrivate() HashAlgorithmName.SHA256, 1234), EccTestData.GetNistP256ReferenceKeyExplicit(), - SupportsExplicitCurves); + SupportsExplicitCurves && CanDeriveNewPublicKey); } [Fact] @@ -163,7 +166,7 @@ public void ReadWriteBrainpoolKey1ECPrivateKey_LimitedPrivate() ReadWriteBase64ECPrivateKey( "MCYCAQEEFMXZRFR94RXbJYjcb966O0c+nE2WoAsGCSskAwMCCAEBAQ==", EccTestData.BrainpoolP160r1Key1, - SupportsBrainpool); + SupportsBrainpool && CanDeriveNewPublicKey); } [Fact] @@ -201,7 +204,7 @@ public void ReadWriteSect163k1Key1ECPrivateKey_LimitedPrivate() ReadWriteBase64ECPrivateKey( "MCMCAQEEFQPBmVrfrowFGNwT3+YwS7AQF+akEqAHBgUrgQQAAQ==", EccTestData.Sect163k1Key1, - SupportsSect163k1); + SupportsSect163k1 && CanDeriveNewPublicKey); } [Fact] @@ -226,7 +229,7 @@ public void ReadWriteSect163k1Key1ExplicitECPrivateKey_LimitedPrivate() XlyU7ugCiQcPsF04/1gyHy6ABTbVOMzao9kCFQQAAAAAAAAAAAACAQii4MwNmfil 7wIBAg==", EccTestData.Sect163k1Key1Explicit, - SupportsSect163k1); + SupportsSect163k1 && CanDeriveNewPublicKey); } [Fact] @@ -290,7 +293,7 @@ public void ReadWriteSect283k1Key1ECPrivateKey_LimitedPrivate() MDICAQEEJAC08a4ef9zUsOggU8CKkIhSsmIx5sAWcPzGw+osXT/tQO3wN6AHBgUr gQQAEA==", EccTestData.Sect283k1Key1, - SupportsSect283k1); + SupportsSect283k1 && CanDeriveNewPublicKey); } [Fact] @@ -304,7 +307,7 @@ public void ReadWriteC2pnb163v1ExplicitECPrivateKey_LimitedPrivate() VhUXVAQrBAevaZiVRhA9eTKfzD10iA8zu+gDywHsIyEbWWat6h0/h/fqWEiu8LfK nwIVBAAAAAAAAAAAAAHmD8iCHMdNrq/BAgEC", EccTestData.C2pnb163v1Key1Explicit, - SupportsC2pnb163v1); + SupportsC2pnb163v1 && CanDeriveNewPublicKey); } [Fact] @@ -377,7 +380,7 @@ public void ReadWriteC2pnb163v1ECPrivateKey_LimitedPrivate() ReadWriteBase64ECPrivateKey( "MCYCAQEEFQD00koUBxIvRFlnvh2TwAk6ZTZ5hqAKBggqhkjOPQMAAQ==", EccTestData.C2pnb163v1Key1, - SupportsC2pnb163v1); + SupportsC2pnb163v1 && CanDeriveNewPublicKey); } [Fact] diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.cs index 3dc77cd88673b..6d64fd3cc3c45 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.cs @@ -30,6 +30,8 @@ public abstract partial class ECKeyFileTests where T : AsymmetricAlgorithm // allowed explicit in ECDH or ECDSA but not the other. public static bool SupportsExplicitCurves { get; } = EcDiffieHellman.Tests.ECDiffieHellmanFactory.ExplicitCurvesSupported; + public static bool CanDeriveNewPublicKey { get; } = EcDiffieHellman.Tests.ECDiffieHellmanFactory.CanDeriveNewPublicKey; + private static bool IsCurveSupported(Oid oid) { return EcDiffieHellman.Tests.ECDiffieHellmanFactory.IsCurveValid(oid); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs index f9b19c388fb78..aec1b09fc8e82 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanFactory.cs @@ -12,6 +12,7 @@ public interface IECDiffieHellmanProvider #endif bool IsCurveValid(Oid oid); bool ExplicitCurvesSupported { get; } + bool CanDeriveNewPublicKey { get; } } public static partial class ECDiffieHellmanFactory @@ -39,5 +40,7 @@ public static bool IsCurveValid(Oid oid) } public static bool ExplicitCurvesSupported => s_provider.ExplicitCurvesSupported; + + public static bool CanDeriveNewPublicKey => s_provider.CanDeriveNewPublicKey; } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs index 8bf26097f5921..01674560c7028 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs @@ -14,6 +14,9 @@ public partial class ECDiffieHellmanTests // probe for this capability before depending on it. internal static bool ECDsa224Available => ECDiffieHellmanFactory.IsCurveValid(new Oid(ECDSA_P224_OID_VALUE)); + + internal static bool CanDeriveNewPublicKey { get; } + = EcDiffieHellman.Tests.ECDiffieHellmanFactory.CanDeriveNewPublicKey; [Theory, MemberData(nameof(TestCurvesFull))] public static void TestNamedCurves(CurveDef curveDef) @@ -385,7 +388,7 @@ public static void ExportIncludingPrivateOnPublicOnlyKey() } } - [Fact] + [ConditionalFact(nameof(CanDeriveNewPublicKey))] public static void ImportFromPrivateOnlyKey() { byte[] expectedX = "00d45615ed5d37fde699610a62cd43ba76bedd8f85ed31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9f4671105309ec9b6879d0551d930dac8ba45d255".HexToByteArray(); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs index d6bc25635063a..89144c6fc46d4 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs @@ -10,6 +10,9 @@ namespace System.Security.Cryptography.EcDsa.Tests [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)] public class ECDsaImportExportTests : ECDsaTestsBase { + internal static bool CanDeriveNewPublicKey { get; } + = EcDiffieHellman.Tests.ECDiffieHellmanFactory.CanDeriveNewPublicKey; + #if NETCOREAPP [Fact] public static void DiminishedCoordsRoundtrip() @@ -320,7 +323,7 @@ public static void ExportIncludingPrivateOnPublicOnlyKey() } } - [Fact] + [ConditionalFact(nameof(CanDeriveNewPublicKey))] public static void ImportFromPrivateOnlyKey() { byte[] expectedX = "00d45615ed5d37fde699610a62cd43ba76bedd8f85ed31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9f4671105309ec9b6879d0551d930dac8ba45d255".HexToByteArray(); diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ecc_import_export.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ecc_import_export.c index 20d97c3a7d32a..6bce31af2df42 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ecc_import_export.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ecc_import_export.c @@ -520,7 +520,7 @@ EC_KEY* AndroidCryptoNative_EcKeyCreateByExplicitParameters(ECCurveType curveTyp goto error; } - loc[paramSpec] = (*env)->NewObject(env, g_ECParameterSpecClass, g_ECParameterSpecCtor, loc[group], loc[G], bn[ORDER], bn[COFACTOR]); + loc[paramSpec] = (*env)->NewObject(env, g_ECParameterSpecClass, g_ECParameterSpecCtor, loc[group], loc[G], bn[ORDER], cofactorInt); if ((qx && qy) || d) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Android.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Android.cs index 033d4d45d3a7f..63ec79d8baeec 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Android.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Android.cs @@ -17,18 +17,9 @@ public bool IsCurveValid(Oid oid) return IsValueOrFriendlyNameValid(oid.FriendlyName); } - public bool ExplicitCurvesSupported - { - get - { - if (PlatformDetection.IsOSXLike) - { - return false; - } + public bool ExplicitCurvesSupported => true; - return true; - } - } + public bool CanDeriveNewPublicKey => false; private static bool IsValueOrFriendlyNameValid(string friendlyNameOrValue) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Unix.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Unix.cs index 6713d1662aa3b..c8390e2b28e92 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Unix.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Unix.cs @@ -34,6 +34,8 @@ public bool ExplicitCurvesSupported } } + public bool CanDeriveNewPublicKey => true; + private static bool IsValueOrFriendlyNameValid(string friendlyNameOrValue) { if (string.IsNullOrEmpty(friendlyNameOrValue)) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Windows.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Windows.cs index 0982bada8f6b6..c458f74cd8931 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Windows.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/DefaultECDiffieHellmanProvider.Windows.cs @@ -22,6 +22,8 @@ public bool ExplicitCurvesSupported } } + public bool CanDeriveNewPublicKey => true; + private static bool NativeOidFriendlyNameExists(string oidFriendlyName) { if (string.IsNullOrEmpty(oidFriendlyName)) diff --git a/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngProvider.cs b/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngProvider.cs index da665e79741fe..6159cc28e2244 100644 --- a/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngProvider.cs +++ b/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngProvider.cs @@ -36,6 +36,8 @@ public bool ExplicitCurvesSupported } } + public bool CanDeriveNewPublicKey => true; + private static bool NativeOidFriendlyNameExists(string oidFriendlyName) { if (string.IsNullOrEmpty(oidFriendlyName)) diff --git a/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj b/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj index 9a91ceba6b8a6..7216670a2c0b2 100644 --- a/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj @@ -32,6 +32,9 @@ Link="CommonTest\System\Security\Cryptography\AlgorithmImplementations\TripleDES\TripleDESFactory.cs" /> + + - - _ecdsaProvider.IsCurveValid(oid); public bool ExplicitCurvesSupported => _ecdsaProvider.ExplicitCurvesSupported; + + public bool CanDeriveNewPublicKey => true; } public partial class ECDiffieHellmanFactory From 5a6ee66306034f339c6ea01e742aa59b13731a73 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Tue, 9 Mar 2021 00:53:29 -0800 Subject: [PATCH 47/83] Change package names without interior dir names (#49202) * Change package names without interior dir names The previous renaming properly renamed the package, but also renamed the nested folder in the dotnet-runtime zip to Microsoft.NETCore.App.PGO, which created problems with integration with the installer. This should fix that by creating packages with a changed name without altering the contents. * Test change without renaming host package * Only set property when pgoinstrument is set * Missed .Runtime package * Code review comments --- .../pkg/sfx/Microsoft.NETCore.App/Directory.Build.props | 1 - .../Microsoft.NETCore.App.Crossgen2.sfxproj | 3 ++- .../Microsoft.NETCore.App/Microsoft.NETCore.App.Host.sfxproj | 1 + .../Microsoft.NETCore.App/Microsoft.NETCore.App.Ref.sfxproj | 1 + .../Microsoft.NETCore.App.Runtime.sfxproj | 1 + 5 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index d165bf2c06efb..2e26aeef0c562 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -3,7 +3,6 @@ $(MicrosoftNetCoreAppFrameworkName) - $(SharedFrameworkName).PGO false .NET Runtime diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Crossgen2.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Crossgen2.sfxproj index 45b0ae1217795..1084bd31a8201 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Crossgen2.sfxproj +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Crossgen2.sfxproj @@ -6,7 +6,8 @@ true RuntimePack $(SharedFrameworkName).Crossgen2 - $(SharedFrameworkName).$(RuntimeIdentifier) + .PGO + $(SharedFrameworkName)$(PgoSuffix).$(RuntimeIdentifier) dotnet-crossgen2 crossgen2 linux-x64;linux-musl-x64;osx-x64;osx-arm64;win-x64 diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Host.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Host.sfxproj index eb264e1385fd9..ab948eb5ddbae 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Host.sfxproj +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Host.sfxproj @@ -8,6 +8,7 @@ dotnet-apphost-pack dotnet-apphost-pack NetCore.AppHostPack + $(SharedFrameworkName).PGO + + + diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs index 564227d0f9a1d..c960388901732 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs @@ -50,9 +50,6 @@ public static partial class PlatformDetection public static bool IsNotFedoraOrRedHatFamily => !IsFedora && !IsRedHatFamily; public static bool IsNotDebian10 => !IsDebian10; - // Android - public static bool IsAndroid => RuntimeInformation.IsOSPlatform(OSPlatform.Create("Android")); - public static bool IsSuperUser => IsBrowser || IsWindows ? false : libc.geteuid() == 0; public static Version OpenSslVersion => !IsOSXLike && !IsWindows ? diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index 4e02843b71d51..f39ef807e9cab 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -26,6 +26,7 @@ public static partial class PlatformDetection public static bool IsMonoInterpreter => GetIsRunningOnMonoInterpreter(); public static bool IsFreeBSD => RuntimeInformation.IsOSPlatform(OSPlatform.Create("FREEBSD")); public static bool IsNetBSD => RuntimeInformation.IsOSPlatform(OSPlatform.Create("NETBSD")); + public static bool IsAndroid => RuntimeInformation.IsOSPlatform(OSPlatform.Create("Android")); public static bool IsiOS => RuntimeInformation.IsOSPlatform(OSPlatform.Create("IOS")); public static bool IstvOS => RuntimeInformation.IsOSPlatform(OSPlatform.Create("TVOS")); public static bool IsMacCatalyst => RuntimeInformation.IsOSPlatform(OSPlatform.Create("MACCATALYST")); @@ -33,6 +34,7 @@ public static partial class PlatformDetection public static bool IsSolaris => RuntimeInformation.IsOSPlatform(OSPlatform.Create("SOLARIS")); public static bool IsBrowser => RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER")); public static bool IsNotBrowser => !IsBrowser; + public static bool IsNotMobile => IsNotBrowser && !IsMacCatalyst && !IsiOS && !IstvOS && !IsAndroid; public static bool IsNotNetFramework => !IsNetFramework; public static bool IsArmProcess => RuntimeInformation.ProcessArchitecture == Architecture.Arm; @@ -56,6 +58,9 @@ public static partial class PlatformDetection public static bool IsBrowserDomSupported => GetIsBrowserDomSupported(); public static bool IsNotBrowserDomSupported => !IsBrowserDomSupported; + public static bool IsUsingLimitedCultures => !IsNotMobile; + public static bool IsNotUsingLimitedCultures => IsNotMobile; + // Please make sure that you have the libgdiplus dependency installed. // For details, see https://docs.microsoft.com/dotnet/core/install/dependencies?pivots=os-macos&tabs=netcore31#libgdiplus public static bool IsDrawingSupported diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.h b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.h index ef940e2509355..5f0123d8ef521 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.h +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim.h @@ -8,3 +8,11 @@ PALEXPORT int32_t GlobalizationNative_LoadICU(void); PALEXPORT void GlobalizationNative_InitICUFunctions(void* icuuc, void* icuin, const char* version, const char* suffix); PALEXPORT int32_t GlobalizationNative_GetICUVersion(void); + +#if defined(STATIC_ICU) + +PALEXPORT int32_t GlobalizationNative_LoadICUData(char* path); + +PALEXPORT const char* GlobalizationNative_GetICUDTName(const char* culture); + +#endif diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_static.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_static.c index c4e38fb3e8177..49dd64df6507c 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_static.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_static.c @@ -38,9 +38,99 @@ static void U_CALLCONV icu_trace_data(const void* context, int32_t fnNumber, int #ifdef __EMSCRIPTEN__ #include +static int32_t load_icu_data(void* pData); + EMSCRIPTEN_KEEPALIVE const char* mono_wasm_get_icudt_name(const char* culture); EMSCRIPTEN_KEEPALIVE const char* mono_wasm_get_icudt_name(const char* culture) +{ + return GlobalizationNative_GetICUDTName(culture); +} + +EMSCRIPTEN_KEEPALIVE int32_t mono_wasm_load_icu_data(void* pData); + +EMSCRIPTEN_KEEPALIVE int32_t mono_wasm_load_icu_data(void* pData) +{ + return load_icu_data(pData); +} + + +/* + * driver.c calls this to make sure this file is linked, otherwise + * its not, meaning the EMSCRIPTEN_KEEPALIVE functions above + * are not kept. + */ +void mono_wasm_link_icu_shim(void); + +void mono_wasm_link_icu_shim(void) +{ +} + +#endif + +static int32_t load_icu_data(void* pData) +{ + + UErrorCode status = 0; + udata_setCommonData(pData, &status); + + if (U_FAILURE(status)) { + log_icu_error("udata_setCommonData", status); + return 0; + } else { + +#if defined(ICU_TRACING) + // see https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/tracing.md + utrace_setFunctions(0, 0, 0, icu_trace_data); + utrace_setLevel(UTRACE_VERBOSE); +#endif + isDataSet = 1; + return 1; + } +} + +int32_t GlobalizationNative_LoadICUData(char* path) +{ + int32_t ret = -1; + char* icu_data; + + FILE *fp = fopen (path, "rb"); + if (fp == NULL) { + fprintf (stderr, "Unable to load ICU dat file '%s'.", path); + return ret; + } + + if (fseek (fp, 0L, SEEK_END) != 0) { + fprintf (stderr, "Unable to determine size of the dat file"); + return ret; + } + + long bufsize = ftell (fp); + + if (bufsize == -1) { + fprintf (stderr, "Unable to determine size of the ICU dat file."); + return ret; + } + + icu_data = malloc (sizeof (char) * (bufsize + 1)); + + if (fseek (fp, 0L, SEEK_SET) != 0) { + fprintf (stderr, "Unable to seek ICU dat file."); + return ret; + } + + fread (icu_data, sizeof (char), bufsize, fp); + if (ferror ( fp ) != 0 ) { + fprintf (stderr, "Unable to read ICU dat file"); + return ret; + } + + fclose (fp); + + return load_icu_data (icu_data); +} + +const char* GlobalizationNative_GetICUDTName(const char* culture) { // Based on https://github.com/dotnet/icu/tree/maint/maint-67/icu-filters @@ -69,39 +159,6 @@ EMSCRIPTEN_KEEPALIVE const char* mono_wasm_get_icudt_name(const char* culture) return "icudt_no_CJK.dat"; } -EMSCRIPTEN_KEEPALIVE int32_t mono_wasm_load_icu_data(void * pData); - -EMSCRIPTEN_KEEPALIVE int32_t mono_wasm_load_icu_data(void * pData) -{ - UErrorCode status = 0; - udata_setCommonData(pData, &status); - - if (U_FAILURE(status)) { - log_icu_error("udata_setCommonData", status); - return 0; - } else { - //// Uncomment to enable ICU tracing, - //// see https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/tracing.md - // utrace_setFunctions(0, 0, 0, icu_trace_data); - // utrace_setLevel(UTRACE_VERBOSE); - isDataSet = 1; - return 1; - } -} - -/* - * driver.c calls this to make sure this file is linked, otherwise - * its not, meaning the EMSCRIPTEN_KEEPALIVE functions above - * are not kept. - */ -void mono_wasm_link_icu_shim(void); - -void mono_wasm_link_icu_shim(void) -{ -} - -#endif - int32_t GlobalizationNative_LoadICU(void) { if (!isDataSet) { diff --git a/src/libraries/System.Globalization.Calendars/tests/CalendarTestWithConfigSwitch/CalendarTests.cs b/src/libraries/System.Globalization.Calendars/tests/CalendarTestWithConfigSwitch/CalendarTests.cs index e498c1730e541..6219061acb4c2 100644 --- a/src/libraries/System.Globalization.Calendars/tests/CalendarTestWithConfigSwitch/CalendarTests.cs +++ b/src/libraries/System.Globalization.Calendars/tests/CalendarTestWithConfigSwitch/CalendarTests.cs @@ -10,6 +10,7 @@ namespace System.Globalization.Tests public static class CalendarTests { [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/36883", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.Android)] public static void TestJapaneseCalendarDateParsing() { CultureInfo ciJapanese = new CultureInfo("ja-JP") { DateTimeFormat = { Calendar = new JapaneseCalendar() } }; @@ -18,6 +19,8 @@ public static void TestJapaneseCalendarDateParsing() string eraName = dt.ToString("gg", ciJapanese); // Legacy behavior which we used to throw when using a year number exceeding the era max year. + // + // On mobile, this does not throw, but instead produces a DateTime w/ 95/01/01 Assert.ThrowsAny(() => DateTime.Parse(eraName + " 70/1/1 0:00:00", ciJapanese)); } } diff --git a/src/libraries/System.Globalization.Extensions/tests/Normalization/NormalizationAll.cs b/src/libraries/System.Globalization.Extensions/tests/Normalization/NormalizationAll.cs index e62dfd81f93bc..0f52f67c6b545 100644 --- a/src/libraries/System.Globalization.Extensions/tests/Normalization/NormalizationAll.cs +++ b/src/libraries/System.Globalization.Extensions/tests/Normalization/NormalizationAll.cs @@ -51,8 +51,8 @@ public void Normalize() // Form D VerifyConformanceInvariant(NormalizationForm.FormD, part0, part1, part2, part3, part4); - // Browser's ICU doesn't support FormKC and FormKD - if (PlatformDetection.IsNotBrowser) + // Mobile / Browser ICU doesn't support FormKC and FormKD + if (PlatformDetection.IsNotUsingLimitedCultures) { // Form KC VerifyConformanceInvariant(NormalizationForm.FormKC, part0, part1, part2, part3, part4); diff --git a/src/libraries/System.Globalization.Extensions/tests/Normalization/StringNormalizationTests.cs b/src/libraries/System.Globalization.Extensions/tests/Normalization/StringNormalizationTests.cs index 3ac46a8bd7540..7fe18bb314049 100644 --- a/src/libraries/System.Globalization.Extensions/tests/Normalization/StringNormalizationTests.cs +++ b/src/libraries/System.Globalization.Extensions/tests/Normalization/StringNormalizationTests.cs @@ -49,9 +49,9 @@ public static IEnumerable NormalizeTestData() yield return new object[] { "\u1E9b\u0323", NormalizationForm.FormC, "\u1E9b\u0323" }; yield return new object[] { "\u1E9b\u0323", NormalizationForm.FormD, "\u017f\u0323\u0307" }; - if (PlatformDetection.IsNotBrowser) + if (PlatformDetection.IsNotUsingLimitedCultures) { - // Browser's ICU doesn't support FormKC and FormKD + // Mobile / Browser ICU doesn't support FormKC and FormKD yield return new object[] { "\uFB01", NormalizationForm.FormKC, "fi" }; yield return new object[] { "\uFB01", NormalizationForm.FormKD, "fi" }; yield return new object[] { "\u1E9b\u0323", NormalizationForm.FormKC, "\u1E69" }; diff --git a/src/libraries/System.Globalization/tests/AssemblyInfo.cs b/src/libraries/System.Globalization/tests/AssemblyInfo.cs index 8180aaf9bdf9e..ef77f35ad83a9 100644 --- a/src/libraries/System.Globalization/tests/AssemblyInfo.cs +++ b/src/libraries/System.Globalization/tests/AssemblyInfo.cs @@ -4,4 +4,3 @@ using System; using Xunit; -[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/36883", TestPlatforms.iOS)] diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoEnglishName.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoEnglishName.cs index fdb6e4b189fce..74a0cf9f37e47 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoEnglishName.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoEnglishName.cs @@ -12,14 +12,14 @@ public static IEnumerable EnglishName_TestData() { yield return new object[] { CultureInfo.CurrentCulture.Name, CultureInfo.CurrentCulture.EnglishName }; - if (PlatformDetection.IsNotBrowser) + if (PlatformDetection.IsNotUsingLimitedCultures) { yield return new object[] { "en-US", "English (United States)" }; yield return new object[] { "fr-FR", "French (France)" }; } else { - // Browser's ICU doesn't contain CultureInfo.EnglishName + // Mobile / Browser ICU doesn't contain CultureInfo.EnglishName yield return new object[] { "en-US", "en (US)" }; yield return new object[] { "fr-FR", "fr (FR)" }; } diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoNativeName.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoNativeName.cs index 58429b132138c..0a39e96c80857 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoNativeName.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoNativeName.cs @@ -12,14 +12,14 @@ public static IEnumerable NativeName_TestData() { yield return new object[] { CultureInfo.CurrentCulture.Name, CultureInfo.CurrentCulture.NativeName }; - if (PlatformDetection.IsNotBrowser) + if (PlatformDetection.IsNotUsingLimitedCultures) { yield return new object[] { "en-US", "English (United States)" }; yield return new object[] { "en-CA", "English (Canada)" }; } else { - // Browser's ICU doesn't contain CultureInfo.NativeName + // Mobile / Browser ICU doesn't contain CultureInfo.NativeName yield return new object[] { "en-US", "en (US)" }; yield return new object[] { "en-CA", "en (CA)" }; } diff --git a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoTests.cs b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoTests.cs index b4c5576322c0b..3139852d79d7c 100644 --- a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoTests.cs +++ b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoTests.cs @@ -67,9 +67,9 @@ public void NativeCalendarName_Get_ReturnsExpected(DateTimeFormatInfo dtfi, Cale { dtfi.Calendar = calendar; - if (PlatformDetection.IsNotBrowser) + if (PlatformDetection.IsNotUsingLimitedCultures) { - // Browser's ICU doesn't contain NativeCalendarName, + // Mobile / Browser ICU doesn't contain NativeCalendarName, Assert.Equal(nativeCalendarName, dtfi.NativeCalendarName); } } diff --git a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyGroupSizes.cs b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyGroupSizes.cs index 261edc3fb0d26..34fd7bc00cb2b 100644 --- a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyGroupSizes.cs +++ b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyGroupSizes.cs @@ -13,7 +13,7 @@ public static IEnumerable CurrencyGroupSizes_TestData() yield return new object[] { NumberFormatInfo.InvariantInfo, new int[] { 3 } }; yield return new object[] { CultureInfo.GetCultureInfo("en-US").NumberFormat, new int[] { 3 } }; - if (PlatformDetection.IsNotBrowser && !PlatformDetection.IsUbuntu && !PlatformDetection.IsWindows7 && !PlatformDetection.IsWindows8x && !PlatformDetection.IsFedora) + if (PlatformDetection.IsNotUsingLimitedCultures && !PlatformDetection.IsUbuntu && !PlatformDetection.IsWindows7 && !PlatformDetection.IsWindows8x && !PlatformDetection.IsFedora) { yield return new object[] { CultureInfo.GetCultureInfo("ur-IN").NumberFormat, new int[] { 3, 2 } }; } diff --git a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyNegativePattern.cs b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyNegativePattern.cs index 76653b6d68af4..c001a7446525d 100644 --- a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyNegativePattern.cs +++ b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoCurrencyNegativePattern.cs @@ -30,9 +30,9 @@ public static IEnumerable CurrencyNegativePatternTestLocales() yield return new object[] { "fr-CD" }; yield return new object[] { "fr-CA" }; - if (PlatformDetection.IsNotBrowser) + if (PlatformDetection.IsNotUsingLimitedCultures) { - // Browser's ICU doesn't contain these locales + // ICU for mobile / browser do not contain these locales yield return new object[] { "as" }; yield return new object[] { "es-BO" }; } diff --git a/src/libraries/System.Globalization/tests/System/Globalization/RegionInfoTests.cs b/src/libraries/System.Globalization/tests/System/Globalization/RegionInfoTests.cs index 4fa32f5127936..fa5a5e23a24a7 100644 --- a/src/libraries/System.Globalization/tests/System/Globalization/RegionInfoTests.cs +++ b/src/libraries/System.Globalization/tests/System/Globalization/RegionInfoTests.cs @@ -111,7 +111,7 @@ public void DisplayName(string name, string expected) public static IEnumerable NativeName_TestData() { - if (PlatformDetection.IsNotBrowser) + if (PlatformDetection.IsNotUsingLimitedCultures) { yield return new object[] { "GB", "United Kingdom" }; yield return new object[] { "SE", "Sverige" }; @@ -135,7 +135,7 @@ public void NativeName(string name, string expected) public static IEnumerable EnglishName_TestData() { - if (PlatformDetection.IsNotBrowser) + if (PlatformDetection.IsNotUsingLimitedCultures) { yield return new object[] { "en-US", new string[] { "United States" } }; yield return new object[] { "US", new string[] { "United States" } }; @@ -216,7 +216,7 @@ public void MiscTest(int lcid, int geoId, string currencyEnglishName, string cur RegionInfo ri = new RegionInfo(lcid); // create it with lcid Assert.Equal(geoId, ri.GeoId); - if (PlatformDetection.IsBrowser) + if (PlatformDetection.IsUsingLimitedCultures) { Assert.Equal(currencyShortName, ri.CurrencyEnglishName); Assert.Equal(currencyShortName, ri.CurrencyNativeName); diff --git a/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs b/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs index f0c56f385c146..72e155fab597a 100644 --- a/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs +++ b/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs @@ -225,9 +225,9 @@ public static IEnumerable GetTestLocales() yield return "tr"; yield return "tr-TR"; - if (PlatformDetection.IsNotBrowser) + if (PlatformDetection.IsNotUsingLimitedCultures) { - // Browser's ICU doesn't contain these locales + // Mobile / Browser ICU doesn't contain these locales yield return "az"; yield return "az-Latn-AZ"; } diff --git a/src/libraries/System.Private.Xml/tests/XmlReader/Tests/AsyncReaderLateInitTests.cs b/src/libraries/System.Private.Xml/tests/XmlReader/Tests/AsyncReaderLateInitTests.cs index 482014481e8fb..83c9584f4357c 100644 --- a/src/libraries/System.Private.Xml/tests/XmlReader/Tests/AsyncReaderLateInitTests.cs +++ b/src/libraries/System.Private.Xml/tests/XmlReader/Tests/AsyncReaderLateInitTests.cs @@ -69,6 +69,7 @@ public static void ReadAfterInitializationWithTextReaderOnAsyncReaderDoesNotThro } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49187", TestPlatforms.iOS | TestPlatforms.tvOS)] public static void ReadAsyncAfterInitializationWithUriThrows() { using (XmlReader reader = XmlReader.Create("http://test.test/test.html", new XmlReaderSettings() { Async = true })) @@ -78,6 +79,7 @@ public static void ReadAsyncAfterInitializationWithUriThrows() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49187", TestPlatforms.iOS | TestPlatforms.tvOS)] public static void ReadAfterInitializationWithUriOnAsyncReaderTrows() { using (XmlReader reader = XmlReader.Create("http://test.test/test.html", new XmlReaderSettings() { Async = true })) @@ -87,6 +89,7 @@ public static void ReadAfterInitializationWithUriOnAsyncReaderTrows() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsSubsystemForLinux), nameof(PlatformDetection.IsThreadingSupported))] // [ActiveIssue("https://github.com/dotnet/runtime/issues/18258")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49187", TestPlatforms.iOS | TestPlatforms.tvOS)] public static void InitializationWithUriOnNonAsyncReaderThrows() { Assert.Throws(() => XmlReader.Create("http://test.test/test.html", new XmlReaderSettings() { Async = false })); diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index b920de0d7c057..e2c0a92a18589 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -47,7 +47,6 @@ - @@ -85,9 +84,6 @@ - - - @@ -107,10 +103,19 @@ + + + + + + + + + diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index c3964a4c9bf36..12dbafe50ccd6 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -179,7 +179,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "tvOS") # See man cmake-toolchains(7) on which variables # control cross-compiling to ios - add_definitions(-DNO_GLOBALIZATION_SHIM) add_definitions(-D_THREAD_SAFE) set(HOST_DARWIN 1) set(HOST_IOS 1) @@ -522,7 +521,10 @@ elseif(HOST_WASM) set(STATIC_ICU 1) set(ICU_LIBS "icucore") elseif(HOST_IOS) - # FIXME: + set(ICU_FLAGS "-DTARGET_UNIX -DU_DISABLE_RENAMING -Wno-reserved-id-macro -Wno-documentation -Wno-documentation-unknown-command -Wno-switch-enum -Wno-covered-switch-default -Wno-extra-semi-stmt -Wno-unknown-warning-option -Wno-deprecated-declarations") + set(HAVE_SYS_ICU 1) + set(STATIC_ICU 1) + set(ICU_LIBS icuuc icui18n icudata) elseif(HOST_ANDROID) set(ICU_FLAGS "-DPALEXPORT=\"\" -DHAVE_UDAT_STANDALONE_SHORTER_WEEKDAYS -DHAVE_SET_MAX_VARIABLE -DTARGET_UNIX -DTARGET_ANDROID -Wno-reserved-id-macro -Wno-documentation -Wno-documentation-unknown-command -Wno-switch-enum -Wno-covered-switch-default -Wno-covered-switch-default -Wno-extra-semi-stmt -Wno-unknown-warning-option") set(HAVE_SYS_ICU 1) diff --git a/src/mono/mono.proj b/src/mono/mono.proj index 0298eb1a378f5..4b2d2ab2a0c02 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -61,7 +61,7 @@ hybrid - + @@ -248,6 +248,7 @@ <_MonoCMakeSystemName Condition="'$(TargetstvOS)' == 'true'">tvOS <_MonoCMakeVersionMin Condition="'$(TargetsiOS)' == 'true'">$(iOSVersionMin) <_MonoCMakeVersionMin Condition="'$(TargetstvOS)' == 'true'">$(tvOSVersionMin) + <_IcuLibdir>$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)/runtimes/$(TargetOS)-$(TargetArchitecture)/native/lib <_MonoCMakeArgs Include="-DCMAKE_OSX_ARCHITECTURES=arm64"/> @@ -256,11 +257,13 @@ <_MonoCMakeArgs Include="-DCMAKE_SYSTEM_NAME=$(_MonoCMakeSystemName)"/> <_MonoCMakeArgs Include="-DCMAKE_OSX_DEPLOYMENT_TARGET=$(_MonoCMakeVersionMin)" /> <_MonoCMakeArgs Include="-DCMAKE_OSX_SYSROOT='$(_MonoCMakeSysroot)'" /> + <_MonoCMakeArgs Include="-DICU_LIBDIR=$(_IcuLibdir)"/> <_MonoCMakeArgs Condition="'$(Platform)' == 'x64'" Include="-DCMAKE_OSX_ARCHITECTURES=x86_64"/> <_MonoCMakeArgs Condition="'$(Platform)' == 'x86'" Include="-DCMAKE_OSX_ARCHITECTURES=i386"/> <_MonoCMakeArgs Condition="'$(Platform)' == 'arm64'" Include="-DCMAKE_OSX_ARCHITECTURES=arm64"/> <_MonoCMakeArgs Condition="'$(Platform)' == 'arm'" Include=""-DCMAKE_OSX_ARCHITECTURES=armv7%3Barmv7s""/> <_MonoCFLAGS Include="-Wl,-application_extension" /> + <_MonoCFLAGS Include="-I$(PkgMicrosoft_NETCore_Runtime_ICU_Transport)/runtimes/$(TargetOS)-$(TargetArchitecture)/native/include" /> <_MonoCXXFLAGS Include="-Wl,-application_extension" /> @@ -555,6 +558,7 @@ <_MonoRuntimeFilePath Condition="'$(_MonoRuntimeFilePath)' == ''">$(MonoObjDir)out\lib\libmonosgen-2.0.so <_MonoRuntimeStaticFilePath Condition="'$(TargetsMacCatalyst)' == 'true' or '$(TargetsiOS)' == 'true' or '$(TargetstvOS)' == 'true' or '$(TargetsAndroid)' == 'true'">$(MonoObjDir)out\lib\libmonosgen-2.0.a <_MonoIncludeInterpStaticFiles Condition="'$(TargetsBrowser)' == 'true'">true + <_MonoIncludeIcuFiles Condition="'$(TargetsiOS)' == 'true' or '$(TargetstvOS)' == 'true'">true <_MonoAotCrossFilePath>$(MonoObjDir)cross\out\bin\mono-sgen$(ExeExt) @@ -596,8 +600,19 @@ <_MonoRuntimeArtifacts Condition="'$(TargetsBrowser)' == 'true' and '$(BuildMonoAOTCrossCompilerOnly)' != 'true'" Include="$(MonoObjDir)out\lib\libmono-profiler-aot.a"> $(RuntimeBinDir)libmono-profiler-aot.a + + <_IcuArtifacts Condition="'$(_MonoIncludeIcuFiles)' == 'true'" + Include="$(_IcuLibdir)\libicuuc.a; + $(_IcuLibdir)\libicui18n.a; + $(_IcuLibdir)\libicudata.a; + $(_IcuLibdir)\*.dat" /> + + (); + /// + /// Target arch, can be "arm64" (device) or "x64" (simulator) at the moment + /// + [Required] + public string Arch { get; set; } = ""!; + + /// + /// Path to *.app bundle + /// + [Output] + public string AppBundlePath { get; set; } = ""!; + + /// + /// Path to xcode project + /// + [Output] + public string XcodeProjectPath { get; set; } = ""!; + /// /// Path to store build artifacts /// @@ -58,12 +76,6 @@ public class AppleAppBuilderTask : Task /// public bool Optimized { get; set; } - /// - /// Target arch, can be "arm64" (device) or "x64" (simulator) at the moment - /// - [Required] - public string Arch { get; set; } = ""!; - /// /// DEVELOPER_TEAM provisioning, needed for arm64 builds. /// @@ -97,15 +109,14 @@ public class AppleAppBuilderTask : Task public bool UseConsoleUITemplate { get; set; } /// - /// Path to *.app bundle + /// Prefer FullAOT mode for Simulator over JIT /// - [Output] - public string AppBundlePath { get; set; } = ""!; + public bool ForceAOT { get; set; } /// - /// Prefer FullAOT mode for Simulator over JIT + /// Forces the runtime to use the invariant mode /// - public bool ForceAOT { get; set; } + public bool InvariantGlobalization { get; set; } /// /// Forces the runtime to use the interpreter @@ -113,10 +124,9 @@ public class AppleAppBuilderTask : Task public bool ForceInterpreter { get; set; } /// - /// Path to xcode project + /// Enables detailed runtime logging /// - [Output] - public string XcodeProjectPath { get; set; } = ""!; + public bool EnableRuntimeLogging { get; set; } public override bool Execute() { @@ -173,8 +183,10 @@ public override bool Execute() if (GenerateXcodeProject) { Xcode generator = new Xcode(TargetOS); + generator.EnableRuntimeLogging = EnableRuntimeLogging; + XcodeProjectPath = generator.GenerateXCode(ProjectName, MainLibraryFileName, assemblerFiles, - AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, Optimized, NativeMainSource); + AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, NativeMainSource); if (BuildAppBundle) { diff --git a/src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.template b/src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.template index 4b3d40bda6a8a..7fea422c6b4e2 100644 --- a/src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.template +++ b/src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.template @@ -40,6 +40,7 @@ target_link_libraries( "-framework UIKit" %FrameworksToLink% "-lz" + "-lc++" "-liconv" %NativeLibrariesToLink% ) diff --git a/src/tasks/AppleAppBuilder/Templates/runtime.m b/src/tasks/AppleAppBuilder/Templates/runtime.m index 1a27d785f3b13..fe2845a10ad6d 100644 --- a/src/tasks/AppleAppBuilder/Templates/runtime.m +++ b/src/tasks/AppleAppBuilder/Templates/runtime.m @@ -14,6 +14,8 @@ #import #include #include +#include +#include static char *bundle_path; @@ -201,6 +203,23 @@ //%DllMap% } +int32_t GlobalizationNative_LoadICUData(char *path); + +static int32_t load_icu_data () +{ + char path [1024]; + int res; + + const char *dname = "icudt.dat"; + const char *bundle = get_bundle_path (); + + os_log_info (OS_LOG_DEFAULT, "Loading ICU data file '%s'.", dname); + res = snprintf (path, sizeof (path) - 1, "%s/%s", bundle, dname); + assert (res > 0); + + return GlobalizationNative_LoadICUData(path); +} + #if FORCE_INTERPRETER || FORCE_AOT || (!TARGET_OS_SIMULATOR && !TARGET_OS_MACCATALYST) void mono_jit_set_aot_mode (MonoAotMode mode); void register_aot_modules (void); @@ -209,12 +228,24 @@ void mono_ios_runtime_init (void) { - // for now, only Invariant Mode is supported (FIXME: integrate ICU) +#if INVARIANT_GLOBALIZATION setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1", TRUE); - // uncomment for debug output: - // - // setenv ("MONO_LOG_LEVEL", "debug", TRUE); - // setenv ("MONO_LOG_MASK", "all", TRUE); +#endif + +#if ENABLE_RUNTIME_LOGGING + setenv ("MONO_LOG_LEVEL", "debug", TRUE); + setenv ("MONO_LOG_MASK", "all", TRUE); +#endif + +#if !INVARIANT_GLOBALIZATION + int32_t ret = load_icu_data (); + + if (ret == 0) { + os_log_info (OS_LOG_DEFAULT, "ICU BAD EXIT %d.", ret); + exit (ret); + return; + } +#endif id args_array = [[NSProcessInfo processInfo] arguments]; assert ([args_array count] <= 128); diff --git a/src/tasks/AppleAppBuilder/Xcode.cs b/src/tasks/AppleAppBuilder/Xcode.cs index ddf7dee5f8de0..96fab4b703579 100644 --- a/src/tasks/AppleAppBuilder/Xcode.cs +++ b/src/tasks/AppleAppBuilder/Xcode.cs @@ -29,6 +29,8 @@ public Xcode(string target) } } + public bool EnableRuntimeLogging { get; set; } + public string GenerateXCode( string projectName, string entryPointLib, @@ -40,6 +42,7 @@ public string GenerateXCode( bool useConsoleUiTemplate, bool forceAOT, bool forceInterpreter, + bool invariantGlobalization, bool stripDebugSymbols, string? nativeMainSource = null) { @@ -114,16 +117,27 @@ public string GenerateXCode( cmakeLists = cmakeLists.Replace("%AotSources%", aotSources); cmakeLists = cmakeLists.Replace("%AotModulesSource%", string.IsNullOrEmpty(aotSources) ? "" : "modules.m"); - string defines = ""; + var defines = new StringBuilder(); if (forceInterpreter) { - defines = "add_definitions(-DFORCE_INTERPRETER=1)"; + defines.Append("add_definitions(-DFORCE_INTERPRETER=1)"); } else if (forceAOT) { - defines = "add_definitions(-DFORCE_AOT=1)"; + defines.Append("add_definitions(-DFORCE_AOT=1)"); } - cmakeLists = cmakeLists.Replace("%Defines%", defines); + + if (invariantGlobalization) + { + defines.Append("add_definitions(-DINVARIANT_GLOBALIZATION=1)"); + } + + if (EnableRuntimeLogging) + { + defines.Append("add_definitions(-DENABLE_RUNTIME_LOGGING=1)"); + } + + cmakeLists = cmakeLists.Replace("%Defines%", defines.ToString()); string plist = Utils.GetEmbeddedResource("Info.plist.template") .Replace("%BundleIdentifier%", projectName); @@ -156,6 +170,8 @@ public string GenerateXCode( dllMap.AppendLine($" mono_dllmap_insert (NULL, \"{aFileName}\", NULL, \"__Internal\", NULL);"); } + dllMap.AppendLine($" mono_dllmap_insert (NULL, \"System.Globalization.Native\", NULL, \"__Internal\", NULL);"); + File.WriteAllText(Path.Combine(binDir, "runtime.m"), Utils.GetEmbeddedResource("runtime.m") .Replace("//%DllMap%", dllMap.ToString()) From 4db3d3f78e9d9fc1aa5b1136e4ddac27deca4a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Tue, 9 Mar 2021 12:34:38 -0500 Subject: [PATCH 57/83] [metadata_update] Fix bounds check error (#49328) The issue is that the STANDALONESIG bounds check was using a 0-based index, and mono_metadata_bounds_check_slow was compensating by adding 1. But that made another call to the bounds check fail: in mono_class_from_typeref_checked we passed a 1-based index. So in the case where a TypeRef was using the last AssemblyRef in a delta, the bound check would fail. Fixes https://github.com/dotnet/runtime/issues/49227 Co-authored-by: Ryan Lucia Co-authored-by: Ryan Lucia --- src/mono/mono/metadata/metadata-internals.h | 1 + src/mono/mono/metadata/metadata.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 7525b0ba7d333..63e895d54f203 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -973,6 +973,7 @@ mono_metadata_table_bounds_check (MonoImage *image, int table_index, int token_i gboolean mono_metadata_table_bounds_check_slow (MonoImage *image, int table_index, int token_index); +/* token_index is 1-based */ static inline gboolean mono_metadata_table_bounds_check (MonoImage *image, int table_index, int token_index) { diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 6166b2eee7c62..056f2e6c45f90 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -1000,8 +1000,11 @@ mono_metadata_table_bounds_check_slow (MonoImage *image, int table_index, int to GList *list = image->delta_image; MonoImage *dmeta; MonoTableInfo *table; + /* result row, 0-based */ int ridx; + int original_token = mono_metadata_make_token (table_index, token_index); + uint32_t exposed_gen = mono_metadata_update_get_thread_generation (); do { if (!list) @@ -1011,7 +1014,8 @@ mono_metadata_table_bounds_check_slow (MonoImage *image, int table_index, int to return TRUE; list = list->next; table = &dmeta->tables [table_index]; - ridx = mono_image_relative_delta_index (dmeta, mono_metadata_make_token (table_index, token_index + 1)) - 1; + /* mono_image_relative_delta_index returns a 1-based index */ + ridx = mono_image_relative_delta_index (dmeta, original_token) - 1; } while (ridx < 0 || ridx >= table->rows); return FALSE; @@ -4779,7 +4783,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons if (local_var_sig_tok) { int idx = mono_metadata_token_index (local_var_sig_tok) - 1; - if (mono_metadata_table_bounds_check (m, MONO_TABLE_STANDALONESIG, idx)) { + if (mono_metadata_table_bounds_check (m, MONO_TABLE_STANDALONESIG, idx + 1)) { mono_error_set_bad_image (error, m, "Invalid method header local vars signature token 0x%08x", idx); goto fail; } From 542dc938a5e0f924fbfef435144e03c6bcf4dcc7 Mon Sep 17 00:00:00 2001 From: Dan Moseley Date: Tue, 9 Mar 2021 10:35:51 -0800 Subject: [PATCH 58/83] Increase timeout for thread pool tests (#49329) Relates to #48236 It isn't possible to say whether the test is hung, or will complete but occasionally needs more than 30 seconds. Let's try increasing the cutoff to see. --- .../Common/tests/System/Threading/ThreadTestHelpers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Common/tests/System/Threading/ThreadTestHelpers.cs b/src/libraries/Common/tests/System/Threading/ThreadTestHelpers.cs index 38ef355695ca8..f7ea606ffddf5 100644 --- a/src/libraries/Common/tests/System/Threading/ThreadTestHelpers.cs +++ b/src/libraries/Common/tests/System/Threading/ThreadTestHelpers.cs @@ -11,7 +11,7 @@ namespace System.Threading.Tests public static class ThreadTestHelpers { public const int ExpectedTimeoutMilliseconds = 50; - public const int UnexpectedTimeoutMilliseconds = 1000 * 30; + public const int UnexpectedTimeoutMilliseconds = 1000 * 60; // Wait longer for a thread to time out, so that an unexpected timeout in the thread is more likely to expire first and // provide a better stack trace for the failure From e0bbfa0f555cf5b9d8b8749e1a91a78924c9d927 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 9 Mar 2021 12:49:25 -0600 Subject: [PATCH 59/83] Resolve ILLink warnings in System.ComponentModel.TypeConverter (Round 1) (#48890) * Resolve ILLink warnings in System.ComponentModel.TypeConverter (Round 1) Contributes to #45623 * Update the AttributeCollection message * Add trimming test for SimplePropertyDescriptor.IsReadOnly * Update the ref source with DynamicallyAccessedMembers attributes --- .../ref/System.ComponentModel.Annotations.cs | 12 +- .../System.ComponentModel.Annotations.csproj | 2 + .../src/ILLink/ILLink.Suppressions.xml | 14 +- .../System.ComponentModel.Annotations.csproj | 5 + ...atedMetadataTypeTypeDescriptionProvider.cs | 9 +- .../AssociatedMetadataTypeTypeDescriptor.cs | 22 ++- .../DataAnnotations/MetadataTypeAttribute.cs | 5 +- .../DataAnnotations/RangeAttribute.cs | 10 +- .../ref/System.ComponentModel.Primitives.cs | 3 +- .../src/System/ComponentModel/IContainer.cs | 3 +- .../src/System/ComponentModel/ISite.cs | 4 +- .../System.ComponentModel.TypeConverter.cs | 131 +++++++++++++----- .../src/ILLink/ILLink.Suppressions.xml | 82 ++++------- .../Linq/ComponentModel/XComponentModel.cs | 6 +- .../ComponentModel/AmbientValueAttribute.cs | 2 +- .../System/ComponentModel/ArrayConverter.cs | 2 + .../ComponentModel/AttributeCollection.cs | 9 +- .../src/System/ComponentModel/BindingList.cs | 7 +- .../ComponentModel/CollectionConverter.cs | 2 + .../ComponentModel/ComponentConverter.cs | 3 + .../ComponentResourceManager.cs | 3 + .../src/System/ComponentModel/Container.cs | 6 + .../ComponentModel/CustomTypeDescriptor.cs | 4 + .../DelegatingTypeDescriptionProvider.cs | 10 +- .../Design/DesignerOptionService.cs | 5 + .../Design/IDesignerOptionService.cs | 4 + .../MemberRelationshipService.cs | 29 ++-- .../System/ComponentModel/EnumConverter.cs | 4 +- .../ExpandableObjectConverter.cs | 3 + .../ComponentModel/ICustomTypeDescriptor.cs | 4 + .../MultilineStringConverter.cs | 2 + .../System/ComponentModel/NestedContainer.cs | 2 + .../ComponentModel/NullableConverter.cs | 2 + .../ComponentModel/PropertyDescriptor.cs | 7 +- .../ReflectPropertyDescriptor.cs | 43 +++++- ...peDescriptionProvider.ReflectedTypeData.cs | 9 +- .../ReflectTypeDescriptionProvider.cs | 64 ++++++--- .../System/ComponentModel/TypeConverter.cs | 11 +- .../ComponentModel/TypeDescriptionProvider.cs | 18 ++- .../System/ComponentModel/TypeDescriptor.cs | 129 ++++++++++++++--- .../src/System/Drawing/PointConverter.cs | 1 + .../src/System/Drawing/RectangleConverter.cs | 1 + .../src/System/Drawing/SizeConverter.cs | 1 + .../src/System/Drawing/SizeFConverter.cs | 1 + .../TrimmingTests/TypeConverterIsReadOnly.cs | 72 ++++++++++ .../ref/System.Data.Common.cs | 6 + .../src/ILLink/ILLink.Suppressions.xml | 96 +++++++++++++ .../System/Data/Common/DataRecordInternal.cs | 4 + .../Data/Common/DbConnectionStringBuilder.cs | 3 + .../src/System/Data/Common/DbDataRecord.cs | 4 + .../src/System/Data/DataRowView.cs | 7 + .../DataViewManagerListItemTypeDescriptor.cs | 4 + .../src/System/Data/xmlsaver.cs | 6 +- 53 files changed, 704 insertions(+), 194 deletions(-) create mode 100644 src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeConverterIsReadOnly.cs diff --git a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs index ec83158f170ec..e50b88250a2f6 100644 --- a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs +++ b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs @@ -6,13 +6,13 @@ namespace System.ComponentModel.DataAnnotations { -// TODO-NULLABLE: Enable after System.ComponentModel.TypeDescriptionProvider is annotated + // TODO-NULLABLE: Enable after System.ComponentModel.TypeDescriptionProvider is annotated #nullable disable public partial class AssociatedMetadataTypeTypeDescriptionProvider : System.ComponentModel.TypeDescriptionProvider { public AssociatedMetadataTypeTypeDescriptionProvider(System.Type type) { } - public AssociatedMetadataTypeTypeDescriptionProvider(System.Type type, System.Type associatedMetadataType) { } - public override System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor(System.Type objectType, object instance) { throw null; } + public AssociatedMetadataTypeTypeDescriptionProvider(System.Type type, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type associatedMetadataType) { } + public override System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type objectType, object instance) { throw null; } } #nullable enable [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] @@ -194,7 +194,8 @@ public MaxLengthAttribute(int length) { } [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false)] public sealed partial class MetadataTypeAttribute : System.Attribute { - public MetadataTypeAttribute(System.Type metadataClassType) { } + public MetadataTypeAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type metadataClassType) { } + [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] public System.Type MetadataClassType { get { throw null; } } } [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)] @@ -216,10 +217,11 @@ public partial class RangeAttribute : System.ComponentModel.DataAnnotations.Vali { public RangeAttribute(double minimum, double maximum) { } public RangeAttribute(int minimum, int maximum) { } - public RangeAttribute(System.Type type, string minimum, string maximum) { } + public RangeAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string minimum, string maximum) { } public bool ConvertValueInInvariantCulture { get { throw null; } set { } } public object Maximum { get { throw null; } } public object Minimum { get { throw null; } } + [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] public System.Type OperandType { get { throw null; } } public bool ParseLimitsInInvariantCulture { get { throw null; } set { } } public override string FormatErrorMessage(string name) { throw null; } diff --git a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.csproj b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.csproj index fdedddfbbdb24..532f0e6653c48 100644 --- a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.csproj +++ b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.csproj @@ -5,5 +5,7 @@ + + \ No newline at end of file diff --git a/src/libraries/System.ComponentModel.Annotations/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.ComponentModel.Annotations/src/ILLink/ILLink.Suppressions.xml index 6153ad909d861..acf0ec22218af 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.ComponentModel.Annotations/src/ILLink/ILLink.Suppressions.xml @@ -1,18 +1,6 @@  - - ILLink - IL2070 - member - M:System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptor.TypeDescriptorCache.CheckAssociatedMetadataType(System.Type,System.Type) - - - ILLink - IL2070 - member - M:System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptor.TypeDescriptorCache.GetAssociatedMetadata(System.Type,System.String) - ILLink IL2072 @@ -56,4 +44,4 @@ M:System.ComponentModel.DataAnnotations.ValidationAttribute.SetResourceAccessorByPropertyLookup - \ No newline at end of file + diff --git a/src/libraries/System.ComponentModel.Annotations/src/System.ComponentModel.Annotations.csproj b/src/libraries/System.ComponentModel.Annotations/src/System.ComponentModel.Annotations.csproj index 6291ade5c7046..52c3fff0064fd 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System.ComponentModel.Annotations.csproj +++ b/src/libraries/System.ComponentModel.Annotations/src/System.ComponentModel.Annotations.csproj @@ -60,6 +60,11 @@ + + + + + diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptionProvider.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptionProvider.cs index fc7b7e456b9b9..a408e38342083 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptionProvider.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptionProvider.cs @@ -4,6 +4,8 @@ // TODO-NULLABLE: Enable after System.ComponentModel.TypeDescriptionProvider is annotated #nullable disable +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel.DataAnnotations { /// @@ -12,6 +14,7 @@ namespace System.ComponentModel.DataAnnotations /// public class AssociatedMetadataTypeTypeDescriptionProvider : TypeDescriptionProvider { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] private readonly Type _associatedMetadataType; /// @@ -31,7 +34,9 @@ public AssociatedMetadataTypeTypeDescriptionProvider(Type type) /// The type for which the metadata provider is created. /// The associated type that contains the metadata. /// The value of associatedMetadataType is null. - public AssociatedMetadataTypeTypeDescriptionProvider(Type type, Type associatedMetadataType) + public AssociatedMetadataTypeTypeDescriptionProvider( + Type type, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type associatedMetadataType) : this(type) { if (associatedMetadataType == null) @@ -48,7 +53,7 @@ public AssociatedMetadataTypeTypeDescriptionProvider(Type type, Type associatedM /// The type of object to retrieve the type descriptor for. /// An instance of the type. /// The descriptor that provides metadata for the type. - public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) + public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, object instance) { ICustomTypeDescriptor baseDescriptor = base.GetTypeDescriptor(objectType, instance); return new AssociatedMetadataTypeTypeDescriptor(baseDescriptor, objectType, _associatedMetadataType); diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptor.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptor.cs index 2bc82d50a6e34..2a6d206859eef 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptor.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptor.cs @@ -6,7 +6,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; -using System.Globalization; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; @@ -14,11 +14,15 @@ namespace System.ComponentModel.DataAnnotations { internal class AssociatedMetadataTypeTypeDescriptor : CustomTypeDescriptor { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] private Type AssociatedMetadataType { get; set; } private bool IsSelfAssociated { get; set; } - public AssociatedMetadataTypeTypeDescriptor(ICustomTypeDescriptor parent, Type type, Type associatedMetadataType) + public AssociatedMetadataTypeTypeDescriptor( + ICustomTypeDescriptor parent, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type associatedMetadataType) : base(parent) { AssociatedMetadataType = associatedMetadataType ?? TypeDescriptorCache.GetAssociatedMetadataType(type); @@ -29,6 +33,7 @@ public AssociatedMetadataTypeTypeDescriptor(ICustomTypeDescriptor parent, Type t } } + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) { return GetPropertiesWithMetadata(base.GetProperties(attributes)); @@ -98,7 +103,9 @@ private static class TypeDescriptorCache // Stores whether or not a type and associated metadata type has been checked for validity private static readonly ConcurrentDictionary<(Type, Type), bool> s_validatedMetadataTypeCache = new ConcurrentDictionary<(Type, Type), bool>(); - public static void ValidateMetadataType(Type type, Type associatedType) + public static void ValidateMetadataType( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] Type associatedType) { (Type, Type) typeTuple = (type, associatedType); if (!s_validatedMetadataTypeCache.ContainsKey(typeTuple)) @@ -108,6 +115,7 @@ public static void ValidateMetadataType(Type type, Type associatedType) } } + [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public static Type GetAssociatedMetadataType(Type type) { Type associatedMetadataType = null; @@ -126,7 +134,9 @@ public static Type GetAssociatedMetadataType(Type type) return associatedMetadataType; } - private static void CheckAssociatedMetadataType(Type mainType, Type associatedMetadataType) + private static void CheckAssociatedMetadataType( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type mainType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] Type associatedMetadataType) { // Only properties from main type HashSet mainTypeMemberNames = new HashSet(mainType.GetProperties().Select(p => p.Name)); @@ -148,7 +158,9 @@ private static void CheckAssociatedMetadataType(Type mainType, Type associatedMe } } - public static Attribute[] GetAssociatedMetadata(Type type, string memberName) + public static Attribute[] GetAssociatedMetadata( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, + string memberName) { (Type, string) memberTuple = (type, memberName); Attribute[] attributes; diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MetadataTypeAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MetadataTypeAttribute.cs index b4e3b568bccdf..43ac37f837159 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MetadataTypeAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MetadataTypeAttribute.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; namespace System.ComponentModel.DataAnnotations { @@ -11,6 +12,7 @@ namespace System.ComponentModel.DataAnnotations [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public sealed class MetadataTypeAttribute : Attribute { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] private readonly Type _metadataClassType; /// @@ -19,7 +21,7 @@ public sealed class MetadataTypeAttribute : Attribute /// /// The metadata class to reference. /// metadataClassType is null. - public MetadataTypeAttribute(Type metadataClassType) + public MetadataTypeAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type metadataClassType) { _metadataClassType = metadataClassType; } @@ -27,6 +29,7 @@ public MetadataTypeAttribute(Type metadataClassType) /// /// Gets the metadata class that is associated with a data-model partial class. /// + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public Type MetadataClassType { get diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RangeAttribute.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RangeAttribute.cs index a3b2e0b96c511..ce76d2481c486 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RangeAttribute.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RangeAttribute.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace System.ComponentModel.DataAnnotations @@ -45,7 +46,10 @@ public RangeAttribute(double minimum, double maximum) /// The type of the range parameters. Must implement IComparable. /// The minimum allowable value. /// The maximum allowable value. - public RangeAttribute(Type type, string minimum, string maximum) + public RangeAttribute( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, + string minimum, + string maximum) : base(() => SR.RangeAttribute_ValidationError) { OperandType = type; @@ -67,6 +71,7 @@ public RangeAttribute(Type type, string minimum, string maximum) /// Gets the type of the and values (e.g. Int32, Double, or some custom /// type) /// + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public Type OperandType { get; } /// @@ -199,7 +204,8 @@ private void SetupConversion() comparableType.FullName)); } - TypeConverter converter = TypeDescriptor.GetConverter(type); + // use OperandType here so the trimmer doesn't warn about the 'type' field on a compiler generated type + TypeConverter converter = TypeDescriptor.GetConverter(OperandType); IComparable min = (IComparable)(ParseLimitsInInvariantCulture ? converter.ConvertFromInvariantString((string)minimum) : converter.ConvertFromString((string)minimum)); diff --git a/src/libraries/System.ComponentModel.Primitives/ref/System.ComponentModel.Primitives.cs b/src/libraries/System.ComponentModel.Primitives/ref/System.ComponentModel.Primitives.cs index 35d52c010c2a9..c4b69c84f1e74 100644 --- a/src/libraries/System.ComponentModel.Primitives/ref/System.ComponentModel.Primitives.cs +++ b/src/libraries/System.ComponentModel.Primitives/ref/System.ComponentModel.Primitives.cs @@ -192,6 +192,7 @@ public partial interface IContainer : System.IDisposable { System.ComponentModel.ComponentCollection Components { get; } void Add(System.ComponentModel.IComponent? component); + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered to validate the name.")] void Add(System.ComponentModel.IComponent? component, string? name); void Remove(System.ComponentModel.IComponent? component); } @@ -233,7 +234,7 @@ public partial interface ISite : System.IServiceProvider System.ComponentModel.IComponent Component { get; } System.ComponentModel.IContainer? Container { get; } bool DesignMode { get; } - string? Name { get; set; } + string? Name { get; [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered to validate the name.")] set; } } public partial interface ISupportInitialize { diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/IContainer.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/IContainer.cs index d9a63059fd2aa..07b17161480c2 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/IContainer.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/IContainer.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Runtime.InteropServices; +using System.Diagnostics.CodeAnalysis; namespace System.ComponentModel { @@ -27,6 +27,7 @@ public interface IContainer : IDisposable /// at the end of the list, /// and assigns a name to the component. /// + [RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered to validate the name.")] void Add(IComponent? component, string? name); /// diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ISite.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ISite.cs index e51287ff1f867..911d8eb0c4528 100644 --- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ISite.cs +++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/ISite.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -37,6 +39,6 @@ public interface ISite : IServiceProvider /// When implemented by a class, gets or sets the name of the component /// associated with the . /// - string? Name { get; set; } + string? Name { get; [RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered to validate the name.")] set; } } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs index d741db09af163..29397fc17ead1 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs @@ -38,7 +38,7 @@ public AmbientValueAttribute(long value) { } public AmbientValueAttribute(object value) { } public AmbientValueAttribute(float value) { } public AmbientValueAttribute(string value) { } - public AmbientValueAttribute(System.Type type, string value) { } + public AmbientValueAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, string value) { } public object Value { get { throw null; } } public override bool Equals(object obj) { throw null; } public override int GetHashCode() { throw null; } @@ -47,6 +47,7 @@ public partial class ArrayConverter : System.ComponentModel.CollectionConverter { public ArrayConverter() { } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } } @@ -58,15 +59,17 @@ public AttributeCollection(params System.Attribute[] attributes) { } protected virtual System.Attribute[] Attributes { get { throw null; } } public int Count { get { throw null; } } public virtual System.Attribute this[int index] { get { throw null; } } - public virtual System.Attribute this[System.Type attributeType] { get { throw null; } } + public virtual System.Attribute this[[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type attributeType] { get { throw null; } } int System.Collections.ICollection.Count { get { throw null; } } bool System.Collections.ICollection.IsSynchronized { get { throw null; } } object System.Collections.ICollection.SyncRoot { get { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public bool Contains(System.Attribute attribute) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public bool Contains(System.Attribute[] attributes) { throw null; } public void CopyTo(System.Array array, int index) { } public static System.ComponentModel.AttributeCollection FromExisting(System.ComponentModel.AttributeCollection existing, params System.Attribute[] newAttributes) { throw null; } - protected System.Attribute GetDefaultAttribute(System.Type attributeType) { throw null; } + protected System.Attribute GetDefaultAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type attributeType) { throw null; } public System.Collections.IEnumerator GetEnumerator() { throw null; } public bool Matches(System.Attribute attribute) { throw null; } public bool Matches(System.Attribute[] attributes) { throw null; } @@ -116,7 +119,7 @@ public enum BindingDirection OneWay = 0, TwoWay = 1, } - public partial class BindingList : System.Collections.ObjectModel.Collection, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.ComponentModel.IBindingList, System.ComponentModel.ICancelAddNew, System.ComponentModel.IRaiseItemChangedEvents + public partial class BindingList<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] T> : System.Collections.ObjectModel.Collection, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.ComponentModel.IBindingList, System.ComponentModel.ICancelAddNew, System.ComponentModel.IRaiseItemChangedEvents { public BindingList() { } public BindingList(System.Collections.Generic.IList list) { } @@ -202,6 +205,7 @@ public partial class CollectionConverter : System.ComponentModel.TypeConverter { public CollectionConverter() { } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } } @@ -220,6 +224,7 @@ public ComplexBindingPropertiesAttribute(string dataSource, string dataMember) { public partial class ComponentConverter : System.ComponentModel.ReferenceConverter { public ComponentConverter(System.Type type) : base (default(System.Type)) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } } @@ -233,7 +238,9 @@ public partial class ComponentResourceManager : System.Resources.ResourceManager { public ComponentResourceManager() { } public ComponentResourceManager(System.Type t) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of value cannot be statically discovered.")] public void ApplyResources(object value, string objectName) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of value cannot be statically discovered.")] public virtual void ApplyResources(object value, string objectName, System.Globalization.CultureInfo culture) { } } public partial class Container : System.ComponentModel.IContainer, System.IDisposable @@ -241,6 +248,7 @@ public partial class Container : System.ComponentModel.IContainer, System.IDispo public Container() { } public virtual System.ComponentModel.ComponentCollection Components { get { throw null; } } public virtual void Add(System.ComponentModel.IComponent component) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered to validate the name.")] public virtual void Add(System.ComponentModel.IComponent component, string name) { } protected virtual System.ComponentModel.ISite CreateSite(System.ComponentModel.IComponent component, string name) { throw null; } public void Dispose() { } @@ -249,6 +257,7 @@ protected virtual void Dispose(bool disposing) { } protected virtual object GetService(System.Type service) { throw null; } public virtual void Remove(System.ComponentModel.IComponent component) { } protected void RemoveWithoutUnsiting(System.ComponentModel.IComponent component) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered.")] protected virtual void ValidateName(System.ComponentModel.IComponent component, string name) { } } public abstract partial class ContainerFilterService @@ -280,8 +289,10 @@ protected CustomTypeDescriptor(System.ComponentModel.ICustomTypeDescriptor paren public virtual System.ComponentModel.PropertyDescriptor GetDefaultProperty() { throw null; } public virtual object GetEditor(System.Type editorBaseType) { throw null; } public virtual System.ComponentModel.EventDescriptorCollection GetEvents() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public virtual System.ComponentModel.EventDescriptorCollection GetEvents(System.Attribute[] attributes) { throw null; } public virtual System.ComponentModel.PropertyDescriptorCollection GetProperties() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public virtual System.ComponentModel.PropertyDescriptorCollection GetProperties(System.Attribute[] attributes) { throw null; } public virtual object GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd) { throw null; } } @@ -400,8 +411,9 @@ public DoubleConverter() { } } public partial class EnumConverter : System.ComponentModel.TypeConverter { - public EnumConverter(System.Type type) { } + public EnumConverter([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type type) { } protected virtual System.Collections.IComparer Comparer { get { throw null; } } + [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] protected System.Type EnumType { get { throw null; } } protected System.ComponentModel.TypeConverter.StandardValuesCollection Values { get { throw null; } set { } } public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) { throw null; } @@ -415,9 +427,9 @@ public EnumConverter(System.Type type) { } } public abstract partial class EventDescriptor : System.ComponentModel.MemberDescriptor { - protected EventDescriptor(System.ComponentModel.MemberDescriptor descr) : base (default(System.ComponentModel.MemberDescriptor)) { } - protected EventDescriptor(System.ComponentModel.MemberDescriptor descr, System.Attribute[] attrs) : base (default(System.ComponentModel.MemberDescriptor)) { } - protected EventDescriptor(string name, System.Attribute[] attrs) : base (default(System.ComponentModel.MemberDescriptor)) { } + protected EventDescriptor(System.ComponentModel.MemberDescriptor descr) : base (default(string)) { } + protected EventDescriptor(System.ComponentModel.MemberDescriptor descr, System.Attribute[] attrs) : base (default(string)) { } + protected EventDescriptor(string name, System.Attribute[] attrs) : base (default(string)) { } public abstract System.Type ComponentType { get; } public abstract System.Type EventType { get; } public abstract bool IsMulticast { get; } @@ -466,6 +478,7 @@ void System.Collections.IList.RemoveAt(int index) { } public partial class ExpandableObjectConverter : System.ComponentModel.TypeConverter { public ExpandableObjectConverter() { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } } @@ -554,8 +567,10 @@ public partial interface ICustomTypeDescriptor System.ComponentModel.PropertyDescriptor GetDefaultProperty(); object GetEditor(System.Type editorBaseType); System.ComponentModel.EventDescriptorCollection GetEvents(); + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] System.ComponentModel.EventDescriptorCollection GetEvents(System.Attribute[] attributes); System.ComponentModel.PropertyDescriptorCollection GetProperties(); + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] System.ComponentModel.PropertyDescriptorCollection GetProperties(System.Attribute[] attributes); object GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd); } @@ -965,6 +980,7 @@ public partial class MultilineStringConverter : System.ComponentModel.TypeConver { public MultilineStringConverter() { } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } } @@ -989,6 +1005,7 @@ public NullableConverter(System.Type type) { } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext context, System.Collections.IDictionary propertyValues) { throw null; } public override bool GetCreateInstanceSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(System.ComponentModel.ITypeDescriptorContext context) { throw null; } @@ -1011,11 +1028,11 @@ public PasswordPropertyTextAttribute(bool password) { } } public abstract partial class PropertyDescriptor : System.ComponentModel.MemberDescriptor { - protected PropertyDescriptor(System.ComponentModel.MemberDescriptor descr) : base (default(System.ComponentModel.MemberDescriptor)) { } - protected PropertyDescriptor(System.ComponentModel.MemberDescriptor descr, System.Attribute[] attrs) : base (default(System.ComponentModel.MemberDescriptor)) { } - protected PropertyDescriptor(string name, System.Attribute[] attrs) : base (default(System.ComponentModel.MemberDescriptor)) { } + protected PropertyDescriptor(System.ComponentModel.MemberDescriptor descr) : base (default(string)) { } + protected PropertyDescriptor(System.ComponentModel.MemberDescriptor descr, System.Attribute[] attrs) : base (default(string)) { } + protected PropertyDescriptor(string name, System.Attribute[] attrs) : base (default(string)) { } public abstract System.Type ComponentType { get; } - public virtual System.ComponentModel.TypeConverter Converter { get { throw null; } } + public virtual System.ComponentModel.TypeConverter Converter { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The PropertyDescriptor's PropertyType cannot be statically discovered.")] get { throw null; } } public virtual bool IsLocalizable { get { throw null; } } public abstract bool IsReadOnly { get; } public abstract System.Type PropertyType { get; } @@ -1026,10 +1043,15 @@ public virtual void AddValueChanged(object component, System.EventHandler handle protected object CreateInstance(System.Type type) { throw null; } public override bool Equals(object obj) { throw null; } protected override void FillAttributes(System.Collections.IList attributeList) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The PropertyDescriptor's PropertyType cannot be statically discovered.")] public System.ComponentModel.PropertyDescriptorCollection GetChildProperties() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The PropertyDescriptor's PropertyType cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public System.ComponentModel.PropertyDescriptorCollection GetChildProperties(System.Attribute[] filter) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The PropertyDescriptor's PropertyType cannot be statically discovered. The Type of instance cannot be statically discovered.")] public System.ComponentModel.PropertyDescriptorCollection GetChildProperties(object instance) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The PropertyDescriptor's PropertyType cannot be statically discovered. The Type of instance cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public virtual System.ComponentModel.PropertyDescriptorCollection GetChildProperties(object instance, System.Attribute[] filter) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The PropertyDescriptor's PropertyType cannot be statically discovered.")] public virtual object GetEditor(System.Type editorBaseType) { throw null; } public override int GetHashCode() { throw null; } protected override object GetInvocationTarget(System.Type type, object instance) { throw null; } @@ -1269,8 +1291,11 @@ public TypeConverter() { } protected System.Exception GetConvertToException(object value, System.Type destinationType) { throw null; } public bool GetCreateInstanceSupported() { throw null; } public virtual bool GetCreateInstanceSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of value cannot be statically discovered.")] public System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public virtual System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of value cannot be statically discovered.")] public System.ComponentModel.PropertyDescriptorCollection GetProperties(object value) { throw null; } public bool GetPropertiesSupported() { throw null; } public virtual bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } @@ -1285,8 +1310,8 @@ public TypeConverter() { } protected System.ComponentModel.PropertyDescriptorCollection SortProperties(System.ComponentModel.PropertyDescriptorCollection props, string[] names) { throw null; } protected abstract partial class SimplePropertyDescriptor : System.ComponentModel.PropertyDescriptor { - protected SimplePropertyDescriptor(System.Type componentType, string name, System.Type propertyType) : base (default(System.ComponentModel.MemberDescriptor)) { } - protected SimplePropertyDescriptor(System.Type componentType, string name, System.Type propertyType, System.Attribute[] attributes) : base (default(System.ComponentModel.MemberDescriptor)) { } + protected SimplePropertyDescriptor(System.Type componentType, string name, System.Type propertyType) : base (default(string), default(System.Attribute[])) { } + protected SimplePropertyDescriptor(System.Type componentType, string name, System.Type propertyType, System.Attribute[] attributes) : base (default(string), default(System.Attribute[])) { } public override System.Type ComponentType { get { throw null; } } public override bool IsReadOnly { get { throw null; } } public override System.Type PropertyType { get { throw null; } } @@ -1311,16 +1336,22 @@ protected TypeDescriptionProvider() { } protected TypeDescriptionProvider(System.ComponentModel.TypeDescriptionProvider parent) { } public virtual object CreateInstance(System.IServiceProvider provider, System.Type objectType, System.Type[] argTypes, object[] args) { throw null; } public virtual System.Collections.IDictionary GetCache(object instance) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] public virtual System.ComponentModel.ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) { throw null; } protected internal virtual System.ComponentModel.IExtenderProvider[] GetExtenderProviders(object instance) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public virtual string GetFullComponentName(object component) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("GetReflectionType is not trim compatible because the Type of object cannot be statically discovered.")] public System.Type GetReflectionType(object instance) { throw null; } - public System.Type GetReflectionType(System.Type objectType) { throw null; } - public virtual System.Type GetReflectionType(System.Type objectType, object instance) { throw null; } + [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + public System.Type GetReflectionType([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type objectType) { throw null; } + [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + public virtual System.Type GetReflectionType([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type objectType, object instance) { throw null; } public virtual System.Type GetRuntimeType(System.Type reflectionType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] public System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor(object instance) { throw null; } - public System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor(System.Type objectType) { throw null; } - public virtual System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor(System.Type objectType, object instance) { throw null; } + public System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type objectType) { throw null; } + public virtual System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type objectType, object instance) { throw null; } public virtual bool IsSupportedType(System.Type type) { throw null; } } public sealed partial class TypeDescriptor @@ -1348,65 +1379,93 @@ public static void AddProviderTransparent(System.ComponentModel.TypeDescriptionP public static void AddProviderTransparent(System.ComponentModel.TypeDescriptionProvider provider, System.Type type) { } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static void CreateAssociation(object primary, object secondary) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.Design.IDesigner CreateDesigner(System.ComponentModel.IComponent component, System.Type designerBaseType) { throw null; } public static System.ComponentModel.EventDescriptor CreateEvent(System.Type componentType, System.ComponentModel.EventDescriptor oldEventDescriptor, params System.Attribute[] attributes) { throw null; } public static System.ComponentModel.EventDescriptor CreateEvent(System.Type componentType, string name, System.Type type, params System.Attribute[] attributes) { throw null; } public static object CreateInstance(System.IServiceProvider provider, System.Type objectType, System.Type[] argTypes, object[] args) { throw null; } - public static System.ComponentModel.PropertyDescriptor CreateProperty(System.Type componentType, System.ComponentModel.PropertyDescriptor oldPropertyDescriptor, params System.Attribute[] attributes) { throw null; } - public static System.ComponentModel.PropertyDescriptor CreateProperty(System.Type componentType, string name, System.Type type, params System.Attribute[] attributes) { throw null; } + public static System.ComponentModel.PropertyDescriptor CreateProperty([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType, System.ComponentModel.PropertyDescriptor oldPropertyDescriptor, params System.Attribute[] attributes) { throw null; } + public static System.ComponentModel.PropertyDescriptor CreateProperty([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType, string name, System.Type type, params System.Attribute[] attributes) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static object GetAssociation(System.Type type, object primary) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.AttributeCollection GetAttributes(object component) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.AttributeCollection GetAttributes(object component, bool noCustomTypeDesc) { throw null; } - public static System.ComponentModel.AttributeCollection GetAttributes(System.Type componentType) { throw null; } + public static System.ComponentModel.AttributeCollection GetAttributes([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static string GetClassName(object component) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static string GetClassName(object component, bool noCustomTypeDesc) { throw null; } - public static string GetClassName(System.Type componentType) { throw null; } + public static string GetClassName([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static string GetComponentName(object component) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static string GetComponentName(object component, bool noCustomTypeDesc) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.TypeConverter GetConverter(object component) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.TypeConverter GetConverter(object component, bool noCustomTypeDesc) { throw null; } - public static System.ComponentModel.TypeConverter GetConverter(System.Type type) { throw null; } + public static System.ComponentModel.TypeConverter GetConverter([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.EventDescriptor GetDefaultEvent(object component) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.EventDescriptor GetDefaultEvent(object component, bool noCustomTypeDesc) { throw null; } - public static System.ComponentModel.EventDescriptor GetDefaultEvent(System.Type componentType) { throw null; } + public static System.ComponentModel.EventDescriptor GetDefaultEvent([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.PropertyDescriptor GetDefaultProperty(object component) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.PropertyDescriptor GetDefaultProperty(object component, bool noCustomTypeDesc) { throw null; } - public static System.ComponentModel.PropertyDescriptor GetDefaultProperty(System.Type componentType) { throw null; } + public static System.ComponentModel.PropertyDescriptor GetDefaultProperty([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static object GetEditor(object component, System.Type editorBaseType) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static object GetEditor(object component, System.Type editorBaseType, bool noCustomTypeDesc) { throw null; } - public static object GetEditor(System.Type type, System.Type editorBaseType) { throw null; } + public static object GetEditor([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, System.Type editorBaseType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.EventDescriptorCollection GetEvents(object component) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public static System.ComponentModel.EventDescriptorCollection GetEvents(object component, System.Attribute[] attributes) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public static System.ComponentModel.EventDescriptorCollection GetEvents(object component, System.Attribute[] attributes, bool noCustomTypeDesc) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.EventDescriptorCollection GetEvents(object component, bool noCustomTypeDesc) { throw null; } - public static System.ComponentModel.EventDescriptorCollection GetEvents(System.Type componentType) { throw null; } - public static System.ComponentModel.EventDescriptorCollection GetEvents(System.Type componentType, System.Attribute[] attributes) { throw null; } + public static System.ComponentModel.EventDescriptorCollection GetEvents([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] + public static System.ComponentModel.EventDescriptorCollection GetEvents([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType, System.Attribute[] attributes) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static string GetFullComponentName(object component) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.PropertyDescriptorCollection GetProperties(object component) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public static System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, System.Attribute[] attributes) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of component cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public static System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, System.Attribute[] attributes, bool noCustomTypeDesc) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, bool noCustomTypeDesc) { throw null; } - public static System.ComponentModel.PropertyDescriptorCollection GetProperties(System.Type componentType) { throw null; } - public static System.ComponentModel.PropertyDescriptorCollection GetProperties(System.Type componentType, System.Attribute[] attributes) { throw null; } + public static System.ComponentModel.PropertyDescriptorCollection GetProperties([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] + public static System.ComponentModel.PropertyDescriptorCollection GetProperties([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type componentType, System.Attribute[] attributes) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.ComponentModel.TypeDescriptionProvider GetProvider(object instance) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] public static System.ComponentModel.TypeDescriptionProvider GetProvider(System.Type type) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("GetReflectionType is not trim compatible because the Type of object cannot be statically discovered.")] public static System.Type GetReflectionType(object instance) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - public static System.Type GetReflectionType(System.Type type) { throw null; } + [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] + public static System.Type GetReflectionType([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicFields | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type type) { throw null; } public static void Refresh(object component) { } public static void Refresh(System.Reflection.Assembly assembly) { } public static void Refresh(System.Reflection.Module module) { } @@ -1553,7 +1612,9 @@ protected DesignerOptionService() { } protected System.ComponentModel.Design.DesignerOptionService.DesignerOptionCollection CreateOptionCollection(System.ComponentModel.Design.DesignerOptionService.DesignerOptionCollection parent, string name, object value) { throw null; } protected virtual void PopulateOptionCollection(System.ComponentModel.Design.DesignerOptionService.DesignerOptionCollection options) { } protected virtual bool ShowDialog(System.ComponentModel.Design.DesignerOptionService.DesignerOptionCollection options, object optionObject) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The option value's Type cannot be statically discovered.")] object System.ComponentModel.Design.IDesignerOptionService.GetOptionValue(string pageName, string valueName) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The option value's Type cannot be statically discovered.")] void System.ComponentModel.Design.IDesignerOptionService.SetOptionValue(string pageName, string valueName, object value) { } [System.ComponentModel.EditorAttribute("", "System.Drawing.Design.UITypeEditor, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] public sealed partial class DesignerOptionCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList @@ -1564,7 +1625,7 @@ internal DesignerOptionCollection() { } public System.ComponentModel.Design.DesignerOptionService.DesignerOptionCollection this[string name] { get { throw null; } } public string Name { get { throw null; } } public System.ComponentModel.Design.DesignerOptionService.DesignerOptionCollection Parent { get { throw null; } } - public System.ComponentModel.PropertyDescriptorCollection Properties { get { throw null; } } + public System.ComponentModel.PropertyDescriptorCollection Properties { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The Type of DesignerOptionCollection's value cannot be statically discovered.")] get { throw null; } } bool System.Collections.ICollection.IsSynchronized { get { throw null; } } object System.Collections.ICollection.SyncRoot { get { throw null; } } bool System.Collections.IList.IsFixedSize { get { throw null; } } @@ -1747,7 +1808,9 @@ public partial interface IDesignerHostTransactionState } public partial interface IDesignerOptionService { + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The option value's Type cannot be statically discovered.")] object GetOptionValue(string pageName, string valueName); + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The option value's Type cannot be statically discovered.")] void SetOptionValue(string pageName, string valueName, object value); } public partial interface IDictionaryService @@ -2175,6 +2238,7 @@ public PointConverter() { } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext context, System.Collections.IDictionary propertyValues) { throw null; } public override bool GetCreateInstanceSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } } @@ -2187,6 +2251,7 @@ public RectangleConverter() { } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext context, System.Collections.IDictionary propertyValues) { throw null; } public override bool GetCreateInstanceSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } } @@ -2199,6 +2264,7 @@ public SizeConverter() { } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext context, System.Collections.IDictionary propertyValues) { throw null; } public override bool GetCreateInstanceSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } } @@ -2211,6 +2277,7 @@ public SizeFConverter() { } public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) { throw null; } public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext context, System.Collections.IDictionary propertyValues) { throw null; } public override bool GetCreateInstanceSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The Type of value cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) { throw null; } public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) { throw null; } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.xml index d0db9830e3e59..558d9f107eb5a 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.xml @@ -145,18 +145,6 @@ member M:System.ComponentModel.ReflectTypeDescriptionProvider.CreateInstance(System.Type,System.Type) - - ILLink - IL2070 - member - M:System.ComponentModel.ReflectTypeDescriptionProvider.ReflectGetEvents(System.Type) - - - ILLink - IL2070 - member - M:System.ComponentModel.ReflectTypeDescriptionProvider.ReflectGetProperties(System.Type) - ILLink IL2072 @@ -175,131 +163,119 @@ member M:System.ComponentModel.TypeDescriptor.ComNativeDescriptorProxy.#ctor - - ILLink - IL2072 - member - M:System.ComponentModel.TypeDescriptor.CreateDesigner(System.ComponentModel.IComponent,System.Type) - ILLink IL2075 member - M:System.ComponentModel.AttributeCollection.GetDefaultAttribute(System.Type) + M:System.ComponentModel.NullableConverter.ConvertTo(System.ComponentModel.ITypeDescriptorContext,System.Globalization.CultureInfo,System.Object,System.Type) ILLink IL2075 member - M:System.ComponentModel.ComponentResourceManager.ApplyResources(System.Object,System.String,System.Globalization.CultureInfo) + M:System.ComponentModel.ReflectEventDescriptor.FillEventInfoAttribute(System.Reflection.EventInfo,System.Collections.IList) ILLink IL2075 member - M:System.ComponentModel.EnumConverter.ConvertTo(System.ComponentModel.ITypeDescriptorContext,System.Globalization.CultureInfo,System.Object,System.Type) + M:System.ComponentModel.ReflectEventDescriptor.FillMethods ILLink IL2075 member - M:System.ComponentModel.EnumConverter.GetStandardValues(System.ComponentModel.ITypeDescriptorContext) + M:System.ComponentModel.ReflectEventDescriptor.FillSingleMethodAttribute(System.Reflection.MethodInfo,System.Collections.IList) ILLink IL2075 member - M:System.ComponentModel.NullableConverter.ConvertTo(System.ComponentModel.ITypeDescriptorContext,System.Globalization.CultureInfo,System.Object,System.Type) + M:System.ComponentModel.ReflectPropertyDescriptor.FillAttributes(System.Collections.IList) ILLink IL2075 member - M:System.ComponentModel.ReflectEventDescriptor.FillEventInfoAttribute(System.Reflection.EventInfo,System.Collections.IList) + M:System.ComponentModel.ReflectPropertyDescriptor.get_SetMethodValue ILLink IL2075 member - M:System.ComponentModel.ReflectEventDescriptor.FillMethods + M:System.ComponentModel.ReflectTypeDescriptionProvider.GetIntrinsicTypeEditor(System.Collections.Hashtable,System.Type) ILLink - IL2075 + IL2080 member - M:System.ComponentModel.ReflectEventDescriptor.FillSingleMethodAttribute(System.Reflection.MethodInfo,System.Collections.IList) + M:System.ComponentModel.ReflectEventDescriptor.FillMethods ILLink - IL2075 + IL2080 member M:System.ComponentModel.ReflectPropertyDescriptor.FillAttributes(System.Collections.IList) ILLink - IL2075 + IL2080 member M:System.ComponentModel.ReflectPropertyDescriptor.get_SetMethodValue ILLink - IL2075 - member - M:System.ComponentModel.ReflectTypeDescriptionProvider.GetIntrinsicTypeEditor(System.Collections.Hashtable,System.Type) - - - ILLink - IL2075 + IL2026 member - M:System.ComponentModel.ReflectTypeDescriptionProvider.ReflectGetExtendedProperties(System.ComponentModel.IExtenderProvider) + M:System.ComponentModel.Design.DesigntimeLicenseContextSerializer.Deserialize(System.IO.Stream,System.String,System.ComponentModel.Design.RuntimeLicenseContext) ILLink - IL2080 + IL2026 member - M:System.ComponentModel.ReflectEventDescriptor.FillMethods + M:System.ComponentModel.Design.DesigntimeLicenseContextSerializer.Serialize(System.IO.Stream,System.String,System.ComponentModel.Design.DesigntimeLicenseContext) ILLink - IL2080 + IL2026 member - M:System.ComponentModel.ReflectPropertyDescriptor.FillAttributes(System.Collections.IList) + M:System.ComponentModel.TypeDescriptor.TypeDescriptionNode.DefaultTypeDescriptor.System#ComponentModel#ICustomTypeDescriptor#GetConverter ILLink - IL2080 + IL2026 member - M:System.ComponentModel.ReflectPropertyDescriptor.get_GetMethodValue + M:System.ComponentModel.TypeDescriptor.TypeDescriptionNode.DefaultTypeDescriptor.System#ComponentModel#ICustomTypeDescriptor#GetDefaultEvent ILLink - IL2080 + IL2026 member - M:System.ComponentModel.ReflectPropertyDescriptor.get_SetMethodValue + M:System.ComponentModel.TypeDescriptor.TypeDescriptionNode.DefaultTypeDescriptor.System#ComponentModel#ICustomTypeDescriptor#GetDefaultProperty ILLink - IL2087 + IL2026 member - M:System.ComponentModel.BindingList`1.AddNewCore + M:System.ComponentModel.TypeDescriptor.TypeDescriptionNode.DefaultTypeDescriptor.System#ComponentModel#ICustomTypeDescriptor#GetEditor(System.Type) ILLink - IL2090 + IL2062 member - M:System.ComponentModel.BindingList`1.get_ItemTypeHasDefaultConstructor + M:System.ComponentModel.ReflectTypeDescriptionProvider.ReflectedTypeData.GetAttributes ILLink - IL2026 + IL2072 member - M:System.ComponentModel.Design.DesigntimeLicenseContextSerializer.Deserialize(System.IO.Stream,System.String,System.ComponentModel.Design.RuntimeLicenseContext) + M:System.ComponentModel.NullableConverter.#ctor(System.Type) ILLink - IL2026 + IL2072 member - M:System.ComponentModel.Design.DesigntimeLicenseContextSerializer.Serialize(System.IO.Stream,System.String,System.ComponentModel.Design.DesigntimeLicenseContext) + M:System.ComponentModel.ReflectPropertyDescriptor.FillAttributes(System.Collections.IList) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/MS/Internal/Xml/Linq/ComponentModel/XComponentModel.cs b/src/libraries/System.ComponentModel.TypeConverter/src/MS/Internal/Xml/Linq/ComponentModel/XComponentModel.cs index 9b98716a366c3..d59b6b60c4d1e 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/MS/Internal/Xml/Linq/ComponentModel/XComponentModel.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/MS/Internal/Xml/Linq/ComponentModel/XComponentModel.cs @@ -5,6 +5,7 @@ using System.Collections; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Xml.Linq; @@ -16,7 +17,7 @@ public XTypeDescriptionProvider() : base(TypeDescriptor.GetProvider(typeof(T))) { } - public override ICustomTypeDescriptor GetTypeDescriptor(Type type, object instance) + public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, object instance) { return new XTypeDescriptor(base.GetTypeDescriptor(type, instance)); } @@ -28,11 +29,14 @@ public XTypeDescriptor(ICustomTypeDescriptor parent) : base(parent) { } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "No attributes are supplied.")] public override PropertyDescriptorCollection GetProperties() { return GetProperties(null); } + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) { PropertyDescriptorCollection properties = new PropertyDescriptorCollection(null); diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs index d592d19730531..76e19ce56ab10 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AmbientValueAttribute.cs @@ -17,7 +17,7 @@ public sealed class AmbientValueAttribute : Attribute /// specified value to the specified type, and using the U.S. English culture as the /// translation context. /// - public AmbientValueAttribute(Type type, string value) + public AmbientValueAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string value) { // The try/catch here is because attributes should never throw exceptions. We would fail to // load an otherwise normal class. diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ArrayConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ArrayConverter.cs index 0405be41d76d7..c7a0b666fd5a2 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ArrayConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ArrayConverter.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace System.ComponentModel @@ -27,6 +28,7 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul /// /// Gets a collection of properties for the type of array specified by the value parameter. /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { if (value == null) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeCollection.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeCollection.cs index 0bfda008e58a8..31fac2df2488e 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeCollection.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/AttributeCollection.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Collections; +using System.Diagnostics.CodeAnalysis; namespace System.ComponentModel { @@ -11,6 +12,8 @@ namespace System.ComponentModel /// public class AttributeCollection : ICollection, IEnumerable { + internal const string FilterRequiresUnreferencedCodeMessage = "The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type."; + /// /// An empty AttributeCollection that can used instead of creating a new one. /// @@ -132,7 +135,7 @@ public static AttributeCollection FromExisting(AttributeCollection existing, par /// /// Gets the attribute with the specified type. /// - public virtual Attribute this[Type attributeType] + public virtual Attribute this[[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields)] Type attributeType] { get { @@ -215,6 +218,7 @@ public virtual Attribute this[Type attributeType] /// /// Determines if this collection of attributes has the specified attribute. /// + [RequiresUnreferencedCode(FilterRequiresUnreferencedCodeMessage)] public bool Contains(Attribute attribute) { if (attribute == null) @@ -230,6 +234,7 @@ public bool Contains(Attribute attribute) /// Determines if this attribute collection contains the all /// the specified attributes in the attribute array. /// + [RequiresUnreferencedCode(FilterRequiresUnreferencedCodeMessage)] public bool Contains(Attribute[] attributes) { if (attributes == null) @@ -252,7 +257,7 @@ public bool Contains(Attribute[] attributes) /// Returns the default value for an attribute. This uses the following heuristic: /// 1. It looks for a public static field named "Default". /// - protected Attribute GetDefaultAttribute(Type attributeType) + protected Attribute GetDefaultAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields)] Type attributeType) { if (attributeType == null) { diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindingList.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindingList.cs index de3d0e2f80afb..6f6925308b50d 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindingList.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/BindingList.cs @@ -1,18 +1,19 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; -using System.Collections.ObjectModel; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Reflection; using System.Runtime.CompilerServices; namespace System.ComponentModel { [Serializable] [TypeForwardedFrom("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public class BindingList : Collection, IBindingList, ICancelAddNew, IRaiseItemChangedEvents + public class BindingList<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T> : + Collection, IBindingList, ICancelAddNew, IRaiseItemChangedEvents { private int addNewPos = -1; // Do not rename (binary serialization) private bool raiseListChangedEvents = true; // Do not rename (binary serialization) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CollectionConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CollectionConverter.cs index 67a92b573e889..d78d0142489b1 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CollectionConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CollectionConverter.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; +using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace System.ComponentModel @@ -29,6 +30,7 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul /// Gets a collection of properties for the type of array specified by the value /// parameter using the specified context and attributes. /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { return new PropertyDescriptorCollection(null); diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentConverter.cs index 097cc3f67fb6c..23f8591136cf6 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentConverter.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -20,6 +22,7 @@ public ComponentConverter(Type type) : base(type) /// Gets a collection of properties for the type of component /// specified by the value parameter. /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { return TypeDescriptor.GetProperties(value, attributes); diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs index 034be51fafca7..88f6bcf92ac92 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ComponentResourceManager.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; using System.Resources; @@ -51,6 +52,7 @@ private CultureInfo NeutralResourcesCulture /// to the corresponding property on the object. If there is no matching /// property the resource will be ignored. /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered.")] public void ApplyResources(object value, string objectName) => ApplyResources(value, objectName, null); /// @@ -60,6 +62,7 @@ private CultureInfo NeutralResourcesCulture /// to the corresponding property on the object. If there is no matching /// property the resource will be ignored. /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered.")] public virtual void ApplyResources(object value, string objectName, CultureInfo culture) { if (value == null) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs index cc0a8015d7924..d966c032c4eaa 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Container.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -22,6 +24,7 @@ public class Container : IContainer /// Adds the specified component to the /// The component is unnamed. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "No name is provided.")] public virtual void Add(IComponent component) => Add(component, null); // Adds a component to the container. @@ -29,6 +32,7 @@ public class Container : IContainer /// Adds the specified component to the and assigns /// a name to it. /// + [RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered to validate the name.")] public virtual void Add(IComponent component, string name) { lock (_syncObj) @@ -212,6 +216,7 @@ private void Remove(IComponent component, bool preserveSite) /// verifies that name is either null or unique compared to the names of other /// components in the container. /// + [RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered.")] protected virtual void ValidateName(IComponent component, string name) { if (component == null) @@ -274,6 +279,7 @@ public object GetService(Type service) public string Name { get => _name; + [RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered to validate the name.")] set { if (value == null || _name == null || !value.Equals(_name)) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs index 79d0e80b3dd0b..fd6e5f7167774 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/CustomTypeDescriptor.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { public abstract class CustomTypeDescriptor : ICustomTypeDescriptor @@ -119,6 +121,7 @@ public virtual EventDescriptorCollection GetEvents() /// returned. If no parent is provided,this will return an empty /// event collection. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public virtual EventDescriptorCollection GetEvents(Attribute[] attributes) { if (_parent != null) @@ -153,6 +156,7 @@ public virtual PropertyDescriptorCollection GetProperties() /// If no parent is provided,this will return an empty /// property collection. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public virtual PropertyDescriptorCollection GetProperties(Attribute[] attributes) { if (_parent != null) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs index 6c3f604720579..5e05f31d18b22 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/DelegatingTypeDescriptionProvider.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; +using System.Diagnostics.CodeAnalysis; namespace System.ComponentModel { @@ -58,6 +59,7 @@ public override object CreateInstance(IServiceProvider provider, Type objectType /// If not overridden, the default implementation of this method will call /// GetTypeDescriptor.GetComponentName. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public override string GetFullComponentName(object component) => Provider.GetFullComponentName(component); /// @@ -74,6 +76,7 @@ public override object CreateInstance(IServiceProvider provider, Type objectType /// model only supports extended properties this API can be used for extended /// attributes and events as well, if the type description provider supports it. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) { return Provider.GetExtendedTypeDescriptor(instance); @@ -89,7 +92,10 @@ protected internal override IExtenderProvider[] GetExtenderProviders(object inst /// If no custom type descriptor can be located for an object, GetReflection /// is called to perform normal reflection against the object. /// - public override Type GetReflectionType(Type objectType, object instance) + [return: DynamicallyAccessedMembers(TypeDescriptor.ReflectTypesDynamicallyAccessedMembers)] + public override Type GetReflectionType( + [DynamicallyAccessedMembers(TypeDescriptor.ReflectTypesDynamicallyAccessedMembers)] Type objectType, + object instance) { return Provider.GetReflectionType(objectType, instance); } @@ -104,7 +110,7 @@ public override Type GetReflectionType(Type objectType, object instance) /// interested in providing type information for the object it should /// return null. /// - public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) + public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, object instance) { return Provider.GetTypeDescriptor(objectType, instance); } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs index 3c19b44028fcc..490dded91c36a 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesignerOptionService.cs @@ -56,6 +56,7 @@ protected DesignerOptionCollection CreateOptionCollection(DesignerOptionCollecti /// Retrieves the property descriptor for the given page / value name. Returns /// null if the property couldn't be found. /// + [RequiresUnreferencedCode("The Type of DesignerOptionCollection's value cannot be statically discovered.")] private PropertyDescriptor GetOptionProperty(string pageName, string valueName) { if (pageName == null) @@ -99,6 +100,7 @@ protected virtual void PopulateOptionCollection(DesignerOptionCollection options /// /// Gets the value of an option defined in this package. /// + [RequiresUnreferencedCode("The option value's Type cannot be statically discovered.")] object IDesignerOptionService.GetOptionValue(string pageName, string valueName) { PropertyDescriptor optionProp = GetOptionProperty(pageName, valueName); @@ -108,6 +110,7 @@ object IDesignerOptionService.GetOptionValue(string pageName, string valueName) /// /// Sets the value of an option defined in this package. /// + [RequiresUnreferencedCode("The option value's Type cannot be statically discovered.")] void IDesignerOptionService.SetOptionValue(string pageName, string valueName, object value) { PropertyDescriptor optionProp = GetOptionProperty(pageName, valueName); @@ -185,6 +188,7 @@ public int Count /// public PropertyDescriptorCollection Properties { + [RequiresUnreferencedCode("The Type of DesignerOptionCollection's value cannot be statically discovered.")] get { if (_properties == null) @@ -450,6 +454,7 @@ internal sealed class DesignerOptionConverter : TypeConverter { public override bool GetPropertiesSupported(ITypeDescriptorContext cxt) => true; + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext cxt, object value, Attribute[] attributes) { PropertyDescriptorCollection props = new PropertyDescriptorCollection(null); diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerOptionService.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerOptionService.cs index 7b4326e132494..49909f5327cdd 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerOptionService.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/IDesignerOptionService.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel.Design { /// @@ -11,11 +13,13 @@ public interface IDesignerOptionService /// /// Gets the value of an option defined in this package. /// + [RequiresUnreferencedCode("The option value's Type cannot be statically discovered.")] object GetOptionValue(string pageName, string valueName); /// /// Sets the value of an option defined in this package. /// + [RequiresUnreferencedCode("The option value's Type cannot be statically discovered.")] void SetOptionValue(string pageName, string valueName, object value); } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs index 52f691564f215..463b159310b81 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs @@ -122,22 +122,29 @@ protected virtual void SetRelationship(MemberRelationship source, MemberRelation { if (!relationship.IsEmpty && !SupportsRelationship(source, relationship)) { - string sourceName = TypeDescriptor.GetComponentName(source.Owner); - string relName = TypeDescriptor.GetComponentName(relationship.Owner); - if (sourceName == null) - { - sourceName = source.Owner.ToString(); - } - if (relName == null) - { - relName = relationship.Owner.ToString(); - } - throw new ArgumentException(SR.Format(SR.MemberRelationshipService_RelationshipNotSupported, sourceName, source.Member.Name, relName, relationship.Member.Name)); + ThrowRelationshipNotSupported(source, relationship); } _relationships[new RelationshipEntry(source)] = new RelationshipEntry(relationship); } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "GetComponentName is only used to create a nice exception message, and has a fallback when null is returned.")] + private static void ThrowRelationshipNotSupported(MemberRelationship source, MemberRelationship relationship) + { + string sourceName = TypeDescriptor.GetComponentName(source.Owner); + string relName = TypeDescriptor.GetComponentName(relationship.Owner); + if (sourceName == null) + { + sourceName = source.Owner.ToString(); + } + if (relName == null) + { + relName = relationship.Owner.ToString(); + } + throw new ArgumentException(SR.Format(SR.MemberRelationshipService_RelationshipNotSupported, sourceName, source.Member.Name, relName, relationship.Member.Name)); + } + /// /// Returns true if the provided relationship is supported. /// diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs index 38c7932c1653b..8820290a6e9d1 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Generic; using System.ComponentModel.Design.Serialization; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; @@ -19,11 +20,12 @@ public class EnumConverter : TypeConverter /// Initializes a new instance of the class for the given /// type. /// - public EnumConverter(Type type) + public EnumConverter([DynamicallyAccessedMembers(TypeDescriptor.ReflectTypesDynamicallyAccessedMembers)] Type type) { EnumType = type; } + [DynamicallyAccessedMembers(TypeDescriptor.ReflectTypesDynamicallyAccessedMembers)] protected Type EnumType { get; } protected StandardValuesCollection Values { get; set; } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExpandableObjectConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExpandableObjectConverter.cs index 294a894a75f86..53cf1494d03de 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExpandableObjectConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ExpandableObjectConverter.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -20,6 +22,7 @@ public ExpandableObjectConverter() /// Gets a collection of properties for the type of object /// specified by the value parameter. /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { return TypeDescriptor.GetProperties(value, attributes); diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ICustomTypeDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ICustomTypeDescriptor.cs index b9849a371d168..f194821f7d36f 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ICustomTypeDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ICustomTypeDescriptor.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.ComponentModel { /// @@ -53,6 +55,7 @@ public interface ICustomTypeDescriptor /// Gets the events for this instance of a component using the attribute array as a /// filter. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] EventDescriptorCollection GetEvents(Attribute[] attributes); /// @@ -63,6 +66,7 @@ public interface ICustomTypeDescriptor /// /// Gets the properties for this instance of a component using the attribute array as a filter. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] PropertyDescriptorCollection GetProperties(Attribute[] attributes); /// diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MultilineStringConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MultilineStringConverter.cs index 735b4799cb573..65db30246f3fd 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MultilineStringConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MultilineStringConverter.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace System.ComponentModel @@ -32,6 +33,7 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul /// Gets a collection of properties for the type of array specified by the value /// parameter using the specified context and attributes. /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { return null; diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NestedContainer.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NestedContainer.cs index 21e3b57861c5c..0261be604f3ed 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NestedContainer.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NestedContainer.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace System.ComponentModel @@ -160,6 +161,7 @@ public string FullName public string Name { get => _name; + [RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered to validate the name.")] set { if (value == null || _name == null || !value.Equals(_name)) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs index e5eb919d6eaa3..336015c00986c 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/NullableConverter.cs @@ -4,6 +4,7 @@ using System.Collections; using System.ComponentModel.Design.Serialization; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; @@ -158,6 +159,7 @@ public override bool GetCreateInstanceSupported(ITypeDescriptorContext context) /// Gets a collection of properties for the type of array specified by the value /// parameter using the specified context and attributes. /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { if (UnderlyingTypeConverter != null) diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs index 3f8d7047ad670..c9381b807aa61 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/PropertyDescriptor.cs @@ -57,6 +57,7 @@ protected PropertyDescriptor(MemberDescriptor descr, Attribute[] attrs) : base(d /// public virtual TypeConverter Converter { + [RequiresUnreferencedCode("The PropertyDescriptor's PropertyType cannot be statically discovered.")] get { // Always grab the attribute collection first here, because if the metadata version @@ -212,15 +213,19 @@ protected override void FillAttributes(IList attributeList) base.FillAttributes(attributeList); } + [RequiresUnreferencedCode("The PropertyDescriptor's PropertyType cannot be statically discovered.")] public PropertyDescriptorCollection GetChildProperties() => GetChildProperties(null, null); + [RequiresUnreferencedCode("The PropertyDescriptor's PropertyType cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public PropertyDescriptorCollection GetChildProperties(Attribute[] filter) => GetChildProperties(null, filter); + [RequiresUnreferencedCode("The PropertyDescriptor's PropertyType cannot be statically discovered. The Type of instance cannot be statically discovered.")] public PropertyDescriptorCollection GetChildProperties(object instance) => GetChildProperties(instance, null); /// /// Retrieves the properties /// + [RequiresUnreferencedCode("The PropertyDescriptor's PropertyType cannot be statically discovered. The Type of instance cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public virtual PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter) { if (instance == null) @@ -233,10 +238,10 @@ public virtual PropertyDescriptorCollection GetChildProperties(object instance, } } - /// /// Gets an editor of the specified type. /// + [RequiresUnreferencedCode("The PropertyDescriptor's PropertyType cannot be statically discovered.")] public virtual object GetEditor(Type editorBaseType) { object editor = null; diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs index 975804a488169..49517569e9648 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectPropertyDescriptor.cs @@ -4,6 +4,7 @@ using System.Collections; using System.ComponentModel.Design; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; @@ -59,6 +60,7 @@ internal sealed class ReflectPropertyDescriptor : PropertyDescriptor private static readonly int s_bitSetOnDemand = InterlockedBitVector32.CreateMask(s_bitAmbientValueQueried); private InterlockedBitVector32 _state; // Contains the state bits for this proeprty descriptor. + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] private readonly Type _componentClass; // used to determine if we should all on us or on the designer private readonly Type _type; // the data type of the property private object _defaultValue; // the default value of the property (or noValue) @@ -75,7 +77,11 @@ internal sealed class ReflectPropertyDescriptor : PropertyDescriptor /// /// The main constructor for ReflectPropertyDescriptors. /// - public ReflectPropertyDescriptor(Type componentClass, string name, Type type, Attribute[] attributes) + public ReflectPropertyDescriptor( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentClass, + string name, + Type type, + Attribute[] attributes) : base(name, attributes) { Debug.WriteLine($"Creating ReflectPropertyDescriptor for {componentClass?.FullName}.{name}"); @@ -106,7 +112,15 @@ public ReflectPropertyDescriptor(Type componentClass, string name, Type type, At /// /// A constructor for ReflectPropertyDescriptors that have no attributes. /// - public ReflectPropertyDescriptor(Type componentClass, string name, Type type, PropertyInfo propInfo, MethodInfo getMethod, MethodInfo setMethod, Attribute[] attrs) : this(componentClass, name, type, attrs) + public ReflectPropertyDescriptor( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentClass, + string name, + Type type, + PropertyInfo propInfo, + MethodInfo getMethod, + MethodInfo setMethod, + Attribute[] attrs) + : this(componentClass, name, type, attrs) { _propInfo = propInfo; _getMethod = getMethod; @@ -120,7 +134,15 @@ public ReflectPropertyDescriptor(Type componentClass, string name, Type type, Pr /// /// A constructor for ReflectPropertyDescriptors that creates an extender property. /// - public ReflectPropertyDescriptor(Type componentClass, string name, Type type, Type receiverType, MethodInfo getMethod, MethodInfo setMethod, Attribute[] attrs) : this(componentClass, name, type, attrs) + public ReflectPropertyDescriptor( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentClass, + string name, + Type type, + Type receiverType, + MethodInfo getMethod, + MethodInfo setMethod, + Attribute[] attrs) + : this(componentClass, name, type, attrs) { _receiverType = receiverType; _getMethod = getMethod; @@ -132,7 +154,10 @@ public ReflectPropertyDescriptor(Type componentClass, string name, Type type, Ty /// This constructor takes an existing ReflectPropertyDescriptor and modifies it by merging in the /// passed-in attributes. /// - public ReflectPropertyDescriptor(Type componentClass, PropertyDescriptor oldReflectPropertyDescriptor, Attribute[] attributes) + public ReflectPropertyDescriptor( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentClass, + PropertyDescriptor oldReflectPropertyDescriptor, + Attribute[] attributes) : base(oldReflectPropertyDescriptor, attributes) { _componentClass = componentClass; @@ -221,7 +246,7 @@ private EventDescriptor ChangedEventValue { if (!_state[s_bitChangedQueried]) { - _realChangedEvent = TypeDescriptor.GetEvents(ComponentType)[Name + "Changed"]; + _realChangedEvent = TypeDescriptor.GetEvents(_componentClass)[Name + "Changed"]; _state[s_bitChangedQueried] = true; } @@ -639,7 +664,7 @@ internal bool ExtenderShouldSerializeValue(IExtenderProvider provider, object co } catch { } } - return Attributes.Contains(DesignerSerializationVisibilityAttribute.Content); + return AttributesContainsDesignerVisibilityContent(); } else if (DefaultValue == s_noValue) { @@ -656,6 +681,10 @@ internal bool ExtenderShouldSerializeValue(IExtenderProvider provider, object co return !Equals(DefaultValue, ExtenderGetValue(provider, component)); } + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields, typeof(DesignerSerializationVisibilityAttribute))] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The DynamicDependency ensures the correct members are preserved.")] + private bool AttributesContainsDesignerVisibilityContent() => Attributes.Contains(DesignerSerializationVisibilityAttribute.Content); + /// /// Indicates whether reset will change the value of the component. If there /// is a DefaultValueAttribute, then this will return true if getValue returns @@ -1139,7 +1168,7 @@ public override bool ShouldSerializeValue(object component) } catch { } } - return Attributes.Contains(DesignerSerializationVisibilityAttribute.Content); + return AttributesContainsDesignerVisibilityContent(); } else if (DefaultValue == s_noValue) { diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs index 4b474040f09d7..3ddd16dd19ea1 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.ReflectedTypeData.cs @@ -3,8 +3,8 @@ using System.Collections; using System.Collections.Generic; -using System.Collections.Specialized; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace System.ComponentModel @@ -17,6 +17,7 @@ internal sealed partial class ReflectTypeDescriptionProvider : TypeDescriptionPr /// private class ReflectedTypeData { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] private readonly Type _type; private AttributeCollection _attributes; private EventDescriptorCollection _events; @@ -26,7 +27,7 @@ private class ReflectedTypeData private Type[] _editorTypes; private int _editorCount; - internal ReflectedTypeData(Type type) + internal ReflectedTypeData([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { _type = type; } @@ -169,6 +170,7 @@ internal string GetComponentName(object instance) /// it will be used to retrieve attributes. Otherwise, _type /// will be used. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] internal TypeConverter GetConverter(object instance) { TypeConverterAttribute typeAttr = null; @@ -225,6 +227,7 @@ internal TypeConverter GetConverter(object instance) /// Return the default event. The default event is determined by the /// presence of a DefaultEventAttribute on the class. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] internal EventDescriptor GetDefaultEvent(object instance) { AttributeCollection attributes; @@ -257,6 +260,7 @@ internal EventDescriptor GetDefaultEvent(object instance) /// /// Return the default property. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] internal PropertyDescriptor GetDefaultProperty(object instance) { AttributeCollection attributes; @@ -289,6 +293,7 @@ internal PropertyDescriptor GetDefaultProperty(object instance) /// /// Retrieves the editor for the given base type. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] internal object GetEditor(object instance, Type editorBaseType) { EditorAttribute typeAttr; diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs index d8de50a61aeec..c2a136f65d5c7 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.ComponentModel.Design; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Reflection; @@ -172,11 +173,19 @@ private static Dictionary IntrinsicTypeConve // [typeof(Array)] = new IntrinsicTypeConverterData((type) => new ArrayConverter()), [typeof(ICollection)] = new IntrinsicTypeConverterData((type) => new CollectionConverter()), - [typeof(Enum)] = new IntrinsicTypeConverterData((type) => new EnumConverter(type), cacheConverterInstance: false), + [typeof(Enum)] = new IntrinsicTypeConverterData((type) => CreateEnumConverter(type), cacheConverterInstance: false), [s_intrinsicNullableKey] = new IntrinsicTypeConverterData((type) => new NullableConverter(type), cacheConverterInstance: false), [s_intrinsicReferenceKey] = new IntrinsicTypeConverterData((type) => new ReferenceConverter(type), cacheConverterInstance: false), }); + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", + Justification = "Trimmer does not trim enums")] + private static EnumConverter CreateEnumConverter(Type type) + { + Debug.Assert(type.IsEnum || type == typeof(Enum)); + return new EnumConverter(type); + } + private static Hashtable PropertyCache => LazyInitializer.EnsureInitialized(ref s_propertyCache, () => new Hashtable()); private static Hashtable EventCache => LazyInitializer.EnsureInitialized(ref s_eventCache, () => new Hashtable()); @@ -271,7 +280,7 @@ private static object CreateInstance(Type objectType, Type callingType) /// /// Retrieves custom attributes. /// - internal AttributeCollection GetAttributes(Type type) + internal AttributeCollection GetAttributes([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { ReflectedTypeData td = GetTypeData(type, true); return td.GetAttributes(); @@ -304,7 +313,7 @@ public override IDictionary GetCache(object instance) /// /// Retrieves the class name for our type. /// - internal string GetClassName(Type type) + internal string GetClassName([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { ReflectedTypeData td = GetTypeData(type, true); return td.GetClassName(null); @@ -313,7 +322,7 @@ internal string GetClassName(Type type) /// /// Retrieves the component name from the site. /// - internal string GetComponentName(Type type, object instance) + internal string GetComponentName([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, object instance) { ReflectedTypeData td = GetTypeData(type, true); return td.GetComponentName(instance); @@ -324,7 +333,8 @@ internal string GetComponentName(Type type, object instance) /// it will be used to retrieve attributes. Otherwise, _type /// will be used. /// - internal TypeConverter GetConverter(Type type, object instance) + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] + internal TypeConverter GetConverter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, object instance) { ReflectedTypeData td = GetTypeData(type, true); return td.GetConverter(instance); @@ -334,7 +344,8 @@ internal TypeConverter GetConverter(Type type, object instance) /// Return the default event. The default event is determined by the /// presence of a DefaultEventAttribute on the class. /// - internal EventDescriptor GetDefaultEvent(Type type, object instance) + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] + internal EventDescriptor GetDefaultEvent([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, object instance) { ReflectedTypeData td = GetTypeData(type, true); return td.GetDefaultEvent(instance); @@ -343,7 +354,8 @@ internal EventDescriptor GetDefaultEvent(Type type, object instance) /// /// Return the default property. /// - internal PropertyDescriptor GetDefaultProperty(Type type, object instance) + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] + internal PropertyDescriptor GetDefaultProperty([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, object instance) { ReflectedTypeData td = GetTypeData(type, true); return td.GetDefaultProperty(instance); @@ -352,7 +364,8 @@ internal PropertyDescriptor GetDefaultProperty(Type type, object instance) /// /// Retrieves the editor for the given base type. /// - internal object GetEditor(Type type, object instance, Type editorBaseType) + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] + internal object GetEditor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, object instance, Type editorBaseType) { ReflectedTypeData td = GetTypeData(type, true); return td.GetEditor(instance, editorBaseType); @@ -407,7 +420,7 @@ private static Hashtable GetEditorTable(Type editorBaseType) /// /// Retrieves the events for this type. /// - internal EventDescriptorCollection GetEvents(Type type) + internal EventDescriptorCollection GetEvents([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { ReflectedTypeData td = GetTypeData(type, true); return td.GetEvents(); @@ -425,6 +438,7 @@ internal AttributeCollection GetExtendedAttributes(object instance) /// /// Retrieves the class name for our type. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] internal string GetExtendedClassName(object instance) { return GetClassName(instance.GetType()); @@ -433,6 +447,7 @@ internal string GetExtendedClassName(object instance) /// /// Retrieves the component name from the site. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] internal string GetExtendedComponentName(object instance) { return GetComponentName(instance.GetType(), instance); @@ -443,6 +458,7 @@ internal string GetExtendedComponentName(object instance) /// it will be used to retrieve attributes. Otherwise, _type /// will be used. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] internal TypeConverter GetExtendedConverter(object instance) { return GetConverter(instance.GetType(), instance); @@ -468,6 +484,7 @@ internal PropertyDescriptor GetExtendedDefaultProperty(object instance) /// /// Retrieves the editor for the given base type. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] internal object GetExtendedEditor(object instance, Type editorBaseType) { return GetEditor(instance.GetType(), instance, editorBaseType); @@ -484,6 +501,7 @@ internal EventDescriptorCollection GetExtendedEvents(object instance) /// /// Retrieves the properties for this type. /// + [RequiresUnreferencedCode("The Type of instance and its IExtenderProviders cannot be statically discovered.")] internal PropertyDescriptorCollection GetExtendedProperties(object instance) { // Is this object a sited component? If not, then it @@ -756,6 +774,7 @@ internal object GetExtendedPropertyOwner(object instance, PropertyDescriptor pd) /// Provides a type descriptor for the given object. We only support this /// if the object is a component that /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) { Debug.Fail("This should never be invoked. TypeDescriptionNode should wrap for us."); @@ -771,6 +790,7 @@ public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) /// If not overridden, the default implementation of this method will call /// GetComponentName. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public override string GetFullComponentName(object component) { IComponent comp = component as IComponent; @@ -811,7 +831,7 @@ internal Type[] GetPopulatedTypes(Module module) /// /// Retrieves the properties for this type. /// - internal PropertyDescriptorCollection GetProperties(Type type) + internal PropertyDescriptorCollection GetProperties([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { ReflectedTypeData td = GetTypeData(type, true); return td.GetProperties(); @@ -829,7 +849,10 @@ internal object GetPropertyOwner(Type type, object instance, PropertyDescriptor /// Returns an Type for the given type. Since type implements IReflect, /// we just return objectType. /// - public override Type GetReflectionType(Type objectType, object instance) + [return: DynamicallyAccessedMembers(TypeDescriptor.ReflectTypesDynamicallyAccessedMembers)] + public override Type GetReflectionType( + [DynamicallyAccessedMembers(TypeDescriptor.ReflectTypesDynamicallyAccessedMembers)] Type objectType, + object instance) { Debug.Assert(objectType != null, "Should have arg-checked before coming in here"); return objectType; @@ -840,7 +863,7 @@ public override Type GetReflectionType(Type objectType, object instance) /// null if there is no type data for the type yet and /// createIfNeeded is false. /// - private ReflectedTypeData GetTypeData(Type type, bool createIfNeeded) + private ReflectedTypeData GetTypeData([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, bool createIfNeeded) { ReflectedTypeData td = null; @@ -882,7 +905,7 @@ private ReflectedTypeData GetTypeData(Type type, bool createIfNeeded) /// interested in providing type information for the object it should /// return null. /// - public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) + public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, object instance) { Debug.Fail("This should never be invoked. TypeDescriptionNode should wrap for us."); return null; @@ -921,9 +944,11 @@ private static Type GetTypeFromName(string typeName) /// This method returns true if the data cache in this reflection /// type descriptor has data in it. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", + Justification = "ReflectedTypeData is not being created here, just checking if was already created.")] internal bool IsPopulated(Type type) { - ReflectedTypeData td = GetTypeData(type, false); + ReflectedTypeData td = GetTypeData(type, createIfNeeded: false); if (td != null) { return td.IsPopulated; @@ -994,7 +1019,8 @@ internal static Attribute[] ReflectGetAttributes(MemberInfo member) /// Static helper API around reflection to get and cache /// events. This does not recurse to the base class. /// - private static EventDescriptor[] ReflectGetEvents(Type type) + private static EventDescriptor[] ReflectGetEvents( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { Hashtable eventCache = EventCache; EventDescriptor[] events = (EventDescriptor[])eventCache[type]; @@ -1076,6 +1102,7 @@ private static EventDescriptor[] ReflectGetEvents(Type type) /// provider instance, and a per-provider cache that contains /// the ExtendedPropertyDescriptors. /// + [RequiresUnreferencedCode("The type of provider cannot be statically discovered.")] private static PropertyDescriptor[] ReflectGetExtendedProperties(IExtenderProvider provider) { IDictionary cache = TypeDescriptor.GetCache(provider); @@ -1168,7 +1195,8 @@ private static PropertyDescriptor[] ReflectGetExtendedProperties(IExtenderProvid /// Static helper API around reflection to get and cache /// properties. This does not recurse to the base class. /// - private static PropertyDescriptor[] ReflectGetProperties(Type type) + private static PropertyDescriptor[] ReflectGetProperties( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { Hashtable propertyCache = PropertyCache; PropertyDescriptor[] properties = (PropertyDescriptor[])propertyCache[type]; @@ -1250,9 +1278,11 @@ private static PropertyDescriptor[] ReflectGetProperties(Type type) /// actually requery, but it will clear our state so the next /// query re-populates. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", + Justification = "ReflectedTypeData is not being created here, just checking if was already created.")] internal void Refresh(Type type) { - ReflectedTypeData td = GetTypeData(type, false); + ReflectedTypeData td = GetTypeData(type, createIfNeeded: false); td?.Refresh(); } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverter.cs index 09e8cb13e275b..f16fb9efac11f 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeConverter.cs @@ -224,6 +224,7 @@ protected Exception GetConvertToException(object value, Type destinationType) /// /// Gets a collection of properties for the type of array specified by the value parameter. /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered.")] public PropertyDescriptorCollection GetProperties(object value) => GetProperties(null, value); /// @@ -232,6 +233,8 @@ protected Exception GetConvertToException(object value, Type destinationType) /// the specified context. /// /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered.")] + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields, typeof(BrowsableAttribute))] public PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value) { return GetProperties(context, value, new Attribute[] { BrowsableAttribute.Yes }); @@ -243,6 +246,7 @@ public PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context /// the specified context and attributes. /// /// + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public virtual PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { return null; @@ -364,7 +368,12 @@ protected SimplePropertyDescriptor(Type componentType, string name, Type propert /// /// Gets a value indicating whether this property is read-only. /// - public override bool IsReadOnly => Attributes.Contains(ReadOnlyAttribute.Yes); + public override bool IsReadOnly + { + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields, typeof(ReadOnlyAttribute))] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The DynamicDependency ensures the correct members are preserved.")] + get { return Attributes.Contains(ReadOnlyAttribute.Yes); } + } /// /// Gets the type of the property. diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs index 28b7a3aa94d2e..2c4ad1fcbdba1 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptionProvider.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; -using System.Runtime.Versioning; +using System.Diagnostics.CodeAnalysis; namespace System.ComponentModel { @@ -92,6 +92,7 @@ public virtual object CreateInstance(IServiceProvider provider, Type objectType, /// model only supports extended properties this API can be used for extended /// attributes and events as well, if the type description provider supports it. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] public virtual ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) { if (_parent != null) @@ -126,6 +127,7 @@ protected internal virtual IExtenderProvider[] GetExtenderProviders(object insta /// If not overridden, the default implementation of this method will call /// GetTypeDescriptor.GetComponentName. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public virtual string GetFullComponentName(object component) { if (_parent != null) @@ -141,7 +143,8 @@ public virtual string GetFullComponentName(object component) /// If no custom type descriptor can be located for an object, GetReflectionType /// is called to perform normal reflection against the object. /// - public Type GetReflectionType(Type objectType) => GetReflectionType(objectType, null); + [return: DynamicallyAccessedMembers(TypeDescriptor.ReflectTypesDynamicallyAccessedMembers)] + public Type GetReflectionType([DynamicallyAccessedMembers(TypeDescriptor.ReflectTypesDynamicallyAccessedMembers)] Type objectType) => GetReflectionType(objectType, null); /// /// The GetReflection method is a lower level version of GetTypeDescriptor. @@ -152,6 +155,7 @@ public virtual string GetFullComponentName(object component) /// object type if no parent provider was passed. If a parent provider was passed, this /// method will invoke the parent provider's GetReflectionType method. /// + [RequiresUnreferencedCode("GetReflectionType is not trim compatible because the Type of object cannot be statically discovered.")] public Type GetReflectionType(object instance) { if (instance == null) @@ -171,7 +175,10 @@ public Type GetReflectionType(object instance) /// object type if no parent provider was passed. If a parent provider was passed, this /// method will invoke the parent provider's GetReflectionType method. /// - public virtual Type GetReflectionType(Type objectType, object instance) + [return: DynamicallyAccessedMembers(TypeDescriptor.ReflectTypesDynamicallyAccessedMembers)] + public virtual Type GetReflectionType( + [DynamicallyAccessedMembers(TypeDescriptor.ReflectTypesDynamicallyAccessedMembers)] Type objectType, + object instance) { if (_parent != null) { @@ -215,7 +222,7 @@ public virtual Type GetRuntimeType(Type reflectionType) /// interested in providing type information for the object it should /// return base. /// - public ICustomTypeDescriptor GetTypeDescriptor(Type objectType) + public ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType) { return GetTypeDescriptor(objectType, null); } @@ -228,6 +235,7 @@ public ICustomTypeDescriptor GetTypeDescriptor(Type objectType) /// interested in providing type information for the object it should /// return base. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] public ICustomTypeDescriptor GetTypeDescriptor(object instance) { if (instance == null) @@ -252,7 +260,7 @@ public ICustomTypeDescriptor GetTypeDescriptor(object instance) /// this method will invoke the parent provider's GetTypeDescriptor /// method. /// - public virtual ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) + public virtual ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, object instance) { if (_parent != null) { diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs index 5ad91b8c3cb83..d4136ddb87fbe 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs @@ -8,7 +8,6 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; -using System.Runtime.Versioning; using System.Threading; namespace System.ComponentModel @@ -19,6 +18,8 @@ namespace System.ComponentModel /// public sealed class TypeDescriptor { + internal const DynamicallyAccessedMemberTypes ReflectTypesDynamicallyAccessedMembers = DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields; + // Note: this is initialized at class load because we // lock on it for thread safety. It is used from nearly // every call to this class, so it will be created soon after @@ -460,10 +461,15 @@ public static object CreateInstance(IServiceProvider provider, Type objectType, return instance ?? NodeFor(objectType).CreateInstance(provider, objectType, argTypes, args); } + /// /// This dynamically binds a PropertyDescriptor to a type. /// - public static PropertyDescriptor CreateProperty(Type componentType, string name, Type type, params Attribute[] attributes) + public static PropertyDescriptor CreateProperty( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType, + string name, + Type type, + params Attribute[] attributes) { return new ReflectPropertyDescriptor(componentType, name, type, attributes); } @@ -472,7 +478,10 @@ public static PropertyDescriptor CreateProperty(Type componentType, string name, /// This creates a new property descriptor identical to an existing property descriptor. The new property descriptor /// has the specified metadata attributes merged with the existing metadata attributes. /// - public static PropertyDescriptor CreateProperty(Type componentType, PropertyDescriptor oldPropertyDescriptor, params Attribute[] attributes) + public static PropertyDescriptor CreateProperty( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType, + PropertyDescriptor oldPropertyDescriptor, + params Attribute[] attributes) { // We must do some special case work here for extended properties. If the old property descriptor is really // an extender property that is being surfaced on a component as a normal property, then we must @@ -504,6 +513,7 @@ public static PropertyDescriptor CreateProperty(Type componentType, PropertyDesc /// contains only the remaining members. The API returns /// NULL if it did not need to filter any members. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] private static ArrayList FilterMembers(IList members, Attribute[] attributes) { ArrayList newMembers = null; @@ -627,7 +637,7 @@ public static object GetAssociation(Type type, object primary) /// /// Gets a collection of attributes for the specified type of component. /// - public static AttributeCollection GetAttributes(Type componentType) + public static AttributeCollection GetAttributes([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType) { if (componentType == null) { @@ -642,6 +652,7 @@ public static AttributeCollection GetAttributes(Type componentType) /// /// Gets a collection of attributes for the specified component. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static AttributeCollection GetAttributes(object component) { return GetAttributes(component, false); @@ -651,6 +662,7 @@ public static AttributeCollection GetAttributes(object component) /// Gets a collection of attributes for the specified component. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static AttributeCollection GetAttributes(object component, bool noCustomTypeDesc) { if (component == null) @@ -740,12 +752,14 @@ public static AttributeCollection GetAttributes(object component, bool noCustomT /// /// Gets the name of the class for the specified component. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static string GetClassName(object component) => GetClassName(component, false); /// /// Gets the name of the class for the specified component. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static string GetClassName(object component, bool noCustomTypeDesc) { return GetDescriptor(component, noCustomTypeDesc).GetClassName(); @@ -754,7 +768,8 @@ public static string GetClassName(object component, bool noCustomTypeDesc) /// /// Gets the name of the class for the specified type. /// - public static string GetClassName(Type componentType) + public static string GetClassName( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType) { return GetDescriptor(componentType, nameof(componentType)).GetClassName(); } @@ -762,12 +777,14 @@ public static string GetClassName(Type componentType) /// /// The name of the class for the specified component. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static string GetComponentName(object component) => GetComponentName(component, false); /// /// Gets the name of the class for the specified component. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static string GetComponentName(object component, bool noCustomTypeDesc) { return GetDescriptor(component, noCustomTypeDesc).GetComponentName(); @@ -776,12 +793,14 @@ public static string GetComponentName(object component, bool noCustomTypeDesc) /// /// Gets a type converter for the type of the specified component. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static TypeConverter GetConverter(object component) => GetConverter(component, false); /// /// Gets a type converter for the type of the specified component. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static TypeConverter GetConverter(object component, bool noCustomTypeDesc) { TypeConverter converter = GetDescriptor(component, noCustomTypeDesc).GetConverter(); @@ -791,13 +810,13 @@ public static TypeConverter GetConverter(object component, bool noCustomTypeDesc /// /// Gets a type converter for the specified type. /// - public static TypeConverter GetConverter(Type type) + public static TypeConverter GetConverter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { return GetDescriptor(type, nameof(type)).GetConverter(); } // This is called by System.ComponentModel.DefaultValueAttribute via reflection. - private static object ConvertFromInvariantString(Type type, string stringValue) + private static object ConvertFromInvariantString([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string stringValue) { return GetConverter(type).ConvertFromInvariantString(stringValue); } @@ -805,7 +824,8 @@ private static object ConvertFromInvariantString(Type type, string stringValue) /// /// Gets the default event for the specified type of component. /// - public static EventDescriptor GetDefaultEvent(Type componentType) + public static EventDescriptor GetDefaultEvent( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType) { if (componentType == null) { @@ -819,12 +839,14 @@ public static EventDescriptor GetDefaultEvent(Type componentType) /// /// Gets the default event for the specified component. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static EventDescriptor GetDefaultEvent(object component) => GetDefaultEvent(component, false); /// /// Gets the default event for a component. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static EventDescriptor GetDefaultEvent(object component, bool noCustomTypeDesc) { if (component == null) @@ -839,7 +861,8 @@ public static EventDescriptor GetDefaultEvent(object component, bool noCustomTyp /// /// Gets the default property for the specified type of component. /// - public static PropertyDescriptor GetDefaultProperty(Type componentType) + public static PropertyDescriptor GetDefaultProperty( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType) { if (componentType == null) { @@ -853,12 +876,14 @@ public static PropertyDescriptor GetDefaultProperty(Type componentType) /// /// Gets the default property for the specified component. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static PropertyDescriptor GetDefaultProperty(object component) => GetDefaultProperty(component, false); /// /// Gets the default property for the specified component. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static PropertyDescriptor GetDefaultProperty(object component, bool noCustomTypeDesc) { if (component == null) @@ -874,7 +899,9 @@ public static PropertyDescriptor GetDefaultProperty(object component, bool noCus /// Returns a custom type descriptor for the given type. /// Performs arg checking so callers don't have to. /// - internal static ICustomTypeDescriptor GetDescriptor(Type type, string typeName) + internal static ICustomTypeDescriptor GetDescriptor( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, + string typeName) { if (type == null) { @@ -890,6 +917,7 @@ internal static ICustomTypeDescriptor GetDescriptor(Type type, string typeName) /// will call through to instance if it is a custom type /// descriptor. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] internal static ICustomTypeDescriptor GetDescriptor(object component, bool noCustomTypeDesc) { if (component == null) @@ -910,6 +938,7 @@ internal static ICustomTypeDescriptor GetDescriptor(object component, bool noCus /// /// Returns an extended custom type descriptor for the given instance. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] internal static ICustomTypeDescriptor GetExtendedDescriptor(object component) { if (component == null) @@ -924,6 +953,7 @@ internal static ICustomTypeDescriptor GetExtendedDescriptor(object component) /// Gets an editor with the specified base type for the /// specified component. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static object GetEditor(object component, Type editorBaseType) { return GetEditor(component, editorBaseType, false); @@ -934,6 +964,7 @@ public static object GetEditor(object component, Type editorBaseType) /// specified component. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static object GetEditor(object component, Type editorBaseType, bool noCustomTypeDesc) { if (editorBaseType == null) @@ -947,7 +978,9 @@ public static object GetEditor(object component, Type editorBaseType, bool noCus /// /// Gets an editor with the specified base type for the specified type. /// - public static object GetEditor(Type type, Type editorBaseType) + public static object GetEditor( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, + Type editorBaseType) { if (editorBaseType == null) { @@ -960,7 +993,8 @@ public static object GetEditor(Type type, Type editorBaseType) /// /// Gets a collection of events for a specified type of component. /// - public static EventDescriptorCollection GetEvents(Type componentType) + public static EventDescriptorCollection GetEvents( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType) { if (componentType == null) { @@ -975,7 +1009,10 @@ public static EventDescriptorCollection GetEvents(Type componentType) /// Gets a collection of events for a specified type of /// component using a specified array of attributes as a filter. /// - public static EventDescriptorCollection GetEvents(Type componentType, Attribute[] attributes) + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] + public static EventDescriptorCollection GetEvents( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType, + Attribute[] attributes) { if (componentType == null) { @@ -1000,6 +1037,7 @@ public static EventDescriptorCollection GetEvents(Type componentType, Attribute[ /// /// Gets a collection of events for a specified component. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static EventDescriptorCollection GetEvents(object component) { return GetEvents(component, null, false); @@ -1009,6 +1047,7 @@ public static EventDescriptorCollection GetEvents(object component) /// Gets a collection of events for a specified component. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static EventDescriptorCollection GetEvents(object component, bool noCustomTypeDesc) { return GetEvents(component, null, noCustomTypeDesc); @@ -1018,6 +1057,7 @@ public static EventDescriptorCollection GetEvents(object component, bool noCusto /// Gets a collection of events for a specified component /// using a specified array of attributes as a filter. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public static EventDescriptorCollection GetEvents(object component, Attribute[] attributes) { return GetEvents(component, attributes, false); @@ -1028,6 +1068,7 @@ public static EventDescriptorCollection GetEvents(object component, Attribute[] /// using a specified array of attributes as a filter. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("The Type of component cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public static EventDescriptorCollection GetEvents(object component, Attribute[] attributes, bool noCustomTypeDesc) { if (component == null) @@ -1153,6 +1194,7 @@ private static string GetExtenderCollisionSuffix(MemberDescriptor member) /// component resides in a nested container or has other nested semantics, it may /// return a different fully qualified name. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static string GetFullComponentName(object component) { if (component == null) @@ -1179,7 +1221,8 @@ private static Type GetNodeForBaseType(Type searchType) /// /// Gets a collection of properties for a specified type of component. /// - public static PropertyDescriptorCollection GetProperties(Type componentType) + public static PropertyDescriptorCollection GetProperties( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType) { if (componentType == null) { @@ -1194,7 +1237,10 @@ public static PropertyDescriptorCollection GetProperties(Type componentType) /// Gets a collection of properties for a specified type of /// component using a specified array of attributes as a filter. /// - public static PropertyDescriptorCollection GetProperties(Type componentType, Attribute[] attributes) + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] + public static PropertyDescriptorCollection GetProperties( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type componentType, + Attribute[] attributes) { if (componentType == null) { @@ -1219,6 +1265,7 @@ public static PropertyDescriptorCollection GetProperties(Type componentType, Att /// /// Gets a collection of properties for a specified component. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static PropertyDescriptorCollection GetProperties(object component) { return GetProperties(component, false); @@ -1228,6 +1275,7 @@ public static PropertyDescriptorCollection GetProperties(object component) /// Gets a collection of properties for a specified component. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static PropertyDescriptorCollection GetProperties(object component, bool noCustomTypeDesc) { return GetPropertiesImpl(component, null, noCustomTypeDesc, true); @@ -1238,6 +1286,7 @@ public static PropertyDescriptorCollection GetProperties(object component, bool /// component using a specified array of attributes /// as a filter. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public static PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes) { return GetProperties(component, attributes, false); @@ -1248,6 +1297,7 @@ public static PropertyDescriptorCollection GetProperties(object component, Attri /// component using a specified array of attributes /// as a filter. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public static PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes, bool noCustomTypeDesc) { return GetPropertiesImpl(component, attributes, noCustomTypeDesc, false); @@ -1258,6 +1308,7 @@ public static PropertyDescriptorCollection GetProperties(object component, Attri /// only if noAttributes is false. This is to preserve backward compat for the case when /// no attribute filter was passed in (as against passing in null). /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] private static PropertyDescriptorCollection GetPropertiesImpl(object component, Attribute[] attributes, bool noCustomTypeDesc, bool noAttributes) { if (component == null) @@ -1393,7 +1444,8 @@ internal static TypeDescriptionProvider GetProviderRecursive(Type type) /// Returns an Type instance that can be used to perform reflection. /// [EditorBrowsable(EditorBrowsableState.Advanced)] - public static Type GetReflectionType(Type type) + [return: DynamicallyAccessedMembers(ReflectTypesDynamicallyAccessedMembers)] + public static Type GetReflectionType([DynamicallyAccessedMembers(ReflectTypesDynamicallyAccessedMembers)] Type type) { if (type == null) { @@ -1403,11 +1455,11 @@ public static Type GetReflectionType(Type type) return NodeFor(type).GetReflectionType(type); } - /// /// Returns an Type instance that can be used to perform reflection. /// [EditorBrowsable(EditorBrowsableState.Advanced)] + [RequiresUnreferencedCode("GetReflectionType is not trim compatible because the Type of object cannot be statically discovered.")] public static Type GetReflectionType(object instance) { if (instance == null) @@ -1649,6 +1701,7 @@ private static void NodeRemove(object key, TypeDescriptionProvider provider) /// This is the last stage in our filtering pipeline. Here, we apply any /// user-defined filter. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] private static ICollection PipelineAttributeFilter(int pipelineType, ICollection members, Attribute[] filter, object instance, IDictionary cache) { Debug.Assert(pipelineType != PIPELINE_ATTRIBUTES, "PipelineAttributeFilter is not supported for attributes"); @@ -2321,6 +2374,7 @@ public static Type ComObjectType get => typeof(TypeDescriptorComObject); } + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public static IDesigner CreateDesigner(IComponent component, Type designerBaseType) { Type type = null; @@ -2542,6 +2596,7 @@ public static void RemoveProviderTransparent(TypeDescriptionProvider provider, o /// contains the attribute or the member does not contain the attribute and the default /// for the attribute matches the passed in attribute. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] private static bool ShouldHideMember(MemberDescriptor member, Attribute attribute) { if (member == null || attribute == null) @@ -2595,7 +2650,7 @@ internal ComNativeDescriptionProvider(IComNativeDescriptorHandler handler) /// Implements GetTypeDescriptor. This creates a custom type /// descriptor that walks the linked list for each of its calls. /// - public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) + public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, object instance) { if (objectType == null) { @@ -2663,6 +2718,7 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents() return _handler.GetEvents(_instance); } + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) { return _handler.GetEvents(_instance, attributes); @@ -2673,6 +2729,7 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() return _handler.GetProperties(_instance, null); } + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { return _handler.GetProperties(_instance, attributes); @@ -2702,7 +2759,7 @@ internal AttributeProvider(TypeDescriptionProvider existingProvider, params Attr /// /// Creates a custom type descriptor that replaces the attributes. /// - public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) + public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, object instance) { return new AttributeTypeDescriptor(_attrs, base.GetTypeDescriptor(objectType, instance)); } @@ -2869,7 +2926,7 @@ public ComNativeDescriptorProxy() _comNativeDescriptor = (TypeDescriptionProvider)Activator.CreateInstance(realComNativeDescriptor); } - public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) + public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, object instance) { return _comNativeDescriptor.GetTypeDescriptor(objectType, instance); } @@ -2981,6 +3038,7 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents() /// /// ICustomTypeDescriptor implementation. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) { EventDescriptorCollection events = _primary.GetEvents(attributes) ?? _secondary.GetEvents(attributes); @@ -3003,6 +3061,7 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() /// /// ICustomTypeDescriptor implementation. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { PropertyDescriptorCollection properties = _primary.GetProperties(attributes); @@ -3091,6 +3150,7 @@ public override IDictionary GetCache(object instance) /// Implements GetExtendedTypeDescriptor. This creates a custom type /// descriptor that walks the linked list for each of its calls. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance) { if (instance == null) @@ -3120,6 +3180,7 @@ protected internal override IExtenderProvider[] GetExtenderProviders(object inst /// If not overridden, the default implementation of this method will call /// GetTypeDescriptor.GetComponentName. /// + [RequiresUnreferencedCode("The Type of component cannot be statically discovered.")] public override string GetFullComponentName(object component) { if (component == null) @@ -3134,7 +3195,10 @@ public override string GetFullComponentName(object component) /// Implements GetReflectionType. This just walks the linked list /// looking for someone who implements the call. /// - public override Type GetReflectionType(Type objectType, object instance) + [return: DynamicallyAccessedMembers(ReflectTypesDynamicallyAccessedMembers)] + public override Type GetReflectionType( + [DynamicallyAccessedMembers(ReflectTypesDynamicallyAccessedMembers)] Type objectType, + object instance) { if (objectType == null) { @@ -3158,7 +3222,7 @@ public override Type GetRuntimeType(Type objectType) /// Implements GetTypeDescriptor. This creates a custom type /// descriptor that walks the linked list for each of its calls. /// - public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) + public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, object instance) { if (objectType == null) { @@ -3194,6 +3258,7 @@ public override bool IsSupportedType(Type type) /// /// Creates a new WalkingExtendedTypeDescriptor. /// + [RequiresUnreferencedCode("The Type of instance cannot be statically discovered.")] internal DefaultExtendedTypeDescriptor(TypeDescriptionNode node, object instance) { _node = node; @@ -3203,6 +3268,7 @@ internal DefaultExtendedTypeDescriptor(TypeDescriptionNode node, object instance /// /// ICustomTypeDescriptor implementation. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctor of this Type has RequiresUnreferencedCode.")] AttributeCollection ICustomTypeDescriptor.GetAttributes() { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3225,6 +3291,7 @@ AttributeCollection ICustomTypeDescriptor.GetAttributes() /// /// ICustomTypeDescriptor implementation. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctor of this Type has RequiresUnreferencedCode.")] string ICustomTypeDescriptor.GetClassName() { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3246,6 +3313,7 @@ string ICustomTypeDescriptor.GetClassName() /// /// ICustomTypeDescriptor implementation. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctor of this Type has RequiresUnreferencedCode.")] string ICustomTypeDescriptor.GetComponentName() { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3266,6 +3334,7 @@ string ICustomTypeDescriptor.GetComponentName() /// /// ICustomTypeDescriptor implementation. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctor of this Type has RequiresUnreferencedCode.")] TypeConverter ICustomTypeDescriptor.GetConverter() { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3288,6 +3357,7 @@ TypeConverter ICustomTypeDescriptor.GetConverter() /// /// ICustomTypeDescriptor implementation. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctor of this Type has RequiresUnreferencedCode.")] EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3308,6 +3378,7 @@ EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() /// /// ICustomTypeDescriptor implementation. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctor of this Type has RequiresUnreferencedCode.")] PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3327,6 +3398,7 @@ PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() /// /// ICustomTypeDescriptor implementation. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctor of this Type has RequiresUnreferencedCode.")] object ICustomTypeDescriptor.GetEditor(Type editorBaseType) { if (editorBaseType == null) @@ -3351,6 +3423,7 @@ object ICustomTypeDescriptor.GetEditor(Type editorBaseType) /// /// ICustomTypeDescriptor implementation. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctor of this Type has RequiresUnreferencedCode.")] EventDescriptorCollection ICustomTypeDescriptor.GetEvents() { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3372,6 +3445,7 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents() /// /// ICustomTypeDescriptor implementation. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3398,6 +3472,7 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes /// /// ICustomTypeDescriptor implementation. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctor of this Type has RequiresUnreferencedCode.")] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3419,6 +3494,7 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() /// /// ICustomTypeDescriptor implementation. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3445,6 +3521,7 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] att /// /// ICustomTypeDescriptor implementation. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The ctor of this Type has RequiresUnreferencedCode.")] object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3471,13 +3548,17 @@ object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) private readonly struct DefaultTypeDescriptor : ICustomTypeDescriptor { private readonly TypeDescriptionNode _node; + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] private readonly Type _objectType; private readonly object _instance; /// /// Creates a new WalkingTypeDescriptor. /// - internal DefaultTypeDescriptor(TypeDescriptionNode node, Type objectType, object instance) + internal DefaultTypeDescriptor( + TypeDescriptionNode node, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, + object instance) { _node = node; _objectType = objectType; @@ -3698,6 +3779,7 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents() /// /// ICustomTypeDescriptor implementation. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. @@ -3752,6 +3834,7 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() /// /// ICustomTypeDescriptor implementation. /// + [RequiresUnreferencedCode(AttributeCollection.FilterRequiresUnreferencedCodeMessage)] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { // Check to see if the provider we get is a ReflectTypeDescriptionProvider. diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/PointConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/PointConverter.cs index e662f6f38b4bc..ca62378f801e5 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/PointConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/PointConverter.cs @@ -123,6 +123,7 @@ public override object CreateInstance(ITypeDescriptorContext context, IDictionar private static readonly string[] s_propertySort = { "X", "Y" }; + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(Point), attributes); diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs index 758f5bfa669e7..8a4df6c0b0d51 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs @@ -129,6 +129,7 @@ public override object CreateInstance(ITypeDescriptorContext context, IDictionar private static readonly string[] s_propertySort = { "X", "Y", "Width", "Height" }; + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(Rectangle), attributes); diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeConverter.cs index dc492bbac4bc8..d71fee467c97b 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeConverter.cs @@ -121,6 +121,7 @@ public override object CreateInstance(ITypeDescriptorContext context, IDictionar private static readonly string[] s_propertySort = { "Width", "Height" }; + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(Size), attributes); diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeFConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeFConverter.cs index 1dd5a976b8749..61bb9c5beeb99 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeFConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/SizeFConverter.cs @@ -118,6 +118,7 @@ public override object CreateInstance(ITypeDescriptorContext context, IDictionar private static readonly string[] s_propertySort = { "Width", "Height" }; + [RequiresUnreferencedCode("The Type of value cannot be statically discovered. " + AttributeCollection.FilterRequiresUnreferencedCodeMessage)] public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) { PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(SizeF), attributes); diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeConverterIsReadOnly.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeConverterIsReadOnly.cs new file mode 100644 index 0000000000000..08f15c32b8a78 --- /dev/null +++ b/src/libraries/System.ComponentModel.TypeConverter/tests/TrimmingTests/TypeConverterIsReadOnly.cs @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections; +using System.ComponentModel; + +/// +/// Tests that SimplePropertyDescriptor.IsReadOnly works correctly when trimming. +/// +class Program +{ + static int Main() + { + PropertyDescriptor property = MyTypeConverter.CreatePropertyDescriptor(isReadOnly: false); + if (property.IsReadOnly) + { + return -1; + } + + property = MyTypeConverter.CreatePropertyDescriptor(isReadOnly: true); + if (!property.IsReadOnly) + { + return -2; + } + + Type readOnlyAttributeType = property.Attributes[0].GetType(); + if (readOnlyAttributeType.Name != "ReadOnlyAttribute") + { + return -3; + } + + // check to make sure the 'ReadOnlyAttribute.Default' static field is preserved + if (readOnlyAttributeType.GetField("Default") == null) + { + return -4; + } + + return 100; + } +} + +internal class MyTypeConverter : TypeConverter +{ + protected class MyPropertyDescriptor : SimplePropertyDescriptor + { + private readonly bool _isReadOnly; + + public MyPropertyDescriptor(bool isReadOnly) : base(typeof(Program), "property", typeof(int)) + { + _isReadOnly = isReadOnly; + } + + protected override void FillAttributes(IList attributeList) + { + if (_isReadOnly) + { + attributeList.Add(ReadOnlyAttribute.Yes); + } + + base.FillAttributes(attributeList); + } + + public override object GetValue(object component) => null; + public override void SetValue(object component, object value) { } + } + + public static PropertyDescriptor CreatePropertyDescriptor(bool isReadOnly) + { + return new MyPropertyDescriptor(isReadOnly); + } +} diff --git a/src/libraries/System.Data.Common/ref/System.Data.Common.cs b/src/libraries/System.Data.Common/ref/System.Data.Common.cs index 423e82d28d8dd..9844b892a40b7 100644 --- a/src/libraries/System.Data.Common/ref/System.Data.Common.cs +++ b/src/libraries/System.Data.Common/ref/System.Data.Common.cs @@ -470,8 +470,10 @@ public void EndEdit() { } System.ComponentModel.PropertyDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty() { throw null; } object System.ComponentModel.ICustomTypeDescriptor.GetEditor(System.Type editorBaseType) { throw null; } System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents(System.Attribute[] attributes) { throw null; } System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties(System.Attribute[] attributes) { throw null; } object System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd) { throw null; } #nullable enable @@ -2057,8 +2059,10 @@ void System.Collections.IDictionary.Remove(object keyword) { } System.ComponentModel.PropertyDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty() { throw null; } object System.ComponentModel.ICustomTypeDescriptor.GetEditor(System.Type editorBaseType) { throw null; } System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents(System.Attribute[] attributes) { throw null; } System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties(System.Attribute[] attributes) { throw null; } object System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd) { throw null; } public override string ToString() { throw null; } @@ -2232,8 +2236,10 @@ protected DbDataRecord() { } System.ComponentModel.PropertyDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty() { throw null; } object System.ComponentModel.ICustomTypeDescriptor.GetEditor(System.Type editorBaseType) { throw null; } System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents(System.Attribute[] attributes) { throw null; } System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties(System.Attribute[] attributes) { throw null; } object System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd) { throw null; } #nullable enable diff --git a/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml index a337709a48943..aae5e3cc281c9 100644 --- a/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml @@ -151,5 +151,101 @@ member M:System.Data.DataSet.SerializeDataSet(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext,System.Data.SerializationFormat) + + ILLink + IL2026 + member + M:System.Data.Common.DbConnectionStringBuilder.GetProperties(System.Collections.Hashtable) + + + ILLink + IL2026 + member + M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetAttributes + + + ILLink + IL2026 + member + M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetClassName + + + ILLink + IL2026 + member + M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetComponentName + + + ILLink + IL2026 + member + M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetConverter + + + ILLink + IL2026 + member + M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetDefaultEvent + + + ILLink + IL2026 + member + M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetDefaultProperty + + + ILLink + IL2026 + member + M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetEditor(System.Type) + + + ILLink + IL2026 + member + M:System.Data.Common.DbConnectionStringBuilder.System#ComponentModel#ICustomTypeDescriptor#GetEvents + + + ILLink + IL2026 + member + M:System.Data.XMLSchema.SetProperties(System.Object,System.Xml.XmlAttributeCollection) + + + ILLink + IL2026 + member + M:System.Data.XmlTreeGen.AddXdoProperties(System.Object,System.Xml.XmlElement,System.Xml.XmlDocument) + + + ILLink + IL2026 + member + M:System.Data.XmlTreeGen.AddXdoProperty(System.ComponentModel.PropertyDescriptor,System.Object,System.Xml.XmlElement,System.Xml.XmlDocument) + + + ILLink + IL2026 + member + M:System.Data.XSDSchema.SetExtProperties(System.Object,System.Xml.XmlAttribute[]) + + + ILLink + IL2026 + member + M:System.Data.XSDSchema.SetExtProperties(System.Object,System.Xml.XmlAttributeCollection) + + + ILLink + IL2026 + member + M:System.Data.XSDSchema.SetProperties(System.Object,System.Xml.XmlAttribute[]) + + + ILLink + IL2067 + member + M:System.Data.XMLSchema.GetConverter(System.Type) + diff --git a/src/libraries/System.Data.Common/src/System/Data/Common/DataRecordInternal.cs b/src/libraries/System.Data.Common/src/System/Data/Common/DataRecordInternal.cs index 0bad614a43049..e18d3aff22e3a 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Common/DataRecordInternal.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Common/DataRecordInternal.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Data.ProviderBase; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Data.Common { @@ -344,16 +345,19 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents() return new EventDescriptorCollection(null); } + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) { return new EventDescriptorCollection(null); } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "No Attributes are supplied.")] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { return ((ICustomTypeDescriptor)this).GetProperties(null); } + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { if (_propertyDescriptors == null) diff --git a/src/libraries/System.Data.Common/src/System/Data/Common/DbConnectionStringBuilder.cs b/src/libraries/System.Data.Common/src/System/Data/Common/DbConnectionStringBuilder.cs index 533e6ed5ab841..1bd2205a64168 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Common/DbConnectionStringBuilder.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Common/DbConnectionStringBuilder.cs @@ -514,6 +514,7 @@ protected virtual void GetProperties(Hashtable propertyDescriptors) } } + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] private PropertyDescriptorCollection GetProperties(Attribute[]? attributes) { PropertyDescriptorCollection propertyDescriptors = GetProperties(); @@ -591,6 +592,7 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { return GetProperties(); } + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { return GetProperties(attributes); @@ -603,6 +605,7 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents() { return TypeDescriptor.GetEvents(this, true); } + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) { return TypeDescriptor.GetEvents(this, attributes, true); diff --git a/src/libraries/System.Data.Common/src/System/Data/Common/DbDataRecord.cs b/src/libraries/System.Data.Common/src/System/Data/Common/DbDataRecord.cs index 605045fe5b632..11ba1945f3f29 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Common/DbDataRecord.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Common/DbDataRecord.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; namespace System.Data.Common { @@ -86,11 +87,14 @@ protected virtual DbDataReader GetDbDataReader(int i) EventDescriptorCollection ICustomTypeDescriptor.GetEvents() => new EventDescriptorCollection(null); + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) => new EventDescriptorCollection(null); + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "No Attributes are supplied.")] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() => ((ICustomTypeDescriptor)this).GetProperties(null); + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) => new PropertyDescriptorCollection(null); diff --git a/src/libraries/System.Data.Common/src/System/Data/DataRowView.cs b/src/libraries/System.Data.Common/src/System/Data/DataRowView.cs index 8f0813ba1ce08..50e01e4852f9d 100644 --- a/src/libraries/System.Data.Common/src/System/Data/DataRowView.cs +++ b/src/libraries/System.Data.Common/src/System/Data/DataRowView.cs @@ -241,10 +241,17 @@ public void EndEdit() PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() => null; object ICustomTypeDescriptor.GetEditor(Type editorBaseType) => null; EventDescriptorCollection ICustomTypeDescriptor.GetEvents() => new EventDescriptorCollection(null); + + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) => new EventDescriptorCollection(null); + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "No Attributes are supplied.")] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() => ((ICustomTypeDescriptor)this).GetProperties(null); + + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) => (_dataView.Table != null ? _dataView.Table.GetPropertyDescriptorCollection(attributes) : s_zeroPropertyDescriptorCollection); + object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) => this; #nullable enable #endregion diff --git a/src/libraries/System.Data.Common/src/System/Data/DataViewManagerListItemTypeDescriptor.cs b/src/libraries/System.Data.Common/src/System/Data/DataViewManagerListItemTypeDescriptor.cs index 24059e62ad050..734b4f5d597a8 100644 --- a/src/libraries/System.Data.Common/src/System/Data/DataViewManagerListItemTypeDescriptor.cs +++ b/src/libraries/System.Data.Common/src/System/Data/DataViewManagerListItemTypeDescriptor.cs @@ -5,6 +5,7 @@ #nullable disable using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; namespace System.Data { @@ -82,6 +83,7 @@ internal DataView GetDataView(DataTable table) /// additional events. The returned array of events will be /// filtered by the given set of attributes. /// + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) => new EventDescriptorCollection(null); @@ -91,6 +93,7 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes /// provides. If the component is sited, the site may add or remove /// additional properties. /// + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "No Attributes are supplied.")] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() => ((ICustomTypeDescriptor)this).GetProperties(null); @@ -101,6 +104,7 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() => /// additional properties. The returned array of properties will be /// filtered by the given set of attributes. /// + [RequiresUnreferencedCode("The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { if (_propsCollection == null) diff --git a/src/libraries/System.Data.Common/src/System/Data/xmlsaver.cs b/src/libraries/System.Data.Common/src/System/Data/xmlsaver.cs index 4f68992c822a8..6e9fbb9ac1b17 100644 --- a/src/libraries/System.Data.Common/src/System/Data/xmlsaver.cs +++ b/src/libraries/System.Data.Common/src/System/Data/xmlsaver.cs @@ -155,7 +155,7 @@ internal void AddXdoProperty(PropertyDescriptor pd, object instance, XmlElement return; } - if ((!pd.ShouldSerializeValue(instance) || !pd.Attributes.Contains(DesignerSerializationVisibilityAttribute.Visible)) && (bIsSqlType == false)) + if ((!pd.ShouldSerializeValue(instance) || !ContainsDesignerSerializationVisibleAttribute(pd)) && (bIsSqlType == false)) { return; } @@ -220,6 +220,10 @@ internal void AddXdoProperty(PropertyDescriptor pd, object instance, XmlElement return; } + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicFields, typeof(DesignerSerializationVisibilityAttribute))] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The DynamicDependency ensures the correct members are preserved.")] + private bool ContainsDesignerSerializationVisibleAttribute(PropertyDescriptor pd) => pd.Attributes.Contains(DesignerSerializationVisibilityAttribute.Visible); + internal static string XmlDataTypeName(Type type) { if (type == typeof(char)) From 8c64e3073e9c32e081ebd9df8141fbb2438b06d7 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Tue, 9 Mar 2021 14:01:38 -0500 Subject: [PATCH 60/83] [wasm] Add Wasm.Build tests, for testing wasm app builds (#47683) * [wasm] Add Wasm.Build tests, for testing wasm app builds These tests will build wasm test projects, as part of each test method, and run them. Other library tests are run with `xharness`, and the test assembly is run under wasm. But here we want to run them with xunit, outside wasm. So, this has different requirements for the helix payload, eg, the sdk, xunit console runner etc. To make it work, a new Scenario - `BuildWasmApps` is added, which emits it's archives in a `buildwasmapps/` folder, which makes it easy to pick up for the helix test run. The tests are added under `src/tests/BuildWasmApps/Wasm.Build.Tests`, but they use `Directory.Build*` from `src/libraries`, similar to how FunctionalTests do it. Another use case of this kinda scenario are the wasm debugger tests, in which the individual test methods launch wasm apps, and then debug them. (TBD) Tests: - The initial set of tests are just proof-of-concept, and more will be added once this is merged. Note: The individual tests build test projects, and then run them with `xharness`, under `v8`, and Chrome. * [wasm] Disable il stripping completely This uses `mono-cil-strip` from a mono installation. And in it's current form it can cause issues, so disabling it for now. * Bump helix timeout for tests from 30m to 60m * [wasm] Cleanup builing RunScriptCommand .. this allows supporting other properties from xunit*targets, eg. to run a particular test `$(XUnitMethodName)`, which adds `-method foobar` to the command line. * [wasm] Fix timeout string, 00:60:00 to 01:00:00 * [wasm] Fix path to build support dir * cleanup * [wasm] fix InvariantGlobalization test * [wasm] cleanup Wasm.Build.Tests.csproj * [wasm] Add `include_aot` param for the test data * [wasm] Enable verbose output for xunit Instead of writing all the output to stdout also, use `-verbose` which gives output like: ``` Wasm.Build.Tests.WasmBuildAppTest.InvariantGlobalization(config: "Debug", aot: False, invariantGlobalization: null) [STARTING] ============== wasm test ============= ============== wasm test-browser ============= Wasm.Build.Tests.WasmBuildAppTest.InvariantGlobalization(config: "Debug", aot: False, invariantGlobalization: null) [FINISHED] Time: 8.6357275s ``` We log the detailed output to files anyway. * [wasm] fix tests * [wasm] Really enable verbose output for xunit, this time * [wasm] Update tests to track the xharness fix for expected-exit-code * [wasm] Bump browser job's timeout from 120 to 180 mins * Improve comment Co-authored-by: Mitchell Hwang * Update eng/testing/tests.mobile.targets Co-authored-by: Mitchell Hwang * Remove unrelated commit Instead, this is moved to a different AOT PR. Revert "[wasm] Disable il stripping completely" This reverts commit 25c2340a636be7d8973c09b6808a20466fdcd296. * Revert "Remove unrelated commit" This is needed because `mono-cil-strip` isn't available on helix. And we want to disable cil stripping anyway. This reverts commit ead13ee3d9c6d53a22b3c3051542057373c77b31. Co-authored-by: Mitchell Hwang --- eng/pipelines/runtime.yml | 3 +- eng/testing/tests.mobile.targets | 19 +- eng/testing/xunit/xunit.console.targets | 2 +- src/libraries/Directory.Build.props | 3 +- src/libraries/sendtohelixhelp.proj | 25 +- src/libraries/tests.proj | 4 + src/mono/wasm/Makefile | 3 + src/mono/wasm/build/WasmApp.LocalBuild.props | 6 +- src/mono/wasm/build/WasmApp.targets | 9 +- src/tests/BuildWasmApps/Directory.Build.props | 6 + .../BuildWasmApps/Directory.Build.targets | 8 + .../Wasm.Build.Tests/Wasm.Build.Tests.csproj | 34 + .../Wasm.Build.Tests/WasmBuildAppTest.cs | 663 ++++++++++++++++++ src/tests/Common/dirs.proj | 1 + 14 files changed, 772 insertions(+), 14 deletions(-) create mode 100644 src/tests/BuildWasmApps/Directory.Build.props create mode 100644 src/tests/BuildWasmApps/Directory.Build.targets create mode 100644 src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj create mode 100644 src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 564cbdf04fd57..1b5b41d8d9173 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -282,7 +282,7 @@ jobs: testGroup: innerloop nameSuffix: AllSubsets_Mono buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true - timeoutInMinutes: 120 + timeoutInMinutes: 180 condition: >- or( eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), @@ -297,6 +297,7 @@ jobs: scenarios: - normal - wasmtestonbrowser + - buildwasmapps condition: >- or( eq(variables['librariesContainsChange'], true), diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 56a9db8b97ee8..18fb245af492e 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -12,7 +12,7 @@ - $HARNESS_RUNNER wasm $XHARNESS_COMMAND --app=. --engine=$(JSEngine) $(JSEngineArgs) --js-file=runtime.js --output-directory=$XHARNESS_OUT -- $(RunTestsJSArguments) --run WasmTestRunner.dll $(AssemblyName).dll + $HARNESS_RUNNER wasm $XHARNESS_COMMAND --app=. --engine=$(JSEngine) $(JSEngineArgs) --js-file=runtime.js --output-directory=$XHARNESS_OUT -- $(RunTestsJSArguments) --run WasmTestRunner.dll $(AssemblyName).dll $HARNESS_RUNNER wasm $XHARNESS_COMMAND --app=. --engine=$(JSEngine) $(JSEngineArgs) --js-file=runtime.js --output-directory=$XHARNESS_OUT --expected-exit-code=$(ExpectedExitCode) -- $(RunTestsJSArguments) --run $(AssemblyName).dll --testing false true @@ -233,9 +233,24 @@ PrepareForWasmBuildApp;$(WasmBuildAppDependsOn) + $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasm', 'emsdk')) - + + + + + + + + + + + + + diff --git a/eng/testing/xunit/xunit.console.targets b/eng/testing/xunit/xunit.console.targets index ee700551c76b8..a3e7d2614a4f5 100644 --- a/eng/testing/xunit/xunit.console.targets +++ b/eng/testing/xunit/xunit.console.targets @@ -62,7 +62,7 @@ - + $(ArtifactsDir)helix/ $(TestArchiveRoot)tests/ $(TestArchiveRoot)runonly/ + $(TestArchiveRoot)buildwasmapps/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(TestArchiveRoot)runtime/ @@ -170,7 +171,7 @@ false - + diff --git a/src/libraries/sendtohelixhelp.proj b/src/libraries/sendtohelixhelp.proj index 3269b7c389500..4efa7087a45cc 100644 --- a/src/libraries/sendtohelixhelp.proj +++ b/src/libraries/sendtohelixhelp.proj @@ -28,6 +28,7 @@ <_workItemTimeout Condition="'$(_workItemTimeout)' == '' and ('$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'tvOS' or '$(TargetOS)' == 'Android')">00:30:00 <_workItemTimeout Condition="'$(Scenario)' == '' and '$(_workItemTimeout)' == '' and ('$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'arm')">00:45:00 <_workItemTimeout Condition="'$(Scenario)' != '' and '$(_workItemTimeout)' == '' and ('$(TargetArchitecture)' == 'arm64' or '$(TargetArchitecture)' == 'arm')">01:00:00 + <_workItemTimeout Condition="'$(Scenario)' == 'BuildWasmApps' and '$(_workItemTimeout)' == ''">01:00:00 <_workItemTimeout Condition="'$(Scenario)' == '' and '$(_workItemTimeout)' == ''">00:15:00 <_workItemTimeout Condition="'$(Scenario)' != '' and '$(_workItemTimeout)' == ''">00:30:00 @@ -98,11 +99,19 @@ - + + + true + true + sdk + $([System.IO.File]::ReadAllText('$(RepoRoot)global.json')) + $([System.Text.RegularExpressions.Regex]::Match($(GlobalJsonContent), '(%3F<="dotnet": ").*(%3F=")')) + + @@ -224,6 +233,8 @@ 768968 https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/$(ChromiumRevision)/chrome-linux.zip https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/$(ChromiumRevision)/chromedriver_linux64.zip + $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasm', 'emsdk')) + $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'src', 'mono', 'wasm', 'build')) @@ -237,6 +248,14 @@ + + + + + + + + @@ -244,7 +263,7 @@ <_WorkItem Include="$(WorkItemArchiveWildCard)" Exclude="$(HelixCorrelationPayload)" /> - <_WorkItem Include="$(TestArchiveRoot)runonly/**/WebAssembly.Console.*.Test.zip" Condition="'$(TargetOS)' == 'Browser' and '$(Scenario)' != 'WasmTestOnBrowser'" /> + <_WorkItem Include="$(TestArchiveRoot)runonly/**/WebAssembly.Console.*.Test.zip" Condition="'$(TargetOS)' == 'Browser' and '$(Scenario)' != 'WasmTestOnBrowser' and '$(Scenario)' != 'BuildWasmApps'" /> <_WorkItem Include="$(TestArchiveRoot)runonly/**/WebAssembly.Browser.*.Test.zip" Condition="'$(TargetOS)' == 'Browser' and '$(Scenario)' == 'WasmTestOnBrowser'" /> @@ -254,7 +273,7 @@ - + <_RunOnlyWorkItem Include="$(TestArchiveRoot)runonly/**/*.Console.Sample.zip" /> diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index e2c0a92a18589..a46f287acb10c 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -271,6 +271,10 @@ Condition="'$(TestTrimming)' == 'true'" AdditionalProperties="%(AdditionalProperties);SkipTrimmingProjectsRestore=true" /> + diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index a3e15f8454b0a..cbb7e16251fca 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -182,6 +182,9 @@ run-tests-jsc-%: run-tests-%: PATH="$(JSVU):$(PATH)" $(DOTNET) build $(TOP)/src/libraries/$*/tests/ /t:Test $(_MSBUILD_WASM_BUILD_ARGS) $(MSBUILD_ARGS) +run-build-tests: + PATH="$(JSVU):$(PATH)" $(DOTNET) build $(TOP)/src/tests/BuildWasmApps/Wasm.Build.Tests/ /t:Test $(_MSBUILD_WASM_BUILD_ARGS) $(MSBUILD_ARGS) + run-browser-tests-%: PATH="$(GECKODRIVER):$(CHROMEDRIVER):$(PATH)" XHARNESS_COMMAND="test-browser --browser=$(XHARNESS_BROWSER)" $(DOTNET) build $(TOP)/src/libraries/$*/tests/ /t:Test $(_MSBUILD_WASM_BUILD_ARGS) $(MSBUILD_ARGS) diff --git a/src/mono/wasm/build/WasmApp.LocalBuild.props b/src/mono/wasm/build/WasmApp.LocalBuild.props index b545e5764d8f8..a56d7137dac89 100644 --- a/src/mono/wasm/build/WasmApp.LocalBuild.props +++ b/src/mono/wasm/build/WasmApp.LocalBuild.props @@ -19,8 +19,10 @@ $(WasmBuildSupportDir) - directory which has all the tasks, targets, and runtimepack --> + + - <_NetCoreAppToolCurrent>net5.0 + <_NetCoreAppToolCurrent>net6.0 @@ -52,6 +54,4 @@ $([MSBuild]::NormalizePath('$(WasmBuildTasksDir)', 'WasmBuildTasks.dll')) $([MSBuild]::NormalizePath('$(MonoAOTCompilerDir)', 'MonoAOTCompiler.dll')) - - diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 0bd700e379a36..a903819357228 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -58,8 +58,10 @@ --> - false - $(RunAOTCompilation) + false + + + <_ExeExt Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">.exe @@ -69,6 +71,7 @@ + @@ -323,7 +326,7 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ diff --git a/src/tests/BuildWasmApps/Directory.Build.props b/src/tests/BuildWasmApps/Directory.Build.props new file mode 100644 index 0000000000000..68eaef4190505 --- /dev/null +++ b/src/tests/BuildWasmApps/Directory.Build.props @@ -0,0 +1,6 @@ + + + BuildWasmApps + + + diff --git a/src/tests/BuildWasmApps/Directory.Build.targets b/src/tests/BuildWasmApps/Directory.Build.targets new file mode 100644 index 0000000000000..fa2efe47c0815 --- /dev/null +++ b/src/tests/BuildWasmApps/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + $(OutDir) + $(OutDir)\RunTests.sh + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj new file mode 100644 index 0000000000000..a6fe3e49f375d --- /dev/null +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -0,0 +1,34 @@ + + + $(NetCoreAppToolCurrent) + true + true + true + BuildAndRun + xunit + false + + + + + + + <_PreCommand>WasmBuildSupportDir=%24{HELIX_CORRELATION_PAYLOAD}/build + <_PreCommand>$(_PreCommand) DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 + + + + <_PreCommand>$(_PreCommand) TEST_LOG_PATH=%24{XHARNESS_OUT}/logs + <_PreCommand>$(_PreCommand) HARNESS_RUNNER=%24{HARNESS_RUNNER} + + $(_PreCommand) dotnet exec xunit.console.dll $(AssemblyName).dll -xml %24XHARNESS_OUT/testResults.xml + $(RunScriptCommand) -nocolor + $(RunScriptCommand) -verbose + + + + + + + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs new file mode 100644 index 0000000000000..c6ff9aa45d312 --- /dev/null +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -0,0 +1,663 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using Xunit; +using Xunit.Abstractions; + +#nullable enable + +namespace Wasm.Build.Tests +{ + public class WasmBuildAppTest : IDisposable + { + private const string TestLogPathEnvVar = "TEST_LOG_PATH"; + private const string SkipProjectCleanupEnvVar = "SKIP_PROJECT_CLEANUP"; + private const string XHarnessRunnerCommandEnvVar = "XHARNESS_CLI_PATH"; + + private readonly string _tempDir; + private readonly ITestOutputHelper _testOutput; + private readonly string _id; + private readonly string _logPath; + + private const string s_targetFramework = "net5.0"; + private static string s_runtimeConfig = "Release"; + private static string s_runtimePackDir; + private static string s_defaultBuildArgs; + private static readonly string s_logRoot; + private static readonly string s_emsdkPath; + private static readonly bool s_skipProjectCleanup; + private static readonly string s_xharnessRunnerCommand; + + static WasmBuildAppTest() + { + DirectoryInfo? solutionRoot = new (AppContext.BaseDirectory); + while (solutionRoot != null) + { + if (File.Exists(Path.Combine(solutionRoot.FullName, "NuGet.config"))) + { + break; + } + + solutionRoot = solutionRoot.Parent; + } + + if (solutionRoot == null) + { + string? buildDir = Environment.GetEnvironmentVariable("WasmBuildSupportDir"); + + if (buildDir == null || !Directory.Exists(buildDir)) + throw new Exception($"Could not find the solution root, or a build dir: {buildDir}"); + + s_emsdkPath = Path.Combine(buildDir, "emsdk"); + s_runtimePackDir = Path.Combine(buildDir, "microsoft.netcore.app.runtime.browser-wasm"); + s_defaultBuildArgs = $" /p:WasmBuildSupportDir={buildDir} /p:EMSDK_PATH={s_emsdkPath} "; + } + else + { + string artifactsBinDir = Path.Combine(solutionRoot.FullName, "artifacts", "bin"); + s_runtimePackDir = Path.Combine(artifactsBinDir, "microsoft.netcore.app.runtime.browser-wasm", s_runtimeConfig); + + string? emsdk = Environment.GetEnvironmentVariable("EMSDK_PATH"); + if (string.IsNullOrEmpty(emsdk)) + emsdk = Path.Combine(solutionRoot.FullName, "src", "mono", "wasm", "emsdk"); + s_emsdkPath = emsdk; + + s_defaultBuildArgs = $" /p:RuntimeSrcDir={solutionRoot.FullName} /p:RuntimeConfig={s_runtimeConfig} /p:EMSDK_PATH={s_emsdkPath} "; + } + + string? logPathEnvVar = Environment.GetEnvironmentVariable(TestLogPathEnvVar); + if (!string.IsNullOrEmpty(logPathEnvVar)) + { + s_logRoot = logPathEnvVar; + if (!Directory.Exists(s_logRoot)) + { + Directory.CreateDirectory(s_logRoot); + } + } + else + { + s_logRoot = Environment.CurrentDirectory; + } + + string? cleanupVar = Environment.GetEnvironmentVariable(SkipProjectCleanupEnvVar); + s_skipProjectCleanup = !string.IsNullOrEmpty(cleanupVar) && cleanupVar == "1"; + + string? harnessVar = Environment.GetEnvironmentVariable(XHarnessRunnerCommandEnvVar); + if (string.IsNullOrEmpty(harnessVar)) + { + throw new Exception($"{XHarnessRunnerCommandEnvVar} not set"); + } + + s_xharnessRunnerCommand = harnessVar; + } + + public WasmBuildAppTest(ITestOutputHelper output) + { + _testOutput = output; + _id = Path.GetRandomFileName(); + _tempDir = Path.Combine(AppContext.BaseDirectory, _id); + Directory.CreateDirectory(_tempDir); + + _logPath = Path.Combine(s_logRoot, _id); + Directory.CreateDirectory(_logPath); + + _testOutput.WriteLine($"Test Id: {_id}"); + } + + + /* + * TODO: + - AOT modes + - llvmonly + - aotinterp + - skipped assemblies should get have their pinvoke/icall stuff scanned + + - only buildNative + - aot but no wrapper - check that AppBundle wasn't generated + */ + + + public static TheoryData ConfigWithAOTData(bool include_aot=true) + { + TheoryData data = new() + { + { "Debug", false }, + { "Release", false } + }; + + if (include_aot) + { + data.Add("Debug", true); + data.Add("Release", true); + } + + return data; + } + + public static TheoryData InvariantGlobalizationTestData() + { + var data = new TheoryData(); + foreach (var configData in ConfigWithAOTData()) + { + data.Add((string)configData[0], (bool)configData[1], null); + data.Add((string)configData[0], (bool)configData[1], true); + data.Add((string)configData[0], (bool)configData[1], false); + } + return data; + } + + // TODO: check that icu bits have been linked out + [Theory] + [MemberData(nameof(InvariantGlobalizationTestData))] + public void InvariantGlobalization(string config, bool aot, bool? invariantGlobalization) + { + File.WriteAllText(Path.Combine(_tempDir, "Program.cs"), @" + using System; + using System.Threading.Tasks; + + public class TestClass { + public static int Main() + { + Console.WriteLine(""Hello, World!""); + return 42; + } + } + "); + + string? extraProperties = null; + if (invariantGlobalization != null) + extraProperties = $"{invariantGlobalization}"; + + string projectName = $"invariant_{invariantGlobalization?.ToString() ?? "unset"}"; + BuildProject(projectName, config, aot: aot, extraProperties: extraProperties, + hasIcudt: invariantGlobalization == null || invariantGlobalization.Value == false); + + RunAndTestWasmApp(projectName, config, isAOT: aot, expectedExitCode: 42, + test: output => Assert.Contains("Hello, World!", output)); + } + + [Theory] + [MemberData(nameof(ConfigWithAOTData), parameters: /*aot*/ true)] + public void TopLevelMain(string config, bool aot) + => TestMain("top_level", + @"System.Console.WriteLine(""Hello, World!""); return await System.Threading.Tasks.Task.FromResult(42);", + config, aot); + + [Theory] + [MemberData(nameof(ConfigWithAOTData), parameters: /*aot*/ true)] + public void AsyncMain(string config, bool aot) + => TestMain("async_main", @" + using System; + using System.Threading.Tasks; + + public class TestClass { + public static async Task Main() + { + Console.WriteLine(""Hello, World!""); + return await Task.FromResult(42); + } + }", config, aot); + + [Theory] + [MemberData(nameof(ConfigWithAOTData), parameters: /*aot*/ true)] + public void NonAsyncMain(string config, bool aot) + => TestMain("non_async_main", @" + using System; + using System.Threading.Tasks; + + public class TestClass { + public static int Main() + { + Console.WriteLine(""Hello, World!""); + return 42; + } + }", config, aot); + + public static TheoryData MainWithArgsTestData() + { + var data = new TheoryData(); + foreach (var configData in ConfigWithAOTData()) + { + data.Add((string)configData[0], (bool)configData[1], new string[] { "abc", "foobar" }); + data.Add((string)configData[0], (bool)configData[1], new string[0]); + } + + return data; + } + + [Theory] + [MemberData(nameof(MainWithArgsTestData))] + public void NonAsyncMainWithArgs(string config, bool aot, string[] args) + => TestMainWithArgs("non_async_main_args", @" + public class TestClass { + public static int Main(string[] args) + { + ##CODE## + return 42 + count; + } + }", config, aot, args); + + [Theory] + [MemberData(nameof(MainWithArgsTestData))] + public void AsyncMainWithArgs(string config, bool aot, string[] args) + => TestMainWithArgs("async_main_args", @" + public class TestClass { + public static async System.Threading.Tasks.Task Main(string[] args) + { + ##CODE## + return await System.Threading.Tasks.Task.FromResult(42 + count); + } + }", config, aot, args); + + [Theory] + [MemberData(nameof(MainWithArgsTestData))] + public void TopLevelWithArgs(string config, bool aot, string[] args) + => TestMainWithArgs("top_level_args", + @"##CODE## return await System.Threading.Tasks.Task.FromResult(42 + count);", + config, aot, args); + + void TestMain(string projectName, string programText, string config, bool aot) + { + File.WriteAllText(Path.Combine(_tempDir, "Program.cs"), programText); + BuildProject(projectName, config, aot: aot); + RunAndTestWasmApp(projectName, config, isAOT: aot, expectedExitCode: 42, + test: output => Assert.Contains("Hello, World!", output)); + } + + void TestMainWithArgs(string projectName, string programFormatString, string config, bool aot, string[] args) + { + string code = @" + int count = args == null ? 0 : args.Length; + System.Console.WriteLine($""args#: {args?.Length}""); + foreach (var arg in args ?? System.Array.Empty()) + System.Console.WriteLine($""arg: {arg}""); + "; + string programText = programFormatString.Replace("##CODE##", code); + + File.WriteAllText(Path.Combine(_tempDir, "Program.cs"), programText); + BuildProject(projectName, config, aot: aot); + RunAndTestWasmApp(projectName, config, isAOT: aot, expectedExitCode: 42 + args.Length, args: string.Join(' ', args), + test: output => + { + Assert.Contains($"args#: {args.Length}", output); + foreach (var arg in args) + Assert.Contains($"arg: {arg}", output); + }); + } + + private void RunAndTestWasmApp(string projectName, string config, bool isAOT, Action test, int expectedExitCode=0, string? args=null) + { + Dictionary? envVars = new(); + envVars["XHARNESS_DISABLE_COLORED_OUTPUT"] = "true"; + if (isAOT) + { + envVars["EMSDK_PATH"] = s_emsdkPath; + envVars["MONO_LOG_LEVEL"] = "debug"; + envVars["MONO_LOG_MASK"] = "aot"; + } + + string bundleDir = Path.Combine(GetBinDir(config: config), "AppBundle"); + string v8output = RunWasmTest(projectName, bundleDir, envVars, expectedExitCode, appArgs: args); + Test(v8output); + + string browserOutput = RunWasmTestBrowser(projectName, bundleDir, envVars, expectedExitCode, appArgs: args); + Test(browserOutput); + + void Test(string output) + { + if (isAOT) + { + Assert.Contains("AOT: image 'System.Private.CoreLib' found.", output); + Assert.Contains($"AOT: image '{projectName}' found.", output); + } + else + { + Assert.DoesNotContain("AOT: image 'System.Private.CoreLib' found.", output); + Assert.DoesNotContain($"AOT: image '{projectName}' found.", output); + } + } + } + + private string RunWithXHarness(string testCommand, string relativeLogPath, string projectName, string bundleDir, IDictionary? envVars=null, + int expectedAppExitCode=0, int xharnessExitCode=0, string? extraXHarnessArgs=null, string? appArgs=null) + { + _testOutput.WriteLine($"============== {testCommand} ============="); + Console.WriteLine($"============== {testCommand} ============="); + string testLogPath = Path.Combine(_logPath, relativeLogPath); + + StringBuilder args = new(); + args.Append($"exec {s_xharnessRunnerCommand}"); + args.Append($" {testCommand}"); + args.Append($" --app=."); + args.Append($" --output-directory={testLogPath}"); + args.Append($" --expected-exit-code={expectedAppExitCode}"); + args.Append($" {extraXHarnessArgs ?? string.Empty}"); + + args.Append(" -- "); + // App arguments + + if (envVars != null) + { + var setenv = string.Join(' ', envVars.Select(kvp => $"--setenv={kvp.Key}={kvp.Value}").ToArray()); + args.Append($" {setenv}"); + } + + args.Append($" --run {projectName}.dll"); + args.Append($" {appArgs ?? string.Empty}"); + + var (exitCode, output) = RunProcess("dotnet", + args: args.ToString(), + workingDir: bundleDir, + envVars: envVars, + label: testCommand); + + File.WriteAllText(Path.Combine(testLogPath, $"xharness.log"), output); + + if (exitCode != xharnessExitCode) + { + _testOutput.WriteLine($"Exit code: {exitCode}"); + Assert.True(exitCode == expectedAppExitCode, $"[{testCommand}] Exit code, expected {expectedAppExitCode} but got {exitCode}"); + } + + return output; + } + private string RunWasmTest(string projectName, string bundleDir, IDictionary? envVars=null, int expectedAppExitCode=0, int xharnessExitCode=0, string? appArgs=null) + => RunWithXHarness("wasm test", "wasm-test", projectName, bundleDir, + envVars: envVars, + expectedAppExitCode: expectedAppExitCode, + extraXHarnessArgs: "--js-file=runtime.js --engine=V8 -v trace", + appArgs: appArgs); + + private string RunWasmTestBrowser(string projectName, string bundleDir, IDictionary? envVars=null, int expectedAppExitCode=0, int xharnessExitCode=0, string? appArgs=null) + => RunWithXHarness("wasm test-browser", "wasm-test-browser", projectName, bundleDir, + envVars: envVars, + expectedAppExitCode: expectedAppExitCode, + extraXHarnessArgs: "-v trace", // needed to get messages like those for AOT loading + appArgs: appArgs); + + private static void InitProjectDir(string dir) + { + File.WriteAllText(Path.Combine(dir, "Directory.Build.props"), s_directoryBuildProps); + File.WriteAllText(Path.Combine(dir, "Directory.Build.targets"), s_directoryBuildTargets); + } + + private void BuildProject(string projectName, + string config, + string? extraBuildArgs = null, + string? extraProperties = null, + bool aot = false, + bool? dotnetWasmFromRuntimePack = null, + bool hasIcudt = true) + { + if (aot) + extraProperties = $"{extraProperties}\ntrue\n"; + + InitProjectDir(_tempDir); + + File.WriteAllText(Path.Combine(_tempDir, $"{projectName}.csproj"), +@$" + + {s_targetFramework} + Exe + true + runtime-test.js + {extraProperties ?? string.Empty} + +"); + + File.Copy(Path.Combine(AppContext.BaseDirectory, "runtime-test.js"), Path.Combine(_tempDir, "runtime-test.js")); + + StringBuilder sb = new(); + sb.Append("publish"); + sb.Append(s_defaultBuildArgs); + + sb.Append($" /p:Configuration={config}"); + + string logFilePath = Path.Combine(_logPath, $"{projectName}.binlog"); + _testOutput.WriteLine($"Binlog path: {logFilePath}"); + sb.Append($" /bl:\"{logFilePath}\" /v:minimal /nologo"); + if (extraBuildArgs != null) + sb.Append($" {extraBuildArgs} "); + + AssertBuild(sb.ToString()); + + string bundleDir = Path.Combine(GetBinDir(config: config), "AppBundle"); + AssertBasicAppBundle(bundleDir, projectName, config, hasIcudt); + + dotnetWasmFromRuntimePack ??= !aot; + AssertDotNetWasmJs(bundleDir, fromRuntimePack: dotnetWasmFromRuntimePack.Value); + } + + private static void AssertBasicAppBundle(string bundleDir, string projectName, string config, bool hasIcudt=true) + { + AssertFilesExist(bundleDir, new [] + { + "index.html", + "runtime.js", + "dotnet.timezones.blat", + "dotnet.wasm", + "mono-config.js", + "dotnet.js", + "run-v8.sh" + }); + + AssertFilesExist(bundleDir, new[] { "icudt.dat" }, expectToExist: hasIcudt); + + string managedDir = Path.Combine(bundleDir, "managed"); + AssertFilesExist(managedDir, new[] { $"{projectName}.dll" }); + + bool is_debug = config == "Debug"; + if (is_debug) + { + // Use cecil to check embedded pdb? + // AssertFilesExist(managedDir, new[] { $"{projectName}.pdb" }); + + //FIXME: um.. what about these? embedded? why is linker omitting them? + //foreach (string file in Directory.EnumerateFiles(managedDir, "*.dll")) + //{ + //string pdb = Path.ChangeExtension(file, ".pdb"); + //Assert.True(File.Exists(pdb), $"Could not find {pdb} for {file}"); + //} + } + } + + private void AssertDotNetWasmJs(string bundleDir, bool fromRuntimePack) + { + string nativeDir = GetRuntimeNativeDir(); + + AssertFile(Path.Combine(nativeDir, "dotnet.wasm"), Path.Combine(bundleDir, "dotnet.wasm"), "Expected dotnet.wasm to be same as the runtime pack", same: fromRuntimePack); + AssertFile(Path.Combine(nativeDir, "dotnet.js"), Path.Combine(bundleDir, "dotnet.js"), "Expected dotnet.js to be same as the runtime pack", same: fromRuntimePack); + } + + private static void AssertFilesDontExist(string dir, string[] filenames, string? label = null) + => AssertFilesExist(dir, filenames, label, expectToExist: false); + + private static void AssertFilesExist(string dir, string[] filenames, string? label = null, bool expectToExist=true) + { + Assert.True(Directory.Exists(dir), $"[{label}] {dir} not found"); + foreach (string filename in filenames) + { + string path = Path.Combine(dir, filename); + + if (expectToExist) + { + Assert.True(File.Exists(path), + label != null + ? $"{label}: {path} doesn't exist" + : $"{path} doesn't exist"); + } + else + { + Assert.False(File.Exists(path), + label != null + ? $"{label}: {path} should not exist" + : $"{path} should not exist"); + } + } + } + + private static void AssertSameFile(string file0, string file1, string? label=null) => AssertFile(file0, file1, label, same: true); + private static void AssertNotSameFile(string file0, string file1, string? label=null) => AssertFile(file0, file1, label, same: false); + + private static void AssertFile(string file0, string file1, string? label=null, bool same=true) + { + Assert.True(File.Exists(file0), $"{label}: Expected to find {file0}"); + Assert.True(File.Exists(file1), $"{label}: Expected to find {file1}"); + + FileInfo finfo0 = new(file0); + FileInfo finfo1 = new(file1); + + if (same) + Assert.True(finfo0.Length == finfo1.Length, $"{label}: File sizes don't match for {file0} ({finfo0.Length}), and {file1} ({finfo1.Length})"); + else + Assert.True(finfo0.Length != finfo1.Length, $"{label}: File sizes should not match for {file0} ({finfo0.Length}), and {file1} ({finfo1.Length})"); + } + + private void AssertBuild(string args) + { + (int exitCode, _) = RunProcess("dotnet", args, workingDir: _tempDir, label: "build"); + Assert.True(0 == exitCode, $"Build process exited with non-zero exit code: {exitCode}"); + } + + private string GetObjDir(string targetFramework=s_targetFramework, string? baseDir=null, string config="Debug") + => Path.Combine(baseDir ?? _tempDir, "obj", config, targetFramework, "browser-wasm", "wasm"); + + private string GetBinDir(string targetFramework=s_targetFramework, string? baseDir=null, string config="Debug") + => Path.Combine(baseDir ?? _tempDir, "bin", config, targetFramework, "browser-wasm"); + + private string GetRuntimePackDir() => s_runtimePackDir; + + private string GetRuntimeNativeDir() + => Path.Combine(GetRuntimePackDir(), "runtimes", "browser-wasm", "native"); + + public void Dispose() + { + if (s_skipProjectCleanup) + return; + + try + { + Directory.Delete(_tempDir, recursive: true); + } + catch + { + Console.Error.WriteLine($"Failed to delete '{_tempDir}' during test cleanup"); + } + } + + private (int, string) RunProcess(string path, + string args = "", + IDictionary? envVars = null, + string? workingDir = null, + string? label = null, + bool logToXUnit = true) + { + _testOutput.WriteLine($"Running: {path} {args}"); + StringBuilder outputBuilder = new (); + var processStartInfo = new ProcessStartInfo + { + FileName = path, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardError = true, + RedirectStandardOutput = true, + Arguments = args, + }; + + if (workingDir != null) + processStartInfo.WorkingDirectory = workingDir; + + if (envVars != null) + { + if (envVars.Count > 0) + _testOutput.WriteLine("Setting environment variables for execution:"); + + foreach (KeyValuePair envVar in envVars) + { + processStartInfo.EnvironmentVariables[envVar.Key] = envVar.Value; + _testOutput.WriteLine($"\t{envVar.Key} = {envVar.Value}"); + } + } + + Process? process = Process.Start(processStartInfo); + if (process == null) + throw new ArgumentException($"Process.Start({path} {args}) returned null process"); + + process.ErrorDataReceived += (sender, e) => LogData("[stderr]", e.Data); + process.OutputDataReceived += (sender, e) => LogData("[stdout]", e.Data); + + try + { + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + process.WaitForExit(); + + return (process.ExitCode, outputBuilder.ToString().Trim('\r', '\n')); + } + catch + { + Console.WriteLine(outputBuilder.ToString()); + throw; + } + + void LogData(string label, string? message) + { + if (logToXUnit && message != null) + { + _testOutput.WriteLine($"{label} {message}"); + } + outputBuilder.AppendLine($"{label} {message}"); + } + } + + private static string s_directoryBuildProps = @" + + <_WasmTargetsDir Condition=""'$(RuntimeSrcDir)' != ''"">$(RuntimeSrcDir)\src\mono\wasm\build\ + <_WasmTargetsDir Condition=""'$(WasmBuildSupportDir)' != ''"">$(WasmBuildSupportDir)\wasm\ + $(WasmBuildSupportDir)\emsdk\ + + + + + + + PrepareForWasmBuild;$(WasmBuildAppDependsOn) + +"; + + private static string s_directoryBuildTargets = @" + + + + + + + + + + + + + + + + + + +"; + + } + + } diff --git a/src/tests/Common/dirs.proj b/src/tests/Common/dirs.proj index e12d882d1dc67..53a064e6e0e0c 100644 --- a/src/tests/Common/dirs.proj +++ b/src/tests/Common/dirs.proj @@ -10,6 +10,7 @@ + From d9a7eba84072e2b87c8259849d4563fd40850a76 Mon Sep 17 00:00:00 2001 From: gekka <10055381+gekka@users.noreply.github.com> Date: Wed, 10 Mar 2021 05:31:18 +0900 Subject: [PATCH 61/83] Fix to release memory allocated by AllocHGlobal (#48059) --- .../System/Net/NetworkInformation/SystemIPGlobalProperties.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs index 8eb836a9725b7..dff0aad267f73 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs @@ -194,7 +194,7 @@ private unsafe List GetAllTcpConnections() } } } - catch + finally { Marshal.FreeHGlobal(buffer); } From 9ae7e7ebf52cbe624b19db38b8d404056b725c33 Mon Sep 17 00:00:00 2001 From: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Wed, 10 Mar 2021 00:32:05 +0300 Subject: [PATCH 62/83] Do not block folding of unsigned (and unordered) comparisons in value numbering (#48568) * Do not block folding of unsigned comparisons in value numbering * Handle unordered FP comparisons in ValueNumStore::EvalComparison * Added coverage of evaluating unordered FP comparisons of constants in value numbering * Do not block evaluation of unordered comparisons with NaNs in ValueNumStore::VNForFunc * Added coverage of early folding logic for cgt.un.r4 * Added coverage of early folding logic for cgt.un.r8 * Added coverage of early folding logic for clt.un.r4 * Added coverage of early folding logic for clt.un.r8 * Improve placement of comments * Added coverage of early folding logic for bge.un.r4 * Added coverage of early folding logic for bge.un.r8 * Added coverage of early folding logic for bgt.un.r4 * Added coverage of early folding logic for bgt.un.r8 * Added coverage of early folding logic for ble.un.r4 * Added coverage of early folding logic for ble.un.r8 * Added coverage of early folding logic for blt.un.r4 * Added coverage of early folding logic for blt.un.r8 * Added coverage of early folding logic for bne.un.r4 * Added coverage of early folding logic for bne.un.r8 --- src/coreclr/jit/valuenum.cpp | 50 +- ...ring_unordered_comparisons_of_constants.cs | 766 ++++++++++++++++++ ...ordered_comparisons_of_constants_ro.csproj | 13 + .../Old/Conformance_Base/bge_un_r4.il | 464 ++++++++++- .../Old/Conformance_Base/bge_un_r8.il | 467 ++++++++++- .../Old/Conformance_Base/bgt_un_r4.il | 643 ++++++++++++--- .../Old/Conformance_Base/bgt_un_r8.il | 643 ++++++++++++--- .../Old/Conformance_Base/ble_un_r4.il | 663 ++++++++++++--- .../Old/Conformance_Base/ble_un_r8.il | 663 ++++++++++++--- .../Old/Conformance_Base/blt_un_r4.il | 643 ++++++++++++--- .../Old/Conformance_Base/blt_un_r8.il | 643 ++++++++++++--- .../Old/Conformance_Base/bne_un_r4.il | 696 +++++++++++++--- .../Old/Conformance_Base/bne_un_r8.il | 696 +++++++++++++--- .../Old/Conformance_Base/cgt_un_r4.il | 634 ++++++++++++--- .../Old/Conformance_Base/cgt_un_r8.il | 634 ++++++++++++--- .../Old/Conformance_Base/clt_un_r4.il | 634 ++++++++++++--- .../Old/Conformance_Base/clt_un_r8.il | 631 ++++++++++++--- 17 files changed, 8241 insertions(+), 1342 deletions(-) create mode 100644 src/tests/JIT/Directed/ConstantFolding/value_numbering_unordered_comparisons_of_constants.cs create mode 100644 src/tests/JIT/Directed/ConstantFolding/value_numbering_unordered_comparisons_of_constants_ro.csproj diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 11825b08952d8..a128ae6f92959 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -790,6 +790,29 @@ int ValueNumStore::EvalComparison(VNFunc vnf, double v0, double v1) break; } } + else // must be a VNF_ function + { + if (hasNanArg) + { + // unordered comparisons with NaNs always return true + return true; + } + + switch (vnf) + { + case VNF_GT_UN: + return v0 > v1; + case VNF_GE_UN: + return v0 >= v1; + case VNF_LT_UN: + return v0 < v1; + case VNF_LE_UN: + return v0 <= v1; + default: + // For any other value of 'vnf', we will assert below + break; + } + } noway_assert(!"Unhandled operation in EvalComparison"); return 0; } @@ -835,8 +858,8 @@ int ValueNumStore::EvalComparison(VNFunc vnf, float v0, float v1) { if (hasNanArg) { - // always returns true - return false; + // unordered comparisons with NaNs always return true + return true; } switch (vnf) @@ -1926,18 +1949,6 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V canFold = false; } - // NaNs are unordered wrt to other floats. While an ordered - // comparison would return false, an unordered comparison - // will return true if any operands are a NaN. We only perform - // ordered NaN comparison in EvalComparison. - if ((arg0IsFloating && (((arg0VNtyp == TYP_FLOAT) && _isnanf(GetConstantSingle(arg0VN))) || - ((arg0VNtyp == TYP_DOUBLE) && _isnan(GetConstantDouble(arg0VN))))) || - (arg1IsFloating && (((arg1VNtyp == TYP_FLOAT) && _isnanf(GetConstantSingle(arg1VN))) || - ((arg1VNtyp == TYP_DOUBLE) && _isnan(GetConstantDouble(arg1VN)))))) - { - canFold = false; - } - if (typ == TYP_BYREF) { // We don't want to fold expressions that produce TYP_BYREF @@ -3117,13 +3128,10 @@ bool ValueNumStore::CanEvalForConstantArgs(VNFunc vnf) // some VNF_ that we can evaluate switch (vnf) { - // Consider adding: - // case VNF_GT_UN: - // case VNF_GE_UN: - // case VNF_LT_UN: - // case VNF_LE_UN: - // - + case VNF_GT_UN: + case VNF_GE_UN: + case VNF_LT_UN: + case VNF_LE_UN: case VNF_Cast: // We can evaluate these. return true; diff --git a/src/tests/JIT/Directed/ConstantFolding/value_numbering_unordered_comparisons_of_constants.cs b/src/tests/JIT/Directed/ConstantFolding/value_numbering_unordered_comparisons_of_constants.cs new file mode 100644 index 0000000000000..1904ebbd2a246 --- /dev/null +++ b/src/tests/JIT/Directed/ConstantFolding/value_numbering_unordered_comparisons_of_constants.cs @@ -0,0 +1,766 @@ +using System; +using System.Runtime.CompilerServices; + +public class ValueNumberingUnorderedComparisonsOfConstants +{ + private static readonly double _quietDoubleNaN = BitConverter.Int64BitsToDouble(unchecked((long)0xfff8000000000001)); + private static readonly float _quietFloatNaN = BitConverter.Int32BitsToSingle(unchecked((int)0xffc00001)); + + private static int _counter = 100; + + public static int Main() + { + // The conditions of the loops get reversed and duplicated. + // As part of this a comparison like a > b, which is really !IsNaN(a) && !IsNaN(b) && a > b + // Gets turned into IsNaN(a) || IsNaN(b) || a <= b. + // We are testing that the constant folding of these new unordered comparisons in VN is correct. + + TestDoubleComparisonsEvaluatingToTrue(); + TestSingleComparisonsEvaluatingToTrue(); + TestDoubleComparisonsEvaluatingToFalse(); + TestSingleComparisonsEvaluatingToFalse(); + + return _counter; + } + + // We rely on these static readonly fields being constants at compile time. + // This means that by the time the test methods are being compiled, the static constructor must have run. + [ModuleInitializer] + internal static void InitializeNaNs() => RuntimeHelpers.RunClassConstructor(typeof(ValueNumberingUnorderedComparisonsOfConstants).TypeHandle); + + private static void TestDoubleComparisonsEvaluatingToTrue() + { + // The following inverted conditions must be folded to "true". + // Meaning the loop body must never execute. + + // Basic scenarios + // VNF_LT_UN + for (double i = 1.0; i >= 2.0; i++) + _counter++; + // VNF_LE_UN + for (double i = -3.0; i > 4.0; i++) + _counter++; + for (double i = 5.0; i > 5.0; i++) + _counter++; + for (double i = 0.0; i > -0.0; i++) + _counter++; + // VNF_GT_UN + for (double i = 6.0; i <= -7.0; i++) + _counter++; + // VNF_GE_UN + for (double i = 8.0; i < -9.0; i++) + _counter++; + for (double i = 10.0; i < 10.0; i++) + _counter++; + for (double i = -0.0; i < 0.0; i++) + _counter++; + + // Positive infinities on the lhs + // VNF_GT_UN + for (double i = double.PositiveInfinity; i <= 11.0; i++) + _counter++; + // VNF_GE_UN + for (double i = double.PositiveInfinity; i < 12.0; i++) + _counter++; + + // Positive infinities on the rhs + // VNF_LT_UN + for (double i = 13.0; i >= double.PositiveInfinity; i++) + _counter++; + // VNF_LE_UN + for (double i = -14.0; i > double.PositiveInfinity; i++) + _counter++; + + // Positive infinities on both sides + // VNF_LE_UN + for (double i = double.PositiveInfinity; i > double.PositiveInfinity; i++) + _counter++; + // VNF_GE_UN + for (double i = double.PositiveInfinity; i < double.PositiveInfinity; i++) + _counter++; + + // Negative infinities on the lhs + // VNF_LT_UN + for (double i = double.NegativeInfinity; i >= 15.0; i++) + _counter++; + // VNF_LE_UN + for (double i = double.NegativeInfinity; i > 16.0; i++) + _counter++; + + // Negative infinities on the rhs + // VNF_GT_UN + for (double i = 17.0; i <= double.NegativeInfinity; i++) + _counter++; + // VNF_GE_UN + for (double i = 18.0; i < double.NegativeInfinity; i++) + _counter++; + + // Negative infinities on both sides + // VNF_LE_UN + for (double i = double.NegativeInfinity; i > double.NegativeInfinity; i++) + _counter++; + // VNF_GE_UN + for (double i = double.NegativeInfinity; i < double.NegativeInfinity; i++) + _counter++; + + // NaN on the lhs + // VNF_LT_UN + for (double i = double.NaN; i >= 19.0; i++) + _counter++; + for (double i = double.NaN; i >= double.PositiveInfinity; i++) + _counter++; + for (double i = double.NaN; i >= double.NegativeInfinity; i++) + _counter++; + for (double i = _quietDoubleNaN; i >= 19.0; i++) + _counter++; + for (double i = _quietDoubleNaN; i >= double.PositiveInfinity; i++) + _counter++; + for (double i = _quietDoubleNaN; i >= double.NegativeInfinity; i++) + _counter++; + // VNF_LE_UN + for (double i = double.NaN; i > 20.0; i++) + _counter++; + for (double i = double.NaN; i > double.PositiveInfinity; i++) + _counter++; + for (double i = double.NaN; i > double.NegativeInfinity; i++) + _counter++; + for (double i = _quietDoubleNaN; i > 20.0; i++) + _counter++; + for (double i = _quietDoubleNaN; i > double.PositiveInfinity; i++) + _counter++; + for (double i = _quietDoubleNaN; i > double.NegativeInfinity; i++) + _counter++; + // VNF_GT_UN + for (double i = double.NaN; i <= -21.0; i++) + _counter++; + for (double i = double.NaN; i <= double.PositiveInfinity; i++) + _counter++; + for (double i = double.NaN; i <= double.NegativeInfinity; i++) + _counter++; + for (double i = _quietDoubleNaN; i <= -21.0; i++) + _counter++; + for (double i = _quietDoubleNaN; i <= double.PositiveInfinity; i++) + _counter++; + for (double i = _quietDoubleNaN; i <= double.NegativeInfinity; i++) + _counter++; + // VNF_GE_UN + for (double i = double.NaN; i < 22.0; i++) + _counter++; + for (double i = double.NaN; i < double.PositiveInfinity; i++) + _counter++; + for (double i = double.NaN; i < double.NegativeInfinity; i++) + _counter++; + for (double i = _quietDoubleNaN; i < 22.0; i++) + _counter++; + for (double i = _quietDoubleNaN; i < double.PositiveInfinity; i++) + _counter++; + for (double i = _quietDoubleNaN; i < double.NegativeInfinity; i++) + _counter++; + + // NaN on the rhs + // VNF_LT_UN + for (double i = 23.0; i >= double.NaN; i++) + _counter++; + for (double i = double.NegativeInfinity; i >= double.NaN; i++) + _counter++; + for (double i = double.PositiveInfinity; i >= double.NaN; i++) + _counter++; + for (double i = 23.0; i >= _quietDoubleNaN; i++) + _counter++; + for (double i = double.NegativeInfinity; i >= _quietDoubleNaN; i++) + _counter++; + for (double i = double.PositiveInfinity; i >= _quietDoubleNaN; i++) + _counter++; + // VNF_LE_UN + for (double i = -24.0; i > double.NaN; i++) + _counter++; + for (double i = double.NegativeInfinity; i > double.NaN; i++) + _counter++; + for (double i = double.PositiveInfinity; i > double.NaN; i++) + _counter++; + for (double i = -24.0; i > _quietDoubleNaN; i++) + _counter++; + for (double i = double.NegativeInfinity; i > _quietDoubleNaN; i++) + _counter++; + for (double i = double.PositiveInfinity; i > _quietDoubleNaN; i++) + _counter++; + // VNF_GT_UN + for (double i = 25.0; i <= double.NaN; i++) + _counter++; + for (double i = double.NegativeInfinity; i <= double.NaN; i++) + _counter++; + for (double i = double.PositiveInfinity; i <= double.NaN; i++) + _counter++; + for (double i = 25.0; i <= _quietDoubleNaN; i++) + _counter++; + for (double i = double.NegativeInfinity; i <= _quietDoubleNaN; i++) + _counter++; + for (double i = double.PositiveInfinity; i <= _quietDoubleNaN; i++) + _counter++; + // VNF_GE_UN + for (double i = 26.0; i < double.NaN; i++) + _counter++; + for (double i = double.NegativeInfinity; i < double.NaN; i++) + _counter++; + for (double i = double.PositiveInfinity; i < double.NaN; i++) + _counter++; + for (double i = 26.0; i < _quietDoubleNaN; i++) + _counter++; + for (double i = double.NegativeInfinity; i < _quietDoubleNaN; i++) + _counter++; + for (double i = double.PositiveInfinity; i < _quietDoubleNaN; i++) + _counter++; + + // NaN on both sides + // VNF_LT_UN + for (double i = double.NaN; i >= double.NaN; i++) + _counter++; + for (double i = double.NaN; i >= _quietDoubleNaN; i++) + _counter++; + for (double i = _quietDoubleNaN; i >= double.NaN; i++) + _counter++; + for (double i = _quietDoubleNaN; i >= _quietDoubleNaN; i++) + _counter++; + // VNF_LE_UN + for (double i = double.NaN; i > double.NaN; i++) + _counter++; + for (double i = double.NaN; i > _quietDoubleNaN; i++) + _counter++; + for (double i = _quietDoubleNaN; i > double.NaN; i++) + _counter++; + for (double i = _quietDoubleNaN; i > _quietDoubleNaN; i++) + _counter++; + // VNF_GT_UN + for (double i = double.NaN; i <= double.NaN; i++) + _counter++; + for (double i = double.NaN; i <= _quietDoubleNaN; i++) + _counter++; + for (double i = _quietDoubleNaN; i <= double.NaN; i++) + _counter++; + for (double i = _quietDoubleNaN; i <= _quietDoubleNaN; i++) + _counter++; + // VNF_GE_UN + for (double i = double.NaN; i < double.NaN; i++) + _counter++; + for (double i = double.NaN; i < _quietDoubleNaN; i++) + _counter++; + for (double i = _quietDoubleNaN; i < double.NaN; i++) + _counter++; + for (double i = _quietDoubleNaN; i < _quietDoubleNaN; i++) + _counter++; + } + + private static void TestSingleComparisonsEvaluatingToTrue() + { + // The following inverted conditions must be folded to "true". + // Meaning the loop body must never execute. + + // Basic scenarios + // VNF_LT_UN + for (float i = 27.0f; i >= 28.0f; i++) + _counter++; + // VNF_LE_UN + for (float i = -29.0f; i > 30.0f; i++) + _counter++; + for (float i = 31.0f; i > 31.0f; i++) + _counter++; + for (float i = 0.0f; i > -0.0f; i++) + _counter++; + // VNF_GT_UN + for (float i = 32.0f; i <= -33.0f; i++) + _counter++; + // VNF_GE_UN + for (float i = 34.0f; i < -35.0f; i++) + _counter++; + for (float i = 36.0f; i < 36.0f; i++) + _counter++; + for (float i = -0.0f; i < 0.0f; i++) + _counter++; + + // Positive infinities on the lhs + // VNF_GT_UN + for (float i = float.PositiveInfinity; i <= 37.0f; i++) + _counter++; + // VNF_GE_UN + for (float i = float.PositiveInfinity; i < 38.0f; i++) + _counter++; + + // Positive infinities on the rhs + // VNF_LT_UN + for (float i = 39.0f; i >= float.PositiveInfinity; i++) + _counter++; + // VNF_LE_UN + for (float i = -40.0f; i > float.PositiveInfinity; i++) + _counter++; + + // Positive infinities on both sides + // VNF_LE_UN + for (float i = float.PositiveInfinity; i > float.PositiveInfinity; i++) + _counter++; + // VNF_GE_UN + for (float i = float.PositiveInfinity; i < float.PositiveInfinity; i++) + _counter++; + + // Negative infinities on the lhs + // VNF_LT_UN + for (float i = float.NegativeInfinity; i >= 41.0f; i++) + _counter++; + // VNF_LE_UN + for (float i = float.NegativeInfinity; i > 42.0f; i++) + _counter++; + + // Negative infinities on the rhs + // VNF_GT_UN + for (float i = 43.0f; i <= float.NegativeInfinity; i++) + _counter++; + // VNF_GE_UN + for (float i = 44.0f; i < float.NegativeInfinity; i++) + _counter++; + + // Negative infinities on both sides + // VNF_LE_UN + for (float i = float.NegativeInfinity; i > float.NegativeInfinity; i++) + _counter++; + // VNF_GE_UN + for (float i = float.NegativeInfinity; i < float.NegativeInfinity; i++) + _counter++; + + // NaN on the lhs + // VNF_LT_UN + for (float i = float.NaN; i >= 45.0f; i++) + _counter++; + for (float i = float.NaN; i >= float.PositiveInfinity; i++) + _counter++; + for (float i = float.NaN; i >= float.NegativeInfinity; i++) + _counter++; + for (float i = _quietFloatNaN; i >= 45.0f; i++) + _counter++; + for (float i = _quietFloatNaN; i >= float.PositiveInfinity; i++) + _counter++; + for (float i = _quietFloatNaN; i >= float.NegativeInfinity; i++) + _counter++; + // VNF_LE_UN + for (float i = float.NaN; i > 46.0f; i++) + _counter++; + for (float i = float.NaN; i > float.PositiveInfinity; i++) + _counter++; + for (float i = float.NaN; i > float.NegativeInfinity; i++) + _counter++; + for (float i = _quietFloatNaN; i > 46.0f; i++) + _counter++; + for (float i = _quietFloatNaN; i > float.PositiveInfinity; i++) + _counter++; + for (float i = _quietFloatNaN; i > float.NegativeInfinity; i++) + _counter++; + // VNF_GT_UN + for (float i = float.NaN; i <= -47.0f; i++) + _counter++; + for (float i = float.NaN; i <= float.PositiveInfinity; i++) + _counter++; + for (float i = float.NaN; i <= float.NegativeInfinity; i++) + _counter++; + for (float i = _quietFloatNaN; i <= -47.0f; i++) + _counter++; + for (float i = _quietFloatNaN; i <= float.PositiveInfinity; i++) + _counter++; + for (float i = _quietFloatNaN; i <= float.NegativeInfinity; i++) + _counter++; + // VNF_GE_UN + for (float i = float.NaN; i < 48.0f; i++) + _counter++; + for (float i = float.NaN; i < float.PositiveInfinity; i++) + _counter++; + for (float i = float.NaN; i < float.NegativeInfinity; i++) + _counter++; + for (float i = _quietFloatNaN; i < 48.0f; i++) + _counter++; + for (float i = _quietFloatNaN; i < float.PositiveInfinity; i++) + _counter++; + for (float i = _quietFloatNaN; i < float.NegativeInfinity; i++) + _counter++; + + // NaN on the rhs + // VNF_LT_UN + for (float i = 49.0f; i >= float.NaN; i++) + _counter++; + for (float i = float.NegativeInfinity; i >= float.NaN; i++) + _counter++; + for (float i = float.PositiveInfinity; i >= float.NaN; i++) + _counter++; + for (float i = 49.0f; i >= _quietFloatNaN; i++) + _counter++; + for (float i = float.NegativeInfinity; i >= _quietFloatNaN; i++) + _counter++; + for (float i = float.PositiveInfinity; i >= _quietFloatNaN; i++) + _counter++; + // VNF_LE_UN + for (float i = -50.0f; i > float.NaN; i++) + _counter++; + for (float i = float.NegativeInfinity; i > float.NaN; i++) + _counter++; + for (float i = float.PositiveInfinity; i > float.NaN; i++) + _counter++; + for (float i = -50.0f; i > _quietFloatNaN; i++) + _counter++; + for (float i = float.NegativeInfinity; i > _quietFloatNaN; i++) + _counter++; + for (float i = float.PositiveInfinity; i > _quietFloatNaN; i++) + _counter++; + // VNF_GT_UN + for (float i = 51.0f; i <= float.NaN; i++) + _counter++; + for (float i = float.NegativeInfinity; i <= float.NaN; i++) + _counter++; + for (float i = float.PositiveInfinity; i <= float.NaN; i++) + _counter++; + for (float i = 51.0f; i <= _quietFloatNaN; i++) + _counter++; + for (float i = float.NegativeInfinity; i <= _quietFloatNaN; i++) + _counter++; + for (float i = float.PositiveInfinity; i <= _quietFloatNaN; i++) + _counter++; + // VNF_GE_UN + for (float i = 52.0f; i < float.NaN; i++) + _counter++; + for (float i = float.NegativeInfinity; i < float.NaN; i++) + _counter++; + for (float i = float.PositiveInfinity; i < float.NaN; i++) + _counter++; + for (float i = 52.0f; i < _quietFloatNaN; i++) + _counter++; + for (float i = float.NegativeInfinity; i < _quietFloatNaN; i++) + _counter++; + for (float i = float.PositiveInfinity; i < _quietFloatNaN; i++) + _counter++; + + // NaN on both sides + // VNF_LT_UN + for (float i = float.NaN; i >= float.NaN; i++) + _counter++; + for (float i = float.NaN; i >= _quietFloatNaN; i++) + _counter++; + for (float i = _quietFloatNaN; i >= float.NaN; i++) + _counter++; + for (float i = _quietFloatNaN; i >= _quietFloatNaN; i++) + _counter++; + // VNF_LE_UN + for (float i = float.NaN; i > float.NaN; i++) + _counter++; + for (float i = float.NaN; i > _quietFloatNaN; i++) + _counter++; + for (float i = _quietFloatNaN; i > float.NaN; i++) + _counter++; + for (float i = _quietFloatNaN; i > _quietFloatNaN; i++) + _counter++; + // VNF_GT_UN + for (float i = float.NaN; i <= float.NaN; i++) + _counter++; + for (float i = float.NaN; i <= _quietFloatNaN; i++) + _counter++; + for (float i = _quietFloatNaN; i <= float.NaN; i++) + _counter++; + for (float i = _quietFloatNaN; i <= _quietFloatNaN; i++) + _counter++; + // VNF_GE_UN + for (float i = float.NaN; i < float.NaN; i++) + _counter++; + for (float i = float.NaN; i < _quietFloatNaN; i++) + _counter++; + for (float i = _quietFloatNaN; i < float.NaN; i++) + _counter++; + for (float i = _quietFloatNaN; i < _quietFloatNaN; i++) + _counter++; + } + + private static void TestDoubleComparisonsEvaluatingToFalse() + { + // The following inverted conditions must be folded to "true". + // Meaning the loop body must execute. + // The "i = double.NaN" pattern is equivalent to "break". + // We use it here as it is less likely to be optimized in the future before the loop condition is duplicated. + + // Basic scenarios + // VNF_LT_UN + for (double i = 54.0; i >= 53.0; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + for (double i = 55.0; i >= 55.0; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + // VNF_LE_UN + for (double i = 56.0; i > -57.0; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + // VNF_GT_UN + for (double i = -58.0; i <= 59.0; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + for (double i = -60.0; i <= -60.0; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + // VNF_GE_UN + for (double i = -62.0; i < 61.0; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + + // Positive infinities on the lhs + // VNF_LT_UN + for (double i = double.PositiveInfinity; i >= 63.0; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + // VNF_LE_UN + for (double i = double.PositiveInfinity; i > -64.0; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + + // Positive infinities on the rhs + // VNF_GT_UN + for (double i = -65.0; i <= double.PositiveInfinity; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + // VNF_GE_UN + for (double i = -66.0; i < double.PositiveInfinity; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + + // Positive infinities on both sides + // VNF_LT_UN + for (double i = double.PositiveInfinity; i >= double.PositiveInfinity; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + // VNF_GT_UN + for (double i = double.PositiveInfinity; i <= double.PositiveInfinity; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + + // Negative infinities on the lhs + // VNF_GT_UN + for (double i = double.NegativeInfinity; i <= 67.0; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + // VNF_GE_UN + for (double i = double.NegativeInfinity; i < 68.0; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + + // Negative infinities on the rhs + // VNF_LT_UN + for (double i = 69.0; i >= double.NegativeInfinity; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + // VNF_LE_UN + for (double i = 70.0; i > double.NegativeInfinity; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + + // Negative infinities on both sides + // VNF_LT_UN + for (double i = double.NegativeInfinity; i >= double.NegativeInfinity; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + // VNF_GT_UN + for (double i = double.NegativeInfinity; i <= double.NegativeInfinity; i++) + { + _counter++; + i = double.NaN; + } + _counter--; + } + + private static void TestSingleComparisonsEvaluatingToFalse() + { + // The following inverted conditions must be folded to "true". + // Meaning the loop body must execute. + // The "i = float.NaN" pattern is equivalent to "break". + // We use it here as it is less likely to be optimized in the future before the loop condition is duplicated. + + // Basic scenarios + // VNF_LT_UN + for (float i = 71.0f; i >= 70.0f; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + for (float i = 72.0f; i >= 72.0f; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + // VNF_LE_UN + for (float i = 73.0f; i > -74.0f; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + // VNF_GT_UN + for (float i = -75.0f; i <= 76.0f; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + for (float i = -77.0f; i <= -77.0f; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + // VNF_GE_UN + for (float i = -79.0f; i < 78.0f; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + + // Positive infinities on the lhs + // VNF_LT_UN + for (float i = float.PositiveInfinity; i >= 80.0f; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + // VNF_LE_UN + for (float i = float.PositiveInfinity; i > -81.0f; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + + // Positive infinities on the rhs + // VNF_GT_UN + for (float i = -82.0f; i <= float.PositiveInfinity; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + // VNF_GE_UN + for (float i = -83.0f; i < float.PositiveInfinity; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + + // Positive infinities on both sides + // VNF_LT_UN + for (float i = float.PositiveInfinity; i >= float.PositiveInfinity; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + // VNF_GT_UN + for (float i = float.PositiveInfinity; i <= float.PositiveInfinity; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + + // Negative infinities on the lhs + // VNF_GT_UN + for (float i = float.NegativeInfinity; i <= 84.0f; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + // VNF_GE_UN + for (float i = float.NegativeInfinity; i < 85.0f; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + + // Negative infinities on the rhs + // VNF_LT_UN + for (float i = 86.0f; i >= float.NegativeInfinity; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + // VNF_LE_UN + for (float i = 87.0f; i > float.NegativeInfinity; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + + // Negative infinities on both sides + // VNF_LT_UN + for (float i = float.NegativeInfinity; i >= float.NegativeInfinity; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + // VNF_GT_UN + for (float i = float.NegativeInfinity; i <= float.NegativeInfinity; i++) + { + _counter++; + i = float.NaN; + } + _counter--; + } +} diff --git a/src/tests/JIT/Directed/ConstantFolding/value_numbering_unordered_comparisons_of_constants_ro.csproj b/src/tests/JIT/Directed/ConstantFolding/value_numbering_unordered_comparisons_of_constants_ro.csproj new file mode 100644 index 0000000000000..8cce6c7e514c0 --- /dev/null +++ b/src/tests/JIT/Directed/ConstantFolding/value_numbering_unordered_comparisons_of_constants_ro.csproj @@ -0,0 +1,13 @@ + + + Exe + 1 + + + True + None + + + + + \ No newline at end of file diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bge_un_r4.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bge_un_r4.il index 9ff23b4643573..c652ab6766c75 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bge_un_r4.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bge_un_r4.il @@ -2,11 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. .assembly extern legacy library mscorlib {} - - - .assembly extern ConvDLL{} +#define NEG_INF "float32(0xFF800000)" +#define MIN "float32(0xFF7FFFFF)" +#define MINUS_ONE "float32(0xBF800000)" +#define MINUS_ZERO "float32(0x80000000)" +#define ZERO "float32(0x00000000)" +#define ONE "float32(0x3F800000)" +#define MAX "float32(0x7F7FFFFF)" +#define POS_INF "float32(0x7F800000)" +#define NAN "float32(0x7FC00000)" + .method public static int32 main(class [mscorlib]System.String[]) { .entrypoint .maxstack 2 @@ -606,6 +613,457 @@ SS: ldfld float32 [ConvDLL]ConvDLL::NaN_r4 ldloc 0 ldfld float32 [ConvDLL]ConvDLL::NaN_r4 + bge.un L0 + br FAIL + + // Testing early folding logic + +L0: + ldc.r4 POS_INF + ldc.r4 POS_INF + bge.un L1 + br FAIL + +L1: + ldc.r4 POS_INF + ldc.r4 MAX + bge.un L2 + br FAIL + +L2: + ldc.r4 POS_INF + ldc.r4 ONE + bge.un L3 + br FAIL + +L3: + ldc.r4 POS_INF + ldc.r4 ZERO + bge.un L4 + br FAIL + +L4: + ldc.r4 POS_INF + ldc.r4 float32(0x80000000) + bge.un L5 + br FAIL + +L5: + ldc.r4 POS_INF + ldc.r4 MINUS_ONE + bge.un L6 + br FAIL + +L6: + ldc.r4 POS_INF + ldc.r4 MIN + bge.un L7 + br FAIL + +L7: + ldc.r4 POS_INF + ldc.r4 NEG_INF + bge.un L8 + br FAIL + +L8: + ldc.r4 POS_INF + ldc.r4 NAN + bge.un L9 + br FAIL + + +L9: + ldc.r4 MAX + ldc.r4 POS_INF + bge.un L10 + + ldc.r4 MAX + ldc.r4 MAX + bge.un L10 + br FAIL + +L10: + ldc.r4 MAX + ldc.r4 ONE + bge.un L11 + br FAIL + +L11: + ldc.r4 MAX + ldc.r4 ZERO + bge.un L12 + br FAIL + +L12: + ldc.r4 MAX + ldc.r4 float32(0x80000000) + bge.un L13 + br FAIL + +L13: + ldc.r4 MAX + ldc.r4 MINUS_ONE + bge.un L14 + br FAIL + +L14: + ldc.r4 MAX + ldc.r4 MIN + bge.un L15 + br FAIL + +L15: + ldc.r4 MAX + ldc.r4 NEG_INF + bge.un L16 + br FAIL + +L16: + ldc.r4 MAX + ldc.r4 NAN + bge.un L17 + br FAIL + + + +L17: + ldc.r4 ONE + ldc.r4 POS_INF + bge.un L18 + + ldc.r4 ONE + ldc.r4 MAX + bge.un L18 + + ldc.r4 ONE + ldc.r4 ONE + bge.un L18 + br FAIL + +L18: + ldc.r4 ONE + ldc.r4 ZERO + bge.un L19 + br FAIL + +L19: + ldc.r4 ONE + ldc.r4 float32(0x80000000) + bge.un L20 + br FAIL + +L20: + ldc.r4 ONE + ldc.r4 MINUS_ONE + bge.un L21 + br FAIL + +L21: + ldc.r4 ONE + ldc.r4 MIN + bge.un L22 + br FAIL + +L22: + ldc.r4 ONE + ldc.r4 NEG_INF + bge.un L23 + br FAIL + +L23: + ldc.r4 ONE + ldc.r4 NAN + bge.un L24 + br FAIL + + + +L24: + ldc.r4 ZERO + ldc.r4 POS_INF + bge.un L25 + + ldc.r4 ZERO + ldc.r4 MAX + bge.un L25 + + ldc.r4 ZERO + ldc.r4 ONE + bge.un L25 + + ldc.r4 ZERO + ldc.r4 ZERO + bge.un L25 + br FAIL + +L25: + ldc.r4 ZERO + ldc.r4 float32(0x80000000) + bge.un L26 + br FAIL + +L26: + ldc.r4 ZERO + ldc.r4 MINUS_ONE + bge.un L27 + br FAIL + +L27: + ldc.r4 ZERO + ldc.r4 MIN + bge.un L28 + br FAIL + +L28: + ldc.r4 ZERO + ldc.r4 NEG_INF + bge.un L29 + br FAIL + +L29: + ldc.r4 ZERO + ldc.r4 NAN + bge.un L30 + br FAIL + + + +L30: + ldc.r4 float32(0x80000000) + ldc.r4 POS_INF + bge.un L31 + + ldc.r4 float32(0x80000000) + ldc.r4 MAX + bge.un L31 + + ldc.r4 float32(0x80000000) + ldc.r4 ONE + bge.un L31 + + ldc.r4 float32(0x80000000) + ldc.r4 ZERO + bge.un L31 + br FAIL + +L31: + ldc.r4 float32(0x80000000) + ldc.r4 float32(0x80000000) + bge.un L32 + br FAIL + +L32: + ldc.r4 float32(0x80000000) + ldc.r4 MINUS_ONE + bge.un L33 + br FAIL + +L33: + ldc.r4 float32(0x80000000) + ldc.r4 MIN + bge.un L34 + br FAIL + +L34: + ldc.r4 float32(0x80000000) + ldc.r4 NEG_INF + bge.un L35 + br FAIL + +L35: + ldc.r4 float32(0x80000000) + ldc.r4 NAN + bge.un L36 + br FAIL + + + +L36: + ldc.r4 MINUS_ONE + ldc.r4 POS_INF + bge.un L37 + + ldc.r4 MINUS_ONE + ldc.r4 MAX + bge.un L37 + + ldc.r4 MINUS_ONE + ldc.r4 ONE + bge.un L37 + + ldc.r4 MINUS_ONE + ldc.r4 ZERO + bge.un L37 + + ldc.r4 MINUS_ONE + ldc.r4 float32(0x80000000) + bge.un L37 + + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ONE + bge.un L37 + br FAIL + +L37: + ldc.r4 MINUS_ONE + ldc.r4 MIN + bge.un L38 + br FAIL + +L38: + ldc.r4 MINUS_ONE + ldc.r4 NEG_INF + bge.un L39 + br FAIL + +L39: + ldc.r4 MINUS_ONE + ldc.r4 NAN + bge.un L40 + br FAIL + + + +L40: + ldc.r4 MIN + ldc.r4 POS_INF + bge.un L41 + + ldc.r4 MIN + ldc.r4 MAX + bge.un L41 + + ldc.r4 MIN + ldc.r4 ONE + bge.un L41 + + ldc.r4 MIN + ldc.r4 ZERO + bge.un L41 + + ldc.r4 MIN + ldc.r4 float32(0x80000000) + bge.un L41 + + ldc.r4 MIN + ldc.r4 MINUS_ONE + bge.un L41 + + ldc.r4 MIN + ldc.r4 MIN + bge.un L41 + br FAIL + +L41: + ldc.r4 MIN + ldc.r4 NEG_INF + bge.un L42 + br FAIL + +L42: + ldc.r4 MIN + ldc.r4 NAN + bge.un L43 + br FAIL + + + + +L43: + ldc.r4 NEG_INF + ldc.r4 POS_INF + bge.un L44 + + ldc.r4 NEG_INF + ldc.r4 MAX + bge.un L44 + + ldc.r4 NEG_INF + ldc.r4 ONE + bge.un L44 + + ldc.r4 NEG_INF + ldc.r4 ZERO + bge.un L44 + + ldc.r4 NEG_INF + ldc.r4 float32(0x80000000) + bge.un L44 + + ldc.r4 NEG_INF + ldc.r4 MINUS_ONE + bge.un L44 + + ldc.r4 NEG_INF + ldc.r4 MIN + bge.un L44 + + ldc.r4 NEG_INF + ldc.r4 NEG_INF + bge.un L44 + br FAIL + +L44: + ldc.r4 NEG_INF + ldc.r4 NAN + bge.un L45 + br FAIL + + + + +L45: + ldc.r4 NAN + ldc.r4 POS_INF + bge.un L46 + br FAIL + +L46: + ldc.r4 NAN + ldc.r4 MAX + bge.un L47 + br FAIL + +L47: + ldc.r4 NAN + ldc.r4 ONE + bge.un L48 + br FAIL + +L48: + ldc.r4 NAN + ldc.r4 ZERO + bge.un L49 + br FAIL + +L49: + ldc.r4 NAN + ldc.r4 float32(0x80000000) + bge.un L50 + br FAIL + +L50: + ldc.r4 NAN + ldc.r4 MINUS_ONE + bge.un L51 + br FAIL + +L51: + ldc.r4 NAN + ldc.r4 MIN + bge.un L52 + br FAIL + +L52: + ldc.r4 NAN + ldc.r4 NEG_INF + bge.un L53 + br FAIL + +L53: + ldc.r4 NAN + ldc.r4 NAN bge.un BACKCHECK br FAIL diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bge_un_r8.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bge_un_r8.il index 01d8511fcde87..0a4f995fd95e6 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bge_un_r8.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bge_un_r8.il @@ -2,11 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. .assembly extern legacy library mscorlib {} - - - .assembly extern ConvDLL{} +#define NEG_INF "float64(0xFFF0000000000000)" +#define MIN "float64(0xFF7FFFFFFFFFFFFF)" +#define MINUS_ONE "float64(0xBFF0000000000000)" +#define MINUS_ZERO "float64(0x8000000000000000)" +#define ZERO "float64(0x0000000000000000)" +#define ONE "float64(0x3FF0000000000000)" +#define MAX "float64(0x7FEFFFFFFFFFFFFF)" +#define POS_INF "float64(0x7FF0000000000000)" +#define NAN "float64(0x7FF8000000000000)" + .method public static int32 main(class [mscorlib]System.String[]) { .entrypoint .maxstack 2 @@ -88,7 +95,8 @@ H: br FAIL -_H: ldloc 0 +_H: + ldloc 0 ldfld float64 [ConvDLL]ConvDLL::max_r8 ldloc 0 ldfld float64 [ConvDLL]ConvDLL::inf_r8 @@ -605,6 +613,457 @@ SS: ldfld float64 [ConvDLL]ConvDLL::NaN_r8 ldloc 0 ldfld float64 [ConvDLL]ConvDLL::NaN_r8 + bge.un L0 + br FAIL + + // Testing early folding logic + +L0: + ldc.r8 POS_INF + ldc.r8 POS_INF + bge.un L1 + br FAIL + +L1: + ldc.r8 POS_INF + ldc.r8 MAX + bge.un L2 + br FAIL + +L2: + ldc.r8 POS_INF + ldc.r8 ONE + bge.un L3 + br FAIL + +L3: + ldc.r8 POS_INF + ldc.r8 ZERO + bge.un L4 + br FAIL + +L4: + ldc.r8 POS_INF + ldc.r8 float64(0x8000000000000000) + bge.un L5 + br FAIL + +L5: + ldc.r8 POS_INF + ldc.r8 MINUS_ONE + bge.un L6 + br FAIL + +L6: + ldc.r8 POS_INF + ldc.r8 MIN + bge.un L7 + br FAIL + +L7: + ldc.r8 POS_INF + ldc.r8 NEG_INF + bge.un L8 + br FAIL + +L8: + ldc.r8 POS_INF + ldc.r8 NAN + bge.un L9 + br FAIL + + +L9: + ldc.r8 MAX + ldc.r8 POS_INF + bge.un L10 + + ldc.r8 MAX + ldc.r8 MAX + bge.un L10 + br FAIL + +L10: + ldc.r8 MAX + ldc.r8 ONE + bge.un L11 + br FAIL + +L11: + ldc.r8 MAX + ldc.r8 ZERO + bge.un L12 + br FAIL + +L12: + ldc.r8 MAX + ldc.r8 float64(0x8000000000000000) + bge.un L13 + br FAIL + +L13: + ldc.r8 MAX + ldc.r8 MINUS_ONE + bge.un L14 + br FAIL + +L14: + ldc.r8 MAX + ldc.r8 MIN + bge.un L15 + br FAIL + +L15: + ldc.r8 MAX + ldc.r8 NEG_INF + bge.un L16 + br FAIL + +L16: + ldc.r8 MAX + ldc.r8 NAN + bge.un L17 + br FAIL + + + +L17: + ldc.r8 ONE + ldc.r8 POS_INF + bge.un L18 + + ldc.r8 ONE + ldc.r8 MAX + bge.un L18 + + ldc.r8 ONE + ldc.r8 ONE + bge.un L18 + br FAIL + +L18: + ldc.r8 ONE + ldc.r8 ZERO + bge.un L19 + br FAIL + +L19: + ldc.r8 ONE + ldc.r8 float64(0x8000000000000000) + bge.un L20 + br FAIL + +L20: + ldc.r8 ONE + ldc.r8 MINUS_ONE + bge.un L21 + br FAIL + +L21: + ldc.r8 ONE + ldc.r8 MIN + bge.un L22 + br FAIL + +L22: + ldc.r8 ONE + ldc.r8 NEG_INF + bge.un L23 + br FAIL + +L23: + ldc.r8 ONE + ldc.r8 NAN + bge.un L24 + br FAIL + + + +L24: + ldc.r8 ZERO + ldc.r8 POS_INF + bge.un L25 + + ldc.r8 ZERO + ldc.r8 MAX + bge.un L25 + + ldc.r8 ZERO + ldc.r8 ONE + bge.un L25 + + ldc.r8 ZERO + ldc.r8 ZERO + bge.un L25 + br FAIL + +L25: + ldc.r8 ZERO + ldc.r8 float64(0x8000000000000000) + bge.un L26 + br FAIL + +L26: + ldc.r8 ZERO + ldc.r8 MINUS_ONE + bge.un L27 + br FAIL + +L27: + ldc.r8 ZERO + ldc.r8 MIN + bge.un L28 + br FAIL + +L28: + ldc.r8 ZERO + ldc.r8 NEG_INF + bge.un L29 + br FAIL + +L29: + ldc.r8 ZERO + ldc.r8 NAN + bge.un L30 + br FAIL + + + +L30: + ldc.r8 float64(0x8000000000000000) + ldc.r8 POS_INF + bge.un L31 + + ldc.r8 float64(0x8000000000000000) + ldc.r8 MAX + bge.un L31 + + ldc.r8 float64(0x8000000000000000) + ldc.r8 ONE + bge.un L31 + + ldc.r8 float64(0x8000000000000000) + ldc.r8 ZERO + bge.un L31 + br FAIL + +L31: + ldc.r8 float64(0x8000000000000000) + ldc.r8 float64(0x8000000000000000) + bge.un L32 + br FAIL + +L32: + ldc.r8 float64(0x8000000000000000) + ldc.r8 MINUS_ONE + bge.un L33 + br FAIL + +L33: + ldc.r8 float64(0x8000000000000000) + ldc.r8 MIN + bge.un L34 + br FAIL + +L34: + ldc.r8 float64(0x8000000000000000) + ldc.r8 NEG_INF + bge.un L35 + br FAIL + +L35: + ldc.r8 float64(0x8000000000000000) + ldc.r8 NAN + bge.un L36 + br FAIL + + + +L36: + ldc.r8 MINUS_ONE + ldc.r8 POS_INF + bge.un L37 + + ldc.r8 MINUS_ONE + ldc.r8 MAX + bge.un L37 + + ldc.r8 MINUS_ONE + ldc.r8 ONE + bge.un L37 + + ldc.r8 MINUS_ONE + ldc.r8 ZERO + bge.un L37 + + ldc.r8 MINUS_ONE + ldc.r8 float64(0x8000000000000000) + bge.un L37 + + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ONE + bge.un L37 + br FAIL + +L37: + ldc.r8 MINUS_ONE + ldc.r8 MIN + bge.un L38 + br FAIL + +L38: + ldc.r8 MINUS_ONE + ldc.r8 NEG_INF + bge.un L39 + br FAIL + +L39: + ldc.r8 MINUS_ONE + ldc.r8 NAN + bge.un L40 + br FAIL + + + +L40: + ldc.r8 MIN + ldc.r8 POS_INF + bge.un L41 + + ldc.r8 MIN + ldc.r8 MAX + bge.un L41 + + ldc.r8 MIN + ldc.r8 ONE + bge.un L41 + + ldc.r8 MIN + ldc.r8 ZERO + bge.un L41 + + ldc.r8 MIN + ldc.r8 float64(0x8000000000000000) + bge.un L41 + + ldc.r8 MIN + ldc.r8 MINUS_ONE + bge.un L41 + + ldc.r8 MIN + ldc.r8 MIN + bge.un L41 + br FAIL + +L41: + ldc.r8 MIN + ldc.r8 NEG_INF + bge.un L42 + br FAIL + +L42: + ldc.r8 MIN + ldc.r8 NAN + bge.un L43 + br FAIL + + + + +L43: + ldc.r8 NEG_INF + ldc.r8 POS_INF + bge.un L44 + + ldc.r8 NEG_INF + ldc.r8 MAX + bge.un L44 + + ldc.r8 NEG_INF + ldc.r8 ONE + bge.un L44 + + ldc.r8 NEG_INF + ldc.r8 ZERO + bge.un L44 + + ldc.r8 NEG_INF + ldc.r8 float64(0x8000000000000000) + bge.un L44 + + ldc.r8 NEG_INF + ldc.r8 MINUS_ONE + bge.un L44 + + ldc.r8 NEG_INF + ldc.r8 MIN + bge.un L44 + + ldc.r8 NEG_INF + ldc.r8 NEG_INF + bge.un L44 + br FAIL + +L44: + ldc.r8 NEG_INF + ldc.r8 NAN + bge.un L45 + br FAIL + + + + +L45: + ldc.r8 NAN + ldc.r8 POS_INF + bge.un L46 + br FAIL + +L46: + ldc.r8 NAN + ldc.r8 MAX + bge.un L47 + br FAIL + +L47: + ldc.r8 NAN + ldc.r8 ONE + bge.un L48 + br FAIL + +L48: + ldc.r8 NAN + ldc.r8 ZERO + bge.un L49 + br FAIL + +L49: + ldc.r8 NAN + ldc.r8 float64(0x8000000000000000) + bge.un L50 + br FAIL + +L50: + ldc.r8 NAN + ldc.r8 MINUS_ONE + bge.un L51 + br FAIL + +L51: + ldc.r8 NAN + ldc.r8 MIN + bge.un L52 + br FAIL + +L52: + ldc.r8 NAN + ldc.r8 NEG_INF + bge.un L53 + br FAIL + +L53: + ldc.r8 NAN + ldc.r8 NAN bge.un BACKCHECK br FAIL diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bgt_un_r4.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bgt_un_r4.il index 863bb2df72f18..4b5eed4d97dbf 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bgt_un_r4.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bgt_un_r4.il @@ -3,38 +3,47 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float32(0xFF800000)" +#define MIN "float32(0xFF7FFFFF)" +#define MINUS_ONE "float32(0xBF800000)" +#define MINUS_ZERO "float32(0x80000000)" +#define ZERO "float32(0x00000000)" +#define ONE "float32(0x3F800000)" +#define MAX "float32(0x7F7FFFFF)" +#define POS_INF "float32(0x7F800000)" +#define NAN "float32(0x7FC00000)" .class public bgt_un { -.field public static float32 _inf -.field public static float32 _min -.field public static float32 _one -.field public static float32 _zero +.field public static float32 neg_inf +.field public static float32 min +.field public static float32 minus_one +.field public static float32 minus_zero .field public static float32 zero .field public static float32 one .field public static float32 max -.field public static float32 inf +.field public static float32 pos_inf .field public static float32 NaN .method public static void initialize() { .maxstack 10 - ldc.r4 float32(0xFF800000) - stsfld float32 bgt_un::_inf - ldc.r4 float32(0xFF7FFFFF) - stsfld float32 bgt_un::_min - ldc.r4 float32(0xBF800000) - stsfld float32 bgt_un::_one - ldc.r4 float32(0x80000000) - stsfld float32 bgt_un::_zero - ldc.r4 float32(0x00000000) + ldc.r4 NEG_INF + stsfld float32 bgt_un::neg_inf + ldc.r4 MIN + stsfld float32 bgt_un::min + ldc.r4 MINUS_ONE + stsfld float32 bgt_un::minus_one + ldc.r4 MINUS_ZERO + stsfld float32 bgt_un::minus_zero + ldc.r4 ZERO stsfld float32 bgt_un::zero - ldc.r4 float32(0x3F800000) + ldc.r4 ONE stsfld float32 bgt_un::one - ldc.r4 float32(0x7F7FFFFF) + ldc.r4 MAX stsfld float32 bgt_un::max - ldc.r4 float32(0x7F800000) - stsfld float32 bgt_un::inf - ldc.r4 float32(0x7FC00000) + ldc.r4 POS_INF + stsfld float32 bgt_un::pos_inf + ldc.r4 NAN stsfld float32 bgt_un::NaN ret } @@ -44,189 +53,189 @@ .maxstack 10 call void bgt_un::initialize() - ldsfld float32 bgt_un::_inf - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::neg_inf + ldsfld float32 bgt_un::neg_inf bgt.un FAIL - ldsfld float32 bgt_un::_inf - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::neg_inf + ldsfld float32 bgt_un::min bgt.un FAIL - ldsfld float32 bgt_un::_inf - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::neg_inf + ldsfld float32 bgt_un::minus_one bgt.un FAIL - ldsfld float32 bgt_un::_inf - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::neg_inf + ldsfld float32 bgt_un::minus_zero bgt.un FAIL - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::neg_inf ldsfld float32 bgt_un::zero bgt.un FAIL - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::neg_inf ldsfld float32 bgt_un::one bgt.un FAIL - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::neg_inf ldsfld float32 bgt_un::max bgt.un FAIL - ldsfld float32 bgt_un::_inf - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::neg_inf + ldsfld float32 bgt_un::pos_inf bgt.un FAIL - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::neg_inf ldsfld float32 bgt_un::NaN bgt.un A br FAIL A: - ldsfld float32 bgt_un::_min - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::min + ldsfld float32 bgt_un::neg_inf bgt.un B br FAIL B: - ldsfld float32 bgt_un::_min - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::min + ldsfld float32 bgt_un::min bgt.un FAIL - ldsfld float32 bgt_un::_min - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::min + ldsfld float32 bgt_un::minus_one bgt.un FAIL - ldsfld float32 bgt_un::_min - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::min + ldsfld float32 bgt_un::minus_zero bgt.un FAIL - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::min ldsfld float32 bgt_un::zero bgt.un FAIL - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::min ldsfld float32 bgt_un::one bgt.un FAIL - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::min ldsfld float32 bgt_un::max bgt.un FAIL - ldsfld float32 bgt_un::_min - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::min + ldsfld float32 bgt_un::pos_inf bgt.un FAIL - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::min ldsfld float32 bgt_un::NaN bgt.un C br FAIL C: - ldsfld float32 bgt_un::_one - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::minus_one + ldsfld float32 bgt_un::neg_inf bgt.un D br FAIL D: - ldsfld float32 bgt_un::_one - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::minus_one + ldsfld float32 bgt_un::min bgt.un E br FAIL E: - ldsfld float32 bgt_un::_one - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::minus_one + ldsfld float32 bgt_un::minus_one bgt.un FAIL - ldsfld float32 bgt_un::_one - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::minus_one + ldsfld float32 bgt_un::minus_zero bgt.un FAIL - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::minus_one ldsfld float32 bgt_un::zero bgt.un FAIL - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::minus_one ldsfld float32 bgt_un::one bgt.un FAIL - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::minus_one ldsfld float32 bgt_un::max bgt.un FAIL - ldsfld float32 bgt_un::_one - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::minus_one + ldsfld float32 bgt_un::pos_inf bgt.un FAIL - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::minus_one ldsfld float32 bgt_un::NaN bgt.un F br FAIL F: - ldsfld float32 bgt_un::_zero - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::minus_zero + ldsfld float32 bgt_un::neg_inf bgt.un G br FAIL G: - ldsfld float32 bgt_un::_zero - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::minus_zero + ldsfld float32 bgt_un::min bgt.un H br FAIL H: - ldsfld float32 bgt_un::_zero - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::minus_zero + ldsfld float32 bgt_un::minus_one bgt.un I br FAIL I: - ldsfld float32 bgt_un::_zero - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::minus_zero + ldsfld float32 bgt_un::minus_zero bgt.un FAIL - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::minus_zero ldsfld float32 bgt_un::zero bgt.un FAIL - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::minus_zero ldsfld float32 bgt_un::one bgt.un FAIL - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::minus_zero ldsfld float32 bgt_un::max bgt.un FAIL - ldsfld float32 bgt_un::_zero - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::minus_zero + ldsfld float32 bgt_un::pos_inf bgt.un FAIL - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::minus_zero ldsfld float32 bgt_un::NaN bgt.un J br FAIL J: ldsfld float32 bgt_un::zero - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::neg_inf bgt.un K br FAIL K: ldsfld float32 bgt_un::zero - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::min bgt.un L br FAIL L: ldsfld float32 bgt_un::zero - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::minus_one bgt.un M br FAIL M: ldsfld float32 bgt_un::zero - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::minus_zero bgt.un FAIL ldsfld float32 bgt_un::zero @@ -242,7 +251,7 @@ M: bgt.un FAIL ldsfld float32 bgt_un::zero - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::pos_inf bgt.un FAIL ldsfld float32 bgt_un::zero @@ -252,25 +261,25 @@ M: N: ldsfld float32 bgt_un::one - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::neg_inf bgt.un O br FAIL O: ldsfld float32 bgt_un::one - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::min bgt.un P br FAIL P: ldsfld float32 bgt_un::one - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::minus_one bgt.un Q br FAIL Q: ldsfld float32 bgt_un::one - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::minus_zero bgt.un R br FAIL @@ -290,7 +299,7 @@ S: bgt.un FAIL ldsfld float32 bgt_un::one - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::pos_inf bgt.un FAIL ldsfld float32 bgt_un::one @@ -300,25 +309,25 @@ S: T: ldsfld float32 bgt_un::max - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::neg_inf bgt.un U br FAIL U: ldsfld float32 bgt_un::max - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::min bgt.un V br FAIL V: ldsfld float32 bgt_un::max - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::minus_one bgt.un W br FAIL W: ldsfld float32 bgt_un::max - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::minus_zero bgt.un X br FAIL @@ -340,7 +349,7 @@ Z: bgt.un FAIL ldsfld float32 bgt_un::max - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::pos_inf bgt.un FAIL ldsfld float32 bgt_un::max @@ -349,78 +358,78 @@ Z: br FAIL AA: - ldsfld float32 bgt_un::inf - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::pos_inf + ldsfld float32 bgt_un::neg_inf bgt.un BB br FAIL BB: - ldsfld float32 bgt_un::inf - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::pos_inf + ldsfld float32 bgt_un::min bgt.un CC br FAIL CC: - ldsfld float32 bgt_un::inf - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::pos_inf + ldsfld float32 bgt_un::minus_one bgt.un DD br FAIL DD: - ldsfld float32 bgt_un::inf - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::pos_inf + ldsfld float32 bgt_un::minus_zero bgt.un EE br FAIL EE: - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::pos_inf ldsfld float32 bgt_un::zero bgt.un FF br FAIL FF: - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::pos_inf ldsfld float32 bgt_un::one bgt.un GG br FAIL GG: - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::pos_inf ldsfld float32 bgt_un::max bgt.un HH br FAIL HH: - ldsfld float32 bgt_un::inf - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::pos_inf + ldsfld float32 bgt_un::pos_inf bgt.un FAIL - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::pos_inf ldsfld float32 bgt_un::NaN bgt.un II br FAIL II: ldsfld float32 bgt_un::NaN - ldsfld float32 bgt_un::_inf + ldsfld float32 bgt_un::neg_inf bgt.un JJ br FAIL JJ: ldsfld float32 bgt_un::NaN - ldsfld float32 bgt_un::_min + ldsfld float32 bgt_un::min bgt.un KK br FAIL KK: ldsfld float32 bgt_un::NaN - ldsfld float32 bgt_un::_one + ldsfld float32 bgt_un::minus_one bgt.un LL br FAIL LL: ldsfld float32 bgt_un::NaN - ldsfld float32 bgt_un::_zero + ldsfld float32 bgt_un::minus_zero bgt.un MM br FAIL @@ -444,14 +453,428 @@ OO: PP: ldsfld float32 bgt_un::NaN - ldsfld float32 bgt_un::inf + ldsfld float32 bgt_un::pos_inf bgt.un QQ br FAIL QQ: ldsfld float32 bgt_un::NaN ldsfld float32 bgt_un::NaN - bgt.un BACKCHECK + bgt.un L0 + br FAIL + + // Testing early folding logic + +L0: + ldc.r4 NEG_INF + ldc.r4 NEG_INF + bgt.un FAIL + + ldc.r4 NEG_INF + ldc.r4 MIN + bgt.un FAIL + + ldc.r4 NEG_INF + ldc.r4 MINUS_ONE + bgt.un FAIL + + ldc.r4 NEG_INF + ldc.r4 MINUS_ZERO + bgt.un FAIL + + ldc.r4 NEG_INF + ldc.r4 ZERO + bgt.un FAIL + + ldc.r4 NEG_INF + ldc.r4 ONE + bgt.un FAIL + + ldc.r4 NEG_INF + ldc.r4 MAX + bgt.un FAIL + + ldc.r4 NEG_INF + ldc.r4 POS_INF + bgt.un FAIL + + ldc.r4 NEG_INF + ldc.r4 NAN + bgt.un L1 + br FAIL + +L1: + ldc.r4 MIN + ldc.r4 NEG_INF + bgt.un L2 + br FAIL + +L2: + ldc.r4 MIN + ldc.r4 MIN + bgt.un FAIL + + ldc.r4 MIN + ldc.r4 MINUS_ONE + bgt.un FAIL + + ldc.r4 MIN + ldc.r4 MINUS_ZERO + bgt.un FAIL + + ldc.r4 MIN + ldc.r4 ZERO + bgt.un FAIL + + ldc.r4 MIN + ldc.r4 ONE + bgt.un FAIL + + ldc.r4 MIN + ldc.r4 MAX + bgt.un FAIL + + ldc.r4 MIN + ldc.r4 POS_INF + bgt.un FAIL + + ldc.r4 MIN + ldc.r4 NAN + bgt.un L3 + br FAIL + +L3: + ldc.r4 MINUS_ONE + ldc.r4 NEG_INF + bgt.un L4 + br FAIL + +L4: + ldc.r4 MINUS_ONE + ldc.r4 MIN + bgt.un L5 + br FAIL + +L5: + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ONE + bgt.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ZERO + bgt.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 ZERO + bgt.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 ONE + bgt.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MAX + bgt.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 POS_INF + bgt.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 NAN + bgt.un L6 + br FAIL + +L6: + ldc.r4 MINUS_ZERO + ldc.r4 NEG_INF + bgt.un L7 + br FAIL + +L7: + ldc.r4 MINUS_ZERO + ldc.r4 MIN + bgt.un L8 + br FAIL + +L8: + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ONE + bgt.un L9 + br FAIL + +L9: + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ZERO + bgt.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 ZERO + bgt.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 ONE + bgt.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MAX + bgt.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 POS_INF + bgt.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 NAN + bgt.un L10 + br FAIL + +L10: + ldc.r4 ZERO + ldc.r4 NEG_INF + bgt.un L11 + br FAIL + +L11: + ldc.r4 ZERO + ldc.r4 MIN + bgt.un L12 + br FAIL + +L12: + ldc.r4 ZERO + ldc.r4 MINUS_ONE + bgt.un L13 + br FAIL + +L13: + ldc.r4 ZERO + ldc.r4 MINUS_ZERO + bgt.un FAIL + + ldc.r4 ZERO + ldc.r4 ZERO + bgt.un FAIL + + ldc.r4 ZERO + ldc.r4 ONE + bgt.un FAIL + + ldc.r4 ZERO + ldc.r4 MAX + bgt.un FAIL + + ldc.r4 ZERO + ldc.r4 POS_INF + bgt.un FAIL + + ldc.r4 ZERO + ldc.r4 NAN + bgt.un L14 + br FAIL + +L14: + ldc.r4 ONE + ldc.r4 NEG_INF + bgt.un L15 + br FAIL + +L15: + ldc.r4 ONE + ldc.r4 MIN + bgt.un L16 + br FAIL + +L16: + ldc.r4 ONE + ldc.r4 MINUS_ONE + bgt.un L17 + br FAIL + +L17: + ldc.r4 ONE + ldc.r4 MINUS_ZERO + bgt.un L18 + br FAIL + +L18: + ldc.r4 ONE + ldc.r4 ZERO + bgt.un L19 + br FAIL + +L19: + ldc.r4 ONE + ldc.r4 ONE + bgt.un FAIL + + ldc.r4 ONE + ldc.r4 MAX + bgt.un FAIL + + ldc.r4 ONE + ldc.r4 POS_INF + bgt.un FAIL + + ldc.r4 ONE + ldc.r4 NAN + bgt.un L20 + br FAIL + +L20: + ldc.r4 MAX + ldc.r4 NEG_INF + bgt.un L21 + br FAIL + +L21: + ldc.r4 MAX + ldc.r4 MIN + bgt.un L22 + br FAIL + +L22: + ldc.r4 MAX + ldc.r4 MINUS_ONE + bgt.un L23 + br FAIL + +L23: + ldc.r4 MAX + ldc.r4 MINUS_ZERO + bgt.un L24 + br FAIL + +L24: + ldc.r4 MAX + ldc.r4 ZERO + bgt.un L25 + br FAIL + +L25: + ldc.r4 MAX + ldc.r4 ONE + bgt.un L26 + br FAIL + +L26: + ldc.r4 MAX + ldc.r4 MAX + bgt.un FAIL + + ldc.r4 MAX + ldc.r4 POS_INF + bgt.un FAIL + + ldc.r4 MAX + ldc.r4 NAN + bgt.un L27 + br FAIL + +L27: + ldc.r4 POS_INF + ldc.r4 NEG_INF + bgt.un L28 + br FAIL + +L28: + ldc.r4 POS_INF + ldc.r4 MIN + bgt.un L29 + br FAIL + +L29: + ldc.r4 POS_INF + ldc.r4 MINUS_ONE + bgt.un L30 + br FAIL + +L30: + ldc.r4 POS_INF + ldc.r4 MINUS_ZERO + bgt.un L31 + br FAIL + +L31: + ldc.r4 POS_INF + ldc.r4 ZERO + bgt.un L32 + br FAIL + +L32: + ldc.r4 POS_INF + ldc.r4 ONE + bgt.un L33 + br FAIL + +L33: + ldc.r4 POS_INF + ldc.r4 MAX + bgt.un L34 + br FAIL + +L34: + ldc.r4 POS_INF + ldc.r4 POS_INF + bgt.un FAIL + + ldc.r4 POS_INF + ldc.r4 NAN + bgt.un L35 + br FAIL + +L35: + ldc.r4 NAN + ldc.r4 NEG_INF + bgt.un L36 + br FAIL + +L36: + ldc.r4 NAN + ldc.r4 MIN + bgt.un L37 + br FAIL + +L37: + ldc.r4 NAN + ldc.r4 MINUS_ONE + bgt.un L38 + br FAIL + +L38: + ldc.r4 NAN + ldc.r4 MINUS_ZERO + bgt.un L39 + br FAIL + +L39: + ldc.r4 NAN + ldc.r4 ZERO + bgt.un L40 + br FAIL + +L40: + ldc.r4 NAN + ldc.r4 ONE + bgt.un L41 + br FAIL + +L41: + ldc.r4 NAN + ldc.r4 MAX + bgt.un L42 + br FAIL + +L42: + ldc.r4 NAN + ldc.r4 POS_INF + bgt.un L43 + br FAIL + +L43: + ldc.r4 NAN + ldc.r4 NAN + bgt.un BACKCHECK br FAIL TOPASS: diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bgt_un_r8.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bgt_un_r8.il index 850e9af06cbc5..e3f46e8509a00 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bgt_un_r8.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bgt_un_r8.il @@ -3,38 +3,47 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float64(0xFFF0000000000000)" +#define MIN "float64(0xFF7FFFFFFFFFFFFF)" +#define MINUS_ONE "float64(0xBFF0000000000000)" +#define MINUS_ZERO "float64(0x8000000000000000)" +#define ZERO "float64(0x0000000000000000)" +#define ONE "float64(0x3FF0000000000000)" +#define MAX "float64(0x7FEFFFFFFFFFFFFF)" +#define POS_INF "float64(0x7FF0000000000000)" +#define NAN "float64(0x7FF8000000000000)" .class public bgt_un { -.field public static float64 _inf -.field public static float64 _min -.field public static float64 _one -.field public static float64 _zero +.field public static float64 neg_inf +.field public static float64 min +.field public static float64 minus_one +.field public static float64 minus_zero .field public static float64 zero .field public static float64 one .field public static float64 max -.field public static float64 inf +.field public static float64 pos_inf .field public static float64 NaN .method public static void initialize() { .maxstack 10 - ldc.r8 float64(0xFFF0000000000000) - stsfld float64 bgt_un::_inf - ldc.r8 float64(0xFF7FFFFFFFFFFFFF) - stsfld float64 bgt_un::_min - ldc.r8 float64(0xBFF0000000000000) - stsfld float64 bgt_un::_one - ldc.r8 float64(0x8000000000000000) - stsfld float64 bgt_un::_zero - ldc.r8 float64(0x0000000000000000) + ldc.r8 NEG_INF + stsfld float64 bgt_un::neg_inf + ldc.r8 MIN + stsfld float64 bgt_un::min + ldc.r8 MINUS_ONE + stsfld float64 bgt_un::minus_one + ldc.r8 MINUS_ZERO + stsfld float64 bgt_un::minus_zero + ldc.r8 ZERO stsfld float64 bgt_un::zero - ldc.r8 float64(0x3FF0000000000000) + ldc.r8 ONE stsfld float64 bgt_un::one - ldc.r8 float64(0x7FEFFFFFFFFFFFFF) + ldc.r8 MAX stsfld float64 bgt_un::max - ldc.r8 float64(0x7FF0000000000000) - stsfld float64 bgt_un::inf - ldc.r8 float64(0x7FF8000000000000) + ldc.r8 POS_INF + stsfld float64 bgt_un::pos_inf + ldc.r8 NAN stsfld float64 bgt_un::NaN ret } @@ -44,189 +53,189 @@ .maxstack 10 call void bgt_un::initialize() - ldsfld float64 bgt_un::_inf - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::neg_inf + ldsfld float64 bgt_un::neg_inf bgt.un FAIL - ldsfld float64 bgt_un::_inf - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::neg_inf + ldsfld float64 bgt_un::min bgt.un FAIL - ldsfld float64 bgt_un::_inf - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::neg_inf + ldsfld float64 bgt_un::minus_one bgt.un FAIL - ldsfld float64 bgt_un::_inf - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::neg_inf + ldsfld float64 bgt_un::minus_zero bgt.un FAIL - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::neg_inf ldsfld float64 bgt_un::zero bgt.un FAIL - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::neg_inf ldsfld float64 bgt_un::one bgt.un FAIL - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::neg_inf ldsfld float64 bgt_un::max bgt.un FAIL - ldsfld float64 bgt_un::_inf - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::neg_inf + ldsfld float64 bgt_un::pos_inf bgt.un FAIL - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::neg_inf ldsfld float64 bgt_un::NaN bgt.un A br FAIL A: - ldsfld float64 bgt_un::_min - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::min + ldsfld float64 bgt_un::neg_inf bgt.un B br FAIL B: - ldsfld float64 bgt_un::_min - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::min + ldsfld float64 bgt_un::min bgt.un FAIL - ldsfld float64 bgt_un::_min - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::min + ldsfld float64 bgt_un::minus_one bgt.un FAIL - ldsfld float64 bgt_un::_min - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::min + ldsfld float64 bgt_un::minus_zero bgt.un FAIL - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::min ldsfld float64 bgt_un::zero bgt.un FAIL - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::min ldsfld float64 bgt_un::one bgt.un FAIL - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::min ldsfld float64 bgt_un::max bgt.un FAIL - ldsfld float64 bgt_un::_min - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::min + ldsfld float64 bgt_un::pos_inf bgt.un FAIL - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::min ldsfld float64 bgt_un::NaN bgt.un C br FAIL C: - ldsfld float64 bgt_un::_one - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::minus_one + ldsfld float64 bgt_un::neg_inf bgt.un D br FAIL D: - ldsfld float64 bgt_un::_one - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::minus_one + ldsfld float64 bgt_un::min bgt.un E br FAIL E: - ldsfld float64 bgt_un::_one - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::minus_one + ldsfld float64 bgt_un::minus_one bgt.un FAIL - ldsfld float64 bgt_un::_one - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::minus_one + ldsfld float64 bgt_un::minus_zero bgt.un FAIL - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::minus_one ldsfld float64 bgt_un::zero bgt.un FAIL - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::minus_one ldsfld float64 bgt_un::one bgt.un FAIL - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::minus_one ldsfld float64 bgt_un::max bgt.un FAIL - ldsfld float64 bgt_un::_one - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::minus_one + ldsfld float64 bgt_un::pos_inf bgt.un FAIL - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::minus_one ldsfld float64 bgt_un::NaN bgt.un F br FAIL F: - ldsfld float64 bgt_un::_zero - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::minus_zero + ldsfld float64 bgt_un::neg_inf bgt.un G br FAIL G: - ldsfld float64 bgt_un::_zero - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::minus_zero + ldsfld float64 bgt_un::min bgt.un H br FAIL H: - ldsfld float64 bgt_un::_zero - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::minus_zero + ldsfld float64 bgt_un::minus_one bgt.un I br FAIL I: - ldsfld float64 bgt_un::_zero - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::minus_zero + ldsfld float64 bgt_un::minus_zero bgt.un FAIL - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::minus_zero ldsfld float64 bgt_un::zero bgt.un FAIL - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::minus_zero ldsfld float64 bgt_un::one bgt.un FAIL - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::minus_zero ldsfld float64 bgt_un::max bgt.un FAIL - ldsfld float64 bgt_un::_zero - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::minus_zero + ldsfld float64 bgt_un::pos_inf bgt.un FAIL - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::minus_zero ldsfld float64 bgt_un::NaN bgt.un J br FAIL J: ldsfld float64 bgt_un::zero - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::neg_inf bgt.un K br FAIL K: ldsfld float64 bgt_un::zero - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::min bgt.un L br FAIL L: ldsfld float64 bgt_un::zero - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::minus_one bgt.un M br FAIL M: ldsfld float64 bgt_un::zero - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::minus_zero bgt.un FAIL ldsfld float64 bgt_un::zero @@ -242,7 +251,7 @@ M: bgt.un FAIL ldsfld float64 bgt_un::zero - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::pos_inf bgt.un FAIL ldsfld float64 bgt_un::zero @@ -252,25 +261,25 @@ M: N: ldsfld float64 bgt_un::one - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::neg_inf bgt.un O br FAIL O: ldsfld float64 bgt_un::one - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::min bgt.un P br FAIL P: ldsfld float64 bgt_un::one - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::minus_one bgt.un Q br FAIL Q: ldsfld float64 bgt_un::one - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::minus_zero bgt.un R br FAIL @@ -290,7 +299,7 @@ S: bgt.un FAIL ldsfld float64 bgt_un::one - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::pos_inf bgt.un FAIL ldsfld float64 bgt_un::one @@ -300,25 +309,25 @@ S: T: ldsfld float64 bgt_un::max - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::neg_inf bgt.un U br FAIL U: ldsfld float64 bgt_un::max - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::min bgt.un V br FAIL V: ldsfld float64 bgt_un::max - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::minus_one bgt.un W br FAIL W: ldsfld float64 bgt_un::max - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::minus_zero bgt.un X br FAIL @@ -340,7 +349,7 @@ Z: bgt.un FAIL ldsfld float64 bgt_un::max - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::pos_inf bgt.un FAIL ldsfld float64 bgt_un::max @@ -349,78 +358,78 @@ Z: br FAIL AA: - ldsfld float64 bgt_un::inf - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::pos_inf + ldsfld float64 bgt_un::neg_inf bgt.un BB br FAIL BB: - ldsfld float64 bgt_un::inf - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::pos_inf + ldsfld float64 bgt_un::min bgt.un CC br FAIL CC: - ldsfld float64 bgt_un::inf - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::pos_inf + ldsfld float64 bgt_un::minus_one bgt.un DD br FAIL DD: - ldsfld float64 bgt_un::inf - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::pos_inf + ldsfld float64 bgt_un::minus_zero bgt.un EE br FAIL EE: - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::pos_inf ldsfld float64 bgt_un::zero bgt.un FF br FAIL FF: - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::pos_inf ldsfld float64 bgt_un::one bgt.un GG br FAIL GG: - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::pos_inf ldsfld float64 bgt_un::max bgt.un HH br FAIL HH: - ldsfld float64 bgt_un::inf - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::pos_inf + ldsfld float64 bgt_un::pos_inf bgt.un FAIL - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::pos_inf ldsfld float64 bgt_un::NaN bgt.un II br FAIL II: ldsfld float64 bgt_un::NaN - ldsfld float64 bgt_un::_inf + ldsfld float64 bgt_un::neg_inf bgt.un JJ br FAIL JJ: ldsfld float64 bgt_un::NaN - ldsfld float64 bgt_un::_min + ldsfld float64 bgt_un::min bgt.un KK br FAIL KK: ldsfld float64 bgt_un::NaN - ldsfld float64 bgt_un::_one + ldsfld float64 bgt_un::minus_one bgt.un LL br FAIL LL: ldsfld float64 bgt_un::NaN - ldsfld float64 bgt_un::_zero + ldsfld float64 bgt_un::minus_zero bgt.un MM br FAIL @@ -444,14 +453,428 @@ OO: PP: ldsfld float64 bgt_un::NaN - ldsfld float64 bgt_un::inf + ldsfld float64 bgt_un::pos_inf bgt.un QQ br FAIL QQ: ldsfld float64 bgt_un::NaN ldsfld float64 bgt_un::NaN - bgt.un BACKCHECK + bgt.un L0 + br FAIL + + // Testing early folding logic + +L0: + ldc.r8 NEG_INF + ldc.r8 NEG_INF + bgt.un FAIL + + ldc.r8 NEG_INF + ldc.r8 MIN + bgt.un FAIL + + ldc.r8 NEG_INF + ldc.r8 MINUS_ONE + bgt.un FAIL + + ldc.r8 NEG_INF + ldc.r8 MINUS_ZERO + bgt.un FAIL + + ldc.r8 NEG_INF + ldc.r8 ZERO + bgt.un FAIL + + ldc.r8 NEG_INF + ldc.r8 ONE + bgt.un FAIL + + ldc.r8 NEG_INF + ldc.r8 MAX + bgt.un FAIL + + ldc.r8 NEG_INF + ldc.r8 POS_INF + bgt.un FAIL + + ldc.r8 NEG_INF + ldc.r8 NAN + bgt.un L1 + br FAIL + +L1: + ldc.r8 MIN + ldc.r8 NEG_INF + bgt.un L2 + br FAIL + +L2: + ldc.r8 MIN + ldc.r8 MIN + bgt.un FAIL + + ldc.r8 MIN + ldc.r8 MINUS_ONE + bgt.un FAIL + + ldc.r8 MIN + ldc.r8 MINUS_ZERO + bgt.un FAIL + + ldc.r8 MIN + ldc.r8 ZERO + bgt.un FAIL + + ldc.r8 MIN + ldc.r8 ONE + bgt.un FAIL + + ldc.r8 MIN + ldc.r8 MAX + bgt.un FAIL + + ldc.r8 MIN + ldc.r8 POS_INF + bgt.un FAIL + + ldc.r8 MIN + ldc.r8 NAN + bgt.un L3 + br FAIL + +L3: + ldc.r8 MINUS_ONE + ldc.r8 NEG_INF + bgt.un L4 + br FAIL + +L4: + ldc.r8 MINUS_ONE + ldc.r8 MIN + bgt.un L5 + br FAIL + +L5: + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ONE + bgt.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ZERO + bgt.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 ZERO + bgt.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 ONE + bgt.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MAX + bgt.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 POS_INF + bgt.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 NAN + bgt.un L6 + br FAIL + +L6: + ldc.r8 MINUS_ZERO + ldc.r8 NEG_INF + bgt.un L7 + br FAIL + +L7: + ldc.r8 MINUS_ZERO + ldc.r8 MIN + bgt.un L8 + br FAIL + +L8: + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ONE + bgt.un L9 + br FAIL + +L9: + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ZERO + bgt.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 ZERO + bgt.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 ONE + bgt.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MAX + bgt.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 POS_INF + bgt.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 NAN + bgt.un L10 + br FAIL + +L10: + ldc.r8 ZERO + ldc.r8 NEG_INF + bgt.un L11 + br FAIL + +L11: + ldc.r8 ZERO + ldc.r8 MIN + bgt.un L12 + br FAIL + +L12: + ldc.r8 ZERO + ldc.r8 MINUS_ONE + bgt.un L13 + br FAIL + +L13: + ldc.r8 ZERO + ldc.r8 MINUS_ZERO + bgt.un FAIL + + ldc.r8 ZERO + ldc.r8 ZERO + bgt.un FAIL + + ldc.r8 ZERO + ldc.r8 ONE + bgt.un FAIL + + ldc.r8 ZERO + ldc.r8 MAX + bgt.un FAIL + + ldc.r8 ZERO + ldc.r8 POS_INF + bgt.un FAIL + + ldc.r8 ZERO + ldc.r8 NAN + bgt.un L14 + br FAIL + +L14: + ldc.r8 ONE + ldc.r8 NEG_INF + bgt.un L15 + br FAIL + +L15: + ldc.r8 ONE + ldc.r8 MIN + bgt.un L16 + br FAIL + +L16: + ldc.r8 ONE + ldc.r8 MINUS_ONE + bgt.un L17 + br FAIL + +L17: + ldc.r8 ONE + ldc.r8 MINUS_ZERO + bgt.un L18 + br FAIL + +L18: + ldc.r8 ONE + ldc.r8 ZERO + bgt.un L19 + br FAIL + +L19: + ldc.r8 ONE + ldc.r8 ONE + bgt.un FAIL + + ldc.r8 ONE + ldc.r8 MAX + bgt.un FAIL + + ldc.r8 ONE + ldc.r8 POS_INF + bgt.un FAIL + + ldc.r8 ONE + ldc.r8 NAN + bgt.un L20 + br FAIL + +L20: + ldc.r8 MAX + ldc.r8 NEG_INF + bgt.un L21 + br FAIL + +L21: + ldc.r8 MAX + ldc.r8 MIN + bgt.un L22 + br FAIL + +L22: + ldc.r8 MAX + ldc.r8 MINUS_ONE + bgt.un L23 + br FAIL + +L23: + ldc.r8 MAX + ldc.r8 MINUS_ZERO + bgt.un L24 + br FAIL + +L24: + ldc.r8 MAX + ldc.r8 ZERO + bgt.un L25 + br FAIL + +L25: + ldc.r8 MAX + ldc.r8 ONE + bgt.un L26 + br FAIL + +L26: + ldc.r8 MAX + ldc.r8 MAX + bgt.un FAIL + + ldc.r8 MAX + ldc.r8 POS_INF + bgt.un FAIL + + ldc.r8 MAX + ldc.r8 NAN + bgt.un L27 + br FAIL + +L27: + ldc.r8 POS_INF + ldc.r8 NEG_INF + bgt.un L28 + br FAIL + +L28: + ldc.r8 POS_INF + ldc.r8 MIN + bgt.un L29 + br FAIL + +L29: + ldc.r8 POS_INF + ldc.r8 MINUS_ONE + bgt.un L30 + br FAIL + +L30: + ldc.r8 POS_INF + ldc.r8 MINUS_ZERO + bgt.un L31 + br FAIL + +L31: + ldc.r8 POS_INF + ldc.r8 ZERO + bgt.un L32 + br FAIL + +L32: + ldc.r8 POS_INF + ldc.r8 ONE + bgt.un L33 + br FAIL + +L33: + ldc.r8 POS_INF + ldc.r8 MAX + bgt.un L34 + br FAIL + +L34: + ldc.r8 POS_INF + ldc.r8 POS_INF + bgt.un FAIL + + ldc.r8 POS_INF + ldc.r8 NAN + bgt.un L35 + br FAIL + +L35: + ldc.r8 NAN + ldc.r8 NEG_INF + bgt.un L36 + br FAIL + +L36: + ldc.r8 NAN + ldc.r8 MIN + bgt.un L37 + br FAIL + +L37: + ldc.r8 NAN + ldc.r8 MINUS_ONE + bgt.un L38 + br FAIL + +L38: + ldc.r8 NAN + ldc.r8 MINUS_ZERO + bgt.un L39 + br FAIL + +L39: + ldc.r8 NAN + ldc.r8 ZERO + bgt.un L40 + br FAIL + +L40: + ldc.r8 NAN + ldc.r8 ONE + bgt.un L41 + br FAIL + +L41: + ldc.r8 NAN + ldc.r8 MAX + bgt.un L42 + br FAIL + +L42: + ldc.r8 NAN + ldc.r8 POS_INF + bgt.un L43 + br FAIL + +L43: + ldc.r8 NAN + ldc.r8 NAN + bgt.un BACKCHECK br FAIL TOPASS: diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ble_un_r4.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ble_un_r4.il index 22927bd13e256..82eb0f6c47dfc 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ble_un_r4.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ble_un_r4.il @@ -3,38 +3,47 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float32(0xFF800000)" +#define MIN "float32(0xFF7FFFFF)" +#define MINUS_ONE "float32(0xBF800000)" +#define MINUS_ZERO "float32(0x80000000)" +#define ZERO "float32(0x00000000)" +#define ONE "float32(0x3F800000)" +#define MAX "float32(0x7F7FFFFF)" +#define POS_INF "float32(0x7F800000)" +#define NAN "float32(0x7FC00000)" .class public _ble_un { -.field public static float32 _inf -.field public static float32 _min -.field public static float32 _one -.field public static float32 _zero +.field public static float32 neg_inf +.field public static float32 min +.field public static float32 minus_one +.field public static float32 minus_zero .field public static float32 zero .field public static float32 one .field public static float32 max -.field public static float32 inf +.field public static float32 pos_inf .field public static float32 NaN .method public static void initialize() { .maxstack 10 - ldc.r4 float32(0xFF800000) - stsfld float32 _ble_un::_inf - ldc.r4 float32(0xFF7FFFFF) - stsfld float32 _ble_un::_min - ldc.r4 float32(0xBF800000) - stsfld float32 _ble_un::_one - ldc.r4 float32(0x80000000) - stsfld float32 _ble_un::_zero - ldc.r4 float32(0x00000000) + ldc.r4 NEG_INF + stsfld float32 _ble_un::neg_inf + ldc.r4 MIN + stsfld float32 _ble_un::min + ldc.r4 MINUS_ONE + stsfld float32 _ble_un::minus_one + ldc.r4 MINUS_ZERO + stsfld float32 _ble_un::minus_zero + ldc.r4 ZERO stsfld float32 _ble_un::zero - ldc.r4 float32(0x3F800000) + ldc.r4 ONE stsfld float32 _ble_un::one - ldc.r4 float32(0x7F7FFFFF) + ldc.r4 MAX stsfld float32 _ble_un::max - ldc.r4 float32(0x7F800000) - stsfld float32 _ble_un::inf - ldc.r4 float32(0x7FC00000) + ldc.r4 POS_INF + stsfld float32 _ble_un::pos_inf + ldc.r4 NAN stsfld float32 _ble_un::NaN ret } @@ -44,223 +53,223 @@ .maxstack 10 call void _ble_un::initialize() - ldsfld float32 _ble_un::_inf - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::neg_inf + ldsfld float32 _ble_un::neg_inf ble.un A br FAIL A: - ldsfld float32 _ble_un::_inf - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::neg_inf + ldsfld float32 _ble_un::min ble.un B br FAIL B: - ldsfld float32 _ble_un::_inf - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::neg_inf + ldsfld float32 _ble_un::minus_one ble.un C br FAIL C: - ldsfld float32 _ble_un::_inf - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::neg_inf + ldsfld float32 _ble_un::minus_zero ble.un D br FAIL D: - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::neg_inf ldsfld float32 _ble_un::zero ble.un E br FAIL E: - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::neg_inf ldsfld float32 _ble_un::one ble.un F br FAIL F: - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::neg_inf ldsfld float32 _ble_un::max ble.un G br FAIL G: - ldsfld float32 _ble_un::_inf - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::neg_inf + ldsfld float32 _ble_un::pos_inf ble.un H br FAIL H: - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::neg_inf ldsfld float32 _ble_un::NaN ble.un K br FAIL K: - ldsfld float32 _ble_un::_min - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::min + ldsfld float32 _ble_un::neg_inf ble.un FAIL - ldsfld float32 _ble_un::_min - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::min + ldsfld float32 _ble_un::min ble.un L br FAIL L: - ldsfld float32 _ble_un::_min - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::min + ldsfld float32 _ble_un::minus_one ble.un M br FAIL M: - ldsfld float32 _ble_un::_min - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::min + ldsfld float32 _ble_un::minus_zero ble.un N br FAIL N: - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::min ldsfld float32 _ble_un::zero ble.un O br FAIL O: - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::min ldsfld float32 _ble_un::one ble.un P br FAIL P: - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::min ldsfld float32 _ble_un::max ble.un Q br FAIL Q: - ldsfld float32 _ble_un::_min - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::min + ldsfld float32 _ble_un::pos_inf ble.un R br FAIL R: - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::min ldsfld float32 _ble_un::NaN ble.un S br FAIL S: - ldsfld float32 _ble_un::_one - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::minus_one + ldsfld float32 _ble_un::neg_inf ble.un FAIL - ldsfld float32 _ble_un::_one - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::minus_one + ldsfld float32 _ble_un::min ble.un FAIL - ldsfld float32 _ble_un::_one - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::minus_one + ldsfld float32 _ble_un::minus_one ble.un T br FAIL T: - ldsfld float32 _ble_un::_one - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::minus_one + ldsfld float32 _ble_un::minus_zero ble.un U br FAIL U: - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::minus_one ldsfld float32 _ble_un::zero ble.un V br FAIL V: - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::minus_one ldsfld float32 _ble_un::one ble.un W br FAIL W: - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::minus_one ldsfld float32 _ble_un::max ble.un X br FAIL X: - ldsfld float32 _ble_un::_one - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::minus_one + ldsfld float32 _ble_un::pos_inf ble.un Y br FAIL Y: - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::minus_one ldsfld float32 _ble_un::NaN ble.un Z br FAIL Z: - ldsfld float32 _ble_un::_zero - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::minus_zero + ldsfld float32 _ble_un::neg_inf ble.un FAIL - ldsfld float32 _ble_un::_zero - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::minus_zero + ldsfld float32 _ble_un::min ble.un FAIL - ldsfld float32 _ble_un::_zero - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::minus_zero + ldsfld float32 _ble_un::minus_one ble.un FAIL - ldsfld float32 _ble_un::_zero - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::minus_zero + ldsfld float32 _ble_un::minus_zero ble.un AA br FAIL AA: - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::minus_zero ldsfld float32 _ble_un::zero ble.un BB br FAIL BB: - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::minus_zero ldsfld float32 _ble_un::one ble.un CC br FAIL CC: - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::minus_zero ldsfld float32 _ble_un::max ble.un DD br FAIL DD: - ldsfld float32 _ble_un::_zero - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::minus_zero + ldsfld float32 _ble_un::pos_inf ble.un EE br FAIL EE: - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::minus_zero ldsfld float32 _ble_un::NaN ble.un FF br FAIL FF: ldsfld float32 _ble_un::zero - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::neg_inf ble.un FAIL ldsfld float32 _ble_un::zero - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::min ble.un FAIL ldsfld float32 _ble_un::zero - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::minus_one ble.un FAIL ldsfld float32 _ble_un::zero - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::minus_zero ble.un GG br FAIL @@ -284,7 +293,7 @@ II: JJ: ldsfld float32 _ble_un::zero - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::pos_inf ble.un KK br FAIL @@ -296,19 +305,19 @@ KK: LL: ldsfld float32 _ble_un::one - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::neg_inf ble.un FAIL ldsfld float32 _ble_un::one - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::min ble.un FAIL ldsfld float32 _ble_un::one - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::minus_one ble.un FAIL ldsfld float32 _ble_un::one - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::minus_zero ble.un FAIL ldsfld float32 _ble_un::one @@ -328,7 +337,7 @@ MM: NN: ldsfld float32 _ble_un::one - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::pos_inf ble.un OO br FAIL @@ -340,19 +349,19 @@ OO: PP: ldsfld float32 _ble_un::max - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::neg_inf ble.un FAIL ldsfld float32 _ble_un::max - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::min ble.un FAIL ldsfld float32 _ble_un::max - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::minus_one ble.un FAIL ldsfld float32 _ble_un::max - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::minus_zero ble.un FAIL ldsfld float32 _ble_un::max @@ -370,7 +379,7 @@ PP: QQ: ldsfld float32 _ble_un::max - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::pos_inf ble.un RR br FAIL @@ -381,66 +390,66 @@ RR: br FAIL SS: - ldsfld float32 _ble_un::inf - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::pos_inf + ldsfld float32 _ble_un::neg_inf ble.un FAIL - ldsfld float32 _ble_un::inf - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::pos_inf + ldsfld float32 _ble_un::min ble.un FAIL - ldsfld float32 _ble_un::inf - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::pos_inf + ldsfld float32 _ble_un::minus_one ble.un FAIL - ldsfld float32 _ble_un::inf - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::pos_inf + ldsfld float32 _ble_un::minus_zero ble.un FAIL - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::pos_inf ldsfld float32 _ble_un::zero ble.un FAIL - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::pos_inf ldsfld float32 _ble_un::one ble.un FAIL - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::pos_inf ldsfld float32 _ble_un::max ble.un FAIL - ldsfld float32 _ble_un::inf - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::pos_inf + ldsfld float32 _ble_un::pos_inf ble.un TT br FAIL TT: - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::pos_inf ldsfld float32 _ble_un::NaN ble.un UU br FAIL UU: ldsfld float32 _ble_un::NaN - ldsfld float32 _ble_un::_inf + ldsfld float32 _ble_un::neg_inf ble.un VV br FAIL VV: ldsfld float32 _ble_un::NaN - ldsfld float32 _ble_un::_min + ldsfld float32 _ble_un::min ble.un WW br FAIL WW: ldsfld float32 _ble_un::NaN - ldsfld float32 _ble_un::_one + ldsfld float32 _ble_un::minus_one ble.un XX br FAIL XX: ldsfld float32 _ble_un::NaN - ldsfld float32 _ble_un::_zero + ldsfld float32 _ble_un::minus_zero ble.un YY br FAIL @@ -464,14 +473,448 @@ AAA: BBB: ldsfld float32 _ble_un::NaN - ldsfld float32 _ble_un::inf + ldsfld float32 _ble_un::pos_inf ble.un CCC br FAIL CCC: ldsfld float32 _ble_un::NaN ldsfld float32 _ble_un::NaN - ble.un BACKCHECK + ble.un L0 + br FAIL + + // Testing early folding logic + +L0: + ldc.r4 NEG_INF + ldc.r4 NEG_INF + ble.un L1 + br FAIL + +L1: + ldc.r4 NEG_INF + ldc.r4 MIN + ble.un L2 + br FAIL + +L2: + ldc.r4 NEG_INF + ldc.r4 MINUS_ONE + ble.un L3 + br FAIL + +L3: + ldc.r4 NEG_INF + ldc.r4 MINUS_ZERO + ble.un L4 + br FAIL + +L4: + ldc.r4 NEG_INF + ldc.r4 ZERO + ble.un L5 + br FAIL + +L5: + ldc.r4 NEG_INF + ldc.r4 ONE + ble.un L6 + br FAIL + +L6: + ldc.r4 NEG_INF + ldc.r4 MAX + ble.un L7 + br FAIL + +L7: + ldc.r4 NEG_INF + ldc.r4 POS_INF + ble.un L8 + br FAIL + +L8: + ldc.r4 NEG_INF + ldc.r4 NAN + ble.un L9 + br FAIL + +L9: + ldc.r4 MIN + ldc.r4 NEG_INF + ble.un FAIL + + ldc.r4 MIN + ldc.r4 MIN + ble.un L10 + br FAIL + +L10: + ldc.r4 MIN + ldc.r4 MINUS_ONE + ble.un L11 + br FAIL + +L11: + ldc.r4 MIN + ldc.r4 MINUS_ZERO + ble.un L12 + br FAIL + +L12: + ldc.r4 MIN + ldc.r4 ZERO + ble.un L13 + br FAIL + +L13: + ldc.r4 MIN + ldc.r4 ONE + ble.un L14 + br FAIL + +L14: + ldc.r4 MIN + ldc.r4 MAX + ble.un L15 + br FAIL + +L15: + ldc.r4 MIN + ldc.r4 POS_INF + ble.un L16 + br FAIL + +L16: + ldc.r4 MIN + ldc.r4 NAN + ble.un L17 + br FAIL + +L17: + ldc.r4 MINUS_ONE + ldc.r4 NEG_INF + ble.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MIN + ble.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ONE + ble.un L18 + br FAIL + +L18: + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ZERO + ble.un L19 + br FAIL + +L19: + ldc.r4 MINUS_ONE + ldc.r4 ZERO + ble.un L20 + br FAIL + +L20: + ldc.r4 MINUS_ONE + ldc.r4 ONE + ble.un L21 + br FAIL + +L21: + ldc.r4 MINUS_ONE + ldc.r4 MAX + ble.un L22 + br FAIL + +L22: + ldc.r4 MINUS_ONE + ldc.r4 POS_INF + ble.un L23 + br FAIL + +L23: + ldc.r4 MINUS_ONE + ldc.r4 NAN + ble.un L24 + br FAIL + +L24: + ldc.r4 MINUS_ZERO + ldc.r4 NEG_INF + ble.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MIN + ble.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ONE + ble.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ZERO + ble.un L25 + br FAIL + +L25: + ldc.r4 MINUS_ZERO + ldc.r4 ZERO + ble.un L26 + br FAIL + +L26: + ldc.r4 MINUS_ZERO + ldc.r4 ONE + ble.un L27 + br FAIL + +L27: + ldc.r4 MINUS_ZERO + ldc.r4 MAX + ble.un L28 + br FAIL + +L28: + ldc.r4 MINUS_ZERO + ldc.r4 POS_INF + ble.un L29 + br FAIL + +L29: + ldc.r4 MINUS_ZERO + ldc.r4 NAN + ble.un L30 + br FAIL + +L30: + ldc.r4 ZERO + ldc.r4 NEG_INF + ble.un FAIL + + ldc.r4 ZERO + ldc.r4 MIN + ble.un FAIL + + ldc.r4 ZERO + ldc.r4 MINUS_ONE + ble.un FAIL + + ldc.r4 ZERO + ldc.r4 MINUS_ZERO + ble.un L31 + br FAIL + +L31: + ldc.r4 ZERO + ldc.r4 ZERO + ble.un L32 + br FAIL + +L32: + ldc.r4 ZERO + ldc.r4 ONE + ble.un L33 + br FAIL + +L33: + ldc.r4 ZERO + ldc.r4 MAX + ble.un L34 + br FAIL + +L34: + ldc.r4 ZERO + ldc.r4 POS_INF + ble.un L35 + br FAIL + +L35: + ldc.r4 ZERO + ldc.r4 NAN + ble.un L36 + br FAIL + +L36: + ldc.r4 ONE + ldc.r4 NEG_INF + ble.un FAIL + + ldc.r4 ONE + ldc.r4 MIN + ble.un FAIL + + ldc.r4 ONE + ldc.r4 MINUS_ONE + ble.un FAIL + + ldc.r4 ONE + ldc.r4 MINUS_ZERO + ble.un FAIL + + ldc.r4 ONE + ldc.r4 ZERO + ble.un FAIL + + ldc.r4 ONE + ldc.r4 ONE + ble.un L37 + br FAIL + +L37: + ldc.r4 ONE + ldc.r4 MAX + ble.un L38 + br FAIL + +L38: + ldc.r4 ONE + ldc.r4 POS_INF + ble.un L39 + br FAIL + +L39: + ldc.r4 ONE + ldc.r4 NAN + ble.un L40 + br FAIL + +L40: + ldc.r4 MAX + ldc.r4 NEG_INF + ble.un FAIL + + ldc.r4 MAX + ldc.r4 MIN + ble.un FAIL + + ldc.r4 MAX + ldc.r4 MINUS_ONE + ble.un FAIL + + ldc.r4 MAX + ldc.r4 MINUS_ZERO + ble.un FAIL + + ldc.r4 MAX + ldc.r4 ZERO + ble.un FAIL + + ldc.r4 MAX + ldc.r4 ONE + ble.un FAIL + + ldc.r4 MAX + ldc.r4 MAX + ble.un L41 + br FAIL + +L41: + ldc.r4 MAX + ldc.r4 POS_INF + ble.un L42 + br FAIL + +L42: + ldc.r4 MAX + ldc.r4 NAN + ble.un L43 + br FAIL + +L43: + ldc.r4 POS_INF + ldc.r4 NEG_INF + ble.un FAIL + + ldc.r4 POS_INF + ldc.r4 MIN + ble.un FAIL + + ldc.r4 POS_INF + ldc.r4 MINUS_ONE + ble.un FAIL + + ldc.r4 POS_INF + ldc.r4 MINUS_ZERO + ble.un FAIL + + ldc.r4 POS_INF + ldc.r4 ZERO + ble.un FAIL + + ldc.r4 POS_INF + ldc.r4 ONE + ble.un FAIL + + ldc.r4 POS_INF + ldc.r4 MAX + ble.un FAIL + + ldc.r4 POS_INF + ldc.r4 POS_INF + ble.un L44 + br FAIL + +L44: + ldc.r4 POS_INF + ldc.r4 NAN + ble.un L45 + br FAIL + +L45: + ldc.r4 NAN + ldc.r4 NEG_INF + ble.un L46 + br FAIL + +L46: + ldc.r4 NAN + ldc.r4 MIN + ble.un L47 + br FAIL + +L47: + ldc.r4 NAN + ldc.r4 MINUS_ONE + ble.un L48 + br FAIL + +L48: + ldc.r4 NAN + ldc.r4 MINUS_ZERO + ble.un L49 + br FAIL + +L49: + ldc.r4 NAN + ldc.r4 ZERO + ble.un L50 + br FAIL + +L50: + ldc.r4 NAN + ldc.r4 ONE + ble.un L51 + br FAIL + +L51: + ldc.r4 NAN + ldc.r4 MAX + ble.un L52 + br FAIL + +L52: + ldc.r4 NAN + ldc.r4 POS_INF + ble.un L53 + br FAIL + +L53: + ldc.r4 NAN + ldc.r4 NAN + ble.un BACKCHECK br FAIL TOPASS: diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ble_un_r8.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ble_un_r8.il index b228a9fecaf43..8f83e4de49d8b 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ble_un_r8.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/ble_un_r8.il @@ -3,38 +3,47 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float64(0xFFF0000000000000)" +#define MIN "float64(0xFF7FFFFFFFFFFFFF)" +#define MINUS_ONE "float64(0xBFF0000000000000)" +#define MINUS_ZERO "float64(0x8000000000000000)" +#define ZERO "float64(0x0000000000000000)" +#define ONE "float64(0x3FF0000000000000)" +#define MAX "float64(0x7FEFFFFFFFFFFFFF)" +#define POS_INF "float64(0x7FF0000000000000)" +#define NAN "float64(0x7FF8000000000000)" .class public ble_un { -.field public static float64 _inf -.field public static float64 _min -.field public static float64 _one -.field public static float64 _zero +.field public static float64 neg_inf +.field public static float64 min +.field public static float64 minus_one +.field public static float64 minus_zero .field public static float64 zero .field public static float64 one .field public static float64 max -.field public static float64 inf +.field public static float64 pos_inf .field public static float64 NaN .method public static void initialize() { .maxstack 10 - ldc.r8 float64(0xFFF0000000000000) - stsfld float64 ble_un::_inf - ldc.r8 float64(0xFF7FFFFFFFFFFFFF) - stsfld float64 ble_un::_min - ldc.r8 float64(0xBFF0000000000000) - stsfld float64 ble_un::_one - ldc.r8 float64(0x8000000000000000) - stsfld float64 ble_un::_zero - ldc.r8 float64(0x0000000000000000) + ldc.r8 NEG_INF + stsfld float64 ble_un::neg_inf + ldc.r8 MIN + stsfld float64 ble_un::min + ldc.r8 MINUS_ONE + stsfld float64 ble_un::minus_one + ldc.r8 MINUS_ZERO + stsfld float64 ble_un::minus_zero + ldc.r8 ZERO stsfld float64 ble_un::zero - ldc.r8 float64(0x3FF0000000000000) + ldc.r8 ONE stsfld float64 ble_un::one - ldc.r8 float64(0x7FEFFFFFFFFFFFFF) + ldc.r8 MAX stsfld float64 ble_un::max - ldc.r8 float64(0x7FF0000000000000) - stsfld float64 ble_un::inf - ldc.r8 float64(0x7FF8000000000000) + ldc.r8 POS_INF + stsfld float64 ble_un::pos_inf + ldc.r8 NAN stsfld float64 ble_un::NaN ret } @@ -44,223 +53,223 @@ .maxstack 10 call void ble_un::initialize() - ldsfld float64 ble_un::_inf - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::neg_inf + ldsfld float64 ble_un::neg_inf ble.un A br FAIL A: - ldsfld float64 ble_un::_inf - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::neg_inf + ldsfld float64 ble_un::min ble.un B br FAIL B: - ldsfld float64 ble_un::_inf - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::neg_inf + ldsfld float64 ble_un::minus_one ble.un C br FAIL C: - ldsfld float64 ble_un::_inf - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::neg_inf + ldsfld float64 ble_un::minus_zero ble.un D br FAIL D: - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::neg_inf ldsfld float64 ble_un::zero ble.un E br FAIL E: - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::neg_inf ldsfld float64 ble_un::one ble.un F br FAIL F: - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::neg_inf ldsfld float64 ble_un::max ble.un G br FAIL G: - ldsfld float64 ble_un::_inf - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::neg_inf + ldsfld float64 ble_un::pos_inf ble.un H br FAIL H: - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::neg_inf ldsfld float64 ble_un::NaN ble.un K br FAIL K: - ldsfld float64 ble_un::_min - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::min + ldsfld float64 ble_un::neg_inf ble.un FAIL - ldsfld float64 ble_un::_min - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::min + ldsfld float64 ble_un::min ble.un L br FAIL L: - ldsfld float64 ble_un::_min - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::min + ldsfld float64 ble_un::minus_one ble.un M br FAIL M: - ldsfld float64 ble_un::_min - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::min + ldsfld float64 ble_un::minus_zero ble.un N br FAIL N: - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::min ldsfld float64 ble_un::zero ble.un O br FAIL O: - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::min ldsfld float64 ble_un::one ble.un P br FAIL P: - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::min ldsfld float64 ble_un::max ble.un Q br FAIL Q: - ldsfld float64 ble_un::_min - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::min + ldsfld float64 ble_un::pos_inf ble.un R br FAIL R: - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::min ldsfld float64 ble_un::NaN ble.un S br FAIL S: - ldsfld float64 ble_un::_one - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::minus_one + ldsfld float64 ble_un::neg_inf ble.un FAIL - ldsfld float64 ble_un::_one - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::minus_one + ldsfld float64 ble_un::min ble.un FAIL - ldsfld float64 ble_un::_one - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::minus_one + ldsfld float64 ble_un::minus_one ble.un T br FAIL T: - ldsfld float64 ble_un::_one - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::minus_one + ldsfld float64 ble_un::minus_zero ble.un U br FAIL U: - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::minus_one ldsfld float64 ble_un::zero ble.un V br FAIL V: - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::minus_one ldsfld float64 ble_un::one ble.un W br FAIL W: - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::minus_one ldsfld float64 ble_un::max ble.un X br FAIL X: - ldsfld float64 ble_un::_one - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::minus_one + ldsfld float64 ble_un::pos_inf ble.un Y br FAIL Y: - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::minus_one ldsfld float64 ble_un::NaN ble.un Z br FAIL Z: - ldsfld float64 ble_un::_zero - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::minus_zero + ldsfld float64 ble_un::neg_inf ble.un FAIL - ldsfld float64 ble_un::_zero - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::minus_zero + ldsfld float64 ble_un::min ble.un FAIL - ldsfld float64 ble_un::_zero - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::minus_zero + ldsfld float64 ble_un::minus_one ble.un FAIL - ldsfld float64 ble_un::_zero - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::minus_zero + ldsfld float64 ble_un::minus_zero ble.un AA br FAIL AA: - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::minus_zero ldsfld float64 ble_un::zero ble.un BB br FAIL BB: - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::minus_zero ldsfld float64 ble_un::one ble.un CC br FAIL CC: - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::minus_zero ldsfld float64 ble_un::max ble.un DD br FAIL DD: - ldsfld float64 ble_un::_zero - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::minus_zero + ldsfld float64 ble_un::pos_inf ble.un EE br FAIL EE: - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::minus_zero ldsfld float64 ble_un::NaN ble.un FF br FAIL FF: ldsfld float64 ble_un::zero - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::neg_inf ble.un FAIL ldsfld float64 ble_un::zero - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::min ble.un FAIL ldsfld float64 ble_un::zero - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::minus_one ble.un FAIL ldsfld float64 ble_un::zero - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::minus_zero ble.un GG br FAIL @@ -284,7 +293,7 @@ II: JJ: ldsfld float64 ble_un::zero - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::pos_inf ble.un KK br FAIL @@ -296,19 +305,19 @@ KK: LL: ldsfld float64 ble_un::one - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::neg_inf ble.un FAIL ldsfld float64 ble_un::one - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::min ble.un FAIL ldsfld float64 ble_un::one - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::minus_one ble.un FAIL ldsfld float64 ble_un::one - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::minus_zero ble.un FAIL ldsfld float64 ble_un::one @@ -328,7 +337,7 @@ MM: NN: ldsfld float64 ble_un::one - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::pos_inf ble.un OO br FAIL @@ -340,19 +349,19 @@ OO: PP: ldsfld float64 ble_un::max - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::neg_inf ble.un FAIL ldsfld float64 ble_un::max - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::min ble.un FAIL ldsfld float64 ble_un::max - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::minus_one ble.un FAIL ldsfld float64 ble_un::max - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::minus_zero ble.un FAIL ldsfld float64 ble_un::max @@ -370,7 +379,7 @@ PP: QQ: ldsfld float64 ble_un::max - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::pos_inf ble.un RR br FAIL @@ -381,66 +390,66 @@ RR: br FAIL SS: - ldsfld float64 ble_un::inf - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::pos_inf + ldsfld float64 ble_un::neg_inf ble.un FAIL - ldsfld float64 ble_un::inf - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::pos_inf + ldsfld float64 ble_un::min ble.un FAIL - ldsfld float64 ble_un::inf - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::pos_inf + ldsfld float64 ble_un::minus_one ble.un FAIL - ldsfld float64 ble_un::inf - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::pos_inf + ldsfld float64 ble_un::minus_zero ble.un FAIL - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::pos_inf ldsfld float64 ble_un::zero ble.un FAIL - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::pos_inf ldsfld float64 ble_un::one ble.un FAIL - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::pos_inf ldsfld float64 ble_un::max ble.un FAIL - ldsfld float64 ble_un::inf - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::pos_inf + ldsfld float64 ble_un::pos_inf ble.un TT br FAIL TT: - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::pos_inf ldsfld float64 ble_un::NaN ble.un UU br FAIL UU: ldsfld float64 ble_un::NaN - ldsfld float64 ble_un::_inf + ldsfld float64 ble_un::neg_inf ble.un VV br FAIL VV: ldsfld float64 ble_un::NaN - ldsfld float64 ble_un::_min + ldsfld float64 ble_un::min ble.un WW br FAIL WW: ldsfld float64 ble_un::NaN - ldsfld float64 ble_un::_one + ldsfld float64 ble_un::minus_one ble.un XX br FAIL XX: ldsfld float64 ble_un::NaN - ldsfld float64 ble_un::_zero + ldsfld float64 ble_un::minus_zero ble.un YY br FAIL @@ -464,14 +473,448 @@ AAA: BBB: ldsfld float64 ble_un::NaN - ldsfld float64 ble_un::inf + ldsfld float64 ble_un::pos_inf ble.un CCC br FAIL CCC: ldsfld float64 ble_un::NaN ldsfld float64 ble_un::NaN - ble.un BACKCHECK + ble.un L0 + br FAIL + + // Testing early folding logic + +L0: + ldc.r8 NEG_INF + ldc.r8 NEG_INF + ble.un L1 + br FAIL + +L1: + ldc.r8 NEG_INF + ldc.r8 MIN + ble.un L2 + br FAIL + +L2: + ldc.r8 NEG_INF + ldc.r8 MINUS_ONE + ble.un L3 + br FAIL + +L3: + ldc.r8 NEG_INF + ldc.r8 MINUS_ZERO + ble.un L4 + br FAIL + +L4: + ldc.r8 NEG_INF + ldc.r8 ZERO + ble.un L5 + br FAIL + +L5: + ldc.r8 NEG_INF + ldc.r8 ONE + ble.un L6 + br FAIL + +L6: + ldc.r8 NEG_INF + ldc.r8 MAX + ble.un L7 + br FAIL + +L7: + ldc.r8 NEG_INF + ldc.r8 POS_INF + ble.un L8 + br FAIL + +L8: + ldc.r8 NEG_INF + ldc.r8 NAN + ble.un L9 + br FAIL + +L9: + ldc.r8 MIN + ldc.r8 NEG_INF + ble.un FAIL + + ldc.r8 MIN + ldc.r8 MIN + ble.un L10 + br FAIL + +L10: + ldc.r8 MIN + ldc.r8 MINUS_ONE + ble.un L11 + br FAIL + +L11: + ldc.r8 MIN + ldc.r8 MINUS_ZERO + ble.un L12 + br FAIL + +L12: + ldc.r8 MIN + ldc.r8 ZERO + ble.un L13 + br FAIL + +L13: + ldc.r8 MIN + ldc.r8 ONE + ble.un L14 + br FAIL + +L14: + ldc.r8 MIN + ldc.r8 MAX + ble.un L15 + br FAIL + +L15: + ldc.r8 MIN + ldc.r8 POS_INF + ble.un L16 + br FAIL + +L16: + ldc.r8 MIN + ldc.r8 NAN + ble.un L17 + br FAIL + +L17: + ldc.r8 MINUS_ONE + ldc.r8 NEG_INF + ble.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MIN + ble.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ONE + ble.un L18 + br FAIL + +L18: + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ZERO + ble.un L19 + br FAIL + +L19: + ldc.r8 MINUS_ONE + ldc.r8 ZERO + ble.un L20 + br FAIL + +L20: + ldc.r8 MINUS_ONE + ldc.r8 ONE + ble.un L21 + br FAIL + +L21: + ldc.r8 MINUS_ONE + ldc.r8 MAX + ble.un L22 + br FAIL + +L22: + ldc.r8 MINUS_ONE + ldc.r8 POS_INF + ble.un L23 + br FAIL + +L23: + ldc.r8 MINUS_ONE + ldc.r8 NAN + ble.un L24 + br FAIL + +L24: + ldc.r8 MINUS_ZERO + ldc.r8 NEG_INF + ble.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MIN + ble.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ONE + ble.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ZERO + ble.un L25 + br FAIL + +L25: + ldc.r8 MINUS_ZERO + ldc.r8 ZERO + ble.un L26 + br FAIL + +L26: + ldc.r8 MINUS_ZERO + ldc.r8 ONE + ble.un L27 + br FAIL + +L27: + ldc.r8 MINUS_ZERO + ldc.r8 MAX + ble.un L28 + br FAIL + +L28: + ldc.r8 MINUS_ZERO + ldc.r8 POS_INF + ble.un L29 + br FAIL + +L29: + ldc.r8 MINUS_ZERO + ldc.r8 NAN + ble.un L30 + br FAIL + +L30: + ldc.r8 ZERO + ldc.r8 NEG_INF + ble.un FAIL + + ldc.r8 ZERO + ldc.r8 MIN + ble.un FAIL + + ldc.r8 ZERO + ldc.r8 MINUS_ONE + ble.un FAIL + + ldc.r8 ZERO + ldc.r8 MINUS_ZERO + ble.un L31 + br FAIL + +L31: + ldc.r8 ZERO + ldc.r8 ZERO + ble.un L32 + br FAIL + +L32: + ldc.r8 ZERO + ldc.r8 ONE + ble.un L33 + br FAIL + +L33: + ldc.r8 ZERO + ldc.r8 MAX + ble.un L34 + br FAIL + +L34: + ldc.r8 ZERO + ldc.r8 POS_INF + ble.un L35 + br FAIL + +L35: + ldc.r8 ZERO + ldc.r8 NAN + ble.un L36 + br FAIL + +L36: + ldc.r8 ONE + ldc.r8 NEG_INF + ble.un FAIL + + ldc.r8 ONE + ldc.r8 MIN + ble.un FAIL + + ldc.r8 ONE + ldc.r8 MINUS_ONE + ble.un FAIL + + ldc.r8 ONE + ldc.r8 MINUS_ZERO + ble.un FAIL + + ldc.r8 ONE + ldc.r8 ZERO + ble.un FAIL + + ldc.r8 ONE + ldc.r8 ONE + ble.un L37 + br FAIL + +L37: + ldc.r8 ONE + ldc.r8 MAX + ble.un L38 + br FAIL + +L38: + ldc.r8 ONE + ldc.r8 POS_INF + ble.un L39 + br FAIL + +L39: + ldc.r8 ONE + ldc.r8 NAN + ble.un L40 + br FAIL + +L40: + ldc.r8 MAX + ldc.r8 NEG_INF + ble.un FAIL + + ldc.r8 MAX + ldc.r8 MIN + ble.un FAIL + + ldc.r8 MAX + ldc.r8 MINUS_ONE + ble.un FAIL + + ldc.r8 MAX + ldc.r8 MINUS_ZERO + ble.un FAIL + + ldc.r8 MAX + ldc.r8 ZERO + ble.un FAIL + + ldc.r8 MAX + ldc.r8 ONE + ble.un FAIL + + ldc.r8 MAX + ldc.r8 MAX + ble.un L41 + br FAIL + +L41: + ldc.r8 MAX + ldc.r8 POS_INF + ble.un L42 + br FAIL + +L42: + ldc.r8 MAX + ldc.r8 NAN + ble.un L43 + br FAIL + +L43: + ldc.r8 POS_INF + ldc.r8 NEG_INF + ble.un FAIL + + ldc.r8 POS_INF + ldc.r8 MIN + ble.un FAIL + + ldc.r8 POS_INF + ldc.r8 MINUS_ONE + ble.un FAIL + + ldc.r8 POS_INF + ldc.r8 MINUS_ZERO + ble.un FAIL + + ldc.r8 POS_INF + ldc.r8 ZERO + ble.un FAIL + + ldc.r8 POS_INF + ldc.r8 ONE + ble.un FAIL + + ldc.r8 POS_INF + ldc.r8 MAX + ble.un FAIL + + ldc.r8 POS_INF + ldc.r8 POS_INF + ble.un L44 + br FAIL + +L44: + ldc.r8 POS_INF + ldc.r8 NAN + ble.un L45 + br FAIL + +L45: + ldc.r8 NAN + ldc.r8 NEG_INF + ble.un L46 + br FAIL + +L46: + ldc.r8 NAN + ldc.r8 MIN + ble.un L47 + br FAIL + +L47: + ldc.r8 NAN + ldc.r8 MINUS_ONE + ble.un L48 + br FAIL + +L48: + ldc.r8 NAN + ldc.r8 MINUS_ZERO + ble.un L49 + br FAIL + +L49: + ldc.r8 NAN + ldc.r8 ZERO + ble.un L50 + br FAIL + +L50: + ldc.r8 NAN + ldc.r8 ONE + ble.un L51 + br FAIL + +L51: + ldc.r8 NAN + ldc.r8 MAX + ble.un L52 + br FAIL + +L52: + ldc.r8 NAN + ldc.r8 POS_INF + ble.un L53 + br FAIL + +L53: + ldc.r8 NAN + ldc.r8 NAN + ble.un BACKCHECK br FAIL TOPASS: diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/blt_un_r4.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/blt_un_r4.il index 0e254711d1966..158ef20b8bbb2 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/blt_un_r4.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/blt_un_r4.il @@ -3,38 +3,47 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float32(0xFF800000)" +#define MIN "float32(0xFF7FFFFF)" +#define MINUS_ONE "float32(0xBF800000)" +#define MINUS_ZERO "float32(0x80000000)" +#define ZERO "float32(0x00000000)" +#define ONE "float32(0x3F800000)" +#define MAX "float32(0x7F7FFFFF)" +#define POS_INF "float32(0x7F800000)" +#define NAN "float32(0x7FC00000)" .class public _blt_un { -.field public static float32 _inf -.field public static float32 _min -.field public static float32 _one -.field public static float32 _zero +.field public static float32 neg_inf +.field public static float32 min +.field public static float32 minus_one +.field public static float32 minus_zero .field public static float32 zero .field public static float32 one .field public static float32 max -.field public static float32 inf +.field public static float32 pos_inf .field public static float32 NaN .method public static void initialize() { .maxstack 10 - ldc.r4 float32(0xFF800000) - stsfld float32 _blt_un::_inf - ldc.r4 float32(0xFF7FFFFF) - stsfld float32 _blt_un::_min - ldc.r4 float32(0xBF800000) - stsfld float32 _blt_un::_one - ldc.r4 float32(0x80000000) - stsfld float32 _blt_un::_zero - ldc.r4 float32(0x00000000) + ldc.r4 NEG_INF + stsfld float32 _blt_un::neg_inf + ldc.r4 MIN + stsfld float32 _blt_un::min + ldc.r4 MINUS_ONE + stsfld float32 _blt_un::minus_one + ldc.r4 MINUS_ZERO + stsfld float32 _blt_un::minus_zero + ldc.r4 ZERO stsfld float32 _blt_un::zero - ldc.r4 float32(0x3F800000) + ldc.r4 ONE stsfld float32 _blt_un::one - ldc.r4 float32(0x7F7FFFFF) + ldc.r4 MAX stsfld float32 _blt_un::max - ldc.r4 float32(0x7F800000) - stsfld float32 _blt_un::inf - ldc.r4 float32(0x7FC00000) + ldc.r4 POS_INF + stsfld float32 _blt_un::pos_inf + ldc.r4 NAN stsfld float32 _blt_un::NaN ret } @@ -44,218 +53,218 @@ .maxstack 10 call void _blt_un::initialize() - ldsfld float32 _blt_un::_inf - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::neg_inf + ldsfld float32 _blt_un::neg_inf blt.un FAIL A: - ldsfld float32 _blt_un::_inf - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::neg_inf + ldsfld float32 _blt_un::min blt.un B br FAIL B: - ldsfld float32 _blt_un::_inf - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::neg_inf + ldsfld float32 _blt_un::minus_one blt.un C br FAIL C: - ldsfld float32 _blt_un::_inf - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::neg_inf + ldsfld float32 _blt_un::minus_zero blt.un D br FAIL D: - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::neg_inf ldsfld float32 _blt_un::zero blt.un E br FAIL E: - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::neg_inf ldsfld float32 _blt_un::one blt.un F br FAIL F: - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::neg_inf ldsfld float32 _blt_un::max blt.un G br FAIL G: - ldsfld float32 _blt_un::_inf - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::neg_inf + ldsfld float32 _blt_un::pos_inf blt.un H br FAIL H: - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::neg_inf ldsfld float32 _blt_un::NaN blt.un K br FAIL K: - ldsfld float32 _blt_un::_min - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::min + ldsfld float32 _blt_un::neg_inf blt.un FAIL - ldsfld float32 _blt_un::_min - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::min + ldsfld float32 _blt_un::min blt.un FAIL L: - ldsfld float32 _blt_un::_min - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::min + ldsfld float32 _blt_un::minus_one blt.un M br FAIL M: - ldsfld float32 _blt_un::_min - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::min + ldsfld float32 _blt_un::minus_zero blt.un N br FAIL N: - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::min ldsfld float32 _blt_un::zero blt.un O br FAIL O: - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::min ldsfld float32 _blt_un::one blt.un P br FAIL P: - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::min ldsfld float32 _blt_un::max blt.un Q br FAIL Q: - ldsfld float32 _blt_un::_min - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::min + ldsfld float32 _blt_un::pos_inf blt.un R br FAIL R: - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::min ldsfld float32 _blt_un::NaN blt.un S br FAIL S: - ldsfld float32 _blt_un::_one - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::minus_one + ldsfld float32 _blt_un::neg_inf blt.un FAIL - ldsfld float32 _blt_un::_one - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::minus_one + ldsfld float32 _blt_un::min blt.un FAIL - ldsfld float32 _blt_un::_one - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::minus_one + ldsfld float32 _blt_un::minus_one blt.un FAIL T: - ldsfld float32 _blt_un::_one - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::minus_one + ldsfld float32 _blt_un::minus_zero blt.un U br FAIL U: - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::minus_one ldsfld float32 _blt_un::zero blt.un V br FAIL V: - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::minus_one ldsfld float32 _blt_un::one blt.un W br FAIL W: - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::minus_one ldsfld float32 _blt_un::max blt.un X br FAIL X: - ldsfld float32 _blt_un::_one - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::minus_one + ldsfld float32 _blt_un::pos_inf blt.un Y br FAIL Y: - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::minus_one ldsfld float32 _blt_un::NaN blt.un Z br FAIL Z: - ldsfld float32 _blt_un::_zero - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::minus_zero + ldsfld float32 _blt_un::neg_inf blt.un FAIL - ldsfld float32 _blt_un::_zero - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::minus_zero + ldsfld float32 _blt_un::min blt.un FAIL - ldsfld float32 _blt_un::_zero - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::minus_zero + ldsfld float32 _blt_un::minus_one blt.un FAIL - ldsfld float32 _blt_un::_zero - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::minus_zero + ldsfld float32 _blt_un::minus_zero blt.un FAIL AA: - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::minus_zero ldsfld float32 _blt_un::zero blt.un FAIL BB: - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::minus_zero ldsfld float32 _blt_un::one blt.un CC br FAIL CC: - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::minus_zero ldsfld float32 _blt_un::max blt.un DD br FAIL DD: - ldsfld float32 _blt_un::_zero - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::minus_zero + ldsfld float32 _blt_un::pos_inf blt.un EE br FAIL EE: - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::minus_zero ldsfld float32 _blt_un::NaN blt.un FF br FAIL FF: ldsfld float32 _blt_un::zero - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::neg_inf blt.un FAIL ldsfld float32 _blt_un::zero - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::min blt.un FAIL ldsfld float32 _blt_un::zero - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::minus_one blt.un FAIL ldsfld float32 _blt_un::zero - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::minus_zero blt.un FAIL GG: @@ -277,7 +286,7 @@ II: JJ: ldsfld float32 _blt_un::zero - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::pos_inf blt.un KK br FAIL @@ -289,19 +298,19 @@ KK: LL: ldsfld float32 _blt_un::one - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::neg_inf blt.un FAIL ldsfld float32 _blt_un::one - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::min blt.un FAIL ldsfld float32 _blt_un::one - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::minus_one blt.un FAIL ldsfld float32 _blt_un::one - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::minus_zero blt.un FAIL ldsfld float32 _blt_un::one @@ -320,7 +329,7 @@ MM: NN: ldsfld float32 _blt_un::one - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::pos_inf blt.un OO br FAIL @@ -332,19 +341,19 @@ OO: PP: ldsfld float32 _blt_un::max - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::neg_inf blt.un FAIL ldsfld float32 _blt_un::max - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::min blt.un FAIL ldsfld float32 _blt_un::max - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::minus_one blt.un FAIL ldsfld float32 _blt_un::max - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::minus_zero blt.un FAIL ldsfld float32 _blt_un::max @@ -361,7 +370,7 @@ PP: QQ: ldsfld float32 _blt_un::max - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::pos_inf blt.un RR br FAIL @@ -372,65 +381,65 @@ RR: br FAIL SS: - ldsfld float32 _blt_un::inf - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::pos_inf + ldsfld float32 _blt_un::neg_inf blt.un FAIL - ldsfld float32 _blt_un::inf - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::pos_inf + ldsfld float32 _blt_un::min blt.un FAIL - ldsfld float32 _blt_un::inf - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::pos_inf + ldsfld float32 _blt_un::minus_one blt.un FAIL - ldsfld float32 _blt_un::inf - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::pos_inf + ldsfld float32 _blt_un::minus_zero blt.un FAIL - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::pos_inf ldsfld float32 _blt_un::zero blt.un FAIL - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::pos_inf ldsfld float32 _blt_un::one blt.un FAIL - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::pos_inf ldsfld float32 _blt_un::max blt.un FAIL - ldsfld float32 _blt_un::inf - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::pos_inf + ldsfld float32 _blt_un::pos_inf blt.un FAIL TT: - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::pos_inf ldsfld float32 _blt_un::NaN blt.un UU br FAIL UU: ldsfld float32 _blt_un::NaN - ldsfld float32 _blt_un::_inf + ldsfld float32 _blt_un::neg_inf blt.un VV br FAIL VV: ldsfld float32 _blt_un::NaN - ldsfld float32 _blt_un::_min + ldsfld float32 _blt_un::min blt.un WW br FAIL WW: ldsfld float32 _blt_un::NaN - ldsfld float32 _blt_un::_one + ldsfld float32 _blt_un::minus_one blt.un XX br FAIL XX: ldsfld float32 _blt_un::NaN - ldsfld float32 _blt_un::_zero + ldsfld float32 _blt_un::minus_zero blt.un YY br FAIL @@ -454,14 +463,428 @@ AAA: BBB: ldsfld float32 _blt_un::NaN - ldsfld float32 _blt_un::inf + ldsfld float32 _blt_un::pos_inf blt.un CCC br FAIL CCC: ldsfld float32 _blt_un::NaN ldsfld float32 _blt_un::NaN - blt.un BACKCHECK + blt.un L0 + br FAIL + + // Testing early folding logic + +L0: + ldc.r4 NEG_INF + ldc.r4 NEG_INF + blt.un FAIL + + ldc.r4 NEG_INF + ldc.r4 MIN + blt.un L1 + br FAIL + +L1: + ldc.r4 NEG_INF + ldc.r4 MINUS_ONE + blt.un L2 + br FAIL + +L2: + ldc.r4 NEG_INF + ldc.r4 MINUS_ZERO + blt.un L3 + br FAIL + +L3: + ldc.r4 NEG_INF + ldc.r4 ZERO + blt.un L4 + br FAIL + +L4: + ldc.r4 NEG_INF + ldc.r4 ONE + blt.un L5 + br FAIL + +L5: + ldc.r4 NEG_INF + ldc.r4 MAX + blt.un L6 + br FAIL + +L6: + ldc.r4 NEG_INF + ldc.r4 POS_INF + blt.un L7 + br FAIL + +L7: + ldc.r4 NEG_INF + ldc.r4 NAN + blt.un L8 + br FAIL + +L8: + ldc.r4 MIN + ldc.r4 NEG_INF + blt.un FAIL + + ldc.r4 MIN + ldc.r4 MIN + blt.un FAIL + + ldc.r4 MIN + ldc.r4 MINUS_ONE + blt.un L9 + br FAIL + +L9: + ldc.r4 MIN + ldc.r4 MINUS_ZERO + blt.un L10 + br FAIL + +L10: + ldc.r4 MIN + ldc.r4 ZERO + blt.un L11 + br FAIL + +L11: + ldc.r4 MIN + ldc.r4 ONE + blt.un L12 + br FAIL + +L12: + ldc.r4 MIN + ldc.r4 MAX + blt.un L13 + br FAIL + +L13: + ldc.r4 MIN + ldc.r4 POS_INF + blt.un L14 + br FAIL + +L14: + ldc.r4 MIN + ldc.r4 NAN + blt.un L15 + br FAIL + +L15: + ldc.r4 MINUS_ONE + ldc.r4 NEG_INF + blt.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MIN + blt.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ONE + blt.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ZERO + blt.un L16 + br FAIL + +L16: + ldc.r4 MINUS_ONE + ldc.r4 ZERO + blt.un L17 + br FAIL + +L17: + ldc.r4 MINUS_ONE + ldc.r4 ONE + blt.un L18 + br FAIL + +L18: + ldc.r4 MINUS_ONE + ldc.r4 MAX + blt.un L19 + br FAIL + +L19: + ldc.r4 MINUS_ONE + ldc.r4 POS_INF + blt.un L20 + br FAIL + +L20: + ldc.r4 MINUS_ONE + ldc.r4 NAN + blt.un L21 + br FAIL + +L21: + ldc.r4 MINUS_ZERO + ldc.r4 NEG_INF + blt.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MIN + blt.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ONE + blt.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ZERO + blt.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 ZERO + blt.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 ONE + blt.un L22 + br FAIL + +L22: + ldc.r4 MINUS_ZERO + ldc.r4 MAX + blt.un L23 + br FAIL + +L23: + ldc.r4 MINUS_ZERO + ldc.r4 POS_INF + blt.un L24 + br FAIL + +L24: + ldc.r4 MINUS_ZERO + ldc.r4 NAN + blt.un L25 + br FAIL + +L25: + ldc.r4 ZERO + ldc.r4 NEG_INF + blt.un FAIL + + ldc.r4 ZERO + ldc.r4 MIN + blt.un FAIL + + ldc.r4 ZERO + ldc.r4 MINUS_ONE + blt.un FAIL + + ldc.r4 ZERO + ldc.r4 MINUS_ZERO + blt.un FAIL + + ldc.r4 ZERO + ldc.r4 ZERO + blt.un FAIL + + ldc.r4 ZERO + ldc.r4 ONE + blt.un L26 + br FAIL + +L26: + ldc.r4 ZERO + ldc.r4 MAX + blt.un L27 + br FAIL + +L27: + ldc.r4 ZERO + ldc.r4 POS_INF + blt.un L28 + br FAIL + +L28: + ldc.r4 ZERO + ldc.r4 NAN + blt.un L29 + br FAIL + +L29: + ldc.r4 ONE + ldc.r4 NEG_INF + blt.un FAIL + + ldc.r4 ONE + ldc.r4 MIN + blt.un FAIL + + ldc.r4 ONE + ldc.r4 MINUS_ONE + blt.un FAIL + + ldc.r4 ONE + ldc.r4 MINUS_ZERO + blt.un FAIL + + ldc.r4 ONE + ldc.r4 ZERO + blt.un FAIL + + ldc.r4 ONE + ldc.r4 ONE + blt.un FAIL + + ldc.r4 ONE + ldc.r4 MAX + blt.un L30 + br FAIL + +L30: + ldc.r4 ONE + ldc.r4 POS_INF + blt.un L31 + br FAIL + +L31: + ldc.r4 ONE + ldc.r4 NAN + blt.un L32 + br FAIL + +L32: + ldc.r4 MAX + ldc.r4 NEG_INF + blt.un FAIL + + ldc.r4 MAX + ldc.r4 MIN + blt.un FAIL + + ldc.r4 MAX + ldc.r4 MINUS_ONE + blt.un FAIL + + ldc.r4 MAX + ldc.r4 MINUS_ZERO + blt.un FAIL + + ldc.r4 MAX + ldc.r4 ZERO + blt.un FAIL + + ldc.r4 MAX + ldc.r4 ONE + blt.un FAIL + + ldc.r4 MAX + ldc.r4 MAX + blt.un FAIL + + ldc.r4 MAX + ldc.r4 POS_INF + blt.un L33 + br FAIL + +L33: + ldc.r4 MAX + ldc.r4 NAN + blt.un L34 + br FAIL + +L34: + ldc.r4 POS_INF + ldc.r4 NEG_INF + blt.un FAIL + + ldc.r4 POS_INF + ldc.r4 MIN + blt.un FAIL + + ldc.r4 POS_INF + ldc.r4 MINUS_ONE + blt.un FAIL + + ldc.r4 POS_INF + ldc.r4 MINUS_ZERO + blt.un FAIL + + ldc.r4 POS_INF + ldc.r4 ZERO + blt.un FAIL + + ldc.r4 POS_INF + ldc.r4 ONE + blt.un FAIL + + ldc.r4 POS_INF + ldc.r4 MAX + blt.un FAIL + + ldc.r4 POS_INF + ldc.r4 POS_INF + blt.un FAIL + + ldc.r4 POS_INF + ldc.r4 NAN + blt.un L35 + br FAIL + +L35: + ldc.r4 NAN + ldc.r4 NEG_INF + blt.un L36 + br FAIL + +L36: + ldc.r4 NAN + ldc.r4 MIN + blt.un L37 + br FAIL + +L37: + ldc.r4 NAN + ldc.r4 MINUS_ONE + blt.un L38 + br FAIL + +L38: + ldc.r4 NAN + ldc.r4 MINUS_ZERO + blt.un L39 + br FAIL + +L39: + ldc.r4 NAN + ldc.r4 ZERO + blt.un L40 + br FAIL + +L40: + ldc.r4 NAN + ldc.r4 ONE + blt.un L41 + br FAIL + +L41: + ldc.r4 NAN + ldc.r4 MAX + blt.un L42 + br FAIL + +L42: + ldc.r4 NAN + ldc.r4 POS_INF + blt.un L43 + br FAIL + +L43: + ldc.r4 NAN + ldc.r4 NAN + blt.un BACKCHECK br FAIL TOPASS: diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/blt_un_r8.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/blt_un_r8.il index 8df3e29e0d9d3..514e66222ef4d 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/blt_un_r8.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/blt_un_r8.il @@ -3,38 +3,47 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float64(0xFFF0000000000000)" +#define MIN "float64(0xFF7FFFFFFFFFFFFF)" +#define MINUS_ONE "float64(0xBFF0000000000000)" +#define MINUS_ZERO "float64(0x8000000000000000)" +#define ZERO "float64(0x0000000000000000)" +#define ONE "float64(0x3FF0000000000000)" +#define MAX "float64(0x7FEFFFFFFFFFFFFF)" +#define POS_INF "float64(0x7FF0000000000000)" +#define NAN "float64(0x7FF8000000000000)" .class public blt_un { -.field public static float64 _inf -.field public static float64 _min -.field public static float64 _one -.field public static float64 _zero +.field public static float64 neg_inf +.field public static float64 min +.field public static float64 minus_one +.field public static float64 minus_zero .field public static float64 zero .field public static float64 one .field public static float64 max -.field public static float64 inf +.field public static float64 pos_inf .field public static float64 NaN .method public static void initialize() { .maxstack 10 - ldc.r8 float64(0xFFF0000000000000) - stsfld float64 blt_un::_inf - ldc.r8 float64(0xFF7FFFFFFFFFFFFF) - stsfld float64 blt_un::_min - ldc.r8 float64(0xBFF0000000000000) - stsfld float64 blt_un::_one - ldc.r8 float64(0x8000000000000000) - stsfld float64 blt_un::_zero - ldc.r8 float64(0x0000000000000000) + ldc.r8 NEG_INF + stsfld float64 blt_un::neg_inf + ldc.r8 MIN + stsfld float64 blt_un::min + ldc.r8 MINUS_ONE + stsfld float64 blt_un::minus_one + ldc.r8 MINUS_ZERO + stsfld float64 blt_un::minus_zero + ldc.r8 ZERO stsfld float64 blt_un::zero - ldc.r8 float64(0x3FF0000000000000) + ldc.r8 ONE stsfld float64 blt_un::one - ldc.r8 float64(0x7FEFFFFFFFFFFFFF) + ldc.r8 MAX stsfld float64 blt_un::max - ldc.r8 float64(0x7FF0000000000000) - stsfld float64 blt_un::inf - ldc.r8 float64(0x7FF8000000000000) + ldc.r8 POS_INF + stsfld float64 blt_un::pos_inf + ldc.r8 NAN stsfld float64 blt_un::NaN ret } @@ -44,218 +53,218 @@ .maxstack 10 call void blt_un::initialize() - ldsfld float64 blt_un::_inf - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::neg_inf + ldsfld float64 blt_un::neg_inf blt.un FAIL A: - ldsfld float64 blt_un::_inf - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::neg_inf + ldsfld float64 blt_un::min blt.un B br FAIL B: - ldsfld float64 blt_un::_inf - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::neg_inf + ldsfld float64 blt_un::minus_one blt.un C br FAIL C: - ldsfld float64 blt_un::_inf - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::neg_inf + ldsfld float64 blt_un::minus_zero blt.un D br FAIL D: - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::neg_inf ldsfld float64 blt_un::zero blt.un E br FAIL E: - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::neg_inf ldsfld float64 blt_un::one blt.un F br FAIL F: - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::neg_inf ldsfld float64 blt_un::max blt.un G br FAIL G: - ldsfld float64 blt_un::_inf - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::neg_inf + ldsfld float64 blt_un::pos_inf blt.un H br FAIL H: - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::neg_inf ldsfld float64 blt_un::NaN blt.un K br FAIL K: - ldsfld float64 blt_un::_min - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::min + ldsfld float64 blt_un::neg_inf blt.un FAIL - ldsfld float64 blt_un::_min - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::min + ldsfld float64 blt_un::min blt.un FAIL L: - ldsfld float64 blt_un::_min - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::min + ldsfld float64 blt_un::minus_one blt.un M br FAIL M: - ldsfld float64 blt_un::_min - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::min + ldsfld float64 blt_un::minus_zero blt.un N br FAIL N: - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::min ldsfld float64 blt_un::zero blt.un O br FAIL O: - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::min ldsfld float64 blt_un::one blt.un P br FAIL P: - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::min ldsfld float64 blt_un::max blt.un Q br FAIL Q: - ldsfld float64 blt_un::_min - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::min + ldsfld float64 blt_un::pos_inf blt.un R br FAIL R: - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::min ldsfld float64 blt_un::NaN blt.un S br FAIL S: - ldsfld float64 blt_un::_one - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::minus_one + ldsfld float64 blt_un::neg_inf blt.un FAIL - ldsfld float64 blt_un::_one - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::minus_one + ldsfld float64 blt_un::min blt.un FAIL - ldsfld float64 blt_un::_one - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::minus_one + ldsfld float64 blt_un::minus_one blt.un FAIL T: - ldsfld float64 blt_un::_one - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::minus_one + ldsfld float64 blt_un::minus_zero blt.un U br FAIL U: - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::minus_one ldsfld float64 blt_un::zero blt.un V br FAIL V: - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::minus_one ldsfld float64 blt_un::one blt.un W br FAIL W: - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::minus_one ldsfld float64 blt_un::max blt.un X br FAIL X: - ldsfld float64 blt_un::_one - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::minus_one + ldsfld float64 blt_un::pos_inf blt.un Y br FAIL Y: - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::minus_one ldsfld float64 blt_un::NaN blt.un Z br FAIL Z: - ldsfld float64 blt_un::_zero - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::minus_zero + ldsfld float64 blt_un::neg_inf blt.un FAIL - ldsfld float64 blt_un::_zero - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::minus_zero + ldsfld float64 blt_un::min blt.un FAIL - ldsfld float64 blt_un::_zero - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::minus_zero + ldsfld float64 blt_un::minus_one blt.un FAIL - ldsfld float64 blt_un::_zero - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::minus_zero + ldsfld float64 blt_un::minus_zero blt.un FAIL AA: - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::minus_zero ldsfld float64 blt_un::zero blt.un FAIL BB: - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::minus_zero ldsfld float64 blt_un::one blt.un CC br FAIL CC: - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::minus_zero ldsfld float64 blt_un::max blt.un DD br FAIL DD: - ldsfld float64 blt_un::_zero - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::minus_zero + ldsfld float64 blt_un::pos_inf blt.un EE br FAIL EE: - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::minus_zero ldsfld float64 blt_un::NaN blt.un FF br FAIL FF: ldsfld float64 blt_un::zero - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::neg_inf blt.un FAIL ldsfld float64 blt_un::zero - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::min blt.un FAIL ldsfld float64 blt_un::zero - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::minus_one blt.un FAIL ldsfld float64 blt_un::zero - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::minus_zero blt.un FAIL GG: @@ -277,7 +286,7 @@ II: JJ: ldsfld float64 blt_un::zero - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::pos_inf blt.un KK br FAIL @@ -289,19 +298,19 @@ KK: LL: ldsfld float64 blt_un::one - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::neg_inf blt.un FAIL ldsfld float64 blt_un::one - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::min blt.un FAIL ldsfld float64 blt_un::one - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::minus_one blt.un FAIL ldsfld float64 blt_un::one - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::minus_zero blt.un FAIL ldsfld float64 blt_un::one @@ -320,7 +329,7 @@ MM: NN: ldsfld float64 blt_un::one - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::pos_inf blt.un OO br FAIL @@ -332,19 +341,19 @@ OO: PP: ldsfld float64 blt_un::max - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::neg_inf blt.un FAIL ldsfld float64 blt_un::max - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::min blt.un FAIL ldsfld float64 blt_un::max - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::minus_one blt.un FAIL ldsfld float64 blt_un::max - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::minus_zero blt.un FAIL ldsfld float64 blt_un::max @@ -361,7 +370,7 @@ PP: QQ: ldsfld float64 blt_un::max - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::pos_inf blt.un RR br FAIL @@ -372,65 +381,65 @@ RR: br FAIL SS: - ldsfld float64 blt_un::inf - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::pos_inf + ldsfld float64 blt_un::neg_inf blt.un FAIL - ldsfld float64 blt_un::inf - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::pos_inf + ldsfld float64 blt_un::min blt.un FAIL - ldsfld float64 blt_un::inf - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::pos_inf + ldsfld float64 blt_un::minus_one blt.un FAIL - ldsfld float64 blt_un::inf - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::pos_inf + ldsfld float64 blt_un::minus_zero blt.un FAIL - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::pos_inf ldsfld float64 blt_un::zero blt.un FAIL - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::pos_inf ldsfld float64 blt_un::one blt.un FAIL - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::pos_inf ldsfld float64 blt_un::max blt.un FAIL - ldsfld float64 blt_un::inf - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::pos_inf + ldsfld float64 blt_un::pos_inf blt.un FAIL TT: - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::pos_inf ldsfld float64 blt_un::NaN blt.un UU br FAIL UU: ldsfld float64 blt_un::NaN - ldsfld float64 blt_un::_inf + ldsfld float64 blt_un::neg_inf blt.un VV br FAIL VV: ldsfld float64 blt_un::NaN - ldsfld float64 blt_un::_min + ldsfld float64 blt_un::min blt.un WW br FAIL WW: ldsfld float64 blt_un::NaN - ldsfld float64 blt_un::_one + ldsfld float64 blt_un::minus_one blt.un XX br FAIL XX: ldsfld float64 blt_un::NaN - ldsfld float64 blt_un::_zero + ldsfld float64 blt_un::minus_zero blt.un YY br FAIL @@ -454,14 +463,428 @@ AAA: BBB: ldsfld float64 blt_un::NaN - ldsfld float64 blt_un::inf + ldsfld float64 blt_un::pos_inf blt.un CCC br FAIL CCC: ldsfld float64 blt_un::NaN ldsfld float64 blt_un::NaN - blt.un BACKCHECK + blt.un L0 + br FAIL + + // Testing early folding logic + +L0: + ldc.r8 NEG_INF + ldc.r8 NEG_INF + blt.un FAIL + + ldc.r8 NEG_INF + ldc.r8 MIN + blt.un L1 + br FAIL + +L1: + ldc.r8 NEG_INF + ldc.r8 MINUS_ONE + blt.un L2 + br FAIL + +L2: + ldc.r8 NEG_INF + ldc.r8 MINUS_ZERO + blt.un L3 + br FAIL + +L3: + ldc.r8 NEG_INF + ldc.r8 ZERO + blt.un L4 + br FAIL + +L4: + ldc.r8 NEG_INF + ldc.r8 ONE + blt.un L5 + br FAIL + +L5: + ldc.r8 NEG_INF + ldc.r8 MAX + blt.un L6 + br FAIL + +L6: + ldc.r8 NEG_INF + ldc.r8 POS_INF + blt.un L7 + br FAIL + +L7: + ldc.r8 NEG_INF + ldc.r8 NAN + blt.un L8 + br FAIL + +L8: + ldc.r8 MIN + ldc.r8 NEG_INF + blt.un FAIL + + ldc.r8 MIN + ldc.r8 MIN + blt.un FAIL + + ldc.r8 MIN + ldc.r8 MINUS_ONE + blt.un L9 + br FAIL + +L9: + ldc.r8 MIN + ldc.r8 MINUS_ZERO + blt.un L10 + br FAIL + +L10: + ldc.r8 MIN + ldc.r8 ZERO + blt.un L11 + br FAIL + +L11: + ldc.r8 MIN + ldc.r8 ONE + blt.un L12 + br FAIL + +L12: + ldc.r8 MIN + ldc.r8 MAX + blt.un L13 + br FAIL + +L13: + ldc.r8 MIN + ldc.r8 POS_INF + blt.un L14 + br FAIL + +L14: + ldc.r8 MIN + ldc.r8 NAN + blt.un L15 + br FAIL + +L15: + ldc.r8 MINUS_ONE + ldc.r8 NEG_INF + blt.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MIN + blt.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ONE + blt.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ZERO + blt.un L16 + br FAIL + +L16: + ldc.r8 MINUS_ONE + ldc.r8 ZERO + blt.un L17 + br FAIL + +L17: + ldc.r8 MINUS_ONE + ldc.r8 ONE + blt.un L18 + br FAIL + +L18: + ldc.r8 MINUS_ONE + ldc.r8 MAX + blt.un L19 + br FAIL + +L19: + ldc.r8 MINUS_ONE + ldc.r8 POS_INF + blt.un L20 + br FAIL + +L20: + ldc.r8 MINUS_ONE + ldc.r8 NAN + blt.un L21 + br FAIL + +L21: + ldc.r8 MINUS_ZERO + ldc.r8 NEG_INF + blt.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MIN + blt.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ONE + blt.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ZERO + blt.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 ZERO + blt.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 ONE + blt.un L22 + br FAIL + +L22: + ldc.r8 MINUS_ZERO + ldc.r8 MAX + blt.un L23 + br FAIL + +L23: + ldc.r8 MINUS_ZERO + ldc.r8 POS_INF + blt.un L24 + br FAIL + +L24: + ldc.r8 MINUS_ZERO + ldc.r8 NAN + blt.un L25 + br FAIL + +L25: + ldc.r8 ZERO + ldc.r8 NEG_INF + blt.un FAIL + + ldc.r8 ZERO + ldc.r8 MIN + blt.un FAIL + + ldc.r8 ZERO + ldc.r8 MINUS_ONE + blt.un FAIL + + ldc.r8 ZERO + ldc.r8 MINUS_ZERO + blt.un FAIL + + ldc.r8 ZERO + ldc.r8 ZERO + blt.un FAIL + + ldc.r8 ZERO + ldc.r8 ONE + blt.un L26 + br FAIL + +L26: + ldc.r8 ZERO + ldc.r8 MAX + blt.un L27 + br FAIL + +L27: + ldc.r8 ZERO + ldc.r8 POS_INF + blt.un L28 + br FAIL + +L28: + ldc.r8 ZERO + ldc.r8 NAN + blt.un L29 + br FAIL + +L29: + ldc.r8 ONE + ldc.r8 NEG_INF + blt.un FAIL + + ldc.r8 ONE + ldc.r8 MIN + blt.un FAIL + + ldc.r8 ONE + ldc.r8 MINUS_ONE + blt.un FAIL + + ldc.r8 ONE + ldc.r8 MINUS_ZERO + blt.un FAIL + + ldc.r8 ONE + ldc.r8 ZERO + blt.un FAIL + + ldc.r8 ONE + ldc.r8 ONE + blt.un FAIL + + ldc.r8 ONE + ldc.r8 MAX + blt.un L30 + br FAIL + +L30: + ldc.r8 ONE + ldc.r8 POS_INF + blt.un L31 + br FAIL + +L31: + ldc.r8 ONE + ldc.r8 NAN + blt.un L32 + br FAIL + +L32: + ldc.r8 MAX + ldc.r8 NEG_INF + blt.un FAIL + + ldc.r8 MAX + ldc.r8 MIN + blt.un FAIL + + ldc.r8 MAX + ldc.r8 MINUS_ONE + blt.un FAIL + + ldc.r8 MAX + ldc.r8 MINUS_ZERO + blt.un FAIL + + ldc.r8 MAX + ldc.r8 ZERO + blt.un FAIL + + ldc.r8 MAX + ldc.r8 ONE + blt.un FAIL + + ldc.r8 MAX + ldc.r8 MAX + blt.un FAIL + + ldc.r8 MAX + ldc.r8 POS_INF + blt.un L33 + br FAIL + +L33: + ldc.r8 MAX + ldc.r8 NAN + blt.un L34 + br FAIL + +L34: + ldc.r8 POS_INF + ldc.r8 NEG_INF + blt.un FAIL + + ldc.r8 POS_INF + ldc.r8 MIN + blt.un FAIL + + ldc.r8 POS_INF + ldc.r8 MINUS_ONE + blt.un FAIL + + ldc.r8 POS_INF + ldc.r8 MINUS_ZERO + blt.un FAIL + + ldc.r8 POS_INF + ldc.r8 ZERO + blt.un FAIL + + ldc.r8 POS_INF + ldc.r8 ONE + blt.un FAIL + + ldc.r8 POS_INF + ldc.r8 MAX + blt.un FAIL + + ldc.r8 POS_INF + ldc.r8 POS_INF + blt.un FAIL + + ldc.r8 POS_INF + ldc.r8 NAN + blt.un L35 + br FAIL + +L35: + ldc.r8 NAN + ldc.r8 NEG_INF + blt.un L36 + br FAIL + +L36: + ldc.r8 NAN + ldc.r8 MIN + blt.un L37 + br FAIL + +L37: + ldc.r8 NAN + ldc.r8 MINUS_ONE + blt.un L38 + br FAIL + +L38: + ldc.r8 NAN + ldc.r8 MINUS_ZERO + blt.un L39 + br FAIL + +L39: + ldc.r8 NAN + ldc.r8 ZERO + blt.un L40 + br FAIL + +L40: + ldc.r8 NAN + ldc.r8 ONE + blt.un L41 + br FAIL + +L41: + ldc.r8 NAN + ldc.r8 MAX + blt.un L42 + br FAIL + +L42: + ldc.r8 NAN + ldc.r8 POS_INF + blt.un L43 + br FAIL + +L43: + ldc.r8 NAN + ldc.r8 NAN + blt.un BACKCHECK br FAIL TOPASS: diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bne_un_r4.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bne_un_r4.il index c02bcad9c7da1..3e5d97c61d3df 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bne_un_r4.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bne_un_r4.il @@ -3,36 +3,46 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float32(0xFF800000)" +#define MIN "float32(0xFF7FFFFF)" +#define MINUS_ONE "float32(0xBF800000)" +#define MINUS_ZERO "float32(0x80000000)" +#define ZERO "float32(0x00000000)" +#define ONE "float32(0x3F800000)" +#define MAX "float32(0x7F7FFFFF)" +#define POS_INF "float32(0x7F800000)" +#define NAN "float32(0x7FC00000)" + .class public bne_un { -.field public static float32 _inf -.field public static float32 _min -.field public static float32 _one -.field public static float32 _zero +.field public static float32 neg_inf +.field public static float32 min +.field public static float32 minus_one +.field public static float32 minus_zero .field public static float32 zero .field public static float32 one .field public static float32 max -.field public static float32 inf +.field public static float32 pos_inf .field public static float32 NaN .method public static void initialize() { .maxstack 10 - ldc.r4 float32(0xFF800000) - stsfld float32 bne_un::_inf - ldc.r4 float32(0xFF7FFFFF) - stsfld float32 bne_un::_min - ldc.r4 float32(0xBF800000) - stsfld float32 bne_un::_one - ldc.r4 float32(0x80000000) - stsfld float32 bne_un::_zero - ldc.r4 float32(0x00000000) + ldc.r4 NEG_INF + stsfld float32 bne_un::neg_inf + ldc.r4 MIN + stsfld float32 bne_un::min + ldc.r4 MINUS_ONE + stsfld float32 bne_un::minus_one + ldc.r4 MINUS_ZERO + stsfld float32 bne_un::minus_zero + ldc.r4 ZERO stsfld float32 bne_un::zero - ldc.r4 float32(0x3F800000) + ldc.r4 ONE stsfld float32 bne_un::one - ldc.r4 float32(0x7F7FFFFF) + ldc.r4 MAX stsfld float32 bne_un::max - ldc.r4 float32(0x7F800000) - stsfld float32 bne_un::inf - ldc.r4 float32(0x7FC00000) + ldc.r4 POS_INF + stsfld float32 bne_un::pos_inf + ldc.r4 NAN stsfld float32 bne_un::NaN ret } @@ -41,230 +51,230 @@ .entrypoint .maxstack 10 call void bne_un::initialize() - ldsfld float32 bne_un::_inf - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::neg_inf + ldsfld float32 bne_un::neg_inf bne.un FAIL - ldsfld float32 bne_un::_inf - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::neg_inf + ldsfld float32 bne_un::min bne.un A br FAIL A: - ldsfld float32 bne_un::_inf - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::neg_inf + ldsfld float32 bne_un::minus_one bne.un B br FAIL B: - ldsfld float32 bne_un::_inf - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::neg_inf + ldsfld float32 bne_un::minus_zero bne.un C br FAIL C: - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::neg_inf ldsfld float32 bne_un::zero bne.un D br FAIL D: - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::neg_inf ldsfld float32 bne_un::one bne.un E br FAIL E: - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::neg_inf ldsfld float32 bne_un::max bne.un F br FAIL F: - ldsfld float32 bne_un::_inf - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::neg_inf + ldsfld float32 bne_un::pos_inf bne.un G br FAIL G: - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::neg_inf ldsfld float32 bne_un::NaN bne.un H br FAIL H: - ldsfld float32 bne_un::_min - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::min + ldsfld float32 bne_un::neg_inf bne.un I br FAIL I: - ldsfld float32 bne_un::_min - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::min + ldsfld float32 bne_un::min bne.un FAIL - ldsfld float32 bne_un::_min - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::min + ldsfld float32 bne_un::minus_one bne.un J br FAIL J: - ldsfld float32 bne_un::_min - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::min + ldsfld float32 bne_un::minus_zero bne.un K br FAIL K: - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::min ldsfld float32 bne_un::zero bne.un L br FAIL L: - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::min ldsfld float32 bne_un::one bne.un M br FAIL M: - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::min ldsfld float32 bne_un::max bne.un N br FAIL N: - ldsfld float32 bne_un::_min - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::min + ldsfld float32 bne_un::pos_inf bne.un O br FAIL O: - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::min ldsfld float32 bne_un::NaN bne.un P br FAIL P: - ldsfld float32 bne_un::_one - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::minus_one + ldsfld float32 bne_un::neg_inf bne.un Q br FAIL Q: - ldsfld float32 bne_un::_one - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::minus_one + ldsfld float32 bne_un::min bne.un R br FAIL R: - ldsfld float32 bne_un::_one - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::minus_one + ldsfld float32 bne_un::minus_one bne.un FAIL S: - ldsfld float32 bne_un::_one - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::minus_one + ldsfld float32 bne_un::minus_zero bne.un T br FAIL T: - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::minus_one ldsfld float32 bne_un::zero bne.un U br FAIL U: - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::minus_one ldsfld float32 bne_un::one bne.un V br FAIL V: - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::minus_one ldsfld float32 bne_un::max bne.un W br FAIL W: - ldsfld float32 bne_un::_one - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::minus_one + ldsfld float32 bne_un::pos_inf bne.un X br FAIL X: - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::minus_one ldsfld float32 bne_un::NaN bne.un Y br FAIL Y: - ldsfld float32 bne_un::_zero - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::minus_zero + ldsfld float32 bne_un::neg_inf bne.un Z br FAIL Z: - ldsfld float32 bne_un::_zero - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::minus_zero + ldsfld float32 bne_un::min bne.un AA br FAIL AA: - ldsfld float32 bne_un::_zero - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::minus_zero + ldsfld float32 bne_un::minus_one bne.un BB br FAIL BB: - ldsfld float32 bne_un::_zero - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::minus_zero + ldsfld float32 bne_un::minus_zero bne.un FAIL - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::minus_zero ldsfld float32 bne_un::zero bne.un FAIL - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::minus_zero ldsfld float32 bne_un::one bne.un CC br FAIL CC: - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::minus_zero ldsfld float32 bne_un::max bne.un DD br FAIL DD: - ldsfld float32 bne_un::_zero - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::minus_zero + ldsfld float32 bne_un::pos_inf bne.un EE br FAIL EE: - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::minus_zero ldsfld float32 bne_un::NaN bne.un FF br FAIL FF: ldsfld float32 bne_un::zero - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::neg_inf bne.un GG br FAIL GG: ldsfld float32 bne_un::zero - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::min bne.un HH br FAIL HH: ldsfld float32 bne_un::zero - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::minus_one bne.un II br FAIL II: ldsfld float32 bne_un::zero - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::minus_zero bne.un FAIL ldsfld float32 bne_un::zero @@ -284,7 +294,7 @@ JJ: KK: ldsfld float32 bne_un::zero - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::pos_inf bne.un LL br FAIL @@ -296,25 +306,25 @@ LL: MM: ldsfld float32 bne_un::one - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::neg_inf bne.un NN br FAIL NN: ldsfld float32 bne_un::one - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::min bne.un OO br FAIL OO: ldsfld float32 bne_un::one - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::minus_one bne.un PP br FAIL PP: ldsfld float32 bne_un::one - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::minus_zero bne.un QQ br FAIL @@ -337,7 +347,7 @@ SS: TT: ldsfld float32 bne_un::one - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::pos_inf bne.un UU br FAIL @@ -349,25 +359,25 @@ UU: VV: ldsfld float32 bne_un::max - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::neg_inf bne.un WW br FAIL WW: ldsfld float32 bne_un::max - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::min bne.un XX br FAIL XX: ldsfld float32 bne_un::max - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::minus_one bne.un YY br FAIL YY: ldsfld float32 bne_un::max - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::minus_zero bne.un ZZ br FAIL @@ -389,7 +399,7 @@ BBB: bne.un FAIL ldsfld float32 bne_un::max - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::pos_inf bne.un CCC br FAIL @@ -400,78 +410,78 @@ CCC: br FAIL DDD: - ldsfld float32 bne_un::inf - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::pos_inf + ldsfld float32 bne_un::neg_inf bne.un EEE br FAIL EEE: - ldsfld float32 bne_un::inf - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::pos_inf + ldsfld float32 bne_un::min bne.un FFF br FAIL FFF: - ldsfld float32 bne_un::inf - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::pos_inf + ldsfld float32 bne_un::minus_one bne.un GGG br FAIL GGG: - ldsfld float32 bne_un::inf - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::pos_inf + ldsfld float32 bne_un::minus_zero bne.un HHH br FAIL HHH: - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::pos_inf ldsfld float32 bne_un::zero bne.un III br FAIL III: - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::pos_inf ldsfld float32 bne_un::one bne.un JJJ br FAIL JJJ: - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::pos_inf ldsfld float32 bne_un::max bne.un KK_ br FAIL KK_: - ldsfld float32 bne_un::inf - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::pos_inf + ldsfld float32 bne_un::pos_inf bne.un FAIL - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::pos_inf ldsfld float32 bne_un::NaN bne.un LLL br FAIL LLL: ldsfld float32 bne_un::NaN - ldsfld float32 bne_un::_inf + ldsfld float32 bne_un::neg_inf bne.un MMM br FAIL MMM: ldsfld float32 bne_un::NaN - ldsfld float32 bne_un::_min + ldsfld float32 bne_un::min bne.un NNN br FAIL NNN: ldsfld float32 bne_un::NaN - ldsfld float32 bne_un::_one + ldsfld float32 bne_un::minus_one bne.un OOO br FAIL OOO: ldsfld float32 bne_un::NaN - ldsfld float32 bne_un::_zero + ldsfld float32 bne_un::minus_zero bne.un PPP br FAIL @@ -495,13 +505,481 @@ RRR: SSS: ldsfld float32 bne_un::NaN - ldsfld float32 bne_un::inf + ldsfld float32 bne_un::pos_inf bne.un TTT br FAIL TTT: ldsfld float32 bne_un::NaN ldsfld float32 bne_un::NaN + bne.un L0 + br FAIL + + // Testing early folding logic + +L0: + ldc.r4 NEG_INF + ldc.r4 NEG_INF + bne.un FAIL + + ldc.r4 NEG_INF + ldc.r4 MIN + bne.un L1 + br FAIL + +L1: + ldc.r4 NEG_INF + ldc.r4 MINUS_ONE + bne.un L2 + br FAIL + +L2: + ldc.r4 NEG_INF + ldc.r4 MINUS_ZERO + bne.un L3 + br FAIL + +L3: + ldc.r4 NEG_INF + ldc.r4 ZERO + bne.un L4 + br FAIL + +L4: + ldc.r4 NEG_INF + ldc.r4 ONE + bne.un L5 + br FAIL + +L5: + ldc.r4 NEG_INF + ldc.r4 MAX + bne.un L6 + br FAIL + +L6: + ldc.r4 NEG_INF + ldc.r4 POS_INF + bne.un L7 + br FAIL + +L7: + ldc.r4 NEG_INF + ldc.r4 NAN + bne.un L8 + br FAIL + +L8: + ldc.r4 MIN + ldc.r4 NEG_INF + bne.un L9 + br FAIL + +L9: + ldc.r4 MIN + ldc.r4 MIN + bne.un FAIL + + ldc.r4 MIN + ldc.r4 MINUS_ONE + bne.un L10 + br FAIL + +L10: + ldc.r4 MIN + ldc.r4 MINUS_ZERO + bne.un L11 + br FAIL + +L11: + ldc.r4 MIN + ldc.r4 ZERO + bne.un L12 + br FAIL + +L12: + ldc.r4 MIN + ldc.r4 ONE + bne.un L13 + br FAIL + +L13: + ldc.r4 MIN + ldc.r4 MAX + bne.un L14 + br FAIL + +L14: + ldc.r4 MIN + ldc.r4 POS_INF + bne.un L15 + br FAIL + +L15: + ldc.r4 MIN + ldc.r4 NAN + bne.un L16 + br FAIL + +L16: + ldc.r4 MINUS_ONE + ldc.r4 NEG_INF + bne.un L17 + br FAIL + +L17: + ldc.r4 MINUS_ONE + ldc.r4 MIN + bne.un L18 + br FAIL + +L18: + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ONE + bne.un FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ZERO + bne.un L19 + br FAIL + +L19: + ldc.r4 MINUS_ONE + ldc.r4 ZERO + bne.un L20 + br FAIL + +L20: + ldc.r4 MINUS_ONE + ldc.r4 ONE + bne.un L21 + br FAIL + +L21: + ldc.r4 MINUS_ONE + ldc.r4 MAX + bne.un L22 + br FAIL + +L22: + ldc.r4 MINUS_ONE + ldc.r4 POS_INF + bne.un L23 + br FAIL + +L23: + ldc.r4 MINUS_ONE + ldc.r4 NAN + bne.un L24 + br FAIL + +L24: + ldc.r4 MINUS_ZERO + ldc.r4 NEG_INF + bne.un L25 + br FAIL + +L25: + ldc.r4 MINUS_ZERO + ldc.r4 MIN + bne.un L26 + br FAIL + +L26: + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ONE + bne.un L27 + br FAIL + +L27: + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ZERO + bne.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 ZERO + bne.un FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 ONE + bne.un L28 + br FAIL + +L28: + ldc.r4 MINUS_ZERO + ldc.r4 MAX + bne.un L29 + br FAIL + +L29: + ldc.r4 MINUS_ZERO + ldc.r4 POS_INF + bne.un L30 + br FAIL + +L30: + ldc.r4 MINUS_ZERO + ldc.r4 NAN + bne.un L31 + br FAIL + +L31: + ldc.r4 ZERO + ldc.r4 NEG_INF + bne.un L32 + br FAIL + +L32: + ldc.r4 ZERO + ldc.r4 MIN + bne.un L33 + br FAIL + +L33: + ldc.r4 ZERO + ldc.r4 MINUS_ONE + bne.un L34 + br FAIL + +L34: + ldc.r4 ZERO + ldc.r4 MINUS_ZERO + bne.un FAIL + + ldc.r4 ZERO + ldc.r4 ZERO + bne.un FAIL + + ldc.r4 ZERO + ldc.r4 ONE + bne.un L35 + br FAIL + +L35: + ldc.r4 ZERO + ldc.r4 MAX + bne.un L36 + br FAIL + +L36: + ldc.r4 ZERO + ldc.r4 POS_INF + bne.un L37 + br FAIL + +L37: + ldc.r4 ZERO + ldc.r4 NAN + bne.un L38 + br FAIL + +L38: + ldc.r4 ONE + ldc.r4 NEG_INF + bne.un L39 + br FAIL + +L39: + ldc.r4 ONE + ldc.r4 MIN + bne.un L40 + br FAIL + +L40: + ldc.r4 ONE + ldc.r4 MINUS_ONE + bne.un L41 + br FAIL + +L41: + ldc.r4 ONE + ldc.r4 MINUS_ZERO + bne.un L42 + br FAIL + +L42: + ldc.r4 ONE + ldc.r4 ZERO + bne.un L43 + br FAIL + +L43: + ldc.r4 ONE + ldc.r4 ONE + bne.un FAIL + + ldc.r4 ONE + ldc.r4 MAX + bne.un L44 + br FAIL + +L44: + ldc.r4 ONE + ldc.r4 POS_INF + bne.un L45 + br FAIL + +L45: + ldc.r4 ONE + ldc.r4 NAN + bne.un L46 + br FAIL + +L46: + ldc.r4 MAX + ldc.r4 NEG_INF + bne.un L47 + br FAIL + +L47: + ldc.r4 MAX + ldc.r4 MIN + bne.un L48 + br FAIL + +L48: + ldc.r4 MAX + ldc.r4 MINUS_ONE + bne.un L49 + br FAIL + +L49: + ldc.r4 MAX + ldc.r4 MINUS_ZERO + bne.un L50 + br FAIL + +L50: + ldc.r4 MAX + ldc.r4 ZERO + bne.un L51 + br FAIL + +L51: + ldc.r4 MAX + ldc.r4 ONE + bne.un L52 + br FAIL + +L52: + ldc.r4 MAX + ldc.r4 MAX + bne.un FAIL + + ldc.r4 MAX + ldc.r4 POS_INF + bne.un L53 + br FAIL + +L53: + ldc.r4 MAX + ldc.r4 NAN + bne.un L54 + br FAIL + +L54: + ldc.r4 POS_INF + ldc.r4 NEG_INF + bne.un L55 + br FAIL + +L55: + ldc.r4 POS_INF + ldc.r4 MIN + bne.un L56 + br FAIL + +L56: + ldc.r4 POS_INF + ldc.r4 MINUS_ONE + bne.un L57 + br FAIL + +L57: + ldc.r4 POS_INF + ldc.r4 MINUS_ZERO + bne.un L58 + br FAIL + +L58: + ldc.r4 POS_INF + ldc.r4 ZERO + bne.un L59 + br FAIL + +L59: + ldc.r4 POS_INF + ldc.r4 ONE + bne.un L60 + br FAIL + +L60: + ldc.r4 POS_INF + ldc.r4 MAX + bne.un L61 + br FAIL + +L61: + ldc.r4 POS_INF + ldc.r4 POS_INF + bne.un FAIL + + ldc.r4 POS_INF + ldc.r4 NAN + bne.un L62 + br FAIL + +L62: + ldc.r4 NAN + ldc.r4 NEG_INF + bne.un L63 + br FAIL + +L63: + ldc.r4 NAN + ldc.r4 MIN + bne.un L64 + br FAIL + +L64: + ldc.r4 NAN + ldc.r4 MINUS_ONE + bne.un L65 + br FAIL + +L65: + ldc.r4 NAN + ldc.r4 MINUS_ZERO + bne.un L66 + br FAIL + +L66: + ldc.r4 NAN + ldc.r4 ZERO + bne.un L67 + br FAIL + +L67: + ldc.r4 NAN + ldc.r4 ONE + bne.un L68 + br FAIL + +L68: + ldc.r4 NAN + ldc.r4 MAX + bne.un L69 + br FAIL + +L69: + ldc.r4 NAN + ldc.r4 POS_INF + bne.un L70 + br FAIL + +L70: + ldc.r4 NAN + ldc.r4 NAN bne.un BACKCHECK br FAIL diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bne_un_r8.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bne_un_r8.il index 4c160e9b5831b..1f0c535d102b6 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bne_un_r8.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/bne_un_r8.il @@ -3,36 +3,46 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float64(0xFFF0000000000000)" +#define MIN "float64(0xFF7FFFFFFFFFFFFF)" +#define MINUS_ONE "float64(0xBFF0000000000000)" +#define MINUS_ZERO "float64(0x8000000000000000)" +#define ZERO "float64(0x0000000000000000)" +#define ONE "float64(0x3FF0000000000000)" +#define MAX "float64(0x7FEFFFFFFFFFFFFF)" +#define POS_INF "float64(0x7FF0000000000000)" +#define NAN "float64(0x7FF8000000000000)" + .class public bne_un { -.field public static float64 _inf -.field public static float64 _min -.field public static float64 _one -.field public static float64 _zero +.field public static float64 neg_inf +.field public static float64 min +.field public static float64 minus_one +.field public static float64 minus_zero .field public static float64 zero .field public static float64 one .field public static float64 max -.field public static float64 inf +.field public static float64 pos_inf .field public static float64 NaN .method public static void initialize() { .maxstack 10 - ldc.r8 float64(0xFFF0000000000000) - stsfld float64 bne_un::_inf - ldc.r8 float64(0xFF7FFFFFFFFFFFFF) - stsfld float64 bne_un::_min - ldc.r8 float64(0xBFF0000000000000) - stsfld float64 bne_un::_one - ldc.r8 float64(0x8000000000000000) - stsfld float64 bne_un::_zero - ldc.r8 float64(0x0000000000000000) + ldc.r8 NEG_INF + stsfld float64 bne_un::neg_inf + ldc.r8 MIN + stsfld float64 bne_un::min + ldc.r8 MINUS_ONE + stsfld float64 bne_un::minus_one + ldc.r8 MINUS_ZERO + stsfld float64 bne_un::minus_zero + ldc.r8 ZERO stsfld float64 bne_un::zero - ldc.r8 float64(0x3FF0000000000000) + ldc.r8 ONE stsfld float64 bne_un::one - ldc.r8 float64(0x7FEFFFFFFFFFFFFF) + ldc.r8 MAX stsfld float64 bne_un::max - ldc.r8 float64(0x7FF0000000000000) - stsfld float64 bne_un::inf - ldc.r8 float64(0x7FF8000000000000) + ldc.r8 POS_INF + stsfld float64 bne_un::pos_inf + ldc.r8 NAN stsfld float64 bne_un::NaN ret } @@ -41,230 +51,230 @@ .entrypoint .maxstack 10 call void bne_un::initialize() - ldsfld float64 bne_un::_inf - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::neg_inf + ldsfld float64 bne_un::neg_inf bne.un FAIL - ldsfld float64 bne_un::_inf - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::neg_inf + ldsfld float64 bne_un::min bne.un A br FAIL A: - ldsfld float64 bne_un::_inf - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::neg_inf + ldsfld float64 bne_un::minus_one bne.un B br FAIL B: - ldsfld float64 bne_un::_inf - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::neg_inf + ldsfld float64 bne_un::minus_zero bne.un C br FAIL C: - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::neg_inf ldsfld float64 bne_un::zero bne.un D br FAIL D: - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::neg_inf ldsfld float64 bne_un::one bne.un E br FAIL E: - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::neg_inf ldsfld float64 bne_un::max bne.un F br FAIL F: - ldsfld float64 bne_un::_inf - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::neg_inf + ldsfld float64 bne_un::pos_inf bne.un G br FAIL G: - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::neg_inf ldsfld float64 bne_un::NaN bne.un H br FAIL H: - ldsfld float64 bne_un::_min - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::min + ldsfld float64 bne_un::neg_inf bne.un I br FAIL I: - ldsfld float64 bne_un::_min - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::min + ldsfld float64 bne_un::min bne.un FAIL - ldsfld float64 bne_un::_min - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::min + ldsfld float64 bne_un::minus_one bne.un J br FAIL J: - ldsfld float64 bne_un::_min - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::min + ldsfld float64 bne_un::minus_zero bne.un K br FAIL K: - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::min ldsfld float64 bne_un::zero bne.un L br FAIL L: - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::min ldsfld float64 bne_un::one bne.un M br FAIL M: - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::min ldsfld float64 bne_un::max bne.un N br FAIL N: - ldsfld float64 bne_un::_min - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::min + ldsfld float64 bne_un::pos_inf bne.un O br FAIL O: - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::min ldsfld float64 bne_un::NaN bne.un P br FAIL P: - ldsfld float64 bne_un::_one - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::minus_one + ldsfld float64 bne_un::neg_inf bne.un Q br FAIL Q: - ldsfld float64 bne_un::_one - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::minus_one + ldsfld float64 bne_un::min bne.un R br FAIL R: - ldsfld float64 bne_un::_one - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::minus_one + ldsfld float64 bne_un::minus_one bne.un FAIL S: - ldsfld float64 bne_un::_one - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::minus_one + ldsfld float64 bne_un::minus_zero bne.un T br FAIL T: - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::minus_one ldsfld float64 bne_un::zero bne.un U br FAIL U: - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::minus_one ldsfld float64 bne_un::one bne.un V br FAIL V: - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::minus_one ldsfld float64 bne_un::max bne.un W br FAIL W: - ldsfld float64 bne_un::_one - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::minus_one + ldsfld float64 bne_un::pos_inf bne.un X br FAIL X: - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::minus_one ldsfld float64 bne_un::NaN bne.un Y br FAIL Y: - ldsfld float64 bne_un::_zero - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::minus_zero + ldsfld float64 bne_un::neg_inf bne.un Z br FAIL Z: - ldsfld float64 bne_un::_zero - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::minus_zero + ldsfld float64 bne_un::min bne.un AA br FAIL AA: - ldsfld float64 bne_un::_zero - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::minus_zero + ldsfld float64 bne_un::minus_one bne.un BB br FAIL BB: - ldsfld float64 bne_un::_zero - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::minus_zero + ldsfld float64 bne_un::minus_zero bne.un FAIL - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::minus_zero ldsfld float64 bne_un::zero bne.un FAIL - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::minus_zero ldsfld float64 bne_un::one bne.un CC br FAIL CC: - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::minus_zero ldsfld float64 bne_un::max bne.un DD br FAIL DD: - ldsfld float64 bne_un::_zero - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::minus_zero + ldsfld float64 bne_un::pos_inf bne.un EE br FAIL EE: - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::minus_zero ldsfld float64 bne_un::NaN bne.un FF br FAIL FF: ldsfld float64 bne_un::zero - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::neg_inf bne.un GG br FAIL GG: ldsfld float64 bne_un::zero - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::min bne.un HH br FAIL HH: ldsfld float64 bne_un::zero - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::minus_one bne.un II br FAIL II: ldsfld float64 bne_un::zero - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::minus_zero bne.un FAIL ldsfld float64 bne_un::zero @@ -284,7 +294,7 @@ JJ: KK: ldsfld float64 bne_un::zero - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::pos_inf bne.un LL br FAIL @@ -296,25 +306,25 @@ LL: MM: ldsfld float64 bne_un::one - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::neg_inf bne.un NN br FAIL NN: ldsfld float64 bne_un::one - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::min bne.un OO br FAIL OO: ldsfld float64 bne_un::one - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::minus_one bne.un PP br FAIL PP: ldsfld float64 bne_un::one - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::minus_zero bne.un QQ br FAIL @@ -337,7 +347,7 @@ SS: TT: ldsfld float64 bne_un::one - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::pos_inf bne.un UU br FAIL @@ -349,25 +359,25 @@ UU: VV: ldsfld float64 bne_un::max - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::neg_inf bne.un WW br FAIL WW: ldsfld float64 bne_un::max - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::min bne.un XX br FAIL XX: ldsfld float64 bne_un::max - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::minus_one bne.un YY br FAIL YY: ldsfld float64 bne_un::max - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::minus_zero bne.un ZZ br FAIL @@ -389,7 +399,7 @@ BBB: bne.un FAIL ldsfld float64 bne_un::max - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::pos_inf bne.un CCC br FAIL @@ -400,78 +410,78 @@ CCC: br FAIL DDD: - ldsfld float64 bne_un::inf - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::pos_inf + ldsfld float64 bne_un::neg_inf bne.un EEE br FAIL EEE: - ldsfld float64 bne_un::inf - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::pos_inf + ldsfld float64 bne_un::min bne.un FFF br FAIL FFF: - ldsfld float64 bne_un::inf - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::pos_inf + ldsfld float64 bne_un::minus_one bne.un GGG br FAIL GGG: - ldsfld float64 bne_un::inf - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::pos_inf + ldsfld float64 bne_un::minus_zero bne.un HHH br FAIL HHH: - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::pos_inf ldsfld float64 bne_un::zero bne.un III br FAIL III: - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::pos_inf ldsfld float64 bne_un::one bne.un JJJ br FAIL JJJ: - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::pos_inf ldsfld float64 bne_un::max bne.un KK_ br FAIL KK_: - ldsfld float64 bne_un::inf - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::pos_inf + ldsfld float64 bne_un::pos_inf bne.un FAIL - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::pos_inf ldsfld float64 bne_un::NaN bne.un LLL br FAIL LLL: ldsfld float64 bne_un::NaN - ldsfld float64 bne_un::_inf + ldsfld float64 bne_un::neg_inf bne.un MMM br FAIL MMM: ldsfld float64 bne_un::NaN - ldsfld float64 bne_un::_min + ldsfld float64 bne_un::min bne.un NNN br FAIL NNN: ldsfld float64 bne_un::NaN - ldsfld float64 bne_un::_one + ldsfld float64 bne_un::minus_one bne.un OOO br FAIL OOO: ldsfld float64 bne_un::NaN - ldsfld float64 bne_un::_zero + ldsfld float64 bne_un::minus_zero bne.un PPP br FAIL @@ -495,13 +505,481 @@ RRR: SSS: ldsfld float64 bne_un::NaN - ldsfld float64 bne_un::inf + ldsfld float64 bne_un::pos_inf bne.un TTT br FAIL TTT: ldsfld float64 bne_un::NaN ldsfld float64 bne_un::NaN + bne.un L0 + br FAIL + + // Testing early folding logic + +L0: + ldc.r8 NEG_INF + ldc.r8 NEG_INF + bne.un FAIL + + ldc.r8 NEG_INF + ldc.r8 MIN + bne.un L1 + br FAIL + +L1: + ldc.r8 NEG_INF + ldc.r8 MINUS_ONE + bne.un L2 + br FAIL + +L2: + ldc.r8 NEG_INF + ldc.r8 MINUS_ZERO + bne.un L3 + br FAIL + +L3: + ldc.r8 NEG_INF + ldc.r8 ZERO + bne.un L4 + br FAIL + +L4: + ldc.r8 NEG_INF + ldc.r8 ONE + bne.un L5 + br FAIL + +L5: + ldc.r8 NEG_INF + ldc.r8 MAX + bne.un L6 + br FAIL + +L6: + ldc.r8 NEG_INF + ldc.r8 POS_INF + bne.un L7 + br FAIL + +L7: + ldc.r8 NEG_INF + ldc.r8 NAN + bne.un L8 + br FAIL + +L8: + ldc.r8 MIN + ldc.r8 NEG_INF + bne.un L9 + br FAIL + +L9: + ldc.r8 MIN + ldc.r8 MIN + bne.un FAIL + + ldc.r8 MIN + ldc.r8 MINUS_ONE + bne.un L10 + br FAIL + +L10: + ldc.r8 MIN + ldc.r8 MINUS_ZERO + bne.un L11 + br FAIL + +L11: + ldc.r8 MIN + ldc.r8 ZERO + bne.un L12 + br FAIL + +L12: + ldc.r8 MIN + ldc.r8 ONE + bne.un L13 + br FAIL + +L13: + ldc.r8 MIN + ldc.r8 MAX + bne.un L14 + br FAIL + +L14: + ldc.r8 MIN + ldc.r8 POS_INF + bne.un L15 + br FAIL + +L15: + ldc.r8 MIN + ldc.r8 NAN + bne.un L16 + br FAIL + +L16: + ldc.r8 MINUS_ONE + ldc.r8 NEG_INF + bne.un L17 + br FAIL + +L17: + ldc.r8 MINUS_ONE + ldc.r8 MIN + bne.un L18 + br FAIL + +L18: + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ONE + bne.un FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ZERO + bne.un L19 + br FAIL + +L19: + ldc.r8 MINUS_ONE + ldc.r8 ZERO + bne.un L20 + br FAIL + +L20: + ldc.r8 MINUS_ONE + ldc.r8 ONE + bne.un L21 + br FAIL + +L21: + ldc.r8 MINUS_ONE + ldc.r8 MAX + bne.un L22 + br FAIL + +L22: + ldc.r8 MINUS_ONE + ldc.r8 POS_INF + bne.un L23 + br FAIL + +L23: + ldc.r8 MINUS_ONE + ldc.r8 NAN + bne.un L24 + br FAIL + +L24: + ldc.r8 MINUS_ZERO + ldc.r8 NEG_INF + bne.un L25 + br FAIL + +L25: + ldc.r8 MINUS_ZERO + ldc.r8 MIN + bne.un L26 + br FAIL + +L26: + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ONE + bne.un L27 + br FAIL + +L27: + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ZERO + bne.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 ZERO + bne.un FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 ONE + bne.un L28 + br FAIL + +L28: + ldc.r8 MINUS_ZERO + ldc.r8 MAX + bne.un L29 + br FAIL + +L29: + ldc.r8 MINUS_ZERO + ldc.r8 POS_INF + bne.un L30 + br FAIL + +L30: + ldc.r8 MINUS_ZERO + ldc.r8 NAN + bne.un L31 + br FAIL + +L31: + ldc.r8 ZERO + ldc.r8 NEG_INF + bne.un L32 + br FAIL + +L32: + ldc.r8 ZERO + ldc.r8 MIN + bne.un L33 + br FAIL + +L33: + ldc.r8 ZERO + ldc.r8 MINUS_ONE + bne.un L34 + br FAIL + +L34: + ldc.r8 ZERO + ldc.r8 MINUS_ZERO + bne.un FAIL + + ldc.r8 ZERO + ldc.r8 ZERO + bne.un FAIL + + ldc.r8 ZERO + ldc.r8 ONE + bne.un L35 + br FAIL + +L35: + ldc.r8 ZERO + ldc.r8 MAX + bne.un L36 + br FAIL + +L36: + ldc.r8 ZERO + ldc.r8 POS_INF + bne.un L37 + br FAIL + +L37: + ldc.r8 ZERO + ldc.r8 NAN + bne.un L38 + br FAIL + +L38: + ldc.r8 ONE + ldc.r8 NEG_INF + bne.un L39 + br FAIL + +L39: + ldc.r8 ONE + ldc.r8 MIN + bne.un L40 + br FAIL + +L40: + ldc.r8 ONE + ldc.r8 MINUS_ONE + bne.un L41 + br FAIL + +L41: + ldc.r8 ONE + ldc.r8 MINUS_ZERO + bne.un L42 + br FAIL + +L42: + ldc.r8 ONE + ldc.r8 ZERO + bne.un L43 + br FAIL + +L43: + ldc.r8 ONE + ldc.r8 ONE + bne.un FAIL + + ldc.r8 ONE + ldc.r8 MAX + bne.un L44 + br FAIL + +L44: + ldc.r8 ONE + ldc.r8 POS_INF + bne.un L45 + br FAIL + +L45: + ldc.r8 ONE + ldc.r8 NAN + bne.un L46 + br FAIL + +L46: + ldc.r8 MAX + ldc.r8 NEG_INF + bne.un L47 + br FAIL + +L47: + ldc.r8 MAX + ldc.r8 MIN + bne.un L48 + br FAIL + +L48: + ldc.r8 MAX + ldc.r8 MINUS_ONE + bne.un L49 + br FAIL + +L49: + ldc.r8 MAX + ldc.r8 MINUS_ZERO + bne.un L50 + br FAIL + +L50: + ldc.r8 MAX + ldc.r8 ZERO + bne.un L51 + br FAIL + +L51: + ldc.r8 MAX + ldc.r8 ONE + bne.un L52 + br FAIL + +L52: + ldc.r8 MAX + ldc.r8 MAX + bne.un FAIL + + ldc.r8 MAX + ldc.r8 POS_INF + bne.un L53 + br FAIL + +L53: + ldc.r8 MAX + ldc.r8 NAN + bne.un L54 + br FAIL + +L54: + ldc.r8 POS_INF + ldc.r8 NEG_INF + bne.un L55 + br FAIL + +L55: + ldc.r8 POS_INF + ldc.r8 MIN + bne.un L56 + br FAIL + +L56: + ldc.r8 POS_INF + ldc.r8 MINUS_ONE + bne.un L57 + br FAIL + +L57: + ldc.r8 POS_INF + ldc.r8 MINUS_ZERO + bne.un L58 + br FAIL + +L58: + ldc.r8 POS_INF + ldc.r8 ZERO + bne.un L59 + br FAIL + +L59: + ldc.r8 POS_INF + ldc.r8 ONE + bne.un L60 + br FAIL + +L60: + ldc.r8 POS_INF + ldc.r8 MAX + bne.un L61 + br FAIL + +L61: + ldc.r8 POS_INF + ldc.r8 POS_INF + bne.un FAIL + + ldc.r8 POS_INF + ldc.r8 NAN + bne.un L62 + br FAIL + +L62: + ldc.r8 NAN + ldc.r8 NEG_INF + bne.un L63 + br FAIL + +L63: + ldc.r8 NAN + ldc.r8 MIN + bne.un L64 + br FAIL + +L64: + ldc.r8 NAN + ldc.r8 MINUS_ONE + bne.un L65 + br FAIL + +L65: + ldc.r8 NAN + ldc.r8 MINUS_ZERO + bne.un L66 + br FAIL + +L66: + ldc.r8 NAN + ldc.r8 ZERO + bne.un L67 + br FAIL + +L67: + ldc.r8 NAN + ldc.r8 ONE + bne.un L68 + br FAIL + +L68: + ldc.r8 NAN + ldc.r8 MAX + bne.un L69 + br FAIL + +L69: + ldc.r8 NAN + ldc.r8 POS_INF + bne.un L70 + br FAIL + +L70: + ldc.r8 NAN + ldc.r8 NAN bne.un BACKCHECK br FAIL diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/cgt_un_r4.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/cgt_un_r4.il index bb8f47dab8a87..1551d49e11749 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/cgt_un_r4.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/cgt_un_r4.il @@ -3,37 +3,47 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float32(0xFF800000)" +#define MIN "float32(0xFF7FFFFF)" +#define MINUS_ONE "float32(0xBF800000)" +#define MINUS_ZERO "float32(0x80000000)" +#define ZERO "float32(0x00000000)" +#define ONE "float32(0x3F800000)" +#define MAX "float32(0x7F7FFFFF)" +#define POS_INF "float32(0x7F800000)" +#define NAN "float32(0x7FC00000)" + .class public cgt_un { -.field public static float32 _inf -.field public static float32 _min -.field public static float32 _one -.field public static float32 _zero +.field public static float32 neg_inf +.field public static float32 min +.field public static float32 minus_one +.field public static float32 minus_zero .field public static float32 zero .field public static float32 one .field public static float32 max -.field public static float32 inf +.field public static float32 pos_inf .field public static float32 NaN .method public static void initialize() { .maxstack 10 - ldc.r4 float32(0xFF800000) - stsfld float32 cgt_un::_inf - ldc.r4 float32(0xFF7FFFFF) - stsfld float32 cgt_un::_min - ldc.r4 float32(0xBF800000) - stsfld float32 cgt_un::_one - ldc.r4 float32(0x80000000) - stsfld float32 cgt_un::_zero - ldc.r4 float32(0x00000000) + ldc.r4 NEG_INF + stsfld float32 cgt_un::neg_inf + ldc.r4 MIN + stsfld float32 cgt_un::min + ldc.r4 MINUS_ONE + stsfld float32 cgt_un::minus_one + ldc.r4 MINUS_ZERO + stsfld float32 cgt_un::minus_zero + ldc.r4 ZERO stsfld float32 cgt_un::zero - ldc.r4 float32(0x3F800000) + ldc.r4 ONE stsfld float32 cgt_un::one - ldc.r4 float32(0x7F7FFFFF) + ldc.r4 MAX stsfld float32 cgt_un::max - ldc.r4 float32(0x7F800000) - stsfld float32 cgt_un::inf - ldc.r4 float32(0x7FC00000) + ldc.r4 POS_INF + stsfld float32 cgt_un::pos_inf + ldc.r4 NAN stsfld float32 cgt_un::NaN ret } @@ -42,202 +52,202 @@ .entrypoint .maxstack 10 call void cgt_un::initialize() - ldsfld float32 cgt_un::_inf - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::neg_inf + ldsfld float32 cgt_un::neg_inf cgt.un brtrue FAIL - ldsfld float32 cgt_un::_inf - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::neg_inf + ldsfld float32 cgt_un::min cgt.un brtrue FAIL - ldsfld float32 cgt_un::_inf - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::neg_inf + ldsfld float32 cgt_un::minus_one cgt.un brtrue FAIL - ldsfld float32 cgt_un::_inf - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::neg_inf + ldsfld float32 cgt_un::minus_zero cgt.un brtrue FAIL - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::neg_inf ldsfld float32 cgt_un::zero cgt.un brtrue FAIL - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::neg_inf ldsfld float32 cgt_un::one cgt.un brtrue FAIL - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::neg_inf ldsfld float32 cgt_un::max cgt.un brtrue FAIL - ldsfld float32 cgt_un::_inf - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::neg_inf + ldsfld float32 cgt_un::pos_inf cgt.un brtrue FAIL - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::neg_inf ldsfld float32 cgt_un::NaN cgt.un brfalse FAIL - ldsfld float32 cgt_un::_min - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::min + ldsfld float32 cgt_un::neg_inf cgt.un brfalse FAIL - ldsfld float32 cgt_un::_min - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::min + ldsfld float32 cgt_un::min cgt.un brtrue FAIL - ldsfld float32 cgt_un::_min - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::min + ldsfld float32 cgt_un::minus_one cgt.un brtrue FAIL - ldsfld float32 cgt_un::_min - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::min + ldsfld float32 cgt_un::minus_zero cgt.un brtrue FAIL - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::min ldsfld float32 cgt_un::zero cgt.un brtrue FAIL - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::min ldsfld float32 cgt_un::one cgt.un brtrue FAIL - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::min ldsfld float32 cgt_un::max cgt.un brtrue FAIL - ldsfld float32 cgt_un::_min - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::min + ldsfld float32 cgt_un::pos_inf cgt.un brtrue FAIL - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::min ldsfld float32 cgt_un::NaN cgt.un brfalse FAIL - ldsfld float32 cgt_un::_one - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::minus_one + ldsfld float32 cgt_un::neg_inf cgt.un brfalse FAIL - ldsfld float32 cgt_un::_one - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::minus_one + ldsfld float32 cgt_un::min cgt.un brfalse FAIL - ldsfld float32 cgt_un::_one - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::minus_one + ldsfld float32 cgt_un::minus_one cgt.un brtrue FAIL - ldsfld float32 cgt_un::_one - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::minus_one + ldsfld float32 cgt_un::minus_zero cgt.un brtrue FAIL - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::minus_one ldsfld float32 cgt_un::zero cgt.un brtrue FAIL - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::minus_one ldsfld float32 cgt_un::one cgt.un brtrue FAIL - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::minus_one ldsfld float32 cgt_un::max cgt.un brtrue FAIL - ldsfld float32 cgt_un::_one - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::minus_one + ldsfld float32 cgt_un::pos_inf cgt.un brtrue FAIL - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::minus_one ldsfld float32 cgt_un::NaN cgt.un brfalse FAIL - ldsfld float32 cgt_un::_zero - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::minus_zero + ldsfld float32 cgt_un::neg_inf cgt.un brfalse FAIL - ldsfld float32 cgt_un::_zero - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::minus_zero + ldsfld float32 cgt_un::min cgt.un brfalse FAIL - ldsfld float32 cgt_un::_zero - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::minus_zero + ldsfld float32 cgt_un::minus_one cgt.un brfalse FAIL - ldsfld float32 cgt_un::_zero - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::minus_zero + ldsfld float32 cgt_un::minus_zero cgt.un brtrue FAIL - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::minus_zero ldsfld float32 cgt_un::zero cgt.un brtrue FAIL - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::minus_zero ldsfld float32 cgt_un::one cgt.un brtrue FAIL - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::minus_zero ldsfld float32 cgt_un::max cgt.un brtrue FAIL - ldsfld float32 cgt_un::_zero - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::minus_zero + ldsfld float32 cgt_un::pos_inf cgt.un brtrue FAIL - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::minus_zero ldsfld float32 cgt_un::NaN cgt.un brfalse FAIL ldsfld float32 cgt_un::zero - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::neg_inf cgt.un brfalse FAIL ldsfld float32 cgt_un::zero - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::min cgt.un brfalse FAIL ldsfld float32 cgt_un::zero - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::minus_one cgt.un brfalse FAIL ldsfld float32 cgt_un::zero - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::minus_zero cgt.un brtrue FAIL @@ -257,7 +267,7 @@ brtrue FAIL ldsfld float32 cgt_un::zero - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::pos_inf cgt.un brtrue FAIL @@ -267,22 +277,22 @@ brfalse FAIL ldsfld float32 cgt_un::one - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::neg_inf cgt.un brfalse FAIL ldsfld float32 cgt_un::one - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::min cgt.un brfalse FAIL ldsfld float32 cgt_un::one - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::minus_one cgt.un brfalse FAIL ldsfld float32 cgt_un::one - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::minus_zero cgt.un brfalse FAIL @@ -302,7 +312,7 @@ brtrue FAIL ldsfld float32 cgt_un::one - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::pos_inf cgt.un brtrue FAIL @@ -312,22 +322,22 @@ brfalse FAIL ldsfld float32 cgt_un::max - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::neg_inf cgt.un brfalse FAIL ldsfld float32 cgt_un::max - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::min cgt.un brfalse FAIL ldsfld float32 cgt_un::max - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::minus_one cgt.un brfalse FAIL ldsfld float32 cgt_un::max - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::minus_zero cgt.un brfalse FAIL @@ -347,7 +357,7 @@ brtrue FAIL ldsfld float32 cgt_un::max - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::pos_inf cgt.un brtrue FAIL @@ -356,68 +366,68 @@ cgt.un brfalse FAIL - ldsfld float32 cgt_un::inf - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::pos_inf + ldsfld float32 cgt_un::neg_inf cgt.un brfalse FAIL - ldsfld float32 cgt_un::inf - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::pos_inf + ldsfld float32 cgt_un::min cgt.un brfalse FAIL - ldsfld float32 cgt_un::inf - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::pos_inf + ldsfld float32 cgt_un::minus_one cgt.un brfalse FAIL - ldsfld float32 cgt_un::inf - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::pos_inf + ldsfld float32 cgt_un::minus_zero cgt.un brfalse FAIL - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::pos_inf ldsfld float32 cgt_un::zero cgt.un brfalse FAIL - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::pos_inf ldsfld float32 cgt_un::one cgt.un brfalse FAIL - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::pos_inf ldsfld float32 cgt_un::max cgt.un brfalse FAIL - ldsfld float32 cgt_un::inf - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::pos_inf + ldsfld float32 cgt_un::pos_inf cgt.un brtrue FAIL - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::pos_inf ldsfld float32 cgt_un::NaN cgt.un brfalse FAIL ldsfld float32 cgt_un::NaN - ldsfld float32 cgt_un::_inf + ldsfld float32 cgt_un::neg_inf cgt.un brfalse FAIL ldsfld float32 cgt_un::NaN - ldsfld float32 cgt_un::_min + ldsfld float32 cgt_un::min cgt.un brfalse FAIL ldsfld float32 cgt_un::NaN - ldsfld float32 cgt_un::_one + ldsfld float32 cgt_un::minus_one cgt.un brfalse FAIL ldsfld float32 cgt_un::NaN - ldsfld float32 cgt_un::_zero + ldsfld float32 cgt_un::minus_zero cgt.un brfalse FAIL @@ -437,7 +447,7 @@ brfalse FAIL ldsfld float32 cgt_un::NaN - ldsfld float32 cgt_un::inf + ldsfld float32 cgt_un::pos_inf cgt.un brfalse FAIL @@ -446,6 +456,412 @@ cgt.un brfalse FAIL + // Testing early folding logic + + ldc.r4 NEG_INF + ldc.r4 NEG_INF + cgt.un + brtrue FAIL + + ldc.r4 NEG_INF + ldc.r4 MIN + cgt.un + brtrue FAIL + + ldc.r4 NEG_INF + ldc.r4 MINUS_ONE + cgt.un + brtrue FAIL + + ldc.r4 NEG_INF + ldc.r4 MINUS_ZERO + cgt.un + brtrue FAIL + + ldc.r4 NEG_INF + ldc.r4 ZERO + cgt.un + brtrue FAIL + + ldc.r4 NEG_INF + ldc.r4 ONE + cgt.un + brtrue FAIL + + ldc.r4 NEG_INF + ldc.r4 MAX + cgt.un + brtrue FAIL + + ldc.r4 NEG_INF + ldc.r4 POS_INF + cgt.un + brtrue FAIL + + ldc.r4 NEG_INF + ldc.r4 NAN + cgt.un + brfalse FAIL + ldc.r4 MIN + ldc.r4 NEG_INF + cgt.un + brfalse FAIL + + ldc.r4 MIN + ldc.r4 MIN + cgt.un + brtrue FAIL + + ldc.r4 MIN + ldc.r4 MINUS_ONE + cgt.un + brtrue FAIL + + ldc.r4 MIN + ldc.r4 MINUS_ZERO + cgt.un + brtrue FAIL + + ldc.r4 MIN + ldc.r4 ZERO + cgt.un + brtrue FAIL + + ldc.r4 MIN + ldc.r4 ONE + cgt.un + brtrue FAIL + + ldc.r4 MIN + ldc.r4 MAX + cgt.un + brtrue FAIL + + ldc.r4 MIN + ldc.r4 POS_INF + cgt.un + brtrue FAIL + + ldc.r4 MIN + ldc.r4 NAN + cgt.un + brfalse FAIL + + + ldc.r4 MINUS_ONE + ldc.r4 NEG_INF + cgt.un + brfalse FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MIN + cgt.un + brfalse FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ONE + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ZERO + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ONE + ldc.r4 ZERO + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ONE + ldc.r4 ONE + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MAX + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ONE + ldc.r4 POS_INF + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ONE + ldc.r4 NAN + cgt.un + brfalse FAIL + ldc.r4 MINUS_ZERO + ldc.r4 NEG_INF + cgt.un + brfalse FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MIN + cgt.un + brfalse FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ZERO + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 ZERO + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 ONE + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MAX + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 POS_INF + cgt.un + brtrue FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 NAN + cgt.un + brfalse FAIL + + ldc.r4 ZERO + ldc.r4 NEG_INF + cgt.un + brfalse FAIL + + ldc.r4 ZERO + ldc.r4 MIN + cgt.un + brfalse FAIL + + ldc.r4 ZERO + ldc.r4 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r4 ZERO + ldc.r4 MINUS_ZERO + cgt.un + brtrue FAIL + + ldc.r4 ZERO + ldc.r4 ZERO + cgt.un + brtrue FAIL + + ldc.r4 ZERO + ldc.r4 ONE + cgt.un + brtrue FAIL + + ldc.r4 ZERO + ldc.r4 MAX + cgt.un + brtrue FAIL + + ldc.r4 ZERO + ldc.r4 POS_INF + cgt.un + brtrue FAIL + + ldc.r4 ZERO + ldc.r4 NAN + cgt.un + brfalse FAIL + + ldc.r4 ONE + ldc.r4 NEG_INF + cgt.un + brfalse FAIL + + ldc.r4 ONE + ldc.r4 MIN + cgt.un + brfalse FAIL + + ldc.r4 ONE + ldc.r4 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r4 ONE + ldc.r4 MINUS_ZERO + cgt.un + brfalse FAIL + + ldc.r4 ONE + ldc.r4 ZERO + cgt.un + brfalse FAIL + + ldc.r4 ONE + ldc.r4 ONE + cgt.un + brtrue FAIL + + ldc.r4 ONE + ldc.r4 MAX + cgt.un + brtrue FAIL + + ldc.r4 ONE + ldc.r4 POS_INF + cgt.un + brtrue FAIL + + ldc.r4 ONE + ldc.r4 NAN + cgt.un + brfalse FAIL + + ldc.r4 MAX + ldc.r4 NEG_INF + cgt.un + brfalse FAIL + + ldc.r4 MAX + ldc.r4 MIN + cgt.un + brfalse FAIL + + ldc.r4 MAX + ldc.r4 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r4 MAX + ldc.r4 MINUS_ZERO + cgt.un + brfalse FAIL + + ldc.r4 MAX + ldc.r4 ZERO + cgt.un + brfalse FAIL + + ldc.r4 MAX + ldc.r4 ONE + cgt.un + brfalse FAIL + + ldc.r4 MAX + ldc.r4 MAX + cgt.un + brtrue FAIL + + ldc.r4 MAX + ldc.r4 POS_INF + cgt.un + brtrue FAIL + + ldc.r4 MAX + ldc.r4 NAN + cgt.un + brfalse FAIL + + ldc.r4 POS_INF + ldc.r4 NEG_INF + cgt.un + brfalse FAIL + + ldc.r4 POS_INF + ldc.r4 MIN + cgt.un + brfalse FAIL + + ldc.r4 POS_INF + ldc.r4 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r4 POS_INF + ldc.r4 MINUS_ZERO + cgt.un + brfalse FAIL + + ldc.r4 POS_INF + ldc.r4 ZERO + cgt.un + brfalse FAIL + + ldc.r4 POS_INF + ldc.r4 ONE + cgt.un + brfalse FAIL + + ldc.r4 POS_INF + ldc.r4 MAX + cgt.un + brfalse FAIL + + ldc.r4 POS_INF + ldc.r4 POS_INF + cgt.un + brtrue FAIL + + ldc.r4 POS_INF + ldc.r4 NAN + cgt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 NEG_INF + cgt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 MIN + cgt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 MINUS_ZERO + cgt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 ZERO + cgt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 ONE + cgt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 MAX + cgt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 POS_INF + cgt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 NAN + cgt.un + brfalse FAIL + ldc.i4 100 ret FAIL: diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/cgt_un_r8.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/cgt_un_r8.il index 95af03090f6fc..fa5d1b315a574 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/cgt_un_r8.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/cgt_un_r8.il @@ -3,37 +3,47 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float64(0xFFF0000000000000)" +#define MIN "float64(0xFF7FFFFFFFFFFFFF)" +#define MINUS_ONE "float64(0xBFF0000000000000)" +#define MINUS_ZERO "float64(0x8000000000000000)" +#define ZERO "float64(0x0000000000000000)" +#define ONE "float64(0x3FF0000000000000)" +#define MAX "float64(0x7FEFFFFFFFFFFFFF)" +#define POS_INF "float64(0x7FF0000000000000)" +#define NAN "float64(0x7FF8000000000000)" + .class public cgt_un { -.field public static float64 _inf -.field public static float64 _min -.field public static float64 _one -.field public static float64 _zero +.field public static float64 neg_inf +.field public static float64 min +.field public static float64 minus_one +.field public static float64 minus_zero .field public static float64 zero .field public static float64 one .field public static float64 max -.field public static float64 inf +.field public static float64 pos_inf .field public static float64 NaN .method public static void initialize() { .maxstack 10 - ldc.r8 float64(0xFFF0000000000000) - stsfld float64 cgt_un::_inf - ldc.r8 float64(0xFF7FFFFFFFFFFFFF) - stsfld float64 cgt_un::_min - ldc.r8 float64(0xBFF0000000000000) - stsfld float64 cgt_un::_one - ldc.r8 float64(0x8000000000000000) - stsfld float64 cgt_un::_zero - ldc.r8 float64(0x0000000000000000) + ldc.r8 NEG_INF + stsfld float64 cgt_un::neg_inf + ldc.r8 MIN + stsfld float64 cgt_un::min + ldc.r8 MINUS_ONE + stsfld float64 cgt_un::minus_one + ldc.r8 MINUS_ZERO + stsfld float64 cgt_un::minus_zero + ldc.r8 ZERO stsfld float64 cgt_un::zero - ldc.r8 float64(0x3FF0000000000000) + ldc.r8 ONE stsfld float64 cgt_un::one - ldc.r8 float64(0x7FEFFFFFFFFFFFFF) + ldc.r8 MAX stsfld float64 cgt_un::max - ldc.r8 float64(0x7FF0000000000000) - stsfld float64 cgt_un::inf - ldc.r8 float64(0x7FF8000000000000) + ldc.r8 POS_INF + stsfld float64 cgt_un::pos_inf + ldc.r8 NAN stsfld float64 cgt_un::NaN ret } @@ -43,202 +53,202 @@ .maxstack 10 call void cgt_un::initialize() - ldsfld float64 cgt_un::_inf - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::neg_inf + ldsfld float64 cgt_un::neg_inf cgt.un brtrue FAIL - ldsfld float64 cgt_un::_inf - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::neg_inf + ldsfld float64 cgt_un::min cgt.un brtrue FAIL - ldsfld float64 cgt_un::_inf - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::neg_inf + ldsfld float64 cgt_un::minus_one cgt.un brtrue FAIL - ldsfld float64 cgt_un::_inf - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::neg_inf + ldsfld float64 cgt_un::minus_zero cgt.un brtrue FAIL - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::neg_inf ldsfld float64 cgt_un::zero cgt.un brtrue FAIL - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::neg_inf ldsfld float64 cgt_un::one cgt.un brtrue FAIL - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::neg_inf ldsfld float64 cgt_un::max cgt.un brtrue FAIL - ldsfld float64 cgt_un::_inf - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::neg_inf + ldsfld float64 cgt_un::pos_inf cgt.un brtrue FAIL - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::neg_inf ldsfld float64 cgt_un::NaN cgt.un brfalse FAIL - ldsfld float64 cgt_un::_min - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::min + ldsfld float64 cgt_un::neg_inf cgt.un brfalse FAIL - ldsfld float64 cgt_un::_min - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::min + ldsfld float64 cgt_un::min cgt.un brtrue FAIL - ldsfld float64 cgt_un::_min - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::min + ldsfld float64 cgt_un::minus_one cgt.un brtrue FAIL - ldsfld float64 cgt_un::_min - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::min + ldsfld float64 cgt_un::minus_zero cgt.un brtrue FAIL - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::min ldsfld float64 cgt_un::zero cgt.un brtrue FAIL - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::min ldsfld float64 cgt_un::one cgt.un brtrue FAIL - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::min ldsfld float64 cgt_un::max cgt.un brtrue FAIL - ldsfld float64 cgt_un::_min - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::min + ldsfld float64 cgt_un::pos_inf cgt.un brtrue FAIL - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::min ldsfld float64 cgt_un::NaN cgt.un brfalse FAIL - ldsfld float64 cgt_un::_one - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::minus_one + ldsfld float64 cgt_un::neg_inf cgt.un brfalse FAIL - ldsfld float64 cgt_un::_one - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::minus_one + ldsfld float64 cgt_un::min cgt.un brfalse FAIL - ldsfld float64 cgt_un::_one - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::minus_one + ldsfld float64 cgt_un::minus_one cgt.un brtrue FAIL - ldsfld float64 cgt_un::_one - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::minus_one + ldsfld float64 cgt_un::minus_zero cgt.un brtrue FAIL - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::minus_one ldsfld float64 cgt_un::zero cgt.un brtrue FAIL - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::minus_one ldsfld float64 cgt_un::one cgt.un brtrue FAIL - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::minus_one ldsfld float64 cgt_un::max cgt.un brtrue FAIL - ldsfld float64 cgt_un::_one - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::minus_one + ldsfld float64 cgt_un::pos_inf cgt.un brtrue FAIL - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::minus_one ldsfld float64 cgt_un::NaN cgt.un brfalse FAIL - ldsfld float64 cgt_un::_zero - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::minus_zero + ldsfld float64 cgt_un::neg_inf cgt.un brfalse FAIL - ldsfld float64 cgt_un::_zero - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::minus_zero + ldsfld float64 cgt_un::min cgt.un brfalse FAIL - ldsfld float64 cgt_un::_zero - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::minus_zero + ldsfld float64 cgt_un::minus_one cgt.un brfalse FAIL - ldsfld float64 cgt_un::_zero - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::minus_zero + ldsfld float64 cgt_un::minus_zero cgt.un brtrue FAIL - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::minus_zero ldsfld float64 cgt_un::zero cgt.un brtrue FAIL - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::minus_zero ldsfld float64 cgt_un::one cgt.un brtrue FAIL - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::minus_zero ldsfld float64 cgt_un::max cgt.un brtrue FAIL - ldsfld float64 cgt_un::_zero - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::minus_zero + ldsfld float64 cgt_un::pos_inf cgt.un brtrue FAIL - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::minus_zero ldsfld float64 cgt_un::NaN cgt.un brfalse FAIL ldsfld float64 cgt_un::zero - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::neg_inf cgt.un brfalse FAIL ldsfld float64 cgt_un::zero - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::min cgt.un brfalse FAIL ldsfld float64 cgt_un::zero - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::minus_one cgt.un brfalse FAIL ldsfld float64 cgt_un::zero - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::minus_zero cgt.un brtrue FAIL @@ -258,7 +268,7 @@ brtrue FAIL ldsfld float64 cgt_un::zero - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::pos_inf cgt.un brtrue FAIL @@ -268,22 +278,22 @@ brfalse FAIL ldsfld float64 cgt_un::one - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::neg_inf cgt.un brfalse FAIL ldsfld float64 cgt_un::one - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::min cgt.un brfalse FAIL ldsfld float64 cgt_un::one - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::minus_one cgt.un brfalse FAIL ldsfld float64 cgt_un::one - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::minus_zero cgt.un brfalse FAIL @@ -303,7 +313,7 @@ brtrue FAIL ldsfld float64 cgt_un::one - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::pos_inf cgt.un brtrue FAIL @@ -313,22 +323,22 @@ brfalse FAIL ldsfld float64 cgt_un::max - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::neg_inf cgt.un brfalse FAIL ldsfld float64 cgt_un::max - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::min cgt.un brfalse FAIL ldsfld float64 cgt_un::max - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::minus_one cgt.un brfalse FAIL ldsfld float64 cgt_un::max - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::minus_zero cgt.un brfalse FAIL @@ -348,7 +358,7 @@ brtrue FAIL ldsfld float64 cgt_un::max - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::pos_inf cgt.un brtrue FAIL @@ -357,68 +367,68 @@ cgt.un brfalse FAIL - ldsfld float64 cgt_un::inf - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::pos_inf + ldsfld float64 cgt_un::neg_inf cgt.un brfalse FAIL - ldsfld float64 cgt_un::inf - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::pos_inf + ldsfld float64 cgt_un::min cgt.un brfalse FAIL - ldsfld float64 cgt_un::inf - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::pos_inf + ldsfld float64 cgt_un::minus_one cgt.un brfalse FAIL - ldsfld float64 cgt_un::inf - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::pos_inf + ldsfld float64 cgt_un::minus_zero cgt.un brfalse FAIL - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::pos_inf ldsfld float64 cgt_un::zero cgt.un brfalse FAIL - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::pos_inf ldsfld float64 cgt_un::one cgt.un brfalse FAIL - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::pos_inf ldsfld float64 cgt_un::max cgt.un brfalse FAIL - ldsfld float64 cgt_un::inf - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::pos_inf + ldsfld float64 cgt_un::pos_inf cgt.un brtrue FAIL - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::pos_inf ldsfld float64 cgt_un::NaN cgt.un brfalse FAIL ldsfld float64 cgt_un::NaN - ldsfld float64 cgt_un::_inf + ldsfld float64 cgt_un::neg_inf cgt.un brfalse FAIL ldsfld float64 cgt_un::NaN - ldsfld float64 cgt_un::_min + ldsfld float64 cgt_un::min cgt.un brfalse FAIL ldsfld float64 cgt_un::NaN - ldsfld float64 cgt_un::_one + ldsfld float64 cgt_un::minus_one cgt.un brfalse FAIL ldsfld float64 cgt_un::NaN - ldsfld float64 cgt_un::_zero + ldsfld float64 cgt_un::minus_zero cgt.un brfalse FAIL @@ -438,7 +448,7 @@ brfalse FAIL ldsfld float64 cgt_un::NaN - ldsfld float64 cgt_un::inf + ldsfld float64 cgt_un::pos_inf cgt.un brfalse FAIL @@ -447,6 +457,412 @@ cgt.un brfalse FAIL + // Testing early folding logic + + ldc.r8 NEG_INF + ldc.r8 NEG_INF + cgt.un + brtrue FAIL + + ldc.r8 NEG_INF + ldc.r8 MIN + cgt.un + brtrue FAIL + + ldc.r8 NEG_INF + ldc.r8 MINUS_ONE + cgt.un + brtrue FAIL + + ldc.r8 NEG_INF + ldc.r8 MINUS_ZERO + cgt.un + brtrue FAIL + + ldc.r8 NEG_INF + ldc.r8 ZERO + cgt.un + brtrue FAIL + + ldc.r8 NEG_INF + ldc.r8 ONE + cgt.un + brtrue FAIL + + ldc.r8 NEG_INF + ldc.r8 MAX + cgt.un + brtrue FAIL + + ldc.r8 NEG_INF + ldc.r8 POS_INF + cgt.un + brtrue FAIL + + ldc.r8 NEG_INF + ldc.r8 NAN + cgt.un + brfalse FAIL + ldc.r8 MIN + ldc.r8 NEG_INF + cgt.un + brfalse FAIL + + ldc.r8 MIN + ldc.r8 MIN + cgt.un + brtrue FAIL + + ldc.r8 MIN + ldc.r8 MINUS_ONE + cgt.un + brtrue FAIL + + ldc.r8 MIN + ldc.r8 MINUS_ZERO + cgt.un + brtrue FAIL + + ldc.r8 MIN + ldc.r8 ZERO + cgt.un + brtrue FAIL + + ldc.r8 MIN + ldc.r8 ONE + cgt.un + brtrue FAIL + + ldc.r8 MIN + ldc.r8 MAX + cgt.un + brtrue FAIL + + ldc.r8 MIN + ldc.r8 POS_INF + cgt.un + brtrue FAIL + + ldc.r8 MIN + ldc.r8 NAN + cgt.un + brfalse FAIL + + + ldc.r8 MINUS_ONE + ldc.r8 NEG_INF + cgt.un + brfalse FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MIN + cgt.un + brfalse FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ONE + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ZERO + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ONE + ldc.r8 ZERO + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ONE + ldc.r8 ONE + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MAX + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ONE + ldc.r8 POS_INF + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ONE + ldc.r8 NAN + cgt.un + brfalse FAIL + ldc.r8 MINUS_ZERO + ldc.r8 NEG_INF + cgt.un + brfalse FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MIN + cgt.un + brfalse FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ZERO + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 ZERO + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 ONE + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MAX + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 POS_INF + cgt.un + brtrue FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 NAN + cgt.un + brfalse FAIL + + ldc.r8 ZERO + ldc.r8 NEG_INF + cgt.un + brfalse FAIL + + ldc.r8 ZERO + ldc.r8 MIN + cgt.un + brfalse FAIL + + ldc.r8 ZERO + ldc.r8 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r8 ZERO + ldc.r8 MINUS_ZERO + cgt.un + brtrue FAIL + + ldc.r8 ZERO + ldc.r8 ZERO + cgt.un + brtrue FAIL + + ldc.r8 ZERO + ldc.r8 ONE + cgt.un + brtrue FAIL + + ldc.r8 ZERO + ldc.r8 MAX + cgt.un + brtrue FAIL + + ldc.r8 ZERO + ldc.r8 POS_INF + cgt.un + brtrue FAIL + + ldc.r8 ZERO + ldc.r8 NAN + cgt.un + brfalse FAIL + + ldc.r8 ONE + ldc.r8 NEG_INF + cgt.un + brfalse FAIL + + ldc.r8 ONE + ldc.r8 MIN + cgt.un + brfalse FAIL + + ldc.r8 ONE + ldc.r8 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r8 ONE + ldc.r8 MINUS_ZERO + cgt.un + brfalse FAIL + + ldc.r8 ONE + ldc.r8 ZERO + cgt.un + brfalse FAIL + + ldc.r8 ONE + ldc.r8 ONE + cgt.un + brtrue FAIL + + ldc.r8 ONE + ldc.r8 MAX + cgt.un + brtrue FAIL + + ldc.r8 ONE + ldc.r8 POS_INF + cgt.un + brtrue FAIL + + ldc.r8 ONE + ldc.r8 NAN + cgt.un + brfalse FAIL + + ldc.r8 MAX + ldc.r8 NEG_INF + cgt.un + brfalse FAIL + + ldc.r8 MAX + ldc.r8 MIN + cgt.un + brfalse FAIL + + ldc.r8 MAX + ldc.r8 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r8 MAX + ldc.r8 MINUS_ZERO + cgt.un + brfalse FAIL + + ldc.r8 MAX + ldc.r8 ZERO + cgt.un + brfalse FAIL + + ldc.r8 MAX + ldc.r8 ONE + cgt.un + brfalse FAIL + + ldc.r8 MAX + ldc.r8 MAX + cgt.un + brtrue FAIL + + ldc.r8 MAX + ldc.r8 POS_INF + cgt.un + brtrue FAIL + + ldc.r8 MAX + ldc.r8 NAN + cgt.un + brfalse FAIL + + ldc.r8 POS_INF + ldc.r8 NEG_INF + cgt.un + brfalse FAIL + + ldc.r8 POS_INF + ldc.r8 MIN + cgt.un + brfalse FAIL + + ldc.r8 POS_INF + ldc.r8 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r8 POS_INF + ldc.r8 MINUS_ZERO + cgt.un + brfalse FAIL + + ldc.r8 POS_INF + ldc.r8 ZERO + cgt.un + brfalse FAIL + + ldc.r8 POS_INF + ldc.r8 ONE + cgt.un + brfalse FAIL + + ldc.r8 POS_INF + ldc.r8 MAX + cgt.un + brfalse FAIL + + ldc.r8 POS_INF + ldc.r8 POS_INF + cgt.un + brtrue FAIL + + ldc.r8 POS_INF + ldc.r8 NAN + cgt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 NEG_INF + cgt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 MIN + cgt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 MINUS_ONE + cgt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 MINUS_ZERO + cgt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 ZERO + cgt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 ONE + cgt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 MAX + cgt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 POS_INF + cgt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 NAN + cgt.un + brfalse FAIL + ldc.i4 100 ret FAIL: diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/clt_un_r4.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/clt_un_r4.il index 8e753f2e9c3a2..91b57cc74d281 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/clt_un_r4.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/clt_un_r4.il @@ -3,36 +3,46 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float32(0xFF800000)" +#define MIN "float32(0xFF7FFFFF)" +#define MINUS_ONE "float32(0xBF800000)" +#define MINUS_ZERO "float32(0x80000000)" +#define ZERO "float32(0x00000000)" +#define ONE "float32(0x3F800000)" +#define MAX "float32(0x7F7FFFFF)" +#define POS_INF "float32(0x7F800000)" +#define NAN "float32(0x7FC00000)" + .class public clt_un { -.field public static float32 _inf -.field public static float32 _min -.field public static float32 _one -.field public static float32 _zero +.field public static float32 neg_inf +.field public static float32 min +.field public static float32 minus_one +.field public static float32 minus_zero .field public static float32 zero .field public static float32 one .field public static float32 max -.field public static float32 inf +.field public static float32 pos_inf .field public static float32 NaN .method public static void initialize() { .maxstack 10 - ldc.r4 float32(0xFF800000) - stsfld float32 clt_un::_inf - ldc.r4 float32(0xFF7FFFFF) - stsfld float32 clt_un::_min - ldc.r4 float32(0xBF800000) - stsfld float32 clt_un::_one - ldc.r4 float32(0x80000000) - stsfld float32 clt_un::_zero - ldc.r4 float32(0x00000000) + ldc.r4 NEG_INF + stsfld float32 clt_un::neg_inf + ldc.r4 MIN + stsfld float32 clt_un::min + ldc.r4 MINUS_ONE + stsfld float32 clt_un::minus_one + ldc.r4 MINUS_ZERO + stsfld float32 clt_un::minus_zero + ldc.r4 ZERO stsfld float32 clt_un::zero - ldc.r4 float32(0x3F800000) + ldc.r4 ONE stsfld float32 clt_un::one - ldc.r4 float32(0x7F7FFFFF) + ldc.r4 MAX stsfld float32 clt_un::max - ldc.r4 float32(0x7F800000) - stsfld float32 clt_un::inf - ldc.r4 float32(0x7FC00000) + ldc.r4 POS_INF + stsfld float32 clt_un::pos_inf + ldc.r4 NAN stsfld float32 clt_un::NaN ret } @@ -41,202 +51,202 @@ .entrypoint .maxstack 10 call void clt_un::initialize() - ldsfld float32 clt_un::_inf - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::neg_inf + ldsfld float32 clt_un::neg_inf clt.un brtrue FAIL - ldsfld float32 clt_un::_inf - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::neg_inf + ldsfld float32 clt_un::min clt.un brfalse FAIL - ldsfld float32 clt_un::_inf - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::neg_inf + ldsfld float32 clt_un::minus_one clt.un brfalse FAIL - ldsfld float32 clt_un::_inf - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::neg_inf + ldsfld float32 clt_un::minus_zero clt.un brfalse FAIL - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::neg_inf ldsfld float32 clt_un::zero clt.un brfalse FAIL - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::neg_inf ldsfld float32 clt_un::one clt.un brfalse FAIL - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::neg_inf ldsfld float32 clt_un::max clt.un brfalse FAIL - ldsfld float32 clt_un::_inf - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::neg_inf + ldsfld float32 clt_un::pos_inf clt.un brfalse FAIL - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::neg_inf ldsfld float32 clt_un::NaN clt.un brfalse FAIL - ldsfld float32 clt_un::_min - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::min + ldsfld float32 clt_un::neg_inf clt.un brtrue FAIL - ldsfld float32 clt_un::_min - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::min + ldsfld float32 clt_un::min clt.un brtrue FAIL - ldsfld float32 clt_un::_min - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::min + ldsfld float32 clt_un::minus_one clt.un brfalse FAIL - ldsfld float32 clt_un::_min - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::min + ldsfld float32 clt_un::minus_zero clt.un brfalse FAIL - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::min ldsfld float32 clt_un::zero clt.un brfalse FAIL - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::min ldsfld float32 clt_un::one clt.un brfalse FAIL - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::min ldsfld float32 clt_un::max clt.un brfalse FAIL - ldsfld float32 clt_un::_min - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::min + ldsfld float32 clt_un::pos_inf clt.un brfalse FAIL - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::min ldsfld float32 clt_un::NaN clt.un brfalse FAIL - ldsfld float32 clt_un::_one - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::minus_one + ldsfld float32 clt_un::neg_inf clt.un brtrue FAIL - ldsfld float32 clt_un::_one - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::minus_one + ldsfld float32 clt_un::min clt.un brtrue FAIL - ldsfld float32 clt_un::_one - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::minus_one + ldsfld float32 clt_un::minus_one clt.un brtrue FAIL - ldsfld float32 clt_un::_one - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::minus_one + ldsfld float32 clt_un::minus_zero clt.un brfalse FAIL - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::minus_one ldsfld float32 clt_un::zero clt.un brfalse FAIL - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::minus_one ldsfld float32 clt_un::one clt.un brfalse FAIL - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::minus_one ldsfld float32 clt_un::max clt.un brfalse FAIL - ldsfld float32 clt_un::_one - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::minus_one + ldsfld float32 clt_un::pos_inf clt.un brfalse FAIL - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::minus_one ldsfld float32 clt_un::NaN clt.un brfalse FAIL - ldsfld float32 clt_un::_zero - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::minus_zero + ldsfld float32 clt_un::neg_inf clt.un brtrue FAIL - ldsfld float32 clt_un::_zero - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::minus_zero + ldsfld float32 clt_un::min clt.un brtrue FAIL - ldsfld float32 clt_un::_zero - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::minus_zero + ldsfld float32 clt_un::minus_one clt.un brtrue FAIL - ldsfld float32 clt_un::_zero - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::minus_zero + ldsfld float32 clt_un::minus_zero clt.un brtrue FAIL - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::minus_zero ldsfld float32 clt_un::zero clt.un brtrue FAIL - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::minus_zero ldsfld float32 clt_un::one clt.un brfalse FAIL - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::minus_zero ldsfld float32 clt_un::max clt.un brfalse FAIL - ldsfld float32 clt_un::_zero - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::minus_zero + ldsfld float32 clt_un::pos_inf clt.un brfalse FAIL - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::minus_zero ldsfld float32 clt_un::NaN clt.un brfalse FAIL ldsfld float32 clt_un::zero - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::neg_inf clt.un brtrue FAIL ldsfld float32 clt_un::zero - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::min clt.un brtrue FAIL ldsfld float32 clt_un::zero - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::minus_one clt.un brtrue FAIL ldsfld float32 clt_un::zero - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::minus_zero clt.un brtrue FAIL @@ -256,7 +266,7 @@ brfalse FAIL ldsfld float32 clt_un::zero - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::pos_inf clt.un brfalse FAIL @@ -266,22 +276,22 @@ brfalse FAIL ldsfld float32 clt_un::one - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::neg_inf clt.un brtrue FAIL ldsfld float32 clt_un::one - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::min clt.un brtrue FAIL ldsfld float32 clt_un::one - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::minus_one clt.un brtrue FAIL ldsfld float32 clt_un::one - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::minus_zero clt.un brtrue FAIL @@ -301,7 +311,7 @@ brfalse FAIL ldsfld float32 clt_un::one - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::pos_inf clt.un brfalse FAIL @@ -311,22 +321,22 @@ brfalse FAIL ldsfld float32 clt_un::max - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::neg_inf clt.un brtrue FAIL ldsfld float32 clt_un::max - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::min clt.un brtrue FAIL ldsfld float32 clt_un::max - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::minus_one clt.un brtrue FAIL ldsfld float32 clt_un::max - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::minus_zero clt.un brtrue FAIL @@ -346,7 +356,7 @@ brtrue FAIL ldsfld float32 clt_un::max - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::pos_inf clt.un brfalse FAIL @@ -355,68 +365,68 @@ clt.un brfalse FAIL - ldsfld float32 clt_un::inf - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::pos_inf + ldsfld float32 clt_un::neg_inf clt.un brtrue FAIL - ldsfld float32 clt_un::inf - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::pos_inf + ldsfld float32 clt_un::min clt.un brtrue FAIL - ldsfld float32 clt_un::inf - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::pos_inf + ldsfld float32 clt_un::minus_one clt.un brtrue FAIL - ldsfld float32 clt_un::inf - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::pos_inf + ldsfld float32 clt_un::minus_zero clt.un brtrue FAIL - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::pos_inf ldsfld float32 clt_un::zero clt.un brtrue FAIL - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::pos_inf ldsfld float32 clt_un::one clt.un brtrue FAIL - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::pos_inf ldsfld float32 clt_un::max clt.un brtrue FAIL - ldsfld float32 clt_un::inf - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::pos_inf + ldsfld float32 clt_un::pos_inf clt.un brtrue FAIL - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::pos_inf ldsfld float32 clt_un::NaN clt.un brfalse FAIL ldsfld float32 clt_un::NaN - ldsfld float32 clt_un::_inf + ldsfld float32 clt_un::neg_inf clt.un brfalse FAIL ldsfld float32 clt_un::NaN - ldsfld float32 clt_un::_min + ldsfld float32 clt_un::min clt.un brfalse FAIL ldsfld float32 clt_un::NaN - ldsfld float32 clt_un::_one + ldsfld float32 clt_un::minus_one clt.un brfalse FAIL ldsfld float32 clt_un::NaN - ldsfld float32 clt_un::_zero + ldsfld float32 clt_un::minus_zero clt.un brfalse FAIL @@ -436,7 +446,7 @@ brfalse FAIL ldsfld float32 clt_un::NaN - ldsfld float32 clt_un::inf + ldsfld float32 clt_un::pos_inf clt.un brfalse FAIL @@ -445,6 +455,412 @@ clt.un brfalse FAIL + // Testing early folding logic + + ldc.r4 NEG_INF + ldc.r4 NEG_INF + clt.un + brtrue FAIL + + ldc.r4 NEG_INF + ldc.r4 MIN + clt.un + brfalse FAIL + + ldc.r4 NEG_INF + ldc.r4 MINUS_ONE + clt.un + brfalse FAIL + + ldc.r4 NEG_INF + ldc.r4 MINUS_ZERO + clt.un + brfalse FAIL + + ldc.r4 NEG_INF + ldc.r4 ZERO + clt.un + brfalse FAIL + + ldc.r4 NEG_INF + ldc.r4 ONE + clt.un + brfalse FAIL + + ldc.r4 NEG_INF + ldc.r4 MAX + clt.un + brfalse FAIL + + ldc.r4 NEG_INF + ldc.r4 POS_INF + clt.un + brfalse FAIL + + ldc.r4 NEG_INF + ldc.r4 NAN + clt.un + brfalse FAIL + ldc.r4 MIN + ldc.r4 NEG_INF + clt.un + brtrue FAIL + + ldc.r4 MIN + ldc.r4 MIN + clt.un + brtrue FAIL + + ldc.r4 MIN + ldc.r4 MINUS_ONE + clt.un + brfalse FAIL + + ldc.r4 MIN + ldc.r4 MINUS_ZERO + clt.un + brfalse FAIL + + ldc.r4 MIN + ldc.r4 ZERO + clt.un + brfalse FAIL + + ldc.r4 MIN + ldc.r4 ONE + clt.un + brfalse FAIL + + ldc.r4 MIN + ldc.r4 MAX + clt.un + brfalse FAIL + + ldc.r4 MIN + ldc.r4 POS_INF + clt.un + brfalse FAIL + + ldc.r4 MIN + ldc.r4 NAN + clt.un + brfalse FAIL + + + ldc.r4 MINUS_ONE + ldc.r4 NEG_INF + clt.un + brtrue FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MIN + clt.un + brtrue FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MINUS_ZERO + clt.un + brfalse FAIL + + ldc.r4 MINUS_ONE + ldc.r4 ZERO + clt.un + brfalse FAIL + + ldc.r4 MINUS_ONE + ldc.r4 ONE + clt.un + brfalse FAIL + + ldc.r4 MINUS_ONE + ldc.r4 MAX + clt.un + brfalse FAIL + + ldc.r4 MINUS_ONE + ldc.r4 POS_INF + clt.un + brfalse FAIL + + ldc.r4 MINUS_ONE + ldc.r4 NAN + clt.un + brfalse FAIL + ldc.r4 MINUS_ZERO + ldc.r4 NEG_INF + clt.un + brtrue FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MIN + clt.un + brtrue FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MINUS_ZERO + clt.un + brtrue FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 ZERO + clt.un + brtrue FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 ONE + clt.un + brfalse FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 MAX + clt.un + brfalse FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 POS_INF + clt.un + brfalse FAIL + + ldc.r4 MINUS_ZERO + ldc.r4 NAN + clt.un + brfalse FAIL + + ldc.r4 ZERO + ldc.r4 NEG_INF + clt.un + brtrue FAIL + + ldc.r4 ZERO + ldc.r4 MIN + clt.un + brtrue FAIL + + ldc.r4 ZERO + ldc.r4 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r4 ZERO + ldc.r4 MINUS_ZERO + clt.un + brtrue FAIL + + ldc.r4 ZERO + ldc.r4 ZERO + clt.un + brtrue FAIL + + ldc.r4 ZERO + ldc.r4 ONE + clt.un + brfalse FAIL + + ldc.r4 ZERO + ldc.r4 MAX + clt.un + brfalse FAIL + + ldc.r4 ZERO + ldc.r4 POS_INF + clt.un + brfalse FAIL + + ldc.r4 ZERO + ldc.r4 NAN + clt.un + brfalse FAIL + + ldc.r4 ONE + ldc.r4 NEG_INF + clt.un + brtrue FAIL + + ldc.r4 ONE + ldc.r4 MIN + clt.un + brtrue FAIL + + ldc.r4 ONE + ldc.r4 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r4 ONE + ldc.r4 MINUS_ZERO + clt.un + brtrue FAIL + + ldc.r4 ONE + ldc.r4 ZERO + clt.un + brtrue FAIL + + ldc.r4 ONE + ldc.r4 ONE + clt.un + brtrue FAIL + + ldc.r4 ONE + ldc.r4 MAX + clt.un + brfalse FAIL + + ldc.r4 ONE + ldc.r4 POS_INF + clt.un + brfalse FAIL + + ldc.r4 ONE + ldc.r4 NAN + clt.un + brfalse FAIL + + ldc.r4 MAX + ldc.r4 NEG_INF + clt.un + brtrue FAIL + + ldc.r4 MAX + ldc.r4 MIN + clt.un + brtrue FAIL + + ldc.r4 MAX + ldc.r4 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r4 MAX + ldc.r4 MINUS_ZERO + clt.un + brtrue FAIL + + ldc.r4 MAX + ldc.r4 ZERO + clt.un + brtrue FAIL + + ldc.r4 MAX + ldc.r4 ONE + clt.un + brtrue FAIL + + ldc.r4 MAX + ldc.r4 MAX + clt.un + brtrue FAIL + + ldc.r4 MAX + ldc.r4 POS_INF + clt.un + brfalse FAIL + + ldc.r4 MAX + ldc.r4 NAN + clt.un + brfalse FAIL + + ldc.r4 POS_INF + ldc.r4 NEG_INF + clt.un + brtrue FAIL + + ldc.r4 POS_INF + ldc.r4 MIN + clt.un + brtrue FAIL + + ldc.r4 POS_INF + ldc.r4 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r4 POS_INF + ldc.r4 MINUS_ZERO + clt.un + brtrue FAIL + + ldc.r4 POS_INF + ldc.r4 ZERO + clt.un + brtrue FAIL + + ldc.r4 POS_INF + ldc.r4 ONE + clt.un + brtrue FAIL + + ldc.r4 POS_INF + ldc.r4 MAX + clt.un + brtrue FAIL + + ldc.r4 POS_INF + ldc.r4 POS_INF + clt.un + brtrue FAIL + + ldc.r4 POS_INF + ldc.r4 NAN + clt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 NEG_INF + clt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 MIN + clt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 MINUS_ONE + clt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 MINUS_ZERO + clt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 ZERO + clt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 ONE + clt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 MAX + clt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 POS_INF + clt.un + brfalse FAIL + + ldc.r4 NAN + ldc.r4 NAN + clt.un + brfalse FAIL + ldc.i4 100 ret FAIL: diff --git a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/clt_un_r8.il b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/clt_un_r8.il index 1585af3efe8bd..9187df14d7f5d 100644 --- a/src/tests/JIT/IL_Conformance/Old/Conformance_Base/clt_un_r8.il +++ b/src/tests/JIT/IL_Conformance/Old/Conformance_Base/clt_un_r8.il @@ -3,36 +3,46 @@ .assembly extern legacy library mscorlib {} +#define NEG_INF "float64(0xFFF0000000000000)" +#define MIN "float64(0xFF7FFFFFFFFFFFFF)" +#define MINUS_ONE "float64(0xBFF0000000000000)" +#define MINUS_ZERO "float64(0x8000000000000000)" +#define ZERO "float64(0x0000000000000000)" +#define ONE "float64(0x3FF0000000000000)" +#define MAX "float64(0x7FEFFFFFFFFFFFFF)" +#define POS_INF "float64(0x7FF0000000000000)" +#define NAN "float64(0x7FF8000000000000)" + .class public clt_un { -.field public static float64 _inf -.field public static float64 _min -.field public static float64 _one -.field public static float64 _zero +.field public static float64 neg_inf +.field public static float64 min +.field public static float64 minus_one +.field public static float64 minus_zero .field public static float64 zero .field public static float64 one .field public static float64 max -.field public static float64 inf +.field public static float64 pos_inf .field public static float64 NaN .method public static void initialize() { .maxstack 10 - ldc.r8 float64(0xFFF0000000000000) - stsfld float64 clt_un::_inf - ldc.r8 float64(0xFF7FFFFFFFFFFFFF) - stsfld float64 clt_un::_min - ldc.r8 float64(0xBFF0000000000000) - stsfld float64 clt_un::_one - ldc.r8 float64(0x8000000000000000) - stsfld float64 clt_un::_zero - ldc.r8 float64(0x0000000000000000) + ldc.r8 NEG_INF + stsfld float64 clt_un::neg_inf + ldc.r8 MIN + stsfld float64 clt_un::min + ldc.r8 MINUS_ONE + stsfld float64 clt_un::minus_one + ldc.r8 MINUS_ZERO + stsfld float64 clt_un::minus_zero + ldc.r8 ZERO stsfld float64 clt_un::zero - ldc.r8 float64(0x3FF0000000000000) + ldc.r8 ONE stsfld float64 clt_un::one - ldc.r8 float64(0x7FEFFFFFFFFFFFFF) + ldc.r8 MAX stsfld float64 clt_un::max - ldc.r8 float64(0x7FF0000000000000) - stsfld float64 clt_un::inf - ldc.r8 float64(0x7FF8000000000000) + ldc.r8 POS_INF + stsfld float64 clt_un::pos_inf + ldc.r8 NAN stsfld float64 clt_un::NaN ret } @@ -41,199 +51,199 @@ .entrypoint .maxstack 10 call void clt_un::initialize() - ldsfld float64 clt_un::_inf - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::neg_inf + ldsfld float64 clt_un::neg_inf clt.un brtrue FAIL - ldsfld float64 clt_un::_inf - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::neg_inf + ldsfld float64 clt_un::min clt.un brfalse FAIL - ldsfld float64 clt_un::_inf - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::neg_inf + ldsfld float64 clt_un::minus_one clt.un brfalse FAIL - ldsfld float64 clt_un::_inf - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::neg_inf + ldsfld float64 clt_un::minus_zero clt.un brfalse FAIL - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::neg_inf ldsfld float64 clt_un::zero clt.un brfalse FAIL - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::neg_inf ldsfld float64 clt_un::one clt.un brfalse FAIL - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::neg_inf ldsfld float64 clt_un::max clt.un brfalse FAIL - ldsfld float64 clt_un::_inf - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::neg_inf + ldsfld float64 clt_un::pos_inf clt.un brfalse FAIL - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::neg_inf ldsfld float64 clt_un::NaN clt.un brfalse FAIL - ldsfld float64 clt_un::_min - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::min + ldsfld float64 clt_un::neg_inf clt.un brtrue FAIL - ldsfld float64 clt_un::_min - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::min + ldsfld float64 clt_un::min clt.un brtrue FAIL - ldsfld float64 clt_un::_min - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::min + ldsfld float64 clt_un::minus_one clt.un brfalse FAIL - ldsfld float64 clt_un::_min - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::min + ldsfld float64 clt_un::minus_zero clt.un brfalse FAIL - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::min ldsfld float64 clt_un::zero clt.un brfalse FAIL - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::min ldsfld float64 clt_un::one clt.un brfalse FAIL - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::min ldsfld float64 clt_un::max clt.un brfalse FAIL - ldsfld float64 clt_un::_min - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::min + ldsfld float64 clt_un::pos_inf clt.un brfalse FAIL - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::min ldsfld float64 clt_un::NaN clt.un brfalse FAIL - ldsfld float64 clt_un::_one - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::minus_one + ldsfld float64 clt_un::neg_inf clt.un brtrue FAIL - ldsfld float64 clt_un::_one - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::minus_one + ldsfld float64 clt_un::min clt.un brtrue FAIL - ldsfld float64 clt_un::_one - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::minus_one + ldsfld float64 clt_un::minus_one clt.un brtrue FAIL - ldsfld float64 clt_un::_one - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::minus_one + ldsfld float64 clt_un::minus_zero clt.un brfalse FAIL - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::minus_one ldsfld float64 clt_un::zero clt.un brfalse FAIL - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::minus_one ldsfld float64 clt_un::one clt.un brfalse FAIL - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::minus_one ldsfld float64 clt_un::max clt.un brfalse FAIL - ldsfld float64 clt_un::_one - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::minus_one + ldsfld float64 clt_un::pos_inf clt.un brfalse FAIL - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::minus_one ldsfld float64 clt_un::NaN clt.un brfalse FAIL - ldsfld float64 clt_un::_zero - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::minus_zero + ldsfld float64 clt_un::neg_inf clt.un brtrue FAIL - ldsfld float64 clt_un::_zero - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::minus_zero + ldsfld float64 clt_un::min clt.un brtrue FAIL - ldsfld float64 clt_un::_zero - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::minus_zero + ldsfld float64 clt_un::minus_one clt.un brtrue FAIL - ldsfld float64 clt_un::_zero - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::minus_zero + ldsfld float64 clt_un::minus_zero clt.un brtrue FAIL - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::minus_zero ldsfld float64 clt_un::zero clt.un brtrue FAIL - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::minus_zero ldsfld float64 clt_un::one clt.un brfalse FAIL - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::minus_zero ldsfld float64 clt_un::max clt.un brfalse FAIL - ldsfld float64 clt_un::_zero - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::minus_zero + ldsfld float64 clt_un::pos_inf clt.un brfalse FAIL - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::minus_zero ldsfld float64 clt_un::NaN clt.un brfalse FAIL ldsfld float64 clt_un::zero - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::neg_inf clt.un brtrue FAIL ldsfld float64 clt_un::zero - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::min clt.un brtrue FAIL ldsfld float64 clt_un::zero - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::minus_one clt.un brtrue FAIL ldsfld float64 clt_un::zero - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::minus_zero clt.un brtrue FAIL @@ -253,7 +263,7 @@ brfalse FAIL ldsfld float64 clt_un::zero - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::pos_inf clt.un brfalse FAIL @@ -263,22 +273,22 @@ brfalse FAIL ldsfld float64 clt_un::one - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::neg_inf clt.un brtrue FAIL ldsfld float64 clt_un::one - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::min clt.un brtrue FAIL ldsfld float64 clt_un::one - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::minus_one clt.un brtrue FAIL ldsfld float64 clt_un::one - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::minus_zero clt.un brtrue FAIL @@ -298,7 +308,7 @@ brfalse FAIL ldsfld float64 clt_un::one - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::pos_inf clt.un brfalse FAIL @@ -308,22 +318,22 @@ brfalse FAIL ldsfld float64 clt_un::max - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::neg_inf clt.un brtrue FAIL ldsfld float64 clt_un::max - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::min clt.un brtrue FAIL ldsfld float64 clt_un::max - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::minus_one clt.un brtrue FAIL ldsfld float64 clt_un::max - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::minus_zero clt.un brtrue FAIL @@ -343,7 +353,7 @@ brtrue FAIL ldsfld float64 clt_un::max - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::pos_inf clt.un brfalse FAIL @@ -352,68 +362,68 @@ clt.un brfalse FAIL - ldsfld float64 clt_un::inf - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::pos_inf + ldsfld float64 clt_un::neg_inf clt.un brtrue FAIL - ldsfld float64 clt_un::inf - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::pos_inf + ldsfld float64 clt_un::min clt.un brtrue FAIL - ldsfld float64 clt_un::inf - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::pos_inf + ldsfld float64 clt_un::minus_one clt.un brtrue FAIL - ldsfld float64 clt_un::inf - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::pos_inf + ldsfld float64 clt_un::minus_zero clt.un brtrue FAIL - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::pos_inf ldsfld float64 clt_un::zero clt.un brtrue FAIL - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::pos_inf ldsfld float64 clt_un::one clt.un brtrue FAIL - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::pos_inf ldsfld float64 clt_un::max clt.un brtrue FAIL - ldsfld float64 clt_un::inf - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::pos_inf + ldsfld float64 clt_un::pos_inf clt.un brtrue FAIL - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::pos_inf ldsfld float64 clt_un::NaN clt.un brfalse FAIL ldsfld float64 clt_un::NaN - ldsfld float64 clt_un::_inf + ldsfld float64 clt_un::neg_inf clt.un brfalse FAIL ldsfld float64 clt_un::NaN - ldsfld float64 clt_un::_min + ldsfld float64 clt_un::min clt.un brfalse FAIL ldsfld float64 clt_un::NaN - ldsfld float64 clt_un::_one + ldsfld float64 clt_un::minus_one clt.un brfalse FAIL ldsfld float64 clt_un::NaN - ldsfld float64 clt_un::_zero + ldsfld float64 clt_un::minus_zero clt.un brfalse FAIL @@ -433,7 +443,7 @@ brfalse FAIL ldsfld float64 clt_un::NaN - ldsfld float64 clt_un::inf + ldsfld float64 clt_un::pos_inf clt.un brfalse FAIL @@ -442,6 +452,409 @@ clt.un brfalse FAIL + // Testing early folding logic + + ldc.r8 NEG_INF + ldc.r8 NEG_INF + clt.un + brtrue FAIL + + ldc.r8 NEG_INF + ldc.r8 MIN + clt.un + brfalse FAIL + + ldc.r8 NEG_INF + ldc.r8 MINUS_ONE + clt.un + brfalse FAIL + + ldc.r8 NEG_INF + ldc.r8 MINUS_ZERO + clt.un + brfalse FAIL + + ldc.r8 NEG_INF + ldc.r8 ZERO + clt.un + brfalse FAIL + + ldc.r8 NEG_INF + ldc.r8 ONE + clt.un + brfalse FAIL + + ldc.r8 NEG_INF + ldc.r8 MAX + clt.un + brfalse FAIL + + ldc.r8 NEG_INF + ldc.r8 POS_INF + clt.un + brfalse FAIL + + ldc.r8 NEG_INF + ldc.r8 NAN + clt.un + brfalse FAIL + ldc.r8 MIN + ldc.r8 NEG_INF + clt.un + brtrue FAIL + + ldc.r8 MIN + ldc.r8 MIN + clt.un + brtrue FAIL + + ldc.r8 MIN + ldc.r8 MINUS_ONE + clt.un + brfalse FAIL + + ldc.r8 MIN + ldc.r8 MINUS_ZERO + clt.un + brfalse FAIL + + ldc.r8 MIN + ldc.r8 ZERO + clt.un + brfalse FAIL + + ldc.r8 MIN + ldc.r8 ONE + clt.un + brfalse FAIL + + ldc.r8 MIN + ldc.r8 MAX + clt.un + brfalse FAIL + + ldc.r8 MIN + ldc.r8 POS_INF + clt.un + brfalse FAIL + + ldc.r8 MIN + ldc.r8 NAN + clt.un + brfalse FAIL + ldc.r8 MINUS_ONE + ldc.r8 NEG_INF + clt.un + brtrue FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MIN + clt.un + brtrue FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MINUS_ZERO + clt.un + brfalse FAIL + + ldc.r8 MINUS_ONE + ldc.r8 ZERO + clt.un + brfalse FAIL + + ldc.r8 MINUS_ONE + ldc.r8 ONE + clt.un + brfalse FAIL + + ldc.r8 MINUS_ONE + ldc.r8 MAX + clt.un + brfalse FAIL + + ldc.r8 MINUS_ONE + ldc.r8 POS_INF + clt.un + brfalse FAIL + + ldc.r8 MINUS_ONE + ldc.r8 NAN + clt.un + brfalse FAIL + ldc.r8 MINUS_ZERO + ldc.r8 NEG_INF + clt.un + brtrue FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MIN + clt.un + brtrue FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MINUS_ZERO + clt.un + brtrue FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 ZERO + clt.un + brtrue FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 ONE + clt.un + brfalse FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 MAX + clt.un + brfalse FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 POS_INF + clt.un + brfalse FAIL + + ldc.r8 MINUS_ZERO + ldc.r8 NAN + clt.un + brfalse FAIL + ldc.r8 ZERO + ldc.r8 NEG_INF + clt.un + brtrue FAIL + + ldc.r8 ZERO + ldc.r8 MIN + clt.un + brtrue FAIL + + ldc.r8 ZERO + ldc.r8 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r8 ZERO + ldc.r8 MINUS_ZERO + clt.un + brtrue FAIL + + ldc.r8 ZERO + ldc.r8 ZERO + clt.un + brtrue FAIL + + ldc.r8 ZERO + ldc.r8 ONE + clt.un + brfalse FAIL + + ldc.r8 ZERO + ldc.r8 MAX + clt.un + brfalse FAIL + + ldc.r8 ZERO + ldc.r8 POS_INF + clt.un + brfalse FAIL + + ldc.r8 ZERO + ldc.r8 NAN + clt.un + brfalse FAIL + + ldc.r8 ONE + ldc.r8 NEG_INF + clt.un + brtrue FAIL + + ldc.r8 ONE + ldc.r8 MIN + clt.un + brtrue FAIL + + ldc.r8 ONE + ldc.r8 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r8 ONE + ldc.r8 MINUS_ZERO + clt.un + brtrue FAIL + + ldc.r8 ONE + ldc.r8 ZERO + clt.un + brtrue FAIL + + ldc.r8 ONE + ldc.r8 ONE + clt.un + brtrue FAIL + + ldc.r8 ONE + ldc.r8 MAX + clt.un + brfalse FAIL + + ldc.r8 ONE + ldc.r8 POS_INF + clt.un + brfalse FAIL + + ldc.r8 ONE + ldc.r8 NAN + clt.un + brfalse FAIL + + ldc.r8 MAX + ldc.r8 NEG_INF + clt.un + brtrue FAIL + + ldc.r8 MAX + ldc.r8 MIN + clt.un + brtrue FAIL + + ldc.r8 MAX + ldc.r8 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r8 MAX + ldc.r8 MINUS_ZERO + clt.un + brtrue FAIL + + ldc.r8 MAX + ldc.r8 ZERO + clt.un + brtrue FAIL + + ldc.r8 MAX + ldc.r8 ONE + clt.un + brtrue FAIL + + ldc.r8 MAX + ldc.r8 MAX + clt.un + brtrue FAIL + + ldc.r8 MAX + ldc.r8 POS_INF + clt.un + brfalse FAIL + + ldc.r8 MAX + ldc.r8 NAN + clt.un + brfalse FAIL + + ldc.r8 POS_INF + ldc.r8 NEG_INF + clt.un + brtrue FAIL + + ldc.r8 POS_INF + ldc.r8 MIN + clt.un + brtrue FAIL + + ldc.r8 POS_INF + ldc.r8 MINUS_ONE + clt.un + brtrue FAIL + + ldc.r8 POS_INF + ldc.r8 MINUS_ZERO + clt.un + brtrue FAIL + + ldc.r8 POS_INF + ldc.r8 ZERO + clt.un + brtrue FAIL + + ldc.r8 POS_INF + ldc.r8 ONE + clt.un + brtrue FAIL + + ldc.r8 POS_INF + ldc.r8 MAX + clt.un + brtrue FAIL + + ldc.r8 POS_INF + ldc.r8 POS_INF + clt.un + brtrue FAIL + + ldc.r8 POS_INF + ldc.r8 NAN + clt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 NEG_INF + clt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 MIN + clt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 MINUS_ONE + clt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 MINUS_ZERO + clt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 ZERO + clt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 ONE + clt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 MAX + clt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 POS_INF + clt.un + brfalse FAIL + + ldc.r8 NAN + ldc.r8 NAN + clt.un + brfalse FAIL + ldc.i4 100 ret FAIL: From ccf2de0d52a2776f3503cc6c577cfe8c2cbc1bcb Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 9 Mar 2021 16:33:05 -0500 Subject: [PATCH 63/83] Replace custom Marvin copy with string.GetHashCode (#48410) * Use HashCode instead of custom Marvin implementation * Update src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs --- src/libraries/Common/src/System/Marvin.cs | 124 ------------------ .../Common/tests/Common.Tests.csproj | 3 - .../Common/tests/Tests/System/MarvinTests.cs | 71 ---------- .../src/System.Formats.Cbor.csproj | 1 - .../Formats/Cbor/CborConformanceLevel.cs | 17 ++- .../src/System.Net.Primitives.csproj | 2 - .../src/System/Net/IPAddress.cs | 45 +++---- .../System.Net.Primitives.Pal.Tests.csproj | 2 - ...stem.Net.Primitives.UnitTests.Tests.csproj | 2 - 9 files changed, 33 insertions(+), 234 deletions(-) delete mode 100644 src/libraries/Common/src/System/Marvin.cs delete mode 100644 src/libraries/Common/tests/Tests/System/MarvinTests.cs diff --git a/src/libraries/Common/src/System/Marvin.cs b/src/libraries/Common/src/System/Marvin.cs deleted file mode 100644 index b36e2a66c3f35..0000000000000 --- a/src/libraries/Common/src/System/Marvin.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable disable -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Security.Cryptography; - -namespace System -{ - internal static class Marvin - { - /// - /// Convenience method to compute a Marvin hash and collapse it into a 32-bit hash. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int ComputeHash32(ReadOnlySpan data, ulong seed) - { - long hash64 = ComputeHash(data, seed); - return ((int)(hash64 >> 32)) ^ (int)hash64; - } - - /// - /// Computes a 64-hash using the Marvin algorithm. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long ComputeHash(ReadOnlySpan data, ulong seed) - => ComputeHash(ref MemoryMarshal.GetReference(data), (uint)data.Length, p0: (uint)seed, p1: (uint)(seed >> 32)); - - private static unsafe long ComputeHash(ref byte rBuffer, nuint cbBuffer, uint p0, uint p1) - { - nuint currentOffset = 0; - - fixed (byte* pbBuffer = &rBuffer) - { - // Consume as many 4-byte chunks as possible. - - if (cbBuffer >= 4) - { - nuint stopOffset = cbBuffer & ~(nuint)3; - do - { - p0 += Unsafe.ReadUnaligned(pbBuffer + currentOffset); - currentOffset += 4; - Block(ref p0, ref p1); - } while (currentOffset < stopOffset); - } - - // Fewer than 4 bytes remain; drain remaining bytes. - - Debug.Assert(cbBuffer - currentOffset < 4, "Should have 0 - 3 bytes remaining."); - switch ((int)cbBuffer & 3) - { - case 0: - p0 += 0x80u; - break; - - case 1: - p0 += 0x8000u | pbBuffer[currentOffset]; - break; - - case 2: - p0 += 0x800000u | Unsafe.ReadUnaligned(pbBuffer + currentOffset); - break; - - case 3: - p0 += 0x80000000u | Unsafe.ReadUnaligned(pbBuffer + currentOffset) | ((uint)pbBuffer[currentOffset + 2] << 16); - break; - - default: - Debug.Fail("Should not get here."); - break; - } - } - - Block(ref p0, ref p1); - Block(ref p0, ref p1); - - return (((long)p1) << 32) | p0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void Block(ref uint rp0, ref uint rp1) - { - uint p0 = rp0; - uint p1 = rp1; - - p1 ^= p0; - p0 = _rotl(p0, 20); - - p0 += p1; - p1 = _rotl(p1, 9); - - p1 ^= p0; - p0 = _rotl(p0, 27); - - p0 += p1; - p1 = _rotl(p1, 19); - - rp0 = p0; - rp1 = p1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint _rotl(uint value, int shift) - { - // This is expected to be optimized into a single rol (or ror with negated shift value) instruction - return (value << shift) | (value >> (32 - shift)); - } - - public static ulong DefaultSeed { get; } = GenerateSeed(); - - private static ulong GenerateSeed() - { - using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) - { - var bytes = new byte[sizeof(ulong)]; - rng.GetBytes(bytes); - return BitConverter.ToUInt64(bytes, 0); - } - } - } -} diff --git a/src/libraries/Common/tests/Common.Tests.csproj b/src/libraries/Common/tests/Common.Tests.csproj index 6cbd38febe7ad..8a8a8b0f466ff 100644 --- a/src/libraries/Common/tests/Common.Tests.csproj +++ b/src/libraries/Common/tests/Common.Tests.csproj @@ -18,8 +18,6 @@ Link="Common\Interop\Linux\Interop.ProcFsStat.TryReadStatusFile.cs" /> - - diff --git a/src/libraries/Common/tests/Tests/System/MarvinTests.cs b/src/libraries/Common/tests/Tests/System/MarvinTests.cs deleted file mode 100644 index a70ae1aed9dc4..0000000000000 --- a/src/libraries/Common/tests/Tests/System/MarvinTests.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using Test.Cryptography; - -using Xunit; - -namespace Tests.System -{ - public class MarvinTests - { - private const ulong Seed1 = 0x4FB61A001BDBCCLU; - private const ulong Seed2 = 0x804FB61A001BDBCCLU; - private const ulong Seed3 = 0x804FB61A801BDBCCLU; - - private const string TestDataString0Byte = ""; - private const string TestDataString1Byte = "af"; - private const string TestDataString2Byte = "e70f"; - private const string TestDataString3Byte = "37f495"; - private const string TestDataString4Byte = "8642dc59"; - private const string TestDataString5Byte = "153fb79826"; - private const string TestDataString6Byte = "0932e6246c47"; - private const string TestDataString7Byte = "ab427ea8d10fc7"; - - [Theory] - [MemberData(nameof(TestDataAndExpectedHashes))] - public void ComputeHash_Success(ulong seed, string testDataString, ulong expectedHash) - { - var testDataSpan = new Span(testDataString.HexToByteArray()); - long hash = Marvin.ComputeHash(testDataSpan, seed); - Assert.Equal((long)expectedHash, hash); - } - - public static object[][] TestDataAndExpectedHashes = - { - new object[] { Seed1, TestDataString0Byte, 0x30ED35C100CD3C7DLU }, - new object[] { Seed1, TestDataString1Byte, 0x48E73FC77D75DDC1LU }, - new object[] { Seed1, TestDataString2Byte, 0xB5F6E1FC485DBFF8LU }, - new object[] { Seed1, TestDataString3Byte, 0xF0B07C789B8CF7E8LU }, - new object[] { Seed1, TestDataString4Byte, 0x7008F2E87E9CF556LU }, - new object[] { Seed1, TestDataString5Byte, 0xE6C08C6DA2AFA997LU }, - new object[] { Seed1, TestDataString6Byte, 0x6F04BF1A5EA24060LU }, - new object[] { Seed1, TestDataString7Byte, 0xE11847E4F0678C41LU }, - - new object[] { Seed2, TestDataString0Byte, 0x10A9D5D3996FD65DLU }, - new object[] { Seed2, TestDataString1Byte, 0x68201F91960EBF91LU }, - new object[] { Seed2, TestDataString2Byte, 0x64B581631F6AB378LU }, - new object[] { Seed2, TestDataString3Byte, 0xE1F2DFA6E5131408LU }, - new object[] { Seed2, TestDataString4Byte, 0x36289D9654FB49F6LU }, - new object[] { Seed2, TestDataString5Byte, 0xA06114B13464DBDLU }, - new object[] { Seed2, TestDataString6Byte, 0xD6DD5E40AD1BC2EDLU }, - new object[] { Seed2, TestDataString7Byte, 0xE203987DBA252FB3LU }, - - new object[] { Seed3, "00", 0xA37FB0DA2ECAE06CLU }, - new object[] { Seed3, "FF", 0xFECEF370701AE054LU }, - new object[] { Seed3, "00FF", 0xA638E75700048880LU }, - new object[] { Seed3, "FF00", 0xBDFB46D969730E2ALU }, - new object[] { Seed3, "FF00FF", 0x9D8577C0FE0D30BFLU }, - new object[] { Seed3, "00FF00", 0x4F9FBDDE15099497LU }, - new object[] { Seed3, "00FF00FF", 0x24EAA279D9A529CALU }, - new object[] { Seed3, "FF00FF00", 0xD3BEC7726B057943LU }, - new object[] { Seed3, "FF00FF00FF", 0x920B62BBCA3E0B72LU }, - new object[] { Seed3, "00FF00FF00", 0x1D7DDF9DFDF3C1BFLU }, - new object[] { Seed3, "00FF00FF00FF", 0xEC21276A17E821A5LU }, - new object[] { Seed3, "FF00FF00FF00", 0x6911A53CA8C12254LU }, - new object[] { Seed3, "FF00FF00FF00FF", 0xFDFD187B1D3CE784LU }, - new object[] { Seed3, "00FF00FF00FF00", 0x71876F2EFB1B0EE8LU }, - }; - } -} diff --git a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj index aff4f212f738c..23462998e03eb 100644 --- a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj +++ b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj @@ -6,7 +6,6 @@ enable - diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs index 7455ddddfaf56..1ac844403c65d 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborConformanceLevel.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Runtime.InteropServices; using System.Text; namespace System.Formats.Cbor @@ -209,7 +210,21 @@ public static bool RequireCanonicalSimpleValueEncodings(CborConformanceMode conf public static int GetKeyEncodingHashCode(ReadOnlySpan encoding) { - return System.Marvin.ComputeHash32(encoding, System.Marvin.DefaultSeed); + HashCode hash = default; + + // TODO: Use https://github.com/dotnet/runtime/issues/48702 if/when it's available + while (encoding.Length >= sizeof(int)) + { + hash.Add(MemoryMarshal.Read(encoding)); + encoding = encoding.Slice(sizeof(int)); + } + + foreach (byte b in encoding) + { + hash.Add(b); + } + + return hash.ToHashCode(); } public static bool AreEqualKeyEncodings(ReadOnlySpan left, ReadOnlySpan right) diff --git a/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj b/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj index 60cd3de352d3a..39c385c8dbc12 100644 --- a/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj +++ b/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj @@ -68,8 +68,6 @@ Link="Common\System\Net\NegotiationInfoClass.cs" /> - addressAndScopeIdSpan = stackalloc byte[AddressAndScopeIdLength]; - - MemoryMarshal.AsBytes(new ReadOnlySpan(_numbers)).CopyTo(addressAndScopeIdSpan); - Span scopeIdSpan = addressAndScopeIdSpan.Slice(IPAddressParserStatics.IPv6AddressBytes); - bool scopeWritten = BitConverter.TryWriteBytes(scopeIdSpan, _addressOrScopeId); - Debug.Assert(scopeWritten); - - hashCode = Marvin.ComputeHash32( - addressAndScopeIdSpan, - Marvin.DefaultSeed); - } - else - { - // For IPv4 addresses, we use Marvin on the integer representation of the Address. - hashCode = Marvin.ComputeHash32( - MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref _addressOrScopeId, 1)), - Marvin.DefaultSeed); + // For IPv4 addresses, we calculate the hashcode based on address bytes. + // For IPv6 addresses, we also factor in scope ID. + if (IsIPv6) + { + ReadOnlySpan numbers = MemoryMarshal.AsBytes(_numbers); + _hashCode = HashCode.Combine( + MemoryMarshal.Read(numbers), + MemoryMarshal.Read(numbers.Slice(4)), + MemoryMarshal.Read(numbers.Slice(8)), + MemoryMarshal.Read(numbers.Slice(12)), + _addressOrScopeId); + } + else + { + _hashCode = HashCode.Combine(_addressOrScopeId); + } } - _hashCode = hashCode; return _hashCode; } diff --git a/src/libraries/System.Net.Primitives/tests/PalTests/System.Net.Primitives.Pal.Tests.csproj b/src/libraries/System.Net.Primitives/tests/PalTests/System.Net.Primitives.Pal.Tests.csproj index 0d48b7390264b..4652679d91bf6 100644 --- a/src/libraries/System.Net.Primitives/tests/PalTests/System.Net.Primitives.Pal.Tests.csproj +++ b/src/libraries/System.Net.Primitives/tests/PalTests/System.Net.Primitives.Pal.Tests.csproj @@ -32,8 +32,6 @@ Link="Common\System\Net\SocketAddress.cs" /> - - From 24b02289c7a6c5c731d392a43abb1981f59643e7 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Tue, 9 Mar 2021 13:58:16 -0800 Subject: [PATCH 64/83] Enregister EH var that are single def (#47307) * Enable EhWriteThry for SingleDef * If EhWriteThru is enabled, DoNotEnregister if variable is not singleDef * Revert code in ExecutionContext.RunInternal * Revert code in AsyncMethodBuildCore.Start() * Make sure we do not reset lvSingleDef * Consitent display of frame offset misc change in superpmi.py * Use lvEHWriteThruCandidate * Do not enregister EH Var that has single use * do not enregister simdtype * add missing comments * jit format * revert an unintended change * jit format * Add missing comments --- src/coreclr/jit/compiler.h | 23 +++++++++ src/coreclr/jit/jitconfigvalues.h | 2 +- src/coreclr/jit/lclvars.cpp | 48 +++++++++++++++++-- src/coreclr/jit/lsra.cpp | 10 ++-- src/coreclr/jit/lsra.h | 17 +------ src/coreclr/jit/lsrabuild.cpp | 13 +++-- src/coreclr/scripts/superpmi.py | 2 +- .../AsyncMethodBuilderCore.cs | 24 ++++------ .../src/System/Threading/ExecutionContext.cs | 33 +++++-------- 9 files changed, 101 insertions(+), 71 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 971fd105ea60a..e6d386e760013 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -454,6 +454,11 @@ class LclVarDsc // before lvaMarkLocalVars: identifies ref type locals that can get type updates // after lvaMarkLocalVars: identifies locals that are suitable for optAddCopies + unsigned char lvEhWriteThruCandidate : 1; // variable has a single def and hence is a register candidate if + // if it is an EH variable + + unsigned char lvDisqualifyForEhWriteThru : 1; // tracks variable that are disqualified from register candidancy + #if ASSERTION_PROP unsigned char lvDisqualify : 1; // variable is no longer OK for add copy optimization unsigned char lvVolatileHint : 1; // hint for AssertionProp @@ -7369,6 +7374,24 @@ class Compiler void raMarkStkVars(); +#if FEATURE_PARTIAL_SIMD_CALLEE_SAVE +#if defined(TARGET_AMD64) + static bool varTypeNeedsPartialCalleeSave(var_types type) + { + return (type == TYP_SIMD32); + } +#elif defined(TARGET_ARM64) + static bool varTypeNeedsPartialCalleeSave(var_types type) + { + // ARM64 ABI FP Callee save registers only require Callee to save lower 8 Bytes + // For SIMD types longer than 8 bytes Caller is responsible for saving and restoring Upper bytes. + return ((type == TYP_SIMD16) || (type == TYP_SIMD12)); + } +#else // !defined(TARGET_AMD64) && !defined(TARGET_ARM64) +#error("Unknown target architecture for FEATURE_SIMD") +#endif // !defined(TARGET_AMD64) && !defined(TARGET_ARM64) +#endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE + protected: // Some things are used by both LSRA and regpredict allocators. diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index eb89d630e67fa..478aa4d8d0bd8 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -274,7 +274,7 @@ CONFIG_INTEGER(EnablePOPCNT, W("EnablePOPCNT"), 1) // Enable POPCNT CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 0) #endif // !defined(TARGET_AMD64) && !defined(TARGET_X86) -CONFIG_INTEGER(EnableEHWriteThru, W("EnableEHWriteThru"), 0) // Enable the register allocator to support EH-write thru: +CONFIG_INTEGER(EnableEHWriteThru, W("EnableEHWriteThru"), 1) // Enable the register allocator to support EH-write thru: // partial enregistration of vars exposed on EH boundaries CONFIG_INTEGER(EnableMultiRegLocals, W("EnableMultiRegLocals"), 1) // Enable the enregistration of locals that are // defined or used in a multireg context. diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index ea51815de2e03..ca6e34a083e1c 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -2614,14 +2614,16 @@ void Compiler::lvaSetVarLiveInOutOfHandler(unsigned varNum) { noway_assert(lvaTable[i].lvIsStructField); lvaTable[i].lvLiveInOutOfHndlr = 1; - if (!lvaEnregEHVars) + // For now, only enregister an EH Var if it is a single def and whose refCnt > 1. + if (!lvaEnregEHVars || !lvaTable[i].lvEhWriteThruCandidate || lvaTable[i].lvRefCnt() <= 1) { lvaSetVarDoNotEnregister(i DEBUGARG(DNER_LiveInOutOfHandler)); } } } - if (!lvaEnregEHVars) + // For now, only enregister an EH Var if it is a single def and whose refCnt > 1. + if (!lvaEnregEHVars || !varDsc->lvEhWriteThruCandidate || varDsc->lvRefCnt() <= 1) { lvaSetVarDoNotEnregister(varNum DEBUGARG(DNER_LiveInOutOfHandler)); } @@ -4040,7 +4042,7 @@ void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt, /* Record if the variable has a single def or not */ - if (!varDsc->lvDisqualify) // If this variable is already disqualified we can skip this + if (!varDsc->lvDisqualify) // If this variable is already disqualified, we can skip this { if (tree->gtFlags & GTF_VAR_DEF) // Is this is a def of our variable { @@ -4075,6 +4077,34 @@ void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt, BlockSetOps::AddElemD(this, varDsc->lvRefBlks, block->bbNum); } } + + if (!varDsc->lvDisqualifyForEhWriteThru) // If this EH var already disqualified, we can skip this + { + if (tree->gtFlags & GTF_VAR_DEF) // Is this is a def of our variable + { + bool bbInALoop = (block->bbFlags & BBF_BACKWARD_JUMP) != 0; + bool bbIsReturn = block->bbJumpKind == BBJ_RETURN; + bool needsExplicitZeroInit = fgVarNeedsExplicitZeroInit(lclNum, bbInALoop, bbIsReturn); + + if (varDsc->lvEhWriteThruCandidate || needsExplicitZeroInit) + { + varDsc->lvEhWriteThruCandidate = false; + varDsc->lvDisqualifyForEhWriteThru = true; + } + else + { +#if FEATURE_PARTIAL_SIMD_CALLEE_SAVE + // TODO-CQ: If the varType needs partial callee save, conservatively do not enregister + // such variable. In future, need to enable enregisteration for such variables. + if (!varTypeNeedsPartialCalleeSave(varDsc->lvType)) +#endif + { + varDsc->lvEhWriteThruCandidate = true; + } + } + } + } + #endif // ASSERTION_PROP bool allowStructs = false; @@ -4178,6 +4208,8 @@ void Compiler::lvaMarkLocalVars(BasicBlock* block, bool isRecompute) Compiler::fgWalkResult PreOrderVisit(GenTree** use, GenTree* user) { + // TODO: Stop passing isRecompute once we are sure that this assert is never hit. + assert(!m_isRecompute); m_compiler->lvaMarkLclRefs(*use, m_block, m_stmt, m_isRecompute); return WALK_CONTINUE; } @@ -4437,7 +4469,13 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers) // Set initial value for lvSingleDef for explicit and implicit // argument locals as they are "defined" on entry. - varDsc->lvSingleDef = varDsc->lvIsParam; + // However, if we are just recomputing the ref counts, retain the value + // that was set by past phases. + if (!isRecompute) + { + varDsc->lvSingleDef = varDsc->lvIsParam; + varDsc->lvEhWriteThruCandidate = varDsc->lvIsParam; + } } // Remember current state of generic context use, and prepare @@ -7194,7 +7232,7 @@ void Compiler::lvaDumpFrameLocation(unsigned lclNum) baseReg = EBPbased ? REG_FPBASE : REG_SPBASE; #endif - printf("[%2s%1s0x%02X] ", getRegName(baseReg), (offset < 0 ? "-" : "+"), (offset < 0 ? -offset : offset)); + printf("[%2s%1s%02XH] ", getRegName(baseReg), (offset < 0 ? "-" : "+"), (offset < 0 ? -offset : offset)); } /***************************************************************************** diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 2fb95562f7abe..bbcc44a281404 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -1781,7 +1781,7 @@ void LinearScan::identifyCandidates() if (varDsc->lvLiveInOutOfHndlr) { - newInt->isWriteThru = true; + newInt->isWriteThru = varDsc->lvEhWriteThruCandidate; setIntervalAsSpilled(newInt); } @@ -1796,7 +1796,7 @@ void LinearScan::identifyCandidates() // Additionally, when we are generating code for a target with partial SIMD callee-save // (AVX on non-UNIX amd64 and 16-byte vectors on arm64), we keep a separate set of the // LargeVectorType vars. - if (varTypeNeedsPartialCalleeSave(varDsc->lvType)) + if (Compiler::varTypeNeedsPartialCalleeSave(varDsc->lvType)) { largeVectorVarCount++; VarSetOps::AddElemD(compiler, largeVectorVars, varDsc->lvVarIndex); @@ -5050,7 +5050,7 @@ void LinearScan::processBlockEndLocations(BasicBlock* currentBlock) } #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE // Ensure that we have no partially-spilled large vector locals. - assert(!varTypeNeedsPartialCalleeSave(interval->registerType) || !interval->isPartiallySpilled); + assert(!Compiler::varTypeNeedsPartialCalleeSave(interval->registerType) || !interval->isPartiallySpilled); #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE } INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_END_BB)); @@ -6922,7 +6922,7 @@ void LinearScan::insertUpperVectorSave(GenTree* tree, } LclVarDsc* varDsc = compiler->lvaTable + lclVarInterval->varNum; - assert(varTypeNeedsPartialCalleeSave(varDsc->lvType)); + assert(Compiler::varTypeNeedsPartialCalleeSave(varDsc->lvType)); // On Arm64, we must always have a register to save the upper half, // while on x86 we can spill directly to memory. @@ -7003,7 +7003,7 @@ void LinearScan::insertUpperVectorRestore(GenTree* tree, // lclVar as spilled). assert(lclVarReg != REG_NA); LclVarDsc* varDsc = compiler->lvaTable + lclVarInterval->varNum; - assert(varTypeNeedsPartialCalleeSave(varDsc->lvType)); + assert(Compiler::varTypeNeedsPartialCalleeSave(varDsc->lvType)); GenTree* restoreLcl = nullptr; restoreLcl = compiler->gtNewLclvNode(lclVarInterval->varNum, varDsc->lvType); diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index f381e223ae781..bcf6843796362 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -985,7 +985,7 @@ class LinearScan : public LinearScanInterface void resolveConflictingDefAndUse(Interval* interval, RefPosition* defRefPosition); - void buildRefPositionsForNode(GenTree* tree, BasicBlock* block, LsraLocation loc); + void buildRefPositionsForNode(GenTree* tree, LsraLocation loc); #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE void buildUpperVectorSaveRefPositions(GenTree* tree, LsraLocation currentLoc, regMaskTP fpCalleeKillSet); @@ -1497,23 +1497,10 @@ class LinearScan : public LinearScanInterface #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE #if defined(TARGET_AMD64) - static bool varTypeNeedsPartialCalleeSave(var_types type) - { - return (type == TYP_SIMD32); - } static const var_types LargeVectorSaveType = TYP_SIMD16; #elif defined(TARGET_ARM64) - static bool varTypeNeedsPartialCalleeSave(var_types type) - { - // ARM64 ABI FP Callee save registers only require Callee to save lower 8 Bytes - // For SIMD types longer than 8 bytes Caller is responsible for saving and restoring Upper bytes. - return ((type == TYP_SIMD16) || (type == TYP_SIMD12)); - } - static const var_types LargeVectorSaveType = TYP_DOUBLE; -#else // !defined(TARGET_AMD64) && !defined(TARGET_ARM64) -#error("Unknown target architecture for FEATURE_SIMD") + static const var_types LargeVectorSaveType = TYP_DOUBLE; #endif // !defined(TARGET_AMD64) && !defined(TARGET_ARM64) - // Set of large vector (TYP_SIMD32 on AVX) variables. VARSET_TP largeVectorVars; // Set of large vector (TYP_SIMD32 on AVX) variables to consider for callee-save registers. diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index f8c9948d8190b..32441ad422aa3 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -1160,7 +1160,7 @@ bool LinearScan::buildKillPositionsForNode(GenTree* tree, LsraLocation currentLo { LclVarDsc* varDsc = compiler->lvaGetDescByTrackedIndex(varIndex); #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE - if (varTypeNeedsPartialCalleeSave(varDsc->lvType)) + if (Compiler::varTypeNeedsPartialCalleeSave(varDsc->lvType)) { if (!VarSetOps::IsMember(compiler, largeVectorCalleeSaveCandidateVars, varIndex)) { @@ -1424,7 +1424,7 @@ void LinearScan::buildInternalRegisterUses() void LinearScan::makeUpperVectorInterval(unsigned varIndex) { Interval* lclVarInterval = getIntervalForLocalVar(varIndex); - assert(varTypeNeedsPartialCalleeSave(lclVarInterval->registerType)); + assert(Compiler::varTypeNeedsPartialCalleeSave(lclVarInterval->registerType)); Interval* newInt = newInterval(LargeVectorSaveType); newInt->relatedInterval = lclVarInterval; newInt->isUpperVector = true; @@ -1506,7 +1506,7 @@ void LinearScan::buildUpperVectorSaveRefPositions(GenTree* tree, LsraLocation cu for (RefInfoListNode *listNode = defList.Begin(), *end = defList.End(); listNode != end; listNode = listNode->Next()) { - if (varTypeNeedsPartialCalleeSave(listNode->treeNode->TypeGet())) + if (Compiler::varTypeNeedsPartialCalleeSave(listNode->treeNode->TypeGet())) { // In the rare case where such an interval is live across nested calls, we don't need to insert another. if (listNode->ref->getInterval()->recentRefPosition->refType != RefTypeUpperVectorSave) @@ -1637,10 +1637,9 @@ int LinearScan::ComputeAvailableSrcCount(GenTree* node) // // Arguments: // tree - The node for which we are building RefPositions -// block - The BasicBlock in which the node resides // currentLoc - The LsraLocation of the given node // -void LinearScan::buildRefPositionsForNode(GenTree* tree, BasicBlock* block, LsraLocation currentLoc) +void LinearScan::buildRefPositionsForNode(GenTree* tree, LsraLocation currentLoc) { // The LIR traversal doesn't visit GT_LIST or GT_ARGPLACE nodes. // GT_CLS_VAR nodes should have been eliminated by rationalizer. @@ -2351,7 +2350,7 @@ void LinearScan::buildIntervals() node->SetRegNum(node->GetRegNum()); #endif - buildRefPositionsForNode(node, block, currentLoc); + buildRefPositionsForNode(node, currentLoc); #ifdef DEBUG if (currentLoc > maxNodeLocation) @@ -3232,7 +3231,7 @@ void LinearScan::BuildStoreLocDef(GenTreeLclVarCommon* storeLoc, def->regOptional = true; } #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE - if (varTypeNeedsPartialCalleeSave(varDefInterval->registerType)) + if (Compiler::varTypeNeedsPartialCalleeSave(varDefInterval->registerType)) { varDefInterval->isPartiallySpilled = false; } diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index 66beb3f1213d5..5f1edd95270ea 100755 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -1346,7 +1346,7 @@ def save_repro_mc_files(temp_location, coreclr_args, repro_base_command_line): shutil.copy2(item, repro_location) logging.info("") - logging.info("Repro .mc files created for failures:") + logging.info("Repro {} .mc file(s) created for failures:".format(len(repro_files))) for item in repro_files: logging.info(item) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs index 6d598e9929621..19b3d82686671 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilderCore.cs @@ -25,17 +25,13 @@ public static void Start(ref TStateMachine stateMachine) where TS ThrowHelper.ThrowArgumentNullException(ExceptionArgument.stateMachine); } - // enregistrer variables with 0 post-fix so they can be used in registers without EH forcing them to stack - // Capture references to Thread Contexts - Thread currentThread0 = Thread.CurrentThread; - Thread currentThread = currentThread0; - ExecutionContext? previousExecutionCtx0 = currentThread0._executionContext; + Thread currentThread = Thread.CurrentThread; // Store current ExecutionContext and SynchronizationContext as "previousXxx". // This allows us to restore them and undo any Context changes made in stateMachine.MoveNext // so that they won't "leak" out of the first await. - ExecutionContext? previousExecutionCtx = previousExecutionCtx0; - SynchronizationContext? previousSyncCtx = currentThread0._synchronizationContext; + ExecutionContext? previousExecutionCtx = currentThread._executionContext; + SynchronizationContext? previousSyncCtx = currentThread._synchronizationContext; try { @@ -43,21 +39,17 @@ public static void Start(ref TStateMachine stateMachine) where TS } finally { - // Re-enregistrer variables post EH with 1 post-fix so they can be used in registers rather than from stack - SynchronizationContext? previousSyncCtx1 = previousSyncCtx; - Thread currentThread1 = currentThread; // The common case is that these have not changed, so avoid the cost of a write barrier if not needed. - if (previousSyncCtx1 != currentThread1._synchronizationContext) + if (previousSyncCtx != currentThread._synchronizationContext) { // Restore changed SynchronizationContext back to previous - currentThread1._synchronizationContext = previousSyncCtx1; + currentThread._synchronizationContext = previousSyncCtx; } - ExecutionContext? previousExecutionCtx1 = previousExecutionCtx; - ExecutionContext? currentExecutionCtx1 = currentThread1._executionContext; - if (previousExecutionCtx1 != currentExecutionCtx1) + ExecutionContext? currentExecutionCtx = currentThread._executionContext; + if (previousExecutionCtx != currentExecutionCtx) { - ExecutionContext.RestoreChangedContextToThread(currentThread1, previousExecutionCtx1, currentExecutionCtx1); + ExecutionContext.RestoreChangedContextToThread(currentThread, previousExecutionCtx, currentExecutionCtx); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs index e1950bd48587d..30b6f9e2561e3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs @@ -153,23 +153,18 @@ internal static void RunInternal(ExecutionContext? executionContext, ContextCall // Note: Manual enregistering may be addressed by "Exception Handling Write Through Optimization" // https://github.com/dotnet/runtime/blob/main/docs/design/features/eh-writethru.md - // Enregister variables with 0 post-fix so they can be used in registers without EH forcing them to stack - // Capture references to Thread Contexts - Thread currentThread0 = Thread.CurrentThread; - Thread currentThread = currentThread0; - ExecutionContext? previousExecutionCtx0 = currentThread0._executionContext; + // Enregister previousExecutionCtx0 so they can be used in registers without EH forcing them to stack + + Thread currentThread = Thread.CurrentThread; + ExecutionContext? previousExecutionCtx0 = currentThread._executionContext; if (previousExecutionCtx0 != null && previousExecutionCtx0.m_isDefault) { // Default is a null ExecutionContext internally previousExecutionCtx0 = null; } - // Store current ExecutionContext and SynchronizationContext as "previousXxx". - // This allows us to restore them and undo any Context changes made in callback.Invoke - // so that they won't "leak" back into caller. - // These variables will cross EH so be forced to stack ExecutionContext? previousExecutionCtx = previousExecutionCtx0; - SynchronizationContext? previousSyncCtx = currentThread0._synchronizationContext; + SynchronizationContext? previousSyncCtx = currentThread._synchronizationContext; if (executionContext != null && executionContext.m_isDefault) { @@ -177,9 +172,9 @@ internal static void RunInternal(ExecutionContext? executionContext, ContextCall executionContext = null; } - if (previousExecutionCtx0 != executionContext) + if (previousExecutionCtx != executionContext) { - RestoreChangedContextToThread(currentThread0, executionContext, previousExecutionCtx0); + RestoreChangedContextToThread(currentThread, executionContext, previousExecutionCtx); } ExceptionDispatchInfo? edi = null; @@ -195,21 +190,17 @@ internal static void RunInternal(ExecutionContext? executionContext, ContextCall edi = ExceptionDispatchInfo.Capture(ex); } - // Re-enregistrer variables post EH with 1 post-fix so they can be used in registers rather than from stack - SynchronizationContext? previousSyncCtx1 = previousSyncCtx; - Thread currentThread1 = currentThread; // The common case is that these have not changed, so avoid the cost of a write barrier if not needed. - if (currentThread1._synchronizationContext != previousSyncCtx1) + if (currentThread._synchronizationContext != previousSyncCtx) { // Restore changed SynchronizationContext back to previous - currentThread1._synchronizationContext = previousSyncCtx1; + currentThread._synchronizationContext = previousSyncCtx; } - ExecutionContext? previousExecutionCtx1 = previousExecutionCtx; - ExecutionContext? currentExecutionCtx1 = currentThread1._executionContext; - if (currentExecutionCtx1 != previousExecutionCtx1) + ExecutionContext? currentExecutionCtx = currentThread._executionContext; + if (currentExecutionCtx != previousExecutionCtx) { - RestoreChangedContextToThread(currentThread1, previousExecutionCtx1, currentExecutionCtx1); + RestoreChangedContextToThread(currentThread, previousExecutionCtx, currentExecutionCtx); } // If exception was thrown by callback, rethrow it now original contexts are restored From ea2d78a0e0d4f04c1a2206e2488367b1744183a5 Mon Sep 17 00:00:00 2001 From: Drew Scoggins Date: Tue, 9 Mar 2021 14:06:18 -0800 Subject: [PATCH 65/83] Add amd and Surface arm64 perf runs (#49389) * Add better queue selection support * Add logical machine to job name * Add logical machine for Arm64 runs * Fix log naming --- eng/common/performance/performance-setup.ps1 | 26 ++++---- eng/common/performance/performance-setup.sh | 24 ++++---- eng/pipelines/coreclr/perf.yml | 60 ++++++++++++++++++- eng/pipelines/coreclr/templates/perf-job.yml | 6 +- .../coreclr/templates/run-performance-job.yml | 8 +-- .../coreclr/templates/run-scenarios-job.yml | 4 +- 6 files changed, 90 insertions(+), 38 deletions(-) diff --git a/eng/common/performance/performance-setup.ps1 b/eng/common/performance/performance-setup.ps1 index c6f1045e3d7f6..9a64b07e692f6 100644 --- a/eng/common/performance/performance-setup.ps1 +++ b/eng/common/performance/performance-setup.ps1 @@ -18,7 +18,8 @@ Param( [switch] $Internal, [switch] $Compare, [string] $MonoDotnet="", - [string] $Configurations="CompilationMode=$CompilationMode RunKind=$Kind" + [string] $Configurations="CompilationMode=$CompilationMode RunKind=$Kind", + [string] $LogicalMachine="" ) $RunFromPerformanceRepo = ($Repository -eq "dotnet/performance") -or ($Repository -eq "dotnet-performance") @@ -33,26 +34,23 @@ $Creator = $env:BUILD_DEFINITIONNAME $PerfLabArguments = "" $HelixSourcePrefix = "pr" -$Queue = "Windows.10.Amd64.ClientRS4.DevEx.15.8.Open" - -# TODO: Implement a better logic to determine if Framework is .NET Core or >= .NET 5. -if ($Framework.StartsWith("netcoreapp") -or ($Framework -eq "net5.0")) { - $Queue = "Windows.10.Amd64.ClientRS5.Open" -} - -if ($Compare) { - $Queue = "Windows.10.Amd64.19H1.Tiger.Perf.Open" - $PerfLabArguments = "" - $ExtraBenchmarkDotNetArguments = "" -} +$Queue = "" if ($Internal) { - $Queue = "Windows.10.Amd64.19H1.Tiger.Perf" + switch ($LogicalMachine) { + "perftiger" { $Queue = "Windows.10.Amd64.19H1.Tiger.Perf" } + "perfowl" { $Queue = "Windows.10.Amd64.20H2.Owl.Perf" } + "perfsurf" { $Queue = "Windows.10.Arm64.Perf.Surf" } + Default { $Queue = "Windows.10.Amd64.19H1.Tiger.Perf" } + } $PerfLabArguments = "--upload-to-perflab-container" $ExtraBenchmarkDotNetArguments = "" $Creator = "" $HelixSourcePrefix = "official" } +else { + $Queue = "Windows.10.Amd64.ClientRS4.DevEx.15.8.Open" +} if($MonoInterpreter) { diff --git a/eng/common/performance/performance-setup.sh b/eng/common/performance/performance-setup.sh index cd4f233d57e6d..33b60b5033742 100755 --- a/eng/common/performance/performance-setup.sh +++ b/eng/common/performance/performance-setup.sh @@ -27,6 +27,7 @@ using_mono=false wasm_runtime_loc= using_wasm=false use_latest_dotnet=false +logical_machine= while (($# > 0)); do lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" @@ -55,6 +56,10 @@ while (($# > 0)); do compilation_mode=$2 shift 2 ;; + --logicalmachine) + logical_machine=$2 + shift 2 + ;; --repository) repository=$2 shift 2 @@ -179,19 +184,6 @@ queue=Ubuntu.1804.Amd64.Open creator=$BUILD_DEFINITIONNAME helix_source_prefix="pr" -if [[ "$compare" == true ]]; then - extra_benchmark_dotnet_arguments= - perflab_arguments= - - # No open queues for arm64 - if [[ "$architecture" = "arm64" ]]; then - echo "Compare not available for arm64" - exit 1 - fi - - queue=Ubuntu.1804.Amd64.Tiger.Perf.Open -fi - if [[ "$internal" == true ]]; then perflab_arguments="--upload-to-perflab-container" helix_source_prefix="official" @@ -201,7 +193,11 @@ if [[ "$internal" == true ]]; then if [[ "$architecture" = "arm64" ]]; then queue=Ubuntu.1804.Arm64.Perf else - queue=Ubuntu.1804.Amd64.Tiger.Perf + if [[ "$logical_machine" = "perfowl" ]]; then + queue=Ubuntu.1804.Amd64.Owl.Perf + else + queue=Ubuntu.1804.Amd64.Tiger.Perf + fi fi if [[ "$alpine" = "true" ]]; then diff --git a/eng/pipelines/coreclr/perf.yml b/eng/pipelines/coreclr/perf.yml index 80891354ecb07..879ff40c57d73 100644 --- a/eng/pipelines/coreclr/perf.yml +++ b/eng/pipelines/coreclr/perf.yml @@ -69,6 +69,7 @@ jobs: projectFile: microbenchmarks.proj runKind: micro_mono runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml + logicalmachine: 'perfa64' - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'Schedule')) }}: @@ -83,6 +84,7 @@ jobs: - windows_x86 - Linux_arm64 - Linux_musl_x64 + - windows_arm64 jobParameters: testGroup: perf @@ -131,6 +133,7 @@ jobs: projectFile: microbenchmarks.proj runKind: micro_mono runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml + logicalmachine: 'perftiger' # run mono interpreter perf job - template: /eng/pipelines/common/platform-matrix.yml @@ -148,6 +151,7 @@ jobs: projectFile: microbenchmarks.proj runKind: micro_mono runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml + logicalmachine: 'perftiger' # run mono wasm microbenchmarks perf job - template: /eng/pipelines/common/platform-matrix.yml @@ -165,9 +169,10 @@ jobs: projectFile: microbenchmarks.proj runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml + logicalmachine: 'perftiger' - # run coreclr microbenchmarks perf job + # run coreclr perftiger microbenchmarks perf job - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -177,7 +182,6 @@ jobs: - Linux_x64 - windows_x64 - windows_x86 - - Linux_arm64 - Linux_musl_x64 jobParameters: testGroup: perf @@ -185,6 +189,56 @@ jobs: projectFile: microbenchmarks.proj runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml + logicalmachine: 'perftiger' + + # run coreclr perfowl microbenchmarks perf job + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml + buildConfig: release + runtimeFlavor: coreclr + platforms: + - Linux_x64 + - windows_x64 + jobParameters: + testGroup: perf + liveLibrariesBuildConfig: Release + projectFile: microbenchmarks.proj + runKind: micro + runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml + logicalmachine: 'perfowl' + +# run coreclr Linux arm64 microbenchmarks perf job + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml + buildConfig: release + runtimeFlavor: coreclr + platforms: + - Linux_arm64 + jobParameters: + testGroup: perf + liveLibrariesBuildConfig: Release + projectFile: microbenchmarks.proj + runKind: micro + runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml + logicalmachine: 'perfa64' + +# run coreclr Windows arm64 microbenchmarks perf job + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml + buildConfig: release + runtimeFlavor: coreclr + platforms: + - windows_arm64 + jobParameters: + testGroup: perf + liveLibrariesBuildConfig: Release + projectFile: microbenchmarks.proj + runKind: micro + runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml + logicalmachine: 'perfsurf' # run coreclr crossgen perf job - template: /eng/pipelines/common/platform-matrix.yml @@ -202,6 +256,7 @@ jobs: projectFile: crossgen_perf.proj runKind: crossgen_scenarios runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml + logicalmachine: 'perftiger' # run mono wasm blazor perf job - template: /eng/pipelines/common/platform-matrix.yml @@ -219,4 +274,5 @@ jobs: runKind: blazor_scenarios runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml additionalSetupParameters: '--latestdotnet' + logicalmachine: 'perftiger' diff --git a/eng/pipelines/coreclr/templates/perf-job.yml b/eng/pipelines/coreclr/templates/perf-job.yml index dd1105546ccfc..ef7bf235269f0 100644 --- a/eng/pipelines/coreclr/templates/perf-job.yml +++ b/eng/pipelines/coreclr/templates/perf-job.yml @@ -15,6 +15,7 @@ parameters: runKind: '' runJobTemplate: '/eng/pipelines/coreclr/templates/run-performance-job.yml' additionalSetupParameters: '' + logicalMachine: '' ### Perf job @@ -25,8 +26,8 @@ jobs: - template: ${{ parameters.runJobTemplate }} parameters: # Compute job name from template parameters - jobName: ${{ format('perfbuild_{0}{1}_{2}_{3}_{4}_{5}_{6}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind) }} - displayName: ${{ format('Performance {0}{1} {2} {3} {4} {5} {6}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind) }} + jobName: ${{ format('perfbuild_{0}{1}_{2}_{3}_{4}_{5}_{6}_{7}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind, parameters.logicalMachine) }} + displayName: ${{ format('Performance {0}{1} {2} {3} {4} {5} {6} {7}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind, parameters.logicalMachine) }} pool: ${{ parameters.pool }} buildConfig: ${{ parameters.buildConfig }} archType: ${{ parameters.archType }} @@ -40,6 +41,7 @@ jobs: runKind: ${{ parameters.runKind }} additionalSetupParameters: ${{ parameters.additionalSetupParameters }} container: ${{ parameters.container }} + logicalmachine: ${{ parameters.logicalmachine }} # Test job depends on the corresponding build job dependsOn: - ${{ format('coreclr_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index 17ef611519b25..4a8c44e6a6f3c 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -20,7 +20,7 @@ parameters: codeGenType: 'JIT' # optional -- Decides on the codegen technology if running on mono projectFile: 'microbenchmarks.proj' # optional -- project file to build helix workitems runKind: '' # required -- test category - + logicalMachine: '' # required -- Used to specify a which pool of machines the test should run against jobs: - template: xplat-pipeline-job.yml parameters: @@ -111,11 +111,11 @@ jobs: _Framework: ${{ framework }} steps: - ${{ parameters.steps }} - - powershell: $(Build.SourcesDirectory)\eng\common\performance\performance-setup.ps1 $(IsInternal)$(Interpreter) -Framework $(_Framework) -Kind ${{ parameters.runKind }} ${{ parameters.extraSetupParameters }} + - powershell: $(Build.SourcesDirectory)\eng\common\performance\performance-setup.ps1 $(IsInternal)$(Interpreter) -Framework $(_Framework) -Kind ${{ parameters.runKind }} -LogicalMachine ${{ parameters.logicalMachine }} ${{ parameters.extraSetupParameters }} displayName: Performance Setup (Windows) condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} - - script: $(Build.SourcesDirectory)/eng/common/performance/performance-setup.sh $(IsInternal)$(Interpreter) --framework $(_Framework) --kind ${{ parameters.runKind }} ${{ parameters.extraSetupParameters }} + - script: $(Build.SourcesDirectory)/eng/common/performance/performance-setup.sh $(IsInternal)$(Interpreter) --framework $(_Framework) --kind ${{ parameters.runKind }} --logicalmachine ${{ parameters.logicalMachine }} ${{ parameters.extraSetupParameters }} displayName: Performance Setup (Unix) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} @@ -139,6 +139,6 @@ jobs: displayName: Publish Logs inputs: targetPath: $(Build.SourcesDirectory)/artifacts/log - artifactName: 'Performance_Run_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}' + artifactName: 'Performance_Run_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}_${{ parameters.logicalMachine }}' continueOnError: true condition: always() diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index 0e98ed830f29e..9b5cb92043fb7 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -88,11 +88,11 @@ jobs: steps: - ${{ parameters.steps }} # run performance-setup - - powershell: $(Build.SourcesDirectory)\eng\common\performance\performance-setup.ps1 $(IsInternal) -Framework $(_Framework) -Kind ${{ parameters.runKind }} ${{ parameters.extraSetupParameters }} ${{ parameters.additionalSetupParameters }} + - powershell: $(Build.SourcesDirectory)\eng\common\performance\performance-setup.ps1 $(IsInternal) -Framework $(_Framework) -Kind ${{ parameters.runKind }} -LogicalMachine ${{ parameters.logicalMachine }} ${{ parameters.extraSetupParameters }} ${{ parameters.additionalSetupParameters }} displayName: Performance Setup (Windows) condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} - - script: $(Build.SourcesDirectory)/eng/common/performance/performance-setup.sh $(IsInternal) --framework $(_Framework) --kind ${{ parameters.runKind }} ${{ parameters.extraSetupParameters }} ${{ parameters.additionalSetupParameters }} + - script: $(Build.SourcesDirectory)/eng/common/performance/performance-setup.sh $(IsInternal) --framework $(_Framework) --kind ${{ parameters.runKind }} --logicalmachine ${{ parameters.logicalMachine }} ${{ parameters.extraSetupParameters }} ${{ parameters.additionalSetupParameters }} displayName: Performance Setup (Linux) condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} From f7072ecfd44c52a1de5c8d71b2ead35194d8b7d0 Mon Sep 17 00:00:00 2001 From: Juan Hoyos Date: Tue, 9 Mar 2021 14:13:54 -0800 Subject: [PATCH 66/83] Make sure event generation is incremental (#48903) --- eng/native/functions.cmake | 7 +++++-- src/coreclr/vm/eventing/CMakeLists.txt | 7 +++++-- src/coreclr/vm/eventing/EtwProvider/CMakeLists.txt | 8 ++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake index 9c2cc0c7dee2b..f39fb67bd0cf5 100644 --- a/eng/native/functions.cmake +++ b/eng/native/functions.cmake @@ -468,9 +468,12 @@ function(generate_module_index Target ModuleIndexFile) set(scriptExt ".sh") endif() + set(index_timestamp ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${Target}_index.timestamp) + add_custom_command( - OUTPUT ${ModuleIndexFile} + OUTPUT ${index_timestamp} COMMAND ${CLR_ENG_NATIVE_DIR}/genmoduleindex${scriptExt} $ ${ModuleIndexFile} + COMMAND ${CMAKE_COMMAND} -E touch ${index_timestamp} DEPENDS ${Target} COMMENT "Generating ${Target} module index file -> ${ModuleIndexFile}" ) @@ -482,7 +485,7 @@ function(generate_module_index Target ModuleIndexFile) add_custom_target( ${Target}_module_index_header - DEPENDS ${ModuleIndexFile} + DEPENDS ${index_timestamp} ) endfunction(generate_module_index) diff --git a/src/coreclr/vm/eventing/CMakeLists.txt b/src/coreclr/vm/eventing/CMakeLists.txt index fccfa86aef3ba..1e27a3c069342 100644 --- a/src/coreclr/vm/eventing/CMakeLists.txt +++ b/src/coreclr/vm/eventing/CMakeLists.txt @@ -24,14 +24,17 @@ endif() set(GENEVENTING_SCRIPT ${CLR_DIR}/scripts/genEventing.py) -add_custom_target(eventing_headers - ${PYTHON_EXECUTABLE} ${GENEVENTING_SCRIPT} --man ${EVENT_MANIFEST} --inc ${GENERATED_INCLUDE_DIR} --dummy ${GENERATED_INCLUDE_DIR}/etmdummy.h ${NONEXTERN_ARG} ${NOXPLATHEADER_ARG} +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/eventing_headers.timestamp + COMMAND ${PYTHON_EXECUTABLE} ${GENEVENTING_SCRIPT} --man ${EVENT_MANIFEST} --inc ${GENERATED_INCLUDE_DIR} --dummy ${GENERATED_INCLUDE_DIR}/etmdummy.h ${NONEXTERN_ARG} ${NOXPLATHEADER_ARG} + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/eventing_headers.timestamp DEPENDS ${EVENT_MANIFEST} ${GENEVENTING_SCRIPT} VERBATIM ) set_source_files_properties(${EventingHeaders} PROPERTIES GENERATED TRUE) +add_custom_target(eventing_headers DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/eventing_headers.timestamp) add_dependencies(eventing_headers eventprovider) add_subdirectory(eventpipe) diff --git a/src/coreclr/vm/eventing/EtwProvider/CMakeLists.txt b/src/coreclr/vm/eventing/EtwProvider/CMakeLists.txt index 6545b03117e5f..3bc2b8c675e5e 100644 --- a/src/coreclr/vm/eventing/EtwProvider/CMakeLists.txt +++ b/src/coreclr/vm/eventing/EtwProvider/CMakeLists.txt @@ -13,6 +13,10 @@ set (ETW_PROVIDER_OUTPUTS set_source_files_properties(${ETW_PROVIDER_OUTPUTS} PROPERTIES GENERATED TRUE) -add_custom_target(eventprovider - ${PYTHON_EXECUTABLE} ${ETW_PROVIDER_SCRIPT} --man ${EVENT_MANIFEST} --exc ${EVENT_EXCLUSIONS} --intermediate ${GENERATED_INCLUDE_DIR} +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/eventprovider.timestamp + COMMAND ${PYTHON_EXECUTABLE} ${ETW_PROVIDER_SCRIPT} --man ${EVENT_MANIFEST} --exc ${EVENT_EXCLUSIONS} --intermediate ${GENERATED_INCLUDE_DIR} + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/eventprovider.timestamp DEPENDS ${EVENT_MANIFEST} ${EVENT_EXCLUSIONS} ${ETW_PROVIDER_SCRIPT}) + +add_custom_target(eventprovider DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/eventprovider.timestamp) From 0ab99cee3d118d42519548ce91ddae9645e98bfc Mon Sep 17 00:00:00 2001 From: TimothyByrd <55807828+TimothyByrd@users.noreply.github.com> Date: Tue, 9 Mar 2021 15:29:00 -0800 Subject: [PATCH 67/83] Make 303 redirects do GET like Net Framework (#49095) * Make 303 redirects do GET like Net Framework In Net Framework, PUT redirects on a 303 do a GET. Net 5.0 breaks compatibility with this. See https://github.com/dotnet/runtime/issues/28998 This commit causes redirects of a 303 to do a GET for all methods except HEAD. Co-authored-by: Timothy Byrd --- .../Net/Http/HttpClientHandlerTest.AutoRedirect.cs | 9 ++++++++- .../Net/Http/SocketsHttpHandler/RedirectHandler.cs | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs index ee41dbb716adf..b7f911048dca8 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs @@ -44,8 +44,15 @@ public static IEnumerable RedirectStatusCodesOldMethodsNewMethods() foreach (int statusCode in new[] { 300, 301, 302, 303, 307, 308 }) { yield return new object[] { statusCode, "GET", "GET" }; - yield return new object[] { statusCode, "POST", statusCode <= 303 ? "GET" : "POST" }; yield return new object[] { statusCode, "HEAD", "HEAD" }; + + yield return new object[] { statusCode, "POST", statusCode <= 303 ? "GET" : "POST" }; + + yield return new object[] { statusCode, "DELETE", statusCode == 303 ? "GET" : "DELETE" }; + yield return new object[] { statusCode, "OPTIONS", statusCode == 303 ? "GET" : "OPTIONS" }; + yield return new object[] { statusCode, "PATCH", statusCode == 303 ? "GET" : "PATCH" }; + yield return new object[] { statusCode, "PUT", statusCode == 303 ? "GET" : "PUT" }; + yield return new object[] { statusCode, "MYCUSTOMMETHOD", statusCode == 303 ? "GET" : "MYCUSTOMMETHOD" }; } } public HttpClientHandlerTest_AutoRedirect(ITestOutputHelper output) : base(output) { } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs index cf1693672b03e..856b4e61da394 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs @@ -142,9 +142,10 @@ private static bool RequestRequiresForceGet(HttpStatusCode statusCode, HttpMetho { case HttpStatusCode.Moved: case HttpStatusCode.Found: - case HttpStatusCode.SeeOther: case HttpStatusCode.MultipleChoices: return requestMethod == HttpMethod.Post; + case HttpStatusCode.SeeOther: + return requestMethod != HttpMethod.Get && requestMethod != HttpMethod.Head; default: return false; } From 4e76febcee4392012954dfc26b108002af71b783 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 9 Mar 2021 16:26:31 -0800 Subject: [PATCH 68/83] Use managed implementation of pbkdf2 for Android's one-shot implementation. (#49314) --- .../Pbkdf2Implementation.Android.cs | 36 +++++++++++++++++++ ...em.Security.Cryptography.Algorithms.csproj | 5 +-- .../Cryptography/Rfc2898DeriveBytes.cs | 8 ++--- 3 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Pbkdf2Implementation.Android.cs diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Pbkdf2Implementation.Android.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Pbkdf2Implementation.Android.cs new file mode 100644 index 0000000000000..c0ab7eebc76fa --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Pbkdf2Implementation.Android.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Security.Cryptography; + +namespace Internal.Cryptography +{ + internal partial class Pbkdf2Implementation + { + public static unsafe void Fill( + ReadOnlySpan password, + ReadOnlySpan salt, + int iterations, + HashAlgorithmName hashAlgorithmName, + Span destination) + { + Debug.Assert(!destination.IsEmpty); + Debug.Assert(hashAlgorithmName.Name is not null); + // Fall back to managed implementation since Android doesn't support the full Pbkdf2 APIs + // until API level 26. + using (Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes( + password.ToArray(), + salt.ToArray(), + iterations, + hashAlgorithmName, + clearPassword: true, + requireMinimumSaltLength: false)) + { + byte[] result = deriveBytes.GetBytes(destination.Length); + result.AsSpan().CopyTo(destination); + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj index e7c4bfaf1da3b..15af720d3ab45 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj @@ -474,8 +474,7 @@ - - + @@ -601,6 +600,7 @@ Link="Common\System\Security\Cryptography\RSAOpenSsl.cs" /> + + Date: Tue, 9 Mar 2021 16:27:36 -0800 Subject: [PATCH 69/83] [AndroidCrypto] Support a zero-length salt for HMACs. (#49384) --- .../pal_hmac.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_hmac.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_hmac.c index 57e78e658aef6..33a40c0480611 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_hmac.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_hmac.c @@ -29,8 +29,22 @@ jobject CryptoNative_HmacCreate(uint8_t* key, int32_t keyLen, intptr_t type) else return FAIL; - jbyteArray keyBytes = (*env)->NewByteArray(env, keyLen); - (*env)->SetByteArrayRegion(env, keyBytes, 0, keyLen, (jbyte*)key); + jbyteArray keyBytes; + + if (key && keyLen > 0) + { + keyBytes = (*env)->NewByteArray(env, keyLen); + (*env)->SetByteArrayRegion(env, keyBytes, 0, keyLen, (jbyte*)key); + } + else + { + // Java does not support zero-length byte arrays in the SecretKeySpec type, + // so instead create an empty 1-byte length byte array that's initalized to 0. + // the HMAC algorithm pads keys with zeros until the key is block-length, + // so this effectively creates the same key as if it were a zero byte-length key. + keyBytes = (*env)->NewByteArray(env, 1); + } + jobject sksObj = (*env)->NewObject(env, g_sksClass, g_sksCtor, keyBytes, macName); if (CheckJNIExceptions(env)) { From 9fc4fb421fd52048b597a31f6cd6ffa28c3a219a Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 10 Mar 2021 01:40:55 +0100 Subject: [PATCH 70/83] Implement AppleCryptoNative_X509GetRawData using SecCertificateCopyData --- .../pal_x509.c | 36 +++++++++---------- .../pal_x509.h | 22 ++++++------ 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c index ec91e362f501b..f69ddd81a0eb8 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.c @@ -257,6 +257,22 @@ int32_t AppleCryptoNative_X509CopyPrivateKeyFromIdentity(SecIdentityRef identity return SecIdentityCopyPrivateKey(identity, pPrivateKeyOut); } +int32_t AppleCryptoNative_X509GetRawData(SecCertificateRef cert, CFDataRef* ppDataOut, int32_t* pOSStatus) +{ + if (cert == NULL || ppDataOut == NULL || pOSStatus == NULL) + { + if (ppDataOut != NULL) + *ppDataOut = NULL; + if (pOSStatus != NULL) + *pOSStatus = noErr; + return kErrorBadInput; + } + + *ppDataOut = SecCertificateCopyData(cert); + *pOSStatus = *ppDataOut == NULL ? errSecParam : noErr; + return (*pOSStatus == noErr); +} + #if !defined(TARGET_MACCATALYST) && !defined(TARGET_IOS) && !defined(TARGET_TVOS) static int32_t ReadX509(uint8_t* pbData, int32_t cbData, @@ -510,26 +526,6 @@ int32_t AppleCryptoNative_X509ExportData(CFArrayRef data, return *pOSStatus == noErr; } -int32_t AppleCryptoNative_X509GetRawData(SecCertificateRef cert, CFDataRef* ppDataOut, int32_t* pOSStatus) -{ - if (ppDataOut != NULL) - *ppDataOut = NULL; - if (pOSStatus != NULL) - *pOSStatus = noErr; - - if (cert == NULL || ppDataOut == NULL || pOSStatus == NULL) - return kErrorBadInput; - - SecExternalFormat dataFormat = kSecFormatX509Cert; - SecItemImportExportKeyParameters keyParams; - memset(&keyParams, 0, sizeof(SecItemImportExportKeyParameters)); - - keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; - - *pOSStatus = SecItemExport(cert, dataFormat, 0, &keyParams, ppDataOut); - return (*pOSStatus == noErr); -} - static OSStatus AddKeyToKeychain(SecKeyRef privateKey, SecKeychainRef targetKeychain, SecKeyRef* importedKey) { // This is quite similar to pal_seckey's ExportImportKey, but diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h index fbe79a9e6af24..067f54b099269 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509.h @@ -73,6 +73,17 @@ pPrivateKeyOut: Receives a SecKeyRef for the private key associated with the ide */ PALEXPORT int32_t AppleCryptoNative_X509CopyPrivateKeyFromIdentity(SecIdentityRef identity, SecKeyRef* pPrivateKeyOut); +/* +Extract the DER encoded value of a certificate (public portion only). + +Returns 1 on success, 0 on failure, any other value indicates invalid state. + +Output: +ppDataOut: Receives a CFDataRef with the exported blob +pOSStatus: Receives the result of SecItemExport +*/ +PALEXPORT int32_t AppleCryptoNative_X509GetRawData(SecCertificateRef cert, CFDataRef* ppDataOut, int32_t* pOSStatus); + #if !defined(TARGET_MACCATALYST) && !defined(TARGET_IOS) && !defined(TARGET_TVOS) /* Read cbData bytes of data from pbData and interpret it to a collection of certificates (or identities). @@ -147,17 +158,6 @@ PALEXPORT int32_t AppleCryptoNative_X509ExportData(CFArrayRef data, CFDataRef* pExportOut, int32_t* pOSStatus); -/* -Extract the DER encoded value of a certificate (public portion only). - -Returns 1 on success, 0 on failure, any other value indicates invalid state. - -Output: -ppDataOut: Receives a CFDataRef with the exported blob -pOSStatus: Receives the result of SecItemExport -*/ -PALEXPORT int32_t AppleCryptoNative_X509GetRawData(SecCertificateRef cert, CFDataRef* ppDataOut, int32_t* pOSStatus); - /* Find a SecIdentityRef for the given cert and private key in the target keychain. If the key does not belong to any keychain it is added to the target keychain and left there. From 220b01a58697eeae580d97cc47879217efd6628f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Wed, 10 Mar 2021 00:58:37 +0000 Subject: [PATCH 71/83] [main] Update dependencies from dotnet/arcade dotnet/llvm-project dotnet/runtime-assets (#49359) [main] Update dependencies from dotnet/arcade dotnet/llvm-project dotnet/runtime-assets - re-introduce publishing workaround --- eng/Version.Details.xml | 132 ++++++++++++++--------------- eng/Versions.props | 58 ++++++------- eng/common/native/install-tool.ps1 | 2 +- global.json | 8 +- 4 files changed, 100 insertions(+), 100 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a064479ce7d93..c53b634d45cbc 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -6,69 +6,69 @@ - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 - + https://github.com/dotnet/arcade - f95dc73e2028d630d67b782c9dcccbe464cf9677 + 287fba3cbedce004fbd9823c268327960a69ca88 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization @@ -94,73 +94,73 @@ https://github.com/microsoft/vstest 140434f7109d357d0158ade9e5164a4861513965 - + https://github.com/dotnet/runtime-assets - ad3e62eb902b7ab02a12ea40d35e0d35e067afe3 + c7c14818023404ed900360565f8289b8e14d9aa4 - + https://github.com/dotnet/runtime-assets - ad3e62eb902b7ab02a12ea40d35e0d35e067afe3 + c7c14818023404ed900360565f8289b8e14d9aa4 - + https://github.com/dotnet/runtime-assets - ad3e62eb902b7ab02a12ea40d35e0d35e067afe3 + c7c14818023404ed900360565f8289b8e14d9aa4 - + https://github.com/dotnet/runtime-assets - ad3e62eb902b7ab02a12ea40d35e0d35e067afe3 + c7c14818023404ed900360565f8289b8e14d9aa4 - + https://github.com/dotnet/runtime-assets - ad3e62eb902b7ab02a12ea40d35e0d35e067afe3 + c7c14818023404ed900360565f8289b8e14d9aa4 - + https://github.com/dotnet/runtime-assets - ad3e62eb902b7ab02a12ea40d35e0d35e067afe3 + c7c14818023404ed900360565f8289b8e14d9aa4 - + https://github.com/dotnet/runtime-assets - ad3e62eb902b7ab02a12ea40d35e0d35e067afe3 + c7c14818023404ed900360565f8289b8e14d9aa4 - + https://github.com/dotnet/runtime-assets - ad3e62eb902b7ab02a12ea40d35e0d35e067afe3 + c7c14818023404ed900360565f8289b8e14d9aa4 - + https://github.com/dotnet/runtime-assets - ad3e62eb902b7ab02a12ea40d35e0d35e067afe3 + c7c14818023404ed900360565f8289b8e14d9aa4 - + https://github.com/dotnet/llvm-project - f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf + 121a29ab0b411db38efa6659307d86fe04aefcb8 - + https://github.com/dotnet/llvm-project - f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf + 121a29ab0b411db38efa6659307d86fe04aefcb8 - + https://github.com/dotnet/llvm-project - f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf + 121a29ab0b411db38efa6659307d86fe04aefcb8 - + https://github.com/dotnet/llvm-project - f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf + 121a29ab0b411db38efa6659307d86fe04aefcb8 - + https://github.com/dotnet/llvm-project - f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf + 121a29ab0b411db38efa6659307d86fe04aefcb8 - + https://github.com/dotnet/llvm-project - f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf + 121a29ab0b411db38efa6659307d86fe04aefcb8 - + https://github.com/dotnet/llvm-project - f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf + 121a29ab0b411db38efa6659307d86fe04aefcb8 - + https://github.com/dotnet/llvm-project - f2a7fc3d94f1a30b822d79ffe453e6b88ae242cf + 121a29ab0b411db38efa6659307d86fe04aefcb8 https://github.com/dotnet/runtime diff --git a/eng/Versions.props b/eng/Versions.props index f6905d2916f0b..03a12faeac6d4 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -49,18 +49,18 @@ 3.9.0-5.final 3.9.0-5.final - 6.0.0-beta.21152.1 - 6.0.0-beta.21152.1 - 6.0.0-beta.21152.1 - 6.0.0-beta.21152.1 - 6.0.0-beta.21152.1 - 6.0.0-beta.21152.1 - 2.5.1-beta.21152.1 - 6.0.0-beta.21152.1 - 6.0.0-beta.21152.1 - 6.0.0-beta.21152.1 - 6.0.0-beta.21152.1 - 6.0.0-beta.21152.1 + 6.0.0-beta.21155.1 + 6.0.0-beta.21155.1 + 6.0.0-beta.21155.1 + 6.0.0-beta.21155.1 + 6.0.0-beta.21155.1 + 6.0.0-beta.21155.1 + 2.5.1-beta.21155.1 + 6.0.0-beta.21155.1 + 6.0.0-beta.21155.1 + 6.0.0-beta.21155.1 + 6.0.0-beta.21155.1 + 6.0.0-beta.21155.1 5.9.0-preview.2 @@ -106,15 +106,15 @@ 4.3.0 6.0.0-preview.3.21157.6 - 5.0.0-beta.21151.2 - 5.0.0-beta.21151.2 - 5.0.0-beta.21151.2 - 5.0.0-beta.21151.2 - 5.0.0-beta.21151.2 - 5.0.0-beta.21151.2 - 5.0.0-beta.21151.2 - 5.0.0-beta.21151.2 - 5.0.0-beta.21151.2 + 5.0.0-beta.21159.1 + 5.0.0-beta.21159.1 + 5.0.0-beta.21159.1 + 5.0.0-beta.21159.1 + 5.0.0-beta.21159.1 + 5.0.0-beta.21159.1 + 5.0.0-beta.21159.1 + 5.0.0-beta.21159.1 + 5.0.0-beta.21159.1 99.99.99-master-20200806.6 99.99.99-master-20200806.6 @@ -159,14 +159,14 @@ 6.0.0-preview.3.21151.1 - 9.0.1-alpha.1.21154.1 - 9.0.1-alpha.1.21154.1 - 9.0.1-alpha.1.21154.1 - 9.0.1-alpha.1.21154.1 - 9.0.1-alpha.1.21154.1 - 9.0.1-alpha.1.21154.1 - 9.0.1-alpha.1.21154.1 - 9.0.1-alpha.1.21154.1 + 9.0.1-alpha.1.21158.1 + 9.0.1-alpha.1.21158.1 + 9.0.1-alpha.1.21158.1 + 9.0.1-alpha.1.21158.1 + 9.0.1-alpha.1.21158.1 + 9.0.1-alpha.1.21158.1 + 9.0.1-alpha.1.21158.1 + 9.0.1-alpha.1.21158.1 diff --git a/eng/common/native/install-tool.ps1 b/eng/common/native/install-tool.ps1 index f397e1c75d411..78f2d84a4e4b1 100644 --- a/eng/common/native/install-tool.ps1 +++ b/eng/common/native/install-tool.ps1 @@ -105,7 +105,7 @@ try { Write-Error "There are multiple copies of $ToolName in $($ToolInstallDirectory): `n$(@($ToolFilePath | out-string))" exit 1 } elseif (@($ToolFilePath).Length -Lt 1) { - Write-Host "$ToolName was not found in $ToolFilePath." + Write-Host "$ToolName was not found in $ToolInstallDirectory." exit 1 } diff --git a/global.json b/global.json index 28d854b09b734..9935b33b7d66d 100644 --- a/global.json +++ b/global.json @@ -12,10 +12,10 @@ "python3": "3.7.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21152.1", - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21152.1", - "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21152.1", - "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21152.1", + "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21155.1", + "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21155.1", + "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21155.1", + "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21155.1", "Microsoft.Build.NoTargets": "2.0.17", "Microsoft.Build.Traversal": "2.1.1", "Microsoft.NET.Sdk.IL": "6.0.0-preview.3.21157.6" From 632a56b089b03e107ea20b2a9276e6235c4e01ac Mon Sep 17 00:00:00 2001 From: Bruce Forstall Date: Tue, 9 Mar 2021 18:25:19 -0800 Subject: [PATCH 72/83] Remove release build cron triggers from jitstress jobs (#49333) We need to make per-preview decisions about when and how frequently to run non-baseline jobs. We don't want the existing configuration to automatically flow to new previews. --- eng/pipelines/coreclr/jitstress.yml | 6 ------ eng/pipelines/coreclr/libraries-jitstress.yml | 6 ------ 2 files changed, 12 deletions(-) diff --git a/eng/pipelines/coreclr/jitstress.yml b/eng/pipelines/coreclr/jitstress.yml index da704d0144e1e..f1f50f97b66ab 100644 --- a/eng/pipelines/coreclr/jitstress.yml +++ b/eng/pipelines/coreclr/jitstress.yml @@ -7,12 +7,6 @@ schedules: include: - main always: true -- cron: "0 4 * * *" - displayName: Daily (if changes) at 8:00 PM (UTC-8:00) - branches: - include: - - release/*.* - always: false jobs: diff --git a/eng/pipelines/coreclr/libraries-jitstress.yml b/eng/pipelines/coreclr/libraries-jitstress.yml index 6e611057302cc..b994f69517ea1 100644 --- a/eng/pipelines/coreclr/libraries-jitstress.yml +++ b/eng/pipelines/coreclr/libraries-jitstress.yml @@ -7,12 +7,6 @@ schedules: include: - main always: true -- cron: "0 7 * * *" - displayName: Daily (if changes) at 11:00 PM (UTC-8:00) - branches: - include: - - release/*.* - always: false jobs: From 11ff8a576aaccbf291ce8e3e9ba0bd0b04913d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Tue, 9 Mar 2021 19:11:17 -0800 Subject: [PATCH 73/83] Remove unnecessary check on polymorphic serialization (#48464) --- .../Json/Serialization/JsonConverterOfT.cs | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs index b55bc531c8cd8..c8ca15daec330 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs @@ -363,26 +363,25 @@ internal bool TryWrite(Utf8JsonWriter writer, in T value, JsonSerializerOptions // For internal converter only: Handle polymorphic case and get the new converter. // Custom converter, even though polymorphic converter, get called for reading AND writing. JsonConverter jsonConverter = state.Current.InitializeReEntry(type, options); - if (jsonConverter != this) + Debug.Assert(jsonConverter != this); + + if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.IgnoreCycles && + jsonConverter.IsValueType) { - if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.IgnoreCycles && - jsonConverter.IsValueType) - { - // For boxed value types: push the value before it gets unboxed on TryWriteAsObject. - state.ReferenceResolver.PushReferenceForCycleDetection(value); - ignoreCyclesPopReference = true; - } + // For boxed value types: push the value before it gets unboxed on TryWriteAsObject. + state.ReferenceResolver.PushReferenceForCycleDetection(value); + ignoreCyclesPopReference = true; + } - // We found a different converter; forward to that. - bool success2 = jsonConverter.TryWriteAsObject(writer, value, options, ref state); + // We found a different converter; forward to that. + bool success2 = jsonConverter.TryWriteAsObject(writer, value, options, ref state); - if (ignoreCyclesPopReference) - { - state.ReferenceResolver.PopReferenceForCycleDetection(); - } - - return success2; + if (ignoreCyclesPopReference) + { + state.ReferenceResolver.PopReferenceForCycleDetection(); } + + return success2; } } From 3eddf4a06b0755747f8e8d659264694eef1f31ee Mon Sep 17 00:00:00 2001 From: Eric StJohn Date: Tue, 9 Mar 2021 21:33:19 -0800 Subject: [PATCH 74/83] Update package index for servicing (#49417) --- src/libraries/pkg/baseline/packageIndex.json | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libraries/pkg/baseline/packageIndex.json b/src/libraries/pkg/baseline/packageIndex.json index 24b38495e8196..04260e73bb565 100644 --- a/src/libraries/pkg/baseline/packageIndex.json +++ b/src/libraries/pkg/baseline/packageIndex.json @@ -3048,7 +3048,8 @@ "4.7.0", "4.7.1", "5.0.0", - "5.0.1" + "5.0.1", + "5.0.2" ], "BaselineVersion": "6.0.0", "InboxOn": { @@ -6677,8 +6678,13 @@ "4.3.1", "4.4.0", "4.5.0", + "4.5.1", "4.6.0", - "5.0.0" + "4.7.0", + "4.7.1", + "4.7.2", + "5.0.0", + "5.0.1" ], "BaselineVersion": "6.0.0", "InboxOn": { @@ -6690,6 +6696,7 @@ "4.0.1.0": "4.3.0", "4.0.2.0": "4.4.0", "4.0.3.0": "4.5.0", + "4.0.3.1": "4.5.1", "4.0.4.0": "4.6.0", "5.0.0.0": "5.0.0", "6.0.0.0": "6.0.0" From beb14c143947346cf9c09ca056a0cee7fcc72108 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Wed, 10 Mar 2021 09:36:04 +0300 Subject: [PATCH 75/83] JIT: Non-void ThrowHelpers (#48589) --- src/coreclr/jit/flowgraph.cpp | 23 +-- src/coreclr/jit/morph.cpp | 11 +- src/coreclr/jit/utils.cpp | 7 + src/coreclr/jit/utils.h | 8 + .../JIT/opt/ThrowHelper/NonVoidThrowHelper.cs | 180 ++++++++++++++++++ .../opt/ThrowHelper/NonVoidThrowHelper.csproj | 10 + src/tests/issues.targets | 3 + 7 files changed, 213 insertions(+), 29 deletions(-) create mode 100644 src/tests/JIT/opt/ThrowHelper/NonVoidThrowHelper.cs create mode 100644 src/tests/JIT/opt/ThrowHelper/NonVoidThrowHelper.csproj diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 8b89c2e5945a5..9fb409929044d 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -684,31 +684,16 @@ PhaseStatus Compiler::fgImport() bool Compiler::fgIsThrow(GenTree* tree) { - if ((tree->gtOper != GT_CALL) || (tree->AsCall()->gtCallType != CT_HELPER)) + if (!tree->IsCall()) { return false; } - - // TODO-Throughput: Replace all these calls to eeFindHelper() with a table based lookup - - if ((tree->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_OVERFLOW)) || - (tree->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_VERIFICATION)) || - (tree->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_RNGCHKFAIL)) || - (tree->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWDIVZERO)) || - (tree->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWNULLREF)) || - (tree->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW)) || - (tree->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_RETHROW)) || - (tree->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED)) || - (tree->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED))) + GenTreeCall* call = tree->AsCall(); + if ((call->gtCallType == CT_HELPER) && s_helperCallProperties.AlwaysThrow(eeGetHelperNum(call->gtCallMethHnd))) { - noway_assert(tree->gtFlags & GTF_CALL); - noway_assert(tree->gtFlags & GTF_EXCEPT); + noway_assert(call->gtFlags & GTF_EXCEPT); return true; } - - // TODO-CQ: there are a bunch of managed methods in System.ThrowHelper - // that would be nice to recognize. - return false; } diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 648ddc49661f2..6b31152a9978a 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -9429,15 +9429,8 @@ GenTree* Compiler::fgMorphCall(GenTreeCall* call) // BBJ_THROW would result in the tail call being dropped as the epilog is generated // only for BBJ_RETURN blocks. // - // Currently this doesn't work for non-void callees. Some of the code that handles - // fgRemoveRestOfBlock expects the tree to have GTF_EXCEPT flag set but call nodes - // do not have this flag by default. We could add the flag here but the proper solution - // would be to replace the return expression with a local var node during inlining - // so the rest of the call tree stays in a separate statement. That statement can then - // be removed by fgRemoveRestOfBlock without needing to add GTF_EXCEPT anywhere. - // - if (!call->IsTailCall() && call->TypeGet() == TYP_VOID) + if (!call->IsTailCall()) { fgRemoveRestOfBlock = true; } @@ -14916,7 +14909,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) if (fgIsCommaThrow(op1, true)) { GenTree* throwNode = op1->AsOp()->gtOp1; - noway_assert(throwNode->gtType == TYP_VOID); JITDUMP("Removing [%06d] GT_JTRUE as the block now unconditionally throws an exception.\n", dspTreeID(tree)); @@ -14969,7 +14961,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) } GenTree* throwNode = op1->AsOp()->gtOp1; - noway_assert(throwNode->gtType == TYP_VOID); if (oper == GT_COMMA) { diff --git a/src/coreclr/jit/utils.cpp b/src/coreclr/jit/utils.cpp index c973f6f63c876..dafa816193cb7 100644 --- a/src/coreclr/jit/utils.cpp +++ b/src/coreclr/jit/utils.cpp @@ -1217,6 +1217,7 @@ void HelperCallProperties::init() // bool isPure = false; // true if the result only depends upon input args and not any global state bool noThrow = false; // true if the helper will never throw + bool alwaysThrow = false; // true if the helper will always throw bool nonNullReturn = false; // true if the result will never be null or zero bool isAllocator = false; // true if the result is usually a newly created heap item, or may throw OutOfMemory bool mutatesHeap = false; // true if any previous heap objects [are|can be] modified @@ -1458,7 +1459,12 @@ void HelperCallProperties::init() case CORINFO_HELP_THROW_NOT_IMPLEMENTED: case CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED: case CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED: + case CORINFO_HELP_FAIL_FAST: + case CORINFO_HELP_METHOD_ACCESS_EXCEPTION: + case CORINFO_HELP_FIELD_ACCESS_EXCEPTION: + case CORINFO_HELP_CLASS_ACCESS_EXCEPTION: + alwaysThrow = true; break; // These helper calls may throw an exception @@ -1498,6 +1504,7 @@ void HelperCallProperties::init() m_isPure[helper] = isPure; m_noThrow[helper] = noThrow; + m_alwaysThrow[helper] = alwaysThrow; m_nonNullReturn[helper] = nonNullReturn; m_isAllocator[helper] = isAllocator; m_mutatesHeap[helper] = mutatesHeap; diff --git a/src/coreclr/jit/utils.h b/src/coreclr/jit/utils.h index 2a50680229efd..3f08f3e25618d 100644 --- a/src/coreclr/jit/utils.h +++ b/src/coreclr/jit/utils.h @@ -451,6 +451,7 @@ class HelperCallProperties private: bool m_isPure[CORINFO_HELP_COUNT]; bool m_noThrow[CORINFO_HELP_COUNT]; + bool m_alwaysThrow[CORINFO_HELP_COUNT]; bool m_nonNullReturn[CORINFO_HELP_COUNT]; bool m_isAllocator[CORINFO_HELP_COUNT]; bool m_mutatesHeap[CORINFO_HELP_COUNT]; @@ -478,6 +479,13 @@ class HelperCallProperties return m_noThrow[helperId]; } + bool AlwaysThrow(CorInfoHelpFunc helperId) + { + assert(helperId > CORINFO_HELP_UNDEF); + assert(helperId < CORINFO_HELP_COUNT); + return m_alwaysThrow[helperId]; + } + bool NonNullReturn(CorInfoHelpFunc helperId) { assert(helperId > CORINFO_HELP_UNDEF); diff --git a/src/tests/JIT/opt/ThrowHelper/NonVoidThrowHelper.cs b/src/tests/JIT/opt/ThrowHelper/NonVoidThrowHelper.cs new file mode 100644 index 0000000000000..c6b0e9e527f14 --- /dev/null +++ b/src/tests/JIT/opt/ThrowHelper/NonVoidThrowHelper.cs @@ -0,0 +1,180 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; + +public class ProgramException : Exception {} + +public sealed class ProgramSubclass : Program +{ + public static readonly object s_Obj = new object(); +} + +public unsafe class Program +{ + private static int s_ReturnCode = 100; + + private Guid field; + + private static Program s_Instance = new (); + + private static Program GetClass() => throw new ProgramException(); + + private static Guid GetGuid() => throw new ProgramException(); + + private static IntPtr GetIntPtr() => throw new ProgramException(); + + private static int* GetPtr() => throw new ProgramException(); + + private static Span GetSpan() => throw new ProgramException(); + + private static int GetInt(object obj) => throw new ProgramException(); + + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void DoWork() => s_ReturnCode++; + + private static void TestCond0() + { + if (GetClass() == default) + DoWork(); + } + + private static void TestCond1() + { + if (GetClass() is ProgramSubclass) + DoWork(); + } + + private static void TestCond2() + { + if (GetInt(ProgramSubclass.s_Obj) != 42) + DoWork(); + } + + private static void TestCond3() + { + if (GetClass() == s_Instance) + DoWork(); + } + + private static void TestCond4() + { + if (GetClass().field == Guid.NewGuid()) + DoWork(); + } + + private static void TestCond5() + { + if (GetGuid() == default) + DoWork(); + } + + private static void TestCond6() + { + if (GetIntPtr() == (IntPtr)42) + DoWork(); + } + + private static void TestCond7() + { + if (*GetPtr() == 42) + DoWork(); + } + + private static void TestCond8() + { + if (GetSpan()[4] == 42) + DoWork(); + } + + private static bool TestRet1() + { + return GetClass() == default; + } + + private static bool TestRet2() + { + return GetClass() == s_Instance; + } + + private static bool TestRet3() + { + return GetClass() is ProgramSubclass; + } + + private static bool TestRet4() + { + return GetInt(ProgramSubclass.s_Obj) == 42; + } + + private static bool TestRet5() + { + return GetClass().field == Guid.NewGuid(); + } + + private static bool TestRet6() + { + return GetGuid() == default; + } + + private static bool TestRet7() + { + return GetIntPtr() == (IntPtr)42; + } + + private static bool TestRet8() + { + return *GetPtr() == 42; + } + + private static bool TestRet9() + { + return GetSpan()[100] == 42; + } + + private static Program TestTailCall1() + { + return GetClass(); + } + + private static Guid TestTailCall2() + { + return GetGuid(); + } + + private static IntPtr TestTailCall3() + { + return GetIntPtr(); + } + + private static int* TestTailCall4() + { + return GetPtr(); + } + + public static int Main() + { + foreach (var method in typeof(Program) + .GetMethods(BindingFlags.Static | BindingFlags.NonPublic) + .Where(m => m.Name.StartsWith("Test"))) + { + try + { + method.Invoke(null, null); + } + catch (TargetInvocationException tie) + { + if (tie.InnerException is ProgramException) + { + continue; + } + } + + s_ReturnCode++; + } + return s_ReturnCode; + } +} diff --git a/src/tests/JIT/opt/ThrowHelper/NonVoidThrowHelper.csproj b/src/tests/JIT/opt/ThrowHelper/NonVoidThrowHelper.csproj new file mode 100644 index 0000000000000..3430940509932 --- /dev/null +++ b/src/tests/JIT/opt/ThrowHelper/NonVoidThrowHelper.csproj @@ -0,0 +1,10 @@ + + + Exe + True + true + + + + + diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 8cbaa5e5cacbd..004c1fc48070e 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -2667,6 +2667,9 @@ + + https://github.com/dotnet/runtime/issues/48819 + https://github.com/dotnet/runtime/issues/41193 From 016ec299033902f6e68c84ac0a3ec917f9304946 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Wed, 10 Mar 2021 09:36:43 +0300 Subject: [PATCH 76/83] [RyuJIT] Make casthelpers cold for sealed classes (#49295) --- src/coreclr/jit/fgopt.cpp | 4 ++-- src/coreclr/jit/importer.cpp | 10 ++++++---- src/coreclr/jit/morph.cpp | 5 +++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index bd455e19f3d57..cc6ff733f4bba 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -2354,12 +2354,12 @@ bool Compiler::fgOptimizeEmptyBlock(BasicBlock* block) { case BBJ_COND: case BBJ_SWITCH: - case BBJ_THROW: /* can never happen */ - noway_assert(!"Conditional, switch, or throw block with empty body!"); + noway_assert(!"Conditional or switch block with empty body!"); break; + case BBJ_THROW: case BBJ_CALLFINALLY: case BBJ_RETURN: case BBJ_EHCATCHRET: diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 4100eb7e29f94..0b083746808c4 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -11075,9 +11075,6 @@ GenTree* Compiler::impCastClassOrIsInstToTree(GenTree* op1, condTrue = gtNewIconNode(0, TYP_REF); } -#define USE_QMARK_TREES - -#ifdef USE_QMARK_TREES GenTree* qmarkMT; // // Generate first QMARK - COLON tree @@ -11091,6 +11088,12 @@ GenTree* Compiler::impCastClassOrIsInstToTree(GenTree* op1, temp = new (this, GT_COLON) GenTreeColon(TYP_REF, condTrue, condFalse); qmarkMT = gtNewQmarkNode(TYP_REF, condMT, temp); + if (isCastClass && impIsClassExact(pResolvedToken->hClass) && condTrue->OperIs(GT_CALL)) + { + // condTrue is used only for throwing InvalidCastException in case of casting to an exact class. + condTrue->AsCall()->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN; + } + GenTree* qmarkNull; // // Generate second QMARK - COLON tree @@ -11119,7 +11122,6 @@ GenTree* Compiler::impCastClassOrIsInstToTree(GenTree* op1, JITDUMP("Marked V%02u as a single def temp\n", tmp); lvaSetClass(tmp, pResolvedToken->hClass); return gtNewLclvNode(tmp, TYP_REF); -#endif } #ifndef DEBUG diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 6b31152a9978a..9122dbf0756d8 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -17689,6 +17689,11 @@ void Compiler::fgExpandQmarkForCastInstOf(BasicBlock* block, Statement* stmt) // Finally remove the nested qmark stmt. fgRemoveStmt(block, stmt); + if (true2Expr->OperIs(GT_CALL) && (true2Expr->AsCall()->gtCallMoreFlags & GTF_CALL_M_DOES_NOT_RETURN)) + { + fgConvertBBToThrowBB(helperBlock); + } + #ifdef DEBUG if (verbose) { From 423f5e1eb186b90d99002ff35725ece8cbfff30c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 10 Mar 2021 11:54:22 +0100 Subject: [PATCH 77/83] WinHttpHandler: Read HTTP/2 trailing headers Fixes #44778 --- .../Windows/WinHttp/Interop.winhttp_types.cs | 2 + .../Common/src/System/Net/SecurityProtocol.cs | 2 +- .../TestUtilities/System/PlatformDetection.cs | 2 +- .../src/System.Net.Http.WinHttpHandler.csproj | 3 +- .../System/Net/Http/WinHttpResponseParser.cs | 43 +++- .../System/Net/Http/WinHttpResponseStream.cs | 49 +++- .../System/Net/Http/WinHttpTrailersHelper.cs | 64 +++++ ...ttp.WinHttpHandler.Functional.Tests.csproj | 7 +- .../FunctionalTests/TrailingHeadersTest.cs | 222 ++++++++++++++++++ .../tests/UnitTests/FakeInterop.cs | 6 + ....Net.Http.WinHttpHandler.Unit.Tests.csproj | 5 +- .../UnitTests/WinHttpResponseStreamTest.cs | 2 +- 12 files changed, 388 insertions(+), 19 deletions(-) create mode 100644 src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs create mode 100644 src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/TrailingHeadersTest.cs diff --git a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs index e7e1256c4cb47..c8f49628123c5 100644 --- a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs +++ b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs @@ -68,6 +68,7 @@ internal partial class WinHttp public const uint WINHTTP_QUERY_STATUS_TEXT = 20; public const uint WINHTTP_QUERY_RAW_HEADERS = 21; public const uint WINHTTP_QUERY_RAW_HEADERS_CRLF = 22; + public const uint WINHTTP_QUERY_FLAG_TRAILERS = 0x02000000; public const uint WINHTTP_QUERY_CONTENT_ENCODING = 29; public const uint WINHTTP_QUERY_SET_COOKIE = 43; public const uint WINHTTP_QUERY_CUSTOM = 65535; @@ -164,6 +165,7 @@ internal partial class WinHttp public const uint WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE = 123; public const uint WINHTTP_OPTION_TCP_KEEPALIVE = 152; + public const uint WINHTTP_OPTION_STREAM_ERROR_CODE = 159; public enum WINHTTP_WEB_SOCKET_BUFFER_TYPE { diff --git a/src/libraries/Common/src/System/Net/SecurityProtocol.cs b/src/libraries/Common/src/System/Net/SecurityProtocol.cs index f6de449ef3b8d..a8ff9b3cbc698 100644 --- a/src/libraries/Common/src/System/Net/SecurityProtocol.cs +++ b/src/libraries/Common/src/System/Net/SecurityProtocol.cs @@ -8,7 +8,7 @@ namespace System.Net internal static class SecurityProtocol { public const SslProtocols DefaultSecurityProtocols = -#if !NETSTANDARD2_0 && !NETFRAMEWORK +#if !NETSTANDARD2_0 && !NETSTANDARD2_1 && !NETFRAMEWORK SslProtocols.Tls13 | #endif SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12; diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index f39ef807e9cab..c41a3df0cd5ac 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -137,7 +137,7 @@ public static bool IsNonZeroLowerBoundArraySupported // OSX - SecureTransport doesn't expose alpn APIs. TODO https://github.com/dotnet/runtime/issues/27727 public static bool IsOpenSslSupported => IsLinux || IsFreeBSD || Isillumos || IsSolaris; - public static bool SupportsAlpn => (IsWindows && !IsWindows7) || + public static bool SupportsAlpn => (IsWindows && !IsWindows7 && !IsNetFramework) || (IsOpenSslSupported && (OpenSslVersion.Major >= 1 && (OpenSslVersion.Minor >= 1 || OpenSslVersion.Build >= 2))); diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj b/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj index 91be83654d3be..4c08c8421af04 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System.Net.Http.WinHttpHandler.csproj @@ -1,7 +1,7 @@ true - netstandard2.0-windows;netstandard2.0;net461-windows + netstandard2.0-windows;netstandard2.0;netstandard2.1-windows;netstandard2.1;net461-windows true enable @@ -94,6 +94,7 @@ + diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseParser.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseParser.cs index 1f9c88a019a91..9f324ada27a0f 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseParser.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseParser.cs @@ -29,7 +29,7 @@ public static HttpResponseMessage CreateResponseMessage( // Create a single buffer to use for all subsequent WinHttpQueryHeaders string interop calls. // This buffer is the length needed for WINHTTP_QUERY_RAW_HEADERS_CRLF, which includes the status line // and all headers separated by CRLF, so it should be large enough for any individual status line or header queries. - int bufferLength = GetResponseHeaderCharBufferLength(requestHandle, Interop.WinHttp.WINHTTP_QUERY_RAW_HEADERS_CRLF); + int bufferLength = GetResponseHeaderCharBufferLength(requestHandle, isTrailingHeaders: false); char[] buffer = ArrayPool.Shared.Rent(bufferLength); try { @@ -58,7 +58,7 @@ public static HttpResponseMessage CreateResponseMessage( string.Empty; // Create response stream and wrap it in a StreamContent object. - var responseStream = new WinHttpResponseStream(requestHandle, state); + var responseStream = new WinHttpResponseStream(requestHandle, state, response); state.RequestHandle = null; // ownership successfully transfered to WinHttpResponseStram. Stream decompressedStream = responseStream; @@ -223,19 +223,26 @@ private static unsafe int GetResponseHeader(SafeWinHttpHandle requestHandle, uin /// /// Returns the size of the char array buffer. /// - private static unsafe int GetResponseHeaderCharBufferLength(SafeWinHttpHandle requestHandle, uint infoLevel) + public static unsafe int GetResponseHeaderCharBufferLength(SafeWinHttpHandle requestHandle, bool isTrailingHeaders) { char* buffer = null; int bufferLength = 0; uint index = 0; + uint infoLevel = Interop.WinHttp.WINHTTP_QUERY_RAW_HEADERS_CRLF; + if (isTrailingHeaders) + { + infoLevel |= Interop.WinHttp.WINHTTP_QUERY_FLAG_TRAILERS; + } + if (!QueryHeaders(requestHandle, infoLevel, buffer, ref bufferLength, ref index)) { int lastError = Marshal.GetLastWin32Error(); - Debug.Assert(lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND); + Debug.Assert(isTrailingHeaders || lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND); - if (lastError != Interop.WinHttp.ERROR_INSUFFICIENT_BUFFER) + if (lastError != Interop.WinHttp.ERROR_INSUFFICIENT_BUFFER && + (!isTrailingHeaders || lastError != Interop.WinHttp.ERROR_WINHTTP_HEADER_NOT_FOUND)) { throw WinHttpException.CreateExceptionUsingError(lastError, nameof(Interop.WinHttp.WinHttpQueryHeaders)); } @@ -306,10 +313,7 @@ private static void ParseResponseHeaders( reader.ReadLine(); // Parse the array of headers and split them between Content headers and Response headers. - string headerName; - string headerValue; - - while (reader.ReadHeader(out headerName, out headerValue)) + while (reader.ReadHeader(out string headerName, out string headerValue)) { if (!responseHeaders.TryAddWithoutValidation(headerName, headerValue)) { @@ -331,6 +335,27 @@ private static void ParseResponseHeaders( } } + public static void ParseResponseTrailers( + SafeWinHttpHandle requestHandle, + HttpResponseMessage response, + char[] buffer) + { + HttpHeaders responseTrailers = WinHttpTrailersHelper.GetResponseTrailers(response); + + int bufferLength = GetResponseHeader( + requestHandle, + Interop.WinHttp.WINHTTP_QUERY_RAW_HEADERS_CRLF | Interop.WinHttp.WINHTTP_QUERY_FLAG_TRAILERS, + buffer); + + var reader = new WinHttpResponseHeaderReader(buffer, 0, bufferLength); + + // Parse the array of headers and split them between Content headers and Response headers. + while (reader.ReadHeader(out string headerName, out string headerValue)) + { + responseTrailers.TryAddWithoutValidation(headerName, headerValue); + } + } + private static bool IsResponseHttp2(SafeWinHttpHandle requestHandle) { uint data = 0; diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs index 812a56e7232cf..2922291faa01f 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpResponseStream.cs @@ -16,11 +16,14 @@ internal sealed class WinHttpResponseStream : Stream { private volatile bool _disposed; private readonly WinHttpRequestState _state; + private readonly HttpResponseMessage _responseMessage; private SafeWinHttpHandle _requestHandle; + private bool _readTrailingHeaders; - internal WinHttpResponseStream(SafeWinHttpHandle requestHandle, WinHttpRequestState state) + internal WinHttpResponseStream(SafeWinHttpHandle requestHandle, WinHttpRequestState state, HttpResponseMessage responseMessage) { _state = state; + _responseMessage = responseMessage; _requestHandle = requestHandle; } @@ -126,6 +129,7 @@ private async Task CopyToAsyncCore(Stream destination, byte[] buffer, Cancellati int bytesAvailable = await _state.LifecycleAwaitable; if (bytesAvailable == 0) { + ReadResponseTrailers(); break; } Debug.Assert(bytesAvailable > 0); @@ -142,12 +146,17 @@ private async Task CopyToAsyncCore(Stream destination, byte[] buffer, Cancellati int bytesRead = await _state.LifecycleAwaitable; if (bytesRead == 0) { + ReadResponseTrailers(); break; } Debug.Assert(bytesRead > 0); // Write that data out to the output stream +#if NETSTANDARD2_1 + await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false); +#else await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); +#endif } } finally @@ -240,7 +249,14 @@ private async Task ReadAsyncCore(byte[] buffer, int offset, int count, Canc } } - return await _state.LifecycleAwaitable; + int bytesRead = await _state.LifecycleAwaitable; + + if (bytesRead == 0) + { + ReadResponseTrailers(); + } + + return bytesRead; } finally { @@ -249,6 +265,35 @@ private async Task ReadAsyncCore(byte[] buffer, int offset, int count, Canc } } + private void ReadResponseTrailers() + { + // Only load response trailers if: + // 1. WINHTTP_QUERY_FLAG_TRAILERS is supported by the OS + // 2. HTTP/2 or later (WINHTTP_QUERY_FLAG_TRAILERS does not work with HTTP/1.1) + // 3. Response trailers not already loaded + if (!WinHttpTrailersHelper.OsSupportsTrailers || _responseMessage.Version < WinHttpHandler.HttpVersion20 || _readTrailingHeaders) + { + return; + } + + _readTrailingHeaders = true; + + var bufferLength = WinHttpResponseParser.GetResponseHeaderCharBufferLength(_requestHandle, isTrailingHeaders: true); + + if (bufferLength != 0) + { + char[] trailersBuffer = ArrayPool.Shared.Rent(bufferLength); + try + { + WinHttpResponseParser.ParseResponseTrailers(_requestHandle, _responseMessage, trailersBuffer); + } + finally + { + ArrayPool.Shared.Return(trailersBuffer); + } + } + } + public override int Read(byte[] buffer, int offset, int count) { return ReadAsync(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult(); diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs new file mode 100644 index 0000000000000..7be5a4c5a240d --- /dev/null +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpTrailersHelper.cs @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Net.Http.Headers; +using System.Runtime.InteropServices; +using SafeWinHttpHandle = Interop.WinHttp.SafeWinHttpHandle; + +namespace System.Net.Http +{ + internal static class WinHttpTrailersHelper + { + // UNITTEST is true when building against WinHttpHandler.Unit.Tests, which includes the source file. +#if !NETSTANDARD2_1 && !UNITTEST + // Trailer property name was chosen to be descriptive and be unlikely to collide with a user set property. + // Apps and libraries will use this key so it shouldn't change. + private const string RequestMessagePropertyName = "__ResponseTrailers"; + private class HttpResponseTrailers : HttpHeaders + { + } +#endif + private static Lazy s_trailersSupported = new Lazy(GetTrailersSupported); + public static bool OsSupportsTrailers => s_trailersSupported.Value; + + public static HttpHeaders GetResponseTrailers(HttpResponseMessage response) + { +#if NETSTANDARD2_1 || UNITTEST + return response.TrailingHeaders; +#else + HttpResponseTrailers responseTrailers = new HttpResponseTrailers(); + response.RequestMessage.Properties[RequestMessagePropertyName] = responseTrailers; + return responseTrailers; +#endif + } + + // There is no way to verify if WINHTTP_QUERY_FLAG_TRAILERS is supported by the OS without creating a request. + // Instead, the WinHTTP team recommended to check if WINHTTP_OPTION_STREAM_ERROR_CODE is recognized by the OS. + // Both features were introduced in Manganese and are planned to be backported to older Windows versions together. + private static bool GetTrailersSupported() + { + using SafeWinHttpHandle sessionHandle = Interop.WinHttp.WinHttpOpen( + IntPtr.Zero, + Interop.WinHttp.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + Interop.WinHttp.WINHTTP_NO_PROXY_NAME, + Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, + (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC); + + if (sessionHandle.IsInvalid) return false; + uint buffer = 0; + uint bufferSize = sizeof(uint); + if (Interop.WinHttp.WinHttpQueryOption(sessionHandle, Interop.WinHttp.WINHTTP_OPTION_STREAM_ERROR_CODE, ref buffer, ref bufferSize)) + { + Debug.Fail("Querying WINHTTP_OPTION_STREAM_ERROR_CODE on a session handle should never succeed."); + return false; + } + + int lastError = Marshal.GetLastWin32Error(); + + // New Windows builds are expected to fail with ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, + // when querying WINHTTP_OPTION_STREAM_ERROR_CODE on a session handle. + return lastError != Interop.WinHttp.ERROR_INVALID_PARAMETER; + } + } +} diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj index 58aa20055a8fc..d27cac268cecd 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/System.Net.Http.WinHttpHandler.Functional.Tests.csproj @@ -14,11 +14,11 @@ - + + Link="Common\System\IO\DelegateStream.cs" /> + Link="Common\System\Net\Http\ResponseStreamTest.cs" /> + diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/TrailingHeadersTest.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/TrailingHeadersTest.cs new file mode 100644 index 0000000000000..cef52465524dc --- /dev/null +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/TrailingHeadersTest.cs @@ -0,0 +1,222 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http.Functional.Tests; +using System.Net.Http.Headers; +using System.Net.Test.Common; +using System.Text; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +namespace System.Net.Http.WinHttpHandlerFunctional.Tests +{ + public class TrailingHeadersTest : HttpClientHandlerTestBase + { + public TrailingHeadersTest(ITestOutputHelper output) : base(output) + { } + + // Build number suggested by the WinHttp team. + // It can be reduced after the backport of WINHTTP_QUERY_FLAG_TRAILERS is finished, + // and the patches are rolled out to CI machines. + public static bool OsSupportsWinHttpTrailingHeaders => Environment.OSVersion.Version >= new Version(10, 0, 19622, 0); + + public static bool TestsEnabled => OsSupportsWinHttpTrailingHeaders && PlatformDetection.SupportsAlpn; + + protected override Version UseVersion => new Version(2, 0); + + protected static byte[] DataBytes = Encoding.ASCII.GetBytes("data"); + + protected static readonly IList TrailingHeaders = new HttpHeaderData[] { + new HttpHeaderData("MyCoolTrailerHeader", "amazingtrailer"), + new HttpHeaderData("EmptyHeader", ""), + new HttpHeaderData("Accept-Encoding", "identity,gzip"), + new HttpHeaderData("Hello", "World") }; + + protected static Frame MakeDataFrame(int streamId, byte[] data, bool endStream = false) => + new DataFrame(data, (endStream ? FrameFlags.EndStream : FrameFlags.None), 0, streamId); + + [ConditionalFact(nameof(TestsEnabled))] + public async Task Http2GetAsync_NoTrailingHeaders_EmptyCollection() + { + using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) + using (HttpClient client = CreateHttpClient()) + { + Task sendTask = client.GetAsync(server.Address); + + Http2LoopbackConnection connection = await server.EstablishConnectionAsync(); + + int streamId = await connection.ReadRequestHeaderAsync(); + + // Response header. + await connection.SendDefaultResponseHeadersAsync(streamId); + + // Response data. + await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes, endStream: true)); + + // Server doesn't send trailing header frame. + HttpResponseMessage response = await sendTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var trailingHeaders = GetTrailingHeaders(response); + Assert.NotNull(trailingHeaders); + Assert.Equal(0, trailingHeaders.Count()); + } + } + + [ConditionalFact(nameof(TestsEnabled))] + public async Task Http2GetAsync_MissingTrailer_TrailingHeadersAccepted() + { + using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) + using (HttpClient client = CreateHttpClient()) + { + Task sendTask = client.GetAsync(server.Address); + + Http2LoopbackConnection connection = await server.EstablishConnectionAsync(); + + int streamId = await connection.ReadRequestHeaderAsync(); + + // Response header. + await connection.SendDefaultResponseHeadersAsync(streamId); + + // Response data, missing Trailers. + await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes)); + + // Additional trailing header frame. + await connection.SendResponseHeadersAsync(streamId, isTrailingHeader: true, headers: TrailingHeaders, endStream: true); + + HttpResponseMessage response = await sendTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var trailingHeaders = GetTrailingHeaders(response); + Assert.Equal(TrailingHeaders.Count, trailingHeaders.Count()); + Assert.Contains("amazingtrailer", trailingHeaders.GetValues("MyCoolTrailerHeader")); + Assert.Contains("World", trailingHeaders.GetValues("Hello")); + } + } + + [ConditionalFact(nameof(TestsEnabled))] + public async Task Http2GetAsyncResponseHeadersReadOption_TrailingHeaders_Available() + { + using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) + using (HttpClient client = CreateHttpClient()) + { + Task sendTask = client.GetAsync(server.Address, HttpCompletionOption.ResponseHeadersRead); + + Http2LoopbackConnection connection = await server.EstablishConnectionAsync(); + + int streamId = await connection.ReadRequestHeaderAsync(); + + // Response header. + await connection.SendDefaultResponseHeadersAsync(streamId); + + // Response data, missing Trailers. + await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes)); + + HttpResponseMessage response = await sendTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + // Pending read on the response content. + var trailingHeaders = GetTrailingHeaders(response); + Assert.True(trailingHeaders == null || trailingHeaders.Count() == 0); + + Stream stream = await response.Content.ReadAsStreamAsync(TestAsync); + Byte[] data = new Byte[100]; + await stream.ReadAsync(data, 0, data.Length); + + // Intermediate test - haven't reached stream EOF yet. + trailingHeaders = GetTrailingHeaders(response); + Assert.True(trailingHeaders == null || trailingHeaders.Count() == 0); + + // Finish data stream and write out trailing headers. + await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes)); + await connection.SendResponseHeadersAsync(streamId, endStream: true, isTrailingHeader: true, headers: TrailingHeaders); + + // Read data until EOF is reached + while (stream.Read(data, 0, data.Length) != 0) ; + + trailingHeaders = GetTrailingHeaders(response); + Assert.Equal(TrailingHeaders.Count, trailingHeaders.Count()); + Assert.Contains("amazingtrailer", trailingHeaders.GetValues("MyCoolTrailerHeader")); + Assert.Contains("World", trailingHeaders.GetValues("Hello")); + + // Read when already zero. Trailers shouldn't be changed. + stream.Read(data, 0, data.Length); + + trailingHeaders = GetTrailingHeaders(response); + Assert.Equal(TrailingHeaders.Count, trailingHeaders.Count()); + } + } + + [ConditionalFact(nameof(TestsEnabled))] + public async Task Http2GetAsync_TrailerHeaders_TrailingHeaderNoBody() + { + using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) + using (HttpClient client = CreateHttpClient()) + { + Task sendTask = client.GetAsync(server.Address); + + Http2LoopbackConnection connection = await server.EstablishConnectionAsync(); + + int streamId = await connection.ReadRequestHeaderAsync(); + + // Response header. + await connection.SendDefaultResponseHeadersAsync(streamId); + await connection.SendResponseHeadersAsync(streamId, endStream: true, isTrailingHeader: true, headers: TrailingHeaders); + + HttpResponseMessage response = await sendTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var trailingHeaders = GetTrailingHeaders(response); + Assert.Equal(TrailingHeaders.Count, trailingHeaders.Count()); + Assert.Contains("amazingtrailer", trailingHeaders.GetValues("MyCoolTrailerHeader")); + Assert.Contains("World", trailingHeaders.GetValues("Hello")); + } + } + + [ConditionalFact(nameof(TestsEnabled))] + public async Task Http2GetAsync_TrailingHeaders_NoData_EmptyResponseObserved() + { + using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) + using (HttpClient client = CreateHttpClient()) + { + Task sendTask = client.GetAsync(server.Address); + + Http2LoopbackConnection connection = await server.EstablishConnectionAsync(); + + int streamId = await connection.ReadRequestHeaderAsync(); + + // Response header. + await connection.SendDefaultResponseHeadersAsync(streamId); + + // No data. + + // Response trailing headers + await connection.SendResponseHeadersAsync(streamId, isTrailingHeader: true, headers: TrailingHeaders); + + HttpResponseMessage response = await sendTask; + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(Array.Empty(), await response.Content.ReadAsByteArrayAsync()); + + var trailingHeaders = GetTrailingHeaders(response); + Assert.Contains("amazingtrailer", trailingHeaders.GetValues("MyCoolTrailerHeader")); + Assert.Contains("World", trailingHeaders.GetValues("Hello")); + } + } + + private HttpHeaders GetTrailingHeaders(HttpResponseMessage responseMessage) + { +#if !NET48 + return responseMessage.TrailingHeaders; +#else +#pragma warning disable CS0618 // Type or member is obsolete + responseMessage.RequestMessage.Properties.TryGetValue("__ResponseTrailers", out object trailers); +#pragma warning restore CS0618 // Type or member is obsolete + return (HttpHeaders)trailers; +#endif + } + } +} diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/FakeInterop.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/FakeInterop.cs index 596ce8212979b..e26f1976418d6 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/FakeInterop.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/FakeInterop.cs @@ -422,6 +422,12 @@ public static bool WinHttpQueryOption( ref uint buffer, ref uint bufferSize) { + if (option == WINHTTP_OPTION_STREAM_ERROR_CODE) + { + TestControl.LastWin32Error = (int)ERROR_INVALID_PARAMETER; + return false; + } + return true; } diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/System.Net.Http.WinHttpHandler.Unit.Tests.csproj b/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/System.Net.Http.WinHttpHandler.Unit.Tests.csproj index 32e7c9c9e44aa..52b02b402fb79 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/System.Net.Http.WinHttpHandler.Unit.Tests.csproj +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/System.Net.Http.WinHttpHandler.Unit.Tests.csproj @@ -1,9 +1,10 @@ - + $(NoWarn);0436 true ../../src/Resources/Strings.resx $(NetCoreAppCurrent)-windows + UNITTEST annotations @@ -84,6 +85,8 @@ Link="ProductionCode\WinHttpResponseStream.cs" /> + Date: Wed, 10 Mar 2021 14:14:17 +0100 Subject: [PATCH 78/83] jitutils M2M renaming reaction (#49430) * jitutils M2M renaming reaction * Update format.py --- src/tests/Common/scripts/format.py | 2 +- src/tests/Common/scripts/run-pmi-diffs.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/Common/scripts/format.py b/src/tests/Common/scripts/format.py index 47089497631f1..1ba1ecc7ce63a 100644 --- a/src/tests/Common/scripts/format.py +++ b/src/tests/Common/scripts/format.py @@ -118,7 +118,7 @@ def main(argv): elif platform == 'windows': bootstrapFilename = "bootstrap.cmd" - bootstrapUrl = "https://raw.githubusercontent.com/dotnet/jitutils/master/" + bootstrapFilename + bootstrapUrl = "https://raw.githubusercontent.com/dotnet/jitutils/main/" + bootstrapFilename with TempDir() as temp_location: bootstrapPath = os.path.join(temp_location, bootstrapFilename) diff --git a/src/tests/Common/scripts/run-pmi-diffs.py b/src/tests/Common/scripts/run-pmi-diffs.py index a4f1d3ecde718..106137eaeaefd 100755 --- a/src/tests/Common/scripts/run-pmi-diffs.py +++ b/src/tests/Common/scripts/run-pmi-diffs.py @@ -502,7 +502,7 @@ def do_pmi_diffs(): # Clone jitutils - command = 'git clone -b master --single-branch %s %s' % (Jitutils_url, jitutilsPath) + command = 'git clone -b main --single-branch %s %s' % (Jitutils_url, jitutilsPath) log(command) returncode = 0 if testing else os.system(command) if returncode != 0: From 60dc59b8eb93ca6a7fe18e1269949b7af7e5c3bd Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 10 Mar 2021 08:16:22 -0500 Subject: [PATCH 79/83] [mono] Fix the emission of EnumEqualityComparer instances into the corlib AOT image. (#49402) Add a few dummy enums to the Mono namespace in corlib, and use them to create valid EnumEqualityComparer instances. Also make sure the instances are actually emitted and not replaced by gsharedvt instances. Fixes https://github.com/dotnet/runtime/issues/49229. --- .../src/ILLink/ILLink.Descriptors.xml | 9 ++++++ .../src/Mono/RuntimeStructs.cs | 32 +++++++++++++++++++ src/mono/mono/mini/aot-compiler.c | 29 +++++++++++++---- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml index a327adba23fc3..f066b8f010d43 100644 --- a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml +++ b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml @@ -618,6 +618,15 @@ + + + + + + + + + diff --git a/src/mono/System.Private.CoreLib/src/Mono/RuntimeStructs.cs b/src/mono/System.Private.CoreLib/src/Mono/RuntimeStructs.cs index e566558967218..b327ae3733f9e 100644 --- a/src/mono/System.Private.CoreLib/src/Mono/RuntimeStructs.cs +++ b/src/mono/System.Private.CoreLib/src/Mono/RuntimeStructs.cs @@ -118,6 +118,38 @@ internal struct ValueTuple public T5 Item5; } + internal enum I8Enum : byte + { + } + + internal enum UI8Enum : sbyte + { + } + + internal enum I16Enum : short + { + } + + internal enum UI16Enum : ushort + { + } + + internal enum I32Enum : int + { + } + + internal enum UI32Enum : uint + { + } + + internal enum I64Enum : long + { + } + + internal enum UI64Enum : ulong + { + } + internal class NullByRefReturnException : Exception { public NullByRefReturnException() diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 6d97bf9c859bf..b30835fc288fb 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -5185,6 +5185,19 @@ is_vt_inst (MonoGenericInst *inst) return FALSE; } +static gboolean +is_vt_inst_no_enum (MonoGenericInst *inst) +{ + int i; + + for (i = 0; i < inst->type_argc; ++i) { + MonoType *t = inst->type_argv [i]; + if (MONO_TYPE_ISSTRUCT (t)) + return TRUE; + } + return FALSE; +} + static gboolean method_has_type_vars (MonoMethod *method) { @@ -5338,7 +5351,7 @@ add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, * WASM only since other platforms depend on the * previous behavior. */ - if ((acfg->jit_opts & MONO_OPT_GSHAREDVT) && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst (mono_class_get_generic_class (klass)->context.class_inst)) { + if ((acfg->jit_opts & MONO_OPT_GSHAREDVT) && mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst && is_vt_inst_no_enum (mono_class_get_generic_class (klass)->context.class_inst)) { use_gsharedvt = TRUE; use_gsharedvt_for_array = TRUE; } @@ -5758,17 +5771,19 @@ add_generic_instances (MonoAotCompile *acfg) /* Add instances of EnumEqualityComparer which are created by EqualityComparer for enums */ { - MonoClass *enum_comparer; + MonoClass *k, *enum_comparer; MonoType *insts [16]; int ninsts; + const char *enum_names [] = { "I8Enum", "I16Enum", "I32Enum", "I64Enum", "UI8Enum", "UI16Enum", "UI32Enum", "UI64Enum" }; ninsts = 0; - insts [ninsts ++] = int32_type; - insts [ninsts ++] = uint32_type; - insts [ninsts ++] = uint16_type; - insts [ninsts ++] = byte_type; + for (int i = 0; i < G_N_ELEMENTS (enum_names); ++i) { + k = mono_class_try_load_from_name (acfg->image, "Mono", enum_names [i]); + g_assert (k); + insts [ninsts ++] = m_class_get_byval_arg (k); + } enum_comparer = mono_class_load_from_name (mono_defaults.corlib, "System.Collections.Generic", "EnumEqualityComparer`1"); - add_instances_of (acfg, enum_comparer, insts, ninsts, FALSE); + add_instances_of (acfg, enum_comparer, insts, ninsts, TRUE); } /* Add instances of the array generic interfaces for primitive types */ From 647c258a2c826ec6a575b3cdca76980f1ed1474c Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Wed, 10 Mar 2021 09:52:35 -0500 Subject: [PATCH 80/83] [wasm] Fix debugger tests (#49206) * [wasm][debugger] Correctly skip static properties when iterating type .. members. * [wasm][debugger][tests] cleanup * [wasm][debugger][tests] Use SingleLine for the logger --- src/mono/mono/mini/mini-wasm-debugger.c | 3 +++ src/mono/wasm/debugger/BrowserDebugHost/Startup.cs | 6 ++++-- .../wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs | 5 ----- src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs | 5 +++-- .../wasm/debugger/DebuggerTestSuite/TestHarnessProxy.cs | 3 ++- src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs | 2 +- .../wasm/debugger/tests/debugger-test/debugger-cfo-test.cs | 6 ++++++ 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/mono/mono/mini/mini-wasm-debugger.c b/src/mono/mono/mini/mini-wasm-debugger.c index 8795abc655dfa..e93320adebb4a 100644 --- a/src/mono/mono/mini/mini-wasm-debugger.c +++ b/src/mono/mono/mini/mini-wasm-debugger.c @@ -1272,6 +1272,9 @@ describe_object_properties_for_klass (void *obj, MonoClass *klass, gboolean isAs continue; } + if (p->get->flags & METHOD_ATTRIBUTE_STATIC) + continue; + EM_ASM ({ MONO.mono_wasm_add_properties_var ($0, { field_offset: $1, is_own: $2, attr: $3, owner_class: $4 }); }, p->name, pnum, is_own, p->attrs, klass_name); diff --git a/src/mono/wasm/debugger/BrowserDebugHost/Startup.cs b/src/mono/wasm/debugger/BrowserDebugHost/Startup.cs index 0a28e88096272..c4de27f4ee9f6 100644 --- a/src/mono/wasm/debugger/BrowserDebugHost/Startup.cs +++ b/src/mono/wasm/debugger/BrowserDebugHost/Startup.cs @@ -153,8 +153,10 @@ async Task ConnectProxy(HttpContext context) var endpoint = new Uri($"ws://{devToolsHost.Authority}{context.Request.Path}"); try { - using ILoggerFactory loggerFactory = LoggerFactory.Create( - builder => builder.AddConsole().AddFilter(null, LogLevel.Information)); + using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => + builder.AddSimpleConsole(options => options.SingleLine = true) + .AddFilter(null, LogLevel.Information) + ); context.Request.Query.TryGetValue("urlSymbolServer", out StringValues urlSymbolServerList); var proxy = new DebuggerProxy(loggerFactory, urlSymbolServerList.ToList()); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs index 1e9f155b19f16..fdd23b0f58f81 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs @@ -5,13 +5,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net.WebSockets; using System.Reflection; -using System.Text; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; using Microsoft.WebAssembly.Diagnostics; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -430,7 +426,6 @@ internal async Task SendCommandAndCheck(JObject args, string method, st AssertEqual(function_name, wait_res["callFrames"]?[0]?["functionName"]?.Value(), top_frame?.ToString()); } - Console.WriteLine(top_frame); if (script_loc != null && line >= 0) CheckLocation(script_loc, line, column, scripts, top_frame["location"]); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs b/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs index 8c9edc677cc45..c555cd0439767 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/Inspector.cs @@ -41,8 +41,9 @@ public Inspector() _cancellationTokenSource = new CancellationTokenSource(); Token = _cancellationTokenSource.Token; - _loggerFactory = LoggerFactory.Create( - builder => builder.AddConsole().AddFilter(null, LogLevel.Trace)); + _loggerFactory = LoggerFactory.Create(builder => + builder.AddSimpleConsole(options => options.SingleLine = true) + .AddFilter(null, LogLevel.Trace)); Client = new InspectorClient(_loggerFactory.CreateLogger()); _logger = _loggerFactory.CreateLogger(); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/TestHarnessProxy.cs b/src/mono/wasm/debugger/DebuggerTestSuite/TestHarnessProxy.cs index d50a845494931..7a5c30d9cc9e8 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/TestHarnessProxy.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/TestHarnessProxy.cs @@ -38,7 +38,8 @@ public static Task Start(string chromePath, string appPath, string pagePath) }) .ConfigureLogging(logging => { - logging.AddConsole(); + logging.AddSimpleConsole(options => options.SingleLine = true) + .AddFilter(null, LogLevel.Information); }) .ConfigureServices((ctx, services) => { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs index 9e964558b5244..d16844783c948 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs @@ -718,7 +718,7 @@ await CompareObjectPropertiesFor(frame_locals, "dto", Day = TNumber(2), Year = TNumber(2020), DayOfWeek = TEnum("System.DayOfWeek", "Thursday") - }, "dto_props", num_fields: 22); + }, "dto_props", num_fields: 20); var DT = new DateTime(2004, 10, 15, 1, 2, 3); var DTO = new DateTimeOffset(dt0, new TimeSpan(2, 14, 0)); diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-cfo-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-cfo-test.cs index 66a964a280817..31dfe11d1e603 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-cfo-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-cfo-test.cs @@ -58,6 +58,9 @@ class ClassWithProperties public DateTime[] DTArray { get { return new DateTime[] { new DateTime(6, 7, 8, 9, 10, 11), new DateTime(1, 2, 3, 4, 5, 6) }; } } public DateTime DTAutoProperty { get; set; } public string StringField; + + private static DateTime PrivateStaticDTProp => new DateTime(6, 5, 4, 3, 2, 1); + public static DateTime PublicStaticDTProp => new DateTime(3, 6, 1, 7, 9, 4); } struct StructWithProperties @@ -71,5 +74,8 @@ struct StructWithProperties public DateTime[] DTArray { get { return new DateTime[] { new DateTime(6, 7, 8, 9, 10, 11), new DateTime(1, 2, 3, 4, 5, 6) }; } } public DateTime DTAutoProperty { get; set; } public string StringField; + + private static DateTime PrivateStaticDTProp => new DateTime(6, 5, 4, 3, 2, 1); + public static DateTime PublicStaticDTProp => new DateTime(3, 6, 1, 7, 9, 4); } } From 21c739706c71a09fd5553487aacdb9cc1b37552e Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Wed, 10 Mar 2021 15:54:32 +0000 Subject: [PATCH 81/83] improve PriorityQueue documentation (#49392) --- .../Collections/Generic/PriorityQueue.cs | 159 ++++++++++++++---- 1 file changed, 125 insertions(+), 34 deletions(-) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs index 554f7f0e84c40..5918bc1a62915 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs @@ -8,11 +8,14 @@ namespace System.Collections.Generic { /// - /// Represents a data structure in which each element has an associated priority - /// that determines the order in which the pair is dequeued. + /// Represents a min priority queue. /// - /// The type of the element. - /// The type of the priority. + /// Specifies the type of elements in the queue. + /// Specifies the type of priority associated with enqueued elements. + /// + /// Implements an array-backed quaternary min-heap. Each element is enqueued with an associated priority + /// that determines the dequeue order: elements with the lowest priority get dequeued first. + /// [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(PriorityQueueDebugView<,>))] public class PriorityQueue @@ -61,7 +64,7 @@ static PriorityQueue() #endif /// - /// Creates an empty priority queue. + /// Initializes a new instance of the class. /// public PriorityQueue() { @@ -70,16 +73,26 @@ public PriorityQueue() } /// - /// Creates an empty priority queue with the specified initial capacity for its underlying array. + /// Initializes a new instance of the class + /// with the specified initial capacity. /// + /// Initial capacity to allocate in the underlying heap array. + /// + /// The specified was negative. + /// public PriorityQueue(int initialCapacity) : this(initialCapacity, comparer: null) { } /// - /// Creates an empty priority queue with the specified priority comparer. + /// Initializes a new instance of the class + /// with the specified custom priority comparer. /// + /// + /// Custom comparer dictating the ordering of elements. + /// Uses if the argument is . + /// public PriorityQueue(IComparer? comparer) { _nodes = Array.Empty<(TElement, TPriority)>(); @@ -87,9 +100,17 @@ public PriorityQueue(IComparer? comparer) } /// - /// Creates an empty priority queue with the specified priority comparer and - /// the specified initial capacity for its underlying array. + /// Initializes a new instance of the class + /// with the specified initial capacity and custom priority comparer. /// + /// Initial capacity to allocate in the underlying heap array. + /// + /// Custom comparer dictating the ordering of elements. + /// Uses if the argument is . + /// + /// + /// The specified was negative. + /// public PriorityQueue(int initialCapacity, IComparer? comparer) { if (initialCapacity < 0) @@ -103,17 +124,39 @@ public PriorityQueue(int initialCapacity, IComparer? comparer) } /// - /// Creates a priority queue populated with the specified elements and priorities. + /// Initializes a new instance of the class + /// that is populated with the specified elements and priorities. /// + /// The pairs of elements and priorities with which to populate the queue. + /// + /// The specified argument was . + /// + /// + /// Constructs the heap using a heapify operation, + /// which is generally faster than enqueuing individual elements sequentially. + /// public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> items) : this(items, comparer: null) { } /// - /// Creates a priority queue populated with the specified elements and priorities, - /// and with the specified priority comparer. - /// + /// Initializes a new instance of the class + /// that is populated with the specified elements and priorities, + /// and with the specified custom priority comparer. + /// + /// The pairs of elements and priorities with which to populate the queue. + /// + /// Custom comparer dictating the ordering of elements. + /// Uses if the argument is . + /// + /// + /// The specified argument was . + /// + /// + /// Constructs the heap using a heapify operation, + /// which is generally faster than enqueuing individual elements sequentially. + /// public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> items, IComparer? comparer) { if (items is null) @@ -131,23 +174,29 @@ public PriorityQueue(IEnumerable<(TElement Element, TPriority Priority)> items, } /// - /// Gets the current amount of items in the priority queue. + /// Gets the number of elements contained in the . /// public int Count => _size; /// - /// Gets the priority comparer of the priority queue. + /// Gets the priority comparer used by the . /// public IComparer Comparer => _comparer ?? Comparer.Default; /// - /// Gets a collection that enumerates the elements of the queue. + /// Gets a collection that enumerates the elements of the queue in an unordered manner. /// + /// + /// The enumeration does not order items by priority, since that would require N * log(N) time and N space. + /// Items are instead enumerated following the internal array heap layout. + /// public UnorderedItemsCollection UnorderedItems => _unorderedItems ??= new UnorderedItemsCollection(this); /// - /// Enqueues the specified element and associates it with the specified priority. + /// Adds the specified element with associated priority to the . /// + /// The element to add to the . + /// The priority with which to associate the new element. public void Enqueue(TElement element, TPriority priority) { // Virtually add the node at the end of the underlying array. @@ -173,9 +222,10 @@ public void Enqueue(TElement element, TPriority priority) } /// - /// Gets the element associated with the minimal priority. + /// Returns the minimal element from the without removing it. /// - /// The queue is empty. + /// The is empty. + /// The minimal element of the . public TElement Peek() { if (_size == 0) @@ -187,9 +237,10 @@ public TElement Peek() } /// - /// Dequeues the element associated with the minimal priority. + /// Removes and returns the minimal element from the . /// /// The queue is empty. + /// The minimal element of the . public TElement Dequeue() { if (_size == 0) @@ -203,10 +254,15 @@ public TElement Dequeue() } /// - /// Dequeues the element associated with the minimal priority + /// Removes the minimal element from the , + /// and copies it to the parameter, + /// and its associated priority to the parameter. /// + /// The removed element. + /// The priority associated with the removed element. /// - /// if the priority queue is non-empty; otherwise. + /// if the element is successfully removed; + /// if the is empty. /// public bool TryDequeue([MaybeNullWhen(false)] out TElement element, [MaybeNullWhen(false)] out TPriority priority) { @@ -223,10 +279,16 @@ public bool TryDequeue([MaybeNullWhen(false)] out TElement element, [MaybeNullWh } /// - /// Gets the element associated with the minimal priority. + /// Returns a value that indicates whether there is a minimal element in the , + /// and if one is present, copies it to the parameter, + /// and its associated priority to the parameter. + /// The element is not removed from the . /// + /// The minimal element in the queue. + /// The priority associated with the minimal element. /// - /// if the priority queue is non-empty; otherwise. + /// if there is a minimal element; + /// if the is empty. /// public bool TryPeek([MaybeNullWhen(false)] out TElement element, [MaybeNullWhen(false)] out TPriority priority) { @@ -242,8 +304,17 @@ public bool TryPeek([MaybeNullWhen(false)] out TElement element, [MaybeNullWhen( } /// - /// Combined enqueue/dequeue operation, generally more efficient than sequential Enqueue/Dequeue calls. + /// Adds the specified element with associated priority to the , + /// and immediately removes the minimal element, returning the result. /// + /// The element to add to the . + /// The priority with which to associate the new element. + /// The minimal element removed after the enqueue operation. + /// + /// Implements an insert-then-extract heap operation that is generally more efficient + /// than sequencing Enqueue and Dequeue operations: in the worst case scenario only one + /// sift-down operation is required. + /// public TElement EnqueueDequeue(TElement element, TPriority priority) { if (_size != 0) @@ -274,8 +345,12 @@ public TElement EnqueueDequeue(TElement element, TPriority priority) } /// - /// Enqueues a collection of element/priority pairs. + /// Enqueues a sequence of element/priority pairs to the . /// + /// The pairs of elements and priorities to add to the queue. + /// + /// The specified argument was . + /// public void EnqueueRange(IEnumerable<(TElement Element, TPriority Priority)> items) { if (items is null) @@ -308,8 +383,14 @@ public void EnqueueRange(IEnumerable<(TElement Element, TPriority Priority)> ite } /// - /// Enqueues a collection of elements, each associated with the specified priority. + /// Enqueues a sequence of elements pairs to the , + /// all associated with the specified priority. /// + /// The elements to add to the queue. + /// The priority to associate with the new elements. + /// + /// The specified argument was . + /// public void EnqueueRange(IEnumerable elements, TPriority priority) { if (elements is null) @@ -353,7 +434,7 @@ public void EnqueueRange(IEnumerable elements, TPriority priority) } /// - /// Removes all items from the priority queue. + /// Removes all items from the . /// public void Clear() { @@ -367,9 +448,14 @@ public void Clear() } /// - /// Ensures that the priority queue has the specified capacity - /// and resizes its underlying array if necessary. + /// Ensures that the can hold up to + /// items without further expansion of its backing storage. /// + /// The minimum capacity to be used. + /// + /// The specified is negative. + /// + /// The current capacity of the . public int EnsureCapacity(int capacity) { if (capacity < 0) @@ -387,9 +473,13 @@ public int EnsureCapacity(int capacity) } /// - /// Sets the capacity to the actual number of items in the priority queue, - /// if that is less than 90 percent of current capacity. + /// Sets the capacity to the actual number of items in the , + /// if that is less than 90 percent of current capacity. /// + /// + /// This method can be used to minimize a collection's memory overhead + /// if no new elements will be added to the collection. + /// public void TrimExcess() { int threshold = (int)(_nodes.Length * 0.9); @@ -677,7 +767,7 @@ private void MoveDownCustomComparer((TElement Element, TPriority Priority) node, } /// - /// Represents the contents of a without ordering. + /// Enumerates the contents of a , without any ordering guarantees. /// [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(PriorityQueueDebugView<,>))] @@ -729,7 +819,8 @@ void ICollection.CopyTo(Array array, int index) } /// - /// Enumerates the element and priority pairs of a . + /// Enumerates the element and priority pairs of a , + /// without any ordering guarantees. /// public struct Enumerator : IEnumerator<(TElement Element, TPriority Priority)> { From 34294fabcb7641943b65e5afc99c7a567e1307c5 Mon Sep 17 00:00:00 2001 From: Steve MacLean Date: Wed, 10 Mar 2021 12:02:50 -0500 Subject: [PATCH 82/83] [macOS-arm64] Disable failing libraries tests (#49400) * Disable tests for XUnit crashes on Apple Silicon * Apple Silicon Disable System.IO.MemoryMappedFiles.Tests * Apple Silicon disable DirectoryServices.Protocols.Tests * Apple Silicon disable Cryptography tests M1 helix missing usable libssl * Apple Silicon disable TestVirtualMemorySize64 * Apple Silicon disable ImportCollectionsFromContainerOnly * Apple Silicon disable XmlWriterApi tests * Fix whitespace --- ...sions.DependencyInjection.ExternalContainers.Tests.csproj | 3 +++ .../ComponentModel/Composition/ExportCollectionTests.cs | 1 + .../System.Diagnostics.Process/tests/ProcessTests.cs | 1 + .../tests/AsqRequestControlTests.cs | 1 + .../tests/BerConversionExceptionTests.cs | 1 + .../tests/BerConverterTests.cs | 1 + .../tests/DirSyncRequestControlTests.cs | 1 + .../tests/DirectoryControlTests.cs | 1 + .../tests/DirectoryServicesProtocolsTests.cs | 1 + .../tests/ExtendedDNControlTests.cs | 1 + .../tests/PageResultRequestControlTests.cs | 1 + .../tests/QuotaControlTests.cs | 1 + .../tests/SearchOptionsControlTests.cs | 1 + .../tests/SecurityDescriptorFlagControlTests.cs | 1 + .../tests/VerifyNameControlTests.cs | 1 + .../tests/VlvRequestControlTests.cs | 1 + .../tests/System.IO.FileSystem.Watcher.Tests.csproj | 3 +++ .../tests/MemoryMappedFile.CreateNew.Tests.cs | 1 + .../tests/MemoryMappedViewAccessor.Tests.cs | 1 + .../tests/MemoryMappedViewStream.Tests.cs | 1 + .../tests/MemoryMappedViewStreamConformanceTests.cs | 1 + .../tests/System.Linq.Expressions.Tests.csproj | 3 +++ .../tests/System.Numerics.Vectors.Tests.csproj | 3 +++ .../tests/UnitTests/System.Private.Uri.Unit.Tests.csproj | 5 ++++- .../tests/Misc/System.Xml.Misc.Tests.csproj | 5 ++++- .../tests/Writers/XmlWriterApi/EndOfLineHandlingTests.cs | 1 + .../tests/Writers/XmlWriterApi/ErrorCondition.cs | 1 + .../Writers/XmlWriterApi/WriteEndDocumentOnCloseTest.cs | 1 + .../System.Xml.Xsl.XslCompiledTransformApi.Tests.csproj | 5 ++++- .../System.Runtime/tests/System.Runtime.Tests.csproj | 3 +++ .../System.Security.Cryptography.Algorithms.Tests.csproj | 3 +++ .../tests/System.Security.Cryptography.OpenSsl.Tests.csproj | 3 +++ .../System.Text.Json/tests/System.Text.Json.Tests.csproj | 3 +++ .../tests/System.Text.RegularExpressions.Tests.csproj | 3 +++ .../tests/System.Threading.Tasks.Parallel.Tests.csproj | 3 +++ 35 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.External.Tests/Microsoft.Extensions.DependencyInjection.ExternalContainers.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.External.Tests/Microsoft.Extensions.DependencyInjection.ExternalContainers.Tests.csproj index e74abce985bf8..5b048b60cdc8d 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.External.Tests/Microsoft.Extensions.DependencyInjection.ExternalContainers.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.External.Tests/Microsoft.Extensions.DependencyInjection.ExternalContainers.Tests.csproj @@ -4,6 +4,9 @@ $(NetCoreAppCurrent);net461 true $(NoWarn);CS8002 + + true diff --git a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/ExportCollectionTests.cs b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/ExportCollectionTests.cs index 2bdbd73252c30..6a6cad837a877 100644 --- a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/ExportCollectionTests.cs +++ b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/ExportCollectionTests.cs @@ -142,6 +142,7 @@ public class ExporterDefault42 [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/31792", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49365", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] [Trait("Type", "Integration")] public void ImportCollectionsFromContainerOnly() { diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs index f97ba57d8ec72..d6333e67747ad 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs @@ -735,6 +735,7 @@ public void PrivateMemorySize64_GetNotStarted_ThrowsInvalidOperationException() } [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49107", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public void TestVirtualMemorySize64() { CreateDefaultProcess(); diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs index d2704307152d5..6391870ef11aa 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs @@ -8,6 +8,7 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class AsqRequestControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/BerConversionExceptionTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/BerConversionExceptionTests.cs index b0a47bad6fe64..4a474ec57eae1 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/BerConversionExceptionTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/BerConversionExceptionTests.cs @@ -9,6 +9,7 @@ namespace System.DirectoryServices.Protocols.Tests { + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class BerConversionExceptionTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs index d47ecba69a09c..d636a88989881 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs @@ -9,6 +9,7 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class BerConverterTests { public static IEnumerable Encode_TestData() diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs index da6bcfbdf5b69..847f482176d7d 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs @@ -8,6 +8,7 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class DirSyncRequestControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryControlTests.cs index 32d2b36f06249..4f79e81c83ec1 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryControlTests.cs @@ -5,6 +5,7 @@ namespace System.DirectoryServices.Protocols.Tests { + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class DirectoryControlTests { [Theory] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs index 00d56e12bc8d1..1329fa83a6cff 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs @@ -10,6 +10,7 @@ namespace System.DirectoryServices.Protocols.Tests { + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public partial class DirectoryServicesProtocolsTests { internal static bool IsLdapConfigurationExist => LdapConfiguration.Configuration != null; diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs index 284d916613b23..a7c571598d7c2 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs @@ -8,6 +8,7 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class ExtendedDNControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs index 537874c7f4fbd..e6f10e4bddc7e 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs @@ -8,6 +8,7 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class PageResultRequestControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs index b1ddaa9efa8e8..033865e1353d9 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs @@ -9,6 +9,7 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class QuotaControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs index 2a30d7dc3a522..c173904caaaef 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs @@ -8,6 +8,7 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class SearchOptionsControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs index 6ec7955faa782..47ceca06e70a5 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs @@ -8,6 +8,7 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class SecurityDescriptorFlagControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs index 5e7469d27ed01..c6edf3487253d 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs @@ -8,6 +8,7 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class VerifyNameControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs index a259bd11c7e8a..4ea87e1a5f6ec 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs @@ -8,6 +8,7 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class VlvRequestControlTests { [Fact] diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj b/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj index 6198325a2dfb7..15e15be33edb3 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj +++ b/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj @@ -2,6 +2,9 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-FreeBSD + + true diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateNew.Tests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateNew.Tests.cs index 76cf9ca2a3882..0d771fc85dab5 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateNew.Tests.cs +++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateNew.Tests.cs @@ -11,6 +11,7 @@ namespace System.IO.MemoryMappedFiles.Tests /// /// Tests for MemoryMappedFile.CreateNew. /// + [ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class MemoryMappedFileTests_CreateNew : MemoryMappedFilesTestBase { /// diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs index 1e3d69124cb51..0e0f76284dfeb 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs +++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs @@ -11,6 +11,7 @@ namespace System.IO.MemoryMappedFiles.Tests /// /// Tests for MemoryMappedViewAccessor. /// + [ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class MemoryMappedViewAccessorTests : MemoryMappedFilesTestBase { /// diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs index e6d40a8808a63..f8c073d86a269 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs +++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs @@ -11,6 +11,7 @@ namespace System.IO.MemoryMappedFiles.Tests /// /// Tests for MemoryMappedViewStream. /// + [ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class MemoryMappedViewStreamTests : MemoryMappedFilesTestBase { /// diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStreamConformanceTests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStreamConformanceTests.cs index c190d329a00fe..e84a86a91f20c 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStreamConformanceTests.cs +++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStreamConformanceTests.cs @@ -45,6 +45,7 @@ private Task CreateStream(byte[] initialData, FileAccess access) } } + [ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class AnonymousMemoryMappedViewStreamConformanceTests : MemoryMappedViewStreamConformanceTests { protected override MemoryMappedFile CreateFile(int length) => diff --git a/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj b/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj index b0a74eabbce8f..4b7fc689beb8b 100644 --- a/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj +++ b/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj @@ -5,6 +5,9 @@ $(DefineConstants);FEATURE_COMPILE $(DefineConstants);FEATURE_INTERPRET $(NetCoreAppCurrent) + + true diff --git a/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj b/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj index c8cff8865d09d..057f0f6240fbc 100644 --- a/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj +++ b/src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj @@ -3,6 +3,9 @@ true $(NetCoreAppCurrent) true + + true diff --git a/src/libraries/System.Private.Uri/tests/UnitTests/System.Private.Uri.Unit.Tests.csproj b/src/libraries/System.Private.Uri/tests/UnitTests/System.Private.Uri.Unit.Tests.csproj index 99d7b269e7a98..b83cd467a556f 100644 --- a/src/libraries/System.Private.Uri/tests/UnitTests/System.Private.Uri.Unit.Tests.csproj +++ b/src/libraries/System.Private.Uri/tests/UnitTests/System.Private.Uri.Unit.Tests.csproj @@ -5,6 +5,9 @@ ../../src/Resources/Strings.resx $(NetCoreAppCurrent) enable + + true @@ -22,4 +25,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Private.Xml/tests/Misc/System.Xml.Misc.Tests.csproj b/src/libraries/System.Private.Xml/tests/Misc/System.Xml.Misc.Tests.csproj index 212a6f9731f3a..c833fa31e9135 100644 --- a/src/libraries/System.Private.Xml/tests/Misc/System.Xml.Misc.Tests.csproj +++ b/src/libraries/System.Private.Xml/tests/Misc/System.Xml.Misc.Tests.csproj @@ -2,8 +2,11 @@ XmlMiscTests $(NetCoreAppCurrent) + + true - \ No newline at end of file + diff --git a/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/EndOfLineHandlingTests.cs b/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/EndOfLineHandlingTests.cs index 471ec72f5e057..cc59961e18570 100644 --- a/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/EndOfLineHandlingTests.cs +++ b/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/EndOfLineHandlingTests.cs @@ -9,6 +9,7 @@ namespace System.Xml.Tests { + [ActiveIssue("https://github.com/dotnet/runtime/issues/49365", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public partial class TCEOFHandling { private static NewLineHandling[] s_nlHandlingMembers = { NewLineHandling.Entitize, NewLineHandling.Replace, NewLineHandling.None }; diff --git a/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/ErrorCondition.cs b/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/ErrorCondition.cs index 2fdf040281926..b2bcfbb3cabc3 100644 --- a/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/ErrorCondition.cs +++ b/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/ErrorCondition.cs @@ -10,6 +10,7 @@ namespace System.Xml.Tests { + [ActiveIssue("https://github.com/dotnet/runtime/issues/49365", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public partial class TCErrorConditionWriter// : XmlWriterTestCaseBase { public static string file = "writerErr.out"; diff --git a/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/WriteEndDocumentOnCloseTest.cs b/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/WriteEndDocumentOnCloseTest.cs index 17cdd255b89d4..bcb77b319f4bc 100644 --- a/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/WriteEndDocumentOnCloseTest.cs +++ b/src/libraries/System.Private.Xml/tests/Writers/XmlWriterApi/WriteEndDocumentOnCloseTest.cs @@ -7,6 +7,7 @@ namespace System.Xml.Tests { + [ActiveIssue("https://github.com/dotnet/runtime/issues/49365", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public partial class TCWriteEndDocumentOnCloseTest { [Theory] diff --git a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/System.Xml.Xsl.XslCompiledTransformApi.Tests.csproj b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/System.Xml.Xsl.XslCompiledTransformApi.Tests.csproj index d9d8f1aa2f51c..d1d40a593739a 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/System.Xml.Xsl.XslCompiledTransformApi.Tests.csproj +++ b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/System.Xml.Xsl.XslCompiledTransformApi.Tests.csproj @@ -1,6 +1,9 @@ $(NetCoreAppCurrent) + + true @@ -33,4 +36,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj index e4b0b3580f585..d8ab9e64e36a8 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj @@ -6,6 +6,9 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser disable + + true true true + + true $(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser + + true diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj index dbebf9b1814f3..a9b2e55289650 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj @@ -4,6 +4,9 @@ true CS0618 + + true diff --git a/src/libraries/System.Text.RegularExpressions/tests/System.Text.RegularExpressions.Tests.csproj b/src/libraries/System.Text.RegularExpressions/tests/System.Text.RegularExpressions.Tests.csproj index 45fe74f628769..a3059d1ba34bd 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/System.Text.RegularExpressions.Tests.csproj +++ b/src/libraries/System.Text.RegularExpressions/tests/System.Text.RegularExpressions.Tests.csproj @@ -4,6 +4,9 @@ $(NoWarn);xUnit2008 $(NetCoreAppCurrent);net48 + + true diff --git a/src/libraries/System.Threading.Tasks.Parallel/tests/System.Threading.Tasks.Parallel.Tests.csproj b/src/libraries/System.Threading.Tasks.Parallel/tests/System.Threading.Tasks.Parallel.Tests.csproj index c26f5f363a042..635223250e1f4 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/tests/System.Threading.Tasks.Parallel.Tests.csproj +++ b/src/libraries/System.Threading.Tasks.Parallel/tests/System.Threading.Tasks.Parallel.Tests.csproj @@ -2,6 +2,9 @@ true $(NetCoreAppCurrent) + + true From e592acad41db4473baa259cb2d7df062c82bac70 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 10 Mar 2021 12:11:50 -0500 Subject: [PATCH 83/83] Fix a crash in llvm if the sreg of a setret is not set because the methods ends with a throw. (#49122) --- src/mono/mono/mini/mini-llvm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 7dcc4b71a810d..3a7cb5b81d3dc 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -5227,7 +5227,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) /* The return type is an LLVM aggregate type, so a bare bitcast cannot be used to do this conversion. */ int width = mono_type_size (sig->ret, NULL); int elems = width / TARGET_SIZEOF_VOID_P; - LLVMValueRef val = LLVMBuildBitCast (builder, values [ins->sreg1], LLVMVectorType (IntPtrType (), elems), ""); + /* The return value might not be set if there is a throw */ + LLVMValueRef val = lhs ? LLVMBuildBitCast (builder, lhs, LLVMVectorType (IntPtrType (), elems), "") : LLVMConstNull (LLVMVectorType (IntPtrType (), elems)); for (int i = 0; i < elems; ++i) { LLVMValueRef element = LLVMBuildExtractElement (builder, val, const_int32 (i), ""); retval = LLVMBuildInsertValue (builder, retval, element, i, "setret_simd_vtype_in_reg");