Skip to content

Commit 51966dd

Browse files
author
Fadi Hanna
committed
Expand dictionary only when slot needed is beyond dictionary size
1 parent 7ad02f8 commit 51966dd

File tree

2 files changed

+31
-33
lines changed

2 files changed

+31
-33
lines changed

src/coreclr/src/vm/genericdict.cpp

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

src/coreclr/src/vm/genericdict.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,8 @@ class Dictionary
318318
static DWORD GetDictionarySlotsSizeForType(MethodTable* pMT);
319319
static DWORD GetDictionarySlotsSizeForMethod(MethodDesc* pMD);
320320

321-
static Dictionary* GetTypeDictionaryWithSizeCheck(MethodTable* pMT);
322-
static Dictionary* GetMethodDictionaryWithSizeCheck(MethodDesc* pMD);
321+
static Dictionary* GetTypeDictionaryWithSizeCheck(MethodTable* pMT, ULONG slotIndex);
322+
static Dictionary* GetMethodDictionaryWithSizeCheck(MethodDesc* pMD, ULONG slotIndex);
323323

324324
#endif // #ifndef DACCESS_COMPILE
325325

0 commit comments

Comments
 (0)