mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-08 16:01:42 +12:00
PPU/LLVM: Fix recursive call crashing llvm backend
This commit is contained in:
parent
fd5fbab115
commit
53769ae1bd
2 changed files with 16 additions and 8 deletions
|
@ -296,9 +296,9 @@ const Executable *RecompilationEngine::GetExecutable(u32 address, bool isFunctio
|
||||||
return isFunction ? &executeFunc : &executeUntilReturn;
|
return isFunction ? &executeFunc : &executeUntilReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::mutex* RecompilationEngine::GetMutexForAddress(u32 address) {
|
std::pair<std::mutex, std::atomic<int> >* RecompilationEngine::GetMutexAndCounterForAddress(u32 address) {
|
||||||
std::lock_guard<std::mutex> lock(m_address_locks_lock);
|
std::lock_guard<std::mutex> lock(m_address_locks_lock);
|
||||||
std::unordered_map<u32, std::mutex>::iterator It = m_address_locks.find(address);
|
std::unordered_map<u32, std::pair<std::mutex, std::atomic<int>> >::iterator It = m_address_locks.find(address);
|
||||||
if (It == m_address_locks.end())
|
if (It == m_address_locks.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &(It->second);
|
return &(It->second);
|
||||||
|
@ -549,14 +549,18 @@ void RecompilationEngine::CompileBlock(BlockEntry & block_entry) {
|
||||||
std::get<1>(m_address_to_function[block_entry.cfg.start_address]) = nullptr;
|
std::get<1>(m_address_to_function[block_entry.cfg.start_address]) = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<u32, std::mutex>::iterator It2 = m_address_locks.find(block_entry.cfg.start_address);
|
std::unordered_map<u32, std::pair<std::mutex, std::atomic<int>> >::iterator It2 = m_address_locks.find(block_entry.cfg.start_address);
|
||||||
if (It2 == m_address_locks.end())
|
if (It2 == m_address_locks.end())
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_address_locks_lock);
|
std::lock_guard<std::mutex> lock(m_address_locks_lock);
|
||||||
(void)m_address_locks[block_entry.cfg.start_address];
|
(void)m_address_locks[block_entry.cfg.start_address];
|
||||||
|
m_address_locks[block_entry.cfg.start_address].second.store(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(m_address_locks[block_entry.cfg.start_address]);
|
std::lock_guard<std::mutex> lock(m_address_locks[block_entry.cfg.start_address].first);
|
||||||
|
|
||||||
|
while (m_address_locks[block_entry.cfg.start_address].second.load() > 0)
|
||||||
|
std::this_thread::yield();
|
||||||
|
|
||||||
std::get<1>(m_address_to_function[block_entry.cfg.start_address]) = std::unique_ptr<llvm::ExecutionEngine>(compileResult.second);
|
std::get<1>(m_address_to_function[block_entry.cfg.start_address]) = std::unique_ptr<llvm::ExecutionEngine>(compileResult.second);
|
||||||
std::get<0>(m_address_to_function[block_entry.cfg.start_address]) = compileResult.first;
|
std::get<0>(m_address_to_function[block_entry.cfg.start_address]) = compileResult.first;
|
||||||
|
@ -706,13 +710,17 @@ u32 ppu_recompiler_llvm::CPUHybridDecoderRecompiler::ExecuteTillReturn(PPUThread
|
||||||
execution_engine->m_tracer.Trace(Tracer::TraceType::ExitFromCompiledFunction, context >> 32, context & 0xFFFFFFFF);
|
execution_engine->m_tracer.Trace(Tracer::TraceType::ExitFromCompiledFunction, context >> 32, context & 0xFFFFFFFF);
|
||||||
|
|
||||||
while (PollStatus(ppu_state) == false) {
|
while (PollStatus(ppu_state) == false) {
|
||||||
std::mutex *mut = execution_engine->m_recompilation_engine->GetMutexForAddress(ppu_state->PC);
|
std::pair<std::mutex, std::atomic<int>> *mut = execution_engine->m_recompilation_engine->GetMutexAndCounterForAddress(ppu_state->PC);
|
||||||
if (mut) {
|
if (mut) {
|
||||||
std::lock_guard<std::mutex> lock(*mut);
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mut->first);
|
||||||
|
mut->second.fetch_add(1);
|
||||||
|
}
|
||||||
const Executable *executable = execution_engine->m_recompilation_engine->GetCompiledExecutableIfAvailable(ppu_state->PC);
|
const Executable *executable = execution_engine->m_recompilation_engine->GetCompiledExecutableIfAvailable(ppu_state->PC);
|
||||||
auto entry = ppu_state->PC;
|
auto entry = ppu_state->PC;
|
||||||
u32 exit = (u32)(*executable)(ppu_state, 0);
|
u32 exit = (u32)(*executable)(ppu_state, 0);
|
||||||
execution_engine->m_tracer.Trace(Tracer::TraceType::ExitFromCompiledBlock, entry, exit);
|
execution_engine->m_tracer.Trace(Tracer::TraceType::ExitFromCompiledBlock, entry, exit);
|
||||||
|
mut->second.fetch_sub(1);
|
||||||
if (exit == 0)
|
if (exit == 0)
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1012,7 +1012,7 @@ namespace ppu_recompiler_llvm {
|
||||||
/**
|
/**
|
||||||
* Get a mutex for an address. Used to avoid modifying a block currently in execution.
|
* Get a mutex for an address. Used to avoid modifying a block currently in execution.
|
||||||
**/
|
**/
|
||||||
std::mutex* GetMutexForAddress(u32 address);
|
std::pair<std::mutex, std::atomic<int> >* GetMutexAndCounterForAddress(u32 address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the executable for the specified address if a compiled version is
|
* Get the executable for the specified address if a compiled version is
|
||||||
|
@ -1107,7 +1107,7 @@ namespace ppu_recompiler_llvm {
|
||||||
typedef std::tuple<Executable, std::unique_ptr<llvm::ExecutionEngine>, u32> ExecutableStorage;
|
typedef std::tuple<Executable, std::unique_ptr<llvm::ExecutionEngine>, u32> ExecutableStorage;
|
||||||
/// Address to ordinal cahce. Key is address.
|
/// Address to ordinal cahce. Key is address.
|
||||||
std::unordered_map<u32, ExecutableStorage> m_address_to_function;
|
std::unordered_map<u32, ExecutableStorage> m_address_to_function;
|
||||||
std::unordered_map<u32, std::mutex> m_address_locks;
|
std::unordered_map<u32, std::pair<std::mutex, std::atomic<int> > > m_address_locks;
|
||||||
|
|
||||||
/// The time at which the m_address_to_ordinal cache was last cleared
|
/// The time at which the m_address_to_ordinal cache was last cleared
|
||||||
std::chrono::high_resolution_clock::time_point m_last_cache_clear_time;
|
std::chrono::high_resolution_clock::time_point m_last_cache_clear_time;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue