diff --git a/libevmjit/Cache.cpp b/libevmjit/Cache.cpp index acc560309..1dd6f1d9f 100644 --- a/libevmjit/Cache.cpp +++ b/libevmjit/Cache.cpp @@ -1,4 +1,7 @@ #include "Cache.h" +#include +#include +#include namespace dev { @@ -6,6 +9,40 @@ namespace eth { namespace jit { +namespace +{ + using CacheMap = std::unordered_map; + + CacheMap& getCacheMap() + { + static CacheMap map; + return map; + } +} + +#define LOG(...) std::cerr << "CACHE " + +ExecBundle& Cache::registerExec(Cache::Key _key, ExecBundle&& _exec) +{ + auto& map = getCacheMap(); + auto r = map.insert(std::make_pair(_key, std::move(_exec))); + assert(r.second && "Updating cached objects not supported"); + LOG() << "add " << _key << "\n"; + return r.first->second; // return exec, now owned by cache +} + +ExecBundle* Cache::findExec(Cache::Key _key) +{ + auto& map = getCacheMap(); + auto it = map.find(_key); + if (it != map.end()) + { + LOG() << "hit " << _key << "\n"; + return &it->second; + } + LOG() << "miss " << _key << "\n"; + return nullptr; +} } } diff --git a/libevmjit/Cache.h b/libevmjit/Cache.h index e75bce27f..c9a74ea91 100644 --- a/libevmjit/Cache.h +++ b/libevmjit/Cache.h @@ -1,5 +1,9 @@ #pragma once +#include +#include + + namespace dev { namespace eth @@ -17,7 +21,10 @@ struct ExecBundle class Cache { public: + using Key = void const*; + static ExecBundle& registerExec(Key _key, ExecBundle&& _exec); + static ExecBundle* findExec(Key _key); }; } diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 9648bb5cb..719be9ac6 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -41,6 +41,12 @@ ReturnCode ExecutionEngine::run(bytes const& _code, RuntimeData* _data, Env* _en ReturnCode ExecutionEngine::run(std::unique_ptr _module, RuntimeData* _data, Env* _env) { + auto key = _data->code; // TODO: Change cache key + if (auto cachedExec = Cache::findExec(key)) + { + return run(*cachedExec, _data, _env); + } + auto module = _module.get(); // Keep ownership of the module in _module llvm::sys::PrintStackTraceOnErrorSignal(); @@ -88,7 +94,8 @@ ReturnCode ExecutionEngine::run(std::unique_ptr _module, RuntimeDa if (!exec.entryFunc) return ReturnCode::LLVMLinkError; - auto returnCode = run(exec, _data, _env); + auto& cachedExec = Cache::registerExec(_data->code, std::move(exec)); + auto returnCode = run(cachedExec, _data, _env); auto executionEndTime = std::chrono::high_resolution_clock::now(); clog(JIT) << " + " << std::chrono::duration_cast(executionEndTime - executionStartTime).count() << " ms "; diff --git a/libevmjit/ExecutionEngine.h b/libevmjit/ExecutionEngine.h index 8eb4ff347..785e4efda 100644 --- a/libevmjit/ExecutionEngine.h +++ b/libevmjit/ExecutionEngine.h @@ -13,7 +13,7 @@ namespace eth { namespace jit { -class ExecBundle; +struct ExecBundle; class ExecutionEngine {