PPU LLVM: implement ppu_finalize

Properly free certain compiled PRX/OVL modules (except dev_flash)
This commit is contained in:
Nekotekina 2021-01-27 16:08:43 +03:00
parent 15ed963a29
commit 53267e283b
4 changed files with 87 additions and 20 deletions

View File

@ -110,6 +110,7 @@ const ppu_decoder<ppu_interpreter_fast> g_ppu_interpreter_fast;
const ppu_decoder<ppu_itype> g_ppu_itype; const ppu_decoder<ppu_itype> g_ppu_itype;
extern void ppu_initialize(); extern void ppu_initialize();
extern void ppu_finalize(const ppu_module& info);
extern void ppu_initialize(const ppu_module& info); extern void ppu_initialize(const ppu_module& info);
static void ppu_initialize2(class jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name); static void ppu_initialize2(class jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name);
extern void ppu_execute_syscall(ppu_thread& ppu, u64 code); extern void ppu_execute_syscall(ppu_thread& ppu, u64 code);
@ -1921,6 +1922,83 @@ extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value)
return ppu_store_reservation<u64>(ppu, addr, reg_value); return ppu_store_reservation<u64>(ppu, addr, reg_value);
} }
#ifdef LLVM_AVAILABLE
namespace
{
// Compiled PPU module info
struct jit_module
{
std::vector<u64*> vars;
std::vector<ppu_function_t> funcs;
std::shared_ptr<jit_compiler> pjit;
};
struct jit_module_manager
{
shared_mutex mutex;
std::unordered_map<std::string, jit_module> map;
jit_module& get(const std::string& name)
{
std::lock_guard lock(mutex);
return map.emplace(name, jit_module{}).first->second;
}
void remove(const std::string& name) noexcept
{
std::lock_guard lock(mutex);
const auto found = map.find(name);
if (found == map.end()) [[unlikely]]
{
ppu_log.error("Failed to remove module %s", name);
return;
}
map.erase(found);
}
};
}
#endif
extern void ppu_finalize(const ppu_module& info)
{
// Get cache path for this executable
std::string cache_path;
if (info.name.empty())
{
// Don't remove main module from memory
return;
}
else
{
// Get PPU cache location
cache_path = fs::get_cache_dir() + "cache/";
const std::string dev_flash = vfs::get("/dev_flash/");
if (info.path.starts_with(dev_flash) || Emu.GetCat() == "1P")
{
// Don't remove dev_flash prx from memory
return;
}
else if (!Emu.GetTitleID().empty())
{
cache_path += Emu.GetTitleID();
cache_path += '/';
}
// Add PPU hash and filename
fmt::append(cache_path, "ppu-%s-%s/", fmt::base57(info.sha1), info.path.substr(info.path.find_last_of('/') + 1));
}
#ifdef LLVM_AVAILABLE
g_fxo->get<jit_module_manager>()->remove(cache_path + info.name);
#endif
}
extern void ppu_initialize() extern void ppu_initialize()
{ {
const auto _main = g_fxo->get<ppu_module>(); const auto _main = g_fxo->get<ppu_module>();
@ -2056,14 +2134,6 @@ extern void ppu_initialize(const ppu_module& info)
// Initialize progress dialog // Initialize progress dialog
g_progr = "Compiling PPU modules..."; g_progr = "Compiling PPU modules...";
// Compiled PPU module info
struct jit_module
{
std::vector<u64*> vars;
std::vector<ppu_function_t> funcs;
std::shared_ptr<jit_compiler> pjit;
};
struct jit_core_allocator struct jit_core_allocator
{ {
const s32 thread_count = g_cfg.core.llvm_threads ? std::min<s32>(g_cfg.core.llvm_threads, limit()) : limit(); const s32 thread_count = g_cfg.core.llvm_threads ? std::min<s32>(g_cfg.core.llvm_threads, limit()) : limit();
@ -2077,18 +2147,6 @@ extern void ppu_initialize(const ppu_module& info)
} }
}; };
struct jit_module_manager
{
shared_mutex mutex;
std::unordered_map<std::string, jit_module> map;
jit_module& get(const std::string& name)
{
std::lock_guard lock(mutex);
return map.emplace(name, jit_module{}).first->second;
}
};
// Permanently loaded compiled PPU modules (name -> data) // Permanently loaded compiled PPU modules (name -> data)
jit_module& jit_mod = g_fxo->get<jit_module_manager>()->get(cache_path + info.name); jit_module& jit_mod = g_fxo->get<jit_module_manager>()->get(cache_path + info.name);

View File

@ -15,6 +15,7 @@
extern std::shared_ptr<lv2_overlay> ppu_load_overlay(const ppu_exec_object&, const std::string& path); extern std::shared_ptr<lv2_overlay> ppu_load_overlay(const ppu_exec_object&, const std::string& path);
extern void ppu_initialize(const ppu_module&); extern void ppu_initialize(const ppu_module&);
extern void ppu_finalize(const ppu_module&);
LOG_CHANNEL(sys_overlay); LOG_CHANNEL(sys_overlay);
@ -118,5 +119,7 @@ error_code sys_overlay_unload_module(u32 ovlmid)
vm::dealloc(seg.addr); vm::dealloc(seg.addr);
} }
ppu_finalize(*_main);
return CELL_OK; return CELL_OK;
} }

View File

@ -18,6 +18,7 @@
extern std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object&, const std::string&); extern std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object&, const std::string&);
extern void ppu_unload_prx(const lv2_prx& prx); extern void ppu_unload_prx(const lv2_prx& prx);
extern void ppu_initialize(const ppu_module&); extern void ppu_initialize(const ppu_module&);
extern void ppu_finalize(const ppu_module&);
LOG_CHANNEL(sys_prx); LOG_CHANNEL(sys_prx);
@ -590,6 +591,8 @@ error_code _sys_prx_unload_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sy
ppu_unload_prx(*prx); ppu_unload_prx(*prx);
ppu_finalize(*prx);
//s32 result = prx->exit ? prx->exit() : CELL_OK; //s32 result = prx->exit ? prx->exit() : CELL_OK;
return CELL_OK; return CELL_OK;

View File

@ -69,6 +69,7 @@ atomic_t<u64> g_watchdog_hold_ctr{0};
extern void ppu_load_exec(const ppu_exec_object&); extern void ppu_load_exec(const ppu_exec_object&);
extern void spu_load_exec(const spu_exec_object&); extern void spu_load_exec(const spu_exec_object&);
extern void ppu_initialize(const ppu_module&); extern void ppu_initialize(const ppu_module&);
extern void ppu_finalize(const ppu_module&);
extern void ppu_unload_prx(const lv2_prx&); extern void ppu_unload_prx(const lv2_prx&);
extern std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object&, const std::string&); extern std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object&, const std::string&);
@ -1227,6 +1228,8 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
idm::remove<lv2_obj, lv2_prx>(idm::last_id()); idm::remove<lv2_obj, lv2_prx>(idm::last_id());
lock.lock(); lock.lock();
ppu_unload_prx(*prx); ppu_unload_prx(*prx);
lock.unlock();
ppu_finalize(*prx);
g_progr_fdone++; g_progr_fdone++;
continue; continue;
} }