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

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

Issue 970853006: Fix reference counting bug in StatementRewriter. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 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 propagation 9 * - Assignment propagation
10 * - If-to-conditional conversion 10 * - If-to-conditional conversion
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 }); 162 });
163 return node; 163 return node;
164 } 164 }
165 165
166 Expression visitExpression(Expression e) => e.processed ? e : e.accept(this); 166 Expression visitExpression(Expression e) => e.processed ? e : e.accept(this);
167 167
168 @override 168 @override
169 Expression visitVariableUse(VariableUse node) { 169 Expression visitVariableUse(VariableUse node) {
170 // Propagate constant to use site. 170 // Propagate constant to use site.
171 Expression constant = constantEnvironment[node.variable]; 171 Expression constant = constantEnvironment[node.variable];
172 if (constant != null) return constant; 172 if (constant != null) {
173 node.variable.readCount--;
174 return constant;
175 }
173 176
174 // Propagate a variable's definition to its use site if: 177 // Propagate a variable's definition to its use site if:
175 // 1. It has a single use, to avoid code growth and potential duplication 178 // 1. It has a single use, to avoid code growth and potential duplication
176 // of side effects, AND 179 // of side effects, AND
177 // 2. It was the most recent expression evaluated so that we do not 180 // 2. It was the most recent expression evaluated so that we do not
178 // reorder expressions with side effects. 181 // reorder expressions with side effects.
179 if (!environment.isEmpty && 182 if (!environment.isEmpty &&
180 environment.last.variable == node.variable && 183 environment.last.variable == node.variable &&
181 environment.last.hasExactlyOneUse) { 184 node.variable.readCount == 1) {
185 node.variable.readCount--;
182 return visitExpression(environment.removeLast().definition); 186 return visitExpression(environment.removeLast().definition);
183 } 187 }
184 188
185 // If the definition could not be propagated, leave the variable use. 189 // If the definition could not be propagated, leave the variable use.
186 return node; 190 return node;
187 } 191 }
188 192
189 /// Returns true if [exp] has no side effects and has a constant value within 193 /// Returns true if [exp] has no side effects and has a constant value within
190 /// any given activation of the enclosing method. 194 /// any given activation of the enclosing method.
191 bool isEffectivelyConstant(Expression exp) { 195 bool isEffectivelyConstant(Expression exp) {
192 // TODO(asgerf): Can be made more aggressive e.g. by checking conditional 196 // TODO(asgerf): Can be made more aggressive e.g. by checking conditional
193 // expressions recursively. Determine if that is a valuable optimization 197 // expressions recursively. Determine if that is a valuable optimization
194 // and/or if it is better handled at the CPS level. 198 // and/or if it is better handled at the CPS level.
195 return exp is Constant || 199 return exp is Constant ||
196 exp is This || 200 exp is This ||
197 exp is ReifyTypeVar || 201 exp is ReifyTypeVar ||
198 exp is VariableUse && constantEnvironment.containsKey(exp.variable); 202 exp is VariableUse && constantEnvironment.containsKey(exp.variable);
199 } 203 }
200 204
201 Statement visitAssign(Assign node) { 205 Statement visitAssign(Assign node) {
202 if (isEffectivelyConstant(node.definition) && 206 if (isEffectivelyConstant(node.definition) &&
203 node.variable.writeCount == 1) { 207 node.variable.writeCount == 1) {
204 // Handle constant assignments specially. 208 // Handle constant assignments specially.
205 // They are always safe to propagate (though we should avoid duplication). 209 // They are always safe to propagate (though we should avoid duplication).
206 // Moreover, they should not prevent other expressions from propagating. 210 // Moreover, they should not prevent other expressions from propagating.
207 if (node.variable.readCount <= 1) { 211 if (node.variable.readCount <= 1) {
208 // A single-use constant should always be propagted to its use site. 212 // A single-use constant should always be propagted to its use site.
209 constantEnvironment[node.variable] = visitExpression(node.definition); 213 constantEnvironment[node.variable] = visitExpression(node.definition);
214 node.variable.writeCount--;
210 return visitStatement(node.next); 215 return visitStatement(node.next);
211 } else { 216 } else {
212 // With more than one use, we cannot propagate the constant. 217 // With more than one use, we cannot propagate the constant.
213 // Visit the following statement without polluting [environment] so 218 // Visit the following statement without polluting [environment] so
214 // that any preceding non-constant assignments might still propagate. 219 // that any preceding non-constant assignments might still propagate.
215 node.next = visitStatement(node.next); 220 node.next = visitStatement(node.next);
216 node.definition = visitExpression(node.definition); 221 node.definition = visitExpression(node.definition);
217 return node; 222 return node;
218 } 223 }
219 } else { 224 } else {
220 // Try to propagate assignment, and block previous assignment until this 225 // Try to propagate assignment, and block previous assignment until this
221 // has propagated. 226 // has propagated.
222 environment.add(node); 227 environment.add(node);
223 Statement next = visitStatement(node.next); 228 Statement next = visitStatement(node.next);
224 if (!environment.isEmpty && environment.last == node) { 229 if (!environment.isEmpty && environment.last == node) {
225 // The definition could not be propagated. Residualize the let binding. 230 // The definition could not be propagated. Residualize the let binding.
226 node.next = next; 231 node.next = next;
227 environment.removeLast(); 232 environment.removeLast();
228 node.definition = visitExpression(node.definition); 233 node.definition = visitExpression(node.definition);
229 return node; 234 return node;
230 } 235 }
231 assert(!environment.contains(node)); 236 assert(!environment.contains(node));
237 node.variable.writeCount--; // This assignment was removed.
232 return next; 238 return next;
233 } 239 }
234 } 240 }
235 241
236 Expression visitInvokeStatic(InvokeStatic node) { 242 Expression visitInvokeStatic(InvokeStatic node) {
237 // Process arguments right-to-left, the opposite of evaluation order. 243 // Process arguments right-to-left, the opposite of evaluation order.
238 for (int i = node.arguments.length - 1; i >= 0; --i) { 244 for (int i = node.arguments.length - 1; i >= 0; --i) {
239 node.arguments[i] = visitExpression(node.arguments[i]); 245 node.arguments[i] = visitExpression(node.arguments[i]);
240 } 246 }
241 return node; 247 return node;
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 static Statement combineStatementsWithSubexpressions( 516 static Statement combineStatementsWithSubexpressions(
511 Statement s, 517 Statement s,
512 Statement t, 518 Statement t,
513 Expression combine(Expression s, Expression t)) { 519 Expression combine(Expression s, Expression t)) {
514 if (s is Return && t is Return) { 520 if (s is Return && t is Return) {
515 return new Return(combine(s.value, t.value)); 521 return new Return(combine(s.value, t.value));
516 } 522 }
517 if (s is Assign && t is Assign && s.variable == t.variable) { 523 if (s is Assign && t is Assign && s.variable == t.variable) {
518 Statement next = combineStatements(s.next, t.next); 524 Statement next = combineStatements(s.next, t.next);
519 if (next != null) { 525 if (next != null) {
520 --t.variable.writeCount; // Two assignments become one. 526 // Destroy both original assignments to the variable.
527 --s.variable.writeCount;
Kevin Millikin (Google) 2015/03/04 10:35:30 I guess we should be consistent within this file a
528 --t.variable.writeCount;
529 // The Assign constructor will increment the reference count again.
521 return new Assign(s.variable, 530 return new Assign(s.variable,
522 combine(s.definition, t.definition), 531 combine(s.definition, t.definition),
523 next); 532 next);
524 } 533 }
525 } 534 }
526 if (s is ExpressionStatement && t is ExpressionStatement) { 535 if (s is ExpressionStatement && t is ExpressionStatement) {
527 Statement next = combineStatements(s.next, t.next); 536 Statement next = combineStatements(s.next, t.next);
528 if (next != null) { 537 if (next != null) {
529 return new ExpressionStatement(combine(s.expression, t.expression), 538 return new ExpressionStatement(combine(s.expression, t.expression),
530 next); 539 next);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 } 657 }
649 658
650 Expression makeCondition(Expression e, bool polarity) { 659 Expression makeCondition(Expression e, bool polarity) {
651 return polarity ? e : new Not(e); 660 return polarity ? e : new Not(e);
652 } 661 }
653 662
654 Statement getBranch(If node, bool polarity) { 663 Statement getBranch(If node, bool polarity) {
655 return polarity ? node.thenStatement : node.elseStatement; 664 return polarity ? node.thenStatement : node.elseStatement;
656 } 665 }
657 } 666 }
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