Add a JIT stats debug overlay

Shows the number of blocks, how full the native code space and the IR
arena are, and how many times each filling up cleared the cache.

The "Ran out of block numbers" message was logged for both of those, and
there is no block number limit. It now says which one filled up.

Also hide the GPU profile and allocator overlays by value on backends
that lack them. Cutting the last two off the list had been hiding the
framebuffer list since it was added after them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-17 14:49:24 +02:00
1 parent 370a9ca963
commit 2b0b1ed561
9 files changed
+122 -13

No files matched your search

+39
View File
@@ -7,6 +7,7 @@
#include "Common/Data/Text/StringWriter.h"
#include "Core/MIPS/MIPS.h"
#include "Core/MIPS/JitCommon/JitCommon.h"
#include "Core/HW/Display.h"
#include "Core/FrameTiming.h"
#include "Core/HLE/sceSas.h"
@@ -66,6 +67,40 @@ static void DrawDebugStats(UIContext *ctx, const Bounds &bounds) {
ctx->RebindTexture();
}
static void DrawJitStats(UIContext *ctx, const Bounds &bounds) {
FontID ubuntu24("UBUNTU24");
char statbuf[1024];
StringWriter w(statbuf, sizeof(statbuf));
if (MIPSComp::jit) {
MIPSComp::JitStats stats;
MIPSComp::jit->GetStats(&stats);
const double irPercent = stats.irArenaSize ? 100.0 * stats.irArenaUsed / stats.irArenaSize : 0.0;
w.F("Blocks: %d (%d valid)\n", stats.numBlocks, stats.numValidBlocks);
if (stats.codeSize) {
// The native JITs compile from the IR, and keep it for the debugger.
w.F("Native code: %0.2f / %0.2f MB (%0.1f%%)\n", stats.codeUsed / (1024.0 * 1024.0), stats.codeSize / (1024.0 * 1024.0),
100.0 * stats.codeUsed / stats.codeSize);
w.F("IR (debug info): %d / %d instructions (%0.1f%%)\n", (int)stats.irArenaUsed, (int)stats.irArenaSize, irPercent);
w.F("Cleared because full: native code %d, IR %d\n", stats.codeFullClears, stats.irArenaFullClears);
} else {
w.F("IR arena: %d / %d instructions (%0.1f%%)\n", (int)stats.irArenaUsed, (int)stats.irArenaSize, irPercent);
w.F("Cleared because full: %d\n", stats.irArenaFullClears);
}
} else {
w.W("No JIT (interpreter)\n");
}
ctx->Flush();
ctx->BindFontTexture();
ctx->Draw()->SetFontScale(.7f, .7f);
ctx->Draw()->DrawTextRect(ubuntu24, w.as_view(), bounds.x + 11, bounds.y + 31, bounds.w - 20, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII);
ctx->Draw()->DrawTextRect(ubuntu24, w.as_view(), bounds.x + 10, bounds.y + 30, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
ctx->Draw()->SetFontScale(1.0f, 1.0f);
ctx->Flush();
ctx->RebindTexture();
}
static void DrawAudioDebugStats(UIContext *ctx, const Bounds &bounds) {
FontID ubuntu24("UBUNTU24");
@@ -271,6 +306,10 @@ void DrawDebugOverlay(UIContext *ctx, const Bounds &bounds, DebugOverlay overlay
if (inGame)
DrawFramebufferList(ctx, gpu, layoutBounds);
break;
case DebugOverlay::JIT_STATS:
if (inGame)
DrawJitStats(ctx, layoutBounds);
break;
default:
break;
}