mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 00:41:26 +12:00
SPU Recompiler: optimize JIT memory consumption
Avoid rebuilding trampoline for every function at startup. This should fix Out of Memory error in some cases.
This commit is contained in:
parent
95b6883ad4
commit
1b140c8e97
2 changed files with 36 additions and 12 deletions
|
@ -463,6 +463,9 @@ void spu_cache::initialize()
|
||||||
|
|
||||||
if (compilers.size() && !func_list.empty())
|
if (compilers.size() && !func_list.empty())
|
||||||
{
|
{
|
||||||
|
LOG_NOTICE(SPU, "SPU Runtime: Building trampoline...");
|
||||||
|
spu_runtime::g_dispatcher[0] = compilers[0]->get_runtime().rebuild_ubertrampoline();
|
||||||
|
|
||||||
LOG_SUCCESS(SPU, "SPU Runtime: Built %u functions.", func_list.size());
|
LOG_SUCCESS(SPU, "SPU Runtime: Built %u functions.", func_list.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,6 +567,26 @@ bool spu_runtime::add(u64 last_reset_count, void* _where, spu_function_t compile
|
||||||
// Register function in PIC map
|
// Register function in PIC map
|
||||||
m_pic_map[{func.data() + _off, func.size() - _off}] = compiled;
|
m_pic_map[{func.data() + _off, func.size() - _off}] = compiled;
|
||||||
|
|
||||||
|
if (fxm::check_unlocked<spu_cache>())
|
||||||
|
{
|
||||||
|
// Rebuild trampolines if necessary
|
||||||
|
if (const auto new_tr = rebuild_ubertrampoline())
|
||||||
|
{
|
||||||
|
g_dispatcher[0] = new_tr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify in lock destructor
|
||||||
|
lock.notify = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
spu_function_t spu_runtime::rebuild_ubertrampoline()
|
||||||
|
{
|
||||||
// Prepare sorted list
|
// Prepare sorted list
|
||||||
m_flat_list.clear();
|
m_flat_list.clear();
|
||||||
m_flat_list.assign(m_pic_map.cbegin(), m_pic_map.cend());
|
m_flat_list.assign(m_pic_map.cbegin(), m_pic_map.cend());
|
||||||
|
@ -586,18 +609,14 @@ bool spu_runtime::add(u64 last_reset_count, void* _where, spu_function_t compile
|
||||||
const auto _end = m_flat_list.end();
|
const auto _end = m_flat_list.end();
|
||||||
const u32 size0 = ::size32(m_flat_list);
|
const u32 size0 = ::size32(m_flat_list);
|
||||||
|
|
||||||
if (size0 == 1)
|
if (size0 != 1)
|
||||||
{
|
|
||||||
g_dispatcher[0] = compiled;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// Allocate some writable executable memory
|
// Allocate some writable executable memory
|
||||||
u8* const wxptr = jit_runtime::alloc(size0 * 22 + 14, 16);
|
u8* const wxptr = jit_runtime::alloc(size0 * 22 + 14, 16);
|
||||||
|
|
||||||
if (!wxptr)
|
if (!wxptr)
|
||||||
{
|
{
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raw assembly pointer
|
// Raw assembly pointer
|
||||||
|
@ -728,7 +747,7 @@ bool spu_runtime::add(u64 last_reset_count, void* _where, spu_function_t compile
|
||||||
if (w.level >= w.beg->first.size() || w.level >= it->first.size())
|
if (w.level >= w.beg->first.size() || w.level >= it->first.size())
|
||||||
{
|
{
|
||||||
// If functions cannot be compared, assume smallest function
|
// If functions cannot be compared, assume smallest function
|
||||||
LOG_ERROR(SPU, "Trampoline simplified at 0x%x (level=%u)", func[0], w.level);
|
LOG_ERROR(SPU, "Trampoline simplified at ??? (level=%u)", w.level);
|
||||||
make_jump(0xe9, w.beg->second); // jmp rel32
|
make_jump(0xe9, w.beg->second); // jmp rel32
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -760,7 +779,7 @@ bool spu_runtime::add(u64 last_reset_count, void* _where, spu_function_t compile
|
||||||
|
|
||||||
if (it == m_flat_list.end())
|
if (it == m_flat_list.end())
|
||||||
{
|
{
|
||||||
LOG_ERROR(SPU, "Trampoline simplified (II) at 0x%x (level=%u)", func[0], w.level);
|
LOG_ERROR(SPU, "Trampoline simplified (II) at ??? (level=%u)", w.level);
|
||||||
make_jump(0xe9, w.beg->second); // jmp rel32
|
make_jump(0xe9, w.beg->second); // jmp rel32
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -871,12 +890,11 @@ bool spu_runtime::add(u64 last_reset_count, void* _where, spu_function_t compile
|
||||||
}
|
}
|
||||||
|
|
||||||
workload.clear();
|
workload.clear();
|
||||||
g_dispatcher[0] = reinterpret_cast<spu_function_t>(reinterpret_cast<u64>(wxptr));
|
return reinterpret_cast<spu_function_t>(reinterpret_cast<u64>(wxptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify in lock destructor
|
// No trampoline required
|
||||||
lock.notify = true;
|
return beg->second;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* spu_runtime::find(u64 last_reset_count, const std::vector<u32>& func)
|
void* spu_runtime::find(u64 last_reset_count, const std::vector<u32>& func)
|
||||||
|
|
|
@ -84,6 +84,12 @@ public:
|
||||||
// Add compiled function and generate trampoline if necessary
|
// Add compiled function and generate trampoline if necessary
|
||||||
bool add(u64 last_reset_count, void* where, spu_function_t compiled);
|
bool add(u64 last_reset_count, void* where, spu_function_t compiled);
|
||||||
|
|
||||||
|
private:
|
||||||
|
spu_function_t rebuild_ubertrampoline();
|
||||||
|
|
||||||
|
friend class spu_cache;
|
||||||
|
public:
|
||||||
|
|
||||||
// Return opaque pointer for add()
|
// Return opaque pointer for add()
|
||||||
void* find(u64 last_reset_count, const std::vector<u32>&);
|
void* find(u64 last_reset_count, const std::vector<u32>&);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue