summaryrefslogtreecommitdiff
path: root/src/vm/instmethhash.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/instmethhash.h')
-rw-r--r--src/vm/instmethhash.h172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/vm/instmethhash.h b/src/vm/instmethhash.h
new file mode 100644
index 0000000000..1aa4e59f1e
--- /dev/null
+++ b/src/vm/instmethhash.h
@@ -0,0 +1,172 @@
+// 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: instmethhash.h
+//
+
+
+//
+
+//
+// ============================================================================
+
+#ifndef _INSTMETHHASH_H
+#define _INSTMETHHASH_H
+
+#include "ngenhash.h"
+
+class AllocMemTracker;
+
+//========================================================================================
+// The hash table types defined in this header file are used by the loader to
+// look up instantiation-specific methods:
+// - per-instantiation static method stubs e.g ArrayList<string>.HelperMeth
+// - instantiated methods e.g. Array.Sort<string>
+//
+// Each persisted Module has an InstMethodHashTable used for such methods that
+// were ngen'ed into that module. See ceeload.hpp for more information about ngen modules.
+//
+// Methods created at runtime are placed in an InstMethHashTable in BaseDomain.
+//
+// Keys are always derivable from the data stored in the table (MethodDesc)
+//
+// Keys are always derivable from the data stored in the table (MethodDesc),
+// with the exception of some flag values that cannot be computed for unrestore MDs
+// (we need to be able to look up entries without restoring other entries along
+// the way!)
+//
+// The table is safe for multiple readers and a single writer i.e. only one thread
+// can be in InsertMethodDesc but multiple threads can be in FindMethodDesc.
+//========================================================================================
+
+class InstMethodHashTable;
+
+// One of these is present for each element in the table
+// It simply chains together (hash,data) pairs
+typedef DPTR(struct InstMethodHashEntry) PTR_InstMethodHashEntry;
+typedef struct InstMethodHashEntry
+{
+ PTR_MethodDesc GetMethod();
+ DWORD GetFlags();
+#ifndef DACCESS_COMPILE
+ void SetMethodAndFlags(MethodDesc *pMethod, DWORD dwFlags);
+#endif // !DACCESS_COMPILE
+
+ enum
+ {
+ UnboxingStub = 0x01,
+ RequiresInstArg = 0x02
+ };
+
+private:
+ friend class InstMethodHashTable;
+#ifdef DACCESS_COMPILE
+ friend class NativeImageDumper;
+#endif
+
+ PTR_MethodDesc data;
+} InstMethodHashEntry_t;
+
+
+// The method-desc hash table itself
+typedef DPTR(class InstMethodHashTable) PTR_InstMethodHashTable;
+class InstMethodHashTable : public NgenHashTable<InstMethodHashTable, InstMethodHashEntry, 4>
+{
+#ifdef DACCESS_COMPILE
+ friend class NativeImageDumper;
+#endif
+
+public:
+ // This is the allocator
+ PTR_LoaderAllocator m_pLoaderAllocator;
+
+#ifdef _DEBUG
+private:
+ Volatile<LONG> m_dwSealCount; // Can more types be added to the table?
+
+public:
+ void InitUnseal() { LIMITED_METHOD_CONTRACT; m_dwSealCount = 0; }
+ bool IsUnsealed() { LIMITED_METHOD_CONTRACT; return (m_dwSealCount == 0); }
+ void Seal() { LIMITED_METHOD_CONTRACT; FastInterlockIncrement(&m_dwSealCount); }
+ void Unseal() { LIMITED_METHOD_CONTRACT; FastInterlockDecrement(&m_dwSealCount); }
+#endif // _DEBUG
+
+private:
+ InstMethodHashTable();
+ ~InstMethodHashTable();
+
+public:
+ static InstMethodHashTable* Create(LoaderAllocator *pAllocator, Module *pModule, DWORD dwNumBuckets, AllocMemTracker *pamTracker);
+
+private:
+ friend class NgenHashTable<InstMethodHashTable, InstMethodHashEntry, 4>;
+
+#ifndef DACCESS_COMPILE
+ InstMethodHashTable(Module *pModule, LoaderHeap *pHeap, DWORD cInitialBuckets) :
+ NgenHashTable<InstMethodHashTable, InstMethodHashEntry, 4>(pModule, pHeap, cInitialBuckets) {}
+#endif
+ void operator delete(void *p);
+
+public:
+ // Add a method desc to the hash table
+ void InsertMethodDesc(MethodDesc *pMD);
+
+ // Look up a method in the hash table
+ MethodDesc *FindMethodDesc(TypeHandle declaringType,
+ mdMethodDef token,
+ BOOL unboxingStub,
+ Instantiation inst,
+ BOOL getSharedNotStub);
+
+ BOOL ContainsMethodDesc(MethodDesc* pMD);
+
+#if defined(FEATURE_PREJIT) && !defined(DACCESS_COMPILE)
+ // Save the hash table and any method descriptors referenced by it
+ void Save(DataImage *image, CorProfileData *pProfileData);
+
+ // Record fixups required on the hash table
+ // Recurse into method descriptors referenced by it
+ void Fixup(DataImage *image);
+
+ bool ShouldSave(DataImage *pImage, InstMethodHashEntry_t *pEntry);
+ bool IsHotEntry(InstMethodHashEntry_t *pEntry, CorProfileData *pProfileData);
+ bool SaveEntry(DataImage *pImage, CorProfileData *pProfileData, InstMethodHashEntry_t *pOldEntry, InstMethodHashEntry_t *pNewEntry, EntryMappingTable *pMap);
+ void FixupEntry(DataImage *pImage, InstMethodHashEntry_t *pEntry, void *pFixupBase, DWORD cbFixupOffset);
+#endif // FEATURE_PREJIT && !DACCESS_COMPILE
+
+ // An iterator for the table, currently used only by Module::Save
+ struct Iterator
+ {
+ public:
+ // This iterator can be reused for walking different tables
+ void Reset();
+ Iterator();
+
+ Iterator(InstMethodHashTable * pTable);
+ ~Iterator();
+
+ private:
+ friend class InstMethodHashTable;
+
+ void Init();
+
+ InstMethodHashTable*m_pTable;
+ BaseIterator m_sIterator;
+ bool m_fIterating;
+ };
+
+ BOOL FindNext(Iterator *it, InstMethodHashEntry **ppEntry);
+
+ DWORD GetCount();
+
+#ifdef DACCESS_COMPILE
+ void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
+ void EnumMemoryRegionsForEntry(InstMethodHashEntry_t *pEntry, CLRDataEnumMemoryFlags flags);
+#endif
+
+private:
+ LoaderAllocator* GetLoaderAllocator();
+};
+
+#endif /* _INSTMETHHASH_H */