void Heap::allocateSmallBumpRanges(std::lock_guard<StaticMutex>& lock, size_t sizeClass, BumpAllocator& allocator, BumpRangeCache& rangeCache) { BASSERT(!rangeCache.size()); SmallPage* page = allocateSmallPage(lock, sizeClass); SmallLine* lines = page->begin(); // Due to overlap from the previous line, the last line in the page may not be able to fit any objects. size_t end = SmallPage::lineCount; if (!m_smallLineMetadata[sizeClass][SmallPage::lineCount - 1].objectCount) --end; // Find a free line. for (size_t lineNumber = 0; lineNumber < end; ++lineNumber) { if (lines[lineNumber].refCount(lock)) continue; // In a fragmented page, some free ranges might not fit in the cache. if (rangeCache.size() == rangeCache.capacity()) { m_smallPagesWithFreeLines[sizeClass].push(page); return; } LineMetadata& lineMetadata = m_smallLineMetadata[sizeClass][lineNumber]; char* begin = lines[lineNumber].begin() + lineMetadata.startOffset; unsigned short objectCount = lineMetadata.objectCount; lines[lineNumber].ref(lock, lineMetadata.objectCount); page->ref(lock); // Merge with subsequent free lines. while (++lineNumber < end) { if (lines[lineNumber].refCount(lock)) break; LineMetadata& lineMetadata = m_smallLineMetadata[sizeClass][lineNumber]; objectCount += lineMetadata.objectCount; lines[lineNumber].ref(lock, lineMetadata.objectCount); page->ref(lock); } if (!allocator.canAllocate()) allocator.refill({ begin, objectCount }); else rangeCache.push({ begin, objectCount }); } }
SmallLine* Heap::allocateSmallLineSlowCase(std::lock_guard<StaticMutex>& lock, size_t smallSizeClass) { m_isAllocatingPages = true; SmallPage* page = [this]() { if (m_smallPages.size()) return m_smallPages.pop(); SmallPage* page = m_vmHeap.allocateSmallPage(); vmAllocatePhysicalPages(page->begin()->begin(), vmPageSize); return page; }(); SmallLine* line = page->begin(); Vector<SmallLine*>& smallLines = m_smallLines[smallSizeClass]; for (auto it = line + 1; it != page->end(); ++it) smallLines.push(it); BASSERT(!line->refCount(lock)); page->setSmallSizeClass(smallSizeClass); page->ref(lock); return line; }