@@ -800,7 +800,7 @@ DWORD Dictionary::GetDictionarySlotsSizeForMethod(MethodDesc* pMD)
800800 return *(DWORD*)pSizeSlot;
801801}
802802
803- Dictionary* Dictionary::GetMethodDictionaryWithSizeCheck (MethodDesc* pMD)
803+ Dictionary* Dictionary::GetMethodDictionaryWithSizeCheck (MethodDesc* pMD, ULONG slotIndex )
804804{
805805 CONTRACT (Dictionary*)
806806 {
@@ -814,27 +814,26 @@ Dictionary* Dictionary::GetMethodDictionaryWithSizeCheck(MethodDesc* pMD)
814814 Dictionary* pDictionary = pMD->GetMethodDictionary ();
815815
816816#if !defined(CROSSGEN_COMPILE)
817- DictionaryLayout* pDictLayout = pMD->GetDictionaryLayout ();
818- InstantiatedMethodDesc* pIMD = pMD->AsInstantiatedMethodDesc ();
819- _ASSERTE (pDictLayout != NULL && pDictLayout->GetMaxSlots () > 0 );
817+ DWORD currentDictionarySize = GetDictionarySlotsSizeForMethod (pMD);
820818
821- DWORD currentDictLayoutSize = GetDictionarySlotsSizeForMethod (pMD);
822- DWORD expectedDictLayoutSize = DictionaryLayout::GetDictionarySizeFromLayout (pMD->GetNumGenericMethodArgs (), pDictLayout);
823- if (currentDictLayoutSize != expectedDictLayoutSize)
819+ if (currentDictionarySize <= (slotIndex * sizeof (DictionaryEntry)))
824820 {
825- _ASSERT (currentDictLayoutSize < expectedDictLayoutSize);
821+ // Only expand the dictionary if the current slot we're trying to use is beyond the size of the dictionary
822+
823+ DictionaryLayout* pDictLayout = pMD->GetDictionaryLayout ();
824+ InstantiatedMethodDesc* pIMD = pMD->AsInstantiatedMethodDesc ();
825+ _ASSERTE (pDictLayout != NULL && pDictLayout->GetMaxSlots () > 0 );
826826
827- pDictionary = (Dictionary*)(void *)pIMD->GetLoaderAllocator ()->GetHighFrequencyHeap ()->AllocMem (S_SIZE_T (expectedDictLayoutSize));
828- ZeroMemory (pDictionary, expectedDictLayoutSize);
827+ DWORD expectedDictionarySize = DictionaryLayout::GetDictionarySizeFromLayout (pMD->GetNumGenericMethodArgs (), pDictLayout);
828+ _ASSERT (currentDictionarySize < expectedDictionarySize);
829+
830+ pDictionary = (Dictionary*)(void *)pIMD->GetLoaderAllocator ()->GetHighFrequencyHeap ()->AllocMem (S_SIZE_T (expectedDictionarySize));
829831
830832 // Copy old dictionary entry contents
831- memcpy (pDictionary, (const void *)pIMD->m_pPerInstInfo .GetValue (), currentDictLayoutSize );
833+ memcpy (pDictionary, (const void *)pIMD->m_pPerInstInfo .GetValue (), currentDictionarySize );
832834
833835 DWORD* pSizeSlot = (DWORD*)(pDictionary + pIMD->GetNumGenericMethodArgs ());
834- *pSizeSlot = expectedDictLayoutSize;
835-
836- // Flush any write buffers before publishing the new dictionary contents
837- FlushProcessWriteBuffers ();
836+ *pSizeSlot = expectedDictionarySize;
838837
839838 // Publish the new dictionary slots to the type.
840839 FastInterlockExchangePointer ((TypeHandle**)pIMD->m_pPerInstInfo .GetValuePtr (), (TypeHandle*)pDictionary);
@@ -844,7 +843,7 @@ Dictionary* Dictionary::GetMethodDictionaryWithSizeCheck(MethodDesc* pMD)
844843 RETURN pDictionary;
845844}
846845
847- Dictionary* Dictionary::GetTypeDictionaryWithSizeCheck (MethodTable* pMT)
846+ Dictionary* Dictionary::GetTypeDictionaryWithSizeCheck (MethodTable* pMT, ULONG slotIndex )
848847{
849848 CONTRACT (Dictionary*)
850849 {
@@ -858,27 +857,26 @@ Dictionary* Dictionary::GetTypeDictionaryWithSizeCheck(MethodTable* pMT)
858857 Dictionary* pDictionary = pMT->GetDictionary ();
859858
860859#if !defined(CROSSGEN_COMPILE)
861- DictionaryLayout* pDictLayout = pMT->GetClass ()->GetDictionaryLayout ();
862- _ASSERTE (pDictLayout != NULL && pDictLayout->GetMaxSlots () > 0 );
860+ DWORD currentDictionarySize = GetDictionarySlotsSizeForType (pMT);
863861
864- DWORD currentDictLayoutSize = GetDictionarySlotsSizeForType (pMT);
865- DWORD expectedDictLayoutSize = DictionaryLayout::GetDictionarySizeFromLayout (pMT->GetNumGenericArgs (), pDictLayout);
866- if (currentDictLayoutSize != expectedDictLayoutSize)
862+ if (currentDictionarySize <= (slotIndex * sizeof (DictionaryEntry)))
867863 {
868- _ASSERT (currentDictLayoutSize < expectedDictLayoutSize);
864+ // Only expand the dictionary if the current slot we're trying to use is beyond the size of the dictionary
865+
866+ DictionaryLayout* pDictLayout = pMT->GetClass ()->GetDictionaryLayout ();
867+ _ASSERTE (pDictLayout != NULL && pDictLayout->GetMaxSlots () > 0 );
868+
869+ DWORD expectedDictionarySize = DictionaryLayout::GetDictionarySizeFromLayout (pMT->GetNumGenericArgs (), pDictLayout);
870+ _ASSERT (currentDictionarySize < expectedDictionarySize);
869871
870872 // Expand type dictionary
871- pDictionary = (Dictionary*)(void *)pMT->GetLoaderAllocator ()->GetHighFrequencyHeap ()->AllocMem (S_SIZE_T (expectedDictLayoutSize));
872- ZeroMemory (pDictionary, expectedDictLayoutSize);
873+ pDictionary = (Dictionary*)(void *)pMT->GetLoaderAllocator ()->GetHighFrequencyHeap ()->AllocMem (S_SIZE_T (expectedDictionarySize));
873874
874875 // Copy old dictionary entry contents
875- memcpy (pDictionary, (const void *)pMT->GetPerInstInfo ()[pMT->GetNumDicts () - 1 ].GetValue (), currentDictLayoutSize );
876+ memcpy (pDictionary, (const void *)pMT->GetPerInstInfo ()[pMT->GetNumDicts () - 1 ].GetValue (), currentDictionarySize );
876877
877878 DWORD* pSizeSlot = (DWORD*)(pDictionary + pMT->GetNumGenericArgs ());
878- *pSizeSlot = expectedDictLayoutSize;
879-
880- // Flush any write buffers before publishing the new dictionary contents
881- FlushProcessWriteBuffers ();
879+ *pSizeSlot = expectedDictionarySize;
882880
883881 // Publish the new dictionary slots to the type.
884882 ULONG dictionaryIndex = pMT->GetNumDicts () - 1 ;
@@ -1499,8 +1497,8 @@ Dictionary::PopulateEntry(
14991497 CrstHolder ch (&SystemDomain::SystemModule ()->m_DictionaryCrst );
15001498
15011499 Dictionary* pDictionary = (pMT != NULL ) ?
1502- GetTypeDictionaryWithSizeCheck (pMT) :
1503- GetMethodDictionaryWithSizeCheck (pMD);
1500+ GetTypeDictionaryWithSizeCheck (pMT, slotIndex ) :
1501+ GetMethodDictionaryWithSizeCheck (pMD, slotIndex );
15041502
15051503 *(pDictionary->GetSlotAddr (0 , slotIndex)) = result;
15061504 *ppSlot = pDictionary->GetSlotAddr (0 , slotIndex);
0 commit comments