Skip to content

Commit

Permalink
Avoid handing out duplicate CORINFO_MODULE_STRUCT_* handles (#95499)
Browse files Browse the repository at this point in the history
RyuJIT depends on never seeing two different `CORINFO_MODULE_STRUCT` for the same thing.

Fixes #93843.

Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
  • Loading branch information
github-actions[bot] and MichalStrehovsky committed Jan 2, 2024
1 parent a29f2fa commit 10bf9a0
Showing 1 changed file with 23 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<object, IntPtr> _objectToHandle = new Dictionary<object, IntPtr>(new JitObjectComparer());
private Dictionary<MethodDesc, IntPtr> _methodILScopeToHandle = new Dictionary<MethodDesc, IntPtr>(new JitObjectComparer());
private List<object> _handleToObject = new List<object>();

private const int handleMultiplier = 8;
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 10bf9a0

Please sign in to comment.