Description

This is from the linked EPS case:

==============================

When 5.0 first introduced TObjectPtr, the guidance was that it would compile down to raw pointer access in Shipping builds to ensure identical performance.

Evidenced by the following quote from the documentation for 5.0:

UE5 introduces TObjectPtr, a template-based, 64-bit pointer system, as an optional replacement for raw object pointers in editor builds. This system adds dynamic resolution and access tracking in editor builds, while performing identically to raw pointers in non-editor builds.

In recent versions of the engine, this guarantee seems to have been silently dropped.

The introduction of incremental reachability analysis adds code to call ConditionallyMarkAsReachable, regardless of whether incremental GC is turned on.

This causes assembly instructions comparable to the following to be generated inline every time a TObjectPtr or TSubclassOf is assigned:

cmp byte ptr [UE::GC::GIsIncrementalReachabilityPending],r14b

je _____+16Fh

mov rcx,qword ptr [rbx+458h]

test rcx,rcx

je _____+16Fh

call UE::GC::MarkAsReachable

In our game, this adds several megabytes to our compiled binary size, putting pressure on the instruction cache and branch predictor.

Even though incremental GC is experimental and not even supported outside of single-threaded servers, right now every game is paying for the feature even when not enabled, due to `UE_OBJECT_PTR_GC_BARRIER` being unconditionally set to `1` in `ObjectPtr.h`.

My questions are the following:

  • It would be nice if this code was automatically compiled out when incremental GC is off, instead of us having to randomly find out about the define during profiling.
  • This seems to unconditionally apply to every TSubclassOf as well, even when used as a parameter/local variable and GC barriers are unnecessary.
  • Inlining the check to `GIsIncrementalReachabilityPending` makes sense, but it might be worth moving the null object check into `MarkAsReachable` itself, which would reduce the binary size cost of the repeatedly inlined code.

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-386406 in the post.

0
Login to Vote

Unresolved
ComponentUE - CoreTech - UObject
Affects Versions5.8
CreatedJul 13, 2026
UpdatedJul 13, 2026
View Jira Issue