Browse Source

JIT implementation cleanups.

cl-refactor
Paweł Bylica 10 years ago
parent
commit
b8a66c7f3e
  1. 2
      evmjit/include/evmjit/JIT.h
  2. 78
      evmjit/libevmjit/JIT.cpp

2
evmjit/include/evmjit/JIT.h

@ -17,7 +17,7 @@ public:
/// Returns `true` if the EVM code has been compiled and loaded into memory. /// Returns `true` if the EVM code has been compiled and loaded into memory.
/// In this case the code can be executed without overhead. /// In this case the code can be executed without overhead.
/// \param _codeHash The Keccak hash of the EVM code. /// \param _codeHash The Keccak hash of the EVM code.
static bool isCodeReady(h256 _codeHash); static bool isCodeReady(h256 const& _codeHash);
EXPORT static ReturnCode exec(ExecutionContext& _context); EXPORT static ReturnCode exec(ExecutionContext& _context);
}; };

78
evmjit/libevmjit/JIT.cpp

@ -26,7 +26,7 @@ using namespace eth::jit;
namespace namespace
{ {
using EntryFuncPtr = ReturnCode(*)(ExecutionContext*); using ExecFunc = ReturnCode(*)(ExecutionContext*);
std::string hash2str(i256 const& _hash) std::string hash2str(i256 const& _hash)
{ {
@ -78,10 +78,28 @@ void parseOptions()
cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler"); cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");
} }
std::unique_ptr<llvm::ExecutionEngine> init() class JITImpl
{ {
/// ExecutionEngine is created only once std::unique_ptr<llvm::ExecutionEngine> m_engine;
std::unordered_map<h256, ExecFunc> m_codeMap;
public:
static JITImpl& instance()
{
static JITImpl s_instance;
return s_instance;
}
JITImpl();
llvm::ExecutionEngine& engine() { return *m_engine; }
ExecFunc getExecFunc(h256 const& _codeHash) const;
void mapExecFunc(h256 _codeHash, ExecFunc _funcAddr);
};
JITImpl::JITImpl()
{
parseOptions(); parseOptions();
bool preloadCache = g_cache == CacheMode::preload; bool preloadCache = g_cache == CacheMode::preload;
@ -103,57 +121,39 @@ std::unique_ptr<llvm::ExecutionEngine> init()
builder.setEngineKind(llvm::EngineKind::JIT); builder.setEngineKind(llvm::EngineKind::JIT);
builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None); builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None);
auto ee = std::unique_ptr<llvm::ExecutionEngine>{builder.create()}; m_engine.reset(builder.create());
// TODO: Update cache listener // TODO: Update cache listener
ee->setObjectCache(Cache::init(g_cache, nullptr)); m_engine->setObjectCache(Cache::init(g_cache, nullptr));
// FIXME: Disabled during API changes // FIXME: Disabled during API changes
//if (preloadCache) //if (preloadCache)
// Cache::preload(*ee, funcCache); // Cache::preload(*m_engine, funcCache);
return ee;
} }
class JITImpl ExecFunc JITImpl::getExecFunc(h256 const& _codeHash) const
{
public:
std::unordered_map<h256, void*> codeMap;
static JITImpl& instance()
{
static JITImpl s_instance;
return s_instance;
}
static void* getCode(h256 _codeHash);
static void mapCode(h256 _codeHash, void* _funcAddr);
};
void* JITImpl::getCode(h256 _codeHash)
{ {
auto& codeMap = JITImpl::instance().codeMap; auto it = m_codeMap.find(_codeHash);
auto it = codeMap.find(_codeHash); if (it != m_codeMap.end())
if (it != codeMap.end())
return it->second; return it->second;
return nullptr; return nullptr;
} }
void JITImpl::mapCode(h256 _codeHash, void* _funcAddr) void JITImpl::mapExecFunc(h256 _codeHash, ExecFunc _funcAddr)
{ {
JITImpl::instance().codeMap.insert(std::make_pair(_codeHash, _funcAddr)); m_codeMap.emplace(std::move(_codeHash), _funcAddr);
} }
} // anonymous namespace } // anonymous namespace
bool JIT::isCodeReady(h256 _codeHash) bool JIT::isCodeReady(h256 const& _codeHash)
{ {
return JITImpl::instance().codeMap.count(_codeHash) != 0; return JITImpl::instance().getExecFunc(_codeHash) != nullptr;
} }
ReturnCode JIT::exec(ExecutionContext& _context) ReturnCode JIT::exec(ExecutionContext& _context)
{ {
static auto s_ee = init(); auto& jit = JITImpl::instance();
std::unique_ptr<ExecStats> listener{new ExecStats}; std::unique_ptr<ExecStats> listener{new ExecStats};
listener->stateChanged(ExecState::Started); listener->stateChanged(ExecState::Started);
@ -167,8 +167,8 @@ ReturnCode JIT::exec(ExecutionContext& _context)
auto mainFuncName = hash2str(codeHash); auto mainFuncName = hash2str(codeHash);
// TODO: Remove cast // TODO: Remove cast
auto entryFuncPtr = (EntryFuncPtr) JITImpl::getCode(codeHash); auto execFunc = jit.getExecFunc(codeHash);
if (!entryFuncPtr) if (!execFunc)
{ {
auto module = Cache::getObject(mainFuncName); auto module = Cache::getObject(mainFuncName);
if (!module) if (!module)
@ -188,16 +188,16 @@ ReturnCode JIT::exec(ExecutionContext& _context)
if (g_dump) if (g_dump)
module->dump(); module->dump();
s_ee->addModule(std::move(module)); jit.engine().addModule(std::move(module));
listener->stateChanged(ExecState::CodeGen); listener->stateChanged(ExecState::CodeGen);
entryFuncPtr = (EntryFuncPtr)s_ee->getFunctionAddress(mainFuncName); execFunc = (ExecFunc)jit.engine().getFunctionAddress(mainFuncName);
if (!CHECK(entryFuncPtr)) if (!CHECK(execFunc))
return ReturnCode::LLVMLinkError; return ReturnCode::LLVMLinkError;
JITImpl::mapCode(codeHash, (void*)entryFuncPtr); // FIXME: Remove cast jit.mapExecFunc(codeHash, execFunc);
} }
listener->stateChanged(ExecState::Execution); listener->stateChanged(ExecState::Execution);
auto returnCode = entryFuncPtr(&_context); auto returnCode = execFunc(&_context);
listener->stateChanged(ExecState::Return); listener->stateChanged(ExecState::Return);
if (returnCode == ReturnCode::Return) if (returnCode == ReturnCode::Return)

Loading…
Cancel
Save