github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/jit/jit_driver.cpp (about) 1 // Copyright (C) 2018 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or 6 // modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // (at your option) any later version. 10 // 11 // the go-nebulas library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with the go-nebulas library. If not, see 18 // <http://www.gnu.org/licenses/>. 19 // 20 21 #include "jit/jit_driver.h" 22 #include "common/configuration.h" 23 #include "jit/OrcLazyJIT.h" 24 25 #include "jit/jit_exception.h" 26 #include "llvm/ADT/StringExtras.h" 27 #include "llvm/ADT/Triple.h" 28 #include "llvm/Bitcode/BitcodeReader.h" 29 #include "llvm/CodeGen/CommandFlags.def" 30 #include "llvm/CodeGen/LinkAllCodegenComponents.h" 31 #include "llvm/ExecutionEngine/GenericValue.h" 32 #include "llvm/ExecutionEngine/Interpreter.h" 33 #include "llvm/ExecutionEngine/JITEventListener.h" 34 #include "llvm/ExecutionEngine/MCJIT.h" 35 #include "llvm/ExecutionEngine/ObjectCache.h" 36 #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" 37 #include "llvm/ExecutionEngine/OrcMCJITReplacement.h" 38 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 39 #include "llvm/IR/IRBuilder.h" 40 #include "llvm/IR/LLVMContext.h" 41 #include "llvm/IR/Module.h" 42 #include "llvm/IR/Type.h" 43 #include "llvm/IR/TypeBuilder.h" 44 #include "llvm/IRReader/IRReader.h" 45 #include "llvm/Object/Archive.h" 46 #include "llvm/Object/ObjectFile.h" 47 #include "llvm/Support/CommandLine.h" 48 #include "llvm/Support/Debug.h" 49 #include "llvm/Support/DynamicLibrary.h" 50 #include "llvm/Support/Format.h" 51 #include "llvm/Support/ManagedStatic.h" 52 #include "llvm/Support/MathExtras.h" 53 #include "llvm/Support/Memory.h" 54 #include "llvm/Support/MemoryBuffer.h" 55 #include "llvm/Support/Path.h" 56 #include "llvm/Support/PluginLoader.h" 57 #include "llvm/Support/PrettyStackTrace.h" 58 #include "llvm/Support/Process.h" 59 #include "llvm/Support/Program.h" 60 #include "llvm/Support/Signals.h" 61 #include "llvm/Support/SourceMgr.h" 62 #include "llvm/Support/TargetSelect.h" 63 #include "llvm/Support/raw_ostream.h" 64 #include "llvm/Transforms/Instrumentation.h" 65 #include <cerrno> 66 67 namespace neb { 68 69 jit_driver::jit_driver() { 70 // llvm::sys::PrintStackTraceOnErrorSignal( 71 // configuration::instance().exec_name(), false); 72 llvm::InitializeNativeTarget(); 73 llvm::InitializeNativeTargetAsmPrinter(); 74 llvm::sys::Process::PreventCoreFiles(); 75 std::string errMsg; 76 llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr, &errMsg); 77 } 78 79 jit_driver::~jit_driver() { llvm::llvm_shutdown(); } 80 81 bool jit_driver::find_mangling(llvm::Module *M, const std::string &func_name, 82 std::string &mangling_name) { 83 if (!M) { 84 return false; 85 } 86 87 auto contains = [](const std::string &str, 88 const std::string &substr) -> bool { 89 size_t str_len = str.size(); 90 size_t substr_len = substr.size(); 91 92 size_t j = 0; 93 for (size_t i = 0; i < str_len && j < substr_len; i++) { 94 if (str[i] == substr[j]) { 95 j++; 96 } 97 } 98 return j == substr_len; 99 }; 100 101 for (auto &func : M->functions()) { 102 std::string name = func.getName().data(); 103 // LOG(INFO) << "to check " << func_name << " in " << name; 104 if (contains(name, func_name)) { 105 LOG(INFO) << "find " << func_name << " in " << name; 106 mangling_name = name; 107 return true; 108 } 109 } 110 return false; 111 } 112 113 std::unique_ptr<jit_driver::jit_context> 114 jit_driver::make_context(const std::vector<nbre::NBREIR> &irs, 115 const std::string &func_name) { 116 std::unique_ptr<jit_context> ret = std::make_unique<jit_context>(); 117 118 std::string mangling_name; 119 std::vector<std::unique_ptr<llvm::Module>> modules; 120 for (const auto &ir : irs) { 121 std::string ir_str = ir.ir(); 122 llvm::StringRef sr(ir_str); 123 auto mem_buf = llvm::MemoryBuffer::getMemBuffer(sr, "", false); 124 llvm::SMDiagnostic err; 125 126 auto module = 127 llvm::parseIR(mem_buf->getMemBufferRef(), err, ret->m_context, true); 128 find_mangling(module.get(), func_name, mangling_name); 129 if (nullptr == module) { 130 LOG(ERROR) << "Module broken"; 131 } else { 132 modules.push_back(std::move(module)); 133 } 134 } 135 ret->m_jit.init(std::move(modules), mangling_name); 136 return std::move(ret); 137 } 138 139 void jit_driver::timer_callback() { 140 std::unique_lock<std::mutex> _l(m_mutex); 141 std::vector<std::string> keys; 142 for (auto &it : m_jit_instances) { 143 it.second->m_time_counter--; 144 if (it.second->m_time_counter < 0) { 145 keys.push_back(it.first); 146 } 147 } 148 for (auto &s : keys) { 149 m_jit_instances.erase(s); 150 } 151 } 152 153 std::string jit_driver::gen_key(const std::vector<nbre::NBREIR> &irs, 154 const std::string &func_name) { 155 std::stringstream ss; 156 for (auto &m : irs) { 157 ss << m.name() << m.version(); 158 } 159 ss << func_name; 160 return ss.str(); 161 } 162 163 void jit_driver::shrink_instances() { 164 if (m_jit_instances.size() < 16) 165 return; 166 167 int32_t min_count = 30 * 60 + 1; 168 std::string min_key; 169 for (auto &pair : m_jit_instances) { 170 if (pair.second->m_time_counter < min_count && !pair.second->m_using) { 171 min_count = pair.second->m_time_counter; 172 min_key = pair.first; 173 } 174 } 175 if (!min_key.empty()) { 176 m_jit_instances.erase(min_key); 177 } 178 } 179 } // namespace neb