Repository: dotnet/runtime
File: src/coreclr/vm/method.hpp (C++)

Code before:

    union
    {
        PTR_CUTF8   m_pszLibName;
        DWORD       m_dwECallID;    // ECallID for QCalls
    };

    // The JIT generates an indirect call through this location in some cases.
    // Initialized to PInvokeImportThunkGlue. Patched to the true target or
    // host interceptor stub or alignment thunk after linking.
    LPVOID      m_pPInvokeTarget;

#ifdef HAS_PINVOKE_IMPORT_PRECODE
    PTR_PInvokeImportThunkGlue  m_pImportThunkGlue;
#else // HAS_PINVOKE_IMPORT_PRECODE
    PInvokeImportThunkGlue      m_ImportThunkGlue;
#endif // HAS_PINVOKE_IMPORT_PRECODE

    ULONG       m_DefaultDllImportSearchPathsAttributeValue; // DefaultDllImportSearchPathsAttribute is saved.

    // Various attributes needed at runtime.
    WORD        m_wPInvokeFlags;

    // Points to the PInvoke ILStub DynamicMethodDesc if one has been created.
    // This mapping is needed for debugging to recognize the ILStub code.
    PTR_DynamicMethodDesc m_pILStub;

#if defined(TARGET_X86)
    // Size of outgoing arguments (on stack). Note that in order to get the @n stdcall name decoration,
    WORD        m_cbStackArgumentSize;
#endif // defined(TARGET_X86)

    enum Flags
    {
        // There are two groups of flag bits here each which gets initialized
        // at different times.

        //
        // Group 1: The init group.
        //
        //   This group is set during MethodDesc construction. No race issues
        //   here since they are initialized before the MD is ever published
        //   and never change after that.

        kEarlyBound                     = 0x0001,   // IJW managed->unmanaged thunk. Standard [sysimport] stuff otherwise.

        // unused                       = 0x0002,

        kDefaultDllImportSearchPathsIsCached = 0x0004, // set if we cache attribute value.

        // kUnusedMask                  = 0x0008

Review comment (suggestion):
For R2R compiled PInvoke stubs, we do not have the DynamicMethodDesc at all. So this fix won't fix the problem for R2R code.

I do not think it is the right fix to store and retrieve DynamicMethodDesc. Instead, we should handle the PInvoke MethodDesc directly.

Code after:

typedef DPTR(PInvokeImportThunkGlue)      PTR_PInvokeImportThunkGlue;


//-----------------------------------------------------------------------
// Operations specific to PInvoke methods. We use a derived class to get
// the compiler involved in enforcing proper method type usage.
// DO NOT ADD FIELDS TO THIS CLASS.
//-----------------------------------------------------------------------
class PInvokeMethodDesc : public MethodDesc
{
public:
    // Information about the entrypoint
    PTR_CUTF8   m_pszEntrypointName;

    union
    {
        PTR_CUTF8   m_pszLibName;
        DWORD       m_dwECallID;    // ECallID for QCalls
    };

    // The JIT generates an indirect call through this location in some cases.
    // Initialized to PInvokeImportThunkGlue. Patched to the true target or
    // host interceptor stub or alignment thunk after linking.
    LPVOID      m_pPInvokeTarget;

#ifdef HAS_PINVOKE_IMPORT_PRECODE
    PTR_PInvokeImportThunkGlue  m_pImportThunkGlue;
#else // HAS_PINVOKE_IMPORT_PRECODE
    PInvokeImportThunkGlue      m_ImportThunkGlue;
#endif // HAS_PINVOKE_IMPORT_PRECODE

    ULONG       m_DefaultDllImportSearchPathsAttributeValue; // DefaultDllImportSearchPathsAttribute is saved.

    // Various attributes needed at runtime.
    WORD        m_wPInvokeFlags;

#if defined(TARGET_X86)
    // Size of outgoing arguments (on stack). Note that in order to get the @n stdcall name decoration,
    WORD        m_cbStackArgumentSize;
#endif // defined(TARGET_X86)

    enum Flags
    {
        // There are two groups of flag bits here each which gets initialized
        // at different times.

        //
        // Group 1: The init group.
        //
        //   This group is set during MethodDesc construction. No race issues