CheckedBoolean CopiedSpace::tryReallocateOversize(void** ptr, size_t oldSize, size_t newSize) { ASSERT(isOversize(oldSize) || isOversize(newSize)); ASSERT(newSize > oldSize); void* oldPtr = *ptr; void* newPtr = 0; if (!tryAllocateOversize(newSize, &newPtr)) { *ptr = 0; return false; } memcpy(newPtr, oldPtr, oldSize); CopiedBlock* oldBlock = CopiedSpace::blockFor(oldPtr); if (oldBlock->isOversize()) { // FIXME: Eagerly deallocating the old space block probably buys more confusion than // value. // https://bugs.webkit.org/show_bug.cgi?id=144750 if (oldBlock->isOld()) { m_bytesRemovedFromOldSpaceDueToReallocation += oldBlock->size(); m_oldGen.oversizeBlocks.remove(oldBlock); } else m_newGen.oversizeBlocks.remove(oldBlock); m_blockSet.remove(oldBlock); CopiedBlock::destroy(*heap(), oldBlock); } *ptr = newPtr; return true; }
CheckedBoolean CopiedSpace::tryReallocateOversize(void** ptr, size_t oldSize, size_t newSize) { ASSERT(isOversize(oldSize) || isOversize(newSize)); ASSERT(newSize > oldSize); void* oldPtr = *ptr; void* newPtr = 0; if (!tryAllocateOversize(newSize, &newPtr)) { *ptr = 0; return false; } memcpy(newPtr, oldPtr, oldSize); CopiedBlock* oldBlock = CopiedSpace::blockFor(oldPtr); if (oldBlock->isOversize()) { if (oldBlock->isOld()) m_oldGen.oversizeBlocks.remove(oldBlock); else m_newGen.oversizeBlocks.remove(oldBlock); m_blockSet.remove(oldBlock); m_heap->blockAllocator().deallocateCustomSize(CopiedBlock::destroy(oldBlock)); } *ptr = newPtr; return true; }
CheckedBoolean CopiedSpace::tryReallocate(void** ptr, size_t oldSize, size_t newSize) { if (oldSize >= newSize) return true; void* oldPtr = *ptr; ASSERT(!m_heap->globalData()->isInitializingObject()); if (isOversize(oldSize) || isOversize(newSize)) return tryReallocateOversize(ptr, oldSize, newSize); if (m_allocator.wasLastAllocation(oldPtr, oldSize)) { size_t delta = newSize - oldSize; if (m_allocator.fitsInCurrentBlock(delta)) { (void)m_allocator.allocate(delta); return true; } } void* result = 0; if (!tryAllocate(newSize, &result)) { *ptr = 0; return false; } memcpy(result, oldPtr, oldSize); *ptr = result; return true; }
CheckedBoolean CopiedSpace::tryAllocateSlowCase(size_t bytes, void** outPtr) { if (isOversize(bytes)) return tryAllocateOversize(bytes, outPtr); ASSERT(m_heap->vm()->currentThreadIsHoldingAPILock()); m_heap->didAllocate(m_allocator.currentCapacity()); allocateBlock(); *outPtr = m_allocator.forceAllocate(bytes); return true; }
CheckedBoolean CopiedSpace::tryAllocateSlowCase(size_t bytes, void** outPtr) { if (isOversize(bytes)) return tryAllocateOversize(bytes, outPtr); m_heap->didAllocate(m_allocator.currentCapacity()); if (!addNewBlock()) { *outPtr = 0; return false; } *outPtr = m_allocator.allocate(bytes); ASSERT(*outPtr); return true; }
CheckedBoolean CopiedSpace::tryReallocateOversize(void** ptr, size_t oldSize, size_t newSize) { ASSERT(isOversize(oldSize) || isOversize(newSize)); ASSERT(newSize > oldSize); void* oldPtr = *ptr; void* newPtr = 0; if (!tryAllocateOversize(newSize, &newPtr)) { *ptr = 0; return false; } memcpy(newPtr, oldPtr, oldSize); if (isOversize(oldSize)) { CopiedBlock* oldBlock = oversizeBlockFor(oldPtr); m_oversizeBlocks.remove(oldBlock); oldBlock->m_allocation.deallocate(); } *ptr = newPtr; return true; }
CheckedBoolean CopiedSpace::tryAllocateOversize(size_t bytes, void** outPtr) { ASSERT(isOversize(bytes)); CopiedBlock* block = CopiedBlock::create(m_heap->blockAllocator().allocateCustomSize(sizeof(CopiedBlock) + bytes, CopiedBlock::blockSize)); m_oversizeBlocks.push(block); m_blockFilter.add(reinterpret_cast<Bits>(block)); m_blockSet.add(block); CopiedAllocator allocator; allocator.setCurrentBlock(block); *outPtr = allocator.forceAllocate(bytes); allocator.resetCurrentBlock(); m_heap->didAllocate(block->region()->blockSize()); return true; }
CheckedBoolean CopiedSpace::tryAllocateOversize(size_t bytes, void** outPtr) { ASSERT(isOversize(bytes)); CopiedBlock* block = CopiedBlock::create(*m_heap, WTF::roundUpToMultipleOf<sizeof(double)>(sizeof(CopiedBlock) + bytes)); m_newGen.oversizeBlocks.push(block); m_newGen.blockFilter.add(reinterpret_cast<Bits>(block)); m_blockSet.add(block); ASSERT(!block->isOld()); CopiedAllocator allocator; allocator.setCurrentBlock(block); *outPtr = allocator.forceAllocate(bytes); allocator.resetCurrentBlock(); m_heap->didAllocate(block->capacity()); return true; }
CheckedBoolean CopiedSpace::tryAllocateOversize(size_t bytes, void** outPtr) { ASSERT(isOversize(bytes)); size_t blockSize = WTF::roundUpToMultipleOf(WTF::pageSize(), sizeof(CopiedBlock) + bytes); PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, WTF::pageSize(), OSAllocator::JSGCHeapPages); if (!static_cast<bool>(allocation)) { *outPtr = 0; return false; } CopiedBlock* block = new (NotNull, allocation.base()) CopiedBlock(allocation); m_oversizeBlocks.push(block); m_oversizeFilter.add(reinterpret_cast<Bits>(block)); *outPtr = allocateFromBlock(block, bytes); m_heap->didAllocate(blockSize); return true; }
CheckedBoolean CopiedSpace::tryReallocate(void** ptr, size_t oldSize, size_t newSize) { if (oldSize >= newSize) return true; void* oldPtr = *ptr; ASSERT(!m_heap->vm()->isInitializingObject()); if (CopiedSpace::blockFor(oldPtr)->isOversize() || isOversize(newSize)) return tryReallocateOversize(ptr, oldSize, newSize); if (m_allocator.tryReallocate(oldPtr, oldSize, newSize)) return true; void* result = 0; if (!tryAllocate(newSize, &result)) { *ptr = 0; return false; } memcpy(result, oldPtr, oldSize); *ptr = result; return true; }