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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/bailout.dart

Issue 12082074: Fix another bailout problem where not all blocks were visiting when propagating bailout information… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 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 | sdk/lib/_internal/compiler/implementation/ssa/codegen.dart » ('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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 ssa; 5 part of ssa;
6 6
7 class BailoutInfo { 7 class BailoutInfo {
8 int instructionId; 8 int instructionId;
9 int bailoutId; 9 int bailoutId;
10 BailoutInfo(this.instructionId, this.bailoutId); 10 BailoutInfo(this.instructionId, this.bailoutId);
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 } 387 }
388 388
389 /** 389 /**
390 * Propagates bailout information to blocks that need it. This visitor 390 * Propagates bailout information to blocks that need it. This visitor
391 * is run before codegen, to know which blocks have to deal with 391 * is run before codegen, to know which blocks have to deal with
392 * bailouts. 392 * bailouts.
393 */ 393 */
394 class SsaBailoutPropagator extends HBaseVisitor { 394 class SsaBailoutPropagator extends HBaseVisitor {
395 final Compiler compiler; 395 final Compiler compiler;
396 final List<HBasicBlock> blocks; 396 final List<HBasicBlock> blocks;
397 final List<HLabeledBlockInformation> labeledBlockInformations;
398 final Set<HInstruction> generateAtUseSite;
399 SubGraph subGraph; 397 SubGraph subGraph;
398 HBlockInformation currentBlockInformation;
399
400 /** 400 /**
401 * Max number of arguments to the bailout (not counting the state). 401 * Max number of arguments to the bailout (not counting the state).
402 */ 402 */
403 int bailoutArity; 403 int bailoutArity;
404 /** 404 /**
405 * A map from variables to their names. These are the names in the 405 * A map from variables to their names. These are the names in the
406 * unoptimized (bailout) version of the function. Their names could be 406 * unoptimized (bailout) version of the function. Their names could be
407 * different in the optimized version. 407 * different in the optimized version.
408 */ 408 */
409 VariableNames variableNames; 409 VariableNames variableNames;
(...skipping 17 matching lines...) Expand all
427 * The first type guard in the graph. 427 * The first type guard in the graph.
428 */ 428 */
429 HBailoutTarget firstBailoutTarget; 429 HBailoutTarget firstBailoutTarget;
430 430
431 /** 431 /**
432 * If set, it is the first block in the graph where we generate 432 * If set, it is the first block in the graph where we generate
433 * code. Blocks before this one are dead code in the bailout 433 * code. Blocks before this one are dead code in the bailout
434 * version. 434 * version.
435 */ 435 */
436 436
437 SsaBailoutPropagator(this.compiler, 437 SsaBailoutPropagator(this.compiler, this.variableNames)
438 this.generateAtUseSite,
439 this.variableNames)
440 : blocks = <HBasicBlock>[], 438 : blocks = <HBasicBlock>[],
441 labeledBlockInformations = <HLabeledBlockInformation>[],
442 bailoutArity = 0, 439 bailoutArity = 0,
443 parameterNames = new Map<String, int>(); 440 parameterNames = new Map<String, int>();
444 441
445 void visitGraph(HGraph graph) { 442 void visitGraph(HGraph graph) {
446 subGraph = new SubGraph(graph.entry, graph.exit); 443 subGraph = new SubGraph(graph.entry, graph.exit);
447 visitBasicBlock(graph.entry); 444 visitBasicBlock(graph.entry);
448 if (!blocks.isEmpty) { 445 if (!blocks.isEmpty) {
449 compiler.internalError('Bailout propagation', 446 compiler.internalError('Bailout propagation',
450 node: compiler.currentElement.parseNode(compiler)); 447 node: compiler.currentElement.parseNode(compiler));
451 } 448 }
452 } 449 }
453 450
451 bool handleBlockFlow(HBlockFlow blockFlow) {
kasperl 2013/01/31 01:50:06 This method deserves a comment.
ngeoffray 2013/01/31 08:17:24 Done.
452 HBlockInformation body = blockFlow.body;
453
454 // We reach here again when starting to visit a subgraph. Just
455 // return to visiting the block.
456 if (currentBlockInformation == body) return false;
457
458 HBlockInformation oldInformation = currentBlockInformation;
459 if (body is HLabeledBlockInformation) {
460 currentBlockInformation = body;
461 HLabeledBlockInformation info = body;
462 visitStatements(info.body, newFlow: true);
463 } else if (body is HLoopBlockInformation) {
464 currentBlockInformation = body;
465 HLoopBlockInformation info = body;
466 if (info.initializer != null) {
467 visitExpression(info.initializer);
468 }
469 blocks.addLast(info.loopHeader);
470 if (!info.isDoWhile()) {
471 visitExpression(info.condition);
472 }
473 visitStatements(info.body, newFlow: false);
474 if (info.isDoWhile()) {
475 visitExpression(info.condition);
476 }
477 if (info.updates != null) {
478 visitExpression(info.updates);
479 }
480 blocks.removeLast();
481 } else {
482 assert(body is! HTryBlockInformation);
483 assert(body is! HSwitchBlockInformation);
484 // [HIfBlockInformation] is handled by visitIf.
485 return false;
486 }
487
488 currentBlockInformation = oldInformation;
489 if (blockFlow.continuation != null) {
490 visitBasicBlock(blockFlow.continuation);
491 }
492 return true;
493 }
494
454 void visitBasicBlock(HBasicBlock block) { 495 void visitBasicBlock(HBasicBlock block) {
455 // Abort traversal if we are leaving the currently active sub-graph. 496 // Abort traversal if we are leaving the currently active sub-graph.
456 if (!subGraph.contains(block)) return; 497 if (!subGraph.contains(block)) return;
457 498
458 if (block.isLoopHeader()) { 499 HBlockFlow blockFlow = block.blockFlow;
459 blocks.addLast(block); 500 if (blockFlow != null && handleBlockFlow(blockFlow)) return;
460 } else if (block.isLabeledBlock()
461 && (blocks.isEmpty || !identical(blocks.last, block))) {
462 HLabeledBlockInformation info = block.blockFlow.body;
463 visitStatements(info.body);
464 return;
465 }
466 501
467 HInstruction instruction = block.first; 502 HInstruction instruction = block.first;
468 while (instruction != null) { 503 while (instruction != null) {
469 instruction.accept(this); 504 instruction.accept(this);
470 instruction = instruction.next; 505 instruction = instruction.next;
471 } 506 }
472 } 507 }
473 508
474 void visitStatements(HStatementInformation info) { 509 void visitExpression(HSubExpressionBlockInformation info) {
475 assert(info is HSubGraphBlockInformation); 510 visitSubGraph(info.subExpression);
476 HSubGraphBlockInformation graph = info; 511 }
477 visitSubGraph(graph.subGraph); 512
513 void visitStatements(HSubGraphBlockInformation info, {bool newFlow}) {
kasperl 2013/01/31 01:50:06 Add a comment that explains how this works and wha
ngeoffray 2013/01/31 08:17:24 Done.
514 SubGraph graph = info.subGraph;
515 if (newFlow) blocks.addLast(graph.start);
516 visitSubGraph(graph);
517 if (newFlow) blocks.removeLast();
478 } 518 }
479 519
480 void visitSubGraph(SubGraph graph) { 520 void visitSubGraph(SubGraph graph) {
481 SubGraph oldSubGraph = subGraph; 521 SubGraph oldSubGraph = subGraph;
482 subGraph = graph; 522 subGraph = graph;
483 HBasicBlock start = graph.start; 523 visitBasicBlock(graph.start);
484 blocks.addLast(start);
485 visitBasicBlock(start);
486 blocks.removeLast();
487 subGraph = oldSubGraph; 524 subGraph = oldSubGraph;
488
489 if (start.isLabeledBlock()) {
490 HBasicBlock continuation = start.blockFlow.continuation;
491 if (continuation != null) {
492 visitBasicBlock(continuation);
493 }
494 }
495 } 525 }
496 526
497 void visitIf(HIf instruction) { 527 void visitIf(HIf instruction) {
498 int preVisitedBlocks = 0; 528 int preVisitedBlocks = 0;
499 HIfBlockInformation info = instruction.blockInformation.body; 529 HIfBlockInformation info = instruction.blockInformation.body;
500 visitStatements(info.thenGraph); 530 visitStatements(info.thenGraph, newFlow: true);
501 preVisitedBlocks++; 531 preVisitedBlocks++;
502 visitStatements(info.elseGraph); 532 visitStatements(info.elseGraph, newFlow: true);
503 preVisitedBlocks++; 533 preVisitedBlocks++;
504 534
505 HBasicBlock joinBlock = instruction.joinBlock; 535 HBasicBlock joinBlock = instruction.joinBlock;
506 if (joinBlock != null 536 if (joinBlock != null
507 && !identical(joinBlock.dominator, instruction.block)) { 537 && !identical(joinBlock.dominator, instruction.block)) {
508 // The join block is dominated by a block in one of the branches. 538 // The join block is dominated by a block in one of the branches.
509 // The subgraph traversal never reached it, so we visit it here 539 // The subgraph traversal never reached it, so we visit it here
510 // instead. 540 // instead.
511 visitBasicBlock(joinBlock); 541 visitBasicBlock(joinBlock);
512 } 542 }
(...skipping 12 matching lines...) Expand all
525 555
526 void visitGoto(HGoto goto) { 556 void visitGoto(HGoto goto) {
527 HBasicBlock block = goto.block; 557 HBasicBlock block = goto.block;
528 HBasicBlock successor = block.successors[0]; 558 HBasicBlock successor = block.successors[0];
529 if (identical(successor.dominator, block)) { 559 if (identical(successor.dominator, block)) {
530 visitBasicBlock(block.successors[0]); 560 visitBasicBlock(block.successors[0]);
531 } 561 }
532 } 562 }
533 563
534 void visitLoopBranch(HLoopBranch branch) { 564 void visitLoopBranch(HLoopBranch branch) {
535 HBasicBlock branchBlock = branch.block;
536 List<HBasicBlock> dominated = branchBlock.dominatedBlocks;
537 // For a do-while loop, the body has already been visited. 565 // For a do-while loop, the body has already been visited.
538 if (!branch.isDoWhile()) { 566 if (!branch.isDoWhile()) {
539 visitBasicBlock(dominated[0]); 567 visitBasicBlock(branch.block.dominatedBlocks[0]);
540 }
541 blocks.removeLast();
542
543 // If the branch does not dominate the code after the loop, the
544 // dominator will visit it.
545 if (!identical(branchBlock.successors[1].dominator, branchBlock)) return;
546
547 visitBasicBlock(branchBlock.successors[1]);
548 // With labeled breaks we can have more dominated blocks.
549 if (dominated.length >= 3) {
550 for (int i = 2; i < dominated.length; i++) {
551 visitBasicBlock(dominated[i]);
552 }
553 } 568 }
554 } 569 }
555 570
556 visitBailoutTarget(HBailoutTarget target) { 571 visitBailoutTarget(HBailoutTarget target) {
557 int inputLength = target.inputs.length; 572 int inputLength = target.inputs.length;
558 for (HInstruction input in target.inputs) { 573 for (HInstruction input in target.inputs) {
559 String inputName = variableNames.getName(input); 574 String inputName = variableNames.getName(input);
560 int position = parameterNames[inputName]; 575 int position = parameterNames[inputName];
561 if (position == null) { 576 if (position == null) {
562 position = parameterNames[inputName] = bailoutArity++; 577 position = parameterNames[inputName] = bailoutArity++;
563 } 578 }
564 } 579 }
565 580
566 if (blocks.isEmpty) { 581 if (blocks.isEmpty) {
567 if (firstBailoutTarget == null) { 582 if (firstBailoutTarget == null) {
568 firstBailoutTarget = target; 583 firstBailoutTarget = target;
569 } else { 584 } else {
570 hasComplexBailoutTargets = true; 585 hasComplexBailoutTargets = true;
571 } 586 }
572 } else { 587 } else {
573 hasComplexBailoutTargets = true; 588 hasComplexBailoutTargets = true;
574 blocks.forEach((HBasicBlock block) { 589 blocks.forEach((HBasicBlock block) {
575 block.bailoutTargets.add(target); 590 block.bailoutTargets.add(target);
576 }); 591 });
577 } 592 }
578 } 593 }
579 } 594 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698