void Cache::preload(llvm::ExecutionEngine& _ee, std::unordered_map<std::string, uint64_t>& _funcCache) { Guard g{x_cacheMutex}; // Disable listener auto listener = g_listener; g_listener = nullptr; auto cachePath = getVersionedCacheDir(); std::error_code err; for (auto it = llvm::sys::fs::directory_iterator{cachePath, err}; it != decltype(it){}; it.increment(err)) { auto name = it->path().substr(cachePath.size() + 1); if (auto module = getObject(name)) { DLOG(cache) << "Preload: " << name << "\n"; _ee.addModule(std::move(module)); auto addr = _ee.getFunctionAddress(name); assert(addr); _funcCache[std::move(name)] = addr; } } g_listener = listener; }
bool ExternalDispatcherImpl::executeCall(Function *f, Instruction *i, uint64_t *args) { dispatchers_ty::iterator it = dispatchers.find(i); if (it != dispatchers.end()) { // Code already JIT'ed for this return runProtectedCall(it->second, args); } // Code for this not JIT'ed. Do this now. Function *dispatcher; #ifdef WINDOWS std::map<std::string, void *>::iterator it2 = preboundFunctions.find(f->getName()); if (it2 != preboundFunctions.end()) { // only bind once if (it2->second) { executionEngine->addGlobalMapping(f, it2->second); it2->second = 0; } } #endif Module *dispatchModule = NULL; #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) // The MCJIT generates whole modules at a time so for every call that we // haven't made before we need to create a new Module. dispatchModule = new Module(getFreshModuleID(), ctx); #else dispatchModule = this->singleDispatchModule; #endif dispatcher = createDispatcher(f, i, dispatchModule); dispatchers.insert(std::make_pair(i, dispatcher)); // Force the JIT execution engine to go ahead and build the function. This // ensures that any errors or assertions in the compilation process will // trigger crashes instead of being caught as aborts in the external // function. #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) if (dispatcher) { // The dispatchModule is now ready so tell MCJIT to generate the code for // it. auto dispatchModuleUniq = std::unique_ptr<Module>(dispatchModule); executionEngine->addModule( std::move(dispatchModuleUniq)); // MCJIT takes ownership // Force code generation uint64_t fnAddr = executionEngine->getFunctionAddress(dispatcher->getName()); executionEngine->finalizeObject(); assert(fnAddr && "failed to get function address"); (void)fnAddr; } else { // MCJIT didn't take ownership of the module so delete it. delete dispatchModule; } #else if (dispatcher) { // Old JIT works on a function at a time so compile the function. executionEngine->recompileAndRelinkFunction(dispatcher); } #endif return runProtectedCall(dispatcher, args); }