github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/jit/jit_driver.h (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  #pragma once
    21  
    22  #include "common/common.h"
    23  #include "core/ir_warden.h"
    24  #include "fs/proto/ir.pb.h"
    25  #include "jit/jit_engine.h"
    26  #include "util/singleton.h"
    27  
    28  namespace neb {
    29  namespace internal {
    30  class jit_driver_impl;
    31  }
    32  namespace core {
    33  class driver;
    34  }
    35  class jit_driver : public ::neb::util::singleton<jit_driver> {
    36  public:
    37    jit_driver();
    38    ~jit_driver();
    39  
    40    template <typename RT, typename... ARGS>
    41    RT run_ir(const std::string &name, uint64_t height,
    42              const std::string &func_name, ARGS... args) {
    43      auto irs_ptr =
    44          core::ir_warden::instance().get_ir_by_name_height(name, height, false);
    45      auto irs = *irs_ptr;
    46      if (irs.size() != 1) {
    47        throw std::invalid_argument("no such ir");
    48      }
    49      std::string key = gen_key(irs, func_name);
    50      auto ret = run_if_exists<RT>(irs.back(), func_name, args...);
    51      if (ret.first) {
    52        return ret.second;
    53      }
    54  
    55      irs_ptr =
    56          core::ir_warden::instance().get_ir_by_name_height(name, height, true);
    57      return run<RT>(key, *irs_ptr, func_name, args...);
    58    }
    59  
    60    template <typename RT, typename... ARGS>
    61    std::pair<bool, RT> run_if_exists(const nbre::NBREIR &ir,
    62                                      const std::string &func_name,
    63                                      ARGS... args) {
    64  
    65      std::vector<nbre::NBREIR> irs;
    66      irs.push_back(ir);
    67      std::string key = gen_key(irs, func_name);
    68      std::unique_lock<std::mutex> _l(m_mutex);
    69      auto it = m_jit_instances.find(key);
    70      if (it == m_jit_instances.end())
    71        return std::make_pair(false, RT());
    72  
    73      auto &context = it->second;
    74      context->m_time_counter = 30 * 60;
    75      _l.unlock();
    76      return std::make_pair(true, context->m_jit.run<RT>(args...));
    77    }
    78  
    79    template <typename RT, typename... ARGS>
    80    RT run(const std::string &ir_key, const std::vector<nbre::NBREIR> &irs,
    81           const std::string &func_name, ARGS... args) {
    82      std::string key = ir_key;
    83      m_mutex.lock();
    84      auto it = m_jit_instances.find(key);
    85      if (it == m_jit_instances.end()) {
    86        shrink_instances();
    87        m_jit_instances.insert(std::make_pair(key, make_context(irs, func_name)));
    88        it = m_jit_instances.find(key);
    89      }
    90      auto &context = it->second;
    91      context->m_time_counter = 30 * 60;
    92      m_mutex.unlock();
    93      struct using_helper {
    94        using_helper(jit_context *jc) : m_jc(jc) { jc->m_using = true; }
    95        ~using_helper() { m_jc->m_using = false; }
    96        jit_context *m_jc;
    97      } _ul(context.get());
    98      context->m_using = true;
    99      LOG(INFO) << "ir key " << ir_key << " irs size " << irs.size()
   100                << " func_name " << func_name;
   101      return context->m_jit.run<RT>(args...);
   102    }
   103  
   104    void timer_callback();
   105  
   106  protected:
   107    void shrink_instances();
   108  
   109    std::string gen_key(const std::vector<nbre::NBREIR> &irs,
   110                        const std::string &func_name);
   111  
   112    struct jit_context {
   113      llvm::LLVMContext m_context;
   114      jit::jit_engine m_jit;
   115      int32_t m_time_counter;
   116      bool m_using;
   117    };
   118  
   119    std::unique_ptr<jit_driver::jit_context>
   120    make_context(const std::vector<nbre::NBREIR> &irs,
   121                 const std::string &func_name);
   122  
   123    bool find_mangling(llvm::Module *M, const std::string &func_name,
   124                       std::string &mangling_name);
   125  
   126  protected:
   127    std::mutex m_mutex;
   128    std::unordered_map<std::string, std::unique_ptr<jit_context>> m_jit_instances;
   129  }; // end class jit_driver;
   130  } // end namespace neb