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

Commit 8169302

Browse files
gumb0chfast
authored andcommitted
Get rid of global variables for trace function and context.
Store them as member variables of a class wrapping evmc_instance.
1 parent c289f48 commit 8169302

File tree

2 files changed

+103
-88
lines changed

2 files changed

+103
-88
lines changed

libaleth-interpreter/VM.cpp

Lines changed: 99 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,6 @@
2222

2323
namespace
2424
{
25-
evmc_trace_callback g_traceCallback = nullptr;
26-
evmc_tracer_context* g_traceContext = nullptr;
27-
28-
void destroy(evmc_instance* _instance)
29-
{
30-
(void)_instance;
31-
}
3225

3326
evmc_capabilities_flagset getCapabilities(evmc_instance* _instance) noexcept
3427
{
@@ -41,99 +34,115 @@ void delete_output(const evmc_result* result)
4134
delete[] result->output_data;
4235
}
4336

44-
evmc_result execute(evmc_instance* _instance, evmc_context* _context, evmc_revision _rev,
45-
evmc_message const* _msg, uint8_t const* _code, size_t _codeSize) noexcept
37+
class InterpreterEvmcInstance : public evmc_instance
4638
{
47-
(void)_instance;
48-
std::unique_ptr<dev::eth::VM> vm{new dev::eth::VM};
39+
public:
40+
static InterpreterEvmcInstance* create() { return new InterpreterEvmcInstance{}; }
4941

50-
evmc_result result = {};
51-
dev::eth::owning_bytes_ref output;
42+
private:
43+
InterpreterEvmcInstance()
44+
: evmc_instance{
45+
EVMC_ABI_VERSION, "interpreter", aleth_get_buildinfo()->project_version, destroy,
46+
execute, getCapabilities, setTracer,
47+
nullptr, // set_option
48+
}
49+
{}
5250

53-
try
54-
{
55-
output = vm->exec(_context, _rev, _msg, _code, _codeSize);
56-
result.status_code = EVMC_SUCCESS;
57-
result.gas_left = vm->m_io_gas;
58-
}
59-
catch (dev::eth::RevertInstruction& ex)
51+
static void destroy(evmc_instance* _instance)
6052
{
61-
result.status_code = EVMC_REVERT;
62-
result.gas_left = vm->m_io_gas;
63-
output = ex.output(); // This moves the output from the exception!
53+
delete static_cast<InterpreterEvmcInstance*>(_instance);
6454
}
65-
catch (dev::eth::BadInstruction const&)
66-
{
67-
result.status_code = EVMC_UNDEFINED_INSTRUCTION;
68-
}
69-
catch (dev::eth::OutOfStack const&)
70-
{
71-
result.status_code = EVMC_STACK_OVERFLOW;
72-
}
73-
catch (dev::eth::StackUnderflow const&)
74-
{
75-
result.status_code = EVMC_STACK_UNDERFLOW;
76-
}
77-
catch (dev::eth::BufferOverrun const&)
78-
{
79-
result.status_code = EVMC_INVALID_MEMORY_ACCESS;
80-
}
81-
catch (dev::eth::OutOfGas const&)
82-
{
83-
result.status_code = EVMC_OUT_OF_GAS;
84-
}
85-
catch (dev::eth::BadJumpDestination const&)
86-
{
87-
result.status_code = EVMC_BAD_JUMP_DESTINATION;
88-
}
89-
catch (dev::eth::DisallowedStateChange const&)
90-
{
91-
result.status_code = EVMC_STATIC_MODE_VIOLATION;
92-
}
93-
catch (dev::eth::VMException const&)
94-
{
95-
result.status_code = EVMC_FAILURE;
96-
}
97-
catch (...)
55+
56+
static evmc_result execute(evmc_instance* _instance, evmc_context* _context, evmc_revision _rev,
57+
evmc_message const* _msg, uint8_t const* _code, size_t _codeSize) noexcept
9858
{
99-
result.status_code = EVMC_INTERNAL_ERROR;
59+
std::unique_ptr<dev::eth::VM> vm{new dev::eth::VM};
60+
61+
evmc_result result = {};
62+
dev::eth::owning_bytes_ref output;
63+
64+
auto evmc = static_cast<InterpreterEvmcInstance*>(_instance);
65+
try
66+
{
67+
output = vm->exec(_context, _rev, _msg, _code, _codeSize, evmc->m_traceCallback,
68+
evmc->m_traceContext);
69+
result.status_code = EVMC_SUCCESS;
70+
result.gas_left = vm->m_io_gas;
71+
}
72+
catch (dev::eth::RevertInstruction& ex)
73+
{
74+
result.status_code = EVMC_REVERT;
75+
result.gas_left = vm->m_io_gas;
76+
output = ex.output(); // This moves the output from the exception!
77+
}
78+
catch (dev::eth::BadInstruction const&)
79+
{
80+
result.status_code = EVMC_UNDEFINED_INSTRUCTION;
81+
}
82+
catch (dev::eth::OutOfStack const&)
83+
{
84+
result.status_code = EVMC_STACK_OVERFLOW;
85+
}
86+
catch (dev::eth::StackUnderflow const&)
87+
{
88+
result.status_code = EVMC_STACK_UNDERFLOW;
89+
}
90+
catch (dev::eth::BufferOverrun const&)
91+
{
92+
result.status_code = EVMC_INVALID_MEMORY_ACCESS;
93+
}
94+
catch (dev::eth::OutOfGas const&)
95+
{
96+
result.status_code = EVMC_OUT_OF_GAS;
97+
}
98+
catch (dev::eth::BadJumpDestination const&)
99+
{
100+
result.status_code = EVMC_BAD_JUMP_DESTINATION;
101+
}
102+
catch (dev::eth::DisallowedStateChange const&)
103+
{
104+
result.status_code = EVMC_STATIC_MODE_VIOLATION;
105+
}
106+
catch (dev::eth::VMException const&)
107+
{
108+
result.status_code = EVMC_FAILURE;
109+
}
110+
catch (...)
111+
{
112+
result.status_code = EVMC_INTERNAL_ERROR;
113+
}
114+
115+
if (!output.empty())
116+
{
117+
// Make a copy of the output.
118+
auto outputData = new uint8_t[output.size()];
119+
std::memcpy(outputData, output.data(), output.size());
120+
result.output_data = outputData;
121+
result.output_size = output.size();
122+
result.release = delete_output;
123+
}
124+
125+
return result;
100126
}
101127

102-
if (!output.empty())
128+
static void setTracer(evmc_instance* _instance, evmc_trace_callback _callback,
129+
evmc_tracer_context* _context) noexcept
103130
{
104-
// Make a copy of the output.
105-
auto outputData = new uint8_t[output.size()];
106-
std::memcpy(outputData, output.data(), output.size());
107-
result.output_data = outputData;
108-
result.output_size = output.size();
109-
result.release = delete_output;
131+
auto evmc = static_cast<InterpreterEvmcInstance*>(_instance);
132+
133+
evmc->m_traceCallback = _callback;
134+
evmc->m_traceContext = _context;
110135
}
111136

112-
return result;
113-
}
137+
evmc_trace_callback m_traceCallback = nullptr;
138+
evmc_tracer_context* m_traceContext = nullptr;
139+
};
114140

