Clean up StructArrayList for GC info.
authorPat Gavlin <pagavlin@microsoft.com>
Fri, 8 Apr 2016 22:39:55 +0000 (15:39 -0700)
committerPat Gavlin <pagavlin@microsoft.com>
Tue, 12 Apr 2016 19:44:05 +0000 (12:44 -0700)
- Move the code into the GC info encoder, as that is its
  only consumer.
- Remove contracts
- Delete dead code
- Reformat and refactor to current coding standards

Commit migrated from https://github.com/dotnet/coreclr/commit/d241f9d5bcdaf9e99e4c4e54508d2cec2ed35d04

src/coreclr/src/gcinfo/CMakeLists.txt
src/coreclr/src/gcinfo/arraylist.cpp [new file with mode: 0644]
src/coreclr/src/gcinfo/dbggcinfoencoder.cpp
src/coreclr/src/gcinfo/gcinfo.settings.targets
src/coreclr/src/gcinfo/gcinfoencoder.cpp
src/coreclr/src/inc/arraylist.h
src/coreclr/src/inc/dbggcinfoencoder.h
src/coreclr/src/inc/gcinfoarraylist.h [new file with mode: 0644]
src/coreclr/src/inc/gcinfoencoder.h
src/coreclr/src/utilcode/arraylist.cpp

index d8b91d1..53a1ad2 100644 (file)
@@ -1,6 +1,7 @@
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 
 set( GCINFO_SOURCES
+  arraylist.cpp
   gcinfoencoder.cpp
   dbggcinfoencoder.cpp
 )
diff --git a/src/coreclr/src/gcinfo/arraylist.cpp b/src/coreclr/src/gcinfo/arraylist.cpp
new file mode 100644 (file)
index 0000000..566304c
--- /dev/null
@@ -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;
+}
index eb18f69..c41db2f 100644 (file)
@@ -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;
 }
 
 
index b20bca4..f600e2a 100644 (file)
@@ -12,6 +12,7 @@
 
   <!-- Leaf Project Items -->
   <ItemGroup>
+    <CppCompile Include="..\ArrayList.cpp" />
     <CppCompile Include="..\GCInfoEncoder.cpp" />
     <CppCompile Include="..\DbgGCInfoEncoder.cpp" />
   </ItemGroup>
index a013c42..95673a1 100644 (file)
@@ -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));
 }
index b709514..f45085b 100644 (file)
@@ -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(&currentChunkCount);
-        }
-        
-        ELEMENT_TYPE *
-        GetNext()
-        {
-            ELEMENT_TYPE * returnElem = (currentChunk + currentChunkIndex);
-            
-            currentChunkIndex++;
-            if (currentChunkIndex == currentChunkCount)
-            {
-                currentChunkIndex = 0;
-                currentChunk = iter.GetNext(&currentChunkCount);
-            }
-            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
index 95450fb..5442213 100644 (file)
@@ -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/coreclr/src/inc/gcinfoarraylist.h b/src/coreclr/src/inc/gcinfoarraylist.h
new file mode 100644 (file)
index 0000000..c19f00d
--- /dev/null
@@ -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
index a66d87a..8a5e760 100644 (file)
@@ -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;
index 1b962c0..30793c4 100644 (file)
@@ -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;
-    }
-}
-