diff options
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | libevmasm/ExpressionClasses.cpp | 1 | ||||
-rw-r--r-- | libevmasm/RuleList.h | 47 | ||||
-rw-r--r-- | libevmasm/SimplificationRules.cpp | 21 | ||||
-rw-r--r-- | libevmasm/SimplificationRules.h | 6 | ||||
-rw-r--r-- | libjulia/optimiser/SimplificationRules.cpp | 7 | ||||
-rw-r--r-- | libjulia/optimiser/SimplificationRules.h | 3 |
7 files changed, 73 insertions, 13 deletions
diff --git a/Changelog.md b/Changelog.md index 95197e04..4e8b4ee3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -102,6 +102,7 @@ Bugfixes: * Commandline Interface: Correctly handle paths with backslashes on windows. * Fix NatSpec json output for `@notice` and `@dev` tags on contract definitions. * Optimizer: Correctly estimate gas costs of constants for special cases. + * Optimizer: Fix simplification rule initialization bug that appeared on some emscripten platforms. * References Resolver: Do not crash on using ``_slot`` and ``_offset`` suffixes on their own. * References Resolver: Enforce ``storage`` as data location for mappings. * References Resolver: Properly handle invalid references used together with ``_slot`` and ``_offset``. diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp index 69b33ec5..42a1819a 100644 --- a/libevmasm/ExpressionClasses.cpp +++ b/libevmasm/ExpressionClasses.cpp @@ -184,6 +184,7 @@ string ExpressionClasses::fullDAGToString(ExpressionClasses::Id _id) const ExpressionClasses::Id ExpressionClasses::tryToSimplify(Expression const& _expr) { static Rules rules; + assertThrow(rules.isInitialized(), OptimizerException, "Rule list not properly initialized."); if ( !_expr.item || diff --git a/libevmasm/RuleList.h b/libevmasm/RuleList.h index 0573856b..874a8929 100644 --- a/libevmasm/RuleList.h +++ b/libevmasm/RuleList.h @@ -44,12 +44,11 @@ template <class S> S modWorkaround(S const& _a, S const& _b) return (S)(bigint(_a) % bigint(_b)); } -/// @returns a list of simplification rules given certain match placeholders. -/// A, B and C should represent constants, X and Y arbitrary expressions. -/// The simplifications should never change the order of evaluation of -/// arbitrary operations. +// This part of simplificationRuleList below was split out to prevent +// stack overflows in the JavaScript optimizer for emscripten builds +// that affected certain browser versions. template <class Pattern> -std::vector<SimplificationRule<Pattern>> simplificationRuleList( +std::vector<SimplificationRule<Pattern>> simplificationRuleListPart1( Pattern A, Pattern B, Pattern C, @@ -57,8 +56,7 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleList( Pattern Y ) { - std::vector<SimplificationRule<Pattern>> rules; - rules += std::vector<SimplificationRule<Pattern>>{ + return std::vector<SimplificationRule<Pattern>> { // arithmetic on constants {{Instruction::ADD, {A, B}}, [=]{ return A.d() + B.d(); }, false}, {{Instruction::MUL, {A, B}}, [=]{ return A.d() * B.d(); }, false}, @@ -162,6 +160,22 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleList( {{Instruction::OR, {X, {Instruction::NOT, {X}}}}, [=]{ return ~u256(0); }, true}, {{Instruction::OR, {{Instruction::NOT, {X}}, X}}, [=]{ return ~u256(0); }, true}, }; +} + + +// This part of simplificationRuleList below was split out to prevent +// stack overflows in the JavaScript optimizer for emscripten builds +// that affected certain browser versions. +template <class Pattern> +std::vector<SimplificationRule<Pattern>> simplificationRuleListPart2( + Pattern A, + Pattern B, + Pattern, + Pattern X, + Pattern Y +) +{ + std::vector<SimplificationRule<Pattern>> rules; // Replace MOD X, <power-of-two> with AND X, <power-of-two> - 1 for (size_t i = 0; i < 256; ++i) @@ -292,5 +306,24 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleList( return rules; } +/// @returns a list of simplification rules given certain match placeholders. +/// A, B and C should represent constants, X and Y arbitrary expressions. +/// The simplifications should never change the order of evaluation of +/// arbitrary operations. +template <class Pattern> +std::vector<SimplificationRule<Pattern>> simplificationRuleList( + Pattern A, + Pattern B, + Pattern C, + Pattern X, + Pattern Y +) +{ + std::vector<SimplificationRule<Pattern>> rules; + rules += simplificationRuleListPart1(A, B, C, X, Y); + rules += simplificationRuleListPart2(A, B, C, X, Y); + return rules; +} + } } diff --git a/libevmasm/SimplificationRules.cpp b/libevmasm/SimplificationRules.cpp index 504dbc24..ba13a611 100644 --- a/libevmasm/SimplificationRules.cpp +++ b/libevmasm/SimplificationRules.cpp @@ -21,16 +21,19 @@ * Container for equivalence classes of expressions for use in common subexpression elimination. */ +#include <libevmasm/SimplificationRules.h> + #include <libevmasm/ExpressionClasses.h> -#include <utility> -#include <functional> -#include <boost/range/adaptor/reversed.hpp> -#include <boost/noncopyable.hpp> #include <libevmasm/Assembly.h> #include <libevmasm/CommonSubexpressionEliminator.h> -#include <libevmasm/SimplificationRules.h> - #include <libevmasm/RuleList.h> +#include <libdevcore/Assertions.h> + +#include <boost/range/adaptor/reversed.hpp> +#include <boost/noncopyable.hpp> + +#include <utility> +#include <functional> using namespace std; using namespace dev; @@ -54,6 +57,11 @@ SimplificationRule<Pattern> const* Rules::findFirstMatch( return nullptr; } +bool Rules::isInitialized() const +{ + return !m_rules[byte(Instruction::ADD)].empty(); +} + void Rules::addRules(std::vector<SimplificationRule<Pattern>> const& _rules) { for (auto const& r: _rules) @@ -82,6 +90,7 @@ Rules::Rules() Y.setMatchGroup(5, m_matchGroups); addRules(simplificationRuleList(A, B, C, X, Y)); + assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized."); } Pattern::Pattern(Instruction _instruction, std::vector<Pattern> const& _arguments): diff --git a/libevmasm/SimplificationRules.h b/libevmasm/SimplificationRules.h index 53f7e595..fbe5a2b0 100644 --- a/libevmasm/SimplificationRules.h +++ b/libevmasm/SimplificationRules.h @@ -26,6 +26,8 @@ #include <libevmasm/ExpressionClasses.h> #include <libevmasm/SimplificationRule.h> +#include <boost/noncopyable.hpp> + #include <functional> #include <vector> @@ -53,6 +55,10 @@ public: ExpressionClasses const& _classes ); + /// Checks whether the rulelist is non-empty. This is usually enforced + /// by the constructor, but we had some issues with static initialization. + bool isInitialized() const; + private: void addRules(std::vector<SimplificationRule<Pattern>> const& _rules); void addRule(SimplificationRule<Pattern> const& _rule); diff --git a/libjulia/optimiser/SimplificationRules.cpp b/libjulia/optimiser/SimplificationRules.cpp index a5e296c3..56cb96ac 100644 --- a/libjulia/optimiser/SimplificationRules.cpp +++ b/libjulia/optimiser/SimplificationRules.cpp @@ -40,6 +40,7 @@ SimplificationRule<Pattern> const* SimplificationRules::findFirstMatch(Expressio return nullptr; static SimplificationRules rules; + assertThrow(rules.isInitialized(), OptimizerException, "Rule list not properly initialized."); FunctionalInstruction const& instruction = boost::get<FunctionalInstruction>(_expr); for (auto const& rule: rules.m_rules[byte(instruction.instruction)]) @@ -51,6 +52,11 @@ SimplificationRule<Pattern> const* SimplificationRules::findFirstMatch(Expressio return nullptr; } +bool SimplificationRules::isInitialized() const +{ + return !m_rules[byte(solidity::Instruction::ADD)].empty(); +} + void SimplificationRules::addRules(vector<SimplificationRule<Pattern>> const& _rules) { for (auto const& r: _rules) @@ -79,6 +85,7 @@ SimplificationRules::SimplificationRules() Y.setMatchGroup(5, m_matchGroups); addRules(simplificationRuleList(A, B, C, X, Y)); + assertThrow(isInitialized(), OptimizerException, "Rule list not properly initialized."); } Pattern::Pattern(solidity::Instruction _instruction, vector<Pattern> const& _arguments): diff --git a/libjulia/optimiser/SimplificationRules.h b/libjulia/optimiser/SimplificationRules.h index 68b640b1..e35e6466 100644 --- a/libjulia/optimiser/SimplificationRules.h +++ b/libjulia/optimiser/SimplificationRules.h @@ -51,6 +51,9 @@ public: /// groups accordingly. static SimplificationRule<Pattern> const* findFirstMatch(Expression const& _expr); + /// Checks whether the rulelist is non-empty. This is usually enforced + /// by the constructor, but we had some issues with static initialization. + bool isInitialized() const; private: void addRules(std::vector<SimplificationRule<Pattern>> const& _rules); void addRule(SimplificationRule<Pattern> const& _rule); |