aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md5
-rw-r--r--libevmasm/Assembly.cpp61
-rw-r--r--test/libsolidity/SolidityOptimizer.cpp20
3 files changed, 50 insertions, 36 deletions
diff --git a/Changelog.md b/Changelog.md
index abd8d593..eb1e5e72 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,8 @@
+### 0.4.6 (2016-11-22)
+
+Bugfixes:
+ * Optimizer: Knowledge about state was not correctly cleared for JUMPDESTs
+
### 0.4.5 (2016-11-21)
Features:
diff --git a/libevmasm/Assembly.cpp b/libevmasm/Assembly.cpp
index a3037456..c394afa2 100644
--- a/libevmasm/Assembly.cpp
+++ b/libevmasm/Assembly.cpp
@@ -360,46 +360,35 @@ map<u256, u256> Assembly::optimiseInternal(bool _enable, bool _isCreation, size_
auto iter = m_items.begin();
while (iter != m_items.end())
{
- auto end = iter;
- while (end != m_items.end())
- if (SemanticInformation::altersControlFlow(*end++))
- break;
-
KnownState emptyState;
CommonSubexpressionEliminator eliminator(emptyState);
- auto blockIter = iter;
- auto const blockEnd = end;
- while (blockIter < blockEnd)
+ auto orig = iter;
+ iter = eliminator.feedItems(iter, m_items.end());
+ bool shouldReplace = false;
+ AssemblyItems optimisedChunk;
+ try
+ {
+ optimisedChunk = eliminator.getOptimizedItems();
+ shouldReplace = (optimisedChunk.size() < size_t(iter - orig));
+ }
+ catch (StackTooDeepException const&)
+ {
+ // This might happen if the opcode reconstruction is not as efficient
+ // as the hand-crafted code.
+ }
+ catch (ItemNotAvailableException const&)
{
- auto orig = blockIter;
- blockIter = eliminator.feedItems(blockIter, blockEnd);
- bool shouldReplace = false;
- AssemblyItems optimisedChunk;
- try
- {
- optimisedChunk = eliminator.getOptimizedItems();
- shouldReplace = (optimisedChunk.size() < size_t(blockIter - orig));
- }
- catch (StackTooDeepException const&)
- {
- // This might happen if the opcode reconstruction is not as efficient
- // as the hand-crafted code.
- }
- catch (ItemNotAvailableException const&)
- {
- // This might happen if e.g. associativity and commutativity rules
- // reorganise the expression tree, but not all leaves are available.
- }
-
- if (shouldReplace)
- {
- count++;
- optimisedItems += optimisedChunk;
- }
- else
- copy(orig, blockIter, back_inserter(optimisedItems));
+ // This might happen if e.g. associativity and commutativity rules
+ // reorganise the expression tree, but not all leaves are available.
}
- iter = end;
+
+ if (shouldReplace)
+ {
+ count++;
+ optimisedItems += optimisedChunk;
+ }
+ else
+ copy(orig, iter, back_inserter(optimisedItems));
}
if (optimisedItems.size() < m_items.size())
{
diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp
index 4991cf24..017fc0e9 100644
--- a/test/libsolidity/SolidityOptimizer.cpp
+++ b/test/libsolidity/SolidityOptimizer.cpp
@@ -1246,6 +1246,26 @@ BOOST_AUTO_TEST_CASE(dead_code_elimination_across_assemblies)
compareVersions("test()");
}
+BOOST_AUTO_TEST_CASE(invalid_state_at_control_flow_join)
+{
+ char const* sourceCode = R"(
+ contract Test {
+ uint256 public totalSupply = 100;
+ function f() returns (uint r) {
+ if (false)
+ r = totalSupply;
+ totalSupply -= 10;
+ }
+ function test() returns (uint) {
+ f();
+ return this.totalSupply();
+ }
+ }
+ )";
+ compileBothVersions(sourceCode);
+ compareVersions("test()");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}