Browse Source

Fallback to interpreter VM in case of JIT requirements unmet

cl-refactor
Paweł Bylica 10 years ago
parent
commit
de649202a0
  1. 28
      evmjit/libevmjit-cpp/JitVM.cpp
  2. 4
      evmjit/libevmjit-cpp/JitVM.h
  3. 24
      evmjit/libevmjit/Common.h

28
evmjit/libevmjit-cpp/JitVM.cpp

@ -1,6 +1,7 @@
#include "JitVM.h" #include "JitVM.h"
#include <libevm/VM.h> #include <libevm/VM.h>
#include <libevm/VMFactory.h>
#include <evmjit/libevmjit/ExecutionEngine.h> #include <evmjit/libevmjit/ExecutionEngine.h>
#include "Utils.h" #include "Utils.h"
@ -9,22 +10,25 @@ namespace dev
namespace eth namespace eth
{ {
bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _step)
{ {
using namespace jit; using namespace jit;
if (m_gas > std::numeric_limits<decltype(m_data.gas)>::max()) auto rejected = false;
BOOST_THROW_EXCEPTION(OutOfGas()); // Do not accept requests with gas > 2^63 (int64 max) // TODO: Return "not accepted" exception to allow interpreted handle that rejected |= m_gas > std::numeric_limits<decltype(m_data.gas)>::max(); // Do not accept requests with gas > 2^63 (int64 max)
rejected |= _ext.gasPrice > std::numeric_limits<decltype(m_data.gasPrice)>::max();
if (_ext.gasPrice > std::numeric_limits<decltype(m_data.gasPrice)>::max()) rejected |= _ext.currentBlock.number > std::numeric_limits<decltype(m_data.number)>::max();
BOOST_THROW_EXCEPTION(OutOfGas()); rejected |= _ext.currentBlock.timestamp > std::numeric_limits<decltype(m_data.timestamp)>::max();
if (_ext.currentBlock.number > std::numeric_limits<decltype(m_data.number)>::max())
BOOST_THROW_EXCEPTION(OutOfGas());
if (_ext.currentBlock.timestamp > std::numeric_limits<decltype(m_data.timestamp)>::max())
BOOST_THROW_EXCEPTION(OutOfGas());
if (rejected)
{
UNTESTED;
std::cerr << "Rejected\n";
VMFactory::setKind(VMKind::Interpreter);
m_fallbackVM = VMFactory::create(m_gas);
VMFactory::setKind(VMKind::JIT);
return m_fallbackVM->go(_ext, _onOp, _step);
}
m_data.gas = static_cast<decltype(m_data.gas)>(m_gas); m_data.gas = static_cast<decltype(m_data.gas)>(m_gas);
m_data.gasPrice = static_cast<decltype(m_data.gasPrice)>(_ext.gasPrice); m_data.gasPrice = static_cast<decltype(m_data.gasPrice)>(_ext.gasPrice);

4
evmjit/libevmjit-cpp/JitVM.h

@ -12,15 +12,13 @@ class JitVM: public VMFace
{ {
virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final;
enum Kind: bool { Interpreter, JIT };
static std::unique_ptr<VMFace> create(Kind, u256 _gas = 0);
private: private:
friend class VMFactory; friend class VMFactory;
explicit JitVM(u256 _gas = 0) : VMFace(_gas) {} explicit JitVM(u256 _gas = 0) : VMFace(_gas) {}
jit::RuntimeData m_data; jit::RuntimeData m_data;
jit::ExecutionEngine m_engine; jit::ExecutionEngine m_engine;
std::unique_ptr<VMFace> m_fallbackVM; ///< VM used in case of input data rejected by JIT
}; };

24
evmjit/libevmjit/Common.h

@ -25,20 +25,24 @@ struct NoteChannel {}; // FIXME: Use some log library?
enum class ReturnCode enum class ReturnCode
{ {
Stop = 0, // Success codes
Return = 1, Stop = 0,
Return = 1,
Suicide = 2, Suicide = 2,
OutOfGas = -1, // Standard error codes
BadJumpDestination = -2, OutOfGas = -1,
StackTooSmall = -3, StackTooSmall = -2,
BadInstruction = -4, BadJumpDestination = -3,
BadInstruction = -4,
Rejected = -5, ///< Input data (code, gas, block info, etc.) does not meet JIT requirement and execution request has been rejected
LLVMConfigError = -5, // Internal error codes
LLVMCompileError = -6, LLVMConfigError = -101,
LLVMLinkError = -7, LLVMCompileError = -102,
LLVMLinkError = -103,
UnexpectedException = -8, UnexpectedException = -111,
}; };
/// Representation of 256-bit value binary compatible with LLVM i256 /// Representation of 256-bit value binary compatible with LLVM i256

Loading…
Cancel
Save