Skip to content

Commit

Permalink
squash! Support all depths in Histogram
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed May 19, 2021
1 parent c96e184 commit c6b866b
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 29 deletions.
61 changes: 35 additions & 26 deletions lib/evmone/tracing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,61 @@

#include "tracing.hpp"
#include <evmc/hex.hpp>
#include <stack>

namespace evmone
{
namespace
{
std::string get_name(const char* const* names, uint8_t opcode)
{
const auto name = names[opcode];
return (name != nullptr) ? name : "0x" + evmc::hex(opcode);
}

/// @see create_histogram_tracer()
class HistogramTracer : public Tracer
{
const uint8_t* m_code = nullptr;
int32_t m_depth = -1;
const char* const* m_opcode_names = nullptr;
uint32_t m_counts[256]{};
struct Context
{
const int32_t depth;
const uint8_t* const code;
const char* const* const opcode_names;
uint32_t counts[256]{};

Context(int32_t _depth, const uint8_t* _code, const char* const* _opcode_names) noexcept
: depth{_depth}, code{_code}, opcode_names{_opcode_names}
{}
};

std::stack<Context> m_contexts;
std::ostream& m_out;

void on_execution_start(
evmc_revision rev, const evmc_message& msg, bytes_view code) noexcept override
{
m_code = code.data();
m_depth = msg.depth;
if (m_depth == 0)
m_opcode_names = evmc_get_instruction_names_table(rev);
m_contexts.emplace(msg.depth, code.data(), evmc_get_instruction_names_table(rev));
}

void on_instruction_start(uint32_t pc) noexcept override { ++m_counts[m_code[pc]]; }
void on_instruction_start(uint32_t pc) noexcept override
{
auto& ctx = m_contexts.top();
++ctx.counts[ctx.code[pc]];
}

void on_execution_end(const evmc_result& /*result*/) noexcept override
{
if (m_depth == 0)
{
m_out << "--- # HISTOGRAM\nopcode,count\n";
for (size_t i = 0; i < std::size(m_counts); ++i)
{
if (m_counts[i] != 0)
{
if (const auto name = m_opcode_names[i]; name != nullptr)
m_out << name;
else
m_out << "0x" << evmc::hex(static_cast<uint8_t>(i));
m_out << ',' << m_counts[i] << '\n';
}
}
const auto& ctx = m_contexts.top();
const auto names = ctx.opcode_names;

m_opcode_names = nullptr;
m_depth = -1;
m_code = nullptr;
m_out << "--- # HISTOGRAM depth=" << ctx.depth << "\nopcode,count\n";
for (size_t i = 0; i < std::size(ctx.counts); ++i)
{
if (ctx.counts[i] != 0)
m_out << get_name(names, static_cast<uint8_t>(i)) << ',' << ctx.counts[i] << '\n';
}

m_contexts.pop();
}

public:
Expand Down
14 changes: 11 additions & 3 deletions test/unittests/tracing_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ TEST_F(tracing, histogram)

trace_stream << '\n';
EXPECT_EQ(trace(add(0, 0)), R"(
--- # HISTOGRAM
--- # HISTOGRAM depth=0
opcode,count
ADD,1
PUSH1,2
Expand All @@ -116,7 +116,7 @@ TEST_F(tracing, histogram_undefined_instruction)

trace_stream << '\n';
EXPECT_EQ(trace(bytecode{"EF"}), R"(
--- # HISTOGRAM
--- # HISTOGRAM depth=0
opcode,count
0xef,1
)");
Expand All @@ -125,5 +125,13 @@ opcode,count
TEST_F(tracing, histogram_internal_call)
{
vm.add_tracer(evmone::create_histogram_tracer(trace_stream));
EXPECT_EQ(trace(add(0, 0), 1), ""); // No output on depth=1.
trace_stream << '\n';
EXPECT_EQ(trace(push(0) + OP_DUP1 + OP_SWAP1 + OP_POP + OP_POP, 1), R"(
--- # HISTOGRAM depth=1
opcode,count
POP,2
PUSH1,1
DUP1,1
SWAP1,1
)");
}

0 comments on commit c6b866b

Please sign in to comment.