diff options
author | chriseth <c@ethdev.com> | 2015-04-30 21:31:16 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-05-06 17:11:16 +0800 |
commit | a2e3bcbd0c45a79a9709dc8a69858765ab904805 (patch) | |
tree | 1201a25150145a991ef11c5f62465986c6b27dea | |
parent | 867101e40981db56d8b72fd363e4f9e376991284 (diff) | |
download | dexon-solidity-a2e3bcbd0c45a79a9709dc8a69858765ab904805.tar.gz dexon-solidity-a2e3bcbd0c45a79a9709dc8a69858765ab904805.tar.zst dexon-solidity-a2e3bcbd0c45a79a9709dc8a69858765ab904805.zip |
Make KnownState work with all instructions.
-rw-r--r-- | ExpressionClasses.cpp | 19 | ||||
-rw-r--r-- | KnownState.cpp | 7 | ||||
-rw-r--r-- | SemanticInformation.cpp | 54 | ||||
-rw-r--r-- | SemanticInformation.h | 9 |
4 files changed, 83 insertions, 6 deletions
diff --git a/ExpressionClasses.cpp b/ExpressionClasses.cpp index e62f7526..cfbeba7f 100644 --- a/ExpressionClasses.cpp +++ b/ExpressionClasses.cpp @@ -57,12 +57,15 @@ ExpressionClasses::Id ExpressionClasses::find( exp.arguments = _arguments; exp.sequenceNumber = _sequenceNumber; - if (SemanticInformation::isCommutativeOperation(_item)) - sort(exp.arguments.begin(), exp.arguments.end()); + if (SemanticInformation::isDeterministic(_item)) + { + if (SemanticInformation::isCommutativeOperation(_item)) + sort(exp.arguments.begin(), exp.arguments.end()); - auto it = m_expressions.find(exp); - if (it != m_expressions.end()) - return it->id; + auto it = m_expressions.find(exp); + if (it != m_expressions.end()) + return it->id; + } if (_copyItem) exp.item = storeItem(_item); @@ -286,7 +289,11 @@ ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr, { static Rules rules; - if (!_expr.item || _expr.item->type() != Operation) + if ( + !_expr.item || + _expr.item->type() != Operation || + !SemanticInformation::isDeterministic(*_expr.item) + ) return -1; for (auto const& rule: rules.rules()) diff --git a/KnownState.cpp b/KnownState.cpp index 02c6ee13..632777c8 100644 --- a/KnownState.cpp +++ b/KnownState.cpp @@ -101,6 +101,7 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool vector<Id> arguments(info.args); for (int i = 0; i < info.args; ++i) arguments[i] = stackElement(m_stackHeight - i, _item.getLocation()); + if (_item.instruction() == Instruction::SSTORE) op = storeInStorage(arguments[0], arguments[1], _item.getLocation()); else if (_item.instruction() == Instruction::SLOAD) @@ -121,10 +122,16 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool applySha3(arguments.at(0), arguments.at(1), _item.getLocation()) ); else + { + if (SemanticInformation::invalidatesMemory(_item.instruction())) + resetMemory(); + if (SemanticInformation::invalidatesStorage(_item.instruction())) + resetStorage(); setStackElement( m_stackHeight + _item.deposit(), m_expressionClasses->find(_item, arguments, _copyItem) ); + } } m_stackHeight += _item.deposit(); } diff --git a/SemanticInformation.cpp b/SemanticInformation.cpp index 83d59efc..40c36f9e 100644 --- a/SemanticInformation.cpp +++ b/SemanticInformation.cpp @@ -122,3 +122,57 @@ bool SemanticInformation::altersControlFlow(AssemblyItem const& _item) return false; } } + + +bool SemanticInformation::isDeterministic(AssemblyItem const& _item) +{ + if (_item.type() != Operation) + return true; + assertThrow(!altersControlFlow(_item), OptimizerException, ""); + + switch (_item.instruction()) + { + case Instruction::CALL: + case Instruction::CALLCODE: + case Instruction::CREATE: + case Instruction::GAS: + case Instruction::PC: + case Instruction::MSIZE: // depends on previous writes and reads, not only on content + case Instruction::BALANCE: // depends on previous calls + case Instruction::EXTCODESIZE: + return false; + default: + return true; + } +} + +bool SemanticInformation::invalidatesMemory(Instruction _instruction) +{ + switch (_instruction) + { + case Instruction::CALLDATACOPY: + case Instruction::CODECOPY: + case Instruction::EXTCODECOPY: + case Instruction::MSTORE: + case Instruction::MSTORE8: + case Instruction::CALL: + case Instruction::CALLCODE: + return true; + default: + return false; + } +} + +bool SemanticInformation::invalidatesStorage(Instruction _instruction) +{ + switch (_instruction) + { + case Instruction::CALL: + case Instruction::CALLCODE: + case Instruction::CREATE: + case Instruction::SSTORE: + return true; + default: + return false; + } +} diff --git a/SemanticInformation.h b/SemanticInformation.h index 27aa6f1a..b14ddb65 100644 --- a/SemanticInformation.h +++ b/SemanticInformation.h @@ -23,6 +23,7 @@ #pragma once +#include <libevmcore/Instruction.h> namespace dev { @@ -45,6 +46,14 @@ struct SemanticInformation static bool isSwapInstruction(AssemblyItem const& _item); static bool isJumpInstruction(AssemblyItem const& _item); static bool altersControlFlow(AssemblyItem const& _item); + /// @returns false if the value put on the stack by _item depends on anything else than + /// the information in the current block header, memory, storage or stack. + /// @note should not be called for instructions that alter the control flow. + static bool isDeterministic(AssemblyItem const& _item); + /// @returns true if the given instruction modifies memory. + static bool invalidatesMemory(Instruction _instruction); + /// @returns true if the given instruction modifies storage (even indirectly). + static bool invalidatesStorage(Instruction _instruction); }; } |