aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-09-18 21:39:46 +0800
committerGitHub <noreply@github.com>2018-09-18 21:39:46 +0800
commit4b656420ac84eb5c8c752d125fcd282612476b07 (patch)
treebd440467d4d2f4d2c275b47f51057933cac2aaef
parent06ffcd0502c1c06788bec9b1e1e4db3f7c42ed4d (diff)
parenta1d73a7befd2f3d72c18d4cb539edab5111c681f (diff)
downloaddexon-solidity-4b656420ac84eb5c8c752d125fcd282612476b07.tar.gz
dexon-solidity-4b656420ac84eb5c8c752d125fcd282612476b07.tar.zst
dexon-solidity-4b656420ac84eb5c8c752d125fcd282612476b07.zip
Merge pull request #4983 from ethereum/optimizerEmscriptenBug
Fix weird Optimizer Emscripten Bug
-rw-r--r--Changelog.md1
-rw-r--r--libevmasm/ExpressionClasses.cpp1
-rw-r--r--libevmasm/RuleList.h47
-rw-r--r--libevmasm/SimplificationRules.cpp21
-rw-r--r--libevmasm/SimplificationRules.h6
-rw-r--r--libjulia/optimiser/SimplificationRules.cpp7
-rw-r--r--libjulia/optimiser/SimplificationRules.h3
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);