Skip to content
This repository has been archived by the owner on Oct 28, 2021. It is now read-only.

Commit

Permalink
Get rid of global variables for trace function and context.
Browse files Browse the repository at this point in the history
Store them as member variables of a class wrapping evmc_instance.
  • Loading branch information
gumb0 committed Aug 7, 2018
1 parent e89c186 commit df1517f
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 62 deletions.
140 changes: 79 additions & 61 deletions libaleth-interpreter/VM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,87 +22,102 @@

namespace
{
evmc_trace_callback g_traceCallback = nullptr;
evmc_tracer_context* g_traceContext = nullptr;

void destroy(evmc_instance* _instance)
{
(void)_instance;
}

void delete_output(const evmc_result* result)
{
delete[] result->output_data;
}

evmc_result execute(evmc_instance* _instance, evmc_context* _context, evmc_revision _rev,
evmc_message const* _msg, uint8_t const* _code, size_t _codeSize) noexcept
class InterpreterEvmcInstance : public evmc_instance
{
(void)_instance;
std::unique_ptr<dev::eth::VM> vm{new dev::eth::VM};
public:
static InterpreterEvmcInstance* create() { return new InterpreterEvmcInstance{}; }

evmc_result result = {};
dev::eth::owning_bytes_ref output;

try
{
output = vm->exec(_context, _rev, _msg, _code, _codeSize);
result.status_code = EVMC_SUCCESS;
result.gas_left = vm->m_io_gas;
}
catch (dev::eth::RevertInstruction& ex)
{
result.status_code = EVMC_REVERT;
result.gas_left = vm->m_io_gas;
output = ex.output(); // This moves the output from the exception!
}
catch (dev::eth::BadInstruction const&)
{
result.status_code = EVMC_UNDEFINED_INSTRUCTION;
}
catch (dev::eth::DisallowedStateChange const&)
private:
InterpreterEvmcInstance()
: evmc_instance{
EVMC_ABI_VERSION, "interpreter", aleth_get_buildinfo()->project_version, destroy,
execute, setTracer,
nullptr, // set_option
}
{
result.status_code = EVMC_STATIC_MODE_VIOLATION;
}
catch (dev::eth::VMException const&)

static void destroy(evmc_instance* _instance)
{
result.status_code = EVMC_FAILURE;
delete static_cast<InterpreterEvmcInstance*>(_instance);
}
catch (...)

static evmc_result execute(evmc_instance* _instance, evmc_context* _context, evmc_revision _rev,
evmc_message const* _msg, uint8_t const* _code, size_t _codeSize) noexcept
{
result.status_code = EVMC_INTERNAL_ERROR;
std::unique_ptr<dev::eth::VM> vm{new dev::eth::VM};

evmc_result result = {};
dev::eth::owning_bytes_ref output;

auto evmc = static_cast<InterpreterEvmcInstance*>(_instance);
try
{
output = vm->exec(_context, _rev, _msg, _code, _codeSize, evmc->m_traceCallback,
evmc->m_traceContext);
result.status_code = EVMC_SUCCESS;
result.gas_left = vm->m_io_gas;
}
catch (dev::eth::RevertInstruction& ex)
{
result.status_code = EVMC_REVERT;
result.gas_left = vm->m_io_gas;
output = ex.output(); // This moves the output from the exception!
}
catch (dev::eth::BadInstruction const&)
{
result.status_code = EVMC_UNDEFINED_INSTRUCTION;
}
catch (dev::eth::DisallowedStateChange const&)
{
result.status_code = EVMC_STATIC_MODE_VIOLATION;
}
catch (dev::eth::VMException const&)
{
result.status_code = EVMC_FAILURE;
}
catch (...)
{
result.status_code = EVMC_INTERNAL_ERROR;
}

if (!output.empty())
{
// Make a copy of the output.
auto outputData = new uint8_t[output.size()];
std::memcpy(outputData, output.data(), output.size());
result.output_data = outputData;
result.output_size = output.size();
result.release = delete_output;
}

return result;
}

if (!output.empty())
static void setTracer(evmc_instance* _instance, evmc_trace_callback _callback,
evmc_tracer_context* _context) noexcept
{
// Make a copy of the output.
auto outputData = new uint8_t[output.size()];
std::memcpy(outputData, output.data(), output.size());
result.output_data = outputData;
result.output_size = output.size();
result.release = delete_output;
auto evmc = static_cast<InterpreterEvmcInstance*>(_instance);

evmc->m_traceCallback = _callback;
evmc->m_traceContext = _context;
}

return result;
}
evmc_trace_callback m_traceCallback = nullptr;
evmc_tracer_context* m_traceContext = nullptr;
};

