diff options
author | chriseth <c@ethdev.com> | 2015-05-20 06:27:07 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-05-20 06:28:15 +0800 |
commit | 2be64c702609df67903fd89c42cf632d71aad6fd (patch) | |
tree | ceb573ff287d81f47d75acbf8481eab631aa8081 /StructuralGasEstimator.cpp | |
parent | 70d9eb3f1d1e16757c8f9b66669cd0f38d7bfef7 (diff) | |
download | dexon-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.cpp | 39 |
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; +} + |