diff options
author | David Wrighton <davidwr@microsoft.com> | 2017-07-03 20:15:05 +0300 |
---|---|---|
committer | David Wrighton <davidwr@microsoft.com> | 2017-07-03 20:15:05 +0300 |
commit | 6ed0b6c9feb5dc6c2b3819abde41b3946b5efa1f (patch) | |
tree | b58e13f79cde49594604048d0e195565e77a50ec /src/Runtime.Base | |
parent | 090d7b4424fd66fa17d4c4e50214b9b8e6f898ae (diff) |
Improve performance of interface casting
- Primary improvement is to the performance of failed interface casting (the is case where null is returned).
- Change checking ICastable flag from needing access to the RareFlags to being examinable directly from EEType
- Remove unused existing RuntimeAllocated flag and move ICastable flag to be directly on EEType
- Secondary improvement
- Micro-optimize use of assignability cache by removing an if statement from the assignability cache lookup function and force inline it into its caller. Removal of the extra function prolog/epilog/removal of the if statement is worth about 300ms.
- This will improve performance of all interface cast checks by a small but measurable amount.
[tfs-changeset: 1664305]
Diffstat (limited to 'src/Runtime.Base')
-rw-r--r-- | src/Runtime.Base/src/System/Runtime/EEType.Runtime.cs | 2 | ||||
-rw-r--r-- | src/Runtime.Base/src/System/Runtime/TypeCast.cs | 22 |
2 files changed, 21 insertions, 3 deletions
diff --git a/src/Runtime.Base/src/System/Runtime/EEType.Runtime.cs b/src/Runtime.Base/src/System/Runtime/EEType.Runtime.cs index 475b77568..09a6c8bef 100644 --- a/src/Runtime.Base/src/System/Runtime/EEType.Runtime.cs +++ b/src/Runtime.Base/src/System/Runtime/EEType.Runtime.cs @@ -77,7 +77,7 @@ namespace Internal.Runtime { fixed (EEType* pThis = &this) { - if (!IsRuntimeAllocated && !IsDynamicType) + if (!IsDynamicType) return (IntPtr)pThis; // There are currently four types of runtime allocated EETypes, arrays, pointers, byrefs, and generic types. diff --git a/src/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/Runtime.Base/src/System/Runtime/TypeCast.cs index 62dea8448..db68ac4a4 100644 --- a/src/Runtime.Base/src/System/Runtime/TypeCast.cs +++ b/src/Runtime.Base/src/System/Runtime/TypeCast.cs @@ -268,7 +268,7 @@ namespace System.Runtime EEType* pTargetType = (EEType*)pvTargetType; EEType* pObjType = obj.EEType; - if (CastCache.AreTypesAssignableInternal(pObjType, pTargetType, AssignmentVariation.BoxedSource)) + if (CastCache.AreTypesAssignableInternal_SourceNotTarget_BoxedSource(pObjType, pTargetType)) return obj; // If object type implements ICastable then there's one more way to check whether it implements @@ -744,7 +744,7 @@ namespace System.Runtime EEType* pTargetType = (EEType*)pvTargetEEType; EEType* pObjType = obj.EEType; - if (CastCache.AreTypesAssignableInternal(pObjType, pTargetType, AssignmentVariation.BoxedSource)) + if (CastCache.AreTypesAssignableInternal_SourceNotTarget_BoxedSource(pObjType, pTargetType)) return obj; Exception castError = null; @@ -1116,6 +1116,24 @@ namespace System.Runtime return entry.Result; } + // This method is an optimized and customized version of AreTypesAssignable that achieves better performance + // than AreTypesAssignableInternal through 2 significant changes + // 1. Removal of sourceType to targetType check (This propery must be known before calling this function. At time + // of writing, this is true as its is only used if sourceType is from an object, and targetType is an interface.) + // 2. Force inlining (This particular variant is only used in a small number of dispatch scenarios that are particularly + // high in performance impact.) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe bool AreTypesAssignableInternal_SourceNotTarget_BoxedSource(EEType* pSourceType, EEType* pTargetType) + { + Debug.Assert(pSourceType != pTargetType, "target is source"); + Key key = new Key(pSourceType, pTargetType, AssignmentVariation.BoxedSource); + Entry entry = LookupInCache(s_cache, ref key); + if (entry == null) + return CacheMiss(ref key); + + return entry.Result; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Entry LookupInCache(Entry[] cache, ref Key key) { |