void* MarkedAllocator::tryAllocateWithoutCollecting() { SuperSamplerScope superSamplerScope(false); ASSERT(!m_currentBlock); ASSERT(!m_freeList); for (;;) { m_allocationCursor = (m_canAllocateButNotEmpty | m_empty).findBit(m_allocationCursor, true); if (m_allocationCursor >= m_blocks.size()) break; setIsCanAllocateButNotEmpty(m_allocationCursor, false); if (void* result = tryAllocateIn(m_blocks[m_allocationCursor])) return result; } if (Options::stealEmptyBlocksFromOtherAllocators() && shouldStealEmptyBlocksFromOtherAllocators()) { if (MarkedBlock::Handle* block = m_markedSpace->findEmptyBlockToSteal()) { block->sweep(); // It's good that this clears canAllocateButNotEmpty as well as all other bits, // because there is a remote chance that a block may have both canAllocateButNotEmpty // and empty set at the same time. block->removeFromAllocator(); addBlock(block); return allocateIn(block); } } return nullptr; }
MarkedBlock::Handle* BlockDirectory::findBlockForAllocation(LocalAllocator& allocator) { for (;;) { allocator.m_allocationCursor = (m_canAllocateButNotEmpty | m_empty).findBit(allocator.m_allocationCursor, true); if (allocator.m_allocationCursor >= m_blocks.size()) return nullptr; size_t blockIndex = allocator.m_allocationCursor++; MarkedBlock::Handle* result = m_blocks[blockIndex]; setIsCanAllocateButNotEmpty(NoLockingNecessary, blockIndex, false); return result; } }