Skip to content

Commit

Permalink
DolphinQt: JIT Widget Refresh
Browse files Browse the repository at this point in the history
Fulfilling a certain six-year-old todo.
  • Loading branch information
mitaclaw committed Apr 16, 2024
1 parent dbc7e03 commit 1566098
Show file tree
Hide file tree
Showing 49 changed files with 2,133 additions and 566 deletions.
Expand Up @@ -385,6 +385,11 @@ public static native void Run(String[] path, boolean riivolution, String savesta

public static native boolean IsRunningAndUnpaused();

/**
* Re-initialize software JitBlock profiling data
*/
public static native void WipeJitBlockProfilingData();

/**
* Writes out the JitBlock Cache log dump
*/
Expand Down
Expand Up @@ -1987,6 +1987,16 @@ class SettingsFragmentPresenter(
0
)
)
sl.add(
RunRunnable(
context,
R.string.debug_jit_wipe_block_profiling_data,
0,
R.string.debug_jit_wipe_block_profiling_data_alert,
0,
true
) { NativeLibrary.WipeJitBlockProfilingData() }
)
sl.add(
RunRunnable(
context,
Expand Down
2 changes: 2 additions & 0 deletions Source/Android/app/src/main/res/values/strings.xml
Expand Up @@ -408,6 +408,8 @@
<string name="debug_large_entry_points_map">Disable Large Entry Points Map</string>
<string name="debug_jit_profiling_header">Jit Profiling</string>
<string name="debug_jit_enable_block_profiling">Enable Jit Block Profiling</string>
<string name="debug_jit_wipe_block_profiling_data">Wipe Jit Block Profiling Data</string>
<string name="debug_jit_wipe_block_profiling_data_alert">Re-initialize JIT block profiling data?</string>
<string name="debug_jit_write_block_log_dump">Write Jit Block Log Dump</string>
<string name="debug_jit_header">Jit</string>
<string name="debug_jitoff">Jit Disabled</string>
Expand Down
24 changes: 24 additions & 0 deletions Source/Android/jni/MainAndroid.cpp
Expand Up @@ -147,6 +147,14 @@ void Host_UpdateDisasmDialog()
{
}

void Host_JitCacheCleared()
{
}

void Host_JitProfileDataWiped()
{
}

void Host_UpdateMainFrame()
{
}
Expand Down Expand Up @@ -405,6 +413,22 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetMaxLogLev
return static_cast<jint>(Common::Log::MAX_LOGLEVEL);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_WipeJitBlockProfilingData(
JNIEnv* env, jclass native_library_class)
{
HostThreadLock guard;
auto& system = Core::System::GetInstance();
auto& jit_interface = system.GetJitInterface();
if (jit_interface.GetCore() == nullptr)
{
env->CallStaticVoidMethod(native_library_class, IDCache::GetDisplayToastMsg(),
ToJString(env, Common::GetStringT("JIT is not active")),
static_cast<jboolean>(false));
return;
}
jit_interface.WipeBlockProfilingData(Core::CPUThreadGuard{system});
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_WriteJitBlockLogDump(
JNIEnv* env, jclass native_library_class)
{
Expand Down
18 changes: 18 additions & 0 deletions Source/Core/Common/CMakeLists.txt
Expand Up @@ -75,6 +75,8 @@ add_library(common
Hash.cpp
Hash.h
HookableEvent.h
HostDisassembler.cpp
HostDisassembler.h
HttpRequest.cpp
HttpRequest.h
Image.cpp
Expand Down Expand Up @@ -142,6 +144,7 @@ add_library(common
TraversalClient.h
TraversalProto.h
TypeUtils.h
Unreachable.h
UPnP.cpp
UPnP.h
VariantUtil.h
Expand Down Expand Up @@ -177,6 +180,11 @@ PRIVATE
${VTUNE_LIBRARIES}
)

if ((DEFINED CMAKE_ANDROID_ARCH_ABI AND CMAKE_ANDROID_ARCH_ABI MATCHES "x86|x86_64") OR
(NOT DEFINED CMAKE_ANDROID_ARCH_ABI AND _M_X86_64))
target_link_libraries(common PRIVATE bdisasm)
endif()

if (APPLE)
target_link_libraries(common
PRIVATE
Expand Down Expand Up @@ -327,6 +335,16 @@ if(OPROFILE_FOUND)
target_link_libraries(common PRIVATE OProfile::OProfile)
endif()

if(ENABLE_LLVM)
find_package(LLVM CONFIG QUIET)
if(LLVM_FOUND AND TARGET LLVM)
message(STATUS "LLVM found, enabling LLVM support in disassembler")
target_compile_definitions(common PRIVATE HAVE_LLVM)
target_link_libraries(common PRIVATE LLVM)
target_include_directories(common PRIVATE ${LLVM_INCLUDE_DIRS})
endif()
endif()

if(UNIX)
# Posix networking code needs to be fixed for Windows
add_executable(traversal_server TraversalServer.cpp)
Expand Down
175 changes: 175 additions & 0 deletions Source/Core/Common/HostDisassembler.cpp
@@ -0,0 +1,175 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "Common/HostDisassembler.h"

#include <cstdint>
#include <span>
#include <sstream>

#include <fmt/format.h>
#include <fmt/ostream.h>

#if defined(HAVE_LLVM)
#include <llvm-c/Disassembler.h>
#include <llvm-c/Target.h>
#elif defined(_M_X86_64)
#include <disasm.h> // Bochs
#endif

#if defined(HAVE_LLVM)
class HostDisassemblerLLVM final : public HostDisassembler
{
public:
explicit HostDisassemblerLLVM(const char* host_disasm, const char* cpu = "",
std::size_t inst_size = 0);
~HostDisassemblerLLVM();

private:
LLVMDisasmContextRef m_llvm_context;
std::size_t m_instruction_size;

void Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count) override;
};

HostDisassemblerLLVM::HostDisassemblerLLVM(const char* host_disasm, const char* cpu,
std::size_t inst_size)
: m_instruction_size(inst_size)
{
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllDisassemblers();

m_llvm_context = LLVMCreateDisasmCPU(host_disasm, cpu, nullptr, 0, nullptr, nullptr);

// Couldn't create llvm context
if (!m_llvm_context)
return;

LLVMSetDisasmOptions(m_llvm_context, LLVMDisassembler_Option_AsmPrinterVariant |
LLVMDisassembler_Option_PrintLatency);
}

HostDisassemblerLLVM::~HostDisassemblerLLVM()
{
if (m_llvm_context)
LLVMDisasmDispose(m_llvm_context);
}

void HostDisassemblerLLVM::Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count)
{
instruction_count = 0;
if (!m_llvm_context)
return;

while (begin < end)
{
char inst_disasm[256];

const auto inst_size = LLVMDisasmInstruction(
m_llvm_context, const_cast<u8*>(begin), static_cast<u64>(end - begin),
reinterpret_cast<std::uintptr_t>(begin), inst_disasm, sizeof(inst_disasm));
if (inst_size == 0)
{
if (m_instruction_size != 0)
{
// If we are on an architecture that has a fixed instruction
// size, we can continue onward past this bad instruction.
fmt::println(stream, "{}\tInvalid inst: {:02x}", fmt::ptr(begin),
fmt::join(std::span{begin, m_instruction_size}, ""));
begin += m_instruction_size;
}
else
{
// We can't continue if we are on an architecture that has flexible
// instruction sizes. Dump the rest of the block instead.
fmt::println(stream, "{}\tInvalid inst: {:02x}", fmt::ptr(begin),
fmt::join(std::span{begin, end}, ""));
break;
}
}
else
{
fmt::println(stream, "{}{}", fmt::ptr(begin), inst_disasm);
begin += inst_size;
}

++instruction_count;
}
}
#elif defined(_M_X86_64)
class HostDisassemblerBochs final : public HostDisassembler
{
public:
explicit HostDisassemblerBochs();
~HostDisassemblerBochs() = default;

private:
disassembler m_disasm;

void Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count) override;
};

HostDisassemblerBochs::HostDisassemblerBochs()
{
m_disasm.set_syntax_intel();
}

void HostDisassemblerBochs::Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count)
{
instruction_count = 0;

while (begin < end)
{
char inst_disasm[256];
const auto inst_size = m_disasm.disasm64(reinterpret_cast<std::uintptr_t>(begin),
reinterpret_cast<std::uintptr_t>(begin),
const_cast<u8*>(begin), inst_disasm);
fmt::println(stream, "{}\t{}", fmt::ptr(begin), inst_disasm);
begin += inst_size;
++instruction_count;
}
}
#endif

std::unique_ptr<HostDisassembler> HostDisassembler::Factory(Platform arch)
{
switch (arch)
{
#if defined(HAVE_LLVM)
case Platform::x86_64:
return std::make_unique<HostDisassemblerLLVM>("x86_64-none-unknown");
case Platform::aarch64:
return std::make_unique<HostDisassemblerLLVM>("aarch64-none-unknown", "cortex-a57", 4);
#elif defined(_M_X86_64)
case Platform::x86_64:
return std::make_unique<HostDisassemblerBochs>();
#endif
default:
return std::make_unique<HostDisassembler>();
}
}

void HostDisassembler::Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count)
{
instruction_count = 0;
return fmt::println(stream, "{}\t{:02x}", fmt::ptr(begin), fmt::join(std::span{begin, end}, ""));
}

void HostDisassembler::Disassemble(const u8* begin, const u8* end, std::ostream& stream)
{
std::size_t instruction_count;
Disassemble(begin, end, stream, instruction_count);
}

std::string HostDisassembler::Disassemble(const u8* begin, const u8* end)
{
std::ostringstream stream;
Disassemble(begin, end, stream);
return std::move(stream).str();
}
30 changes: 30 additions & 0 deletions Source/Core/Common/HostDisassembler.h
@@ -0,0 +1,30 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <cstddef>
#include <iosfwd>
#include <memory>
#include <string>

#include "Common/CommonTypes.h"

class HostDisassembler
{
public:
enum class Platform
{
x86_64,
aarch64,
};

virtual ~HostDisassembler() = default;

static std::unique_ptr<HostDisassembler> Factory(Platform arch);

virtual void Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count);
void Disassemble(const u8* begin, const u8* end, std::ostream& stream);
std::string Disassemble(const u8* begin, const u8* end);
};
21 changes: 21 additions & 0 deletions Source/Core/Common/Unreachable.h
@@ -0,0 +1,21 @@
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "Common/CommonFuncs.h"

