Dump global names
Closed this issue · 4 comments
rkr35 commented
void DebugDump(TArray<const FNameEntry*>& Out) const
{
FRWScopeLock _(Lock, FRWScopeLockType::SLT_ReadOnly);
for (uint32 BlockIdx = 0; BlockIdx < CurrentBlock; ++BlockIdx)
{
DebugDumpBlock(Blocks[BlockIdx], BlockSizeBytes, Out);
}
DebugDumpBlock(Blocks[CurrentBlock], CurrentByteCursor, Out);
}
static void DebugDumpBlock(const uint8* It, uint32 BlockSize, TArray<const FNameEntry*>& Out)
{
const uint8* End = It + BlockSize - FNameEntry::GetDataOffset();
while (It < End)
{
const FNameEntry* Entry = (const FNameEntry*)It;
if (uint32 Len = Entry->Header.Len)
{
Out.Add(Entry);
It += FNameEntry::GetSize(Len, !Entry->IsWide());
}
else // Null-terminator entry found
{
break;
}
}
}
rkr35 commented
enum { Stride = alignof(FNameEntry) };
enum { BlockSizeBytes = Stride * FNameBlockOffsets };
uint8* Blocks[FNameMaxBlocks] = {};
FNameEntry& Resolve(FNameEntryHandle Handle) const
{
// Lock not needed
return *reinterpret_cast<FNameEntry*>(Blocks[Handle.Block] + Stride * Handle.Offset);
}
rkr35 commented
/** Remember to update natvis if you change these */
enum { FNameMaxBlockBits = 13 }; // Limit block array a bit, still allowing 8k * block size = 1GB - 2G of FName entry data
enum { FNameBlockOffsetBits = 16 };
enum { FNameMaxBlocks = 1 << FNameMaxBlockBits };
enum { FNameBlockOffsets = 1 << FNameBlockOffsetBits };
/** An unpacked FNameEntryId */
struct FNameEntryHandle
{
uint32 Block = 0;
uint32 Offset = 0;
FNameEntryHandle(uint32 InBlock, uint32 InOffset)
: Block(InBlock)
, Offset(InOffset)
{}
FNameEntryHandle(FNameEntryId Id)
: Block(Id.ToUnstableInt() >> FNameBlockOffsetBits)
, Offset(Id.ToUnstableInt() & (FNameBlockOffsets - 1))
{}
operator FNameEntryId() const
{
return FNameEntryId::FromUnstableInt(Block << FNameBlockOffsetBits | Offset);
}
explicit operator bool() const { return Block | Offset; }
};