void setTracer(evmc_instance* /*_instance*/, evmc_trace_callback _callback,
evmc_tracer_context* _context) noexcept
{
g_traceCallback = _callback;
g_traceContext = _context;
}
} // namespace

extern "C" evmc_instance* evmc_create_interpreter() noexcept
{
// TODO: Allow creating multiple instances with different configurations.
static evmc_instance s_instance{
EVMC_ABI_VERSION, "interpreter", aleth_get_buildinfo()->project_version, ::destroy,
::execute, ::setTracer,
nullptr, // set_option
};
return &s_instance;
return InterpreterEvmcInstance::create();
}

namespace dev
Expand All @@ -111,7 +126,7 @@ namespace eth
{
void VM::trace() noexcept
{
if (g_traceCallback)
if (m_traceCallback)
{
auto const& metrics = c_metrics[static_cast<size_t>(m_OP)];
evmc_uint256be topStackItem;
Expand All @@ -121,7 +136,7 @@ void VM::trace() noexcept
topStackItem = toEvmC(m_SPP[0]);
pushedStackItem = &topStackItem;
}
g_traceCallback(g_traceContext, m_PC, EVMC_SUCCESS, m_io_gas, m_stackEnd - m_SPP,
m_traceCallback(m_traceContext, m_PC, EVMC_SUCCESS, m_io_gas, m_stackEnd - m_SPP,
pushedStackItem, m_mem.size(), 0, 0, nullptr);
}
}
Expand Down Expand Up @@ -269,7 +284,8 @@ evmc_tx_context const& VM::getTxContext()
// interpreter entry point

owning_bytes_ref VM::exec(evmc_context* _context, evmc_revision _rev, const evmc_message* _msg,
uint8_t const* _code, size_t _codeSize)
uint8_t const* _code, size_t _codeSize, evmc_trace_callback _traceCallback,
evmc_tracer_context* _traceContext)
{
m_context = _context;
m_rev = _rev;
Expand All @@ -278,6 +294,8 @@ owning_bytes_ref VM::exec(evmc_context* _context, evmc_revision _rev, const evmc
m_PC = 0;
m_pCode = _code;
m_codeSize = _codeSize;
m_traceCallback = _traceCallback;
m_traceContext = _traceContext;

// trampoline to minimize depth of call stack when calling out
m_bounce = &VM::initEntry;
Expand Down
5 changes: 4 additions & 1 deletion libaleth-interpreter/VM.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ class VM
VM() = default;

owning_bytes_ref exec(evmc_context* _context, evmc_revision _rev, const evmc_message* _msg,
uint8_t const* _code, size_t _codeSize);
uint8_t const* _code, size_t _codeSize, evmc_trace_callback _traceCallback,
evmc_tracer_context* _traceContext);

uint64_t m_io_gas = 0;
private:
Expand Down Expand Up @@ -114,6 +115,8 @@ class VM
uint64_t m_newMemSize = 0;
uint64_t m_copyMemSize = 0;

evmc_trace_callback m_traceCallback = nullptr;
evmc_tracer_context* m_traceContext = nullptr;
void trace() noexcept;

// initialize interpreter
Expand Down

0 comments on commit df1517f

Please sign in to comment.