diff options
Diffstat (limited to 'src/vm/eehash.cpp')
-rw-r--r-- | src/vm/eehash.cpp | 536 |
1 files changed, 536 insertions, 0 deletions
diff --git a/src/vm/eehash.cpp b/src/vm/eehash.cpp new file mode 100644 index 0000000000..e5d3c0bdeb --- /dev/null +++ b/src/vm/eehash.cpp @@ -0,0 +1,536 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// File: eehash.cpp +// + +// + + +#include "common.h" +#include "excep.h" +#include "eehash.h" +#include "securityattributes.h" +#include "securitydeclarativecache.h" +#include "stringliteralmap.h" +#include "clsload.hpp" +#include "typectxt.h" +#include "genericdict.h" + +// ============================================================================ +// UTF8 string hash table helper. +// ============================================================================ +EEHashEntry_t * EEUtf8HashTableHelper::AllocateEntry(LPCUTF8 pKey, BOOL bDeepCopy, void *pHeap) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + INJECT_FAULT(return NULL;); + } + CONTRACTL_END + + EEHashEntry_t *pEntry; + + if (bDeepCopy) + { + DWORD StringLen = (DWORD)strlen(pKey); + DWORD BufLen = 0; +// Review conversion of size_t to DWORD. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4267) +#endif + if (!ClrSafeInt<DWORD>::addition(StringLen, SIZEOF_EEHASH_ENTRY + sizeof(LPUTF8) + 1, BufLen)) +#ifdef _MSC_VER +#pragma warning(pop) +#endif + return NULL; + pEntry = (EEHashEntry_t *) new (nothrow) BYTE[BufLen]; + if (!pEntry) + return NULL; + + memcpy(pEntry->Key + sizeof(LPUTF8), pKey, StringLen + 1); + *((LPUTF8*)pEntry->Key) = (LPUTF8)(pEntry->Key + sizeof(LPUTF8)); + } + else + { + pEntry = (EEHashEntry_t *) new (nothrow)BYTE[SIZEOF_EEHASH_ENTRY + sizeof(LPUTF8)]; + if (pEntry) + *((LPCUTF8*)pEntry->Key) = pKey; + } + + return pEntry; +} + + +void EEUtf8HashTableHelper::DeleteEntry(EEHashEntry_t *pEntry, void *pHeap) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + FORBID_FAULT; + } + CONTRACTL_END + + delete [] (BYTE*)pEntry; +} + + +BOOL EEUtf8HashTableHelper::CompareKeys(EEHashEntry_t *pEntry, LPCUTF8 pKey) +{ + LIMITED_METHOD_DAC_CONTRACT; + + LPCUTF8 pEntryKey = *((LPCUTF8*)pEntry->Key); + return (strcmp(pEntryKey, pKey) == 0) ? TRUE : FALSE; +} + + +DWORD EEUtf8HashTableHelper::Hash(LPCUTF8 pKey) +{ + LIMITED_METHOD_DAC_CONTRACT; + + DWORD dwHash = 0; + + while (*pKey != 0) + { + dwHash = (dwHash << 5) + (dwHash >> 5) + (*pKey); + pKey++; + } + + return dwHash; +} + + +LPCUTF8 EEUtf8HashTableHelper::GetKey(EEHashEntry_t *pEntry) +{ + LIMITED_METHOD_CONTRACT; + + return *((LPCUTF8*)pEntry->Key); +} + +#ifndef DACCESS_COMPILE + +// ============================================================================ +// Unicode string hash table helper. +// ============================================================================ +EEHashEntry_t * EEUnicodeHashTableHelper::AllocateEntry(EEStringData *pKey, BOOL bDeepCopy, void *pHeap) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + INJECT_FAULT(return NULL;); + } + CONTRACTL_END + + EEHashEntry_t *pEntry; + + if (bDeepCopy) + { + pEntry = (EEHashEntry_t *) new (nothrow) BYTE[SIZEOF_EEHASH_ENTRY + sizeof(EEStringData) + ((pKey->GetCharCount() + 1) * sizeof(WCHAR))]; + if (pEntry) { + EEStringData *pEntryKey = (EEStringData *)(&pEntry->Key); + pEntryKey->SetIsOnlyLowChars (pKey->GetIsOnlyLowChars()); + pEntryKey->SetCharCount (pKey->GetCharCount()); + pEntryKey->SetStringBuffer ((LPWSTR) ((LPBYTE)pEntry->Key + sizeof(EEStringData))); + memcpy((LPWSTR)pEntryKey->GetStringBuffer(), pKey->GetStringBuffer(), pKey->GetCharCount() * sizeof(WCHAR)); + } + } + else + { + pEntry = (EEHashEntry_t *) new (nothrow) BYTE[SIZEOF_EEHASH_ENTRY + sizeof(EEStringData)]; + if (pEntry) { + EEStringData *pEntryKey = (EEStringData *) pEntry->Key; + pEntryKey->SetIsOnlyLowChars (pKey->GetIsOnlyLowChars()); + pEntryKey->SetCharCount (pKey->GetCharCount()); + pEntryKey->SetStringBuffer (pKey->GetStringBuffer()); + } + } + + return pEntry; +} + + +void EEUnicodeHashTableHelper::DeleteEntry(EEHashEntry_t *pEntry, void *pHeap) +{ + LIMITED_METHOD_CONTRACT; + + delete [] (BYTE*)pEntry; +} + + +BOOL EEUnicodeHashTableHelper::CompareKeys(EEHashEntry_t *pEntry, EEStringData *pKey) +{ + LIMITED_METHOD_CONTRACT; + + EEStringData *pEntryKey = (EEStringData*) pEntry->Key; + + // Same buffer, same string. + if (pEntryKey->GetStringBuffer() == pKey->GetStringBuffer()) + return TRUE; + + // Length not the same, never a match. + if (pEntryKey->GetCharCount() != pKey->GetCharCount()) + return FALSE; + + // Compare the entire thing. + // We'll deliberately ignore the bOnlyLowChars field since this derived from the characters + return !memcmp(pEntryKey->GetStringBuffer(), pKey->GetStringBuffer(), pEntryKey->GetCharCount() * sizeof(WCHAR)); +} + + +DWORD EEUnicodeHashTableHelper::Hash(EEStringData *pKey) +{ + LIMITED_METHOD_CONTRACT; + + return (HashBytes((const BYTE *) pKey->GetStringBuffer(), pKey->GetCharCount()*sizeof(WCHAR))); +} + + +EEStringData *EEUnicodeHashTableHelper::GetKey(EEHashEntry_t *pEntry) +{ + LIMITED_METHOD_CONTRACT; + + return (EEStringData*)pEntry->Key; +} + +void EEUnicodeHashTableHelper::ReplaceKey(EEHashEntry_t *pEntry, EEStringData *pNewKey) +{ + LIMITED_METHOD_CONTRACT; + + ((EEStringData*)pEntry->Key)->SetStringBuffer (pNewKey->GetStringBuffer()); + ((EEStringData*)pEntry->Key)->SetCharCount (pNewKey->GetCharCount()); + ((EEStringData*)pEntry->Key)->SetIsOnlyLowChars (pNewKey->GetIsOnlyLowChars()); +} + +// ============================================================================ +// Unicode stringliteral hash table helper. +// ============================================================================ +EEHashEntry_t * EEUnicodeStringLiteralHashTableHelper::AllocateEntry(EEStringData *pKey, BOOL bDeepCopy, void *pHeap) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + INJECT_FAULT(return NULL;); + } + CONTRACTL_END + + // We assert here because we expect that the heap is not null for EEUnicodeStringLiteralHash table. + // If someone finds more uses of this kind of hashtable then remove this asserte. + // Also note that in case of heap being null we go ahead and use new /delete which is EXPENSIVE + // But for production code this might be ok if the memory is fragmented then thers a better chance + // of getting smaller allocations than full pages. + _ASSERTE (pHeap); + + if (pHeap) + return (EEHashEntry_t *) ((MemoryPool*)pHeap)->AllocateElementNoThrow (); + else + return (EEHashEntry_t *) new (nothrow) BYTE[SIZEOF_EEHASH_ENTRY]; +} + + +void EEUnicodeStringLiteralHashTableHelper::DeleteEntry(EEHashEntry_t *pEntry, void *pHeap) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + FORBID_FAULT; + } + CONTRACTL_END + + // We assert here because we expect that the heap is not null for EEUnicodeStringLiteralHash table. + // If someone finds more uses of this kind of hashtable then remove this asserte. + // Also note that in case of heap being null we go ahead and use new /delete which is EXPENSIVE + // But for production code this might be ok if the memory is fragmented then thers a better chance + // of getting smaller allocations than full pages. + _ASSERTE (pHeap); + + if (pHeap) + ((MemoryPool*)pHeap)->FreeElement(pEntry); + else + delete [] (BYTE*)pEntry; +} + + +BOOL EEUnicodeStringLiteralHashTableHelper::CompareKeys(EEHashEntry_t *pEntry, EEStringData *pKey) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + FORBID_FAULT; + } + CONTRACTL_END + + GCX_COOP(); + + StringLiteralEntry *pHashData = (StringLiteralEntry *)pEntry->Data; + + EEStringData pEntryKey; + pHashData->GetStringData(&pEntryKey); + + // Length not the same, never a match. + if (pEntryKey.GetCharCount() != pKey->GetCharCount()) + return FALSE; + + // Compare the entire thing. + // We'll deliberately ignore the bOnlyLowChars field since this derived from the characters + return (!memcmp(pEntryKey.GetStringBuffer(), pKey->GetStringBuffer(), pEntryKey.GetCharCount() * sizeof(WCHAR))); +} + + +DWORD EEUnicodeStringLiteralHashTableHelper::Hash(EEStringData *pKey) +{ + LIMITED_METHOD_CONTRACT; + + return (HashBytes((const BYTE *) pKey->GetStringBuffer(), pKey->GetCharCount() * sizeof(WCHAR))); +} + +// ============================================================================ +// Permission set hash table helper. +// ============================================================================ + +EEHashEntry_t * EEPsetHashTableHelper::AllocateEntry(PsetCacheKey *pKey, BOOL bDeepCopy, void *pHeap) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + INJECT_FAULT(return NULL;); + } + CONTRACTL_END + + _ASSERTE(!bDeepCopy); + + EEHashEntry_t *pEntry; + + if (pHeap) { + + S_SIZE_T sizeEntry; + LoaderHeap *pLHeap; + + sizeEntry = S_SIZE_T(sizeof (BYTE)) * (S_SIZE_T)SIZEOF_EEHASH_ENTRY + + (S_SIZE_T)sizeof (PPsetCacheKey); + + pLHeap = (LoaderHeap*) pHeap; + + pEntry = (EEHashEntry_t *) + ((void*) pLHeap->AllocMem_NoThrow (sizeEntry)); + + } else { + pEntry = (EEHashEntry_t *) new (nothrow) + BYTE [SIZEOF_EEHASH_ENTRY + sizeof(PPsetCacheKey)]; + } + + if (pEntry) { + *((PPsetCacheKey*)pEntry->Key) = pKey; + } + + return pEntry; +} + +void EEPsetHashTableHelper::DeleteEntry(EEHashEntry_t *pEntry, void *pHeap) +{ + LIMITED_METHOD_CONTRACT; + + // + // If a heap is present, memory will be reclaimed as part of appdomain + // unload. + // + + if (pHeap == NULL) { + delete [] (BYTE*)pEntry; + } + +} + +BOOL EEPsetHashTableHelper::CompareKeys(EEHashEntry_t *pEntry, PsetCacheKey *pKey) +{ + LIMITED_METHOD_CONTRACT; + + PsetCacheKey *pThis = *((PPsetCacheKey*)pEntry->Key); + return pKey->IsEquiv(pThis); +} + +DWORD EEPsetHashTableHelper::Hash(PsetCacheKey *pKey) +{ + LIMITED_METHOD_CONTRACT; + + return pKey->Hash(); +} + +PsetCacheKey * EEPsetHashTableHelper::GetKey(EEHashEntry_t *pEntry) +{ + LIMITED_METHOD_CONTRACT; + + PsetCacheKey *pThis = *((PPsetCacheKey*)pEntry->Key); + return pThis; +} + + +// ============================================================================ +// Instantiation hash table helper. +// ============================================================================ + +EEHashEntry_t *EEInstantiationHashTableHelper::AllocateEntry(const SigTypeContext *pKey, BOOL bDeepCopy, AllocationHeap pHeap) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END + + EEHashEntry_t *pEntry = (EEHashEntry_t *) new (nothrow) BYTE[SIZEOF_EEHASH_ENTRY + sizeof(SigTypeContext)]; + if (!pEntry) + return NULL; + *((SigTypeContext*)pEntry->Key) = *pKey; + + return pEntry; +} + +void EEInstantiationHashTableHelper::DeleteEntry(EEHashEntry_t *pEntry, AllocationHeap pHeap) +{ + LIMITED_METHOD_CONTRACT; + + delete [] (BYTE*)pEntry; +} + +BOOL EEInstantiationHashTableHelper::CompareKeys(EEHashEntry_t *pEntry, const SigTypeContext *pKey) +{ + LIMITED_METHOD_CONTRACT; + + SigTypeContext *pThis = (SigTypeContext*)&pEntry->Key; + return SigTypeContext::Equal(pThis, pKey); +} + +DWORD EEInstantiationHashTableHelper::Hash(const SigTypeContext *pKey) +{ + LIMITED_METHOD_CONTRACT; + + DWORD dwHash = 5381; + DWORD i; + + for (i = 0; i < pKey->m_classInst.GetNumArgs(); i++) + dwHash = ((dwHash << 5) + dwHash) ^ (unsigned int)(SIZE_T)pKey->m_classInst[i].AsPtr(); + + for (i = 0; i < pKey->m_methodInst.GetNumArgs(); i++) + dwHash = ((dwHash << 5) + dwHash) ^ (unsigned int)(SIZE_T)pKey->m_methodInst[i].AsPtr(); + + return dwHash; +} + +const SigTypeContext *EEInstantiationHashTableHelper::GetKey(EEHashEntry_t *pEntry) +{ + LIMITED_METHOD_CONTRACT; + + return (const SigTypeContext*)&pEntry->Key; +} + + + +// ============================================================================ +// ComComponentInfo hash table helper. +// ============================================================================ + +EEHashEntry_t *EEClassFactoryInfoHashTableHelper::AllocateEntry(ClassFactoryInfo *pKey, BOOL bDeepCopy, void *pHeap) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + INJECT_FAULT(return NULL;); + } + CONTRACTL_END + + EEHashEntry_t *pEntry; + S_SIZE_T cbStringLen = S_SIZE_T(0); + + _ASSERTE(bDeepCopy && "Non deep copy is not supported by the EEComCompInfoHashTableHelper"); + + if (pKey->m_strServerName) + cbStringLen = (S_SIZE_T(wcslen(pKey->m_strServerName)) + S_SIZE_T(1)) * S_SIZE_T(sizeof(WCHAR)); + + S_SIZE_T cbEntry = S_SIZE_T(SIZEOF_EEHASH_ENTRY + sizeof(ClassFactoryInfo)) + cbStringLen; + + if (cbEntry.IsOverflow()) + return NULL; + + _ASSERTE(!cbStringLen.IsOverflow()); + + pEntry = (EEHashEntry_t *) new (nothrow) BYTE[cbEntry.Value()]; + if (pEntry) { + memcpy(pEntry->Key + sizeof(ClassFactoryInfo), pKey->m_strServerName, cbStringLen.Value()); + ((ClassFactoryInfo*)pEntry->Key)->m_strServerName = pKey->m_strServerName ? (WCHAR*)(pEntry->Key + sizeof(ClassFactoryInfo)) : NULL; + ((ClassFactoryInfo*)pEntry->Key)->m_clsid = pKey->m_clsid; + } + + return pEntry; +} + +void EEClassFactoryInfoHashTableHelper::DeleteEntry(EEHashEntry_t *pEntry, void *pHeap) +{ + LIMITED_METHOD_CONTRACT; + + delete [] (BYTE*) pEntry; +} + +BOOL EEClassFactoryInfoHashTableHelper::CompareKeys(EEHashEntry_t *pEntry, ClassFactoryInfo *pKey) +{ + LIMITED_METHOD_CONTRACT; + + // First check the GUIDs. + if (((ClassFactoryInfo*)pEntry->Key)->m_clsid != pKey->m_clsid) + return FALSE; + + // Next do a trivial comparition on the server name pointer values. + if (((ClassFactoryInfo*)pEntry->Key)->m_strServerName == pKey->m_strServerName) + return TRUE; + + // If the pointers are not equal then if one is NULL then the server names are different. + if (!((ClassFactoryInfo*)pEntry->Key)->m_strServerName || !pKey->m_strServerName) + return FALSE; + + // Finally do a string comparition of the server names. + return wcscmp(((ClassFactoryInfo*)pEntry->Key)->m_strServerName, pKey->m_strServerName) == 0; +} + +DWORD EEClassFactoryInfoHashTableHelper::Hash(ClassFactoryInfo *pKey) +{ + LIMITED_METHOD_CONTRACT; + + DWORD dwHash = 0; + BYTE *pGuidData = (BYTE*)&pKey->m_clsid; + + for (unsigned int i = 0; i < sizeof(GUID); i++) + { + dwHash = (dwHash << 5) + (dwHash >> 5) + (*pGuidData); + pGuidData++; + } + + if (pKey->m_strServerName) + { + WCHAR *pSrvNameData = pKey->m_strServerName; + + while (*pSrvNameData != 0) + { + dwHash = (dwHash << 5) + (dwHash >> 5) + (*pSrvNameData); + pSrvNameData++; + } + } + + return dwHash; +} + +ClassFactoryInfo *EEClassFactoryInfoHashTableHelper::GetKey(EEHashEntry_t *pEntry) +{ + LIMITED_METHOD_CONTRACT; + + return (ClassFactoryInfo*)pEntry->Key; +} +#endif // !DACCESS_COMPILE |