diff options
author | Pat Gavlin <pgavlin@gmail.com> | 2016-04-12 16:57:42 -0700 |
---|---|---|
committer | Pat Gavlin <pgavlin@gmail.com> | 2016-04-12 16:57:42 -0700 |
commit | 867b8f1ff301d1d0842abec75447be4e94c1f17c (patch) | |
tree | 5c3a39a2c6d8fe8a3c8381a83a1541e90102079a | |
parent | 5d55afa3600904dd2376db9af9838f2fbba27945 (diff) | |
parent | d241f9d5bcdaf9e99e4c4e54508d2cec2ed35d04 (diff) | |
download | coreclr-867b8f1ff301d1d0842abec75447be4e94c1f17c.tar.gz coreclr-867b8f1ff301d1d0842abec75447be4e94c1f17c.tar.bz2 coreclr-867b8f1ff301d1d0842abec75447be4e94c1f17c.zip |
Merge pull request #4255 from pgavlin/GcInfoArrayList
Refactor `StructArrayList` for the GC info encoder.
-rw-r--r-- | src/gcinfo/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/gcinfo/arraylist.cpp | 104 | ||||
-rw-r--r-- | src/gcinfo/dbggcinfoencoder.cpp | 4 | ||||
-rw-r--r-- | src/gcinfo/gcinfo.settings.targets | 1 | ||||
-rw-r--r-- | src/gcinfo/gcinfoencoder.cpp | 8 | ||||
-rw-r--r-- | src/inc/arraylist.h | 279 | ||||
-rw-r--r-- | src/inc/dbggcinfoencoder.h | 13 | ||||
-rw-r--r-- | src/inc/gcinfoarraylist.h | 114 | ||||
-rw-r--r-- | src/inc/gcinfoencoder.h | 44 | ||||
-rw-r--r-- | src/utilcode/arraylist.cpp | 84 |
10 files changed, 232 insertions, 420 deletions
diff --git a/src/gcinfo/CMakeLists.txt b/src/gcinfo/CMakeLists.txt index d8b91d11f0..53a1ad2591 100644 --- a/src/gcinfo/CMakeLists.txt +++ b/src/gcinfo/CMakeLists.txt @@ -1,6 +1,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set( GCINFO_SOURCES + arraylist.cpp gcinfoencoder.cpp dbggcinfoencoder.cpp ) diff --git a/src/gcinfo/arraylist.cpp b/src/gcinfo/arraylist.cpp new file mode 100644 index 0000000000..566304c7ac --- /dev/null +++ b/src/gcinfo/arraylist.cpp @@ -0,0 +1,104 @@ +// 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 <stdint.h> +#include <windows.h> +#include "debugmacros.h" +#include "iallocator.h" +#include "gcinfoarraylist.h" +#include "safemath.h" + +inline size_t roundUp(size_t size, size_t alignment) +{ + // `alignment` must be a power of two + assert(alignment != 0); + assert((alignment & (alignment - 1)) == 0); + + return (size + (alignment - 1)) & ~(alignment - 1); +} + +GcInfoArrayListBase::GcInfoArrayListBase(IAllocator* allocator) + : m_allocator(allocator), + m_firstChunk(nullptr), + m_lastChunk(nullptr), + m_lastChunkCount(0), + m_lastChunkCapacity(0), + m_itemCount(0) +{ + assert(m_allocator != nullptr); +} + +GcInfoArrayListBase::~GcInfoArrayListBase() +{ + for (ChunkBase* list = m_firstChunk, *chunk; list != nullptr; list = chunk) + { + chunk = list->m_next; + m_allocator->Free(list); + } +} + +void GcInfoArrayListBase::AppendNewChunk(size_t firstChunkCapacity, size_t elementSize, size_t chunkAlignment) +{ + size_t chunkCapacity = (m_firstChunk == nullptr) ? firstChunkCapacity : (m_lastChunkCapacity * GrowthFactor); + + S_SIZE_T chunkSize = S_SIZE_T(roundUp(sizeof(ChunkBase), chunkAlignment)) + (S_SIZE_T(elementSize) * S_SIZE_T(chunkCapacity)); + assert(!chunkSize.IsOverflow()); + + ChunkBase* chunk = reinterpret_cast<ChunkBase*>(m_allocator->Alloc(chunkSize.Value())); + chunk->m_next = nullptr; + + if (m_lastChunk != nullptr) + { + assert(m_firstChunk != nullptr); + m_lastChunk->m_next = chunk; + } + else + { + assert(m_lastChunk == nullptr); + m_firstChunk = chunk; + } + + m_lastChunk = chunk; + m_lastChunkCount = 0; + m_lastChunkCapacity = chunkCapacity; +} + +GcInfoArrayListBase::IteratorBase::IteratorBase(GcInfoArrayListBase* list, size_t firstChunkCapacity) + : m_list(list) +{ + assert(m_list != nullptr); + + // Note: if the list is empty, m_list->firstChunk == nullptr == m_list->lastChunk and m_lastChunkCount == 0. + // In that case, the next two lines will set m_currentChunk to nullptr and m_currentChunkCount to 0. + m_currentChunk = m_list->m_firstChunk; + m_currentChunkCount = (m_currentChunk == m_list->m_lastChunk) ? m_list->m_lastChunkCount : firstChunkCapacity; +} + +GcInfoArrayListBase::ChunkBase* GcInfoArrayListBase::IteratorBase::GetNextChunk(size_t& elementCount) +{ + if (m_currentChunk == nullptr) + { + elementCount = 0; + return nullptr; + } + + ChunkBase* chunk = m_currentChunk; + elementCount = m_currentChunkCount; + + m_currentChunk = m_currentChunk->m_next; + if (m_currentChunk == nullptr) + { + m_currentChunkCount = 0; + } + else if (m_currentChunk == m_list->m_lastChunk) + { + m_currentChunkCount = m_list->m_lastChunkCount; + } + else + { + m_currentChunkCount *= GrowthFactor; + } + + return chunk; +} diff --git a/src/gcinfo/dbggcinfoencoder.cpp b/src/gcinfo/dbggcinfoencoder.cpp index eb18f69570..c41db2fe7e 100644 --- a/src/gcinfo/dbggcinfoencoder.cpp +++ b/src/gcinfo/dbggcinfoencoder.cpp @@ -74,7 +74,7 @@ GcInfoEncoder::GcInfoEncoder( #endif #endif m_FullyInterruptibleInfoWriter( pJitAllocator ), - m_LifetimeTransitions() + m_LifetimeTransitions( pJitAllocator ) { _ASSERTE( pCorJitInfo != NULL ); _ASSERTE( pMethodInfo != NULL ); @@ -354,7 +354,7 @@ void GcInfoEncoder::SetSlotState( transition.CodeOffset = instructionOffset; transition.BecomesLive = ( slotState == GC_SLOT_LIVE ); - *( m_LifetimeTransitions.AppendThrowing() ) = transition; + *( m_LifetimeTransitions.Append() ) = transition; } diff --git a/src/gcinfo/gcinfo.settings.targets b/src/gcinfo/gcinfo.settings.targets index b20bca410d..f600e2a904 100644 --- a/src/gcinfo/gcinfo.settings.targets +++ b/src/gcinfo/gcinfo.settings.targets @@ -12,6 +12,7 @@ <!-- Leaf Project Items --> <ItemGroup> + <CppCompile Include="..\ArrayList.cpp" /> <CppCompile Include="..\GCInfoEncoder.cpp" /> <CppCompile Include="..\DbgGCInfoEncoder.cpp" /> </ItemGroup> diff --git a/src/gcinfo/gcinfoencoder.cpp b/src/gcinfo/gcinfoencoder.cpp index a013c4258a..95673a1677 100644 --- a/src/gcinfo/gcinfoencoder.cpp +++ b/src/gcinfo/gcinfoencoder.cpp @@ -438,8 +438,8 @@ GcInfoEncoder::GcInfoEncoder( ) : m_Info1( pJitAllocator ), m_Info2( pJitAllocator ), - m_InterruptibleRanges(), - m_LifetimeTransitions() + m_InterruptibleRanges( pJitAllocator ), + m_LifetimeTransitions( pJitAllocator ) #ifdef VERIFY_GCINFO , m_DbgEncoder(pCorJitInfo, pMethodInfo, pJitAllocator) #endif @@ -647,7 +647,7 @@ void GcInfoEncoder::DefineInterruptibleRange( UINT32 startInstructionOffset, UIN InterruptibleRange range; range.NormStartOffset = normStartOffset; range.NormStopOffset = normStopOffset; - m_pLastInterruptibleRange = m_InterruptibleRanges.AppendThrowing(); + m_pLastInterruptibleRange = m_InterruptibleRanges.Append(); *m_pLastInterruptibleRange = range; } } @@ -679,7 +679,7 @@ void GcInfoEncoder::SetSlotState( transition.BecomesLive = ( slotState == GC_SLOT_LIVE ); transition.IsDeleted = FALSE; - *( m_LifetimeTransitions.AppendThrowing() ) = transition; + *( m_LifetimeTransitions.Append() ) = transition; LOG((LF_GCINFO, LL_INFO1000000, LOG_GCSLOTDESC_FMT " %s at %x\n", LOG_GCSLOTDESC_ARGS(&m_SlotTable[slotId]), slotState == GC_SLOT_LIVE ? "live" : "dead", instructionOffset)); } diff --git a/src/inc/arraylist.h b/src/inc/arraylist.h index b70951490e..f45085bf33 100644 --- a/src/inc/arraylist.h +++ b/src/inc/arraylist.h @@ -302,283 +302,4 @@ typedef DPTR(ArrayListStatic) PTR_ArrayListStatic; #pragma warning(pop) #endif - - -//***************************************************************************** -// StructArrayList is similar to ArrayList, but the element type can be any -// arbitrary type. Elements can only be accessed sequentially. This is -// basically just a more efficient linked list - it's useful for accumulating -// lots of small fixed-size allocations into larger chunks, which would -// otherwise have an unnecessarily high ratio of heap overhead. -// -// The allocator provided must throw an exception on failure. -//***************************************************************************** - -struct StructArrayListEntryBase -{ - StructArrayListEntryBase *pNext; // actually StructArrayListEntry<ELEMENT_TYPE>* -}; - -template<class ELEMENT_TYPE> -struct StructArrayListEntry : StructArrayListEntryBase -{ - ELEMENT_TYPE rgItems[1]; -}; - -class StructArrayListBase -{ -protected: - - typedef void *AllocProc (void *pvContext, SIZE_T cb); - typedef void FreeProc (void *pvContext, void *pv); - - StructArrayListBase () - { - LIMITED_METHOD_CONTRACT; - - m_pChunkListHead = NULL; - m_pChunkListTail = NULL; - m_nTotalItems = 0; - } - - void Destruct (FreeProc *pfnFree); - - void CreateNewChunk (SIZE_T InitialChunkLength, SIZE_T ChunkLengthGrowthFactor, SIZE_T cbElement, AllocProc *pfnAlloc, SIZE_T alignment); - - class ArrayIteratorBase - { - protected: - - void SetCurrentChunk (StructArrayListEntryBase *pChunk, SIZE_T nChunkCapacity); - - StructArrayListEntryBase *m_pCurrentChunk; - SIZE_T m_nItemsInCurrentChunk; - SIZE_T m_nCurrentChunkCapacity; - StructArrayListBase *m_pArrayList; - }; - friend class ArrayIteratorBase; - - StructArrayListEntryBase *m_pChunkListHead; // actually StructArrayListEntry<ELEMENT_TYPE>* - StructArrayListEntryBase *m_pChunkListTail; // actually StructArrayListEntry<ELEMENT_TYPE>* - SIZE_T m_nItemsInLastChunk; - SIZE_T m_nTotalItems; - SIZE_T m_nLastChunkCapacity; -}; - -template <class ELEMENT_TYPE, - SIZE_T INITIAL_CHUNK_LENGTH, - SIZE_T CHUNK_LENGTH_GROWTH_FACTOR, - class ALLOCATOR> -class StructArrayList : public StructArrayListBase -{ -private: - - static_assert_n(1, INITIAL_CHUNK_LENGTH > 0); - static_assert_n(2, CHUNK_LENGTH_GROWTH_FACTOR > 0); - - friend class ArrayIterator; - friend class ElementIterator; - -public: - - StructArrayList () - { - LIMITED_METHOD_CONTRACT; - } - - ~StructArrayList () - { - WRAPPER_NO_CONTRACT; - - Destruct(&ALLOCATOR::Free); - } - - ELEMENT_TYPE *AppendThrowing () - { - CONTRACTL { - THROWS; - } CONTRACTL_END; - - if (!m_pChunkListTail || m_nItemsInLastChunk == m_nLastChunkCapacity) - CreateNewChunk(INITIAL_CHUNK_LENGTH, CHUNK_LENGTH_GROWTH_FACTOR, sizeof(ELEMENT_TYPE), &ALLOCATOR::Alloc, __alignof(ELEMENT_TYPE)); - - m_nTotalItems++; - m_nItemsInLastChunk++; - return &((StructArrayListEntry<ELEMENT_TYPE>*)m_pChunkListTail)->rgItems[m_nItemsInLastChunk-1]; - } - - SIZE_T Count () - { - LIMITED_METHOD_CONTRACT; - - return m_nTotalItems; - } - - VOID CopyTo (ELEMENT_TYPE *pDest) - { - ArrayIterator iter(this); - ELEMENT_TYPE *pSrc; - SIZE_T nSrc; - - while ((pSrc = iter.GetNext(&nSrc))) - { - memcpy(pDest, pSrc, nSrc * sizeof(ELEMENT_TYPE)); - pDest += nSrc; - } - } - - ELEMENT_TYPE *GetIndex(SIZE_T index) - { - ArrayIterator iter(this); - - ELEMENT_TYPE * chunk; - SIZE_T count; - SIZE_T chunkBaseIndex = 0; - - while ((chunk = iter.GetNext(&count))) - { - SIZE_T nextBaseIndex = chunkBaseIndex + count; - if (nextBaseIndex > index) - { - return (chunk + (index - chunkBaseIndex)); - } - chunkBaseIndex = nextBaseIndex; - } - // Should never reach here - assert(false); - return NULL; - } - - class ArrayIterator : public ArrayIteratorBase - { - public: - - ArrayIterator (StructArrayList *pArrayList) - { - WRAPPER_NO_CONTRACT; - - m_pArrayList = pArrayList; - SetCurrentChunk(pArrayList->m_pChunkListHead, INITIAL_CHUNK_LENGTH); - } - - ELEMENT_TYPE *GetCurrent (SIZE_T *pnElements) - { - LIMITED_METHOD_CONTRACT; - - ELEMENT_TYPE *pRet = NULL; - SIZE_T nElements = 0; - - if (m_pCurrentChunk) - { - pRet = &((StructArrayListEntry<ELEMENT_TYPE>*)m_pCurrentChunk)->rgItems[0]; - nElements = m_nItemsInCurrentChunk; - } - - *pnElements = nElements; - return pRet; - } - - // Returns NULL when there are no more items. - ELEMENT_TYPE *GetNext (SIZE_T *pnElements) - { - WRAPPER_NO_CONTRACT; - - ELEMENT_TYPE *pRet = GetCurrent(pnElements); - - if (pRet) - SetCurrentChunk(m_pCurrentChunk->pNext, m_nCurrentChunkCapacity * CHUNK_LENGTH_GROWTH_FACTOR); - - return pRet; - } - }; - - class ItemIterator - { - - typedef StructArrayList<ELEMENT_TYPE, INITIAL_CHUNK_LENGTH, CHUNK_LENGTH_GROWTH_FACTOR, ALLOCATOR> - SAList; - - typedef typename StructArrayList<ELEMENT_TYPE, INITIAL_CHUNK_LENGTH, CHUNK_LENGTH_GROWTH_FACTOR, ALLOCATOR>::ArrayIterator - ArrIter; - - public: - - ItemIterator(SAList *list) : iter(list) - { - currentChunkIndex = 0; - currentChunk = iter.GetNext(¤tChunkCount); - } - - ELEMENT_TYPE * - GetNext() - { - ELEMENT_TYPE * returnElem = (currentChunk + currentChunkIndex); - - currentChunkIndex++; - if (currentChunkIndex == currentChunkCount) - { - currentChunkIndex = 0; - currentChunk = iter.GetNext(¤tChunkCount); - } - return returnElem; - } - - ELEMENT_TYPE *operator*() - { - return currentChunk + currentChunkIndex; - } - - void operator++(int dummy) //int dummy is c++ for "this is postfix ++" - { - GetNext(); - } - - void operator++() // prefix ++ - { - GetNext(); - } - - void MakeEnd() - { - currentChunk = NULL; - currentChunkIndex = 0; - } - - bool operator!=(const ItemIterator &other) - { - if (currentChunk != other.currentChunk) - return true; - if (currentChunkIndex != other.currentChunkIndex) - return true; - - return false; - } - - operator bool() - { - return currentChunk != NULL; - } - - private: - unsigned currentChunkIndex; - SIZE_T currentChunkCount; - ELEMENT_TYPE *currentChunk; - ArrIter iter; - }; - - - ItemIterator begin() - { - return ItemIterator(this); - } - - ItemIterator end() - { - ItemIterator result = ItemIterator(this); - result.MakeEnd(); - return result; - } -}; - - #endif diff --git a/src/inc/dbggcinfoencoder.h b/src/inc/dbggcinfoencoder.h index 95450fb278..5442213dbf 100644 --- a/src/inc/dbggcinfoencoder.h +++ b/src/inc/dbggcinfoencoder.h @@ -24,7 +24,8 @@ #include "utilcode.h" #include "corjit.h" #include "list.h" // for SList -#include "arraylist.h" +#include "iallocator.h" +#include "gcinfoarraylist.h" #include "stdmacros.h" #include "gcinfotypes.h" @@ -343,14 +344,6 @@ private: bool BecomesLive; }; - class LifetimeTransitionAllocator - { - public: - - static void *Alloc (void *context, SIZE_T cb); - static void Free (void *context, void *pv); - }; - ICorJitInfo* m_pCorJitInfo; CORINFO_METHOD_INFO* m_pMethodInfo; IJitAllocator* m_pAllocator; @@ -367,7 +360,7 @@ private: #endif BitStreamWriter m_FullyInterruptibleInfoWriter; - StructArrayList<LifetimeTransition, 64, 2, LifetimeTransitionAllocator> m_LifetimeTransitions; + GcInfoArrayList<LifetimeTransition, 64> m_LifetimeTransitions; LifetimeTransition *m_rgSortedTransitions; bool m_IsVarArg; diff --git a/src/inc/gcinfoarraylist.h b/src/inc/gcinfoarraylist.h new file mode 100644 index 0000000000..c19f00d42f --- /dev/null +++ b/src/inc/gcinfoarraylist.h @@ -0,0 +1,114 @@ +// 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. + +#ifndef _GCINFOARRAYLIST_H_ +#define _GCINFOARRAYLIST_H_ + +// GCInfoArrayList is basically a more efficient linked list--it's useful for accumulating +// lots of small fixed-size allocations into larger chunks which in a typical linked list +// would incur an unnecessarily high amount of overhead. + +class GcInfoArrayListBase +{ +private: + static const size_t GrowthFactor = 2; + +protected: + friend class IteratorBase; + + struct ChunkBase + { + ChunkBase* m_next; // actually GcInfoArrayListChunk<ElementType>* + }; + + class IteratorBase + { + protected: + IteratorBase(GcInfoArrayListBase* list, size_t firstChunkCapacity); + ChunkBase* GetNextChunk(size_t& elementCount); + + private: + GcInfoArrayListBase* m_list; + ChunkBase* m_currentChunk; + size_t m_currentChunkCount; + }; + + GcInfoArrayListBase(IAllocator* allocator); + virtual ~GcInfoArrayListBase(); + + void AppendNewChunk(size_t firstChunkCapacity, size_t elementSize, size_t chunkAlignment); + +public: + size_t Count() + { + return m_itemCount; + } + +protected: + IAllocator* m_allocator; + ChunkBase* m_firstChunk; // actually GcInfoArrayListChunk<ElementType>* + ChunkBase* m_lastChunk; // actually GcInfoArrayListChunk<ElementType>* + size_t m_lastChunkCount; + size_t m_lastChunkCapacity; + size_t m_itemCount; +}; + +template <typename ElementType, size_t FirstChunkCapacity> +class GcInfoArrayList : public GcInfoArrayListBase +{ +private: + struct Chunk : public ChunkBase + { + ElementType m_items[]; + }; + +public: + friend class Iterator; + + struct Iterator : IteratorBase + { + Iterator(GcInfoArrayList* list) + : IteratorBase(list, FirstChunkCapacity) + { + } + + ElementType* GetNext(size_t* elementCount) + { + Chunk* chunk = reinterpret_cast<Chunk*>(GetNextChunk(*elementCount)); + return chunk == nullptr ? nullptr : &chunk->m_items[0]; + } + }; + + GcInfoArrayList(IAllocator* allocator) + : GcInfoArrayListBase(allocator) + { + } + + ElementType* Append() + { + if (m_lastChunk == nullptr || m_lastChunkCount == m_lastChunkCapacity) + { + AppendNewChunk(FirstChunkCapacity, sizeof(ElementType), __alignof(ElementType)); + } + + m_itemCount++; + m_lastChunkCount++; + return &reinterpret_cast<Chunk*>(m_lastChunk)->m_items[m_lastChunkCount - 1]; + } + + void CopyTo(ElementType* dest) + { + Iterator iter(this); + ElementType* source; + size_t elementCount; + + while (source = iter.GetNext(&elementCount), source != nullptr) + { + memcpy(dest, source, elementCount * sizeof(ElementType)); + dest += elementCount; + } + } +}; + +#endif diff --git a/src/inc/gcinfoencoder.h b/src/inc/gcinfoencoder.h index a66d87af22..8a5e760545 100644 --- a/src/inc/gcinfoencoder.h +++ b/src/inc/gcinfoencoder.h @@ -81,8 +81,8 @@ #include "utilcode.h" #include "corjit.h" #include "slist.h" // for SList -#include "arraylist.h" #include "iallocator.h" +#include "gcinfoarraylist.h" #include "stdmacros.h" #include "eexcp.h" #endif @@ -438,44 +438,6 @@ private: UINT32 NormStopOffset; }; - class InterruptibleRangeAllocator - { - public: - - static void *Alloc (void *context, SIZE_T cb) - { - GcInfoEncoder *pGcInfoEncoder = CONTAINING_RECORD(context, GcInfoEncoder, m_InterruptibleRanges); - return pGcInfoEncoder->m_pAllocator->Alloc(cb); - } - - static void Free (void *context, void *pv) - { - #ifdef MUST_CALL_IALLOCATOR_FREE - GcInfoEncoder *pGcInfoEncoder = CONTAINING_RECORD(context, GcInfoEncoder, m_InterruptibleRanges); - pGcInfoEncoder->m_pAllocator->Free(pv); - #endif - } - }; - - class LifetimeTransitionAllocator - { - public: - - static void *Alloc (void *context, SIZE_T cb) - { - GcInfoEncoder *pGcInfoEncoder = CONTAINING_RECORD(context, GcInfoEncoder, m_LifetimeTransitions); - return pGcInfoEncoder->m_pAllocator->Alloc(cb); - } - - static void Free (void *context, void *pv) - { - #ifdef MUST_CALL_IALLOCATOR_FREE - GcInfoEncoder *pGcInfoEncoder = CONTAINING_RECORD(context, GcInfoEncoder, m_LifetimeTransitions); - pGcInfoEncoder->m_pAllocator->Free(pv); - #endif - } - }; - ICorJitInfo* m_pCorJitInfo; CORINFO_METHOD_INFO* m_pMethodInfo; IAllocator* m_pAllocator; @@ -488,8 +450,8 @@ private: BitStreamWriter m_Info1; // Used for everything except for chunk encodings BitStreamWriter m_Info2; // Used for chunk encodings - StructArrayList<InterruptibleRange, 8, 2, InterruptibleRangeAllocator> m_InterruptibleRanges; - StructArrayList<LifetimeTransition, 64, 2, LifetimeTransitionAllocator> m_LifetimeTransitions; + GcInfoArrayList<InterruptibleRange, 8> m_InterruptibleRanges; + GcInfoArrayList<LifetimeTransition, 64> m_LifetimeTransitions; bool m_IsVarArg; bool m_WantsReportOnlyLeaf; diff --git a/src/utilcode/arraylist.cpp b/src/utilcode/arraylist.cpp index 1b962c06ae..30793c4559 100644 --- a/src/utilcode/arraylist.cpp +++ b/src/utilcode/arraylist.cpp @@ -224,87 +224,3 @@ ArrayListBase::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) } #endif // #ifdef DACCESS_COMPILE - - -void StructArrayListBase::Destruct (FreeProc *pfnFree) -{ - WRAPPER_NO_CONTRACT; - - StructArrayListEntryBase *pList = m_pChunkListHead; - while (pList) - { - StructArrayListEntryBase *pTrash = pList; - pList = pList->pNext; - pfnFree(this, pTrash); - } -} - -// Copied from jit.h -inline -size_t roundUp(size_t size, size_t mult = sizeof(size_t)) -{ - assert(mult && ((mult & (mult-1)) == 0)); // power of two test - - return (size + (mult - 1)) & ~(mult - 1); -} - -void StructArrayListBase::CreateNewChunk (SIZE_T InitialChunkLength, SIZE_T ChunkLengthGrowthFactor, SIZE_T cbElement, AllocProc *pfnAlloc, SIZE_T alignment) -{ - CONTRACTL { - THROWS; - PRECONDITION(!m_pChunkListHead || m_nItemsInLastChunk == m_nLastChunkCapacity); - } CONTRACTL_END; - - SIZE_T nChunkCapacity; - if (!m_pChunkListHead) - nChunkCapacity = InitialChunkLength; - else - nChunkCapacity = m_nLastChunkCapacity * ChunkLengthGrowthFactor; - - S_SIZE_T cbBaseSize = S_SIZE_T(roundUp(sizeof(StructArrayListEntryBase), alignment)); - S_SIZE_T cbChunk = cbBaseSize + - S_SIZE_T(cbElement) * S_SIZE_T(nChunkCapacity); - _ASSERTE(!cbChunk.IsOverflow()); - if(cbChunk.IsOverflow()) - { - ThrowWin32(ERROR_ARITHMETIC_OVERFLOW); - } - - StructArrayListEntryBase *pNewChunk = (StructArrayListEntryBase*)pfnAlloc(this, cbChunk.Value()); - - if (m_pChunkListTail) - { - _ASSERTE(m_pChunkListHead); - m_pChunkListTail->pNext = pNewChunk; - } - else - { - _ASSERTE(!m_pChunkListHead); - m_pChunkListHead = pNewChunk; - } - - pNewChunk->pNext = NULL; - m_pChunkListTail = pNewChunk; - - m_nItemsInLastChunk = 0; - m_nLastChunkCapacity = nChunkCapacity; -} - - -void StructArrayListBase::ArrayIteratorBase::SetCurrentChunk (StructArrayListEntryBase *pChunk, SIZE_T nChunkCapacity) -{ - LIMITED_METHOD_CONTRACT; - - m_pCurrentChunk = pChunk; - - if (pChunk) - { - if (pChunk == m_pArrayList->m_pChunkListTail) - m_nItemsInCurrentChunk = m_pArrayList->m_nItemsInLastChunk; - else - m_nItemsInCurrentChunk = nChunkCapacity; - - m_nCurrentChunkCapacity = nChunkCapacity; - } -} - |