// 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.
//
// Hash table associated with each module that records for all types defined in that module the mapping
// between type name and token (or TypeHandle).
//
#ifndef __CLASS_HASH_INCLUDED
#define __CLASS_HASH_INCLUDED
#include "ngenhash.h"
// The type of each entry in the hash.
typedef DPTR(struct EEClassHashEntry) PTR_EEClassHashEntry;
class EEClassHashTable;
typedef struct EEClassHashEntry
{
friend class EEClassHashTable;
#ifdef DACCESS_COMPILE
friend class NativeImageDumper;
#endif
#ifdef _DEBUG
PTR_CUTF8 DebugKey[2]; // Name of the type
#endif // _DEBUG
// Accessors for encloser (pointer to hash entry of enclosing type when this entry describes a nested
// type). You need to use the accessors since the reference is not encoded as a simple pointer anymore.
PTR_EEClassHashEntry GetEncloser();
void SetEncloser(EEClassHashEntry *pEncloser) DAC_EMPTY();
// Bit masks for flags in the data field. Ideally we'd abstract this encoding but that's too much
// code churn right now.
#define EECLASSHASH_TYPEHANDLE_DISCR ((ULONG_PTR)(UINT)0x00000001)
#define EECLASSHASH_MDEXPORT_DISCR ((ULONG_PTR)(UINT)0x80000000)
#define EECLASSHASH_ALREADYSEEN ((ULONG_PTR)(UINT)0x40000000)
// Accessors for the data field (TypeHandle or a token with EECLASSHASH_TYPEHANDLE_DISCR set and possibly
// some of the other flag bits above). The type handle is also encoded as a non-regular pointer, so use
// this accessor.
PTR_VOID GetData();
void SetData(PTR_VOID data) DAC_EMPTY();
private:
PTR_VOID m_Data; // Either the token (if EECLASSHASH_TYPEHANDLE_DISCR), or the type handle encoded
// as a relative pointer
NgenHashEntryRef m_pEncloser; // If this entry is a for a nested
// class, this field stores a
// reference to the enclosing type
// (which must be in this same
// hash). The NgenHashEntryRef<>
// is required to abstract some
// complex logic required while
// ngen'ing such references.
} EEClassHashEntry_t;
// The hash type itself. All common logic is provided by the NgenHashTable templated base class. See
// NgenHash.h for details.
typedef DPTR(class EEClassHashTable) PTR_EEClassHashTable;
class EEClassHashTable : public NgenHashTable
{
#ifdef DACCESS_COMPILE
friend class NativeImageDumper;
#endif
public:
// The LookupContext type we export to track GetValue/FindNextNestedClass enumerations is simply a rename
// of the base classes' hash value enumerator.
typedef NgenHashTable::LookupContext LookupContext;
static EEClassHashTable *Create(Module *pModule, DWORD dwNumBuckets, BOOL bCaseInsensitive, AllocMemTracker *pamTracker);
//NOTICE: look at InsertValue() in ClassLoader, that may be the function you want to use. Use this only
// when you are sure you want to insert the value in 'this' table. This function does not deal
// with case (as often the class loader has to)
EEClassHashEntry_t *InsertValue(LPCUTF8 pszNamespace, LPCUTF8 pszClassName, PTR_VOID Data, EEClassHashEntry_t *pEncloser, AllocMemTracker *pamTracker);
EEClassHashEntry_t *InsertValueIfNotFound(LPCUTF8 pszNamespace, LPCUTF8 pszClassName, PTR_VOID *pData, EEClassHashEntry_t *pEncloser, BOOL IsNested, BOOL *pbFound, AllocMemTracker *pamTracker);
EEClassHashEntry_t *InsertValueUsingPreallocatedEntry(EEClassHashEntry_t *pStorageForNewEntry, LPCUTF8 pszNamespace, LPCUTF8 pszClassName, PTR_VOID Data, EEClassHashEntry_t *pEncloser);
EEClassHashEntry_t *GetValue(LPCUTF8 pszNamespace, LPCUTF8 pszClassName, PTR_VOID *pData, BOOL IsNested, LookupContext *pContext);
EEClassHashEntry_t *GetValue(LPCUTF8 pszFullyQualifiedName, PTR_VOID *pData, BOOL IsNested, LookupContext *pContext);
EEClassHashEntry_t *GetValue(NameHandle* pName, PTR_VOID *pData, BOOL IsNested, LookupContext *pContext);
EEClassHashEntry_t *AllocNewEntry(AllocMemTracker *pamTracker);
EEClassHashTable *MakeCaseInsensitiveTable(Module *pModule, AllocMemTracker *pamTracker);
EEClassHashEntry_t *FindItem(LPCUTF8 pszNamespace, LPCUTF8 pszClassName, BOOL IsNested, LookupContext *pContext);
EEClassHashEntry_t *FindNextNestedClass(NameHandle* pName, PTR_VOID *pData, LookupContext *pContext);
EEClassHashEntry_t *FindNextNestedClass(LPCUTF8 pszNamespace, LPCUTF8 pszClassName, PTR_VOID *pData, LookupContext *pContext);
EEClassHashEntry_t *FindNextNestedClass(LPCUTF8 pszFullyQualifiedName, PTR_VOID *pData, LookupContext *pContext);
BOOL CompareKeys(PTR_EEClassHashEntry pEntry, LPCUTF8 * pKey2);
static DWORD Hash(LPCUTF8 pszNamespace, LPCUTF8 pszClassName);
class ConstructKeyCallback
{
public:
virtual void UseKeys(__in_ecount(2) LPUTF8 *Key) = 0;
};
static PTR_VOID CompressClassDef(mdToken cl /* either a TypeDef or ExportedType*/);
bool UncompressModuleAndClassDef(PTR_VOID Data, Loader::LoadFlag loadFlag,
Module **ppModule, mdTypeDef *pCL,
mdExportedType *pmdFoundExportedType);
VOID UncompressModuleAndNonExportClassDef(PTR_VOID Data, Module **ppModule,
mdTypeDef *pCL);
static mdToken UncompressModuleAndClassDef(PTR_VOID Data);
#ifdef DACCESS_COMPILE
void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
void EnumMemoryRegionsForEntry(EEClassHashEntry_t *pEntry, CLRDataEnumMemoryFlags flags);
#endif
#if defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE)
void Save(DataImage *pImage, CorProfileData *pProfileData);
void Fixup(DataImage *pImage);
private:
friend class NgenHashTable;
void PrepareExportedTypesForSaving(DataImage *image);
bool ShouldSave(DataImage *pImage, EEClassHashEntry_t *pEntry);
bool IsHotEntry(EEClassHashEntry_t *pEntry, CorProfileData *pProfileData);
bool SaveEntry(DataImage *pImage, CorProfileData *pProfileData, EEClassHashEntry_t *pOldEntry, EEClassHashEntry_t *pNewEntry, EntryMappingTable *pMap);
void FixupEntry(DataImage *pImage, EEClassHashEntry_t *pEntry, void *pFixupBase, DWORD cbFixupOffset);
#endif // FEATURE_PREJIT && !DACCESS_COMPILE
private:
#ifndef DACCESS_COMPILE
EEClassHashTable(Module *pModule, LoaderHeap *pHeap, DWORD cInitialBuckets) :
NgenHashTable(pModule, pHeap, cInitialBuckets) {}
#endif
VOID ConstructKeyFromData(PTR_EEClassHashEntry pEntry, ConstructKeyCallback * pCallback);
BOOL m_bCaseInsensitive; // Default is true FALSE unless we call MakeCaseInsensitiveTable
};
#endif // !__CLASS_HASH_INCLUDED