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

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 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } 386 }
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 /**
397 * A list to propagate bailout information to blocks that start a
398 * guarded or labeled list of statements. Currently, these blocks
399 * are:
400 * - first block of a then branch,
401 * - first block of an else branch,
402 * - a loop header,
403 * - labeled block.
404 */
396 final List<HBasicBlock> blocks; 405 final List<HBasicBlock> blocks;
397 final List<HLabeledBlockInformation> labeledBlockInformations; 406
398 final Set<HInstruction> generateAtUseSite; 407 /**
408 * The current subgraph we are visiting.
409 */
399 SubGraph subGraph; 410 SubGraph subGraph;
411
412 /**
413 * The current block information we are visiting.
414 */
415 HBlockInformation currentBlockInformation;
416
400 /** 417 /**
401 * Max number of arguments to the bailout (not counting the state). 418 * Max number of arguments to the bailout (not counting the state).
402 */ 419 */
403 int bailoutArity; 420 int bailoutArity;
404 /** 421 /**
405 * A map from variables to their names. These are the names in the 422 * A map from variables to their names. These are the names in the
406 * unoptimized (bailout) version of the function. Their names could be 423 * unoptimized (bailout) version of the function. Their names could be
407 * different in the optimized version. 424 * different in the optimized version.
408 */ 425 */
409 VariableNames variableNames; 426 VariableNames variableNames;
(...skipping 17 matching lines...) Expand all
427 * The first type guard in the graph. 444 * The first type guard in the graph.
428 */ 445 */
429 HBailoutTarget firstBailoutTarget; 446 HBailoutTarget firstBailoutTarget;
430 447
431 /** 448 /**
432 * If set, it is the first block in the graph where we generate 449 * 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 450 * code. Blocks before this one are dead code in the bailout
434 * version. 451 * version.
435 */ 452 */
436 453
437 SsaBailoutPropagator(this.compiler, 454 SsaBailoutPropagator(this.compiler, this.variableNames)
438 this.generateAtUseSite,
439 this.variableNames)
440 : blocks = <HBasicBlock>[], 455 : blocks = <HBasicBlock>[],
441 labeledBlockInformations = <HLabeledBlockInformation>[],
442 bailoutArity = 0, 456 bailoutArity = 0,
443 parameterNames = new Map<String, int>(); 457 parameterNames = new Map<String, int>();
444 458
445 void visitGraph(HGraph graph) { 459 void visitGraph(HGraph graph) {
446 subGraph = new SubGraph(graph.entry, graph.exit); 460 subGraph = new SubGraph(graph.entry, graph.exit);
447 visitBasicBlock(graph.entry); 461 visitBasicBlock(graph.entry);
448 if (!blocks.isEmpty) { 462 if (!blocks.isEmpty) {
449 compiler.internalError('Bailout propagation', 463 compiler.internalError('Bailout propagation',
450 node: compiler.currentElement.parseNode(compiler)); 464 node: compiler.currentElement.parseNode(compiler));
451 } 465 }
452 } 466 }
453 467
468 /**
469 * Returns true if we can visit the given [blockFlow]. False
470 * otherwise. Currently, try/catch and switch are not in bailout
471 * methods, so this method only deals with loops and labeled blocks.
472 * If [blockFlow] is a labeled block or a loop, we also visit the
473 * continuation of the block flow.
474 */
475 bool handleBlockFlow(HBlockFlow blockFlow) {
476 HBlockInformation body = blockFlow.body;
477
478 // We reach here again when starting to visit a subgraph. Just
479 // return to visiting the block.
480 if (currentBlockInformation == body) return false;
481
482 HBlockInformation oldInformation = currentBlockInformation;
483 if (body is HLabeledBlockInformation) {
484 currentBlockInformation = body;
485 HLabeledBlockInformation info = body;
486 visitStatements(info.body, newFlow: true);
487 } else if (body is HLoopBlockInformation) {
488 currentBlockInformation = body;
489 HLoopBlockInformation info = body;
490 if (info.initializer != null) {
491 visitExpression(info.initializer);
492 }
493 blocks.addLast(info.loopHeader);
494 if (!info.isDoWhile()) {
495 visitExpression(info.condition);
496 }
497 visitStatements(info.body, newFlow: false);
498 if (info.isDoWhile()) {
499 visitExpression(info.condition);
500 }
501 if (info.updates != null) {
502 visitExpression(info.updates);
503 }
504 blocks.removeLast();
505 } else {
506 assert(body is! HTryBlockInformation);
507 assert(body is! HSwitchBlockInformation);
508 // [HIfBlockInformation] is handled by visitIf.
509 return false;
510 }
511
512 currentBlockInformation = oldInformation;
513 if (blockFlow.continuation != null) {
514 visitBasicBlock(blockFlow.continuation);
515 }
516 return true;
517 }
518
454 void visitBasicBlock(HBasicBlock block) { 519 void visitBasicBlock(HBasicBlock block) {
455 // Abort traversal if we are leaving the currently active sub-graph. 520 // Abort traversal if we are leaving the currently active sub-graph.
456 if (!subGraph.contains(block)) return; 521 if (!subGraph.contains(block)) return;
457 522
458 if (block.isLoopHeader()) { 523 HBlockFlow blockFlow = block.blockFlow;
459 blocks.addLast(block); 524 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 525
467 HInstruction instruction = block.first; 526 HInstruction instruction = block.first;
468 while (instruction != null) { 527 while (instruction != null) {
469 instruction.accept(this); 528 instruction.accept(this);
470 instruction = instruction.next; 529 instruction = instruction.next;
471 } 530 }
472 } 531 }
473 532
474 void visitStatements(HStatementInformation info) { 533 void visitExpression(HSubExpressionBlockInformation info) {
475 assert(info is HSubGraphBlockInformation); 534 visitSubGraph(info.subExpression);
476 HSubGraphBlockInformation graph = info; 535 }
477 visitSubGraph(graph.subGraph); 536
537 /**
538 * Visit the statements in [info]. If [newFlow] is true, we add the
539 * first block of [statements] to the list of [blocks].
540 */
541 void visitStatements(HSubGraphBlockInformation info, {bool newFlow}) {
542 SubGraph graph = info.subGraph;
543 if (newFlow) blocks.addLast(graph.start);
544 visitSubGraph(graph);
545 if (newFlow) blocks.removeLast();
478 } 546 }
479 547
480 void visitSubGraph(SubGraph graph) { 548 void visitSubGraph(SubGraph graph) {
481 SubGraph oldSubGraph = subGraph; 549 SubGraph oldSubGraph = subGraph;
482 subGraph = graph; 550 subGraph = graph;
483 HBasicBlock start = graph.start; 551 visitBasicBlock(graph.start);
484 blocks.addLast(start);
485 visitBasicBlock(start);
486 blocks.removeLast();
487 subGraph = oldSubGraph; 552 subGraph = oldSubGraph;
488
489 if (start.isLabeledBlock()) {
490 HBasicBlock continuation = start.blockFlow.continuation;
491 if (continuation != null) {
492 visitBasicBlock(continuation);
493 }
494 }
495 } 553 }
496 554
497 void visitIf(HIf instruction) { 555 void visitIf(HIf instruction) {
498 int preVisitedBlocks = 0; 556 int preVisitedBlocks = 0;
499 HIfBlockInformation info = instruction.blockInformation.body; 557 HIfBlockInformation info = instruction.blockInformation.body;
500 visitStatements(info.thenGraph); 558 visitStatements(info.thenGraph, newFlow: true);
501 preVisitedBlocks++; 559 preVisitedBlocks++;
502 visitStatements(info.elseGraph); 560 visitStatements(info.elseGraph, newFlow: true);
503 preVisitedBlocks++; 561 preVisitedBlocks++;
504 562
505 HBasicBlock joinBlock = instruction.joinBlock; 563 HBasicBlock joinBlock = instruction.joinBlock;
506 if (joinBlock != null 564 if (joinBlock != null
507 && !identical(joinBlock.dominator, instruction.block)) { 565 && !identical(joinBlock.dominator, instruction.block)) {
508 // The join block is dominated by a block in one of the branches. 566 // 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 567 // The subgraph traversal never reached it, so we visit it here
510 // instead. 568 // instead.
511 visitBasicBlock(joinBlock); 569 visitBasicBlock(joinBlock);
512 } 570 }
(...skipping 12 matching lines...) Expand all
525 583
526 void visitGoto(HGoto goto) { 584 void visitGoto(HGoto goto) {
527 HBasicBlock block = goto.block; 585 HBasicBlock block = goto.block;
528 HBasicBlock successor = block.successors[0]; 586 HBasicBlock successor = block.successors[0];
529 if (identical(successor.dominator, block)) { 587 if (identical(successor.dominator, block)) {
530 visitBasicBlock(block.successors[0]); 588 visitBasicBlock(block.successors[0]);
531 } 589 }
532 } 590 }
533 591
534 void visitLoopBranch(HLoopBranch branch) { 592 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. 593 // For a do-while loop, the body has already been visited.
538 if (!branch.isDoWhile()) { 594 if (!branch.isDoWhile()) {
539 visitBasicBlock(dominated[0]); 595 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 } 596 }
554 } 597 }
555 598
556 visitBailoutTarget(HBailoutTarget target) { 599 visitBailoutTarget(HBailoutTarget target) {
557 int inputLength = target.inputs.length; 600 int inputLength = target.inputs.length;
558 for (HInstruction input in target.inputs) { 601 for (HInstruction input in target.inputs) {
559 String inputName = variableNames.getName(input); 602 String inputName = variableNames.getName(input);
560 int position = parameterNames[inputName]; 603 int position = parameterNames[inputName];
561 if (position == null) { 604 if (position == null) {
562 position = parameterNames[inputName] = bailoutArity++; 605 position = parameterNames[inputName] = bailoutArity++;
563 } 606 }
564 } 607 }
565 608
566 if (blocks.isEmpty) { 609 if (blocks.isEmpty) {
567 if (firstBailoutTarget == null) { 610 if (firstBailoutTarget == null) {
568 firstBailoutTarget = target; 611 firstBailoutTarget = target;
569 } else { 612 } else {
570 hasComplexBailoutTargets = true; 613 hasComplexBailoutTargets = true;
571 } 614 }
572 } else { 615 } else {
573 hasComplexBailoutTargets = true; 616 hasComplexBailoutTargets = true;
574 blocks.forEach((HBasicBlock block) { 617 blocks.forEach((HBasicBlock block) {
575 block.bailoutTargets.add(target); 618 block.bailoutTargets.add(target);
576 }); 619 });
577 } 620 }
578 } 621 }
579 } 622 }
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