@@ -4300,29 +4300,43 @@ namespace
43004300 {
43014301 STANDARD_VM_CONTRACT;
43024302
4303- // The hash blob for a forward P/Invoke stub is just the target MethodDesc pointer.
4304- // In order to help avoid collisions, ensure various blob sizes are different.
4305- // See asserts below.
4306- constexpr size_t forwardPInvokeHashBlobSize = sizeof (ILStubHashBlobBase) + sizeof (MethodDesc*);
4303+ // Some stubs (forward P/Invoke non-varags, late bound COM) each target a specific method.
4304+ // The hash blob for an unshared stub is just the target MethodDesc pointer and the stub flags.
4305+ constexpr size_t unsharedStubHashBlobSize = sizeof (ILStubHashBlobBase) + sizeof (DWORD) + sizeof (MethodDesc*);
43074306
43084307 DWORD dwStubFlags = pParams->m_dwStubFlags ;
43094308
4309+ bool isNonSharedStub = false ;
4310+
43104311 // The target MethodDesc may be NULL for field marshalling.
43114312 // Forward P/Invoke stubs (non-CALLI, non-vararg) each target a specific method,
43124313 // so the hash blob is just the target MethodDesc pointer. This ensures racing
43134314 // threads for the same P/Invoke converge on the same DynamicMethodDesc in the
43144315 // ILStubCache, while different P/Invoke methods get distinct cache entries.
4315- if (pTargetMD != NULL
4316- && SF_IsForwardPInvokeStub (dwStubFlags)
4316+ if (SF_IsForwardPInvokeStub (dwStubFlags)
43174317 && !SF_IsCALLIStub (dwStubFlags)
43184318 && !SF_IsVarArgStub (dwStubFlags))
43194319 {
4320- const size_t blobSize = forwardPInvokeHashBlobSize;
4320+ isNonSharedStub = true ;
4321+ }
4322+
4323+ // Late-bound COM stubs depend on metadata on the target MethodDesc (DispIdAttribute, associated properties) in addition to just the signature.
4324+ // Cache based on the target MethodDesc and stub flags instead of the signature to avoid false sharing.
4325+ if (SF_IsCOMLateBoundStub (dwStubFlags))
4326+ {
4327+ isNonSharedStub = true ;
4328+ }
4329+
4330+ if (isNonSharedStub)
4331+ {
4332+ _ASSERTE (pTargetMD != NULL );
4333+ const size_t blobSize = unsharedStubHashBlobSize;
43214334 NewArrayHolder<BYTE> pBytes = new BYTE[blobSize];
43224335 ZeroMemory (pBytes, blobSize);
43234336 ILStubHashBlob* pBlob = (ILStubHashBlob*)(BYTE*)pBytes;
43244337 pBlob->m_cbSizeOfBlob = blobSize;
4325- memcpy (pBlob->m_rgbBlobData , &pTargetMD, sizeof (pTargetMD));
4338+ memcpy (pBlob->m_rgbBlobData , &dwStubFlags, sizeof (dwStubFlags));
4339+ memcpy (pBlob->m_rgbBlobData + sizeof (dwStubFlags), &pTargetMD, sizeof (pTargetMD));
43264340 pBytes.SuppressRelease ();
43274341 return pBlob;
43284342 }
@@ -4381,7 +4395,7 @@ namespace
43814395 if (cbSizeOfBlob.IsOverflow ())
43824396 COMPlusThrowHR (COR_E_OVERFLOW);
43834397
4384- _ASSERTE (cbSizeOfBlob.Value () != forwardPInvokeHashBlobSize );
4398+ _ASSERTE (cbSizeOfBlob.Value () != unsharedStubHashBlobSize );
43854399
43864400 static_assert (nltMaxValue <= 0xFF );
43874401 static_assert (nlfMaxValue <= 0xFF );
0 commit comments