UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
GarbageCollectionSchema.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Containers/Array.h"
6#include "Containers/Map.h"
7#include "Misc/Optional.h"
9#include "UObject/NameTypes.h"
10#include "UObject/ObjectPtr.h"
12
13#if (WITH_VERSE_VM && DO_GUARD_SLOW) || defined(__INTELLISENSE__)
15#endif
16
17#ifndef UE_GC_DEBUGNAMES
18#define UE_GC_DEBUGNAMES (!UE_BUILD_SHIPPING)
19#endif
20
21namespace UE::GC {
22
24enum class EMemberType : uint8
25{
26 Stop, // Null terminator
27 Jump, // Move base pointer forward to reach members at large offsets
28 Reference, // Member - Scalar reference, e.g. MyObject* and TObjectPtr<MyObject>
29 ReferenceArray, // Member - Array of references, e.g. TArray<MyObject*> and TArray<TObjectPtr<MyObject>>
30 StructArray, // Array of structs
31 StridedArray, // Array of structs with single reference per struct (~half of struct instances)
32 StructSet, // TMap/TSet of structs
33 FieldPath, // Field path strong reference to owner
34 FieldPathArray, // Array of field paths
35 FreezableReferenceArray, // Freezable array of references
36 FreezableStructArray, // Freezable array of structs
37 Optional, // TOptional
38 DynamicallyTypedValue, // FDynamicallyTypedValue
39 ARO, // Call Add[Struct]ReferencedObjects() on current object / struct
40 SlowARO, // Call or queue AddReferencedObjects() on current object
41 MemberARO, // Call AddStructReferencedObjects() on a struct member in current object / struct
42#if WITH_VERSE_VM || defined(__INTELLISENSE__)
43 VerseValue, // Member - Verse value
44 VerseValueArray, // Member - Verse value array
45#endif
46 Count
47};
48
50
52enum class EOrigin : uint8
53{
54 Other, // Schema reflects non-blueprint type, such as native C++ classes and structs.
55 Blueprint // Schema reflects blueprint type. References to garbage-marked objects are cleared regardless of WithPendingKill to preserve old BP semantics.
56};
57
59
84
86{
87 FPropertyStack& Stack;
88public:
91 : Stack(InStack)
92 {
94 Stack.Props.Push(Property);
95 }
96
98 {
99 Stack.Props.Pop();
100 }
101};
102
104
106{
107 uint32 StructStride; // sizeof(T), required to iterate over struct array
108 std::atomic<int32> RefCount;
109};
110
111union FMemberWord;
112
115{
116 static constexpr uint64 OriginBit = 1;
117 uint64 Handle;
118
119public:
122 FSchemaView(FSchemaView View, EOrigin Origin) : FSchemaView(View.GetWords(), Origin) {}
123 explicit FSchemaView(const FMemberWord* Data, EOrigin Origin = EOrigin::Other)
124 : Handle(reinterpret_cast<uint64>(Data) | static_cast<uint64>(Origin))
125 {
126 static_assert(sizeof(Handle) >= sizeof(Data)); //-V568
127 }
128
129
130 const FMemberWord* GetWords() const { return reinterpret_cast<FMemberWord*>(Handle & ~OriginBit); }
131 EOrigin GetOrigin() const { return static_cast<EOrigin>(Handle & OriginBit); }
132 bool IsEmpty() const { return GetWords() == nullptr;}
133 void SetOrigin(EOrigin Origin) { Handle = (Handle & ~OriginBit) | static_cast<uint64>(Origin); }
134
136 uint32 GetStructStride() const { return reinterpret_cast<const FSchemaHeader*>(GetWords())[-1].StructStride; }
139};
140
142
143/* Debug id for references that lack a schema member declaration */
145{
146 Collector = 1,
147 Class,
148 Outer,
153};
154
157{
158public:
160 UE_FORCEINLINE_HINT explicit FMemberId(uint32 Idx) : Index(Idx), MemberlessId(0) {}
161
162 bool IsMemberless() const { return MemberlessId != 0; }
163 uint32 GetIndex() const { check(!IsMemberless()); return Index; }
164 int32 AsPrintableIndex() const { return IsMemberless() ? -int32(MemberlessId) : Index; }
165 EMemberlessId AsMemberless() const { check(IsMemberless()); return (EMemberlessId)MemberlessId;}
166
167 friend bool operator==(FMemberId A, FMemberId B) { return reinterpret_cast<uint32&>(A) == reinterpret_cast<uint32&>(B); }
168 friend bool operator!=(FMemberId A, FMemberId B) { return reinterpret_cast<uint32&>(A) != reinterpret_cast<uint32&>(B); }
169
170private:
171 static constexpr uint32 MemberlessIdBits = 3;
172 static constexpr uint32 IndexBits = 32 - MemberlessIdBits;
173
174 uint32 Index : IndexBits;
175 uint32 MemberlessId : MemberlessIdBits;
176
177 void StaticAssert();
178};
179
185
187
188#if !UE_BUILD_SHIPPING
190#endif
191
193
195{
196 static constexpr uint32 TypeBits = 5;
197 static constexpr uint32 OffsetBits = 16 - TypeBits;
199
202};
203
206
212
221
223{
224 FMemberWord Out;
225 Out.InnerSchema = In;
226 return Out;
227}
228
230{
231 FMemberWord Out;
232 Out.StructARO = In;
233 return Out;
234}
235
237
245
246inline FName ToName(const char* Name) { return FName(Name); }
247inline FName ToName(FPropertyStack& Stack) { return FName(Stack.GetPropertyPath()); }
248
249// Inlined so compiler can drop Name literals when compiling w/o UE_GC_DEBUGNAMES
250template<typename NameType>
252{
253 FName DebugName = UE_GC_DEBUGNAMES ? ToName(Forward<NameType>(Name)) : ToName(Type);
254 return { DebugName, Offset, Type };
255}
256
257template<typename NameType, typename ExtraWordType>
259{
260 FName DebugName = UE_GC_DEBUGNAMES ? ToName(Forward<NameType>(Name)) : ToName(Type);
261 return { DebugName, Offset, Type, ToWord(Extra) };
262}
263
265{
266public:
267 COREUOBJECT_API explicit FSchemaBuilder(uint32 InStride, std::initializer_list<FMemberDeclaration> InMembers = {});
269
271
272 // Append all but the last Stop/ARO member
274
275 // Emit Stop or ARO and build a view that builder holds reference to. Returns same view if called multiple times.
277
278 int32 NumMembers() const { return Members.Num(); }
279
280private:
282 const uint32 StructStride;
283 TOptional<FSchemaOwner> BuiltSchema;
284};
285
286
288
289template<class T>
291{
292 template<typename... Ts>
294};
295
296// Type-safe wrapper for declaring native schemas
297template<class T>
304
306namespace Private
307{
308
309template<class T, class R>
311{
312 static_assert(std::is_convertible_v<R, UObject*>);
314}
315
316template<class T, class R>
318{
319 static_assert(std::is_convertible_v<R, UObject*>);
321}
322
323template<class T, class O>
328
329template<class T, class O>
334
335template<class T, class S>
337{
338 return TMemberDeclaration<T>(Name, Offset, EMemberType::StructArray, InnerSchema.Build());
339}
340
341#if WITH_VERSE_VM || defined(__INTELLISENSE__)
342// Note: VValue, VRestValue and TWriteBarrier<U> share the same EMemberType because they are bit-compatible
343// When a VValue points to a cell, it is bit-identical to the raw pointer so we can bitcast from VCell* to VValue
344// Additionally, a VRestValue is bit-identical to a TWriteBarrier<VValue>/TWriteBarrier<VCell>
345#if DO_GUARD_SLOW
346static_assert(sizeof(::Verse::VValue) == sizeof(::Verse::VCell*), "");
347static_assert(sizeof(::Verse::VValue) == sizeof(::Verse::VRestValue), "");
348static_assert(sizeof(::Verse::VValue) == sizeof(::Verse::TWriteBarrier<::Verse::VValue>), "");
349static_assert(sizeof(::Verse::VValue) == sizeof(::Verse::TWriteBarrier<::Verse::VCell>), "");
350#endif
351
352template<class T>
353TMemberDeclaration<T> MakeMember(const char* Name, uint32 Offset, ::Verse::VRestValue T::*)
354{
355 return TMemberDeclaration<T>(Name, Offset, EMemberType::VerseValue);
356}
357
358template<class T>
360{
361 return TMemberDeclaration<T>(Name, Offset, EMemberType::VerseValueArray);
362}
363
364template<class T, typename U>
365TMemberDeclaration<T> MakeMember(const char* Name, uint32 Offset, ::Verse::TWriteBarrier<U> T::*)
366{
367 return TMemberDeclaration<T>(Name, Offset, EMemberType::VerseValue);
368}
369
370template<class T, typename U>
371TMemberDeclaration<T> MakeMember(const char* Name, uint32 Offset, TArray<::Verse::TWriteBarrier<U>> T::*)
372{
373 return TMemberDeclaration<T>(Name, Offset, EMemberType::VerseValueArray);
374}
375#endif
376
377} // namespace Private
378
379// Helpers to overload/dispatch UE_GC_MEMBER with 2 or 3 parameters
380#define _UE_EXPAND(x) x // MSVC macro evaluation workaround
381#define _UE_GC_MEMBER2(Type, Member) UE::GC::Private::MakeMember(#Member, offsetof(Type, Member), &Type::Member)
382#define _UE_GC_MEMBER3(Type, Member, InnerSchema) UE::GC::Private::MakeNestedMember(#Member, offsetof(Type, Member), &Type::Member, InnerSchema)
383#define _UE_GC_MEMBER(_1,_2,_3,CHOSEN_OVERLOAD,...) CHOSEN_OVERLOAD // _UE_GC_MEMBER2 or _UE_GC_MEMBER3
384
385#define UE_GC_MEMBER(...) _UE_EXPAND(_UE_EXPAND(_UE_GC_MEMBER(__VA_ARGS__, _UE_GC_MEMBER3, _UE_GC_MEMBER2)) (__VA_ARGS__))
386
388
390
391template<class T>
392void DeclareIntrinsicMembers(UClass* Class, std::initializer_list<TMemberDeclaration<T>> Members)
393{
395}
396
397FSchemaView GetIntrinsicSchema(UClass* Class);
398
400} // namespace UE::GC
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
#define check(expr)
Definition AssertionMacros.h:314
ENoInit
Definition CoreMiscDefines.h:158
@ NoInit
Definition CoreMiscDefines.h:158
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define UE_GC_DEBUGNAMES
Definition GarbageCollectionSchema.h:18
uint32 Offset
Definition VulkanMemory.cpp:4033
uint8_t uint8
Definition binka_ue_file_header.h:8
uint16_t uint16
Definition binka_ue_file_header.h:7
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition NameTypes.h:617
Definition UnrealType.h:174
Definition UObjectGlobals.h:2492
Definition Array.h:670
UE_NODEBUG UE_FORCEINLINE_HINT void Push(ElementType &&Item)
Definition Array.h:1224
UE_REWRITE bool IsEmpty() const
Definition Array.h:1133
ElementType Pop(EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:1196
Definition Class.h:3793
Definition GarbageCollectionSchema.h:157
UE_FORCEINLINE_HINT FMemberId(uint32 Idx)
Definition GarbageCollectionSchema.h:160
UE_FORCEINLINE_HINT FMemberId(EMemberlessId Memberless)
Definition GarbageCollectionSchema.h:159
friend bool operator==(FMemberId A, FMemberId B)
Definition GarbageCollectionSchema.h:167
bool IsMemberless() const
Definition GarbageCollectionSchema.h:162
int32 AsPrintableIndex() const
Definition GarbageCollectionSchema.h:164
EMemberlessId AsMemberless() const
Definition GarbageCollectionSchema.h:165
uint32 GetIndex() const
Definition GarbageCollectionSchema.h:163
friend bool operator!=(FMemberId A, FMemberId B)
Definition GarbageCollectionSchema.h:168
Definition GarbageCollectionSchema.h:86
FPropertyStackScope(FPropertyStack &InStack, FProperty *Property)
Definition GarbageCollectionSchema.h:90
UE_NONCOPYABLE(FPropertyStackScope)
~FPropertyStackScope()
Definition GarbageCollectionSchema.h:97
Definition GarbageCollectionSchema.h:62
~FPropertyStack()
Definition GarbageCollectionSchema.h:66
UE_NONCOPYABLE(FPropertyStack)
COREUOBJECT_API FString GetPropertyPath() const
Definition GarbageCollectionSchema.cpp:545
static COREUOBJECT_API bool ConvertPathToProperties(UClass *ObjectClass, FName InPropertyPath, TArray< FProperty * > &OutProperties)
Definition GarbageCollectionSchema.cpp:570
Definition GarbageCollectionSchema.h:265
COREUOBJECT_API ~FSchemaBuilder()
Definition GarbageCollectionSchema.cpp:297
COREUOBJECT_API void Add(FMemberDeclaration Member)
Definition GarbageCollectionSchema.cpp:309
int32 NumMembers() const
Definition GarbageCollectionSchema.h:278
Definition GarbageCollectionSchema.h:115
FSchemaView()
Definition GarbageCollectionSchema.h:120
const FMemberWord * GetWords() const
Definition GarbageCollectionSchema.h:130
uint32 GetStructStride() const
Definition GarbageCollectionSchema.h:136
FSchemaHeader * TryGetHeader()
Definition GarbageCollectionSchema.cpp:99
FSchemaHeader & GetHeader()
Definition GarbageCollectionSchema.cpp:93
void SetOrigin(EOrigin Origin)
Definition GarbageCollectionSchema.h:133
bool IsEmpty() const
Definition GarbageCollectionSchema.h:132
EOrigin GetOrigin() const
Definition GarbageCollectionSchema.h:131
FSchemaView(const FMemberWord *Data, EOrigin Origin=EOrigin::Other)
Definition GarbageCollectionSchema.h:123
FSchemaView(ENoInit)
Definition GarbageCollectionSchema.h:121
FSchemaView(FSchemaView View, EOrigin Origin)
Definition GarbageCollectionSchema.h:122
Definition GarbageCollectionSchema.h:299
TSchemaBuilder(std::initializer_list< TMemberDeclaration< T > > InMembers={})
Definition GarbageCollectionSchema.h:301
void Add(TMemberDeclaration< T > Member)
Definition GarbageCollectionSchema.h:302
Definition Object.h:95
Definition OverriddenPropertySet.cpp:45
TMemberDeclaration< T > MakeMember(const char *Name, uint32 Offset, R T::*)
Definition GarbageCollectionSchema.h:310
TMemberDeclaration< T > MakeNestedMember(const char *Name, uint32 Offset, TArray< S > T::*, TSchemaBuilder< S > &InnerSchema)
Definition GarbageCollectionSchema.h:336
Definition GCObjectReferencer.cpp:27
FMemberWord ToWord(FSchemaView In)
Definition GarbageCollectionSchema.h:222
uint32 CountSchemas(uint32 &OutNumWords)
Definition GarbageCollectionSchema.cpp:966
void DeclareIntrinsicMembers(UClass *Class, std::initializer_list< TMemberDeclaration< T > > Members)
Definition GarbageCollectionSchema.h:392
void DeclareIntrinsicSchema(UClass *Class, FSchemaView Schema)
Definition GarbageCollectionSchema.cpp:530
FSchemaView GetIntrinsicSchema(UClass *Class)
Definition GarbageCollectionSchema.cpp:537
void(*)(UObject *, FReferenceCollector &) ObjectAROFn
Definition GarbageCollectionSchema.h:204
EMemberlessId
Definition GarbageCollectionSchema.h:145
EOrigin
Definition GarbageCollectionSchema.h:53
void(*)(void *, FReferenceCollector &) StructAROFn
Definition GarbageCollectionSchema.h:205
EMemberType
Definition GarbageCollectionSchema.h:25
FMemberDeclaration DeclareMember(NameType &&Name, uint32 Offset, EMemberType Type)
Definition GarbageCollectionSchema.h:251
FMemberInfo GetMemberDebugInfo(FSchemaView Schema, FMemberId Id)
Definition GarbageCollectionSchema.cpp:234
FName ToName(EMemberType Type)
Definition GarbageCollectionSchema.cpp:39
U16 Index
Definition radfft.cpp:71
Definition ObjectPtr.h:488
Definition Optional.h:131
Definition GarbageCollectionSchema.h:239
FName DebugName
Definition GarbageCollectionSchema.h:240
FMemberWord ExtraWord
Definition GarbageCollectionSchema.h:243
EMemberType Type
Definition GarbageCollectionSchema.h:242
uint32 Offset
Definition GarbageCollectionSchema.h:241
Definition GarbageCollectionSchema.h:181
int32 Offset
Definition GarbageCollectionSchema.h:182
FName Name
Definition GarbageCollectionSchema.h:183
Definition GarbageCollectionSchema.h:195
uint16 Type
Definition GarbageCollectionSchema.h:200
uint16 WordOffset
Definition GarbageCollectionSchema.h:201
static constexpr uint32 OffsetBits
Definition GarbageCollectionSchema.h:197
static constexpr uint32 TypeBits
Definition GarbageCollectionSchema.h:196
static constexpr uint32 OffsetRange
Definition GarbageCollectionSchema.h:198
Definition GarbageCollectionSchema.h:106
std::atomic< int32 > RefCount
Definition GarbageCollectionSchema.h:108
uint32 StructStride
Definition GarbageCollectionSchema.h:107
Definition GarbageCollectionSchema.h:208
uint16 WordOffset
Definition GarbageCollectionSchema.h:209
uint16 WordStride
Definition GarbageCollectionSchema.h:210
Definition GarbageCollectionSchema.h:291
TMemberDeclaration(Ts &&... Args)
Definition GarbageCollectionSchema.h:293
Definition GarbageCollectionSchema.h:214
FSchemaView InnerSchema
Definition GarbageCollectionSchema.h:216
ObjectAROFn ObjectARO
Definition GarbageCollectionSchema.h:217
StructAROFn StructARO
Definition GarbageCollectionSchema.h:218
FStridedLayout StridedLayout
Definition GarbageCollectionSchema.h:219
FMemberPacked Members[4]
Definition GarbageCollectionSchema.h:215