From 15ba115e24955ee55c46392e848c1ffde1609ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Fri, 27 Oct 2023 12:38:23 +0200 Subject: [PATCH] Avoid handing out duplicate `CORINFO_MODULE_STRUCT_*` handles RyuJIT depends on never seeing two different `CORINFO_MODULE_STRUCT` for the same thing. Fixes #93843. --- .../tools/Common/JitInterface/CorInfoImpl.cs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 9d98650b91bbb..01d2d15fc2997 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -707,9 +707,15 @@ private void CompileMethodCleanup() _instantiationToJitVisibleInstantiation = null; _pgoResults.Clear(); + + // We need to clear out this cache because the next compilation could actually come up + // with a different MethodIL for the same MethodDesc. This happens when we need to replace + // a MethodIL with a throw helper. + _methodILScopeToHandle.Clear(); } private Dictionary _objectToHandle = new Dictionary(new JitObjectComparer()); + private Dictionary _methodILScopeToHandle = new Dictionary(new JitObjectComparer()); private List _handleToObject = new List(); private const int handleMultiplier = 8; @@ -720,6 +726,13 @@ private void CompileMethodCleanup() #endif private IntPtr ObjectToHandle(object obj) + { + // MethodILScopes need to go through ObjectToHandle(MethodILScope methodIL). + Debug.Assert(obj is not MethodILScope); + return ObjectToHandleUnchecked(obj); + } + + private IntPtr ObjectToHandleUnchecked(object obj) { // SuperPMI relies on the handle returned from this function being stable for the lifetime of the crossgen2 process // If handle deletion is implemented, please update SuperPMI @@ -752,10 +765,19 @@ private object HandleToObject(void* handle) private FieldDesc HandleToObject(CORINFO_FIELD_STRUCT_* field) => (FieldDesc)HandleToObject((void*)field); private CORINFO_FIELD_STRUCT_* ObjectToHandle(FieldDesc field) => (CORINFO_FIELD_STRUCT_*)ObjectToHandle((object)field); private MethodILScope HandleToObject(CORINFO_MODULE_STRUCT_* module) => (MethodIL)HandleToObject((void*)module); - private CORINFO_MODULE_STRUCT_* ObjectToHandle(MethodILScope methodIL) => (CORINFO_MODULE_STRUCT_*)ObjectToHandle((object)methodIL); private MethodSignature HandleToObject(MethodSignatureInfo* method) => (MethodSignature)HandleToObject((void*)method); private MethodSignatureInfo* ObjectToHandle(MethodSignature method) => (MethodSignatureInfo*)ObjectToHandle((object)method); + private CORINFO_MODULE_STRUCT_* ObjectToHandle(MethodILScope methodIL) + { + // RyuJIT requires CORINFO_MODULE_STRUCT to be unique. MethodILScope might not be unique + // due to ILProvider cache purging. See https://github.com/dotnet/runtime/issues/93843. + MethodDesc owningMethod = methodIL.OwningMethod; + if (!_methodILScopeToHandle.TryGetValue(owningMethod, out IntPtr handle)) + _methodILScopeToHandle[owningMethod] = handle = ObjectToHandleUnchecked((object)methodIL); + return (CORINFO_MODULE_STRUCT_*)handle; + } + private bool Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, CORINFO_METHOD_INFO* methodInfo) { if (methodIL == null)