summaryrefslogtreecommitdiff
path: root/src/System.Private.CoreLib/src/System/RtType.cs
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2019-01-03 23:05:49 -1000
committerGitHub <noreply@github.com>2019-01-03 23:05:49 -1000
commita6269391cf04c656e9d472e1101e1ec670ecd605 (patch)
treed54e0b5a520b88413adb0d95f338ee4d42bc55a6 /src/System.Private.CoreLib/src/System/RtType.cs
parent7d67f73b7223620b709b2c7e33e0f6e3cef5a7e8 (diff)
downloadcoreclr-a6269391cf04c656e9d472e1101e1ec670ecd605.tar.gz
coreclr-a6269391cf04c656e9d472e1101e1ec670ecd605.tar.bz2
coreclr-a6269391cf04c656e9d472e1101e1ec670ecd605.zip
Reflection performance tweaks & cleanup (#21737)
- Delete internal "Unsafe" field getters/setters. They performance was very close (within 10%) of the regular getters/setters. - Made a few performance tweaks in reflection to make reflection faster overall. The regular field getters/setters are faster than what the unsafe ones used to be with this change.
Diffstat (limited to 'src/System.Private.CoreLib/src/System/RtType.cs')
-rw-r--r--src/System.Private.CoreLib/src/System/RtType.cs50
1 files changed, 33 insertions, 17 deletions
diff --git a/src/System.Private.CoreLib/src/System/RtType.cs b/src/System.Private.CoreLib/src/System/RtType.cs
index 0fcbd3b54c..dd30ea404c 100644
--- a/src/System.Private.CoreLib/src/System/RtType.cs
+++ b/src/System.Private.CoreLib/src/System/RtType.cs
@@ -14,6 +14,8 @@ using System.Threading;
using DebuggerStepThroughAttribute = System.Diagnostics.DebuggerStepThroughAttribute;
using MdToken = System.Reflection.MetadataToken;
+using Internal.Runtime.CompilerServices;
+
namespace System
{
// this is a work around to get the concept of a calli. It's not as fast but it would be interesting to
@@ -2379,30 +2381,44 @@ namespace System
private RuntimeTypeCache Cache
{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- if (m_cache == IntPtr.Zero)
+ if (m_cache != IntPtr.Zero)
{
- IntPtr newgcHandle = new RuntimeTypeHandle(this).GetGCHandle(GCHandleType.WeakTrackResurrection);
- IntPtr gcHandle = Interlocked.CompareExchange(ref m_cache, newgcHandle, IntPtr.Zero);
- // Leak the handle if the type is collectible. It will be reclaimed when
- // the type goes away.
- if (gcHandle != IntPtr.Zero && !IsCollectible)
- GCHandle.InternalFree(newgcHandle);
+ object cache = GCHandle.InternalGet(m_cache);
+ if (cache != null)
+ {
+ Debug.Assert(cache is RuntimeTypeCache);
+ return Unsafe.As<RuntimeTypeCache>(cache);
+ }
}
+ return InitializeCache();
+ }
+ }
- RuntimeTypeCache cache = GCHandle.InternalGet(m_cache) as RuntimeTypeCache;
- if (cache == null)
- {
- cache = new RuntimeTypeCache(this);
- RuntimeTypeCache existingCache = GCHandle.InternalCompareExchange(m_cache, cache, null, false) as RuntimeTypeCache;
- if (existingCache != null)
- cache = existingCache;
- }
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private RuntimeTypeCache InitializeCache()
+ {
+ if (m_cache == IntPtr.Zero)
+ {
+ IntPtr newgcHandle = new RuntimeTypeHandle(this).GetGCHandle(GCHandleType.WeakTrackResurrection);
+ IntPtr gcHandle = Interlocked.CompareExchange(ref m_cache, newgcHandle, IntPtr.Zero);
+ if (gcHandle != IntPtr.Zero)
+ GCHandle.InternalFree(newgcHandle);
+ }
- Debug.Assert(cache != null);
- return cache;
+ RuntimeTypeCache cache = (RuntimeTypeCache)GCHandle.InternalGet(m_cache);
+ if (cache == null)
+ {
+ cache = new RuntimeTypeCache(this);
+ RuntimeTypeCache existingCache = (RuntimeTypeCache)GCHandle.InternalCompareExchange(m_cache, cache, null, false);
+ if (existingCache != null)
+ cache = existingCache;
}
+
+ Debug.Assert(cache != null);
+ return cache;
}
private string GetDefaultMemberName()