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

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

Issue 1178703014: dart2js cps: Fix bug in liveness analysis. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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 | tests/co19/co19-dart2js.status » ('j') | 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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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.variable_merger; 5 library tree_ir.optimization.variable_merger;
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 9
10 /// Merges variables based on liveness and source variable information. 10 /// Merges variables based on liveness and source variable information.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 Block block = new Block(catchBlock); 126 Block block = new Block(catchBlock);
127 blocks.add(block); 127 blocks.add(block);
128 return block; 128 return block;
129 } 129 }
130 130
131 /// Starts a new block after the end of [block]. 131 /// Starts a new block after the end of [block].
132 void branchFrom(Block block, {Block catchBlock}) { 132 void branchFrom(Block block, {Block catchBlock}) {
133 _currentBlock = newBlock(catchBlock: catchBlock)..predecessors.add(block); 133 _currentBlock = newBlock(catchBlock: catchBlock)..predecessors.add(block);
134 } 134 }
135 135
136 /// Starts a new block with the given blocks as predecessors.
137 void joinFrom(Block block1, Block block2) {
138 assert(block1.catchBlock == block2.catchBlock);
139 _currentBlock = newBlock(catchBlock: block1.catchBlock);
140 _currentBlock.predecessors.add(block1);
141 _currentBlock.predecessors.add(block2);
142 }
143
136 /// Called when reading from [variable]. 144 /// Called when reading from [variable].
137 /// 145 ///
138 /// Appends a read operation to the current basic block. 146 /// Appends a read operation to the current basic block.
139 void read(Variable variable) { 147 void read(Variable variable) {
140 if (variable.isCaptured) return; 148 if (variable.isCaptured) return;
141 if (_ignoredVariables.contains(variable)) return; 149 if (_ignoredVariables.contains(variable)) return;
142 _currentBlock.addRead(variable); 150 _currentBlock.addRead(variable);
143 } 151 }
144 152
145 /// Called when writing to [variable]. 153 /// Called when writing to [variable].
(...skipping 19 matching lines...) Expand all
165 visitAssign(Assign node) { 173 visitAssign(Assign node) {
166 visitExpression(node.value); 174 visitExpression(node.value);
167 write(node.variable); 175 write(node.variable);
168 } 176 }
169 177
170 visitIf(If node) { 178 visitIf(If node) {
171 visitExpression(node.condition); 179 visitExpression(node.condition);
172 Block afterCondition = _currentBlock; 180 Block afterCondition = _currentBlock;
173 branchFrom(afterCondition); 181 branchFrom(afterCondition);
174 visitStatement(node.thenStatement); 182 visitStatement(node.thenStatement);
183 Block afterThen = _currentBlock;
175 branchFrom(afterCondition); 184 branchFrom(afterCondition);
176 visitStatement(node.elseStatement); 185 visitStatement(node.elseStatement);
186 joinFrom(_currentBlock, afterThen);
177 } 187 }
178 188
179 visitLabeledStatement(LabeledStatement node) { 189 visitLabeledStatement(LabeledStatement node) {
180 Block join = _jumpTarget[node.label] = newBlock(); 190 Block join = _jumpTarget[node.label] = newBlock();
181 visitStatement(node.body); // visitBreak will add predecessors to join. 191 visitStatement(node.body); // visitBreak will add predecessors to join.
182 _currentBlock = join; 192 _currentBlock = join;
183 visitStatement(node.next); 193 visitStatement(node.next);
184 } 194 }
185 195
186 visitBreak(Break node) { 196 visitBreak(Break node) {
(...skipping 17 matching lines...) Expand all
204 _currentBlock = join; 214 _currentBlock = join;
205 visitExpression(node.condition); 215 visitExpression(node.condition);
206 Block afterCondition = _currentBlock; 216 Block afterCondition = _currentBlock;
207 branchFrom(afterCondition); 217 branchFrom(afterCondition);
208 visitStatement(node.body); // visitContinue will add predecessors to join. 218 visitStatement(node.body); // visitContinue will add predecessors to join.
209 branchFrom(afterCondition); 219 branchFrom(afterCondition);
210 visitStatement(node.next); 220 visitStatement(node.next);
211 } 221 }
212 222
213 visitTry(Try node) { 223 visitTry(Try node) {
214 Block catchBlock = newBlock(); 224 Block outerCatchBlock = _currentBlock.catchBlock;
225 Block catchBlock = newBlock(catchBlock: outerCatchBlock);
215 branchFrom(_currentBlock, catchBlock: catchBlock); 226 branchFrom(_currentBlock, catchBlock: catchBlock);
216 visitStatement(node.tryBody); 227 visitStatement(node.tryBody);
228 Block afterTry = _currentBlock;
217 _currentBlock = catchBlock; 229 _currentBlock = catchBlock;
218 // Catch parameters cannot be hoisted to the top of the function, so to 230 // Catch parameters cannot be hoisted to the top of the function, so to
219 // avoid complications with scoping, we do not attempt to merge them. 231 // avoid complications with scoping, we do not attempt to merge them.
220 node.catchParameters.forEach(ignoreVariable); 232 node.catchParameters.forEach(ignoreVariable);
221 visitStatement(node.catchBody); 233 visitStatement(node.catchBody);
234 Block afterCatch = _currentBlock;
235 _currentBlock = newBlock(catchBlock: outerCatchBlock);
236 _currentBlock.predecessors.add(afterCatch);
237 _currentBlock.predecessors.add(afterTry);
222 } 238 }
223 239
224 visitConditional(Conditional node) { 240 visitConditional(Conditional node) {
225 visitExpression(node.condition); 241 visitExpression(node.condition);
226 Block afterCondition = _currentBlock; 242 Block afterCondition = _currentBlock;
227 branchFrom(afterCondition); 243 branchFrom(afterCondition);
228 visitExpression(node.thenExpression); 244 visitExpression(node.thenExpression);
245 Block afterThen = _currentBlock;
229 branchFrom(afterCondition); 246 branchFrom(afterCondition);
230 visitExpression(node.elseExpression); 247 visitExpression(node.elseExpression);
248 joinFrom(_currentBlock, afterThen);
231 } 249 }
232 250
233 visitLogicalOperator(LogicalOperator node) { 251 visitLogicalOperator(LogicalOperator node) {
234 visitExpression(node.left); 252 visitExpression(node.left);
235 Block afterCondition = _currentBlock; 253 Block afterLeft = _currentBlock;
236 branchFrom(afterCondition); 254 branchFrom(afterLeft);
237 visitExpression(node.right); 255 visitExpression(node.right);
256 joinFrom(_currentBlock, afterLeft);
238 } 257 }
239 } 258 }
240 259
241 /// Computes liveness information of the given control-flow graph. 260 /// Computes liveness information of the given control-flow graph.
242 /// 261 ///
243 /// The results are stored in [Block.liveIn] and [Block.liveOut]. 262 /// The results are stored in [Block.liveIn] and [Block.liveOut].
244 void _computeLiveness(List<Block> blocks) { 263 void _computeLiveness(List<Block> blocks) {
245 // We use a LIFO queue as worklist. Blocks are given in AST order, so by 264 // We use a LIFO queue as worklist. Blocks are given in AST order, so by
246 // inserting them in this order, we initially visit them backwards, which 265 // inserting them in this order, we initially visit them backwards, which
247 // is a good ordering. 266 // is a good ordering.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 pred.inWorklist = true; 336 pred.inWorklist = true;
318 } 337 }
319 } 338 }
320 } 339 }
321 } 340 }
322 } 341 }
323 342
324 /// For testing purposes, this flag can be passed to merge variables that 343 /// For testing purposes, this flag can be passed to merge variables that
325 /// originated from different source variables. 344 /// originated from different source variables.
326 /// 345 ///
327 /// Correctness should not depend on the fact that we only merge variable 346 /// Correctness should not depend on the fact that we only merge variables
328 /// originating from the same source variable. Setting this flag makes a bug 347 /// originating from the same source variable. Setting this flag makes a bug
329 /// more likely to provoke a test case failure. 348 /// more likely to provoke a test case failure.
330 const bool NO_PRESERVE_VARS = const bool.fromEnvironment('NO_PRESERVE_VARS'); 349 const bool NO_PRESERVE_VARS = const bool.fromEnvironment('NO_PRESERVE_VARS');
331 350
332 /// Based on liveness information, computes a map of variable substitutions to 351 /// Based on liveness information, computes a map of variable substitutions to
333 /// merge variables. 352 /// merge variables.
334 /// 353 ///
335 /// Constructs a register interference graph. This is an undirected graph of 354 /// Constructs a register interference graph. This is an undirected graph of
336 /// variables, with an edge between two variables if they cannot be merged 355 /// variables, with an edge between two variables if they cannot be merged
337 /// (because they are live simultaneously). 356 /// (because they are live simultaneously).
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 List<Variable> register = registers[group(v1)]; 438 List<Variable> register = registers[group(v1)];
420 439
421 // Optimization: For the first variable in a group, allocate a new color 440 // Optimization: For the first variable in a group, allocate a new color
422 // without iterating over its interference edges. 441 // without iterating over its interference edges.
423 if (register == null) { 442 if (register == null) {
424 registers[group(v1)] = <Variable>[v1]; 443 registers[group(v1)] = <Variable>[v1];
425 subst[v1] = v1; 444 subst[v1] = v1;
426 continue; 445 continue;
427 } 446 }
428 447
429 // Optimization: If there are no inteference edges for this variable, 448 // Optimization: If there are no interference edges for this variable,
430 // assign it the first color without copying the register list. 449 // assign it the first color without copying the register list.
431 Set<Variable> interferenceSet = interference[v1]; 450 Set<Variable> interferenceSet = interference[v1];
432 if (interferenceSet.isEmpty) { 451 if (interferenceSet.isEmpty) {
433 subst[v1] = register[0]; 452 subst[v1] = register[0];
434 continue; 453 continue;
435 } 454 }
436 455
437 // Find an unused color. 456 // Find an unused color.
438 Set<Variable> potential = new Set<Variable>.from(register); 457 Set<Variable> potential = new Set<Variable>.from(register);
439 for (Variable v2 in interferenceSet) { 458 for (Variable v2 in interferenceSet) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 node.expression = visitExpression(node.expression); 535 node.expression = visitExpression(node.expression);
517 node.next = visitStatement(node.next); 536 node.next = visitStatement(node.next);
518 if (node.expression is VariableUse) { 537 if (node.expression is VariableUse) {
519 VariableUse use = node.expression; 538 VariableUse use = node.expression;
520 --use.variable.readCount; 539 --use.variable.readCount;
521 return node.next; 540 return node.next;
522 } 541 }
523 return node; 542 return node;
524 } 543 }
525 } 544 }
OLDNEW
« no previous file with comments | « no previous file | tests/co19/co19-dart2js.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698