diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
index b83a48925675..8abec6927b16 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java
@@ -385,16 +385,9 @@ public static native void Run(String[] path, boolean riivolution, String savesta
public static native boolean IsRunningAndUnpaused();
/**
- * Enables or disables CPU block profiling
- *
- * @param enable
- */
- public static native void SetProfiling(boolean enable);
-
- /**
- * Writes out the block profile results
+ * Writes out the JitBlock Cache log dump
*/
- public static native void WriteProfileResults();
+ public static native void WriteJitBlockLogDump();
/**
* Native EGL functions not exposed by Java bindings
@@ -454,6 +447,14 @@ private static void CheckGameMetadataValid()
private static native String GetCurrentTitleDescriptionUnchecked();
+ @Keep
+ public static void displayToastMsg(final String text, final boolean long_length)
+ {
+ final int length = long_length ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT;
+ new Handler(Looper.getMainLooper())
+ .post(() -> Toast.makeText(DolphinApplication.getAppContext(), text, length).show());
+ }
+
@Keep
public static boolean displayAlertMsg(final String caption, final String text,
final boolean yesNo, final boolean isWarning, final boolean nonBlocking)
@@ -466,9 +467,7 @@ public static boolean displayAlertMsg(final String caption, final String text,
// and are allowed to block. As a fallback, we can use toasts.
if (emulationActivity == null || nonBlocking)
{
- new Handler(Looper.getMainLooper()).post(
- () -> Toast.makeText(DolphinApplication.getAppContext(), text, Toast.LENGTH_LONG)
- .show());
+ displayToastMsg(text, true);
}
else
{
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt
index 6fddbe6b4325..331ad7fa09ce 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt
@@ -214,6 +214,12 @@ enum class BooleanSetting(
"JitRegisterCacheOff",
false
),
+ MAIN_DEBUG_JIT_ENABLE_PROFILING(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_DEBUG,
+ "JitEnableProfiling",
+ false
+ ),
MAIN_EMULATE_SKYLANDER_PORTAL(
Settings.FILE_DOLPHIN,
Settings.SECTION_EMULATED_USB_DEVICES,
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
index a3ec018b469f..6de39ed1e909 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -1978,6 +1978,26 @@ class SettingsFragmentPresenter(
)
)
+ sl.add(HeaderSetting(context, R.string.debug_jit_profiling_header, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_ENABLE_PROFILING,
+ R.string.debug_jit_enable_block_profiling,
+ 0
+ )
+ )
+ sl.add(
+ RunRunnable(
+ context,
+ R.string.debug_jit_write_block_log_dump,
+ 0,
+ 0,
+ 0,
+ true
+ ) { NativeLibrary.WriteJitBlockLogDump() }
+ )
+
sl.add(HeaderSetting(context, R.string.debug_jit_header, 0))
sl.add(
SwitchSetting(
diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml
index 5dde637d7d73..360e5006a03a 100644
--- a/Source/Android/app/src/main/res/values/strings.xml
+++ b/Source/Android/app/src/main/res/values/strings.xml
@@ -406,6 +406,9 @@
Disable Fastmem
Disable Fastmem Arena
Disable Large Entry Points Map
+ Jit Profiling
+ Enable Jit Block Profiling
+ Write Jit Block Log Dump
Jit
Jit Disabled
Jit Load Store Disabled
diff --git a/Source/Android/jni/AndroidCommon/IDCache.cpp b/Source/Android/jni/AndroidCommon/IDCache.cpp
index a19423d67c3d..5fe151278f28 100644
--- a/Source/Android/jni/AndroidCommon/IDCache.cpp
+++ b/Source/Android/jni/AndroidCommon/IDCache.cpp
@@ -12,6 +12,7 @@ static JavaVM* s_java_vm;
static jclass s_string_class;
static jclass s_native_library_class;
+static jmethodID s_display_toast_msg;
static jmethodID s_display_alert_msg;
static jmethodID s_update_touch_pointer;
static jmethodID s_on_title_changed;
@@ -146,6 +147,11 @@ jclass GetNativeLibraryClass()
return s_native_library_class;
}
+jmethodID GetDisplayToastMsg()
+{
+ return s_display_toast_msg;
+}
+
jmethodID GetDisplayAlertMsg()
{
return s_display_alert_msg;
@@ -528,6 +534,8 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
const jclass native_library_class = env->FindClass("org/dolphinemu/dolphinemu/NativeLibrary");
s_native_library_class = reinterpret_cast(env->NewGlobalRef(native_library_class));
+ s_display_toast_msg =
+ env->GetStaticMethodID(s_native_library_class, "displayToastMsg", "(Ljava/lang/String;Z)V");
s_display_alert_msg = env->GetStaticMethodID(s_native_library_class, "displayAlertMsg",
"(Ljava/lang/String;Ljava/lang/String;ZZZ)Z");
s_update_touch_pointer =
diff --git a/Source/Android/jni/AndroidCommon/IDCache.h b/Source/Android/jni/AndroidCommon/IDCache.h
index 604b68e38e29..c324b6cb1987 100644
--- a/Source/Android/jni/AndroidCommon/IDCache.h
+++ b/Source/Android/jni/AndroidCommon/IDCache.h
@@ -12,6 +12,7 @@ JNIEnv* GetEnvForThread();
jclass GetStringClass();
jclass GetNativeLibraryClass();
+jmethodID GetDisplayToastMsg();
jmethodID GetDisplayAlertMsg();
jmethodID GetUpdateTouchPointer();
jmethodID GetOnTitleChanged();
diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp
index ebd0b2c79238..1034406d7a85 100644
--- a/Source/Android/jni/MainAndroid.cpp
+++ b/Source/Android/jni/MainAndroid.cpp
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -22,6 +23,7 @@
#include "Common/Event.h"
#include "Common/FileUtil.h"
#include "Common/Flag.h"
+#include "Common/IOFile.h"
#include "Common/IniFile.h"
#include "Common/Logging/LogManager.h"
#include "Common/MsgHandler.h"
@@ -42,7 +44,6 @@
#include "Core/Host.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/PowerPC.h"
-#include "Core/PowerPC/Profiler.h"
#include "Core/State.h"
#include "Core/System.h"
@@ -404,26 +405,34 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetMaxLogLev
return static_cast(Common::Log::MAX_LOGLEVEL);
}
-JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetProfiling(JNIEnv*, jclass,
- jboolean enable)
+JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_WriteJitBlockLogDump(
+ JNIEnv* env, jclass native_library_class)
{
HostThreadLock guard;
auto& system = Core::System::GetInstance();
auto& jit_interface = system.GetJitInterface();
- const Core::CPUThreadGuard cpu_guard(system);
- jit_interface.ClearCache(cpu_guard);
- jit_interface.SetProfilingState(enable ? JitInterface::ProfilingState::Enabled :
- JitInterface::ProfilingState::Disabled);
-}
-
-JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_WriteProfileResults(JNIEnv*,
- jclass)
-{
- HostThreadLock guard;
- std::string filename = File::GetUserPath(D_DUMP_IDX) + "Debug/profiler.txt";
- File::CreateFullPath(filename);
- auto& jit_interface = Core::System::GetInstance().GetJitInterface();
- jit_interface.WriteProfileResults(filename);
+ if (jit_interface.GetCore() == nullptr)
+ {
+ env->CallStaticVoidMethod(native_library_class, IDCache::GetDisplayToastMsg(),
+ ToJString(env, Common::GetStringT("JIT is not active")),
+ static_cast(false));
+ return;
+ }
+ const std::string filename = fmt::format("{}{}.txt", File::GetUserPath(D_DUMPDEBUG_JITBLOCKS_IDX),
+ SConfig::GetInstance().GetGameID());
+ File::IOFile f(filename, "w");
+ if (!f)
+ {
+ env->CallStaticVoidMethod(
+ native_library_class, IDCache::GetDisplayToastMsg(),
+ ToJString(env, Common::FmtFormatT("Failed to open \"{0}\" for writing.", filename)),
+ static_cast(false));
+ return;
+ }
+ jit_interface.JitBlockLogDump(Core::CPUThreadGuard{system}, f.GetHandle());
+ env->CallStaticVoidMethod(native_library_class, IDCache::GetDisplayToastMsg(),
+ ToJString(env, Common::FmtFormatT("Wrote to \"{0}\".", filename)),
+ static_cast(false));
}
// Surface Handling
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt
index 1431239af253..7b81cd2c6d0f 100644
--- a/Source/Core/Common/CMakeLists.txt
+++ b/Source/Core/Common/CMakeLists.txt
@@ -108,8 +108,6 @@ add_library(common
Network.h
PcapFile.cpp
PcapFile.h
- PerformanceCounter.cpp
- PerformanceCounter.h
Profiler.cpp
Profiler.h
QoSSession.cpp
diff --git a/Source/Core/Common/CommonPaths.h b/Source/Core/Common/CommonPaths.h
index 1dce5c47f569..bd0f94699115 100644
--- a/Source/Core/Common/CommonPaths.h
+++ b/Source/Core/Common/CommonPaths.h
@@ -77,6 +77,7 @@
#define DUMP_SSL_DIR "SSL"
#define DUMP_DEBUG_DIR "Debug"
#define DUMP_DEBUG_BRANCHWATCH_DIR "BranchWatch"
+#define DUMP_DEBUG_JITBLOCKS_DIR "JitBlocks"
#define LOGS_DIR "Logs"
#define MAIL_LOGS_DIR "Mail"
#define SHADERS_DIR "Shaders"
diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp
index 20c57c2b5a82..a93db638df8c 100644
--- a/Source/Core/Common/FileUtil.cpp
+++ b/Source/Core/Common/FileUtil.cpp
@@ -859,6 +859,8 @@ static void RebuildUserDirectories(unsigned int dir_index)
s_user_paths[D_DUMPDEBUG_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_DEBUG_DIR DIR_SEP;
s_user_paths[D_DUMPDEBUG_BRANCHWATCH_IDX] =
s_user_paths[D_DUMPDEBUG_IDX] + DUMP_DEBUG_BRANCHWATCH_DIR DIR_SEP;
+ s_user_paths[D_DUMPDEBUG_JITBLOCKS_IDX] =
+ s_user_paths[D_DUMPDEBUG_IDX] + DUMP_DEBUG_JITBLOCKS_DIR DIR_SEP;
s_user_paths[D_LOGS_IDX] = s_user_paths[D_USER_IDX] + LOGS_DIR DIR_SEP;
s_user_paths[D_MAILLOGS_IDX] = s_user_paths[D_LOGS_IDX] + MAIL_LOGS_DIR DIR_SEP;
s_user_paths[D_THEMES_IDX] = s_user_paths[D_USER_IDX] + THEMES_DIR DIR_SEP;
@@ -938,6 +940,8 @@ static void RebuildUserDirectories(unsigned int dir_index)
s_user_paths[D_DUMPDEBUG_IDX] = s_user_paths[D_DUMP_IDX] + DUMP_DEBUG_DIR DIR_SEP;
s_user_paths[D_DUMPDEBUG_BRANCHWATCH_IDX] =
s_user_paths[D_DUMPDEBUG_IDX] + DUMP_DEBUG_BRANCHWATCH_DIR DIR_SEP;
+ s_user_paths[D_DUMPDEBUG_JITBLOCKS_IDX] =
+ s_user_paths[D_DUMPDEBUG_IDX] + DUMP_DEBUG_JITBLOCKS_DIR DIR_SEP;
s_user_paths[F_MEM1DUMP_IDX] = s_user_paths[D_DUMP_IDX] + MEM1_DUMP;
s_user_paths[F_MEM2DUMP_IDX] = s_user_paths[D_DUMP_IDX] + MEM2_DUMP;
s_user_paths[F_ARAMDUMP_IDX] = s_user_paths[D_DUMP_IDX] + ARAM_DUMP;
diff --git a/Source/Core/Common/FileUtil.h b/Source/Core/Common/FileUtil.h
index 975ab5525604..7d2d5e737a49 100644
--- a/Source/Core/Common/FileUtil.h
+++ b/Source/Core/Common/FileUtil.h
@@ -54,6 +54,7 @@ enum
D_DUMPSSL_IDX,
D_DUMPDEBUG_IDX,
D_DUMPDEBUG_BRANCHWATCH_IDX,
+ D_DUMPDEBUG_JITBLOCKS_IDX,
D_LOAD_IDX,
D_LOGS_IDX,
D_MAILLOGS_IDX,
diff --git a/Source/Core/Common/PerformanceCounter.cpp b/Source/Core/Common/PerformanceCounter.cpp
deleted file mode 100644
index efe78e33db14..000000000000
--- a/Source/Core/Common/PerformanceCounter.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 Dolphin Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#if !defined(_WIN32)
-#include "Common/PerformanceCounter.h"
-
-#include
-#include
-
-#include
-
-#include "Common/CommonTypes.h"
-
-#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
-#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK > 0
-#define DOLPHIN_CLOCK CLOCK_MONOTONIC
-#else
-#define DOLPHIN_CLOCK CLOCK_REALTIME
-#endif
-#endif
-
-bool QueryPerformanceCounter(u64* out)
-{
-#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
- timespec tp;
- if (clock_gettime(DOLPHIN_CLOCK, &tp))
- return false;
- *out = (u64)tp.tv_nsec + (u64)1000000000 * (u64)tp.tv_sec;
- return true;
-#else
- *out = 0;
- return false;
-#endif
-}
-
-bool QueryPerformanceFrequency(u64* out)
-{
-#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
- *out = 1000000000;
- return true;
-#else
- *out = 1;
- return false;
-#endif
-}
-
-#endif
diff --git a/Source/Core/Common/PerformanceCounter.h b/Source/Core/Common/PerformanceCounter.h
deleted file mode 100644
index 080f40c6cff9..000000000000
--- a/Source/Core/Common/PerformanceCounter.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 Dolphin Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#if !defined(_WIN32)
-
-#include
-
-#include "Common/CommonTypes.h"
-
-typedef u64 LARGE_INTEGER;
-bool QueryPerformanceCounter(u64* out);
-bool QueryPerformanceFrequency(u64* lpFrequency);
-
-#endif
diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index fb2c0c18fa70..9d477b50a500 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -523,7 +523,6 @@ add_library(core
PowerPC/PPCSymbolDB.h
PowerPC/PPCTables.cpp
PowerPC/PPCTables.h
- PowerPC/Profiler.h
PowerPC/SignatureDB/CSVSignatureDB.cpp
PowerPC/SignatureDB/CSVSignatureDB.h
PowerPC/SignatureDB/DSYSignatureDB.cpp
diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp
index 432abbeb2446..0add7e42bfe7 100644
--- a/Source/Core/Core/Config/MainSettings.cpp
+++ b/Source/Core/Core/Config/MainSettings.cpp
@@ -509,6 +509,8 @@ const Info MAIN_DEBUG_JIT_SYSTEM_REGISTERS_OFF{
const Info MAIN_DEBUG_JIT_BRANCH_OFF{{System::Main, "Debug", "JitBranchOff"}, false};
const Info MAIN_DEBUG_JIT_REGISTER_CACHE_OFF{{System::Main, "Debug", "JitRegisterCacheOff"},
false};
+const Info MAIN_DEBUG_JIT_ENABLE_PROFILING{{System::Main, "Debug", "JitEnableProfiling"},
+ false};
// Main.BluetoothPassthrough
diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h
index 5c028d9b3607..d7e78bf6e9e4 100644
--- a/Source/Core/Core/Config/MainSettings.h
+++ b/Source/Core/Core/Config/MainSettings.h
@@ -335,6 +335,7 @@ extern const Info MAIN_DEBUG_JIT_PAIRED_OFF;
extern const Info MAIN_DEBUG_JIT_SYSTEM_REGISTERS_OFF;
extern const Info MAIN_DEBUG_JIT_BRANCH_OFF;
extern const Info MAIN_DEBUG_JIT_REGISTER_CACHE_OFF;
+extern const Info MAIN_DEBUG_JIT_ENABLE_PROFILING;
// Main.BluetoothPassthrough
diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp
index 0c600561d19e..d2296641c2e8 100644
--- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp
+++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp
@@ -316,7 +316,7 @@ void CachedInterpreter::Jit(u32 address)
js.numFloatingPointInst = 0;
js.curBlock = b;
- b->normalEntry = GetCodePtr();
+ b->normalEntry = b->near_begin = GetCodePtr();
for (u32 i = 0; i < code_block.m_num_instructions; i++)
{
@@ -382,6 +382,10 @@ void CachedInterpreter::Jit(u32 address)
}
m_code.emplace_back();
+ b->near_end = GetCodePtr();
+ b->far_begin = nullptr;
+ b->far_end = nullptr;
+
b->codeSize = static_cast(GetCodePtr() - b->normalEntry);
b->originalSize = code_block.m_num_instructions;
diff --git a/Source/Core/Core/PowerPC/Gekko.h b/Source/Core/Core/PowerPC/Gekko.h
index 62a1743b4531..86c6dd863262 100644
--- a/Source/Core/Core/PowerPC/Gekko.h
+++ b/Source/Core/Core/PowerPC/Gekko.h
@@ -931,6 +931,7 @@ enum CPUEmuFeatureFlags : u32
FEATURE_FLAG_MSR_DR = 1 << 0,
FEATURE_FLAG_MSR_IR = 1 << 1,
FEATURE_FLAG_PERFMON = 1 << 2,
+ FEATURE_FLAG_END_OF_ENUMERATION,
};
constexpr s32 SignExt16(s16 x)
diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp
index ce1dc906d396..867190e28487 100644
--- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp
+++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp
@@ -19,7 +19,6 @@
#include "Common/GekkoDisassembler.h"
#include "Common/IOFile.h"
#include "Common/Logging/Log.h"
-#include "Common/PerformanceCounter.h"
#include "Common/StringUtil.h"
#include "Common/Swap.h"
#include "Common/x64ABI.h"
@@ -43,7 +42,6 @@
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PowerPC.h"
-#include "Core/PowerPC/Profiler.h"
#include "Core/System.h"
using namespace Gen;
@@ -454,20 +452,11 @@ bool Jit64::Cleanup()
did_something = true;
}
- if (jo.profile_blocks)
+ if (IsProfilingEnabled())
{
ABI_PushRegistersAndAdjustStack({}, 0);
- // get end tic
- MOV(64, R(ABI_PARAM1), ImmPtr(&js.curBlock->profile_data.ticStop));
- ABI_CallFunction(QueryPerformanceCounter);
- // tic counter += (end tic - start tic)
- MOV(64, R(RSCRATCH2), ImmPtr(&js.curBlock->profile_data));
- MOV(64, R(RSCRATCH), MDisp(RSCRATCH2, offsetof(JitBlock::ProfileData, ticStop)));
- SUB(64, R(RSCRATCH), MDisp(RSCRATCH2, offsetof(JitBlock::ProfileData, ticStart)));
- ADD(64, R(RSCRATCH), MDisp(RSCRATCH2, offsetof(JitBlock::ProfileData, ticCounter)));
- ADD(64, MDisp(RSCRATCH2, offsetof(JitBlock::ProfileData, downcountCounter)),
- Imm32(js.downcountAmount));
- MOV(64, MDisp(RSCRATCH2, offsetof(JitBlock::ProfileData, ticCounter)), R(RSCRATCH));
+ ABI_CallFunctionPC(&JitBlock::ProfileData::EndProfiling, js.curBlock->profile_data.get(),
+ js.downcountAmount);
ABI_PopRegistersAndAdjustStack({}, 0);
did_something = true;
}
@@ -773,7 +762,7 @@ void Jit64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
EnableBlockLink();
EnableOptimization();
- if (!jo.profile_blocks)
+ if (!IsProfilingEnabled())
{
if (m_system.GetCPU().IsStepping())
{
@@ -899,15 +888,9 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
}
// Conditionally add profiling code.
- if (jo.profile_blocks)
- {
- // get start tic
- MOV(64, R(ABI_PARAM1), ImmPtr(&b->profile_data.ticStart));
- int offset = static_cast(offsetof(JitBlock::ProfileData, runCount)) -
- static_cast(offsetof(JitBlock::ProfileData, ticStart));
- ADD(64, MDisp(ABI_PARAM1, offset), Imm8(1));
- ABI_CallFunction(QueryPerformanceCounter);
- }
+ if (IsProfilingEnabled())
+ ABI_CallFunctionP(&JitBlock::ProfileData::BeginProfiling, b->profile_data.get());
+
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(NAN_CHECK)
// should help logged stack-traces become more accurate
MOV(32, PPCSTATE(pc), Imm32(js.blockStart));
diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
index b8fada1dcb88..f596128ef918 100644
--- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
+++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp
@@ -10,7 +10,6 @@
#include "Common/Logging/Log.h"
#include "Common/MathUtil.h"
#include "Common/MsgHandler.h"
-#include "Common/PerformanceCounter.h"
#include "Common/StringUtil.h"
#include "Core/ConfigManager.h"
@@ -26,7 +25,6 @@
#include "Core/PowerPC/JitArm64/JitArm64_RegCache.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/PowerPC.h"
-#include "Core/PowerPC/Profiler.h"
#include "Core/System.h"
using namespace Arm64Gen;
@@ -408,7 +406,11 @@ void JitArm64::WriteExit(u32 destination, bool LK, u32 exit_address_after_return
ARM64Reg exit_address_after_return_reg)
{
Cleanup();
- EndTimeProfile(js.curBlock);
+ if (IsProfilingEnabled())
+ {
+ ABI_CallFunction(&JitBlock::ProfileData::EndProfiling, js.curBlock->profile_data.get(),
+ js.downcountAmount);
+ }
DoDownCount();
LK &= m_enable_blr_optimization;
@@ -509,7 +511,11 @@ void JitArm64::WriteExit(Arm64Gen::ARM64Reg dest, bool LK, u32 exit_address_afte
MOV(DISPATCHER_PC, dest);
Cleanup();
- EndTimeProfile(js.curBlock);
+ if (IsProfilingEnabled())
+ {
+ ABI_CallFunction(&JitBlock::ProfileData::EndProfiling, js.curBlock->profile_data.get(),
+ js.downcountAmount);
+ }
DoDownCount();
LK &= m_enable_blr_optimization;
@@ -672,7 +678,11 @@ void JitArm64::WriteBLRExit(Arm64Gen::ARM64Reg dest)
MOV(DISPATCHER_PC, dest);
Cleanup();
- EndTimeProfile(js.curBlock);
+ if (IsProfilingEnabled())
+ {
+ ABI_CallFunction(&JitBlock::ProfileData::EndProfiling, js.curBlock->profile_data.get(),
+ js.downcountAmount);
+ }
// Check if {PPC_PC, feature_flags} matches the current state, then RET to ARM_PC.
LDP(IndexType::Post, ARM64Reg::X2, ARM64Reg::X1, ARM64Reg::SP, 16);
@@ -736,7 +746,11 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external, bool always
if (!always_exception)
SetJumpTarget(no_exceptions);
- EndTimeProfile(js.curBlock);
+ if (IsProfilingEnabled())
+ {
+ ABI_CallFunction(&JitBlock::ProfileData::EndProfiling, js.curBlock->profile_data.get(),
+ js.downcountAmount);
+ }
DoDownCount();
B(dispatcher);
@@ -804,44 +818,6 @@ void JitArm64::DumpCode(const u8* start, const u8* end)
WARN_LOG_FMT(DYNA_REC, "Code dump from {} to {}:\n{}", fmt::ptr(start), fmt::ptr(end), output);
}
-void JitArm64::BeginTimeProfile(JitBlock* b)
-{
- MOVP2R(ARM64Reg::X0, &b->profile_data);
- LDR(IndexType::Unsigned, ARM64Reg::X1, ARM64Reg::X0, offsetof(JitBlock::ProfileData, runCount));
- ADD(ARM64Reg::X1, ARM64Reg::X1, 1);
-
- // Fetch the current counter register
- CNTVCT(ARM64Reg::X2);
-
- // stores runCount and ticStart
- STP(IndexType::Signed, ARM64Reg::X1, ARM64Reg::X2, ARM64Reg::X0,
- offsetof(JitBlock::ProfileData, runCount));
-}
-
-void JitArm64::EndTimeProfile(JitBlock* b)
-{
- if (!jo.profile_blocks)
- return;
-
- // Fetch the current counter register
- CNTVCT(ARM64Reg::X1);
-
- MOVP2R(ARM64Reg::X0, &b->profile_data);
-
- LDR(IndexType::Unsigned, ARM64Reg::X2, ARM64Reg::X0, offsetof(JitBlock::ProfileData, ticStart));
- SUB(ARM64Reg::X1, ARM64Reg::X1, ARM64Reg::X2);
-
- // loads ticCounter and downcountCounter
- LDP(IndexType::Signed, ARM64Reg::X2, ARM64Reg::X3, ARM64Reg::X0,
- offsetof(JitBlock::ProfileData, ticCounter));
- ADD(ARM64Reg::X2, ARM64Reg::X2, ARM64Reg::X1);
- ADDI2R(ARM64Reg::X3, ARM64Reg::X3, js.downcountAmount, ARM64Reg::X1);
-
- // stores ticCounter and downcountCounter
- STP(IndexType::Signed, ARM64Reg::X2, ARM64Reg::X3, ARM64Reg::X0,
- offsetof(JitBlock::ProfileData, ticCounter));
-}
-
void JitArm64::Run()
{
ProtectStack();
@@ -933,7 +909,7 @@ void JitArm64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
SetBlockLinkingEnabled(true);
SetOptimizationEnabled(true);
- if (!jo.profile_blocks)
+ if (!IsProfilingEnabled())
{
if (cpu.IsStepping())
{
@@ -1052,11 +1028,8 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
b->normalEntry = GetWritableCodePtr();
// Conditionally add profiling code.
- if (jo.profile_blocks)
- {
- // get start tic
- BeginTimeProfile(b);
- }
+ if (IsProfilingEnabled())
+ ABI_CallFunction(&JitBlock::ProfileData::BeginProfiling, b->profile_data.get());
if (code_block.m_gqr_used.Count() == 1 &&
js.pairedQuantizeAddresses.find(js.blockStart) == js.pairedQuantizeAddresses.end())
@@ -1246,7 +1219,11 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
FixupBranch no_breakpoint = CBZ(ARM64Reg::W0);
Cleanup();
- EndTimeProfile(js.curBlock);
+ if (IsProfilingEnabled())
+ {
+ ABI_CallFunction(&JitBlock::ProfileData::EndProfiling, b->profile_data.get(),
+ js.downcountAmount);
+ }
DoDownCount();
B(dispatcher_exit);
diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h
index 6d0ded667a5f..a572b2e38fe4 100644
--- a/Source/Core/Core/PowerPC/JitArm64/Jit.h
+++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h
@@ -307,10 +307,6 @@ class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock, public CommonA
void GenerateQuantizedLoads();
void GenerateQuantizedStores();
- // Profiling
- void BeginTimeProfile(JitBlock* b);
- void EndTimeProfile(JitBlock* b);
-
void EmitUpdateMembase();
void MSRUpdated(u32 msr);
void MSRUpdated(Arm64Gen::ARM64Reg msr);
diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp
index c99938876028..5ec9af396751 100644
--- a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp
+++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp
@@ -57,7 +57,7 @@
// After resetting the stack to the top, we call _resetstkoflw() to restore
// the guard page at the 256kb mark.
-const std::array*>, 22> JitBase::JIT_SETTINGS{{
+const std::array*>, 23> JitBase::JIT_SETTINGS{{
{&JitBase::bJITOff, &Config::MAIN_DEBUG_JIT_OFF},
{&JitBase::bJITLoadStoreOff, &Config::MAIN_DEBUG_JIT_LOAD_STORE_OFF},
{&JitBase::bJITLoadStorelXzOff, &Config::MAIN_DEBUG_JIT_LOAD_STORE_LXZ_OFF},
@@ -71,6 +71,7 @@ const std::array*>, 22> JitB
{&JitBase::bJITSystemRegistersOff, &Config::MAIN_DEBUG_JIT_SYSTEM_REGISTERS_OFF},
{&JitBase::bJITBranchOff, &Config::MAIN_DEBUG_JIT_BRANCH_OFF},
{&JitBase::bJITRegisterCacheOff, &Config::MAIN_DEBUG_JIT_REGISTER_CACHE_OFF},
+ {&JitBase::m_enable_profiling, &Config::MAIN_DEBUG_JIT_ENABLE_PROFILING},
{&JitBase::m_enable_debugging, &Config::MAIN_ENABLE_DEBUGGING},
{&JitBase::m_enable_branch_following, &Config::MAIN_JIT_FOLLOW_BRANCH},
{&JitBase::m_enable_float_exceptions, &Config::MAIN_FLOAT_EXCEPTIONS},
diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/PowerPC/JitCommon/JitBase.h
index d3579368f42f..cf0ce78dbc6c 100644
--- a/Source/Core/Core/PowerPC/JitCommon/JitBase.h
+++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.h
@@ -86,7 +86,6 @@ class JitBase : public CPUCoreBase
bool memcheck;
bool fp_exceptions;
bool div_by_zero_exceptions;
- bool profile_blocks;
};
struct JitState
{
@@ -149,6 +148,7 @@ class JitBase : public CPUCoreBase
bool bJITSystemRegistersOff = false;
bool bJITBranchOff = false;
bool bJITRegisterCacheOff = false;
+ bool m_enable_profiling = false;
bool m_enable_debugging = false;
bool m_enable_branch_following = false;
bool m_enable_float_exceptions = false;
@@ -163,7 +163,7 @@ class JitBase : public CPUCoreBase
bool m_cleanup_after_stackfault = false;
u8* m_stack_guard = nullptr;
- static const std::array*>, 22> JIT_SETTINGS;
+ static const std::array*>, 23> JIT_SETTINGS;
bool DoesConfigNeedRefresh();
void RefreshConfig();
@@ -187,6 +187,7 @@ class JitBase : public CPUCoreBase
JitBase& operator=(JitBase&&) = delete;
~JitBase() override;
+ bool IsProfilingEnabled() const { return m_enable_profiling; }
bool IsDebuggingEnabled() const { return m_enable_debugging; }
static const u8* Dispatch(JitBase& jit);
diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp
index d8d6e8d13b81..8029d06c2d36 100644
--- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp
+++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp
@@ -32,6 +32,18 @@ bool JitBlock::OverlapsPhysicalRange(u32 address, u32 length) const
physical_addresses.lower_bound(address + length);
}
+void JitBlock::ProfileData::BeginProfiling(ProfileData* data)
+{
+ data->run_count += 1;
+ data->time_start = Clock::now();
+}
+
+void JitBlock::ProfileData::EndProfiling(ProfileData* data, int downcount_amount)
+{
+ data->cycles_spent += downcount_amount;
+ data->time_spent += Clock::now() - data->time_start;
+}
+
JitBaseBlockCache::JitBaseBlockCache(JitBase& jit) : m_jit{jit}
{
}
@@ -98,7 +110,8 @@ JitBlock** JitBaseBlockCache::GetFastBlockMapFallback()
return m_fast_block_map_fallback.data();
}
-void JitBaseBlockCache::RunOnBlocks(std::function f)
+void JitBaseBlockCache::RunOnBlocks(const Core::CPUThreadGuard&,
+ std::function f) const
{
for (const auto& e : block_map)
f(e.second);
@@ -107,7 +120,7 @@ void JitBaseBlockCache::RunOnBlocks(std::function f)
JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address)
{
const u32 physical_address = m_jit.m_mmu.JitCache_TranslateAddress(em_address).address;
- JitBlock& b = block_map.emplace(physical_address, JitBlock())->second;
+ JitBlock& b = block_map.emplace(physical_address, m_jit.IsProfilingEnabled())->second;
b.effectiveAddress = em_address;
b.physicalAddress = physical_address;
b.feature_flags = m_jit.m_ppc_state.feature_flags;
diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h
index feb872ee7b60..d44cc097d3eb 100644
--- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h
+++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h
@@ -5,6 +5,7 @@
#include
#include
+#include
#include
#include
#include