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

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

Issue 1080343003: tree-ir bugfix: Count unseen uses instead of seen uses. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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 | Annotate | Revision Log
« 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 part of tree_ir.optimization; 5 part of tree_ir.optimization;
6 6
7 /** 7 /**
8 * Performs the following transformations on the tree: 8 * Performs the following transformations on the tree:
9 * - Assignment inlining 9 * - Assignment inlining
10 * - Assignment expression propagation 10 * - Assignment expression propagation
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 List<Expression> environment = <Expression>[]; 130 List<Expression> environment = <Expression>[];
131 131
132 /// Binding environment for variables that are assigned to effectively 132 /// Binding environment for variables that are assigned to effectively
133 /// constant expressions (see [isEffectivelyConstant]). 133 /// constant expressions (see [isEffectivelyConstant]).
134 final Map<Variable, Expression> constantEnvironment; 134 final Map<Variable, Expression> constantEnvironment;
135 135
136 /// Substitution map for labels. Any break to a label L should be substituted 136 /// Substitution map for labels. Any break to a label L should be substituted
137 /// for a break to L' if L maps to L'. 137 /// for a break to L' if L maps to L'.
138 Map<Label, Jump> labelRedirects = <Label, Jump>{}; 138 Map<Label, Jump> labelRedirects = <Label, Jump>{};
139 139
140 /// Number of uses seen so far. Used to detect the first use of a variable 140 /// Number of uses of the given variable that are still unseen.
141 /// (since we do backwards traversal, the first use is the last one seen). 141 /// Used to detect the first use of a variable (since we do backwards
142 Map<Variable, int> seenUses = <Variable, int>{}; 142 /// traversal, the first use is the last one seen).
143 Map<Variable, int> unseenUses = <Variable, int>{};
143 144
144 /// Rewriter for methods. 145 /// Rewriter for methods.
145 StatementRewriter({this.isDartMode}) 146 StatementRewriter({this.isDartMode})
146 : constantEnvironment = <Variable, Expression>{} { 147 : constantEnvironment = <Variable, Expression>{} {
147 assert(isDartMode != null); 148 assert(isDartMode != null);
148 } 149 }
149 150
150 /// Rewriter for nested functions. 151 /// Rewriter for nested functions.
151 StatementRewriter.nested(StatementRewriter parent) 152 StatementRewriter.nested(StatementRewriter parent)
152 : constantEnvironment = parent.constantEnvironment, 153 : constantEnvironment = parent.constantEnvironment,
153 seenUses = parent.seenUses, 154 unseenUses = parent.unseenUses,
154 isDartMode = parent.isDartMode; 155 isDartMode = parent.isDartMode;
155 156
156 /// A set of labels that can be safely inlined at their use. 157 /// A set of labels that can be safely inlined at their use.
157 /// 158 ///
158 /// The successor statements for labeled statements that have only one break 159 /// The successor statements for labeled statements that have only one break
159 /// from them are normally rewritten inline at the site of the break. This 160 /// from them are normally rewritten inline at the site of the break. This
160 /// is not safe if the code would be moved inside the scope of an exception 161 /// is not safe if the code would be moved inside the scope of an exception
161 /// handler (i.e., if the code would be moved into a try from outside it). 162 /// handler (i.e., if the code would be moved into a try from outside it).
162 Set<Label> safeForInlining = new Set<Label>(); 163 Set<Label> safeForInlining = new Set<Label>();
163 164
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 /// If the given expression always returns the value of one of its 197 /// If the given expression always returns the value of one of its
197 /// subexpressions, and that subexpression is a variable use, returns that 198 /// subexpressions, and that subexpression is a variable use, returns that
198 /// variable. Otherwise `null`. 199 /// variable. Otherwise `null`.
199 Variable getRightHand(Expression e) { 200 Variable getRightHand(Expression e) {
200 Expression value = getValueSubexpression(e); 201 Expression value = getValueSubexpression(e);
201 return value is VariableUse ? value.variable : null; 202 return value is VariableUse ? value.variable : null;
202 } 203 }
203 204
204 @override 205 @override
205 Expression visitVariableUse(VariableUse node) { 206 Expression visitVariableUse(VariableUse node) {
206 // Count of number of uses seen so far. 207 // Count of number of unseen uses remaining.
207 seenUses[node.variable] = 1 + seenUses.putIfAbsent(node.variable, () => 0); 208 unseenUses.putIfAbsent(node.variable, () => node.variable.readCount);
209 --unseenUses[node.variable];
208 210
209 // We traverse the tree right-to-left, so when we have seen all uses, 211 // We traverse the tree right-to-left, so when we have seen all uses,
210 // it means we are looking at the first use. 212 // it means we are looking at the first use.
211 assert(seenUses[node.variable] <= node.variable.readCount); 213 assert(unseenUses[node.variable] < node.variable.readCount);
212 bool isFirstUse = seenUses[node.variable] == node.variable.readCount; 214 assert(unseenUses[node.variable] >= 0);
215 bool isFirstUse = unseenUses[node.variable] == 0;
213 216
214 // Propagate constant to use site. 217 // Propagate constant to use site.
215 Expression constant = constantEnvironment[node.variable]; 218 Expression constant = constantEnvironment[node.variable];
216 if (constant != null) { 219 if (constant != null) {
217 --node.variable.readCount; 220 --node.variable.readCount;
218 --seenUses[node.variable]; // Do not count the use we just destroyed.
asgerf 2015/04/16 12:03:55 I knew this was a bad idea and somehow I did it an
219 return visitExpression(constant); 221 return visitExpression(constant);
220 } 222 }
221 223
222 // Try to propagate another expression into this variable use. 224 // Try to propagate another expression into this variable use.
223 if (!environment.isEmpty) { 225 if (!environment.isEmpty) {
224 Expression binding = environment.last; 226 Expression binding = environment.last;
225 227
226 // Is this variable assigned by the most recently evaluated impure 228 // Is this variable assigned by the most recently evaluated impure
227 // expression? 229 // expression?
228 // 230 //
229 // If so, propagate the assignment, e.g: 231 // If so, propagate the assignment, e.g:
230 // 232 //
231 // { x = foo(); bar(x, x) } ==> bar(x = foo(), x) 233 // { x = foo(); bar(x, x) } ==> bar(x = foo(), x)
232 // 234 //
233 // We must ensure that no other uses separate this use from the 235 // We must ensure that no other uses separate this use from the
234 // assignment. We therefore only propagate assignments into the first use. 236 // assignment. We therefore only propagate assignments into the first use.
235 // 237 //
236 // Note that if this is only use, `visitAssign` will then remove the 238 // Note that if this is only use, `visitAssign` will then remove the
237 // redundant assignment. 239 // redundant assignment.
238 if (getLeftHand(binding) == node.variable && isFirstUse) { 240 if (getLeftHand(binding) == node.variable && isFirstUse) {
239 environment.removeLast(); 241 environment.removeLast();
240 --node.variable.readCount; 242 --node.variable.readCount;
241 --seenUses[node.variable]; // Do not count the use we just destroyed.
242 return visitExpression(binding); 243 return visitExpression(binding);
243 } 244 }
244 245
245 // Is the most recently evaluated impure expression known to have the 246 // Is the most recently evaluated impure expression known to have the
246 // value of this variable? 247 // value of this variable?
247 // 248 //
248 // If so, we can replace this use with the impure expression, e.g: 249 // If so, we can replace this use with the impure expression, e.g:
249 // 250 //
250 // { E.foo = x; bar(x) } ==> bar(E.foo = x) 251 // { E.foo = x; bar(x) } ==> bar(E.foo = x)
251 // 252 //
252 if (getRightHand(binding) == node.variable) { 253 if (getRightHand(binding) == node.variable) {
253 environment.removeLast(); 254 environment.removeLast();
254 --node.variable.readCount; 255 --node.variable.readCount;
255 --seenUses[node.variable];
256 return visitExpression(binding); 256 return visitExpression(binding);
257 } 257 }
258 } 258 }
259 259
260 // If the definition could not be propagated, leave the variable use. 260 // If the definition could not be propagated, leave the variable use.
261 return node; 261 return node;
262 } 262 }
263 263
264 /// Returns true if [exp] has no side effects and has a constant value within 264 /// Returns true if [exp] has no side effects and has a constant value within
265 /// any given activation of the enclosing method. 265 /// any given activation of the enclosing method.
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 } 893 }
894 894
895 /// Combines two variable uses into one. 895 /// Combines two variable uses into one.
896 class CombinedUses implements CombinedExpressions { 896 class CombinedUses implements CombinedExpressions {
897 VariableUse use1, use2; 897 VariableUse use1, use2;
898 Expression combined; 898 Expression combined;
899 899
900 CombinedUses(this.use1, this.use2) { 900 CombinedUses(this.use1, this.use2) {
901 assert(use1.variable == use2.variable); 901 assert(use1.variable == use2.variable);
902 use1.variable.readCount -= 2; // Destroy both the original uses. 902 use1.variable.readCount -= 2; // Destroy both the original uses.
903 combined = new VariableUse(use1.variable); 903 combined = new VariableUse(use1.variable);
asgerf 2015/04/16 12:03:55 FYI this is where the bookkeeping was missing. Up
904 } 904 }
905 905
906 void uncombine() { 906 void uncombine() {
907 ++use1.variable.readCount; // Restore original reference count. 907 ++use1.variable.readCount; // Restore original reference count.
908 } 908 }
909 } 909 }
910 910
911 /// Result of combining two expressions that do not affect reference counting. 911 /// Result of combining two expressions that do not affect reference counting.
912 class GenericCombinedExpressions implements CombinedExpressions { 912 class GenericCombinedExpressions implements CombinedExpressions {
913 Expression combined; 913 Expression combined;
914 914
915 GenericCombinedExpressions(this.combined); 915 GenericCombinedExpressions(this.combined);
916 916
917 void uncombine() {} 917 void uncombine() {}
918 } 918 }
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