summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Runtime/CompilerServices
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Runtime/CompilerServices')
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs1
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs43
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs60
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs2
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs1
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs366
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs1
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs1
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs1
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs18
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs1
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/ITuple.cs22
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs1
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs1
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs4
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs6
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs1
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs9
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs57
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs12
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs13
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs1
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs2
23 files changed, 408 insertions, 216 deletions
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs
index b0010fd7bd..34e66beade 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs
@@ -9,7 +9,6 @@ namespace System.Runtime.CompilerServices
using System;
[AttributeUsage(AttributeTargets.Field)]
-[System.Runtime.InteropServices.ComVisible(true)]
public sealed class AccessedThroughPropertyAttribute : Attribute
{
private readonly string propertyName;
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs
deleted file mode 100644
index c021353475..0000000000
--- a/src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-namespace System.Runtime.CompilerServices {
-
- using System;
-
- // NOTE TO DEVELOPERS: These classes are used by ALink (the assembly linker).
- // They're used for metadata tokens for making multi-module assemblies.
- // Do not randomly touch these classes.
- [System.Runtime.CompilerServices.FriendAccessAllowed]
- internal sealed class AssemblyAttributesGoHere
- {
-
- internal AssemblyAttributesGoHere()
- {
- }
- }
- [System.Runtime.CompilerServices.FriendAccessAllowed]
- internal sealed class AssemblyAttributesGoHereS
- {
- internal AssemblyAttributesGoHereS()
- {
- }
- }
- [System.Runtime.CompilerServices.FriendAccessAllowed]
- internal sealed class AssemblyAttributesGoHereM
- {
- internal AssemblyAttributesGoHereM()
- {
- }
- }
- [System.Runtime.CompilerServices.FriendAccessAllowed]
- internal sealed class AssemblyAttributesGoHereSM
- {
- internal AssemblyAttributesGoHereSM()
- {
- }
- }
-}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
index 6a16462383..afb0c22778 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
@@ -18,7 +18,6 @@ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Runtime.ExceptionServices;
using System.Security;
-using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
@@ -840,36 +839,6 @@ namespace System.Runtime.CompilerServices
// This method is copy&pasted into the public Start methods to avoid size overhead of valuetype generic instantiations.
// Ideally, we would build intrinsics to get the raw ref address and raw code address of MoveNext, and just use the shared implementation.
-#if false
- /// <summary>Initiates the builder's execution with the associated state machine.</summary>
- /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
- /// <param name="stateMachine">The state machine instance, passed by reference.</param>
- /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument is null (Nothing in Visual Basic).</exception>
- [DebuggerStepThrough]
- internal static void Start<TStateMachine>(ref TStateMachine stateMachine)
- where TStateMachine : IAsyncStateMachine
- {
- if (stateMachine == null) throw new ArgumentNullException(nameof(stateMachine));
- Contract.EndContractBlock();
-
- // Run the MoveNext method within a copy-on-write ExecutionContext scope.
- // This allows us to undo any ExecutionContext changes made in MoveNext,
- // so that they won't "leak" out of the first await.
-
- Thread currentThread = Thread.CurrentThread;
- ExecutionContextSwitcher ecs = default(ExecutionContextSwitcher);
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- ExecutionContext.EstablishCopyOnWriteScope(currentThread, ref ecs);
- stateMachine.MoveNext();
- }
- finally
- {
- ecs.Undo(currentThread);
- }
- }
-#endif
/// <summary>Associates the builder with the state machine it represents.</summary>
/// <param name="stateMachine">The heap-allocated state machine object.</param>
@@ -906,12 +875,12 @@ namespace System.Runtime.CompilerServices
Debugger.NotifyOfCrossThreadDependency();
// The builder needs to flow ExecutionContext, so capture it.
- var capturedContext = ExecutionContext.FastCapture(); // ok to use FastCapture as we haven't made any permission demands/asserts
+ var capturedContext = ExecutionContext.Capture();
// If the ExecutionContext is the default context, try to use a cached delegate, creating one if necessary.
Action action;
MoveNextRunner runner;
- if (capturedContext != null && capturedContext.IsPreAllocatedDefault)
+ if (capturedContext == ExecutionContext.Default)
{
// Get the cached delegate, and if it's non-null, return it.
action = m_defaultContextAction;
@@ -1046,12 +1015,8 @@ namespace System.Runtime.CompilerServices
if (m_context != null)
{
- try
- {
- // Use the context and callback to invoke m_stateMachine.MoveNext.
- ExecutionContext.Run(m_context, InvokeMoveNextCallback, m_stateMachine, preserveSyncCtx: true);
- }
- finally { m_context.Dispose(); }
+ // Use the context and callback to invoke m_stateMachine.MoveNext.
+ ExecutionContext.Run(m_context, InvokeMoveNextCallback, m_stateMachine);
}
else
{
@@ -1076,24 +1041,11 @@ namespace System.Runtime.CompilerServices
internal void RunWithDefaultContext()
{
Debug.Assert(m_stateMachine != null, "The state machine must have been set before calling Run.");
- ExecutionContext.Run(ExecutionContext.PreAllocatedDefault, InvokeMoveNextCallback, m_stateMachine, preserveSyncCtx: true);
+ ExecutionContext.Run(ExecutionContext.Default, InvokeMoveNextCallback, m_stateMachine);
}
/// <summary>Gets a delegate to the InvokeMoveNext method.</summary>
- protected static ContextCallback InvokeMoveNextCallback
- {
- get { return s_invokeMoveNext ?? (s_invokeMoveNext = InvokeMoveNext); }
- }
-
- /// <summary>Cached delegate used with ExecutionContext.Run.</summary>
- private static ContextCallback s_invokeMoveNext; // lazily-initialized due to SecurityCritical attribution
-
- /// <summary>Invokes the MoveNext method on the supplied IAsyncStateMachine.</summary>
- /// <param name="stateMachine">The IAsyncStateMachine machine instance.</param>
- private static void InvokeMoveNext(object stateMachine)
- {
- ((IAsyncStateMachine)stateMachine).MoveNext();
- }
+ protected static readonly ContextCallback InvokeMoveNextCallback = sm => ((IAsyncStateMachine)sm).MoveNext();
}
/// <summary>
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs
index 5e4f19410b..c3679b610c 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs
@@ -13,7 +13,6 @@ namespace System.Runtime.CompilerServices
/// IMPORTANT: Keep this in sync with corhdr.h
[Serializable]
[Flags]
-[System.Runtime.InteropServices.ComVisible(true)]
public enum CompilationRelaxations : int
{
NoStringInterning = 0x0008, // Start in 0x0008, we had other non public flags in this enum before,
@@ -23,7 +22,6 @@ namespace System.Runtime.CompilerServices
[Serializable]
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Method)]
-[System.Runtime.InteropServices.ComVisible(true)]
public class CompilationRelaxationsAttribute : Attribute
{
private int m_relaxations; // The relaxations.
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs
index 65755f6baa..1cd830cfca 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs
@@ -18,7 +18,6 @@ namespace System.Runtime.CompilerServices
{
[Serializable]
[AttributeUsage(AttributeTargets.Class)]
- [System.Runtime.InteropServices.ComVisible(true)]
public class CompilerGlobalScopeAttribute : Attribute
{
public CompilerGlobalScopeAttribute () {}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
index 74559673bb..4b2648ba6f 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
@@ -46,7 +46,6 @@
** expose the full public surface area.
**
**
-**
** Thread safety guarantees:
**
** ConditionalWeakTable is fully thread-safe and requires no
@@ -60,6 +59,7 @@
** may be delayed until appdomain shutdown.
===========================================================*/
+using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
@@ -67,8 +67,7 @@ using System.Threading;
namespace System.Runtime.CompilerServices
{
#region ConditionalWeakTable
- [ComVisible(false)]
- public sealed class ConditionalWeakTable<TKey, TValue>
+ public sealed class ConditionalWeakTable<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
where TKey : class
where TValue : class
{
@@ -76,6 +75,7 @@ namespace System.Runtime.CompilerServices
private const int InitialCapacity = 8; // Initial length of the table. Must be a power of two.
private readonly object _lock; // This lock protects all mutation of data in the table. Readers do not take this lock.
private volatile Container _container; // The actual storage for the table; swapped out as the table grows.
+ private int _activeEnumeratorRefCount; // The number of outstanding enumerators on the table
#endregion
#region Constructors
@@ -190,6 +190,34 @@ namespace System.Runtime.CompilerServices
}
}
+ //--------------------------------------------------------------------------------------------
+ // Clear all the key/value pairs
+ //--------------------------------------------------------------------------------------------
+ public void Clear()
+ {
+ lock (_lock)
+ {
+ // To clear, we would prefer to simply drop the existing container
+ // and replace it with an empty one, as that's overall more efficient.
+ // However, if there are any active enumerators, we don't want to do
+ // that as it will end up removing all of the existing entries and
+ // allowing new items to be added at the same indices when the container
+ // is filled and replaced, and one of the guarantees we try to make with
+ // enumeration is that new items added after enumeration starts won't be
+ // included in the enumeration. As such, if there are active enumerators,
+ // we simply use the container's removal functionality to remove all of the
+ // keys; then when the table is resized, if there are still active enumerators,
+ // these empty slots will be maintained.
+ if (_activeEnumeratorRefCount > 0)
+ {
+ _container.RemoveAllKeys();
+ }
+ else
+ {
+ _container = new Container(this);
+ }
+ }
+ }
//--------------------------------------------------------------------------------------------
// key: key of the value to find. Cannot be null.
@@ -256,6 +284,148 @@ namespace System.Runtime.CompilerServices
public delegate TValue CreateValueCallback(TKey key);
+ //--------------------------------------------------------------------------------------------
+ // Gets an enumerator for the table. The returned enumerator will not extend the lifetime of
+ // any object pairs in the table, other than the one that's Current. It will not return entries
+ // that have already been collected, nor will it return entries added after the enumerator was
+ // retrieved. It may not return all entries that were present when the enumerat was retrieved,
+ // however, such as not returning entries that were collected or removed after the enumerator
+ // was retrieved but before they were enumerated.
+ //--------------------------------------------------------------------------------------------
+ IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
+ {
+ lock (_lock)
+ {
+ Container c = _container;
+ return c == null || c.FirstFreeEntry == 0 ?
+ ((IEnumerable<KeyValuePair<TKey, TValue>>)Array.Empty<KeyValuePair<TKey, TValue>>()).GetEnumerator() :
+ new Enumerator(this);
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<KeyValuePair<TKey, TValue>>)this).GetEnumerator();
+
+ /// <summary>Provides an enumerator for the table.</summary>
+ private sealed class Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>
+ {
+ // The enumerator would ideally hold a reference to the Container and the end index within that
+ // container. However, the safety of the CWT depends on the only reference to the Container being
+ // from the CWT itself; the Container then employs a two-phase finalization scheme, where the first
+ // phase nulls out that parent CWT's reference, guaranteeing that the second time it's finalized there
+ // can be no other existing references to it in use that would allow for concurrent usage of the
+ // native handles with finalization. We would break that if we allowed this Enumerator to hold a
+ // reference to the Container. Instead, the Enumerator holds a reference to the CWT rather than to
+ // the Container, and it maintains the CWT._activeEnumeratorRefCount field to track whether there
+ // are outstanding enumerators that have yet to be disposed/finalized. If there aren't any, the CWT
+ // behaves as it normally does. If there are, certain operations are affected, in particular resizes.
+ // Normally when the CWT is resized, it enumerates the contents of the table looking for indices that
+ // contain entries which have been collected or removed, and it frees those up, effectively moving
+ // down all subsequent entries in the container (not in the existing container, but in a replacement).
+ // This, however, would cause the enumerator's understanding of indices to break. So, as long as
+ // there is any outstanding enumerator, no compaction is performed.
+
+ private ConditionalWeakTable<TKey, TValue> _table; // parent table, set to null when disposed
+ private readonly int _maxIndexInclusive; // last index in the container that should be enumerated
+ private int _currentIndex = -1; // the current index into the container
+ private KeyValuePair<TKey, TValue> _current; // the current entry set by MoveNext and returned from Current
+
+ public Enumerator(ConditionalWeakTable<TKey, TValue> table)
+ {
+ Debug.Assert(table != null, "Must provide a valid table");
+ Debug.Assert(Monitor.IsEntered(table._lock), "Must hold the _lock lock to construct the enumerator");
+ Debug.Assert(table._container != null, "Should not be used on a finalized table");
+ Debug.Assert(table._container.FirstFreeEntry > 0, "Should have returned an empty enumerator instead");
+
+ // Store a reference to the parent table and increase its active enumerator count.
+ _table = table;
+ Debug.Assert(table._activeEnumeratorRefCount >= 0, "Should never have a negative ref count before incrementing");
+ table._activeEnumeratorRefCount++;
+
+ // Store the max index to be enumerated.
+ _maxIndexInclusive = table._container.FirstFreeEntry - 1;
+ _currentIndex = -1;
+ }
+
+ ~Enumerator() { Dispose(); }
+
+ public void Dispose()
+ {
+ // Use an interlocked operation to ensure that only one thread can get access to
+ // the _table for disposal and thus only decrement the ref count once.
+ ConditionalWeakTable<TKey, TValue> table = Interlocked.Exchange(ref _table, null);
+ if (table != null)
+ {
+ // Ensure we don't keep the last current alive unnecessarily
+ _current = default(KeyValuePair<TKey, TValue>);
+
+ // Decrement the ref count that was incremented when constructed
+ lock (table._lock)
+ {
+ table._activeEnumeratorRefCount--;
+ Debug.Assert(table._activeEnumeratorRefCount >= 0, "Should never have a negative ref count after decrementing");
+ }
+
+ // Finalization is purely to decrement the ref count. We can suppress it now.
+ GC.SuppressFinalize(this);
+ }
+ }
+
+ public bool MoveNext()
+ {
+ // Start by getting the current table. If it's already been disposed, it will be null.
+ ConditionalWeakTable<TKey, TValue> table = _table;
+ if (table != null)
+ {
+ // Once have the table, we need to lock to synchronize with other operations on
+ // the table, like adding.
+ lock (table._lock)
+ {
+ // From the table, we have to get the current container. This could have changed
+ // since we grabbed the enumerator, but the index-to-pair mapping should not have
+ // due to there being at least one active enumerator. If the table (or rather its
+ // container at the time) has already been finalized, this will be null.
+ Container c = table._container;
+ if (c != null)
+ {
+ // We have the container. Find the next entry to return, if there is one.
+ // We need to loop as we may try to get an entry that's already been removed
+ // or collected, in which case we try again.
+ while (_currentIndex < _maxIndexInclusive)
+ {
+ _currentIndex++;
+ TKey key;
+ TValue value;
+ if (c.TryGetEntry(_currentIndex, out key, out value))
+ {
+ _current = new KeyValuePair<TKey, TValue>(key, value);
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ // Nothing more to enumerate.
+ return false;
+ }
+
+ public KeyValuePair<TKey, TValue> Current
+ {
+ get
+ {
+ if (_currentIndex < 0)
+ {
+ ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen();
+ }
+ return _current;
+ }
+ }
+
+ object IEnumerator.Current => Current;
+
+ public void Reset() { }
+ }
+
#endregion
#region Internal members
@@ -305,17 +475,6 @@ namespace System.Runtime.CompilerServices
}
}
- //--------------------------------------------------------------------------------------------
- // Clear all the key/value pairs
- //--------------------------------------------------------------------------------------------
- internal void Clear()
- {
- lock (_lock)
- {
- _container = new Container(this);
- }
- }
-
#endregion
#region Private Members
@@ -435,6 +594,8 @@ namespace System.Runtime.CompilerServices
internal bool HasCapacity => _firstFreeEntry < _entries.Length;
+ internal int FirstFreeEntry => _firstFreeEntry;
+
//----------------------------------------------------------------------------------------
// Worker for adding a new key/value pair.
// Preconditions:
@@ -508,6 +669,44 @@ namespace System.Runtime.CompilerServices
return -1;
}
+ //----------------------------------------------------------------------------------------
+ // Gets the entry at the specified entry index.
+ //----------------------------------------------------------------------------------------
+ internal bool TryGetEntry(int index, out TKey key, out TValue value)
+ {
+ if (index < _entries.Length)
+ {
+ object oKey, oValue;
+ _entries[index].depHnd.GetPrimaryAndSecondary(out oKey, out oValue);
+ GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles.
+
+ if (oKey != null)
+ {
+ key = JitHelpers.UnsafeCast<TKey>(oKey);
+ value = JitHelpers.UnsafeCast<TValue>(oValue);
+ return true;
+ }
+ }
+
+ key = default(TKey);
+ value = default(TValue);
+ return false;
+ }
+
+ //----------------------------------------------------------------------------------------
+ // Removes all of the keys in the table.
+ //----------------------------------------------------------------------------------------
+ internal void RemoveAllKeys()
+ {
+ for (int i = 0; i < _firstFreeEntry; i++)
+ {
+ RemoveIndex(i);
+ }
+ }
+
+ //----------------------------------------------------------------------------------------
+ // Removes the specified key from the table, if it exists.
+ //----------------------------------------------------------------------------------------
internal bool Remove(TKey key)
{
VerifyIntegrity();
@@ -516,22 +715,27 @@ namespace System.Runtime.CompilerServices
int entryIndex = FindEntry(key, out value);
if (entryIndex != -1)
{
- ref Entry entry = ref _entries[entryIndex];
-
- // We do not free the handle here, as we may be racing with readers who already saw the hash code.
- // Instead, we simply overwrite the entry's hash code, so subsequent reads will ignore it.
- // The handle will be free'd in Container's finalizer, after the table is resized or discarded.
- Volatile.Write(ref entry.HashCode, -1);
-
- // Also, clear the key to allow GC to collect objects pointed to by the entry
- entry.depHnd.SetPrimary(null);
-
+ RemoveIndex(entryIndex);
return true;
}
return false;
}
+ private void RemoveIndex(int entryIndex)
+ {
+ Debug.Assert(entryIndex >= 0 && entryIndex < _firstFreeEntry);
+
+ ref Entry entry = ref _entries[entryIndex];
+
+ // We do not free the handle here, as we may be racing with readers who already saw the hash code.
+ // Instead, we simply overwrite the entry's hash code, so subsequent reads will ignore it.
+ // The handle will be free'd in Container's finalizer, after the table is resized or discarded.
+ Volatile.Write(ref entry.HashCode, -1);
+
+ // Also, clear the key to allow GC to collect objects pointed to by the entry
+ entry.depHnd.SetPrimary(null);
+ }
internal void UpdateValue(int entryIndex, TValue newValue)
{
@@ -556,25 +760,33 @@ namespace System.Runtime.CompilerServices
//----------------------------------------------------------------------------------------
internal Container Resize()
{
- // Start by assuming we won't resize.
- int newSize = _buckets.Length;
+ Debug.Assert(!HasCapacity);
- // If any expired or removed keys exist, we won't resize.
bool hasExpiredEntries = false;
- for (int entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++)
+ int newSize = _buckets.Length;
+
+ if (_parent == null || _parent._activeEnumeratorRefCount == 0)
{
- if (_entries[entriesIndex].HashCode == -1)
+ // If any expired or removed keys exist, we won't resize.
+ // If there any active enumerators, though, we don't want
+ // to compact and thus have no expired entries.
+ for (int entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++)
{
- // the entry was removed
- hasExpiredEntries = true;
- break;
- }
+ ref Entry entry = ref _entries[entriesIndex];
- if (_entries[entriesIndex].depHnd.IsAllocated && _entries[entriesIndex].depHnd.GetPrimary() == null)
- {
- // the entry has expired
- hasExpiredEntries = true;
- break;
+ if (entry.HashCode == -1)
+ {
+ // the entry was removed
+ hasExpiredEntries = true;
+ break;
+ }
+
+ if (entry.depHnd.IsAllocated && entry.depHnd.GetPrimary() == null)
+ {
+ // the entry has expired
+ hasExpiredEntries = true;
+ break;
+ }
}
}
@@ -585,44 +797,73 @@ namespace System.Runtime.CompilerServices
}
return Resize(newSize);
- }
+ }
internal Container Resize(int newSize)
{
+ Debug.Assert(newSize >= _buckets.Length);
Debug.Assert(IsPowerOfTwo(newSize));
// Reallocate both buckets and entries and rebuild the bucket and entries from scratch.
// This serves both to scrub entries with expired keys and to put the new entries in the proper bucket.
int[] newBuckets = new int[newSize];
- for (int bucketIndex = 0; bucketIndex < newSize; bucketIndex++)
+ for (int bucketIndex = 0; bucketIndex < newBuckets.Length; bucketIndex++)
{
newBuckets[bucketIndex] = -1;
}
Entry[] newEntries = new Entry[newSize];
int newEntriesIndex = 0;
+ bool activeEnumerators = _parent != null && _parent._activeEnumeratorRefCount > 0;
// Migrate existing entries to the new table.
- for (int entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++)
+ if (activeEnumerators)
{
- int hashCode = _entries[entriesIndex].HashCode;
- DependentHandle depHnd = _entries[entriesIndex].depHnd;
- if (hashCode != -1 && depHnd.IsAllocated)
+ // There's at least one active enumerator, which means we don't want to
+ // remove any expired/removed entries, in order to not affect existing
+ // entries indices. Copy over the entries while rebuilding the buckets list,
+ // as the buckets are dependent on the buckets list length, which is changing.
+ for (; newEntriesIndex < _entries.Length; newEntriesIndex++)
{
- if (depHnd.GetPrimary() != null)
- {
- // Entry is used and has not expired. Link it into the appropriate bucket list.
- newEntries[newEntriesIndex].HashCode = hashCode;
- newEntries[newEntriesIndex].depHnd = depHnd;
- int bucket = hashCode & (newBuckets.Length - 1);
- newEntries[newEntriesIndex].Next = newBuckets[bucket];
- newBuckets[bucket] = newEntriesIndex;
- newEntriesIndex++;
- }
- else
+ ref Entry oldEntry = ref _entries[newEntriesIndex];
+ ref Entry newEntry = ref newEntries[newEntriesIndex];
+ int hashCode = oldEntry.HashCode;
+
+ newEntry.HashCode = hashCode;
+ newEntry.depHnd = oldEntry.depHnd;
+ int bucket = hashCode & (newBuckets.Length - 1);
+ newEntry.Next = newBuckets[bucket];
+ newBuckets[bucket] = newEntriesIndex;
+ }
+ }
+ else
+ {
+ // There are no active enumerators, which means we want to compact by
+ // removing expired/removed entries.
+ for (int entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++)
+ {
+ ref Entry oldEntry = ref _entries[entriesIndex];
+ int hashCode = oldEntry.HashCode;
+ DependentHandle depHnd = oldEntry.depHnd;
+ if (hashCode != -1 && depHnd.IsAllocated)
{
- // Pretend the item was removed, so that this container's finalizer
- // will clean up this dependent handle.
- Volatile.Write(ref _entries[entriesIndex].HashCode, -1);
+ if (depHnd.GetPrimary() != null)
+ {
+ ref Entry newEntry = ref newEntries[newEntriesIndex];
+
+ // Entry is used and has not expired. Link it into the appropriate bucket list.
+ newEntry.HashCode = hashCode;
+ newEntry.depHnd = depHnd;
+ int bucket = hashCode & (newBuckets.Length - 1);
+ newEntry.Next = newBuckets[bucket];
+ newBuckets[bucket] = newEntriesIndex;
+ newEntriesIndex++;
+ }
+ else
+ {
+ // Pretend the item was removed, so that this container's finalizer
+ // will clean up this dependent handle.
+ Volatile.Write(ref oldEntry.HashCode, -1);
+ }
}
}
}
@@ -632,6 +873,14 @@ namespace System.Runtime.CompilerServices
// while the old container may still be in use. As such, we store a reference from the old container
// to the new one, which will keep the new container alive as long as the old one is.
var newContainer = new Container(_parent, newBuckets, newEntries, newEntriesIndex);
+ if (activeEnumerators)
+ {
+ // If there are active enumerators, both the old container and the new container may be storing
+ // the same entries with -1 hash codes, which the finalizer will clean up even if the container
+ // is not the active container for the table. To prevent that, we want to stop the old container
+ // from being finalized, as it no longer has any responsibility for any cleanup.
+ GC.SuppressFinalize(this);
+ }
_oldKeepAlive = newContainer; // once this is set, the old container's finalizer will not free transferred dependent handles
GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles.
@@ -815,7 +1064,6 @@ namespace System.Runtime.CompilerServices
// This struct intentionally does no self-synchronization. It's up to the caller to
// to use DependentHandles in a thread-safe way.
//=========================================================================================
- [ComVisible(false)]
internal struct DependentHandle
{
#region Constructors
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs
index c912095bda..1a5dcfdc11 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs
@@ -9,7 +9,6 @@ namespace System.Runtime.CompilerServices
{
[Serializable]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)]
- [System.Runtime.InteropServices.ComVisible(true)]
public abstract class CustomConstantAttribute : Attribute
{
public abstract Object Value { get; }
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
index 4362aa84a1..148d916be1 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
@@ -9,7 +9,6 @@ namespace System.Runtime.CompilerServices
{
[Serializable]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)]
- [System.Runtime.InteropServices.ComVisible(true)]
public sealed class DateTimeConstantAttribute : CustomConstantAttribute
{
public DateTimeConstantAttribute(long ticks)
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
index 7bfaa7aafd..f05191840d 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
@@ -14,7 +14,6 @@ namespace System.Runtime.CompilerServices
{
[Serializable]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)]
- [System.Runtime.InteropServices.ComVisible(true)]
public sealed class DecimalConstantAttribute : Attribute
{
[CLSCompliant(false)]
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs
deleted file mode 100644
index 75558d4e7e..0000000000
--- a/src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace System.Runtime.CompilerServices
-{
- [AttributeUsage(AttributeTargets.All),
- ComVisible(false)]
- internal sealed class DecoratedNameAttribute : Attribute
- {
- public DecoratedNameAttribute(string decoratedName)
- {}
- }
-}
-
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs
index 303151f576..3fda4624d4 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs
@@ -9,7 +9,6 @@ namespace System.Runtime.CompilerServices {
using System;
// Custom attribute to indicating a TypeDef is a discardable attribute
-[System.Runtime.InteropServices.ComVisible(true)]
public class DiscardableAttribute : Attribute
{
public DiscardableAttribute()
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ITuple.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ITuple.cs
new file mode 100644
index 0000000000..cafee11f8a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/ITuple.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// This interface is required for types that want to be indexed into by dynamic patterns.
+ /// </summary>
+ public interface ITuple
+ {
+ /// <summary>
+ /// The number of positions in this data structure.
+ /// </summary>
+ int Length { get; }
+
+ /// <summary>
+ /// Get the element at position <param name="index"/>.
+ /// </summary>
+ object this[int index] { get; }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs
index 0323fe0cf6..c32be6f3a2 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs
@@ -8,7 +8,6 @@ namespace System.Runtime.CompilerServices
[Serializable]
[AttributeUsage(AttributeTargets.Property, Inherited = true)]
-[System.Runtime.InteropServices.ComVisible(true)]
public sealed class IndexerNameAttribute: Attribute
{
public IndexerNameAttribute(String indexerName)
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs
index ea2fe032c6..5287e82b7b 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs
@@ -4,7 +4,6 @@
namespace System.Runtime.CompilerServices
{
-[System.Runtime.InteropServices.ComVisible(true)]
public static class IsVolatile
{
// no instantiation, please!
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs
index d081d70070..b4991110f8 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs
@@ -12,7 +12,6 @@ namespace System.Runtime.CompilerServices {
[Serializable]
[Flags]
-[System.Runtime.InteropServices.ComVisible(true)]
public enum MethodImplOptions
{
Unmanaged = System.Reflection.MethodImplAttributes.Unmanaged,
@@ -21,14 +20,12 @@ namespace System.Runtime.CompilerServices {
InternalCall = System.Reflection.MethodImplAttributes.InternalCall,
Synchronized = System.Reflection.MethodImplAttributes.Synchronized,
NoInlining = System.Reflection.MethodImplAttributes.NoInlining,
- [System.Runtime.InteropServices.ComVisible(false)]
AggressiveInlining = System.Reflection.MethodImplAttributes.AggressiveInlining,
NoOptimization = System.Reflection.MethodImplAttributes.NoOptimization,
// **** If you add something, update internal MethodImplAttribute(MethodImplAttributes methodImplAttributes)! ****
}
[Serializable]
-[System.Runtime.InteropServices.ComVisible(true)]
public enum MethodCodeType
{
IL = System.Reflection.MethodImplAttributes.IL,
@@ -41,7 +38,6 @@ namespace System.Runtime.CompilerServices {
// Custom attribute to specify additional method properties.
[Serializable]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)]
-[System.Runtime.InteropServices.ComVisible(true)]
sealed public class MethodImplAttribute : Attribute
{
internal MethodImplOptions _val;
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
index 926eb6c3cb..509e527ecb 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
@@ -18,7 +18,6 @@ namespace System.Runtime.CompilerServices {
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.Serialization;
- using System.Security.Permissions;
using System.Threading;
using System.Runtime.Versioning;
using System.Diagnostics.Contracts;
@@ -131,7 +130,6 @@ namespace System.Runtime.CompilerServices {
// Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack
// below.
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static extern void EnsureSufficientExecutionStack();
// This method ensures that there is sufficient stack to execute the average Framework function.
@@ -139,7 +137,6 @@ namespace System.Runtime.CompilerServices {
// Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack
// below.
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static extern bool TryEnsureSufficientExecutionStack();
public static void ProbeForSufficientStack()
@@ -148,7 +145,6 @@ namespace System.Runtime.CompilerServices {
// This method is a marker placed immediately before a try clause to mark the corresponding catch and finally blocks as
// constrained. There's no code here other than the probe because most of the work is done at JIT time when we spot a call to this routine.
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void PrepareConstrainedRegions()
{
ProbeForSufficientStack();
@@ -156,7 +152,6 @@ namespace System.Runtime.CompilerServices {
// When we detect a CER with no calls, we can point the JIT to this non-probing version instead
// as we don't need to probe.
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void PrepareConstrainedRegionsNoOP()
{
}
@@ -168,7 +163,6 @@ namespace System.Runtime.CompilerServices {
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData);
- [PrePrepareMethod]
internal static void ExecuteBackoutCodeHelper(Object backoutCode, Object userData, bool exceptionThrown)
{
((CleanupCode)backoutCode)(userData, exceptionThrown);
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs
index d2691df6b9..e3b2d2ce62 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs
@@ -15,7 +15,6 @@ namespace System.Runtime.CompilerServices {
using System;
using System.Runtime.Serialization;
using System.Runtime.Remoting;
- using System.Security.Permissions;
using System.Diagnostics.Contracts;
[Serializable]
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs
index 98a81ea470..f01900a5bf 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs
@@ -44,7 +44,6 @@ using System.Diagnostics.Contracts;
using System.Security;
using System.Threading;
using System.Threading.Tasks;
-using System.Security.Permissions;
using System.Diagnostics.Tracing;
// NOTE: For performance reasons, initialization is not verified. If a developer
@@ -198,21 +197,19 @@ namespace System.Runtime.CompilerServices
/// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
/// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
/// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
internal static void OnCompletedInternal(Task task, Action continuation, bool continueOnCapturedContext, bool flowExecutionContext)
{
if (continuation == null) throw new ArgumentNullException(nameof(continuation));
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
// If TaskWait* ETW events are enabled, trace a beginning event for this await
// and set up an ending event to be traced when the asynchronous await completes.
- if ( TplEtwProvider.Log.IsEnabled() || Task.s_asyncDebuggingEnabled)
+ if (TplEtwProvider.Log.IsEnabled() || Task.s_asyncDebuggingEnabled)
{
continuation = OutputWaitEtwEvents(task, continuation);
}
// Set the continuation onto the awaited task.
- task.SetContinuationForAwait(continuation, continueOnCapturedContext, flowExecutionContext, ref stackMark);
+ task.SetContinuationForAwait(continuation, continueOnCapturedContext, flowExecutionContext);
}
/// <summary>
@@ -244,7 +241,7 @@ namespace System.Runtime.CompilerServices
(currentTaskAtBegin != null ? currentTaskAtBegin.m_taskScheduler.Id : TaskScheduler.Default.Id),
(currentTaskAtBegin != null ? currentTaskAtBegin.Id : 0),
task.Id, TplEtwProvider.TaskWaitBehavior.Asynchronous,
- (continuationTask != null ? continuationTask.Id : 0), System.Threading.Thread.GetDomainID());
+ (continuationTask != null ? continuationTask.Id : 0));
}
// Create a continuation action that outputs the end event and then invokes the user
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs
new file mode 100644
index 0000000000..65b120e6b4
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// Indicates that the use of <see cref="System.ValueTuple"/> on a member is meant to be treated as a tuple with element names.
+ /// </summary>
+ [CLSCompliant(false)]
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Event)]
+ public sealed class TupleElementNamesAttribute : Attribute
+ {
+ private readonly string[] _transformNames;
+
+ /// <summary>
+ /// Initializes a new instance of the <see
+ /// cref="TupleElementNamesAttribute"/> class.
+ /// </summary>
+ /// <param name="transformNames">
+ /// Specifies, in a pre-order depth-first traversal of a type's
+ /// construction, which <see cref="System.ValueType"/> occurrences are
+ /// meant to carry element names.
+ /// </param>
+ /// <remarks>
+ /// This constructor is meant to be used on types that contain an
+ /// instantiation of <see cref="System.ValueType"/> that contains
+ /// element names. For instance, if <c>C</c> is a generic type with
+ /// two type parameters, then a use of the constructed type <c>C{<see
+ /// cref="System.ValueTuple{T1, T2}"/>, <see
+ /// cref="System.ValueTuple{T1, T2, T3}"/></c> might be intended to
+ /// treat the first type argument as a tuple with element names and the
+ /// second as a tuple without element names. In which case, the
+ /// appropriate attribute specification should use a
+ /// <c>transformNames</c> value of <c>{ "name1", "name2", null, null,
+ /// null }</c>.
+ /// </remarks>
+ public TupleElementNamesAttribute(string[] transformNames)
+ {
+ if (transformNames == null)
+ {
+ throw new ArgumentNullException(nameof(transformNames));
+ }
+
+ _transformNames = transformNames;
+ }
+
+ /// <summary>
+ /// Specifies, in a pre-order depth-first traversal of a type's
+ /// construction, which <see cref="System.ValueTuple"/> elements are
+ /// meant to carry element names.
+ /// </summary>
+ public IList<string> TransformNames => _transformNames;
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs
index d9e067bd4c..147c103047 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs
@@ -26,18 +26,6 @@ namespace System.Runtime.CompilerServices
}
}
- internal static TypeForwardedToAttribute[] GetCustomAttribute(RuntimeAssembly assembly)
- {
- Type[] types = null;
- RuntimeAssembly.GetForwardedTypes(assembly.GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref types));
-
- TypeForwardedToAttribute[] attributes = new TypeForwardedToAttribute[types.Length];
- for (int i = 0; i < types.Length; ++i)
- attributes[i] = new TypeForwardedToAttribute(types[i]);
-
- return attributes;
- }
-
}
}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs b/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs
index b212f4555b..adfa015161 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs
@@ -76,5 +76,18 @@ namespace System.Runtime.CompilerServices
// See getILIntrinsicImplementationForUnsafe for how this happens.
throw new InvalidOperationException();
}
+
+ /// <summary>
+ /// Initializes a block of memory at the given location with a given initial value
+ /// without assuming architecture dependent alignment of the address.
+ /// </summary>
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void InitBlockUnaligned(ref byte startAddress, byte value, uint byteCount)
+ {
+ // The body of this function will be replaced by the EE with unsafe code!!!
+ // See getILIntrinsicImplementationForUnsafe for how this happens.
+ throw new InvalidOperationException();
+ }
}
}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs b/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs
index 86789bf12d..92d1b4f95b 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs
@@ -28,7 +28,6 @@ using System.Diagnostics.Contracts;
using System.Diagnostics.Tracing;
using System.Threading;
using System.Threading.Tasks;
-using System.Security.Permissions;
namespace System.Runtime.CompilerServices
{
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs b/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs
index c1346f7527..080e42f46f 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs
@@ -216,7 +216,6 @@ namespace System.Runtime.CompilerServices {
extern static bool IsAddressInStack(IntPtr ptr);
#endif
-#if FEATURE_SPAN_OF_T
static internal bool ByRefLessThan<T>(ref T refA, ref T refB)
{
// The body of this function will be replaced by the EE with unsafe code!!!
@@ -239,6 +238,5 @@ namespace System.Runtime.CompilerServices {
typeof(ArrayPinningHelper).ToString(); // Type used by the actual method body
throw new InvalidOperationException();
}
-#endif // FEATURE_SPAN_OF_T
}
}