Speed up `GVMLookupForSlot` (#85901)
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>
Mon, 8 May 2023 21:08:59 +0000 (06:08 +0900)
committerGitHub <noreply@github.com>
Mon, 8 May 2023 21:08:59 +0000 (06:08 +0900)
BasicMinimalApi spends about 1% of samples in this method.

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs

index 0c15531e2081e49f68888724db9d77e19bb34a56..431c83b42d03211eae67f4138a8bc9a22bfa25c6 100644 (file)
@@ -110,10 +110,19 @@ namespace System.Runtime
 
         public static unsafe IntPtr GVMLookupForSlot(object obj, RuntimeMethodHandle slot)
         {
-            Entry entry = LookupInCache(s_cache, (IntPtr)obj.GetMethodTable(), *(IntPtr*)&slot);
-            entry ??= CacheMiss((IntPtr)obj.GetMethodTable(), *(IntPtr*)&slot,
+            Entry entry = LookupInCache(s_cache, (IntPtr)obj.GetMethodTable(), RuntimeMethodHandle.ToIntPtr(slot));
+            if (entry != null)
+                return entry.Result;
+
+            return GVMLookupForSlotSlow(obj, slot);
+        }
+
+        private static unsafe IntPtr GVMLookupForSlotSlow(object obj, RuntimeMethodHandle slot)
+        {
+            Entry entry = CacheMiss((IntPtr)obj.GetMethodTable(), RuntimeMethodHandle.ToIntPtr(slot),
                     (IntPtr context, IntPtr signature, object contextObject, ref IntPtr auxResult)
                         => RuntimeAugments.TypeLoaderCallbacks.ResolveGenericVirtualMethodTarget(new RuntimeTypeHandle(new EETypePtr(context)), *(RuntimeMethodHandle*)&signature));
+
             return entry.Result;
         }
 
@@ -132,7 +141,11 @@ namespace System.Runtime
         private static Entry LookupInCache(Entry[] cache, IntPtr context, IntPtr signature)
         {
             int key = ((context.GetHashCode() >> 4) ^ signature.GetHashCode()) & (cache.Length - 1);
+#if DEBUG
             Entry entry = cache[key];
+#else
+            Entry entry = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(cache), key);
+#endif
             while (entry != null)
             {
                 if (entry.Context == context && entry.Signature == signature)