Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(691)

Unified Diff: pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart

Issue 1563693002: dart2js cps: Disable RHS propagation in operands to builtin operators. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rephrase a comment Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index 32b508ff2cc92ed7615804b77b4ba6fc98597151..526e5588784b806d66925b99f36d810e6162ba34 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -167,7 +167,7 @@ class StatementRewriter extends Transformer implements Pass {
/// Binding environment for variables that are assigned to effectively
/// constant expressions (see [isEffectivelyConstant]).
- Map<Variable, Expression> constantEnvironment;
+ Map<Variable, Expression> constantEnvironment = <Variable, Expression>{};
/// Substitution map for labels. Any break to a label L should be substituted
/// for a break to L' if L maps to L'.
@@ -186,14 +186,6 @@ class StatementRewriter extends Transformer implements Pass {
/// variable might have changed since it was put in the environment.
final Map<Variable, int> dominatingAssignments = <Variable, int>{};
- /// Rewriter for methods.
- StatementRewriter() : constantEnvironment = <Variable, Expression>{};
-
- /// Rewriter for nested functions.
- StatementRewriter.nested(StatementRewriter parent)
- : constantEnvironment = parent.constantEnvironment,
- unseenUses = parent.unseenUses;
-
/// A set of labels that can be safely inlined at their use.
///
/// The successor statements for labeled statements that have only one break
@@ -202,6 +194,13 @@ class StatementRewriter extends Transformer implements Pass {
/// handler (i.e., if the code would be moved into a try from outside it).
Set<Label> safeForInlining = new Set<Label>();
+ /// If the top element is true, assignments of form "x = CONST" may be
+ /// propagated into a following occurence of CONST. This may confuse the JS
+ /// engine so it is disabled in some cases.
+ final List<bool> allowRhsPropagation = <bool>[true];
+
+ bool get isRhsPropagationAllowed => allowRhsPropagation.last;
+
/// Returns the redirect target of [jump] or [jump] itself if it should not
/// be redirected.
Jump redirect(Jump jump) {
@@ -327,7 +326,8 @@ class StatementRewriter extends Transformer implements Pass {
//
// { E.foo = x; bar(x) } ==> bar(E.foo = x)
//
- if (getRightHandVariable(binding) == node.variable) {
+ if (isRhsPropagationAllowed &&
+ getRightHandVariable(binding) == node.variable) {
environment.removeLast();
--node.variable.readCount;
return visitExpression(binding);
@@ -467,7 +467,9 @@ class StatementRewriter extends Transformer implements Pass {
}
Expression visitAssign(Assign node) {
+ allowRhsPropagation.add(true);
node.value = visitExpression(node.value);
+ allowRhsPropagation.removeLast();
// Remove assignments to variables without any uses. This can happen
// because the assignment was propagated into its use, e.g:
//
@@ -482,10 +484,12 @@ class StatementRewriter extends Transformer implements Pass {
/// Process nodes right-to-left, the opposite of evaluation order in the case
/// of argument lists..
- void _rewriteList(List<Node> nodes) {
+ void _rewriteList(List<Node> nodes, {bool rhsPropagation: true}) {
+ allowRhsPropagation.add(rhsPropagation);
for (int i = nodes.length - 1; i >= 0; --i) {
nodes[i] = visitExpression(nodes[i]);
}
+ allowRhsPropagation.removeLast();
}
Expression visitInvokeStatic(InvokeStatic node) {
@@ -721,7 +725,7 @@ class StatementRewriter extends Transformer implements Pass {
}
Expression visitConstant(Constant node) {
- if (!environment.isEmpty) {
+ if (isRhsPropagationAllowed && !environment.isEmpty) {
Constant constant = getRightHandConstant(environment.last);
if (constant != null && constant.value == node.value) {
return visitExpression(environment.removeLast());
@@ -755,8 +759,10 @@ class StatementRewriter extends Transformer implements Pass {
}
Expression visitSetField(SetField node) {
+ allowRhsPropagation.add(true);
node.value = visitExpression(node.value);
node.object = visitExpression(node.object);
+ allowRhsPropagation.removeLast();
return node;
}
@@ -770,7 +776,9 @@ class StatementRewriter extends Transformer implements Pass {
}
Expression visitSetStatic(SetStatic node) {
+ allowRhsPropagation.add(true);
node.value = visitExpression(node.value);
+ allowRhsPropagation.removeLast();
return node;
}
@@ -880,31 +888,31 @@ class StatementRewriter extends Transformer implements Pass {
/// foo() must be evaluated before bar(), so the propagation is only possible
/// by commuting the operator.
Expression visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
- if (environment.isEmpty || getLeftHand(environment.last) == null) {
- // If there is no recent assignment that might propagate, so there is no
- // opportunity for optimization here.
- _rewriteList(node.arguments);
- return node;
- }
- Variable propagatableVariable = getLeftHand(environment.last);
- BuiltinOperator commuted = commuteBinaryOperator(node.operator);
- if (commuted != null) {
- assert(node.arguments.length == 2); // Only binary operators can commute.
- Expression left = node.arguments[0];
- if (left is VariableUse && propagatableVariable == left.variable) {
- Expression right = node.arguments[1];
- if (right is This ||
- (right is VariableUse &&
- propagatableVariable != right.variable &&
- !constantEnvironment.containsKey(right.variable))) {
- // An assignment can be propagated if we commute the operator.
- node.operator = commuted;
- node.arguments[0] = right;
- node.arguments[1] = left;
+ if (!environment.isEmpty && getLeftHand(environment.last) != null) {
+ Variable propagatableVariable = getLeftHand(environment.last);
+ BuiltinOperator commuted = commuteBinaryOperator(node.operator);
+ if (commuted != null) {
+ // Only binary operators can commute.
+ assert(node.arguments.length == 2);
+ Expression left = node.arguments[0];
+ if (left is VariableUse && propagatableVariable == left.variable) {
+ Expression right = node.arguments[1];
+ if (right is This ||
+ (right is VariableUse &&
+ propagatableVariable != right.variable &&
+ !constantEnvironment.containsKey(right.variable))) {
+ // An assignment can be propagated if we commute the operator.
+ node.operator = commuted;
+ node.arguments[0] = right;
+ node.arguments[1] = left;
+ }
}
}
}
- _rewriteList(node.arguments);
+ // Avoid code like `p == (q.f = null)`. JS operators with a constant operand
+ // can sometimes be compiled to a specialized instruction in the JS engine,
+ // so retain syntactically constant operands.
+ _rewriteList(node.arguments, rhsPropagation: false);
return node;
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698