Browse Source

Extract execution context from ExecutionEngine::run.

cl-refactor
Paweł Bylica 10 years ago
parent
commit
e0c176f377
  1. 5
      libevmjit-cpp/JitVM.cpp
  2. 2
      libevmjit-cpp/JitVM.h
  3. 86
      libevmjit/ExecutionEngine.cpp
  4. 24
      libevmjit/ExecutionEngine.h
  5. 14
      libevmjit/interface.cpp

5
libevmjit-cpp/JitVM.cpp

@ -7,7 +7,6 @@
#include <libdevcrypto/SHA3.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#include <evmjit/libevmjit/ExecutionEngine.h>
#include "Utils.h"
@ -56,7 +55,7 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step)
m_data.codeHash = eth2llvm(sha3(_ext.code));
auto env = reinterpret_cast<Env*>(&_ext);
auto exitCode = m_engine.run(&m_data, env);
auto exitCode = jit::ExecutionEngine::run(m_context, &m_data, env);
switch (exitCode)
{
case ReturnCode::Suicide:
@ -79,7 +78,7 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step)
}
m_gas = m_data.gas; // TODO: Remove m_gas field
return {std::get<0>(m_engine.returnData), std::get<1>(m_engine.returnData)};
return {std::get<0>(m_context.returnData), std::get<1>(m_context.returnData)};
}
}

2
libevmjit-cpp/JitVM.h

@ -17,7 +17,7 @@ private:
explicit JitVM(u256 _gas = 0) : VMFace(_gas) {}
jit::RuntimeData m_data;
jit::ExecutionEngine m_engine;
jit::ExecutionContext m_context;
std::unique_ptr<VMFace> m_fallbackVM; ///< VM used in case of input data rejected by JIT
};

86
libevmjit/ExecutionEngine.cpp

