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

Side by Side 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: 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library tree_ir.optimization.statement_rewriter; 5 library tree_ir.optimization.statement_rewriter;
6 6
7 import 'optimization.dart' show Pass; 7 import 'optimization.dart' show Pass;
8 import '../tree_ir_nodes.dart'; 8 import '../tree_ir_nodes.dart';
9 import '../../io/source_information.dart'; 9 import '../../io/source_information.dart';
10 import '../../elements/elements.dart'; 10 import '../../elements/elements.dart';
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 /// Assignments with constant right-hand sides (see [isEffectivelyConstant]) 160 /// Assignments with constant right-hand sides (see [isEffectivelyConstant])
161 /// are not considered impure and are put in [constantEnvironment] instead. 161 /// are not considered impure and are put in [constantEnvironment] instead.
162 /// 162 ///
163 /// Except for [Conditional]s, expressions in the environment have 163 /// Except for [Conditional]s, expressions in the environment have
164 /// not been processed, and all their subexpressions must therefore be 164 /// not been processed, and all their subexpressions must therefore be
165 /// variables uses. 165 /// variables uses.
166 List<Expression> environment = <Expression>[]; 166 List<Expression> environment = <Expression>[];
167 167
168 /// Binding environment for variables that are assigned to effectively 168 /// Binding environment for variables that are assigned to effectively
169 /// constant expressions (see [isEffectivelyConstant]). 169 /// constant expressions (see [isEffectivelyConstant]).
170 Map<Variable, Expression> constantEnvironment; 170 Map<Variable, Expression> constantEnvironment = <Variable, Expression>{};
171 171
172 /// Substitution map for labels. Any break to a label L should be substituted 172 /// Substitution map for labels. Any break to a label L should be substituted
173 /// for a break to L' if L maps to L'. 173 /// for a break to L' if L maps to L'.
174 Map<Label, Jump> labelRedirects = <Label, Jump>{}; 174 Map<Label, Jump> labelRedirects = <Label, Jump>{};
175 175
176 /// Number of uses of the given variable that are still unseen. 176 /// Number of uses of the given variable that are still unseen.
177 /// Used to detect the first use of a variable (since we do backwards 177 /// Used to detect the first use of a variable (since we do backwards
178 /// traversal, the first use is the last one seen). 178 /// traversal, the first use is the last one seen).
179 Map<Variable, int> unseenUses = <Variable, int>{}; 179 Map<Variable, int> unseenUses = <Variable, int>{};
180 180
181 /// Number of assignments to a given variable that dominate the current 181 /// Number of assignments to a given variable that dominate the current
182 /// position. 182 /// position.
183 /// 183 ///
184 /// Pure expressions will not be inlined if it uses a variable with more than 184 /// Pure expressions will not be inlined if it uses a variable with more than
185 /// one dominating assignment, because the reaching definition of the used 185 /// one dominating assignment, because the reaching definition of the used
186 /// variable might have changed since it was put in the environment. 186 /// variable might have changed since it was put in the environment.
187 final Map<Variable, int> dominatingAssignments = <Variable, int>{}; 187 final Map<Variable, int> dominatingAssignments = <Variable, int>{};
188 188
189 /// Rewriter for methods.
190 StatementRewriter() : constantEnvironment = <Variable, Expression>{};
191
192 /// Rewriter for nested functions.
193 StatementRewriter.nested(StatementRewriter parent)
194 : constantEnvironment = parent.constantEnvironment,
195 unseenUses = parent.unseenUses;
196
asgerf 2016/01/06 00:18:41 Drive-by cleanup
197 /// A set of labels that can be safely inlined at their use. 189 /// A set of labels that can be safely inlined at their use.
198 /// 190 ///
199 /// The successor statements for labeled statements that have only one break 191 /// The successor statements for labeled statements that have only one break
200 /// from them are normally rewritten inline at the site of the break. This 192 /// from them are normally rewritten inline at the site of the break. This
201 /// is not safe if the code would be moved inside the scope of an exception 193 /// is not safe if the code would be moved inside the scope of an exception
202 /// handler (i.e., if the code would be moved into a try from outside it). 194 /// handler (i.e., if the code would be moved into a try from outside it).
203 Set<Label> safeForInlining = new Set<Label>(); 195 Set<Label> safeForInlining = new Set<Label>();
204 196
197 /// If the top element is true, assignments of form "x = CONST" may be
198 /// propagated into a following occurence of CONST. This may confuse the JS
199 /// runtime so it is disabled in some cases.
sra1 2016/01/06 00:41:06 'engine' rather than 'runtime'.
asgerf 2016/01/06 15:43:31 Done.
200 List<bool> allowRhsPropagation = <bool>[true];
sra1 2016/01/06 00:41:06 I assume it was too nasty to thread through as an
asgerf 2016/01/06 15:43:31 Yeah.
201
202 bool get isAllowingRhsPropagation => allowRhsPropagation.last;
sra1 2016/01/06 00:41:06 Maybe rename to isRhsPropagationAllowed. ('are you
asgerf 2016/01/06 15:43:31 Done.
203
205 /// Returns the redirect target of [jump] or [jump] itself if it should not 204 /// Returns the redirect target of [jump] or [jump] itself if it should not
206 /// be redirected. 205 /// be redirected.
207 Jump redirect(Jump jump) { 206 Jump redirect(Jump jump) {
208 Jump newJump = labelRedirects[jump.target]; 207 Jump newJump = labelRedirects[jump.target];
209 return newJump != null ? newJump : jump; 208 return newJump != null ? newJump : jump;
210 } 209 }
211 210
212 void inEmptyEnvironment(void action(), {bool keepConstants: true}) { 211 void inEmptyEnvironment(void action(), {bool keepConstants: true}) {
213 List oldEnvironment = environment; 212 List oldEnvironment = environment;
214 Map oldConstantEnvironment = constantEnvironment; 213 Map oldConstantEnvironment = constantEnvironment;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 return visitExpression(binding); 319 return visitExpression(binding);
321 } 320 }
322 321
323 // Is the most recently evaluated impure expression known to have the 322 // Is the most recently evaluated impure expression known to have the
324 // value of this variable? 323 // value of this variable?
325 // 324 //
326 // If so, we can replace this use with the impure expression, e.g: 325 // If so, we can replace this use with the impure expression, e.g:
327 // 326 //
328 // { E.foo = x; bar(x) } ==> bar(E.foo = x) 327 // { E.foo = x; bar(x) } ==> bar(E.foo = x)
329 // 328 //
330 if (getRightHandVariable(binding) == node.variable) { 329 if (isAllowingRhsPropagation &&
330 getRightHandVariable(binding) == node.variable) {
331 environment.removeLast(); 331 environment.removeLast();
332 --node.variable.readCount; 332 --node.variable.readCount;
333 return visitExpression(binding); 333 return visitExpression(binding);
334 } 334 }
335 } 335 }
336 336
337 // If the definition could not be propagated, leave the variable use. 337 // If the definition could not be propagated, leave the variable use.
338 return node; 338 return node;
339 } 339 }
340 340
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 // 475 //
476 if (node.variable.readCount == 0) { 476 if (node.variable.readCount == 0) {
477 --node.variable.writeCount; 477 --node.variable.writeCount;
478 return node.value; 478 return node.value;
479 } 479 }
480 return node; 480 return node;
481 } 481 }
482 482
483 /// Process nodes right-to-left, the opposite of evaluation order in the case 483 /// Process nodes right-to-left, the opposite of evaluation order in the case
484 /// of argument lists.. 484 /// of argument lists..
485 void _rewriteList(List<Node> nodes) { 485 void _rewriteList(List<Node> nodes, {bool rhsPropagation: true}) {
486 allowRhsPropagation.add(rhsPropagation);
486 for (int i = nodes.length - 1; i >= 0; --i) { 487 for (int i = nodes.length - 1; i >= 0; --i) {
487 nodes[i] = visitExpression(nodes[i]); 488 nodes[i] = visitExpression(nodes[i]);
488 } 489 }
490 allowRhsPropagation.removeLast();
489 } 491 }
490 492
491 Expression visitInvokeStatic(InvokeStatic node) { 493 Expression visitInvokeStatic(InvokeStatic node) {
492 _rewriteList(node.arguments); 494 _rewriteList(node.arguments);
493 return node; 495 return node;
494 } 496 }
495 497
496 Expression visitInvokeMethod(InvokeMethod node) { 498 Expression visitInvokeMethod(InvokeMethod node) {
497 if (node.receiverIsNotNull) { 499 if (node.receiverIsNotNull) {
498 _rewriteList(node.arguments); 500 _rewriteList(node.arguments);
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 node.tryBody = visitStatement(node.tryBody); 716 node.tryBody = visitStatement(node.tryBody);
715 safeForInlining = saved; 717 safeForInlining = saved;
716 node.catchParameters.forEach(pushDominatingAssignment); 718 node.catchParameters.forEach(pushDominatingAssignment);
717 node.catchBody = visitStatement(node.catchBody); 719 node.catchBody = visitStatement(node.catchBody);
718 node.catchParameters.forEach(popDominatingAssignment); 720 node.catchParameters.forEach(popDominatingAssignment);
719 }); 721 });
720 return node; 722 return node;
721 } 723 }
722 724
723 Expression visitConstant(Constant node) { 725 Expression visitConstant(Constant node) {
724 if (!environment.isEmpty) { 726 if (isAllowingRhsPropagation && !environment.isEmpty) {
725 Constant constant = getRightHandConstant(environment.last); 727 Constant constant = getRightHandConstant(environment.last);
726 if (constant != null && constant.value == node.value) { 728 if (constant != null && constant.value == node.value) {
727 return visitExpression(environment.removeLast()); 729 return visitExpression(environment.removeLast());
728 } 730 }
729 } 731 }
730 return node; 732 return node;
731 } 733 }
732 734
733 Expression visitThis(This node) { 735 Expression visitThis(This node) {
734 return node; 736 return node;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 /// var y = bar(); 875 /// var y = bar();
874 /// var z = y < x; 876 /// var z = y < x;
875 /// 877 ///
876 /// ==> 878 /// ==>
877 /// 879 ///
878 /// var z = foo() > bar(); 880 /// var z = foo() > bar();
879 /// 881 ///
880 /// foo() must be evaluated before bar(), so the propagation is only possible 882 /// foo() must be evaluated before bar(), so the propagation is only possible
881 /// by commuting the operator. 883 /// by commuting the operator.
882 Expression visitApplyBuiltinOperator(ApplyBuiltinOperator node) { 884 Expression visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
883 if (environment.isEmpty || getLeftHand(environment.last) == null) { 885 if (!environment.isEmpty && getLeftHand(environment.last) != null) {
884 // If there is no recent assignment that might propagate, so there is no 886 Variable propagatableVariable = getLeftHand(environment.last);
885 // opportunity for optimization here. 887 BuiltinOperator commuted = commuteBinaryOperator(node.operator);
886 _rewriteList(node.arguments); 888 if (commuted != null) {
887 return node; 889 // Only binary operators can commute.
888 } 890 assert(node.arguments.length == 2);
889 Variable propagatableVariable = getLeftHand(environment.last); 891 Expression left = node.arguments[0];
890 BuiltinOperator commuted = commuteBinaryOperator(node.operator); 892 if (left is VariableUse && propagatableVariable == left.variable) {
891 if (commuted != null) { 893 Expression right = node.arguments[1];
892 assert(node.arguments.length == 2); // Only binary operators can commute. 894 if (right is This ||
893 Expression left = node.arguments[0]; 895 (right is VariableUse &&
894 if (left is VariableUse && propagatableVariable == left.variable) { 896 propagatableVariable != right.variable &&
895 Expression right = node.arguments[1]; 897 !constantEnvironment.containsKey(right.variable))) {
896 if (right is This || 898 // An assignment can be propagated if we commute the operator.
897 (right is VariableUse && 899 node.operator = commuted;
898 propagatableVariable != right.variable && 900 node.arguments[0] = right;
899 !constantEnvironment.containsKey(right.variable))) { 901 node.arguments[1] = left;
900 // An assignment can be propagated if we commute the operator. 902 }
901 node.operator = commuted;
902 node.arguments[0] = right;
903 node.arguments[1] = left;
904 } 903 }
905 } 904 }
906 } 905 }
907 _rewriteList(node.arguments); 906 _rewriteList(node.arguments, rhsPropagation: false);
sra1 2016/01/06 00:41:06 Add a comment why rhsPropagation is false. if
asgerf 2016/01/06 15:43:31 Done.
908 return node; 907 return node;
909 } 908 }
910 909
911 /// If [s] and [t] are similar statements we extract their subexpressions 910 /// If [s] and [t] are similar statements we extract their subexpressions
912 /// and returns a new statement of the same type using expressions combined 911 /// and returns a new statement of the same type using expressions combined
913 /// with the [combine] callback. For example: 912 /// with the [combine] callback. For example:
914 /// 913 ///
915 /// combineStatements(Return E1, Return E2) = Return combine(E1, E2) 914 /// combineStatements(Return E1, Return E2) = Return combine(E1, E2)
916 /// 915 ///
917 /// If [combine] returns E1 then the unified statement is equivalent to [s], 916 /// If [combine] returns E1 then the unified statement is equivalent to [s],
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
1308 VariableUseCallback callback; 1307 VariableUseCallback callback;
1309 1308
1310 VariableUseVisitor(this.callback); 1309 VariableUseVisitor(this.callback);
1311 1310
1312 visitVariableUse(VariableUse use) => callback(use); 1311 visitVariableUse(VariableUse use) => callback(use);
1313 1312
1314 static void visit(Expression node, VariableUseCallback callback) { 1313 static void visit(Expression node, VariableUseCallback callback) {
1315 new VariableUseVisitor(callback).visitExpression(node); 1314 new VariableUseVisitor(callback).visitExpression(node);
1316 } 1315 }
1317 } 1316 }
OLDNEW
« 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