Merge pull request #9978 from ethereum/dead-code-cleanup

Dead code cleanup
This commit is contained in:
chriseth 2020-10-07 14:10:20 +02:00 committed by GitHub
commit 22caed1e1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 0 additions and 198 deletions

View File

@ -313,46 +313,4 @@ private:
std::function<void(ASTNode const&)> m_onEndVisit;
};
/**
* Utility class that visits the AST in depth-first order and calls a function on each node and each edge.
* Child nodes are only visited if the node callback of the parent returns true.
* The node callback of a parent is called before any edge or node callback involving the children.
* The edge callbacks of all children are called before the edge callback of the parent.
* This way, the node callback can be used as an initializing callback and the edge callbacks can be
* used to compute a "reduce" function.
*/
class ASTReduce: public ASTConstVisitor
{
public:
/**
* Constructs a new ASTReduce object with the given callback functions.
* @param _onNode called for each node, before its child edges and nodes, should return true to descend deeper
* @param _onEdge called for each edge with (parent, child)
*/
ASTReduce(
std::function<bool(ASTNode const&)> _onNode,
std::function<void(ASTNode const&, ASTNode const&)> _onEdge
): m_onNode(std::move(_onNode)), m_onEdge(std::move(_onEdge))
{
}
protected:
bool visitNode(ASTNode const& _node) override
{
m_parents.push_back(&_node);
return m_onNode(_node);
}
void endVisitNode(ASTNode const& _node) override
{
m_parents.pop_back();
if (!m_parents.empty())
m_onEdge(*m_parents.back(), _node);
}
private:
std::vector<ASTNode const*> m_parents;
std::function<bool(ASTNode const&)> m_onNode;
std::function<void(ASTNode const&, ASTNode const&)> m_onEdge;
};
}

View File