@ -90,65 +90,77 @@ void parseOptions()
cl::ParseEnvironmentOptions("evmjit", "EVMJIT", "Ethereum EVM JIT Compiler");
}
// FIXME: It is temporary, becaue ExecutionEngine.h is currently our public header
// and including llvm::ExecutionEngine there is not a good idea.
llvm::ExecutionEngine* g_ee = nullptr;
}
ExecutionEngine& ExecutionEngine::get()
{
static ExecutionEngine instance;
return instance;
}
ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
ExecutionEngine::ExecutionEngine()
{
static std::once_flag flag;
std::call_once(flag, parseOptions);
/// ExecutionEngine is created only once
std::unique_ptr<ExecStats> listener{new ExecStats};
listener->stateChanged(ExecState::Started);
parseOptions();
if (g_cache == CacheMode::clear)
Cache::clear();
bool preloadCache = g_cache == CacheMode::preload;
if (preloadCache)
g_cache = CacheMode::on;
// TODO: Do not pseudo-init the cache every time
auto objectCache = (g_cache != CacheMode::off && g_cache != CacheMode::clear) ? Cache::getObjectCache(g_cache, listener.get()) : nullptr;
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
static std::unique_ptr<llvm::ExecutionEngine> ee;
if (!ee)
{
if (g_cache == CacheMode::clear)
Cache::clear();
auto module = std::unique_ptr<llvm::Module>(new llvm::Module({}, llvm::getGlobalContext()));
// FIXME: LLVM 3.7: test on Windows
auto triple = llvm::Triple(llvm::sys::getProcessTriple());
if (triple.getOS() == llvm::Triple::OSType::Win32)
triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format
module->setTargetTriple(triple.str());
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::EngineBuilder builder(std::move(module));
builder.setEngineKind(llvm::EngineKind::JIT);
builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None);
auto module = std::unique_ptr<llvm::Module>(new llvm::Module({}, llvm::getGlobalContext()));
g_ee = (builder.create());
// FIXME: LLVM 3.7: test on Windows
auto triple = llvm::Triple(llvm::sys::getProcessTriple());
if (triple.getOS() == llvm::Triple::OSType::Win32)
triple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF); // MCJIT does not support COFF format
module->setTargetTriple(triple.str());
// TODO: Update cache listener
auto objectCache = (g_cache != CacheMode::off && g_cache != CacheMode::clear) ? Cache::getObjectCache(g_cache, nullptr) : nullptr;
g_ee->setObjectCache(objectCache);
llvm::EngineBuilder builder(std::move(module));
builder.setEngineKind(llvm::EngineKind::JIT);
builder.setOptLevel(g_optimize ? llvm::CodeGenOpt::Default : llvm::CodeGenOpt::None);
// FIXME: Disabled during API changes
//if (preloadCache)
// Cache::preload(*ee, funcCache);
}
ReturnCode ExecutionEngine::run(ExecutionContext& _context, RuntimeData* _data, Env* _env)
{
ExecutionEngine::get(); // FIXME
std::unique_ptr<ExecStats> listener{new ExecStats};
listener->stateChanged(ExecState::Started);
ee.reset(builder.create());
if (!CHECK(ee))
return ReturnCode::LLVMConfigError;
ee->setObjectCache(objectCache);
// FIXME: Disabled during API changes
//if (preloadCache)
// Cache::preload(*ee, funcCache);
}
static StatsCollector statsCollector;
auto mainFuncName = codeHash(_data->codeHash);
m_runtime.init(_data, _env);
_context.m_runtime.init(_data, _env);
// TODO: Remove cast
auto entryFuncPtr = (EntryFuncPtr) JIT::getCode(_data->codeHash);
if (!entryFuncPtr)
{
auto module = objectCache ? Cache::getObject(mainFuncName) : nullptr;
auto module = Cache::getObject(mainFuncName);
if (!module)
{
listener->stateChanged(ExecState::Compilation);
@ -166,20 +178,20 @@ ReturnCode ExecutionEngine::run(RuntimeData* _data, Env* _env)
if (g_dump)
module->dump();
ee->addModule(std::move(module));
g_ee->addModule(std::move(module));
listener->stateChanged(ExecState::CodeGen);
entryFuncPtr = (EntryFuncPtr)ee->getFunctionAddress(mainFuncName);
entryFuncPtr = (EntryFuncPtr)g_ee->getFunctionAddress(mainFuncName);
if (!CHECK(entryFuncPtr))
return ReturnCode::LLVMLinkError;
JIT::mapCode(_data->codeHash, (void*)entryFuncPtr); // FIXME: Remove cast
}
listener->stateChanged(ExecState::Execution);
auto returnCode = entryFuncPtr(&m_runtime);
auto returnCode = entryFuncPtr(&_context.m_runtime);
listener->stateChanged(ExecState::Return);
if (returnCode == ReturnCode::Return)
returnData = m_runtime.getReturnData(); // Save reference to return data
_context.returnData = _context.m_runtime.getReturnData(); // Save reference to return data
listener->stateChanged(ExecState::Finished);

24
libevmjit/ExecutionEngine.h

@ -38,22 +38,32 @@ public:
virtual void stateChanged(ExecState) {}
};
class ExecutionEngine
class ExecutionContext
{
public:
ExecutionEngine() = default;
ExecutionEngine(ExecutionEngine const&) = delete;
ExecutionEngine& operator=(ExecutionEngine) = delete;
EXPORT ReturnCode run(RuntimeData* _data, Env* _env);
ExecutionContext() = default;
ExecutionContext(ExecutionContext const&) = delete;
ExecutionContext& operator=(ExecutionContext const&) = delete;
/// Reference to returned data (RETURN opcode used)
bytes_ref returnData;
private:
Runtime m_runtime;
};
class ExecutionEngine
{
public:
ExecutionEngine(ExecutionEngine const&) = delete;
ExecutionEngine& operator=(ExecutionEngine const&) = delete;
EXPORT static ReturnCode run(ExecutionContext& _context, RuntimeData* _data, Env* _env);
private:
ExecutionEngine();
static ExecutionEngine& get();
};
}
}
}

14
libevmjit/interface.cpp

@ -7,23 +7,23 @@ using namespace dev::eth::jit;
EXPORT void* evmjit_create() noexcept
{
// TODO: Make sure ExecutionEngine constructor does not throw
return new(std::nothrow) ExecutionEngine;
// TODO: Make sure ExecutionEngine constructor does not throw + make JIT/ExecutionEngine interface all nothrow
return new(std::nothrow) ExecutionContext;
}
EXPORT void evmjit_destroy(ExecutionEngine* _engine) noexcept
EXPORT void evmjit_destroy(ExecutionContext* _context) noexcept
{
delete _engine;
delete _context;
}
EXPORT int evmjit_run(ExecutionEngine* _engine, RuntimeData* _data, Env* _env) noexcept
EXPORT int evmjit_run(ExecutionContext* _context, RuntimeData* _data, Env* _env) noexcept
{
if (!_engine || !_data)
if (!_context || !_data)
return static_cast<int>(ReturnCode::UnexpectedException);
try
{
auto returnCode = _engine->run(_data, _env);
auto returnCode = ExecutionEngine::run(*_context, _data, _env);
return static_cast<int>(returnCode);
}
catch(...)

Loading…
Cancel
Save