Browse Source

Merge pull request #437 from imapp-pl/pr-jit

EVM JIT connector
cl-refactor
Gav Wood 10 years ago
parent
commit
c3fba00f2f
  1. 4
      .gitmodules
  2. 11
      CMakeLists.txt
  3. 1
      evmjit
  4. 2
      libdevcore/CommonIO.cpp
  5. 3
      libevm/CMakeLists.txt
  6. 10
      libevm/VMFactory.cpp
  7. 19
      test/TestHelper.cpp
  8. 1
      test/TestHelper.h
  9. 2
      test/state.cpp
  10. 24
      test/vm.cpp

4
.gitmodules

@ -0,0 +1,4 @@
[submodule "evmjit"]
path = evmjit
url = https://github.com/ethereum/evmjit
branch = develop

11
CMakeLists.txt

@ -18,6 +18,7 @@ function(createDefaultCacheConfig)
set(VMTRACE OFF CACHE BOOL "VM tracing and run-time checks (useful for cross-implementation VM debugging)")
set(PARANOIA OFF CACHE BOOL "Additional run-time checks")
set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on")
set(EVMJIT OFF CACHE BOOL "Build a just-in-time compiler for EVM code (requires LLVM)")
endfunction()
@ -38,6 +39,10 @@ function(configureProject)
message(FATAL_ERROR "VM tracing requires debug.")
endif ()
endif ()
if (EVMJIT)
add_definitions(-DETH_EVMJIT)
endif()
endfunction()
@ -84,7 +89,7 @@ cmake_policy(SET CMP0015 NEW)
createDefaultCacheConfig()
configureProject()
message("-- VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}; JSONRPC: ${JSONRPC}")
message("-- VMTRACE: ${VMTRACE}; PARANOIA: ${PARANOIA}; HEADLESS: ${HEADLESS}; JSONRPC: ${JSONRPC}; EVMJIT: ${EVMJIT}")
# Default TARGET_PLATFORM to "linux".
@ -151,6 +156,10 @@ if (NOT HEADLESS)
endif()
if (EVMJIT)
add_subdirectory(evmjit)
endif()
enable_testing()
add_test(NAME alltests WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test COMMAND testeth)

1
evmjit

@ -0,0 +1 @@
Subproject commit ed63ced24456c28b6dba345b8fc61e680ed406d7

2
libdevcore/CommonIO.cpp

@ -65,6 +65,8 @@ bytes dev::contents(std::string const& _file)
// get length of file:
is.seekg (0, is.end);
streamoff length = is.tellg();
if (length == 0) // return early, MSVC does not like reading 0 bytes
return {};
is.seekg (0, is.beg);
bytes ret(length);
is.read((char*)ret.data(), length);

3
libevm/CMakeLists.txt

@ -30,6 +30,9 @@ target_link_libraries(${EXECUTABLE} ethcore)
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} evmcore)
target_link_libraries(${EXECUTABLE} devcore)
if (EVMJIT)
target_link_libraries(${EXECUTABLE} evmjit-cpp)
endif()
install( TARGETS ${EXECUTABLE} ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )

10
libevm/VMFactory.cpp

@ -18,6 +18,10 @@
#include "VMFactory.h"
#include "VM.h"
#if ETH_EVMJIT
#include <evmjit/libevmjit-cpp/JitVM.h>
#endif
namespace dev
{
namespace eth
@ -34,8 +38,12 @@ void VMFactory::setKind(VMKind _kind)
std::unique_ptr<VMFace> VMFactory::create(u256 _gas)
{
asserts(g_kind == VMKind::Interpreter && "Only interpreter supported for now");
#if ETH_EVMJIT
return std::unique_ptr<VMFace>(g_kind == VMKind::JIT ? (VMFace*)new JitVM(_gas) : new VM(_gas));
#else
asserts(g_kind == VMKind::Interpreter && "JIT disabled in build configuration");
return std::unique_ptr<VMFace>(new VM(_gas));
#endif
}
}

