diff options
author | Jiyoung Yun <jy910.yun@samsung.com> | 2016-11-23 19:09:09 +0900 |
---|---|---|
committer | Jiyoung Yun <jy910.yun@samsung.com> | 2016-11-23 19:09:09 +0900 |
commit | 4b4aad7217d3292650e77eec2cf4c198ea9c3b4b (patch) | |
tree | 98110734c91668dfdbb126fcc0e15ddbd93738ca /src/vm/stringliteralmap.h | |
parent | fa45f57ed55137c75ac870356a1b8f76c84b229c (diff) | |
download | coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.gz coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.bz2 coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.zip |
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'src/vm/stringliteralmap.h')
-rw-r--r-- | src/vm/stringliteralmap.h | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/src/vm/stringliteralmap.h b/src/vm/stringliteralmap.h new file mode 100644 index 0000000000..6f84889e07 --- /dev/null +++ b/src/vm/stringliteralmap.h @@ -0,0 +1,294 @@ +// 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. + + +/*============================================================ +** +** Header: Map used for interning of string literals. +** +===========================================================*/ + +#ifndef _STRINGLITERALMAP_H +#define _STRINGLITERALMAP_H + +#include "vars.hpp" +#include "appdomain.hpp" +#include "eehash.h" +#include "eeconfig.h" // For OS pages size +#include "memorypool.h" + + +class StringLiteralEntry; +// Allocate 16 entries (approx size sizeof(StringLiteralEntry)*16) +#define MAX_ENTRIES_PER_CHUNK 16 + +STRINGREF AllocateStringObject(EEStringData *pStringData); + +// Loader allocator specific string literal map. +class StringLiteralMap +{ +public: + // Constructor and destructor. + StringLiteralMap(); + ~StringLiteralMap(); + + // Initialization method. + void Init(); + + size_t GetSize() + { + LIMITED_METHOD_CONTRACT; + return m_MemoryPool?m_MemoryPool->GetSize():0; + } + + // Method to retrieve a string from the map. + STRINGREF *GetStringLiteral(EEStringData *pStringData, BOOL bAddIfNotFound, BOOL bAppDomainWontUnload); + + // Method to explicitly intern a string object. + STRINGREF *GetInternedString(STRINGREF *pString, BOOL bAddIfNotFound, BOOL bAppDomainWontUnload); + +private: + // Hash tables that maps a Unicode string to a COM+ string handle. + EEUnicodeStringLiteralHashTable *m_StringToEntryHashTable; + + // The memorypool for hash entries for this hash table. + MemoryPool *m_MemoryPool; +}; + +// Global string literal map. +class GlobalStringLiteralMap +{ + // StringLiteralMap and StringLiteralEntry need to acquire the crst of the global string literal map. + friend class StringLiteralMap; + friend class StringLiteralEntry; + +public: + // Constructor and destructor. + GlobalStringLiteralMap(); + ~GlobalStringLiteralMap(); + + // Initialization method. + void Init(); + + // Method to retrieve a string from the map. Takes a precomputed hash (for perf). + StringLiteralEntry *GetStringLiteral(EEStringData *pStringData, DWORD dwHash, BOOL bAddIfNotFound); + + // Method to explicitly intern a string object. Takes a precomputed hash (for perf). + StringLiteralEntry *GetInternedString(STRINGREF *pString, DWORD dwHash, BOOL bAddIfNotFound); + + // Method to calculate the hash + DWORD GetHash(EEStringData* pData) + { + WRAPPER_NO_CONTRACT; + return m_StringToEntryHashTable->GetHash(pData); + } + + // public method to retrieve m_HashTableCrstGlobal + Crst* GetHashTableCrstGlobal() + { + LIMITED_METHOD_CONTRACT; + return &m_HashTableCrstGlobal; + } + +private: + // Helper method to add a string to the global string literal map. + StringLiteralEntry *AddStringLiteral(EEStringData *pStringData); + + // Helper method to add an interned string. + StringLiteralEntry *AddInternedString(STRINGREF *pString); + + // Called by StringLiteralEntry when its RefCount falls to 0. + void RemoveStringLiteralEntry(StringLiteralEntry *pEntry); + + // Hash tables that maps a Unicode string to a LiteralStringEntry. + EEUnicodeStringLiteralHashTable *m_StringToEntryHashTable; + + // The memorypool for hash entries for this hash table. + MemoryPool *m_MemoryPool; + + // The hash table table critical section. + // (the Global suffix is so that it is clear in context whether the global table is being locked + // or the per app domain table is being locked. Sometimes there was confusion in the code + // changing the name of the global one will avoid this problem and prevent copy/paste errors) + + Crst m_HashTableCrstGlobal; + + // The large heap handle table. + LargeHeapHandleTable m_LargeHeapHandleTable; + +}; + +class StringLiteralEntryArray; + +// Ref counted entry representing a string literal. +class StringLiteralEntry +{ +private: + StringLiteralEntry(EEStringData *pStringData, STRINGREF *pStringObj) + : m_pStringObj(pStringObj), m_dwRefCount(1) +#ifdef _DEBUG + , m_bDeleted(FALSE) +#endif + { + LIMITED_METHOD_CONTRACT; + } +protected: + ~StringLiteralEntry() + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(CheckPointer<void>(this)); + } + CONTRACTL_END; + } + +public: + void AddRef() + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(CheckPointer<void>(this)); + PRECONDITION((LONG)VolatileLoad(&m_dwRefCount) > 0); + PRECONDITION(SystemDomain::GetGlobalStringLiteralMapNoCreate()->m_HashTableCrstGlobal.OwnedByCurrentThread()); + } + CONTRACTL_END; + + _ASSERTE (!m_bDeleted); + + // We will keep the item alive forever if the refcount overflowed + if ((LONG)VolatileLoad(&m_dwRefCount) < 0) + return; + + VolatileStore(&m_dwRefCount, VolatileLoad(&m_dwRefCount) + 1); + } +#ifndef DACCESS_COMPILE + FORCEINLINE static void StaticRelease(StringLiteralEntry* pEntry) + { + CONTRACTL + { + PRECONDITION(SystemDomain::GetGlobalStringLiteralMapNoCreate()->m_HashTableCrstGlobal.OwnedByCurrentThread()); + } + CONTRACTL_END; + + pEntry->Release(); + } +#else + FORCEINLINE static void StaticRelease(StringLiteralEntry* /* pEntry */) + { + WRAPPER_NO_CONTRACT; + DacNotImpl(); + } +#endif // DACCESS_COMPILE + +#ifndef DACCESS_COMPILE + void Release() + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(CheckPointer<void>(this)); + PRECONDITION(VolatileLoad(&m_dwRefCount) > 0); + PRECONDITION(SystemDomain::GetGlobalStringLiteralMapNoCreate()->m_HashTableCrstGlobal.OwnedByCurrentThread()); + } + CONTRACTL_END; + + // We will keep the item alive forever if the refcount overflowed + if ((LONG)VolatileLoad(&m_dwRefCount) < 0) + return; + + VolatileStore(&m_dwRefCount, VolatileLoad(&m_dwRefCount) - 1); + if (VolatileLoad(&m_dwRefCount) == 0) + { + _ASSERTE(SystemDomain::GetGlobalStringLiteralMapNoCreate()); + SystemDomain::GetGlobalStringLiteralMapNoCreate()->RemoveStringLiteralEntry(this); + // Puts this entry in the free list + DeleteEntry (this); + } + } +#endif // DACCESS_COMPILE + + LONG GetRefCount() + { + CONTRACTL + { + NOTHROW; + if(GetThread()){GC_NOTRIGGER;}else{DISABLED(GC_TRIGGERS);}; + PRECONDITION(CheckPointer(this)); + } + CONTRACTL_END; + + _ASSERTE (!m_bDeleted); + + return (VolatileLoad(&m_dwRefCount)); + } + + STRINGREF* GetStringObject() + { + CONTRACTL + { + NOTHROW; + if(GetThread()){GC_NOTRIGGER;}else{DISABLED(GC_TRIGGERS);}; + PRECONDITION(CheckPointer(this)); + } + CONTRACTL_END; + return m_pStringObj; + } + + void GetStringData(EEStringData *pStringData) + { + CONTRACTL + { + NOTHROW; + if(GetThread()){GC_NOTRIGGER;}else{DISABLED(GC_TRIGGERS);}; + MODE_COOPERATIVE; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckPointer(pStringData)); + } + CONTRACTL_END; + + WCHAR *thisChars; + int thisLength; + + ObjectToSTRINGREF(*(StringObject**)m_pStringObj)->RefInterpretGetStringValuesDangerousForGC(&thisChars, &thisLength); + pStringData->SetCharCount (thisLength); // thisLength is in WCHARs and that's what EEStringData's char count wants + pStringData->SetStringBuffer (thisChars); + } + + static StringLiteralEntry *AllocateEntry(EEStringData *pStringData, STRINGREF *pStringObj); + static void DeleteEntry (StringLiteralEntry *pEntry); + +private: + STRINGREF* m_pStringObj; + union + { + DWORD m_dwRefCount; + StringLiteralEntry *m_pNext; + }; + +#ifdef _DEBUG + BOOL m_bDeleted; +#endif + + // The static lists below are protected by GetGlobalStringLiteralMap()->m_HashTableCrstGlobal + static StringLiteralEntryArray *s_EntryList; // always the first entry array in the chain. + static DWORD s_UsedEntries; // number of entries used up in the first array + static StringLiteralEntry *s_FreeEntryList; // free list chained thru the arrays. +}; + +typedef Wrapper<StringLiteralEntry*,DoNothing,StringLiteralEntry::StaticRelease> StringLiteralEntryHolder; + +class StringLiteralEntryArray +{ +public: + StringLiteralEntryArray *m_pNext; + BYTE m_Entries[MAX_ENTRIES_PER_CHUNK*sizeof(StringLiteralEntry)]; +}; + +#endif // _STRINGLITERALMAP_H + |