diff options
author | Pat Gavlin <pagavlin@microsoft.com> | 2016-03-03 11:51:59 -0800 |
---|---|---|
committer | Pat Gavlin <pagavlin@microsoft.com> | 2016-03-03 11:51:59 -0800 |
commit | e2df0fdbfaa688de075f020a1bf59e30fffe9fb9 (patch) | |
tree | 5611fcf0839efa44e52bff4d18a58eed852329b4 | |
parent | a70b732323b8be45a80fcd1488d60c7baa9ab0a3 (diff) | |
download | coreclr-e2df0fdbfaa688de075f020a1bf59e30fffe9fb9.tar.gz coreclr-e2df0fdbfaa688de075f020a1bf59e30fffe9fb9.tar.bz2 coreclr-e2df0fdbfaa688de075f020a1bf59e30fffe9fb9.zip |
Refactor Utilcode's IAllocators.
- `DefaultAllocator` has been replaced with `HostAllocator` in RyuJIT, which
uses the JIT hosting interface to allocate and free memory.
- The definition of `DefaultAllocator` has been moved into its own file, as it
remains in use by the interpreter and the binder.
- `ProcessHeapAllocator` has been moved into JIT32, as that was its only
remaining user.
- `AllowZeroAllocator`'s static field has been changed to an instance field
to avoid the need to define storage for the static field in Utilcode.
[tfs-changeset: 1581242]
-rw-r--r-- | src/inc/iallocator.h | 104 | ||||
-rw-r--r-- | src/inc/simplerhash.inl | 2 | ||||
-rw-r--r-- | src/jit/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/jit/compiler.cpp | 23 | ||||
-rw-r--r-- | src/jit/ee_il_dll.cpp | 2 | ||||
-rw-r--r-- | src/jit/ee_il_dll.hpp | 2 | ||||
-rw-r--r-- | src/jit/emit.cpp | 7 | ||||
-rw-r--r-- | src/jit/hostallocator.cpp | 40 | ||||
-rw-r--r-- | src/jit/hostallocator.h | 20 | ||||
-rw-r--r-- | src/jit/jit.settings.targets | 1 | ||||
-rw-r--r-- | src/utilcode/iallocator.cpp | 6 | ||||
-rw-r--r-- | src/vm/interpreter.cpp | 5 |
12 files changed, 93 insertions, 120 deletions
diff --git a/src/inc/iallocator.h b/src/inc/iallocator.h index fea024171e..b4c1b71120 100644 --- a/src/inc/iallocator.h +++ b/src/inc/iallocator.h @@ -30,55 +30,12 @@ class IAllocator virtual void Free(void* p) = 0; }; -// The "DefaultAllocator" class may be used by classes that wish to -// provide the flexibility of using an "IAllocator" may avoid writing -// conditionals at allocation sites about whether a non-default -// "IAllocator" has been provided: if none is, they can simply set the -// allocator to DefaultAllocator::Singleton(). - -class DefaultAllocator: public IAllocator -{ - static DefaultAllocator s_singleton; - - public: - void* Alloc(size_t sz) - { - return ::operator new(sz); - } - - void* ArrayAlloc(size_t elemSize, size_t numElems) - { - ClrSafeInt<size_t> safeElemSize(elemSize); - ClrSafeInt<size_t> safeNumElems(numElems); - ClrSafeInt<size_t> sz = safeElemSize * safeNumElems; - if (sz.IsOverflow()) - { - return NULL; - } - else - { - return ::operator new(sz.Value()); - } - } - - virtual void Free(void * p) - { - ::operator delete(p); - } - - static DefaultAllocator* Singleton() - { - return &s_singleton; - } -}; - // This class wraps an allocator that does not allow zero-length allocations, -// producing one that does (every zero-length allocation produces a pointer to the same +// producing one that does (every zero-length allocation produces a pointer to the same // statically-allocated memory, and freeing that pointer is a no-op). class AllowZeroAllocator: public IAllocator { - static int s_zeroLenAllocTarg; - + int m_zeroLenAllocTarg; IAllocator* m_alloc; public: @@ -87,8 +44,8 @@ public: void* Alloc(size_t sz) { if (sz == 0) - { - return (void*)(&s_zeroLenAllocTarg); + { + return (void*)(&m_zeroLenAllocTarg); } else { @@ -99,8 +56,8 @@ public: void* ArrayAlloc(size_t elemSize, size_t numElems) { if (elemSize == 0 || numElems == 0) - { - return (void*)(&s_zeroLenAllocTarg); + { + return (void*)(&m_zeroLenAllocTarg); } else { @@ -110,58 +67,11 @@ public: virtual void Free(void * p) { - if (p != (void*)(&s_zeroLenAllocTarg)) + if (p != (void*)(&m_zeroLenAllocTarg)) { m_alloc->Free(p); } } }; - -// ProcessHeapAllocator: This class implements an IAllocator that allocates and frees memory -// from the process heap. This is similar to DefaultAllocator, but it can be used by the JIT -// which doesn't allow the use of operator new/delete. - -class ProcessHeapAllocator: public IAllocator -{ - static ProcessHeapAllocator s_singleton; - -public: - - virtual void* Alloc(size_t sz) - { - return ClrAllocInProcessHeap(0, S_SIZE_T(sz)); - } - - virtual void* ArrayAlloc(size_t elemSize, size_t numElems) - { - ClrSafeInt<size_t> safeElemSize(elemSize); - ClrSafeInt<size_t> safeNumElems(numElems); - ClrSafeInt<size_t> sz = safeElemSize * safeNumElems; - if (sz.IsOverflow()) - { - return nullptr; - } - else - { - return ClrAllocInProcessHeap(0, S_SIZE_T(sz)); - } - } - - virtual void Free(void* p) - { - if (p != nullptr) - { - (void)ClrFreeInProcessHeap(0, p); - } - } - - static ProcessHeapAllocator* Singleton() - { - return &s_singleton; - } -}; - #endif // _IALLOCATOR_DEFINED_ - - diff --git a/src/inc/simplerhash.inl b/src/inc/simplerhash.inl index 1a7d004b26..091f047311 100644 --- a/src/inc/simplerhash.inl +++ b/src/inc/simplerhash.inl @@ -51,7 +51,7 @@ SimplerHashTable<Key,KeyFuncs,Value,Behavior>::SimplerHashTable(IAllocator* allo { LIMITED_METHOD_CONTRACT; - if (m_alloc == NULL) m_alloc = DefaultAllocator::Singleton(); + assert(m_alloc != nullptr); #ifndef __GNUC__ // these crash GCC static_assert_no_msg(Behavior::s_growth_factor_numerator > Behavior::s_growth_factor_denominator); diff --git a/src/jit/CMakeLists.txt b/src/jit/CMakeLists.txt index b18b8cf3be..b492cf7a9c 100644 --- a/src/jit/CMakeLists.txt +++ b/src/jit/CMakeLists.txt @@ -32,6 +32,7 @@ set( JIT_SOURCES gentree.cpp gschecks.cpp hashbv.cpp + hostallocator.cpp importer.cpp inline.cpp inlinepolicy.cpp diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index 264286679a..ca9726f04f 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -14,6 +14,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #ifdef _MSC_VER #pragma hdrstop #endif // _MSC_VER +#include "hostallocator.h" #include "emit.h" #include "ssabuilder.h" #include "valuenum.h" @@ -246,10 +247,10 @@ NodeSizeStats genNodeSizeStats; NodeSizeStats genNodeSizeStatsPerFunc; unsigned genTreeNcntHistBuckets[] = { 10, 20, 30, 40, 50, 100, 200, 300, 400, 500, 1000, 5000, 10000, 0 }; -histo genTreeNcntHist(DefaultAllocator::Singleton(), genTreeNcntHistBuckets); +histo genTreeNcntHist(HostAllocator::getHostAllocator(), genTreeNcntHistBuckets); unsigned genTreeNsizHistBuckets[] = { 1000, 5000, 10000, 50000, 100000, 500000, 1000000, 0 }; -histo genTreeNsizHist(DefaultAllocator::Singleton(), genTreeNsizHistBuckets); +histo genTreeNsizHist(HostAllocator::getHostAllocator(), genTreeNsizHistBuckets); #endif // MEASURE_NODE_SIZE /***************************************************************************** @@ -300,16 +301,16 @@ unsigned argTotalGTF_ASGinArgs; unsigned argMaxTempsPerMethod; unsigned argCntBuckets[] = { 0, 1, 2, 3, 4, 5, 6, 10, 0 }; -histo argCntTable(DefaultAllocator::Singleton(), argCntBuckets); +histo argCntTable(HostAllocator::getHostAllocator(), argCntBuckets); unsigned argDWordCntBuckets[] = { 0, 1, 2, 3, 4, 5, 6, 10, 0 }; -histo argDWordCntTable(DefaultAllocator::Singleton(), argDWordCntBuckets); +histo argDWordCntTable(HostAllocator::getHostAllocator(), argDWordCntBuckets); unsigned argDWordLngCntBuckets[] = { 0, 1, 2, 3, 4, 5, 6, 10, 0 }; -histo argDWordLngCntTable(DefaultAllocator::Singleton(), argDWordLngCntBuckets); +histo argDWordLngCntTable(HostAllocator::getHostAllocator(), argDWordLngCntBuckets); unsigned argTempsCntBuckets[] = { 0, 1, 2, 3, 4, 5, 6, 10, 0 }; -histo argTempsCntTable(DefaultAllocator::Singleton(), argTempsCntBuckets); +histo argTempsCntTable(HostAllocator::getHostAllocator(), argTempsCntBuckets); #endif // CALL_ARG_STATS @@ -336,12 +337,12 @@ histo argTempsCntTable(DefaultAllocator::Singleton(), argTempsCntBuckets); // -------------------------------------------------- unsigned bbCntBuckets[] = { 1, 2, 3, 5, 10, 20, 50, 100, 1000, 10000, 0 }; -histo bbCntTable(DefaultAllocator::Singleton(), bbCntBuckets); +histo bbCntTable(HostAllocator::getHostAllocator(), bbCntBuckets); /* Histogram for the IL opcode size of methods with a single basic block */ unsigned bbSizeBuckets[] = { 1, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 0 }; -histo bbOneBBSizeTable(DefaultAllocator::Singleton(), bbSizeBuckets); +histo bbOneBBSizeTable(HostAllocator::getHostAllocator(), bbSizeBuckets); #endif // COUNT_BASIC_BLOCKS @@ -373,12 +374,12 @@ bool loopOverflowThisMethod; // True if we exceeded the max # of loop /* Histogram for number of loops in a method */ unsigned loopCountBuckets[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 }; -histo loopCountTable(DefaultAllocator::Singleton(), loopCountBuckets); +histo loopCountTable(HostAllocator::getHostAllocator(), loopCountBuckets); /* Histogram for number of loop exits */ unsigned loopExitCountBuckets[] = { 0, 1, 2, 3, 4, 5, 6, 0 }; -histo loopExitCountTable(DefaultAllocator::Singleton(), loopExitCountBuckets); +histo loopExitCountTable(HostAllocator::getHostAllocator(), loopExitCountBuckets); #endif // COUNT_LOOPS @@ -2113,7 +2114,7 @@ void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags) { // NOTE: The Assembly name list is allocated in the process heap, not in the no-release heap, which is reclaimed // for every compilation. This is ok because we only allocate once, due to the static. - s_pAltJitExcludeAssembliesList = new (ProcessHeapAllocator::Singleton()) AssemblyNamesList2(wszAltJitExcludeAssemblyList, ProcessHeapAllocator::Singleton()); + s_pAltJitExcludeAssembliesList = new (HostAllocator::getHostAllocator()) AssemblyNamesList2(wszAltJitExcludeAssemblyList, HostAllocator::getHostAllocator()); } } diff --git a/src/jit/ee_il_dll.cpp b/src/jit/ee_il_dll.cpp index dc069fe0e6..da0ae901fe 100644 --- a/src/jit/ee_il_dll.cpp +++ b/src/jit/ee_il_dll.cpp @@ -22,7 +22,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX /*****************************************************************************/ -static ICorJitHost* g_jitHost = nullptr; +ICorJitHost* g_jitHost = nullptr; static CILJit* ILJitter = 0; // The one and only JITTER I return #ifndef FEATURE_MERGE_JIT_AND_ENGINE HINSTANCE g_hInst = NULL; diff --git a/src/jit/ee_il_dll.hpp b/src/jit/ee_il_dll.hpp index c61deb57a1..b1e0327d6b 100644 --- a/src/jit/ee_il_dll.hpp +++ b/src/jit/ee_il_dll.hpp @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +extern ICorJitHost* g_jitHost; + class CILJit: public ICorJitCompiler { CorJitResult __stdcall compileMethod ( diff --git a/src/jit/emit.cpp b/src/jit/emit.cpp index 493d13cde0..e5b6842b14 100644 --- a/src/jit/emit.cpp +++ b/src/jit/emit.cpp @@ -16,6 +16,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #pragma hdrstop #endif +#include "hostallocator.h" #include "instr.h" #include "emit.h" #include "codegen.h" @@ -264,13 +265,13 @@ static unsigned totActualSize; unsigned emitter::emitIFcounts[emitter::IF_COUNT]; static unsigned emitSizeBuckets[] = { 100, 1024*1, 1024*2, 1024*3, 1024*4, 1024*5, 1024*10, 0 }; -static histo emitSizeTable(DefaultAllocator::Singleton(), emitSizeBuckets); +static histo emitSizeTable(HostAllocator::getHostAllocator(), emitSizeBuckets); static unsigned GCrefsBuckets[] = { 0, 1, 2, 5, 10, 20, 50, 128, 256, 512, 1024, 0 }; -static histo GCrefsTable(DefaultAllocator::Singleton(), GCrefsBuckets); +static histo GCrefsTable(HostAllocator::getHostAllocator(), GCrefsBuckets); static unsigned stkDepthBuckets[] = { 0, 1, 2, 5, 10, 16, 32, 128, 1024, 0 }; -static histo stkDepthTable(DefaultAllocator::Singleton(), stkDepthBuckets); +static histo stkDepthTable(HostAllocator::getHostAllocator(), stkDepthBuckets); size_t emitter::emitSizeMethod; diff --git a/src/jit/hostallocator.cpp b/src/jit/hostallocator.cpp new file mode 100644 index 0000000000..b737424ee8 --- /dev/null +++ b/src/jit/hostallocator.cpp @@ -0,0 +1,40 @@ +// 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. + +#include "jitpch.h" +#include "hostallocator.h" + +HostAllocator HostAllocator::s_hostAllocator; + +void* HostAllocator::Alloc(size_t size) +{ + assert(g_jitHost != nullptr); + return g_jitHost->allocateMemory(size, false); +} + +void* HostAllocator::ArrayAlloc(size_t elemSize, size_t numElems) +{ + assert(g_jitHost != nullptr); + + ClrSafeInt<size_t> safeElemSize(elemSize); + ClrSafeInt<size_t> safeNumElems(numElems); + ClrSafeInt<size_t> size = safeElemSize * safeNumElems; + if (size.IsOverflow()) + { + return nullptr; + } + + return g_jitHost->allocateMemory(size.Value(), false); +} + +void HostAllocator::Free(void* p) +{ + assert(g_jitHost != nullptr); + g_jitHost->freeMemory(p, false); +} + +HostAllocator* HostAllocator::getHostAllocator() +{ + return &s_hostAllocator; +} diff --git a/src/jit/hostallocator.h b/src/jit/hostallocator.h new file mode 100644 index 0000000000..c51eccc75e --- /dev/null +++ b/src/jit/hostallocator.h @@ -0,0 +1,20 @@ +// 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. + +class HostAllocator : public IAllocator +{ +private: + static HostAllocator s_hostAllocator; + + HostAllocator() {} + +public: + void* Alloc(size_t size) override; + + void* ArrayAlloc(size_t elemSize, size_t numElems) override; + + void Free(void* p) override; + + static HostAllocator* getHostAllocator(); +}; diff --git a/src/jit/jit.settings.targets b/src/jit/jit.settings.targets index dfbe8f85f9..b95852f63c 100644 --- a/src/jit/jit.settings.targets +++ b/src/jit/jit.settings.targets @@ -82,6 +82,7 @@ <CppCompile Include="..\LoopCloning.cpp" /> <CppCompile Include="..\inline.cpp" /> <CppCompile Include="..\inlinepolicy.cpp" /> + <CppCompile Include="..\hostallocator.cpp" /> <CppCompile Condition="'$(ClDefines.Contains(`LEGACY_BACKEND`))'=='True'" Include="..\CodeGenLegacy.cpp" /> <CppCompile Condition="'$(ClDefines.Contains(`LEGACY_BACKEND`))'=='False'" Include="..\Lower.cpp" /> <CppCompile Condition="'$(ClDefines.Contains(`LEGACY_BACKEND`))'=='False'" Include="..\LSRA.cpp" /> diff --git a/src/utilcode/iallocator.cpp b/src/utilcode/iallocator.cpp index d6dabc7f2e..8c5fc838e5 100644 --- a/src/utilcode/iallocator.cpp +++ b/src/utilcode/iallocator.cpp @@ -4,11 +4,7 @@ #include "stdafx.h" // Precompiled header key. #include "iallocator.h" +#include "defaultallocator.h" // static DefaultAllocator DefaultAllocator::s_singleton; - -// static -ProcessHeapAllocator ProcessHeapAllocator::s_singleton; - -int AllowZeroAllocator::s_zeroLenAllocTarg; diff --git a/src/vm/interpreter.cpp b/src/vm/interpreter.cpp index a846e424df..bdfa9622f9 100644 --- a/src/vm/interpreter.cpp +++ b/src/vm/interpreter.cpp @@ -23,6 +23,7 @@ #include "runtimehandles.h" #include "vars.hpp" #include "cycletimer.h" +#include "defaultallocator.h" #ifdef FEATURE_REMOTING #include "remoting.h" #endif @@ -10837,7 +10838,7 @@ Interpreter::AddrToMDMap* Interpreter::GetAddrToMdMap() if (s_addrToMDMap == NULL) { - s_addrToMDMap = new AddrToMDMap(/* use default allocator */ NULL); + s_addrToMDMap = new AddrToMDMap(DefaultAllocator::Singleton()); } return s_addrToMDMap; } @@ -10899,7 +10900,7 @@ Interpreter::MethodHandleToInterpMethInfoPtrMap* Interpreter::GetMethodHandleToI if (s_methodHandleToInterpMethInfoPtrMap == NULL) { - s_methodHandleToInterpMethInfoPtrMap = new MethodHandleToInterpMethInfoPtrMap(/* use default allocator */ NULL); + s_methodHandleToInterpMethInfoPtrMap = new MethodHandleToInterpMethInfoPtrMap(DefaultAllocator::Singleton()); } return s_methodHandleToInterpMethInfoPtrMap; } |