forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove JitGenericHandleCache (dotnet#106843)
- It was only used for overflow scenarios from the generic dictionary (which don't happen), virtual resolution scenarios for creating delegates, and a few other rare R2R scenarios - Replace the virtual resolution scenarios with a cache of the affected data in managed code, and move the helpers to managed - Use the GenericCache type which was previously only used on NativeAOT for Generic Virtual method resolution paths. - Just remove the pointless checks from within the various normal generic lookup paths, and since they no longer do anything interesting in their hot paths except erect a helper method frame and call a worker routine, move those jit helpers to managed as well.
- Loading branch information
1 parent
8d2b266
commit 128fdfd
Showing
29 changed files
with
582 additions
and
502 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/GenericsHelpers.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// 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; | ||
|
||
namespace System.Runtime.CompilerServices; | ||
|
||
[StackTraceHidden] | ||
[DebuggerStepThrough] | ||
internal static unsafe partial class GenericsHelpers | ||
{ | ||
[LibraryImport(RuntimeHelpers.QCall)] | ||
private static partial IntPtr GenericHandleWorker(IntPtr pMD, IntPtr pMT, IntPtr signature, uint dictionaryIndexAndSlot, IntPtr pModule); | ||
|
||
public struct GenericHandleArgs | ||
{ | ||
public IntPtr signature; | ||
public IntPtr module; | ||
public uint dictionaryIndexAndSlot; | ||
}; | ||
|
||
[DebuggerHidden] | ||
public static IntPtr Method(IntPtr methodHnd, IntPtr signature) | ||
{ | ||
return GenericHandleWorker(methodHnd, IntPtr.Zero, signature, 0xFFFFFFFF, IntPtr.Zero); | ||
} | ||
|
||
[DebuggerHidden] | ||
public static unsafe IntPtr MethodWithSlotAndModule(IntPtr methodHnd, GenericHandleArgs * pArgs) | ||
{ | ||
return GenericHandleWorker(methodHnd, IntPtr.Zero, pArgs->signature, pArgs->dictionaryIndexAndSlot, pArgs->module); | ||
} | ||
|
||
[DebuggerHidden] | ||
public static IntPtr Class(IntPtr classHnd, IntPtr signature) | ||
{ | ||
return GenericHandleWorker(IntPtr.Zero, classHnd, signature, 0xFFFFFFFF, IntPtr.Zero); | ||
} | ||
|
||
[DebuggerHidden] | ||
public static unsafe IntPtr ClassWithSlotAndModule(IntPtr classHnd, GenericHandleArgs * pArgs) | ||
{ | ||
return GenericHandleWorker(IntPtr.Zero, classHnd, pArgs->signature, pArgs->dictionaryIndexAndSlot, pArgs->module); | ||
} | ||
} |
96 changes: 96 additions & 0 deletions
96
...eclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/VirtualDispatchHelpers.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// 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.Diagnostics; | ||
using System.Numerics; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace System.Runtime.CompilerServices; | ||
|
||
[StackTraceHidden] | ||
[DebuggerStepThrough] | ||
internal static unsafe partial class VirtualDispatchHelpers | ||
{ | ||
private struct VirtualResolutionData : IEquatable<VirtualResolutionData> | ||
{ | ||
public int _hashCode; | ||
public MethodTable* _objectMethodTable; | ||
public IntPtr _classHandle; | ||
public IntPtr _methodHandle; | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public VirtualResolutionData(MethodTable* objectMethodTable, IntPtr classHandle, IntPtr methodHandle) | ||
{ | ||
_hashCode = (int) ((uint)objectMethodTable + (BitOperations.RotateLeft((uint)classHandle, 5)) + (BitOperations.RotateRight((uint)methodHandle, 5))); | ||
_objectMethodTable = objectMethodTable; | ||
_classHandle = classHandle; | ||
_methodHandle = methodHandle; | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public bool Equals(VirtualResolutionData other) => | ||
_hashCode == other._hashCode && | ||
(((nint)_objectMethodTable - (nint)other._objectMethodTable) | | ||
(_classHandle - other._classHandle) | | ||
(_methodHandle - other._methodHandle)) == 0; | ||
|
||
public override bool Equals(object? obj) => obj is VirtualResolutionData other && Equals(other); | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public override int GetHashCode() => _hashCode; | ||
} | ||
|
||
private struct VirtualFunctionPointerArgs | ||
{ | ||
public IntPtr classHnd; | ||
public IntPtr methodHnd; | ||
}; | ||
|
||
#if DEBUG | ||
// use smaller numbers to hit resizing/preempting logic in debug | ||
private const int InitialCacheSize = 8; // MUST BE A POWER OF TWO | ||
private const int MaximumCacheSize = 512; | ||
#else | ||
private const int InitialCacheSize = 128; // MUST BE A POWER OF TWO | ||
private const int MaximumCacheSize = 8 * 1024; | ||
#endif // DEBUG | ||
|
||
private static GenericCache<VirtualResolutionData, IntPtr> s_virtualFunctionPointerCache = new GenericCache<VirtualResolutionData, IntPtr>(InitialCacheSize, MaximumCacheSize); | ||
|
||
[LibraryImport(RuntimeHelpers.QCall)] | ||
private static unsafe partial IntPtr ResolveVirtualFunctionPointer(ObjectHandleOnStack obj, IntPtr classHandle, IntPtr methodHandle); | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
[DebuggerHidden] | ||
private static unsafe IntPtr VirtualFunctionPointerSlow(object obj, IntPtr classHandle, IntPtr methodHandle) | ||
{ | ||
IntPtr result = ResolveVirtualFunctionPointer(ObjectHandleOnStack.Create(ref obj), classHandle, methodHandle); | ||
s_virtualFunctionPointerCache.TrySet(new VirtualResolutionData(RuntimeHelpers.GetMethodTable(obj), classHandle, methodHandle), result); | ||
GC.KeepAlive(obj); | ||
return result; | ||
} | ||
|
||
[DebuggerHidden] | ||
private static unsafe IntPtr VirtualFunctionPointer(object obj, IntPtr classHandle, IntPtr methodHandle) | ||
{ | ||
if (s_virtualFunctionPointerCache.TryGet(new VirtualResolutionData(RuntimeHelpers.GetMethodTable(obj), classHandle, methodHandle), out IntPtr result)) | ||
{ | ||
return result; | ||
} | ||
return VirtualFunctionPointerSlow(obj, classHandle, methodHandle); | ||
} | ||
|
||
[DebuggerHidden] | ||
private static unsafe IntPtr VirtualFunctionPointer_Dynamic(object obj, ref VirtualFunctionPointerArgs virtualFunctionPointerArgs) | ||
{ | ||
IntPtr classHandle = virtualFunctionPointerArgs.classHnd; | ||
IntPtr methodHandle = virtualFunctionPointerArgs.methodHnd; | ||
|
||
if (s_virtualFunctionPointerCache.TryGet(new VirtualResolutionData(RuntimeHelpers.GetMethodTable(obj), classHandle, methodHandle), out IntPtr result)) | ||
{ | ||
return result; | ||
} | ||
return VirtualFunctionPointerSlow(obj, classHandle, methodHandle); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
/*============================================================ | ||
** | ||
** Header: JitQCallHelpers.h | ||
** | ||
** | ||
===========================================================*/ | ||
|
||
#ifndef _JITQCALLHELPERS_H | ||
#define _JITQCALLHELPERS_H | ||
|
||
#include "qcall.h" | ||
#include "corinfo.h" | ||
|
||
class Module; | ||
class MethodTable; | ||
class MethodDesc; | ||
|
||
extern "C" void * QCALLTYPE ResolveVirtualFunctionPointer(QCall::ObjectHandleOnStack obj, CORINFO_CLASS_HANDLE classHnd, CORINFO_METHOD_HANDLE methodHnd); | ||
extern "C" CORINFO_GENERIC_HANDLE QCALLTYPE GenericHandleWorker(MethodDesc * pMD, MethodTable * pMT, LPVOID signature, DWORD dictionaryIndexAndSlot, Module* pModule); | ||
|
||
#endif //_JITQCALLHELPERS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.