@ -42,93 +42,6 @@ using namespace solidity::evmasm;
using namespace solidity::frontend;
using namespace solidity::langutil;
GasEstimator::ASTGasConsumptionSelfAccumulated GasEstimator::structuralEstimation(
AssemblyItems const& _items,
vector<ASTNode const*> const& _ast
) const
{
solAssert(std::count(_ast.begin(), _ast.end(), nullptr) == 0, "");
map<SourceLocation, GasConsumption> particularCosts;
ControlFlowGraph cfg(_items);
for (BasicBlock const& block: cfg.optimisedBlocks())
{
solAssert(!!block.startState, "");
GasMeter meter(block.startState->copy(), m_evmVersion);
auto const end = _items.begin() + static_cast<ptrdiff_t>(block.end);
for (auto iter = _items.begin() + static_cast<ptrdiff_t>(block.begin); iter != end; ++iter)
particularCosts[iter->location()] += meter.estimateMax(*iter);
}
set<ASTNode const*> finestNodes = finestNodesAtLocation(_ast);
ASTGasConsumptionSelfAccumulated gasCosts;
auto onNode = [&](ASTNode const& _node)
{
if (!finestNodes.count(&_node))
return true;
gasCosts[&_node][0] = gasCosts[&_node][1] = particularCosts[_node.location()];
return true;
};
auto onEdge = [&](ASTNode const& _parent, ASTNode const& _child)
{
gasCosts[&_parent][1] += gasCosts[&_child][1];
};
ASTReduce folder(onNode, onEdge);
for (ASTNode const* ast: _ast)
ast->accept(folder);
return gasCosts;
}
map<ASTNode const*, GasMeter::GasConsumption> GasEstimator::breakToStatementLevel(
ASTGasConsumptionSelfAccumulated const& _gasCosts,
vector<ASTNode const*> const& _roots
)
{
solAssert(std::count(_roots.begin(), _roots.end(), nullptr) == 0, "");
// first pass: statementDepth[node] is the distance from the deepend statement to node
// in direction of the tree root (or undefined if not possible)
map<ASTNode const*, int> statementDepth;
auto onNodeFirstPass = [&](ASTNode const& _node)
{
if (dynamic_cast<Statement const*>(&_node))
statementDepth[&_node] = 0;
return true;
};
auto onEdgeFirstPass = [&](ASTNode const& _parent, ASTNode const& _child)
{
if (statementDepth.count(&_child))
statementDepth[&_parent] = max(statementDepth[&_parent], statementDepth[&_child] + 1);
};
ASTReduce firstPass(onNodeFirstPass, onEdgeFirstPass);
for (ASTNode const* node: _roots)
node->accept(firstPass);
// we use the location of a node if
// - its statement depth is 0 or
// - its statement depth is undefined but the parent's statement depth is at least 1
map<ASTNode const*, GasConsumption> gasCosts;
auto onNodeSecondPass = [&](ASTNode const& _node)
{
return statementDepth.count(&_node);
};
auto onEdgeSecondPass = [&](ASTNode const& _parent, ASTNode const& _child)
{
bool useNode = false;
if (statementDepth.count(&_child))
useNode = statementDepth[&_child] == 0;
else
useNode = statementDepth.count(&_parent) && statementDepth.at(&_parent) > 0;
if (useNode)
gasCosts[&_child] = _gasCosts.at(&_child)[1];
};
ASTReduce secondPass(onNodeSecondPass, onEdgeSecondPass);
for (ASTNode const* node: _roots)
node->accept(secondPass);
// gasCosts should only contain non-overlapping locations
return gasCosts;
}
GasEstimator::GasConsumption GasEstimator::functionalEstimation(
AssemblyItems const& _items,
string const& _signature

View File

@ -48,22 +48,6 @@ public:
explicit GasEstimator(langutil::EVMVersion _evmVersion): m_evmVersion(_evmVersion) {}
/// Estimates the gas consumption for every assembly item in the given assembly and stores
/// it by source location.
/// @returns a mapping from each AST node to a pair of its particular and syntactically accumulated gas costs.
ASTGasConsumptionSelfAccumulated structuralEstimation(
evmasm::AssemblyItems const& _items,
std::vector<ASTNode const*> const& _ast
) const;
/// @returns a mapping from nodes with non-overlapping source locations to gas consumptions such that
/// the following source locations are part of the mapping:
/// 1. source locations of statements that do not contain other statements
/// 2. maximal source locations that do not overlap locations coming from the first rule
static ASTGasConsumption breakToStatementLevel(
ASTGasConsumptionSelfAccumulated const& _gasCosts,
std::vector<ASTNode const*> const& _roots
);
/// @returns the estimated gas consumption by the (public or external) function with the
/// given signature. If no signature is given, estimates the maximum gas usage.
GasConsumption functionalEstimation(

View File

@ -1638,18 +1638,6 @@ void CommandLineInterface::handleAst(string const& _argStr)
vector<ASTNode const*> asts;
for (auto const& sourceCode: m_sourceCodes)
asts.push_back(&m_compiler->ast(sourceCode.first));
map<ASTNode const*, evmasm::GasMeter::GasConsumption> gasCosts;
for (auto const& contract: m_compiler->contractNames())
if (m_compiler->compilationSuccessful())
if (auto const* assemblyItems = m_compiler->runtimeAssemblyItems(contract))
{
auto ret = GasEstimator::breakToStatementLevel(
GasEstimator(m_evmVersion).structuralEstimation(*assemblyItems, asts),
asts
);
for (auto const& it: ret)
gasCosts[it.first] += it.second;
}
bool legacyFormat = !m_args.count(g_argAstCompactJson);
if (m_args.count(g_argOutputDir))

View File

@ -49,14 +49,6 @@ public:
m_compiler.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
m_compiler.setEVMVersion(m_evmVersion);
BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed");
AssemblyItems const* items = m_compiler.runtimeAssemblyItems(m_compiler.lastContractName());
ASTNode const& sourceUnit = m_compiler.ast("");
BOOST_REQUIRE(items != nullptr);
m_gasCosts = GasEstimator::breakToStatementLevel(
GasEstimator(solidity::test::CommonOptions::get().evmVersion()).structuralEstimation(*items, vector<ASTNode const*>({&sourceUnit})),
{&sourceUnit}
);
}
void testCreationTimeGas(string const& _sourceCode, u256 const& _tolerance = u256(0))
@ -118,43 +110,10 @@ public:
gas += i != 0 ? GasCosts::txDataNonZeroGas(evmVersion) : GasCosts::txDataZeroGas;
return gas;
}
protected:
map<ASTNode const*, evmasm::GasMeter::GasConsumption> m_gasCosts;
};
BOOST_FIXTURE_TEST_SUITE(GasMeterTests, GasMeterTestFramework)
BOOST_AUTO_TEST_CASE(non_overlapping_filtered_costs)
{
char const* sourceCode = R"(
contract test {
bytes x;
function f(uint a) public returns (uint b) {
for (; a < 200; ++a) {
x.push(0x09);
b = a * a;
}
return f(a - 1);
}
}
)";
compile(sourceCode);
for (auto first = m_gasCosts.cbegin(); first != m_gasCosts.cend(); ++first)
{
auto second = first;
for (++second; second != m_gasCosts.cend(); ++second)
if (first->first->location().intersects(second->first->location()))
{
BOOST_CHECK_MESSAGE(false, "Source locations should not overlap!");
langutil::SourceReferenceFormatter formatter(cout);
formatter.printSourceLocation(&first->first->location());
formatter.printSourceLocation(&second->first->location());
}
}
}
BOOST_AUTO_TEST_CASE(simple_contract)
{
// Tests a simple "deploy contract" code without constructor. The actual contract is not relevant.