19
test/TestHelper.cpp

@ -26,6 +26,7 @@
#include <boost/filesystem/path.hpp>
#include <libethereum/Client.h>
#include <liblll/Compiler.h>
#include <libevm/VMFactory.h>
using namespace std;
using namespace dev::eth;
@ -330,7 +331,7 @@ void checkStorage(map<u256, u256> _expectedStore, map<u256, u256> _resultStore,
}
}
BOOST_CHECK_EQUAL(_resultStore.size(), _expectedStore.size());
for (auto&& resultStorePair : _resultStore)
for (auto&& resultStorePair: _resultStore)
{
if (!_expectedStore.count(resultStorePair.first))
BOOST_ERROR(_expectedAddr << ": unexpected store key " << resultStorePair.first);
@ -472,4 +473,20 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun
}
}
void processCommandLineOptions()
{
auto argc = boost::unit_test::framework::master_test_suite().argc;
auto argv = boost::unit_test::framework::master_test_suite().argv;
for (auto i = 0; i < argc; ++i)
{
if (std::string(argv[i]) == "--jit")
{
eth::VMFactory::setKind(eth::VMKind::JIT);
break;
}
}
}
} } // namespaces

1
test/TestHelper.h

@ -76,6 +76,7 @@ void checkLog(eth::LogEntries _resultLogs, eth::LogEntries _expectedLogs);
void executeTests(const std::string& _name, const std::string& _testPathAppendix, std::function<void(json_spirit::mValue&, bool)> doTests);
std::string getTestPath();
void userDefinedTest(std::string testTypeFlag, std::function<void(json_spirit::mValue&, bool)> doTests);
void processCommandLineOptions();
template<typename mapType>
void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs)

2
test/state.cpp

@ -43,6 +43,8 @@ namespace dev { namespace test {
void doStateTests(json_spirit::mValue& v, bool _fillin)
{
processCommandLineOptions();
for (auto& i: v.get_obj())
{
cerr << i.first << endl;

24
test/vm.cpp

@ -20,6 +20,7 @@
* vm test functions.
*/
#include <chrono>
#include <boost/filesystem.hpp>
#include <libethereum/Executive.h>
#include <libevm/VMFactory.h>
@ -308,6 +309,8 @@ namespace dev { namespace test {
void doVMTests(json_spirit::mValue& v, bool _fillin)
{
processCommandLineOptions();
for (auto& i: v.get_obj())
{
cnote << i.first;
@ -317,7 +320,7 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
BOOST_REQUIRE(o.count("pre") > 0);
BOOST_REQUIRE(o.count("exec") > 0);
dev::test::FakeExtVM fev;
FakeExtVM fev;
fev.importEnv(o["env"].get_obj());
fev.importState(o["pre"].get_obj());
@ -332,12 +335,12 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
}
bytes output;
auto vm = eth::VMFactory::create(fev.gas);
u256 gas;
bool vmExceptionOccured = false;
auto startTime = std::chrono::high_resolution_clock::now();
try
{
auto vm = eth::VMFactory::create(fev.gas);
output = vm->go(fev, fev.simpleTrace()).toBytes();
gas = vm->gas();
}
@ -357,6 +360,21 @@ void doVMTests(json_spirit::mValue& v, bool _fillin)
BOOST_ERROR("Failed VM Test with Exception: " << _e.what());
}
auto endTime = std::chrono::high_resolution_clock::now();
auto argc = boost::unit_test::framework::master_test_suite().argc;
auto argv = boost::unit_test::framework::master_test_suite().argv;
for (auto i = 0; i < argc; ++i)
{
if (std::string(argv[i]) == "--show-times")
{
auto testDuration = endTime - startTime;
cnote << "Execution time: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(testDuration).count()
<< " ms";
break;
}
}
// delete null entries in storage for the sake of comparison
for (auto &a: fev.addresses)

Loading…
Cancel
Save