From b1dc0d5e6a1093bcb8849d932df7c7a91578f1d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 10 Dec 2014 17:41:53 +0100 Subject: [PATCH] VMFactory - a new way of creating VMs --- libethereum/Executive.cpp | 5 +++-- libethereum/State.cpp | 14 ++++++------ libevm/ExtVMFace.h | 2 +- libevm/VM.h | 8 ++++--- libevm/VMFactory.cpp | 46 +++++++++++++++++++++++++++++++++++++++ libevm/VMFactory.h | 43 ++++++++++++++++++++++++++++++++++++ test/createRandomTest.cpp | 8 +++---- test/vm.cpp | 7 +++--- 8 files changed, 113 insertions(+), 20 deletions(-) create mode 100644 libevm/VMFactory.cpp create mode 100644 libevm/VMFactory.h diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index db77d349a..9e2f5ee07 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include "Interface.h" #include "Executive.h" @@ -105,7 +106,7 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu if (m_s.addressHasCode(_receiveAddress)) { - m_vm.reset(new VM(_gas)); + m_vm = VMFactory::create(_gas); bytes const& c = m_s.code(_receiveAddress); m_ext.reset(new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms)); } @@ -124,7 +125,7 @@ bool Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress) + _endowment, Account::ContractConception); // Execute _init. - m_vm.reset(new VM(_gas)); + m_vm = VMFactory::create(_gas); m_ext.reset(new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_ms)); return _init.empty(); } diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 335b7ff04..feb732882 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include "BlockChain.h" #include "Defaults.h" #include "ExtVM.h" @@ -1214,19 +1214,19 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA } else if (addressHasCode(_codeAddress)) { - VM vm(*_gas); + auto vm = VMFactory::create(*_gas); ExtVM evm(*this, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &code(_codeAddress), o_ms, _level); bool revert = false; try { - auto out = vm.go(evm, _onOp); + auto out = vm->go(evm, _onOp); memcpy(_out.data(), out.data(), std::min(out.size(), _out.size())); if (o_sub) *o_sub += evm.sub; if (o_ms) o_ms->output = out.toBytes(); - *_gas = vm.gas(); + *_gas = vm->gas(); } catch (VMException const& _e) { @@ -1273,19 +1273,19 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, m_cache[newAddress] = Account(balance(newAddress) + _endowment, Account::ContractConception); // Execute init code. - VM vm(*_gas); + auto vm = VMFactory::create(*_gas); ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); bool revert = false; bytesConstRef out; try { - out = vm.go(evm, _onOp); + out = vm->go(evm, _onOp); if (o_ms) o_ms->output = out.toBytes(); if (o_sub) *o_sub += evm.sub; - *_gas = vm.gas(); + *_gas = vm->gas(); } catch (VMException const& _e) { diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 4a175ff4e..52798cd89 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -150,7 +150,7 @@ public: BlockInfo previousBlock; ///< The previous block's information. BlockInfo currentBlock; ///< The current block's information. SubState sub; ///< Sub-band VM state (suicides, refund counter, logs). - unsigned depth; ///< Depth of the present call. + unsigned depth = 0; ///< Depth of the present call. }; } diff --git a/libevm/VM.h b/libevm/VM.h index 654e9719f..3b9e32c7b 100644 --- a/libevm/VM.h +++ b/libevm/VM.h @@ -52,9 +52,6 @@ inline u256 fromAddress(Address _a) class VM : public VMFace { public: - /// Construct VM object. - explicit VM(u256 _gas = 0) : VMFace(_gas) {} - virtual void reset(u256 _gas = 0) noexcept override final; virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final; @@ -68,6 +65,11 @@ public: u256s const& stack() const { return m_stack; } private: + friend class VMFactory; + + /// Construct VM object. + explicit VM(u256 _gas = 0) : VMFace(_gas) {} + template bytesConstRef goImpl(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); diff --git a/libevm/VMFactory.cpp b/libevm/VMFactory.cpp new file mode 100644 index 000000000..423c6b8ce --- /dev/null +++ b/libevm/VMFactory.cpp @@ -0,0 +1,46 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ + +#include "VMFactory.h" +#include +#include "VM.h" + +namespace dev +{ +namespace eth +{ +namespace +{ + VMKind g_kind = VMKind::Interpreter; +} + +void VMFactory::setKind(VMKind _kind) +{ + g_kind = _kind; +} + +std::unique_ptr VMFactory::create(u256 _gas) +{ + assert(g_kind == VMKind::Interpreter && "Only interpreter supported for now"); + return std::unique_ptr(new VM(_gas)); +} + +} +} + + + diff --git a/libevm/VMFactory.h b/libevm/VMFactory.h new file mode 100644 index 000000000..155350602 --- /dev/null +++ b/libevm/VMFactory.h @@ -0,0 +1,43 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ + +#include "VMFace.h" + +namespace dev +{ +namespace eth +{ + +enum class VMKind : bool +{ + Interpreter, + JIT +}; + +class VMFactory +{ +public: + VMFactory() = delete; + + static std::unique_ptr create(u256 _gas); + + static void setKind(VMKind _kind); + +}; + +} +} diff --git a/test/createRandomTest.cpp b/test/createRandomTest.cpp index caeeb6b67..a11688457 100644 --- a/test/createRandomTest.cpp +++ b/test/createRandomTest.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include "vm.h" using namespace std; @@ -142,14 +142,14 @@ void doMyTests(json_spirit::mValue& v) } bytes output; - eth::VM vm(fev.gas); + auto vm = eth::VMFactory::create(fev.gas); u256 gas; bool vmExceptionOccured = false; try { - output = vm.go(fev, fev.simpleTrace()).toBytes(); - gas = vm.gas(); + output = vm->go(fev, fev.simpleTrace()).toBytes(); + gas = vm->gas(); } catch (eth::VMException const& _e) { diff --git a/test/vm.cpp b/test/vm.cpp index 45034b716..02cee0a05 100644 --- a/test/vm.cpp +++ b/test/vm.cpp @@ -22,6 +22,7 @@ #include #include +#include #include "vm.h" using namespace std; @@ -298,14 +299,14 @@ void doVMTests(json_spirit::mValue& v, bool _fillin) } bytes output; - VM vm(fev.gas); + auto vm = eth::VMFactory::create(fev.gas); u256 gas; bool vmExceptionOccured = false; try { - output = vm.go(fev, fev.simpleTrace()).toBytes(); - gas = vm.gas(); + output = vm->go(fev, fev.simpleTrace()).toBytes(); + gas = vm->gas(); } catch (VMException const& _e) {