aboutsummaryrefslogtreecommitdiffstats
path: root/StructuralGasEstimator.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-05-20 06:27:07 +0800
committerchriseth <c@ethdev.com>2015-05-20 06:28:15 +0800
commit2be64c702609df67903fd89c42cf632d71aad6fd (patch)
treeceb573ff287d81f47d75acbf8481eab631aa8081 /StructuralGasEstimator.cpp
parent70d9eb3f1d1e16757c8f9b66669cd0f38d7bfef7 (diff)
downloaddexon-solidity-2be64c702609df67903fd89c42cf632d71aad6fd.tar.gz
dexon-solidity-2be64c702609df67903fd89c42cf632d71aad6fd.tar.zst
dexon-solidity-2be64c702609df67903fd89c42cf632d71aad6fd.zip
Gas estimation taking known state into account.
Diffstat (limited to 'StructuralGasEstimator.cpp')
-rw-r--r--StructuralGasEstimator.cpp39
1 files changed, 36 insertions, 3 deletions
diff --git a/StructuralGasEstimator.cpp b/StructuralGasEstimator.cpp
index ececd711..9ce32ca5 100644
--- a/StructuralGasEstimator.cpp
+++ b/StructuralGasEstimator.cpp
@@ -23,6 +23,9 @@
#include "StructuralGasEstimator.h"
#include <map>
#include <functional>
+#include <memory>
+#include <libevmasm/ControlFlowGraph.h>
+#include <libevmasm/KnownState.h>
#include <libsolidity/AST.h>
#include <libsolidity/ASTVisitor.h>
@@ -38,14 +41,23 @@ StructuralGasEstimator::ASTGasConsumptionSelfAccumulated StructuralGasEstimator:
{
solAssert(std::count(_ast.begin(), _ast.end(), nullptr) == 0, "");
map<SourceLocation, GasMeter::GasConsumption> particularCosts;
- GasMeter meter;
- for (auto const& item: _items)
- particularCosts[item.getLocation()] += meter.estimateMax(item);
+ ControlFlowGraph cfg(_items);
+ for (BasicBlock const& block: cfg.optimisedBlocks())
+ {
+ assertThrow(!!block.startState, OptimizerException, "");
+ GasMeter meter(block.startState->copy());
+ auto const end = _items.begin() + block.end;
+ for (auto iter = _items.begin() + block.begin; iter != end; ++iter)
+ particularCosts[iter->getLocation()] += 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.getLocation()];
return true;
};
@@ -108,3 +120,24 @@ map<ASTNode const*, GasMeter::GasConsumption> StructuralGasEstimator::breakToSta
// gasCosts should only contain non-overlapping locations
return gasCosts;
}
+
+set<ASTNode const*> StructuralGasEstimator::finestNodesAtLocation(
+ vector<ASTNode const*> const& _roots
+)
+{
+ map<SourceLocation, ASTNode const*> locations;
+ set<ASTNode const*> nodes;
+ SimpleASTVisitor visitor(function<bool(ASTNode const&)>(), [&](ASTNode const& _n)
+ {
+ if (!locations.count(_n.getLocation()))
+ {
+ locations[_n.getLocation()] = &_n;
+ nodes.insert(&_n);
+ }
+ });
+
+ for (ASTNode const* root: _roots)
+ root->accept(visitor);
+ return nodes;
+}
+