- Vector<FreeListEntry*> freeListEntries;
- SizeSortedFreeTree::Iterator iter;
- iter.start_iter_least(m_freeList);
-
- // Empty m_freeList into a Vector.
- for (FreeListEntry* entry; (entry = *iter); ++iter) {
- // Each entry in m_freeList might correspond to multiple
- // free chunks of memory (of the same size). Walk the chain
- // (this is likely of couse only be one entry long!) adding
- // each entry to the Vector (at reseting the next in chain
- // pointer to separate each node out).
- FreeListEntry* next;
- do {
- next = entry->nextEntry;
- entry->nextEntry = 0;
- freeListEntries.append(entry);
- } while ((entry = next));
- }
- // All entries are now in the Vector; purge the tree.
- m_freeList.purge();
-
- // Reverse-sort the freeListEntries and m_commonSizedAllocations Vectors.
- // We reverse-sort so that we can logically work forwards through memory,
- // whilst popping items off the end of the Vectors using last() and removeLast().
- qsort(freeListEntries.begin(), freeListEntries.size(), sizeof(FreeListEntry*), reverseSortFreeListEntriesByPointer);
- qsort(m_commonSizedAllocations.begin(), m_commonSizedAllocations.size(), sizeof(void*), reverseSortCommonSizedAllocations);
-
- // The entries from m_commonSizedAllocations that cannot be
- // coalesced into larger chunks will be temporarily stored here.
- Vector<void*> newCommonSizedAllocations;
-
- // Keep processing so long as entries remain in either of the vectors.
- while (freeListEntries.size() || m_commonSizedAllocations.size()) {
- // We're going to try to find a FreeListEntry node that we can coalesce onto.
- FreeListEntry* coalescionEntry = 0;
-
- // Is the lowest addressed chunk of free memory of common-size, or is it in the free list?
- if (m_commonSizedAllocations.size() && (!freeListEntries.size() || (m_commonSizedAllocations.last() < freeListEntries.last()->pointer))) {
- // Pop an item from the m_commonSizedAllocations vector - this is the lowest
- // addressed free chunk. Find out the begin and end addresses of the memory chunk.
- void* begin = m_commonSizedAllocations.last();
- void* end = (void*)((intptr_t)begin + m_commonSize);
- m_commonSizedAllocations.removeLast();
-
- // Try to find another free chunk abutting onto the end of the one we have already found.
- if (freeListEntries.size() && (freeListEntries.last()->pointer == end)) {
- // There is an existing FreeListEntry for the next chunk of memory!
- // we can reuse this. Pop it off the end of m_freeList.
- coalescionEntry = freeListEntries.last();
- freeListEntries.removeLast();
- // Update the existing node to include the common-sized chunk that we also found.
- coalescionEntry->pointer = (void*)((intptr_t)coalescionEntry->pointer - m_commonSize);
- coalescionEntry->size += m_commonSize;
- } else if (m_commonSizedAllocations.size() && (m_commonSizedAllocations.last() == end)) {
- // There is a second common-sized chunk that can be coalesced.
- // Allocate a new node.
- m_commonSizedAllocations.removeLast();
- coalescionEntry = new FreeListEntry(begin, 2 * m_commonSize);
- } else {
- // Nope - this poor little guy is all on his own. :-(
- // Add him into the newCommonSizedAllocations vector for now, we're
- // going to end up adding him back into the m_commonSizedAllocations
- // list when we're done.
- newCommonSizedAllocations.append(begin);
- continue;
- }
- } else {
- ASSERT(freeListEntries.size());
- ASSERT(!m_commonSizedAllocations.size() || (freeListEntries.last()->pointer < m_commonSizedAllocations.last()));
- // The lowest addressed item is from m_freeList; pop it from the Vector.
- coalescionEntry = freeListEntries.last();
- freeListEntries.removeLast();
- }