LLVM: enable some JIT events (Intel, Perf)

Made some related adjustments.
Currently incomplete.
This commit is contained in:
Nekotekina
2021-12-24 20:33:32 +03:00
parent 510041a873
commit d836033212
16 changed files with 233 additions and 162 deletions
+50 -4
View File
@@ -16,6 +16,15 @@
LOG_CHANNEL(jit_log, "JIT");
void jit_announce(uptr func, usz size, std::string_view name)
{
#ifdef __linux__
static const fs::file s_map(fmt::format("/tmp/perf-%d.map", getpid()), fs::rewrite + fs::append);
s_map.write(fmt::format("%x %x %s\n", func, size, name));
#endif
}
static u8* get_jit_memory()
{
// Reserve 2G memory (magic static)
@@ -230,7 +239,7 @@ asmjit::Runtime& asmjit::get_global_runtime()
return asmjit::kErrorNoCodeGenerated;
}
void* p = m_pos.fetch_add(utils::align(codeSize, 4096));
void* p = m_pos.fetch_add(utils::align(codeSize, 64));
if (!p || m_pos > m_max) [[unlikely]]
{
*dst = nullptr;
@@ -245,7 +254,6 @@ asmjit::Runtime& asmjit::get_global_runtime()
return asmjit::kErrorInvalidState;
}
utils::memory_protect(p, utils::align(codeSize, 4096), utils::protection::rx);
flush(p, relocSize);
*dst = p;
@@ -331,6 +339,9 @@ asmjit::inline_runtime::~inline_runtime()
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolSize.h"
#ifdef _MSC_VER
#pragma warning(pop)
#else
@@ -386,7 +397,7 @@ static u64 make_null_function(const std::string& name)
using namespace asmjit;
// Build a "null" function that contains its name
const auto func = build_function_asm<void (*)()>([&](X86Assembler& c, auto& args)
const auto func = build_function_asm<void (*)()>("NULL", [&](X86Assembler& c, auto& args)
{
Label data = c.newLabel();
c.lea(args[0], x86::qword_ptr(data, 0));
@@ -406,6 +417,34 @@ static u64 make_null_function(const std::string& name)
}
}
struct JITAnnouncer : llvm::JITEventListener
{
void notifyObjectLoaded(u64, const llvm::object::ObjectFile& obj, const llvm::RuntimeDyld::LoadedObjectInfo& info) override
{
using namespace llvm;
object::OwningBinary<object::ObjectFile> debug_obj_ = info.getObjectForDebug(obj);
const object::ObjectFile& debug_obj = *debug_obj_.getBinary();
for (const auto& [sym, size] : computeSymbolSizes(debug_obj))
{
Expected<object::SymbolRef::Type> type_ = sym.getType();
if (!type_ || *type_ != object::SymbolRef::ST_Function)
continue;
Expected<StringRef> name = sym.getName();
if (!name)
continue;
Expected<u64> addr = sym.getAddress();
if (!addr)
continue;
jit_announce(*addr, size, {name->data(), name->size()});
}
}
};
// Simple memory manager
struct MemoryManager1 : llvm::RTDyldMemoryManager
{
@@ -429,7 +468,8 @@ struct MemoryManager1 : llvm::RTDyldMemoryManager
~MemoryManager1() override
{
utils::memory_release(ptr, c_max_size * 2);
// Hack: don't release to prevent reuse of address space, see jit_announce
utils::memory_decommit(ptr, c_max_size * 2);
}
llvm::JITSymbol findSymbol(const std::string& name) override
@@ -812,6 +852,12 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, co
}
}
if (!_link.empty() || !(flags & 0x1))
{
m_engine->RegisterJITEventListener(llvm::JITEventListener::createIntelJITEventListener());
m_engine->RegisterJITEventListener(new JITAnnouncer);
}
if (!m_engine)
{
fmt::throw_exception("LLVM: Failed to create ExecutionEngine: %s", result);
+16 -4
View File
@@ -34,6 +34,13 @@
#include <string_view>
#include <unordered_map>
void jit_announce(uptr func, usz size, std::string_view name);
void jit_announce(auto* func, usz size, std::string_view name)
{
jit_announce(uptr(func), size, name);
}
enum class jit_class
{
ppu_code,
@@ -161,7 +168,7 @@ namespace asmjit
// Build runtime function with asmjit::X86Assembler
template <typename FT, typename F>
inline FT build_function_asm(F&& builder)
inline FT build_function_asm(std::string_view name, F&& builder)
{
using namespace asmjit;
@@ -195,6 +202,7 @@ inline FT build_function_asm(F&& builder)
return nullptr;
}
jit_announce(result, code.getCodeSize(), name);
return result;
}
@@ -210,8 +218,8 @@ public:
built_function& operator=(const built_function&) = delete;
template <typename F>
built_function(F&& builder)
: m_func(ensure(build_function_asm<FT>(std::forward<F>(builder))))
built_function(std::string_view name, F&& builder)
: m_func(ensure(build_function_asm<FT>(name, std::forward<F>(builder))))
{
}
@@ -238,7 +246,7 @@ public:
built_function& operator=(const built_function&) = delete;
template <typename F>
built_function(F&& builder)
built_function(std::string_view name, F&& builder)
{
using namespace asmjit;
@@ -270,6 +278,10 @@ public:
{
ensure(false);
}
else
{
jit_announce(result, code.getCodeSize(), name);
}
}
operator FT() const noexcept
+1 -1
View File
@@ -2190,7 +2190,7 @@ thread_base::native_entry thread_base::finalize(u64 _self) noexcept
thread_base::native_entry thread_base::make_trampoline(u64(*entry)(thread_base* _base))
{
return build_function_asm<native_entry>([&](asmjit::X86Assembler& c, auto& args)
return build_function_asm<native_entry>("thread_base_trampoline", [&](asmjit::X86Assembler& c, auto& args)
{
using namespace asmjit;