Browse Source

Merge pull request #2167 from chfast/execution_stack_offloading

Execution stack offloading
cl-refactor
Gav Wood 10 years ago
parent
commit
0fba5c48c5
  1. 5
      cmake/EthCompilerSettings.cmake
  2. 59
      libethereum/ExtVM.cpp

5
cmake/EthCompilerSettings.cmake

@ -55,11 +55,6 @@ else ()
message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.")
endif ()
# Set stack memory limits
if (APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-stack_size,1000000")
endif()
if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")))
set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}")
set(CMAKE_C_FLAGS "-g ${CMAKE_C_FLAGS}")

59
libethereum/ExtVM.cpp

@ -20,18 +20,69 @@
*/
#include "ExtVM.h"
#include <exception>
#include <boost/thread.hpp>
#include "Executive.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
namespace
{
static unsigned const c_depthLimit = 1024;
/// Upper bound of stack space needed by single CALL/CREATE execution. Set experimentally.
static size_t const c_singleExecutionStackSize = 12 * 1024;
/// Standard OSX thread stack limit. Should be reasonable for other platforms too.
static size_t const c_defaultStackSize = 512 * 1024;
/// On what depth execution should be offloaded to additional separated stack space.
static unsigned const c_offloadPoint = c_defaultStackSize / c_singleExecutionStackSize;
void goOnOffloadedStack(Executive& _e, OnOpFunc const& _onOp)
{
// Set new stack size enouth to handle the rest of the calls up to the limit.
boost::thread::attributes attrs;
attrs.set_stack_size((c_depthLimit - c_offloadPoint) * c_singleExecutionStackSize);
// Create new thread with big stack and join immediately.
// TODO: It is possible to switch the implementation to Boost.Context or similar when the API is stable.
std::exception_ptr exception;
boost::thread{attrs, [&]{
try
{
_e.go(_onOp);
}
catch (...)
{
exception = std::current_exception(); // Catch all exceptions to be rethrown in parent thread.
}
}}.join();
if (exception)
std::rethrow_exception(exception);
}
void go(unsigned _depth, Executive& _e, OnOpFunc const& _onOp)
{
// If in the offloading point we need to switch to additional separated stack space.
// Current stack is too small to handle more CALL/CREATE executions.
// It needs to be done only once as newly allocated stack space it enough to handle
// the rest of the calls up to the depth limit (c_depthLimit).
if (_depth == c_offloadPoint)
goOnOffloadedStack(_e, _onOp);
else
_e.go(_onOp);
}
}
bool ExtVM::call(CallParameters& _p)
{
Executive e(m_s, lastHashes, depth + 1);
if (!e.call(_p, gasPrice, origin))
{
e.go(_p.onOp);
go(depth, e, _p.onOp);
e.accrueSubState(sub);
}
_p.gas = e.gas();
@ -47,7 +98,7 @@ h160 ExtVM::create(u256 _endowment, u256& io_gas, bytesConstRef _code, OnOpFunc
Executive e(m_s, lastHashes, depth + 1);
if (!e.create(myAddress, _endowment, gasPrice, io_gas, _code, origin))
{
e.go(_onOp);
go(depth, e, _onOp);
e.accrueSubState(sub);
}
io_gas = e.gas();

Loading…
Cancel
Save