1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 /*============================================================
8 ** Header: Map used for interning of string literals.
10 ===========================================================*/
12 #ifndef _STRINGLITERALMAP_H
13 #define _STRINGLITERALMAP_H
16 #include "appdomain.hpp"
18 #include "eeconfig.h" // For OS pages size
19 #include "memorypool.h"
22 class StringLiteralEntry;
23 // Allocate 16 entries (approx size sizeof(StringLiteralEntry)*16)
24 #define MAX_ENTRIES_PER_CHUNK 16
26 STRINGREF AllocateStringObject(EEStringData *pStringData);
28 // Loader allocator specific string literal map.
29 class StringLiteralMap
32 // Constructor and destructor.
36 // Initialization method.
41 LIMITED_METHOD_CONTRACT;
42 return m_MemoryPool?m_MemoryPool->GetSize():0;
45 // Method to retrieve a string from the map.
46 STRINGREF *GetStringLiteral(EEStringData *pStringData, BOOL bAddIfNotFound, BOOL bAppDomainWontUnload);
48 // Method to explicitly intern a string object.
49 STRINGREF *GetInternedString(STRINGREF *pString, BOOL bAddIfNotFound, BOOL bAppDomainWontUnload);
52 // Hash tables that maps a Unicode string to a COM+ string handle.
53 EEUnicodeStringLiteralHashTable *m_StringToEntryHashTable;
55 // The memorypool for hash entries for this hash table.
56 MemoryPool *m_MemoryPool;
59 // Global string literal map.
60 class GlobalStringLiteralMap
62 // StringLiteralMap and StringLiteralEntry need to acquire the crst of the global string literal map.
63 friend class StringLiteralMap;
64 friend class StringLiteralEntry;
67 // Constructor and destructor.
68 GlobalStringLiteralMap();
69 ~GlobalStringLiteralMap();
71 // Initialization method.
74 // Method to retrieve a string from the map. Takes a precomputed hash (for perf).
75 StringLiteralEntry *GetStringLiteral(EEStringData *pStringData, DWORD dwHash, BOOL bAddIfNotFound);
77 // Method to explicitly intern a string object. Takes a precomputed hash (for perf).
78 StringLiteralEntry *GetInternedString(STRINGREF *pString, DWORD dwHash, BOOL bAddIfNotFound);
80 // Method to calculate the hash
81 DWORD GetHash(EEStringData* pData)
84 return m_StringToEntryHashTable->GetHash(pData);
87 // public method to retrieve m_HashTableCrstGlobal
88 Crst* GetHashTableCrstGlobal()
90 LIMITED_METHOD_CONTRACT;
91 return &m_HashTableCrstGlobal;
95 // Helper method to add a string to the global string literal map.
96 StringLiteralEntry *AddStringLiteral(EEStringData *pStringData);
98 // Helper method to add an interned string.
99 StringLiteralEntry *AddInternedString(STRINGREF *pString);
101 // Called by StringLiteralEntry when its RefCount falls to 0.
102 void RemoveStringLiteralEntry(StringLiteralEntry *pEntry);
104 // Hash tables that maps a Unicode string to a LiteralStringEntry.
105 EEUnicodeStringLiteralHashTable *m_StringToEntryHashTable;
107 // The memorypool for hash entries for this hash table.
108 MemoryPool *m_MemoryPool;
110 // The hash table table critical section.
111 // (the Global suffix is so that it is clear in context whether the global table is being locked
112 // or the per app domain table is being locked. Sometimes there was confusion in the code
113 // changing the name of the global one will avoid this problem and prevent copy/paste errors)
115 Crst m_HashTableCrstGlobal;
117 // The large heap handle table.
118 LargeHeapHandleTable m_LargeHeapHandleTable;
122 class StringLiteralEntryArray;
124 // Ref counted entry representing a string literal.
125 class StringLiteralEntry
128 StringLiteralEntry(EEStringData *pStringData, STRINGREF *pStringObj)
129 : m_pStringObj(pStringObj), m_dwRefCount(1)
134 LIMITED_METHOD_CONTRACT;
137 ~StringLiteralEntry()
143 PRECONDITION(CheckPointer<void>(this));
155 PRECONDITION(CheckPointer<void>(this));
156 PRECONDITION((LONG)VolatileLoad(&m_dwRefCount) > 0);
157 PRECONDITION(SystemDomain::GetGlobalStringLiteralMapNoCreate()->m_HashTableCrstGlobal.OwnedByCurrentThread());
161 _ASSERTE (!m_bDeleted);
163 // We will keep the item alive forever if the refcount overflowed
164 if ((LONG)VolatileLoad(&m_dwRefCount) < 0)
167 VolatileStore(&m_dwRefCount, VolatileLoad(&m_dwRefCount) + 1);
169 #ifndef DACCESS_COMPILE
170 FORCEINLINE static void StaticRelease(StringLiteralEntry* pEntry)
174 PRECONDITION(SystemDomain::GetGlobalStringLiteralMapNoCreate()->m_HashTableCrstGlobal.OwnedByCurrentThread());
181 FORCEINLINE static void StaticRelease(StringLiteralEntry* /* pEntry */)
186 #endif // DACCESS_COMPILE
188 #ifndef DACCESS_COMPILE
195 PRECONDITION(CheckPointer<void>(this));
196 PRECONDITION(VolatileLoad(&m_dwRefCount) > 0);
197 PRECONDITION(SystemDomain::GetGlobalStringLiteralMapNoCreate()->m_HashTableCrstGlobal.OwnedByCurrentThread());
201 // We will keep the item alive forever if the refcount overflowed
202 if ((LONG)VolatileLoad(&m_dwRefCount) < 0)
205 VolatileStore(&m_dwRefCount, VolatileLoad(&m_dwRefCount) - 1);
206 if (VolatileLoad(&m_dwRefCount) == 0)
208 _ASSERTE(SystemDomain::GetGlobalStringLiteralMapNoCreate());
209 SystemDomain::GetGlobalStringLiteralMapNoCreate()->RemoveStringLiteralEntry(this);
210 // Puts this entry in the free list
214 #endif // DACCESS_COMPILE
221 if(GetThread()){GC_NOTRIGGER;}else{DISABLED(GC_TRIGGERS);};
222 PRECONDITION(CheckPointer(this));
226 _ASSERTE (!m_bDeleted);
228 return (VolatileLoad(&m_dwRefCount));
231 STRINGREF* GetStringObject()
236 if(GetThread()){GC_NOTRIGGER;}else{DISABLED(GC_TRIGGERS);};
237 PRECONDITION(CheckPointer(this));
243 void GetStringData(EEStringData *pStringData)
248 if(GetThread()){GC_NOTRIGGER;}else{DISABLED(GC_TRIGGERS);};
250 PRECONDITION(CheckPointer(this));
251 PRECONDITION(CheckPointer(pStringData));
258 ObjectToSTRINGREF(*(StringObject**)m_pStringObj)->RefInterpretGetStringValuesDangerousForGC(&thisChars, &thisLength);
259 pStringData->SetCharCount (thisLength); // thisLength is in WCHARs and that's what EEStringData's char count wants
260 pStringData->SetStringBuffer (thisChars);
263 static StringLiteralEntry *AllocateEntry(EEStringData *pStringData, STRINGREF *pStringObj);
264 static void DeleteEntry (StringLiteralEntry *pEntry);
267 STRINGREF* m_pStringObj;
271 StringLiteralEntry *m_pNext;
278 // The static lists below are protected by GetGlobalStringLiteralMap()->m_HashTableCrstGlobal
279 static StringLiteralEntryArray *s_EntryList; // always the first entry array in the chain.
280 static DWORD s_UsedEntries; // number of entries used up in the first array
281 static StringLiteralEntry *s_FreeEntryList; // free list chained thru the arrays.
284 typedef Wrapper<StringLiteralEntry*,DoNothing,StringLiteralEntry::StaticRelease> StringLiteralEntryHolder;
286 class StringLiteralEntryArray
289 StringLiteralEntryArray *m_pNext;
290 BYTE m_Entries[MAX_ENTRIES_PER_CHUNK*sizeof(StringLiteralEntry)];
293 #endif // _STRINGLITERALMAP_H