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 <libdevcore/CommonIO.h>
#include <libevm/VMFactory.h>
#include <libevm/VM.h>
#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();
}

14
libethereum/State.cpp

@ -29,7 +29,7 @@
#include <libdevcore/CommonIO.h>
#include <libevmcore/Instruction.h>
#include <libethcore/Exceptions.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#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)
{

2
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.
};
}

8
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 <class Ext>
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/CommonData.h>
#include <libevmcore/Instruction.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
#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)
{

7
test/vm.cpp

@ -22,6 +22,7 @@
#include <boost/filesystem.hpp>
#include <libethereum/Executive.h>
#include <libevm/VMFactory.h>
#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)
{

Loading…
Cancel
Save