namespace Common
{
// TODO C++23: Replace with std::unreachable.
[[noreturn]] inline void Unreachable()
{
#ifdef _DEBUG
Crash();
#elif defined(_MSC_VER) && !defined(__clang__)
__assume(false);
#else
__builtin_unreachable();
#endif
}
} // namespace Common
5 changes: 0 additions & 5 deletions Source/Core/Core/CMakeLists.txt
Expand Up @@ -650,11 +650,6 @@ PRIVATE
ZLIB::ZLIB
)

if ((DEFINED CMAKE_ANDROID_ARCH_ABI AND CMAKE_ANDROID_ARCH_ABI MATCHES "x86|x86_64") OR
(NOT DEFINED CMAKE_ANDROID_ARCH_ABI AND _M_X86_64))
target_link_libraries(core PRIVATE bdisasm)
endif()

if (APPLE)
target_link_libraries(core
PRIVATE
Expand Down
5 changes: 5 additions & 0 deletions Source/Core/Core/HLE/HLE.cpp
Expand Up @@ -195,6 +195,11 @@ u32 GetHookByFunctionAddress(PPCSymbolDB& ppc_symbol_db, u32 address)
return (symbol && symbol->address == address) ? index : 0;
}

const char* GetHookNameByIndex(u32 index)
{
return os_patches[index].name;
}

HookType GetHookTypeByIndex(u32 index)
{
return os_patches[index].type;
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/HLE/HLE.h
Expand Up @@ -69,6 +69,7 @@ void ExecuteFromJIT(u32 current_pc, u32 hook_index, Core::System& system);
u32 GetHookByAddress(u32 address);
// Returns the HLE hook index if the address matches the function start
u32 GetHookByFunctionAddress(PPCSymbolDB& ppc_symbol_db, u32 address);
const char* GetHookNameByIndex(u32 index);
HookType GetHookTypeByIndex(u32 index);
HookFlag GetHookFlagsByIndex(u32 index);

Expand Down
2 changes: 2 additions & 0 deletions Source/Core/Core/Host.h
Expand Up @@ -59,6 +59,8 @@ void Host_PPCSymbolsChanged();
void Host_RefreshDSPDebuggerWindow();
void Host_RequestRenderWindowSize(int width, int height);
void Host_UpdateDisasmDialog();
void Host_JitCacheCleared();
void Host_JitProfileDataWiped();
void Host_UpdateMainFrame();
void Host_UpdateTitle(const std::string& title);
void Host_YieldToUI();
Expand Down

0 comments on commit 1566098

Please sign in to comment.