summaryrefslogtreecommitdiff
path: root/src/vm/eehash.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/eehash.cpp')
-rw-r--r--src/vm/eehash.cpp536
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