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