summaryrefslogtreecommitdiff
path: root/src/vm/dynamicmethod.h
diff options
context:
space:
mode:
authordotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
committerdotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
commitef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch)
treedee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/vm/dynamicmethod.h
downloadcoreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.gz
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.bz2
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.zip
Initial commit to populate CoreCLR repo
[tfs-changeset: 1407945]
Diffstat (limited to 'src/vm/dynamicmethod.h')
-rw-r--r--src/vm/dynamicmethod.h381
1 files changed, 381 insertions, 0 deletions
diff --git a/src/vm/dynamicmethod.h b/src/vm/dynamicmethod.h
new file mode 100644
index 0000000000..772b422093
--- /dev/null
+++ b/src/vm/dynamicmethod.h
@@ -0,0 +1,381 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+//
+
+//
+
+
+#ifndef _DYNAMICMETHOD_H_
+#define _DYNAMICMETHOD_H_
+
+#include "jitinterface.h"
+#include "methodtable.h"
+#include <daccess.h>
+
+//---------------------------------------------------------------------------------------
+//
+// This links together a set of news and release in one object.
+// The idea is to have a predefined size allocated up front and used by different calls to new.
+// All the allocation will be released at the same time releaseing an instance of this class
+// Here is how the object is laid out
+// | ptr_to_next_chunk | size_left_in_chunk | data | ... | data
+// This is not a particularly efficient allocator but it works well for a small number of allocation
+// needed while jitting a method
+//
+class ChunkAllocator
+{
+private:
+ #define CHUNK_SIZE 64
+
+ BYTE *m_pData;
+
+public:
+ ChunkAllocator() : m_pData(NULL) {}
+
+ ~ChunkAllocator();
+ void* New(size_t size);
+ void Delete();
+};
+
+//---------------------------------------------------------------------------------------
+//
+class DynamicResolver
+{
+public:
+ // Keep in sync with dynamicIlGenerator.cs
+ enum SecurityControlFlags
+ {
+ Default = 0,
+ SkipVisibilityChecks = 0x1,
+ RestrictedSkipVisibilityChecks = 0x2,
+ HasCreationContext = 0x4,
+ CanSkipCSEvaluation = 0x8,
+ };
+
+
+ // set up and clean up for jitting
+ virtual void FreeCompileTimeState() = 0;
+ virtual void GetJitContext(SecurityControlFlags * securityControlFlags,
+ TypeHandle *typeOwner) = 0;
+ virtual ChunkAllocator* GetJitMetaHeap() = 0;
+
+ //
+ // code info data
+ virtual BYTE * GetCodeInfo(
+ unsigned * pCodeSize,
+ unsigned * pStackSize,
+ CorInfoOptions * pOptions,
+ unsigned * pEHSize) = 0;
+ virtual SigPointer GetLocalSig() = 0;
+
+ //
+ // jit interface api
+ virtual OBJECTHANDLE ConstructStringLiteral(mdToken metaTok) = 0;
+ virtual BOOL IsValidStringRef(mdToken metaTok) = 0;
+ virtual void ResolveToken(mdToken token, TypeHandle * pTH, MethodDesc ** ppMD, FieldDesc ** ppFD) = 0;
+ virtual SigPointer ResolveSignature(mdToken token) = 0;
+ virtual SigPointer ResolveSignatureForVarArg(mdToken token) = 0;
+ virtual void GetEHInfo(unsigned EHnumber, CORINFO_EH_CLAUSE* clause) = 0;
+
+ virtual MethodDesc * GetDynamicMethod() = 0;
+}; // class DynamicResolver
+
+//---------------------------------------------------------------------------------------
+//
+class StringLiteralEntry;
+
+//---------------------------------------------------------------------------------------
+//
+struct DynamicStringLiteral
+{
+ DynamicStringLiteral * m_pNext;
+ StringLiteralEntry * m_pEntry;
+};
+
+//---------------------------------------------------------------------------------------
+//
+// LCGMethodResolver
+//
+// a jit resolver for managed dynamic methods
+//
+class LCGMethodResolver : public DynamicResolver
+{
+ friend class DynamicMethodDesc;
+ friend class DynamicMethodTable;
+ // review this to see whether the EEJitManageris the only thing to worry about
+ friend class ExecutionManager;
+ friend class EEJitManager;
+ friend class HostCodeHeap;
+
+public:
+ void Destroy(BOOL fDomainUnload = FALSE);
+
+ void FreeCompileTimeState();
+ void GetJitContext(SecurityControlFlags * securityControlFlags,
+ TypeHandle * typeOwner);
+ void GetJitContextCoop(SecurityControlFlags * securityControlFlags,
+ TypeHandle * typeOwner);
+ ChunkAllocator* GetJitMetaHeap();
+
+ BYTE* GetCodeInfo(unsigned *pCodeSize, unsigned *pStackSize, CorInfoOptions *pOptions, unsigned* pEHSize);
+ SigPointer GetLocalSig();
+
+ OBJECTHANDLE ConstructStringLiteral(mdToken metaTok);
+ BOOL IsValidStringRef(mdToken metaTok);
+ void ResolveToken(mdToken token, TypeHandle * pTH, MethodDesc ** ppMD, FieldDesc ** ppFD);
+ SigPointer ResolveSignature(mdToken token);
+ SigPointer ResolveSignatureForVarArg(mdToken token);
+ void GetEHInfo(unsigned EHnumber, CORINFO_EH_CLAUSE* clause);
+
+ MethodDesc* GetDynamicMethod() { LIMITED_METHOD_CONTRACT; return m_pDynamicMethod; }
+ OBJECTREF GetManagedResolver();
+ void SetManagedResolver(OBJECTHANDLE obj) { LIMITED_METHOD_CONTRACT; m_managedResolver = obj; }
+ void * GetRecordCodePointer() { LIMITED_METHOD_CONTRACT; return m_recordCodePointer; }
+
+ STRINGREF GetStringLiteral(mdToken token);
+ STRINGREF * GetOrInternString(STRINGREF *pString);
+ void AddToUsedIndCellList(BYTE * indcell);
+
+private:
+ void RecycleIndCells();
+ void Reset();
+
+ struct IndCellList
+ {
+ BYTE * indcell;
+ IndCellList * pNext;
+ };
+
+ DynamicMethodDesc* m_pDynamicMethod;
+ OBJECTHANDLE m_managedResolver;
+ BYTE *m_Code;
+ DWORD m_CodeSize;
+ SigPointer m_LocalSig;
+ unsigned short m_StackSize;
+ CorInfoOptions m_Options;
+ unsigned m_EHSize;
+ DynamicMethodTable *m_DynamicMethodTable;
+ DynamicMethodDesc *m_next;
+ void *m_recordCodePointer;
+ ChunkAllocator m_jitMetaHeap;
+ ChunkAllocator m_jitTempData;
+ DynamicStringLiteral* m_DynamicStringLiterals;
+ IndCellList * m_UsedIndCellList; // list to keep track of all the indirection cells used by the jitted code
+ JumpStubBlockHeader* m_jumpStubBlock;
+}; // class LCGMethodResolver
+
+//---------------------------------------------------------------------------------------
+//
+// a DynamicMethodTable is used by the light code generation to lazily allocate methods.
+// The methods in this MethodTable are not known up front and their signature is defined
+// at runtime
+//
+class DynamicMethodTable
+{
+public:
+#ifndef DACCESS_COMPILE
+ static void CreateDynamicMethodTable(DynamicMethodTable **ppLocation, Module *pModule, AppDomain *pDomain);
+#endif
+
+private:
+ CrstExplicitInit m_Crst;
+ DynamicMethodDesc *m_DynamicMethodList;
+ MethodTable *m_pMethodTable;
+ Module *m_Module;
+ AppDomain *m_pDomain;
+
+ DynamicMethodTable() {WRAPPER_NO_CONTRACT;}
+
+ class LockHolder : public CrstHolder
+ {
+ public:
+ LockHolder(DynamicMethodTable *pDynMT)
+ : CrstHolder(&pDynMT->m_Crst)
+ {
+ WRAPPER_NO_CONTRACT;
+ }
+ };
+ friend class LockHolder;
+
+#ifndef DACCESS_COMPILE
+ void MakeMethodTable(AllocMemTracker *pamTracker);
+ void AddMethodsToList();
+
+public:
+ void Destroy();
+ DynamicMethodDesc* GetDynamicMethod(BYTE *psig, DWORD sigSize, PTR_CUTF8 name);
+ void LinkMethod(DynamicMethodDesc *pMethod);
+
+#endif
+
+#ifdef _DEBUG
+public:
+ DWORD m_Used;
+#endif
+
+}; // class DynamicMethodTable
+
+
+//---------------------------------------------------------------------------------------
+//
+#define HOST_CODEHEAP_SIZE_ALIGN 64
+
+//---------------------------------------------------------------------------------------
+//
+// Implementation of the CodeHeap for DynamicMethods.
+// This CodeHeap uses the host interface VirtualAlloc/Free and allows
+// for reclamation of generated code
+// (Check the base class - CodeHeap in codeman.h - for comments on the functions)
+//
+class HostCodeHeap : CodeHeap
+{
+#ifdef DACCESS_COMPILE
+ friend class ClrDataAccess;
+#else
+ friend class EEJitManager;
+#endif
+
+ VPTR_VTABLE_CLASS(HostCodeHeap, CodeHeap)
+
+private:
+ // pointer back to jit manager info
+ PTR_HeapList m_pHeapList;
+ PTR_EEJitManager m_pJitManager;
+ // basic allocation data
+ PTR_BYTE m_pBaseAddr;
+ PTR_BYTE m_pLastAvailableCommittedAddr;
+ size_t m_TotalBytesAvailable;
+ size_t m_ReservedData;
+ // Heap ref count
+ DWORD m_AllocationCount;
+
+ // data to track free list and pointers into this heap
+ // - on an used block this struct has got a pointer back to the CodeHeap, size and start of aligned allocation
+ // - on an unused block (free block) this tracks the size of the block and the pointer to the next non contiguos free block
+ struct TrackAllocation {
+ union {
+ HostCodeHeap *pHeap;
+ TrackAllocation *pNext;
+ };
+ size_t size;
+
+ // the location of this TrackAllocation record will be stored right before the start of the allocated memory
+ // if there is padding between them it will be stored in that padding, otherwise it will be stored in this pad field
+ void *pad;
+ };
+ TrackAllocation *m_pFreeList;
+
+ // used for cleanup. Keep track of the next potential heap to release. Normally NULL
+ HostCodeHeap *m_pNextHeapToRelease;
+ LoaderAllocator*m_pAllocator;
+
+public:
+ static HeapList* CreateCodeHeap(CodeHeapRequestInfo *pInfo, EEJitManager *pJitManager);
+
+private:
+ HostCodeHeap(size_t ReserveBlockSize, EEJitManager *pJitManager, CodeHeapRequestInfo *pInfo);
+ BYTE* InitCodeHeapPrivateData(size_t ReserveBlockSize, size_t otherData, size_t nibbleMapSize);
+ void* AllocFromFreeList(size_t size, DWORD alignment);
+ void AddToFreeList(TrackAllocation *pBlockToInsert);
+ static size_t GetPadding(TrackAllocation *pCurrent, size_t size, DWORD alignement);
+
+ void* AllocMemory(size_t size, DWORD alignment);
+ void* AllocMemory_NoThrow(size_t size, DWORD alignment);
+
+public:
+ // Space for header is reserved immediately before. It is not included in size.
+ virtual void* AllocMemForCode_NoThrow(size_t header, size_t size, DWORD alignment) DAC_EMPTY_RET(NULL);
+
+ virtual ~HostCodeHeap() DAC_EMPTY();
+
+ LoaderAllocator* GetAllocator() { return m_pAllocator; }
+
+#ifdef DACCESS_COMPILE
+ virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
+#endif
+
+ static TrackAllocation * GetTrackAllocation(TADDR codeStart);
+ static HostCodeHeap* GetCodeHeap(TADDR codeStart);
+
+ void DestroyCodeHeap();
+
+protected:
+ friend class DynamicMethodDesc;
+ friend class LCGMethodResolver;
+
+ void FreeMemForCode(void * codeStart);
+
+}; // class HostCodeHeap
+
+//---------------------------------------------------------------------------------------
+//
+#include "ilstubresolver.h"
+
+inline MethodDesc* GetMethod(CORINFO_METHOD_HANDLE methodHandle)
+{
+ LIMITED_METHOD_CONTRACT;
+ return (MethodDesc*) methodHandle;
+}
+
+#ifndef DACCESS_COMPILE
+
+#define CORINFO_MODULE_HANDLE_TYPE_MASK 1
+
+enum CORINFO_MODULE_HANDLE_TYPES
+{
+ CORINFO_NORMAL_MODULE = 0,
+ CORINFO_DYNAMIC_MODULE,
+};
+
+inline bool IsDynamicScope(CORINFO_MODULE_HANDLE module)
+{
+ LIMITED_METHOD_CONTRACT;
+ return (CORINFO_DYNAMIC_MODULE == (((size_t)module) & CORINFO_MODULE_HANDLE_TYPE_MASK));
+}
+
+inline CORINFO_MODULE_HANDLE MakeDynamicScope(DynamicResolver* pResolver)
+{
+ LIMITED_METHOD_CONTRACT;
+ CONSISTENCY_CHECK(0 == (((size_t)pResolver) & CORINFO_MODULE_HANDLE_TYPE_MASK));
+ return (CORINFO_MODULE_HANDLE)(((size_t)pResolver) | CORINFO_DYNAMIC_MODULE);
+}
+
+inline DynamicResolver* GetDynamicResolver(CORINFO_MODULE_HANDLE module)
+{
+ LIMITED_METHOD_CONTRACT;
+ CONSISTENCY_CHECK(IsDynamicScope(module));
+ return (DynamicResolver*)(((size_t)module) & ~((size_t)CORINFO_MODULE_HANDLE_TYPE_MASK));
+}
+
+inline Module* GetModule(CORINFO_MODULE_HANDLE scope)
+{
+ WRAPPER_NO_CONTRACT;
+
+ if (IsDynamicScope(scope))
+ {
+ return GetDynamicResolver(scope)->GetDynamicMethod()->GetModule();
+ }
+ else
+ {
+ return((Module*)scope);
+ }
+}
+
+inline CORINFO_MODULE_HANDLE GetScopeHandle(Module* module)
+{
+ LIMITED_METHOD_CONTRACT;
+ return(CORINFO_MODULE_HANDLE(module));
+}
+
+inline bool IsDynamicMethodHandle(CORINFO_METHOD_HANDLE method)
+{
+ LIMITED_METHOD_CONTRACT;
+ CONSISTENCY_CHECK(NULL != GetMethod(method));
+ return GetMethod(method)->IsDynamicMethod();
+}
+
+#endif // DACCESS_COMPILE
+
+#endif // _DYNAMICMETHOD_H_