Browse Source

VMFactory - a new way of creating VMs

cl-refactor
Paweł Bylica 10 years ago
parent
commit
b1dc0d5e6a
  1. 5
      libethereum/Executive.cpp
  2. 14
      libethereum/State.cpp
  3. 2
      libevm/ExtVMFace.h
  4. 8
      libevm/VM.h
  5. 46
      libevm/VMFactory.cpp
  6. 43
      libevm/VMFactory.h
  7. 8
      test/createRandomTest.cpp
  8. 7
      test/vm.cpp

5
libethereum/Executive.cpp

@ -21,6 +21,7 @@
#include <boost/timer.hpp> #include <boost/timer.hpp>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libevm/VMFactory.h>
#include <libevm/VM.h> #include <libevm/VM.h>
#include "Interface.h" #include "Interface.h"
#include "Executive.h" #include "Executive.h"
@ -105,7 +106,7 @@ bool Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu
if (m_s.addressHasCode(_receiveAddress)) if (m_s.addressHasCode(_receiveAddress))
{ {
m_vm.reset(new VM(_gas)); m_vm = VMFactory::create(_gas);
bytes const& c = m_s.code(_receiveAddress); bytes const& c = m_s.code(_receiveAddress);
m_ext.reset(new ExtVM(m_s, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &c, m_ms)); 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); m_s.m_cache[m_newAddress] = Account(m_s.balance(m_newAddress) + _endowment, Account::ContractConception);
// Execute _init. // 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)); m_ext.reset(new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init, m_ms));
return _init.empty(); return _init.empty();
} }

14
libethereum/State.cpp

@ -29,7 +29,7 @@
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libethcore/Exceptions.h> #include <libethcore/Exceptions.h>
#include <libevm/VM.h> #include <libevm/VMFactory.h>
#include "BlockChain.h" #include "BlockChain.h"
#include "Defaults.h" #include "Defaults.h"
#include "ExtVM.h" #include "ExtVM.h"
@ -1214,19 +1214,19 @@ bool State::call(Address _receiveAddress, Address _codeAddress, Address _senderA
} }
else if (addressHasCode(_codeAddress)) 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); ExtVM evm(*this, _receiveAddress, _senderAddress, _originAddress, _value, _gasPrice, _data, &code(_codeAddress), o_ms, _level);
bool revert = false; bool revert = false;
try try
{ {
auto out = vm.go(evm, _onOp); auto out = vm->go(evm, _onOp);
memcpy(_out.data(), out.data(), std::min(out.size(), _out.size())); memcpy(_out.data(), out.data(), std::min(out.size(), _out.size()));
if (o_sub) if (o_sub)
*o_sub += evm.sub; *o_sub += evm.sub;
if (o_ms) if (o_ms)
o_ms->output = out.toBytes(); o_ms->output = out.toBytes();
*_gas = vm.gas(); *_gas = vm->gas();
} }
catch (VMException const& _e) 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); m_cache[newAddress] = Account(balance(newAddress) + _endowment, Account::ContractConception);
// Execute init code. // Execute init code.
VM vm(*_gas); auto vm = VMFactory::create(*_gas);
ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level);
bool revert = false; bool revert = false;
bytesConstRef out; bytesConstRef out;
try try
{ {
out = vm.go(evm, _onOp); out = vm->go(evm, _onOp);
if (o_ms) if (o_ms)
o_ms->output = out.toBytes(); o_ms->output = out.toBytes();
if (o_sub) if (o_sub)
*o_sub += evm.sub; *o_sub += evm.sub;
*_gas = vm.gas(); *_gas = vm->gas();
} }
catch (VMException const& _e) catch (VMException const& _e)
{ {

2
libevm/ExtVMFace.h

@ -150,7 +150,7 @@ public:
BlockInfo previousBlock; ///< The previous block's information. BlockInfo previousBlock; ///< The previous block's information.
BlockInfo currentBlock; ///< The current block's information. BlockInfo currentBlock; ///< The current block's information.
SubState sub; ///< Sub-band VM state (suicides, refund counter, logs). 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.
}; };
} }

8
libevm/VM.h

@ -52,9 +52,6 @@ inline u256 fromAddress(Address _a)
class VM : public VMFace class VM : public VMFace
{ {
public: public:
/// Construct VM object.
explicit VM(u256 _gas = 0) : VMFace(_gas) {}
virtual void reset(u256 _gas = 0) noexcept override final; 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; 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; } u256s const& stack() const { return m_stack; }
private: private:
friend class VMFactory;
/// Construct VM object.
explicit VM(u256 _gas = 0) : VMFace(_gas) {}
template <class Ext> template <class Ext>
bytesConstRef goImpl(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1); bytesConstRef goImpl(Ext& _ext, OnOpFunc const& _onOp = OnOpFunc(), uint64_t _steps = (uint64_t)-1);

46
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 <http://www.gnu.org/licenses/>.
*/
#include "VMFactory.h"
#include <cassert>
#include "VM.h"
namespace dev
{
namespace eth
{
namespace
{
VMKind g_kind = VMKind::Interpreter;
}
void VMFactory::setKind(VMKind _kind)
{
g_kind = _kind;
}
std::unique_ptr<VMFace> VMFactory::create(u256 _gas)
{
assert(g_kind == VMKind::Interpreter && "Only interpreter supported for now");
return std::unique_ptr<VMFace>(new VM(_gas));
}
}
}

43
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 <http://www.gnu.org/licenses/>.
*/
#include "VMFace.h"
namespace dev
{
namespace eth
{
enum class VMKind : bool
{
Interpreter,
JIT
};
class VMFactory
{
public:
VMFactory() = delete;
static std::unique_ptr<VMFace> create(u256 _gas);
static void setKind(VMKind _kind);
};
}
}

8
test/createRandomTest.cpp

@ -32,7 +32,7 @@
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h> #include <libdevcore/CommonData.h>
#include <libevmcore/Instruction.h> #include <libevmcore/Instruction.h>
#include <libevm/VM.h> #include <libevm/VMFactory.h>
#include "vm.h" #include "vm.h"
using namespace std; using namespace std;
@ -142,14 +142,14 @@ void doMyTests(json_spirit::mValue& v)
} }
bytes output; bytes output;
eth::VM vm(fev.gas); auto vm = eth::VMFactory::create(fev.gas);
u256 gas; u256 gas;
bool vmExceptionOccured = false; bool vmExceptionOccured = false;
try try
{ {
output = vm.go(fev, fev.simpleTrace()).toBytes(); output = vm->go(fev, fev.simpleTrace()).toBytes();
gas = vm.gas(); gas = vm->gas();
} }
catch (eth::VMException const& _e) catch (eth::VMException const& _e)
{ {

7
test/vm.cpp

@ -22,6 +22,7 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <libethereum/Executive.h> #include <libethereum/Executive.h>
#include <libevm/VMFactory.h>
#include "vm.h" #include "vm.h"
using namespace std; using namespace std;
@ -298,14 +299,14 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
} }
bytes output; bytes output;
VM vm(fev.gas); auto vm = eth::VMFactory::create(fev.gas);
u256 gas; u256 gas;
bool vmExceptionOccured = false; bool vmExceptionOccured = false;
try try
{ {
output = vm.go(fev, fev.simpleTrace()).toBytes(); output = vm->go(fev, fev.simpleTrace()).toBytes();
gas = vm.gas(); gas = vm->gas();
} }
catch (VMException const& _e) catch (VMException const& _e)
{ {

Loading…
Cancel
Save