EM_Task/CoreUObject/Private/UObject/UObjectAllocator.cpp

106 lines
4.0 KiB
C++
Raw Normal View History

2026-02-13 16:18:33 +08:00
// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
UnObjAllocator.cpp: Unreal object allocation
=============================================================================*/
#include "UObject/UObjectAllocator.h"
#include "UObject/UObjectGlobals.h"
DEFINE_LOG_CATEGORY_STATIC(LogUObjectAllocator, Log, All);
/** Global UObjectBase allocator */
COREUOBJECT_API FUObjectAllocator GUObjectAllocator;
/**
* Allocates and initializes the permanent object pool
*
* @param InPermanentObjectPoolSize size of permanent object pool
*/
void FUObjectAllocator::AllocatePermanentObjectPool(int32 InPermanentObjectPoolSize)
{
PermanentObjectPoolSize = InPermanentObjectPoolSize;
PermanentObjectPool = (uint8*)FMemory::MallocPersistentAuxiliary(PermanentObjectPoolSize);
PermanentObjectPoolTail = PermanentObjectPool;
PermanentObjectPoolExceededTail = PermanentObjectPoolTail;
}
/**
* Prints a debugf message to allow tuning
*/
void FUObjectAllocator::BootMessage()
{
if (PermanentObjectPoolSize && PermanentObjectPoolExceededTail - PermanentObjectPool > PermanentObjectPoolSize)
{
UE_LOG(LogUObjectAllocator, Warning, TEXT("%i Exceeds size of permanent object pool %i, please tune SizeOfPermanentObjectPool."), PermanentObjectPoolExceededTail - PermanentObjectPool, PermanentObjectPoolSize);
}
else
{
UE_LOG(LogUObjectAllocator, Log, TEXT("%i out of %i bytes used by permanent object pool."), PermanentObjectPoolExceededTail - PermanentObjectPool, PermanentObjectPoolSize);
}
}
/**
* Allocates a UObjectBase from the free store or the permanent object pool
*
* @param Size size of uobject to allocate
* @param Alignment alignment of uobject to allocate
* @param bAllowPermanent if true, allow allocation in the permanent object pool, if it fits
* @return newly allocated UObjectBase (not really a UObjectBase yet, no constructor like thing has been called).
*/
UObjectBase* FUObjectAllocator::AllocateUObject(int32 Size, int32 Alignment, bool bAllowPermanent)
{
// Force alignment to 16 bytes
Alignment = 16;
int32 AlignedSize = Align(Size, Alignment);
UObjectBase* Result = NULL;
const bool bPlaceInPerm = bAllowPermanent && (Align(PermanentObjectPoolTail, Alignment) + Size) <= (PermanentObjectPool + PermanentObjectPoolSize);
if (bAllowPermanent && !bPlaceInPerm)
{
// advance anyway so we can determine how much space we should set aside in the ini
uint8* AlignedPtr = Align(PermanentObjectPoolExceededTail, Alignment);
PermanentObjectPoolExceededTail = AlignedPtr + Size;
}
// Use object memory pool for objects disregarded by GC (initially loaded ones). This allows identifying their
// GC status by simply looking at their address.
if (bPlaceInPerm)
{
// Align current tail pointer and use it for object.
uint8* AlignedPtr = Align(PermanentObjectPoolTail, Alignment);
// Update tail pointer.
PermanentObjectPoolTail = AlignedPtr + Size;
Result = (UObjectBase*)AlignedPtr;
if (PermanentObjectPoolExceededTail < PermanentObjectPoolTail)
{
PermanentObjectPoolExceededTail = PermanentObjectPoolTail;
}
}
else
{
// Allocate new memory of the appropriate size and alignment.
Result = (UObjectBase*)FMemory::DebugMalloc(AlignedSize);
}
return Result;
}
/**
* Returns a UObjectBase to the free store, unless it is in the permanent object pool
*
* @param Object object to free
*/
void FUObjectAllocator::FreeUObject(UObjectBase* Object) const
{
check(Object);
// Only free memory if it was allocated directly from allocator and not from permanent object pool.
if (ResidesInPermanentPool(Object) == false)
{
FMemory::DebugFree(Object);
}
// We only destroy objects residing in permanent object pool during the exit purge.
else
{
check(GExitPurge);
}
}