LLJIT执行引擎:ExecutionSession与JITDylib详解
LLJIT执行引擎:ExecutionSession与JITDylib详解
核心架构概览
LLJIT整体架构
graph TBA[ExecutionSession] --> B[JITDylib Manager]B --> C[Main JITDylib]B --> D[Custom JITDylib 1]B --> E[Custom JITDylib 2]C --> F[Symbol Table]D --> G[Symbol Table]E --> H[Symbol Table]A --> I[Layer Stack]I --> J[IRTransformLayer]J --> K[IRCompileLayer]K --> L[ObjectLinkingLayer]L --> M[MemoryManager]
ExecutionSession:JIT会话管理核心
基本概念与职责
ExecutionSession 是ORC JIT架构的中央协调器,负责管理整个JIT会话的生命周期和状态。
class ExecutionSession {
public:// JITDylib管理JITDylib& createJITDylib(std::string Name);JITDylib* getJITDylibByName(StringRef Name);// 符号查找Expected<JITEvaluatedSymbol> lookup(const JITDylibSearchList &SearchOrder,SymbolStringPtr Name);// 会话生命周期Error runJITDispatchTask(std::unique_ptr<Task> T);Error endSession();private:std::map<std::string, std::unique_ptr<JITDylib>> JITDylibs;std::unique_ptr<SymbolStringPool> SSP;SessionLock SessionLock;
};
创建ExecutionSession
方式1:通过LLJIT间接创建(推荐)
#include "llvm/ExecutionEngine/Orc/LLJIT.h"// 创建LLJIT实例,内部自动创建ExecutionSession
auto JIT = cantFail(LLJITBuilder().create());// 获取内部的ExecutionSession引用
ExecutionSession& ES = JIT->getExecutionSession();// 使用ExecutionSession
JITDylib& MainJD = JIT->getMainJITDylib();
方式2:直接创建ExecutionSession(高级用法)
#include "llvm/ExecutionEngine/Orc/ExecutionSession.h"// 直接创建ExecutionSession(需要手动管理生命周期)
auto ES = std::make_unique<ExecutionSession>(std::make_unique<SymbolStringPool>());// 手动创建JITDylib
JITDylib& JD = ES->createJITDylib("main");// 需要手动设置层栈和其他组件...
ExecutionSession的核心功能
符号查找与解析
// 构建搜索路径
JITDylibSearchOrder SearchOrder;
SearchOrder.push_back({&MainJD, JITDylibLookupFlags::MatchExportedSymbolsOnly});// 执行符号查找
auto Symbol = ES.lookup(SearchOrder, ES.intern("myFunction"));if (auto Err = Symbol.takeError()) {// 处理查找错误logAllUnhandledErrors(std::move(Err), errs());return;
}// 使用找到的符号
void(*FuncPtr)() = (void(*)())Symbol->getAddress();
FuncPtr();
并发任务调度
// 提交任务到JIT调度器
auto Task = std::make_unique<MyCustomTask>();
if (auto Err = ES.runJITDispatchTask(std::move(Task))) {// 处理任务提交错误
}
JITDylib:符号容器与管理
JITDylib是包含符号定义的容器。需要通过ExecutionSession来创建或获取JITDylib,并将你的符号添加到其中。
JITDylib架构设计
class JITDylib {
public:// 符号管理Error add(ResourceTrackerSP RT, std::unique_ptr<MaterializationUnit> MU);void setGenerator(JITDylib::GeneratorFunction G);// 依赖管理void addToLinkOrder(JITDylib &Other);void setFallbackDefinitionGenerator(JITDylib::GeneratorFunction G);// 查询接口JITDylibSearchOrder getSearchOrder();SymbolLookupSet getRequestedSymbols();private:SymbolTable Symbols;std::vector<JITDylib*> LinkOrder;std::unique_ptr<GeneratorFunction> Generator;
};
JITDylib的创建与管理
获取主JITDylib
// 通过LLJIT获取主JITDylib(最常用)
auto JIT = cantFail(LLJITBuilder().create());
JITDylib& MainJD = JIT->getMainJITDylib();// 主JITDylib已经预先配置了基本符号解析器
创建自定义JITDylib
// 创建新的JITDylib
JITDylib& MathLib = JIT->getExecutionSession().createJITDylib("math");// 设置库依赖关系(类似动态链接)
MathLib.addToLinkOrder(MainJD); // math库可以访问主库的符号// 创建具有特定搜索顺序的库
JITDylib& CustomLib = ES.createJITDylib("custom");
JITDylibSearchOrder CustomOrder;
CustomOrder.push_back({&CustomLib, JITDylibLookupFlags::MatchAllSymbols});
CustomOrder.push_back({&MainJD, JITDylibLookupFlags::MatchExportedSymbolsOnly});
符号解析策略配置
默认符号解析器
// LLJIT自动为主JITDylib配置的解析器包含:
// 1. JIT内部符号查找
// 2. 进程内符号查找(dlsym)
// 3. 标准库符号查找// 自定义解析器示例
auto CustomResolver = createSymbolResolver([](const SymbolMap &Symbols) -> Expected<SymbolMap> {SymbolMap Result;for (const auto &[Name, Sym] : Symbols) {// 自定义符号解析逻辑if (auto Addr = lookupInCustomLocation(Name)) {Result[Name] = JITEvaluatedSymbol(Addr, JITSymbolFlags::Exported);}}return Result;});MainJD.setGenerator(std::move(CustomResolver));
分层符号解析
// 创建多层符号解析策略
auto createLayeredResolver() {return [](JITDylib& JD, const SymbolNameSet& Names) {SymbolMap Result;SymbolNameSet Unresolved = Names;// 第一层:JIT内部查找for (const auto& Name : Names) {if (auto Sym = JD.lookup(Name)) {Result[Name] = *Sym;Unresolved.erase(Name);}}// 第二层:系统库查找for (const auto& Name : Unresolved) {if (auto Addr = sys::DynamicLibrary::SearchForAddressOfSymbol(Name)) {Result[Name] = JITEvaluatedSymbol(Addr, JITSymbolFlags::Exported);Unresolved.erase(Name);}}// 第三层:自定义查找if (!Unresolved.empty()) {// 处理剩余未解析符号handleUnresolvedSymbols(Unresolved);}return Result;};
}
完整的LLJIT初始化流程
标准初始化模式
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"Error initializeJIT() {// 1. 创建LLJIT构建器LLJITBuilder Builder;// 2. 配置JIT选项Builder.setJITTargetMachineBuilder(cantFail(JITTargetMachineBuilder::detectHost()));Builder.setNumCompileThreads(4); // 设置编译线程数// 3. 创建LLJIT实例auto JIT = cantFail(Builder.create());// 4. 获取ExecutionSession和主JITDylibExecutionSession& ES = JIT->getExecutionSession();JITDylib& MainJD = JIT->getMainJITDylib();// 5. 创建LLVM模块auto Ctx = std::make_unique<LLVMContext>();auto M = std::make_unique<Module>("MyModule", *Ctx);// 6. 生成IR内容// ... 填充模块内容 ...// 7. 创建线程安全模块ThreadSafeModule TSM(std::move(M), std::move(Ctx));// 8. 将模块添加到JITDylibif (auto Err = JIT->addIRModule(MainJD, std::move(TSM))) {return Err;}// 9. 查找并执行符号auto Addr = cantFail(JIT->lookup("main"));auto Main = Addr.toPtr<int(*)(void)>();return Main();
}
多JITDylib管理示例
class MultiLibraryJIT {std::unique_ptr<LLJIT> JIT;std::map<std::string, JITDylib*> Libraries;public:Error initialize() {// 创建JIT实例auto JITOrErr = LLJITBuilder().create();if (!JITOrErr) return JITOrErr.takeError();JIT = std::move(*JITOrErr);// 获取主库引用Libraries["main"] = &JIT->getMainJITDylib();return Error::success();}Error loadLibrary(const std::string& Name, ThreadSafeModule TSM) {// 创建新的JITDylibauto& JD = JIT->getExecutionSession().createJITDylib(Name);// 设置依赖关系:新库可以访问主库符号JD.addToLinkOrder(*Libraries["main"]);// 添加模块到新库if (auto Err = JIT->addIRModule(JD, std::move(TSM))) {return Err;}Libraries[Name] = &JD;return Error::success();}Expected<JITEvaluatedSymbol> lookup(const std::string& LibName, const std::string& SymbolName) {auto It = Libraries.find(LibName);if (It == Libraries.end()) {return make_error<StringError>("Library not found", inconvertibleErrorCode());}return JIT->lookup(*It->second, SymbolName);}
};
高级特性与最佳实践
资源管理与生命周期
资源跟踪器
// 创建资源跟踪器,用于管理模块生命周期
auto RT = MainJD.getDefaultResourceTracker();// 添加模块时指定资源跟踪器
if (auto Err = JIT->addIRModule(RT, std::move(TSM))) {// 处理错误
}// 移除模块释放资源
if (auto Err = RT->remove()) {// 处理移除错误
}
自定义内存管理
// 创建自定义内存管理器
class CustomMemoryManager : public JITLinkMemoryManager {
public:Expected<std::unique_ptr<Allocation>>allocate(const JITLinkDylib* JD, const SegmentsRequestMap& Request) override {// 自定义内存分配逻辑auto Alloc = std::make_unique<CustomAllocation>();// ... 实现分配细节 ...return std::move(Alloc);}
};// 在LLJIT构建器中设置自定义内存管理器
Builder.setObjectLinkingLayerCreator([&](ExecutionSession& ES, const Triple& TT) {return std::make_unique<ObjectLinkingLayer>(ES, std::make_unique<CustomMemoryManager>());});
错误处理模式
全面的错误处理
Error runJITProcess() {// 使用cantFail处理已知安全的操作auto JIT = cantFail(LLJITBuilder().create());// 使用Expected处理可能失败的操作if (auto Symbol = JIT->lookup("myFunction")) {// 成功找到符号auto Func = Symbol->toPtr<void(*)()>();Func();} else {// 处理查找错误auto Err = Symbol.takeError();logAllUnhandledErrors(std::move(Err), errs());return make_error<StringError>("Symbol lookup failed", inconvertibleErrorCode());}return Error::success();
}// 顶层错误处理
int main() {InitLLVM X; // 初始化LLVMif (auto Err = runJITProcess()) {logAllUnhandledErrors(std::move(Err), errs());return 1;}return 0;
}
实际应用案例
案例1:插件系统
class PluginManager {std::unique_ptr<LLJIT> JIT;ExecutionSession& ES;public:PluginManager() : JIT(cantFail(LLJITBuilder().create())), ES(JIT->getExecutionSession()) {}Error loadPlugin(const std::string& PluginName, const std::string& IRFilePath) {// 读取IR文件auto Ctx = std::make_unique<LLVMContext>();SMDiagnostic Err;auto M = parseIRFile(IRFilePath, Err, *Ctx);if (!M) return make_error<StringError>("Failed to parse IR", inconvertibleErrorCode());// 为插件创建独立的JITDylibauto& PluginJD = ES.createJITDylib(PluginName);PluginJD.addToLinkOrder(JIT->getMainJITDylib());// 添加插件模块ThreadSafeModule TSM(std::move(M), std::move(Ctx));return JIT->addIRModule(PluginJD, std::move(TSM));}template<typename FuncPtr>Expected<FuncPtr> getPluginFunction(const std::string& PluginName,const std::string& FuncName) {auto Sym = JIT->lookup(PluginName, FuncName);if (!Sym) return Sym.takeError();return Sym->toPtr<FuncPtr>();}
};
案例2:动态代码热更新
class HotSwappableJIT {std::unique_ptr<LLJIT> JIT;JITDylib& MainJD;std::atomic<ResourceTrackerSP> CurrentVersionRT;public:HotSwappableJIT() : JIT(cantFail(LLJITBuilder().create())),MainJD(JIT->getMainJITDylib()) {CurrentVersionRT = MainJD.getDefaultResourceTracker();}Error updateCode(ThreadSafeModule NewModule) {// 创建新版本资源跟踪器auto NewRT = MainJD.createResourceTracker();// 添加新版本模块if (auto Err = JIT->addIRModule(NewRT, std::move(NewModule))) {return Err;}// 原子交换资源跟踪器auto OldRT = CurrentVersionRT.exchange(NewRT);// 异步移除旧版本(避免阻塞)std::thread([OldRT]() {if (auto Err = OldRT->remove()) {// 记录错误但不阻塞主线程logAllUnhandledErrors(std::move(Err), errs());}}).detach();return Error::success();}
};
性能优化与调试
性能监控
class JITProfiler {ExecutionSession& ES;std::map<std::string, std::chrono::microseconds> CompileTimes;public:void recordCompileTime(const std::string& FuncName, std::chrono::microseconds Duration) {CompileTimes[FuncName] = Duration;}void printStats() {for (const auto& [Name, Time] : CompileTimes) {dbgs() << "Function " << Name << ": " << Time.count() << "μs\n";}}
};// 集成到编译层
auto ProfilingLayer = std::make_unique<IRTransformLayer>(ES, IRCompileLayer,[&](ThreadSafeModule TSM, const MaterializationResponsibility& R) {auto Start = std::chrono::high_resolution_clock::now();// 执行编译...auto End = std::chrono::high_resolution_clock::now();auto Duration = std::chrono::duration_cast<std::chrono::microseconds>(End - Start);Profiler.recordCompileTime(R.getSymbols().begin()->first, Duration);return TSM;});
通过深入理解ExecutionSession和JITDylib的工作原理,您可以构建出高度灵活和强大的JIT编译系统,满足各种复杂的动态代码执行需求。