diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 9a0d508f4c..ef0df028d4 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -6,6 +6,7 @@ set(SRCS BreakPoints.cpp GekkoDisassembler.cpp Hash.cpp IniFile.cpp + JitRegister.cpp MathUtil.cpp MemArena.cpp MemoryUtil.cpp diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 5d7a31904d..8b192642b5 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -62,6 +62,7 @@ + @@ -97,6 +98,7 @@ + diff --git a/Source/Core/Common/JitRegister.cpp b/Source/Core/Common/JitRegister.cpp new file mode 100644 index 0000000000..3dafaac5d7 --- /dev/null +++ b/Source/Core/Common/JitRegister.cpp @@ -0,0 +1,115 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include + +#include "Common/CommonTypes.h" +#include "Common/FileUtil.h" +#include "Common/JitRegister.h" +#include "Common/StringUtil.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +#if defined USE_OPROFILE && USE_OPROFILE +#include +#endif + +#if defined USE_VTUNE +#include +#pragma comment(lib, "libittnotify.lib") +#pragma comment(lib, "jitprofiling.lib") +#endif + +#if defined USE_OPROFILE && USE_OPROFILE +static op_agent_t s_agent = nullptr; +#endif + +static File::IOFile s_perf_map_file; + +namespace JitRegister +{ + +void Init() +{ +#if defined USE_OPROFILE && USE_OPROFILE + s_agent = op_open_agent(); +#endif + + const char* perf_dir = getenv("DOLPHIN_PERF_DIR"); + if (perf_dir && perf_dir[0]) + { + std::string filename = StringFromFormat("%s/perf-%d.map", perf_dir, getpid()); + s_perf_map_file.Open(filename, "w"); + // Disable buffering in order to avoid missing some mappings + // if the event of a crash: + std::setvbuf(s_perf_map_file.GetHandle(), NULL, _IONBF, 0); + } +} + +void Shutdown() +{ +#if defined USE_OPROFILE && USE_OPROFILE + op_close_agent(s_agent); + s_agent = nullptr; +#endif + +#ifdef USE_VTUNE + iJIT_NotifyEvent(iJVM_EVENT_TYPE_SHUTDOWN, nullptr); +#endif + + if (s_perf_map_file.IsOpen()) + s_perf_map_file.Close(); +} + +void Register(const void* base_address, u32 code_size, + const char* name, u32 original_address) +{ +#if !(defined USE_OPROFILE && USE_OPROFILE) && !defined(USE_VTUNE) + if (!s_perf_map_file.IsOpen()) + return; +#endif + + std::string symbol_name; + if (original_address) + symbol_name = StringFromFormat("%s_%x", name, original_address); + else + symbol_name = name; + +#if defined USE_OPROFILE && USE_OPROFILE + op_write_native_code(s_agent, symbol_name.data(), (u64)base_address, + base_address, code_size); +#endif + +#ifdef USE_VTUNE + iJIT_Method_Load jmethod = {0}; + jmethod.method_id = iJIT_GetNewMethodID(); + jmethod.class_file_name = ""; + jmethod.source_file_name = __FILE__; + jmethod.method_load_address = base_address; + jmethod.method_size = code_size; + jmethod.line_number_size = 0; + jmethod.method_name = symbol_name.data(); + iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod); +#endif + + // Linux perf /tmp/perf-$pid.map: + if (s_perf_map_file.IsOpen()) + { + std::string entry = StringFromFormat( + "%" PRIx64 " %x %s\n", + (u64)base_address, code_size, symbol_name.data()); + s_perf_map_file.WriteBytes(entry.data(), entry.size()); + } +} + +} diff --git a/Source/Core/Common/JitRegister.h b/Source/Core/Common/JitRegister.h new file mode 100644 index 0000000000..68e2687d8b --- /dev/null +++ b/Source/Core/Common/JitRegister.h @@ -0,0 +1,15 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +namespace JitRegister +{ + +void Init(); +void Shutdown(); +void Register(const void* base_address, u32 code_size, + const char* name, u32 original_address=0); + +} diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index 0c680dc020..e9b0f52961 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -9,17 +9,10 @@ // performance hit, it's not enabled by default, but it's useful for // locating performance issues. -#include - -#ifdef _WIN32 -#include -#else -#include -#endif - #include "disasm.h" #include "Common/CommonTypes.h" +#include "Common/JitRegister.h" #include "Common/MemoryUtil.h" #include "Core/PowerPC/JitInterface.h" #include "Core/PowerPC/JitCommon/JitBase.h" @@ -28,18 +21,6 @@ #include #endif -#if defined USE_OPROFILE && USE_OPROFILE -#include - -op_agent_t agent; -#endif - -#if defined USE_VTUNE -#include -#pragma comment(lib, "libittnotify.lib") -#pragma comment(lib, "jitprofiling.lib") -#endif - using namespace Gen; bool JitBaseBlockCache::IsFull() const @@ -55,17 +36,7 @@ using namespace Gen; return; } -#if defined USE_OPROFILE && USE_OPROFILE - agent = op_open_agent(); -#endif - - const char* perf_dir = getenv("DOLPHIN_PERF_DIR"); - if (perf_dir && perf_dir[0]) - { - std::string filename = StringFromFormat("%s/perf-%d.map", - perf_dir, getpid()); - m_perf_map_file.open(filename, std::ios::trunc); - } + JitRegister::Init(); iCache.fill(JIT_ICACHE_INVALID_BYTE); iCacheEx.fill(JIT_ICACHE_INVALID_BYTE); @@ -79,16 +50,8 @@ using namespace Gen; { num_blocks = 0; m_initialized = false; -#if defined USE_OPROFILE && USE_OPROFILE - op_close_agent(agent); -#endif -#ifdef USE_VTUNE - iJIT_NotifyEvent(iJVM_EVENT_TYPE_SHUTDOWN, nullptr); -#endif - - if (m_perf_map_file.is_open()) - m_perf_map_file.close(); + JitRegister::Shutdown(); } // This clears the JIT cache. It's called from JitCache.cpp when the JIT cache @@ -178,34 +141,8 @@ using namespace Gen; LinkBlockExits(block_num); } -#if defined USE_OPROFILE && USE_OPROFILE - char buf[100]; - sprintf(buf, "EmuCode%x", b.originalAddress); - const u8* blockStart = blockCodePointers[block_num]; - op_write_native_code(agent, buf, (uint64_t)blockStart, - blockStart, b.codeSize); -#endif - -#ifdef USE_VTUNE - sprintf(b.blockName, "EmuCode_0x%08x", b.originalAddress); - - iJIT_Method_Load jmethod = {0}; - jmethod.method_id = iJIT_GetNewMethodID(); - jmethod.class_file_name = ""; - jmethod.source_file_name = __FILE__; - jmethod.method_load_address = (void*)blockCodePointers[block_num]; - jmethod.method_size = b.codeSize; - jmethod.line_number_size = 0; - jmethod.method_name = b.blockName; - iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod); -#endif - - if (m_perf_map_file.is_open()) - { - m_perf_map_file << StringFromFormat( - "%" PRIx64 " %x EmuCode_%x\n", - (u64)blockCodePointers[block_num], b.codeSize, b.originalAddress); - } + JitRegister::Register(blockCodePointers[block_num], b.codeSize, + "JIT_PPC", b.originalAddress); } const u8 **JitBaseBlockCache::GetCodePointers() diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h index d53fa16d43..21984c8a70 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -57,10 +56,6 @@ struct JitBlock u64 ticStart; // for profiling - time. u64 ticStop; // for profiling - time. u64 ticCounter; // for profiling - time. - -#ifdef USE_VTUNE - char blockName[32]; -#endif }; typedef void (*CompiledCode)(); @@ -120,8 +115,6 @@ class JitBaseBlockCache bool m_initialized; - std::ofstream m_perf_map_file; - bool RangeIntersect(int s1, int e1, int s2, int e2) const; void LinkBlockExits(int i); void LinkBlock(int i);