17#if PLATFORM_HAS_ASAN_INCLUDE
18# include <sanitizer/asan_interface.h>
19# if defined(__SANITIZE_ADDRESS__)
20# define IS_ASAN_ENABLED 1
21# elif defined(__has_feature)
22# if __has_feature(address_sanitizer)
23# define IS_ASAN_ENABLED 1
25# define IS_ASAN_ENABLED 0
28# define IS_ASAN_ENABLED 0
31# define ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
32# define ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
33# define IS_ASAN_ENABLED 0
60UE_DEPRECATED(5.6,
"FOsAllocator is deprecated, use FAlignedAllocator instead")
68 void*
Block =
nullptr;
74 Allocator::Free(
Block, BlockSize);
79 inline static void* SwapBlock(
void*
NewBlock)
81 static thread_local FTLSCleanup
Tls;
82 void* Ret =
Tls.Block;
88 static constexpr bool SupportsAlignment = Allocator::SupportsAlignment;
89 static constexpr bool UsesFMalloc = Allocator::UsesFMalloc;
90 static constexpr uint32 MaxAlignment = Allocator::MaxAlignment;
94 if (
Size == BlockSize)
96 void* Pointer = SwapBlock(
nullptr);
97 if (Pointer !=
nullptr)
102 return Allocator::Malloc(
Size, Alignment);
107 if (
Size == BlockSize)
109 Pointer = SwapBlock(Pointer);
110 if (Pointer ==
nullptr)
115 return Allocator::Free(Pointer,
Size);
119template <u
int32 BlockSize,
typename Allocator = FAlignedAllocator>
130 if (
Size == BlockSize)
136 return Allocator::Malloc(
Size, Alignment);
142 if (
Size == BlockSize)
148 Allocator::Free(Pointer,
Size);
159 static constexpr const char*
TagName =
"DefaultLinear";
188template <
typename BlockAllocationTag, ELinearAllocatorThreadPolicy ThreadPolicy>
191 static constexpr bool SupportsFastPath = ((BlockAllocationTag::BlockSize <= (64 * 1024)) && (FPlatformProperties::GetMaxSupportedVirtualMemoryAlignment() >= 64 * 1024))
194 && BlockAllocationTag::Allocator::SupportsAlignment;
200 class FAllocationHeader
215 return reinterpret_cast<FBlockHeader*
>(
uintptr_t(
this) - BlockHeaderOffset);
220 return SIZE_T(AllocationSize);
228 static inline FAllocationHeader* GetAllocationHeader(
void* Pointer)
230 if (SupportsFastPath)
236 return reinterpret_cast<FAllocationHeader*
>(Pointer) - 1;
244 : NextAllocationPtr(
uintptr_t(
this) +
sizeof(FBlockHeader) +
sizeof(FAllocationHeader))
251 unsigned int FetchSub(
unsigned int N, std::memory_order)
253 unsigned int OriginalValue =
Value;
255 return OriginalValue;
258 void Store(
unsigned int N, std::memory_order)
269 unsigned int FetchSub(
unsigned int N, std::memory_order Order)
271 return Value.fetch_sub(N, Order);
274 void Store(
unsigned int N, std::memory_order Order)
276 return Value.store(N, Order);
282 using NumAllocationsType = std::conditional_t<ThreadPolicy == ELinearAllocatorThreadPolicy::ThreadSafe, FAtomicUInt, FPlainUInt>;
284 NumAllocationsType NumAllocations { .Value =
UINT_MAX };
287 unsigned int Num = 0;
292 FBlockHeader* Header =
nullptr;
298 Header->NextAllocationPtr =
uintptr_t(Header) + BlockAllocationTag::BlockSize;
306 Header->~FBlockHeader();
309 BlockAllocationTag::Allocator::Free(Header, BlockAllocationTag::BlockSize);
317 if constexpr (!BlockAllocationTag::InlineBlockAllocation)
319 static_assert(BlockAllocationTag::BlockSize >=
sizeof(FBlockHeader) +
sizeof(FAllocationHeader));
320 uint32 BlockAlignment = SupportsFastPath ? BlockAllocationTag::BlockSize :
alignof(FBlockHeader);
321 Header =
new (BlockAllocationTag::Allocator::Malloc(BlockAllocationTag::BlockSize, BlockAlignment)) FBlockHeader;
324 if constexpr (!SupportsFastPath)
329 static thread_local FTLSCleanup
Cleanup;
335 template<u
int32 Alignment>
344 return Malloc(
sizeof(T),
alignof(T));
350 if constexpr (!SupportsFastPath)
352 Alignment = (Alignment <
alignof(FAllocationHeader)) ?
alignof(FAllocationHeader) : Alignment;
355 Alignment =
Align(Alignment, 8);
359 static thread_local FBlockHeader*
Header;
363 if constexpr (BlockAllocationTag::InlineBlockAllocation)
365 static_assert(BlockAllocationTag::BlockSize >=
sizeof(FBlockHeader) +
sizeof(FAllocationHeader));
366 uint32 BlockAlignment = SupportsFastPath ? BlockAllocationTag::BlockSize :
alignof(FBlockHeader);
367 Header =
new (BlockAllocationTag::Allocator::Malloc(BlockAllocationTag::BlockSize, BlockAlignment)) FBlockHeader;
370 if constexpr (!SupportsFastPath)
375 static thread_local FTLSCleanup
Cleanup;
385 if constexpr (SupportsFastPath)
390 Header->NextAllocationPtr = AlignedOffset +
Size;
395 return reinterpret_cast<void*
>(AlignedOffset);
399 constexpr SIZE_T HeaderSize =
sizeof(FBlockHeader);
400 if constexpr (BlockAllocationTag::AllowOversizedBlocks)
403 if (HeaderSize +
Size + Alignment > BlockAllocationTag::BlockSize)
405 FBlockHeader*
LargeHeader =
new (BlockAllocationTag::Allocator::Malloc(HeaderSize +
Size + Alignment, BlockAllocationTag::BlockSize)) FBlockHeader;
411 LargeHeader->NumAllocations.Store(1, std::memory_order_release);
420 check(HeaderSize +
Size + Alignment <= BlockAllocationTag::BlockSize);
427 Header->NextAllocationPtr = AlignedOffset +
Size +
sizeof(FAllocationHeader);
430 FAllocationHeader*
AllocationHeader =
reinterpret_cast<FAllocationHeader*
>(AlignedOffset) - 1;
437 return reinterpret_cast<void*
>(AlignedOffset);
441 constexpr SIZE_T HeaderSize =
sizeof(FBlockHeader) +
sizeof(FAllocationHeader);
442 if constexpr (BlockAllocationTag::AllowOversizedBlocks)
445 if (HeaderSize +
Size + Alignment > BlockAllocationTag::BlockSize)
447 FBlockHeader*
LargeHeader =
new (BlockAllocationTag::Allocator::Malloc(HeaderSize +
Size + Alignment,
alignof(FBlockHeader))) FBlockHeader;
453 LargeHeader->NumAllocations.Store(1, std::memory_order_release);
464 check(HeaderSize +
Size + Alignment <= BlockAllocationTag::BlockSize);
482 goto AllocateNewBlock;
485 static inline void Free(
void* Pointer)
487 if(Pointer !=
nullptr)
489 if constexpr (SupportsFastPath)
493 FBlockHeader*
Header =
reinterpret_cast<FBlockHeader*
>(
AlignDown(Pointer, BlockAllocationTag::BlockSize));
496 if (
Header->NumAllocations.FetchSub(1, std::memory_order_acq_rel) == 1)
514 if (
Header->NumAllocations.FetchSub(1, std::memory_order_acq_rel) == 1)
530 if constexpr (SupportsFastPath)
569template<
typename ObjectType,
typename BlockAllocationTag = FDefaultBlockAllocationTag>
573 inline static void*
operator new(
size_t Size)
576 static_assert(
alignof(ObjectType) <= BlockAllocationTag::Allocator::MaxAlignment);
586 inline static void*
operator new[](
size_t Size)
588 static_assert(
alignof(ObjectType) <= BlockAllocationTag::Allocator::MaxAlignment);
592 inline static void*
operator new(
size_t Size, std::align_val_t
Align)
594 static_assert(
alignof(ObjectType) <= BlockAllocationTag::Allocator::MaxAlignment);
599 inline static void*
operator new[](
size_t Size, std::align_val_t
Align)
601 static_assert(
alignof(ObjectType) <= BlockAllocationTag::Allocator::MaxAlignment);
622template <
typename BlockAllocationTag, ELinearAllocatorThreadPolicy ThreadPolicy>
631 template<
typename ElementType>
658 Other.Data =
nullptr;
666 static_assert(
sizeof(
int32) <=
sizeof(
SIZE_T),
"SIZE_T is expected to be larger than int32");
674 static_assert(
alignof(ElementType) <= BlockAllocationTag::Allocator::MaxAlignment);
692 return CurrentMax * NumBytesPerElement;
709 ElementType* Data =
nullptr;
715template <
typename BlockAllocationTag>
718template <
typename BlockAllocationTag>
721template <
typename BlockAllocationTag>
727template <
typename BlockAllocationTag>
730template <
typename BlockAllocationTag>
733template <
typename BlockAllocationTag>
744template<
typename BlockAllocationTag>
750 virtual ~FAllocation() =
default;
751 FAllocation*
Next =
nullptr;
754 template <
typename T>
755 struct TObject final : FAllocation
758 virtual ~TObject()
override
765 Alloc->DestructorType::~T();
769 template <
typename T>
770 struct TObjectArray final : FAllocation
777 virtual ~TObjectArray()
override
786 Alloc[i].DestructorType::~T();
792 std::atomic<FAllocation*> Next {
nullptr };
803 FAllocation* Allocation = Next.exchange(
nullptr, std::memory_order_acquire);
804 while (Allocation !=
nullptr)
806 FAllocation* NextAllocation = Allocation->Next;
807 Allocation->~FAllocation();
809 Allocation = NextAllocation;
818 void* Alloc =
Align(Allocation + 1, Alignment);
821 Allocation->Next = Next.load(std::memory_order_relaxed);
822 while (!Next.compare_exchange_strong(Allocation->Next, Allocation, std::memory_order_release, std::memory_order_relaxed))
835 template <
typename T>
838 return reinterpret_cast<T*
>(
Malloc(
sizeof(T),
alignof(T)));
841 template <
typename T>
844 void* Ptr =
Malloc(
sizeof(T),
alignof(T));
846 return reinterpret_cast<T*
>(Ptr);
849 template <
typename T>
852 return reinterpret_cast<T*
>(
Malloc(
sizeof(T) *
Num,
alignof(T)));
855 template <
typename T>
858 void* Ptr =
Malloc(
sizeof(T) *
Num,
alignof(T));
860 return reinterpret_cast<T*
>(Ptr);
863 template<
typename T,
typename...
TArgs>
871 template<
typename T,
typename...
TArgs>
877 new ((
void*)(&Alloc[i])) T(Args...);
884 inline T* CreateNoInit()
893 Object->Next = Next.load(std::memory_order_relaxed);
894 while (!Next.compare_exchange_weak(
Object->Next,
Object, std::memory_order_release, std::memory_order_relaxed))
910 Array->Next = Next.load(std::memory_order_relaxed);
911 while (!Next.compare_exchange_weak(
Array->Next,
Array, std::memory_order_release, std::memory_order_relaxed))
constexpr T Align(T Val, uint64 Alignment)
Definition AlignmentTemplates.h:18
constexpr T AlignDown(T Val, uint64 Alignment)
Definition AlignmentTemplates.h:34
constexpr bool IsAligned(T Val, uint64 Alignment)
Definition AlignmentTemplates.h:50
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
ELinearAllocatorThreadPolicy
Definition ConcurrentLinearAllocator.h:183
#define ASAN_POISON_MEMORY_REGION(addr, size)
Definition ConcurrentLinearAllocator.h:31
#define IS_ASAN_ENABLED
Definition ConcurrentLinearAllocator.h:33
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)
Definition ConcurrentLinearAllocator.h:32
UE_FORCEINLINE_HINT SizeType DefaultCalculateSlackReserve(SizeType NewMax, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment=DEFAULT_ALIGNMENT)
Definition ContainerAllocationPolicies.h:223
UE_FORCEINLINE_HINT SizeType DefaultCalculateSlackShrink(SizeType NewMax, SizeType CurrentMax, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment=DEFAULT_ALIGNMENT)
Definition ContainerAllocationPolicies.h:139
UE_FORCEINLINE_HINT SizeType DefaultCalculateSlackGrow(SizeType NewMax, SizeType CurrentMax, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment=DEFAULT_ALIGNMENT)
Definition ContainerAllocationPolicies.h:169
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define LLM_IF_ENABLED(...)
Definition LowLevelMemTracker.h:1093
#define LLM(...)
Definition LowLevelMemTracker.h:1092
#define UE_MBC_MAX_SMALL_POOL_ALIGNMENT
Definition MallocBinnedCommon.h:46
T * New(FMemStackBase &Mem, int32 Count=1, int32 Align=DEFAULT_ALIGNMENT)
Definition MemStack.h:259
void MemoryTrace_MarkAllocAsHeap(uint64 Address, HeapId Heap)
Definition MemoryTrace.h:197
void MemoryTrace_Free(uint64 Address, HeapId RootHeap=EMemoryTraceRootHeap::SystemMemory, uint32 ExternalCallstackId=0)
Definition MemoryTrace.h:200
@ SystemMemory
Definition MemoryTrace.h:35
void MemoryTrace_UnmarkAllocAsHeap(uint64 Address, HeapId Heap)
Definition MemoryTrace.h:198
void MemoryTrace_Alloc(uint64 Address, uint64 Size, uint32 Alignment, HeapId RootHeap=EMemoryTraceRootHeap::SystemMemory, uint32 ExternalCallstackId=0)
Definition MemoryTrace.h:199
#define FMEMORY_INLINE_GMalloc
Definition Memory.h:17
#define MAX_int32
Definition NumericLimits.h:25
uint32 Offset
Definition VulkanMemory.cpp:4033
uint32 Size
Definition VulkanMemory.cpp:4034
memcpy(InputBufferBase, BinkBlocksData, BinkBlocksSize)
@ PageSize
Definition MemStack.h:40
CORE_API void Free(void *Mem)
Definition MemStack.cpp:248
static CORE_API FPageAllocator & Get()
Definition MemStack.cpp:30
CORE_API void * Alloc(int32 Alignment=MIN_ALIGNMENT)
Definition MemStack.cpp:236
Definition ConcurrentLinearAllocator.h:65
static void Free(void *Pointer, SIZE_T Size)
Definition ConcurrentLinearAllocator.h:105
static void * Malloc(SIZE_T Size, uint32 Alignment)
Definition ConcurrentLinearAllocator.h:92
Definition ConcurrentLinearAllocator.h:121
static constexpr bool SupportsAlignment
Definition ConcurrentLinearAllocator.h:124
static constexpr uint32 MaxAlignment
Definition ConcurrentLinearAllocator.h:126
static void * Malloc(SIZE_T Size, uint32 Alignment)
Definition ConcurrentLinearAllocator.h:128
static constexpr bool UsesFMalloc
Definition ConcurrentLinearAllocator.h:125
static void Free(void *Pointer, SIZE_T Size)
Definition ConcurrentLinearAllocator.h:140
Definition ConcurrentLinearAllocator.h:746
void * MallocAndMemset(SIZE_T Size, uint32 Alignment, uint8 MemsetChar)
Definition ConcurrentLinearAllocator.h:828
T * MallocAndMemset(uint8 MemsetChar)
Definition ConcurrentLinearAllocator.h:842
T * Malloc()
Definition ConcurrentLinearAllocator.h:836
T * MallocArray(SIZE_T Num)
Definition ConcurrentLinearAllocator.h:850
void BulkDelete()
Definition ConcurrentLinearAllocator.h:801
T * CreateArray(SIZE_T Num, const TArgs &... Args)
Definition ConcurrentLinearAllocator.h:872
T * Create(TArgs &&... Args)
Definition ConcurrentLinearAllocator.h:864
TConcurrentLinearBulkObjectAllocator()=default
T * MallocAndMemsetArray(SIZE_T Num, uint8 MemsetChar)
Definition ConcurrentLinearAllocator.h:856
void * Malloc(SIZE_T Size, uint32 Alignment)
Definition ConcurrentLinearAllocator.h:813
~TConcurrentLinearBulkObjectAllocator()
Definition ConcurrentLinearAllocator.h:796
Definition ConcurrentLinearAllocator.h:571
Definition ConcurrentLinearAllocator.h:190
static SIZE_T GetAllocationSize(void *Pointer)
Definition ConcurrentLinearAllocator.h:526
static void * Realloc(void *Old, SIZE_T Size, uint32 Alignment)
Definition ConcurrentLinearAllocator.h:546
static UE_FORCEINLINE_HINT void * Malloc()
Definition ConcurrentLinearAllocator.h:342
static void * Malloc(SIZE_T Size, uint32 Alignment)
Definition ConcurrentLinearAllocator.h:347
static UE_FORCEINLINE_HINT void * Malloc(SIZE_T Size)
Definition ConcurrentLinearAllocator.h:336
static void Free(void *Pointer)
Definition ConcurrentLinearAllocator.h:485
Definition ConcurrentLinearAllocator.h:633
SizeType GetInitialCapacity() const
Definition ConcurrentLinearAllocator.h:700
bool HasAllocation() const
Definition ConcurrentLinearAllocator.h:695
SizeType CalculateSlackGrow(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ConcurrentLinearAllocator.h:685
void ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement)
Definition ConcurrentLinearAllocator.h:664
SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ConcurrentLinearAllocator.h:690
~ForElementType()
Definition ConcurrentLinearAllocator.h:636
void MoveToEmpty(ForElementType &Other)
Definition ConcurrentLinearAllocator.h:648
ElementType * GetAllocation() const
Definition ConcurrentLinearAllocator.h:660
SizeType CalculateSlackReserve(SizeType NewMax, SIZE_T NumBytesPerElement) const
Definition ConcurrentLinearAllocator.h:677
SizeType CalculateSlackShrink(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ConcurrentLinearAllocator.h:681
Definition ConcurrentLinearAllocator.h:624
@ NeedsElementType
Definition ConcurrentLinearAllocator.h:628
@ RequireRangeCheck
Definition ConcurrentLinearAllocator.h:629
int32 SizeType
Definition ConcurrentLinearAllocator.h:626
Definition ContainerAllocationPolicies.h:1662
Definition ContainerAllocationPolicies.h:894
Definition ContainerAllocationPolicies.h:1383
implementation
Definition PlayInEditorLoadingScope.h:8
CORE_API void OnInvalidConcurrentLinearArrayAllocatorNum(int32 NewNum, SIZE_T NumBytesPerElement)
Definition ConcurrentLinearAllocator.cpp:6
Definition ConcurrentLinearAllocator.h:38
static void * Malloc(SIZE_T Size, uint32 Alignment)
Definition ConcurrentLinearAllocator.h:43
static constexpr bool SupportsAlignment
Definition ConcurrentLinearAllocator.h:39
static constexpr bool UsesFMalloc
Definition ConcurrentLinearAllocator.h:40
static constexpr uint32 MaxAlignment
Definition ConcurrentLinearAllocator.h:41
static UE_FORCEINLINE_HINT void Free(void *Pointer, SIZE_T Size)
Definition ConcurrentLinearAllocator.h:54
Definition ConcurrentLinearAllocator.h:154
static constexpr const char * TagName
Definition ConcurrentLinearAllocator.h:159
static constexpr bool AllowOversizedBlocks
Definition ConcurrentLinearAllocator.h:156
static constexpr bool InlineBlockAllocation
Definition ConcurrentLinearAllocator.h:158
static constexpr bool RequiresAccurateSize
Definition ConcurrentLinearAllocator.h:157
static constexpr uint32 BlockSize
Definition ConcurrentLinearAllocator.h:155
static constexpr UE_FORCEINLINE_HINT bool IsPowerOfTwo(T Value)
Definition UnrealMathUtility.h:519
static FORCENOINLINE CORE_API void Free(void *Original)
Definition UnrealMemory.cpp:685
static UE_FORCEINLINE_HINT void * Memset(void *Dest, uint8 Char, SIZE_T Count)
Definition UnrealMemory.h:119
Definition ContainerAllocationPolicies.h:247
@ IsZeroConstruct
Definition ContainerAllocationPolicies.h:248
Definition ContainerAllocationPolicies.h:256
Definition UnrealTypeTraits.h:40