115-
void setTracer(evmc_instance* /*_instance*/, evmc_trace_callback _callback,
116-
evmc_tracer_context* _context) noexcept
117-
{
118-
g_traceCallback = _callback;
119-
g_traceContext = _context;
120-
}
121141
} // namespace
122142

123143
extern "C" evmc_instance* evmc_create_interpreter() noexcept
124144
{
125-
// TODO: Allow creating multiple instances with different configurations.
126-
static evmc_instance s_instance{
127-
EVMC_ABI_VERSION,
128-
"interpreter",
129-
aleth_get_buildinfo()->project_version,
130-
::destroy,
131-
::execute,
132-
getCapabilities,
133-
::setTracer,
134-
nullptr, // set_option
135-
};
136-
return &s_instance;
145+
return InterpreterEvmcInstance::create();
137146
}
138147

139148
namespace dev
@@ -142,7 +151,7 @@ namespace eth
142151
{
143152
void VM::trace() noexcept
144153
{
145-
if (g_traceCallback)
154+
if (m_traceCallback)
146155
{
147156
auto const& metrics = c_metrics[static_cast<size_t>(m_OP)];
148157
evmc_uint256be topStackItem;
@@ -152,7 +161,7 @@ void VM::trace() noexcept
152161
topStackItem = toEvmC(m_SPP[0]);
153162
pushedStackItem = &topStackItem;
154163
}
155-
g_traceCallback(g_traceContext, m_PC, EVMC_SUCCESS, m_io_gas, m_stackEnd - m_SPP,
164+
m_traceCallback(m_traceContext, m_PC, EVMC_SUCCESS, m_io_gas, m_stackEnd - m_SPP,
156165
pushedStackItem, m_mem.size(), 0, 0, nullptr);
157166
}
158167
}
@@ -288,7 +297,8 @@ evmc_tx_context const& VM::getTxContext()
288297
// interpreter entry point
289298

290299
owning_bytes_ref VM::exec(evmc_context* _context, evmc_revision _rev, const evmc_message* _msg,
291-
uint8_t const* _code, size_t _codeSize)
300+
uint8_t const* _code, size_t _codeSize, evmc_trace_callback _traceCallback,
301+
evmc_tracer_context* _traceContext)
292302
{
293303
m_context = _context;
294304
m_rev = _rev;
@@ -297,6 +307,8 @@ owning_bytes_ref VM::exec(evmc_context* _context, evmc_revision _rev, const evmc
297307
m_PC = 0;
298308
m_pCode = _code;
299309
m_codeSize = _codeSize;
310+
m_traceCallback = _traceCallback;
311+
m_traceContext = _traceContext;
300312

301313
// trampoline to minimize depth of call stack when calling out
302314
m_bounce = &VM::initEntry;

libaleth-interpreter/VM.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ class VM
6666
VM() = default;
6767

6868
owning_bytes_ref exec(evmc_context* _context, evmc_revision _rev, const evmc_message* _msg,
69-
uint8_t const* _code, size_t _codeSize);
69+
uint8_t const* _code, size_t _codeSize, evmc_trace_callback _traceCallback,
70+
evmc_tracer_context* _traceContext);
7071

7172
uint64_t m_io_gas = 0;
7273
private:
@@ -115,6 +116,8 @@ class VM
115116
uint64_t m_newMemSize = 0;
116117
uint64_t m_copyMemSize = 0;
117118

119+
evmc_trace_callback m_traceCallback = nullptr;
120+
evmc_tracer_context* m_traceContext = nullptr;
118121
void trace() noexcept;
119122

120123
// initialize interpreter

0 commit comments

Comments
 (0)