summaryrefslogtreecommitdiff
path: root/src/vm/classhash.h
blob: 4b796c70c1553b7caf9b937702555355de7753e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// 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. <NICE>Ideally we'd abstract this encoding but that's too much
    // code churn right now.</NICE>
    #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<EEClassHashTable, EEClassHashEntry, 4> 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<EEClassHashTable, EEClassHashEntry, 4>
{
#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<EEClassHashTable, EEClassHashEntry, 4>::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<EEClassHashTable, EEClassHashEntry, 4>;

    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<EEClassHashTable, EEClassHashEntry, 4>(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