OLD | NEW |
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 class SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); | 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); |
7 String get name() => 'SSA code generator'; | 7 String get name() => 'SSA code generator'; |
8 | 8 |
9 | 9 |
10 String generateMethod(WorkItem work, HGraph graph) { | 10 String generateMethod(WorkItem work, HGraph graph) { |
11 return measure(() { | 11 return measure(() { |
12 compiler.tracer.traceGraph("codegen", graph); | 12 compiler.tracer.traceGraph("codegen", graph); |
13 Map<Element, String> parameterNames = getParameterNames(work); | 13 Map<Element, String> parameterNames = getParameterNames(work); |
14 String parameters = Strings.join(parameterNames.getValues(), ', '); | 14 String parameters = Strings.join(parameterNames.getValues(), ', '); |
15 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( | 15 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( |
16 compiler, work, parameters, parameterNames); | 16 compiler, work, parameters, parameterNames); |
17 codegen.visitGraph(graph); | 17 codegen.visitGraph(graph); |
18 | 18 |
19 FunctionElement element = work.element; | 19 FunctionElement element = work.element; |
20 String code; | 20 String code; |
21 if (element.isInstanceMember() | 21 if (element.isInstanceMember() |
22 && element.enclosingElement.isClass() | 22 && element.enclosingElement.isClass() |
23 && element.enclosingElement.isNative() | 23 && element.enclosingElement.isNative() |
24 && native.isOverriddenMethod(element, | 24 && native.isOverriddenMethod(element, |
25 element.enclosingElement, | 25 element.enclosingElement, |
26 compiler.emitter.nativeEmitter)) { | 26 compiler.emitter.nativeEmitter)) { |
27 // Record that this method is overridden. In case of optional | 27 // Record that this method is overridden. In case of optional |
28 // arguments, the emitter will generate stubs to handle them, | 28 // arguments, the emitter will generate stubs to handle them, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 parameterNames[element] = function.isNative() | 73 parameterNames[element] = function.isNative() |
74 ? element.name.slowToString() | 74 ? element.name.slowToString() |
75 : JsNames.getValid('${element.name.slowToString()}'); | 75 : JsNames.getValid('${element.name.slowToString()}'); |
76 }); | 76 }); |
77 return parameterNames; | 77 return parameterNames; |
78 } | 78 } |
79 } | 79 } |
80 | 80 |
81 typedef void ElementAction(Element element); | 81 typedef void ElementAction(Element element); |
82 | 82 |
83 class SsaCodeGenerator implements HVisitor { | 83 class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
84 /** | 84 /** |
85 * Current state for generating simple (non-local-control) code. | 85 * Current state for generating simple (non-local-control) code. |
86 * It is generated as either statements (indented and ';'-terminated), | 86 * It is generated as either statements (indented and ';'-terminated), |
87 * expressions (comma separated) or declarations (also comma separated, | 87 * expressions (comma separated) or declarations (also comma separated, |
88 * but expected to be preceeded by a 'var' so it declares its variables); | 88 * but expected to be preceeded by a 'var' so it declares its variables); |
89 */ | 89 */ |
90 static final int STATE_STATEMENT = 0; | 90 static final int STATE_STATEMENT = 0; |
91 static final int STATE_FIRST_EXPRESSION = 1; | 91 static final int STATE_FIRST_EXPRESSION = 1; |
92 static final int STATE_FIRST_DECLARATION = 2; | 92 static final int STATE_FIRST_DECLARATION = 2; |
93 static final int STATE_EXPRESSION = 3; | 93 static final int STATE_EXPRESSION = 3; |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 buffer.add(";\n"); | 406 buffer.add(";\n"); |
407 } | 407 } |
408 | 408 |
409 void implicitBreakWithLabel(TargetElement target) { | 409 void implicitBreakWithLabel(TargetElement target) { |
410 addIndentation(); | 410 addIndentation(); |
411 buffer.add("break "); | 411 buffer.add("break "); |
412 writeImplicitLabel(target); | 412 writeImplicitLabel(target); |
413 buffer.add(";\n"); | 413 buffer.add(";\n"); |
414 } | 414 } |
415 | 415 |
416 void handleLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 416 bool visitIfInfo(HIfBlockInformation info) { |
| 417 return false; |
| 418 } |
| 419 |
| 420 bool visitAndOrInfo(HAndOrBlockInformation info) { |
| 421 return false; |
| 422 } |
| 423 |
| 424 bool visitLoopInfo(HLoopInformation info) { |
| 425 SubExpression condition = info.condition; |
| 426 void visitBodyIgnoreLabels() { |
| 427 if (info.body.start.isLabeledBlock()) { |
| 428 HBlockInformation oldInfo = currentBlockInformation; |
| 429 currentBlockInformation = info.body.start.blockInformation; |
| 430 visitSubGraph(info.body); |
| 431 currentBlockInformation = oldInfo; |
| 432 } else { |
| 433 visitSubGraph(info.body); |
| 434 } |
| 435 } |
| 436 |
| 437 if (!isCondition(condition)) { |
| 438 return false; |
| 439 } |
| 440 switch (info.kind) { |
| 441 case HLoopInformation.WHILE_LOOP: |
| 442 case HLoopInformation.FOR_IN_LOOP: { |
| 443 addIndentation(); |
| 444 for (LabelElement label in info.labels) { |
| 445 writeLabel(label); |
| 446 buffer.add(":"); |
| 447 } |
| 448 bool inlineUpdates = |
| 449 info.updates !== null && isExpression(info.updates); |
| 450 if (inlineUpdates) { |
| 451 buffer.add("for (; "); |
| 452 visitConditionGraph(condition); |
| 453 buffer.add("; "); |
| 454 visitExpressionGraph(info.updates); |
| 455 buffer.add(") {\n"); |
| 456 indent++; |
| 457 // The body might be labeled. Ignore this when recursing on the |
| 458 // subgraph. |
| 459 // TODO(lrn): Remove this extra labeling when handling all loops |
| 460 // using subgraphs. |
| 461 visitBodyIgnoreLabels(); |
| 462 |
| 463 indent--; |
| 464 } else { |
| 465 buffer.add("while ("); |
| 466 visitConditionGraph(condition); |
| 467 buffer.add(") {\n"); |
| 468 indent++; |
| 469 wrapLoopBodyForContinue(info); |
| 470 if (info.updates !== null) visitSubGraph(info.updates); |
| 471 indent--; |
| 472 } |
| 473 addIndentation(); |
| 474 buffer.add("}\n"); |
| 475 break; |
| 476 } |
| 477 case HLoopInformation.FOR_LOOP: { |
| 478 // TODO(lrn): Find a way to put initialization into the for. |
| 479 // It's currently handled before we reach the [HLoopInformation]. |
| 480 addIndentation(); |
| 481 for (LabelElement label in info.labels) { |
| 482 if (label.isTarget) { |
| 483 writeLabel(label); |
| 484 buffer.add(":"); |
| 485 } |
| 486 } |
| 487 buffer.add("for(;"); |
| 488 visitConditionGraph(info.condition); |
| 489 buffer.add(";"); |
| 490 if (isExpression(info.updates)) { |
| 491 visitExpressionGraph(info.updates); |
| 492 buffer.add(") {\n"); |
| 493 indent++; |
| 494 |
| 495 visitBodyIgnoreLabels(); |
| 496 |
| 497 indent--; |
| 498 addIndentation(); |
| 499 buffer.add("}\n"); |
| 500 } else { |
| 501 addIndentation(); |
| 502 buffer.add(") {\n"); |
| 503 indent++; |
| 504 wrapLoopBodyForContinue(info); |
| 505 visitSubGraph(info.updates); |
| 506 indent--; |
| 507 buffer.add("}\n"); |
| 508 } |
| 509 break; |
| 510 } |
| 511 case HLoopInformation.DO_WHILE_LOOP: |
| 512 // Currently unhandled. |
| 513 return false; |
| 514 default: |
| 515 compiler.internalError( |
| 516 'Unexpected loop kind: ${info.kind}', |
| 517 instruction: condition.expression); |
| 518 } |
| 519 visitBasicBlock(info.joinBlock); |
| 520 return true; |
| 521 } |
| 522 |
| 523 bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) { |
417 addIndentation(); | 524 addIndentation(); |
418 Link<Element> continueOverrides = const EmptyLink<Element>(); | 525 Link<Element> continueOverrides = const EmptyLink<Element>(); |
419 // If [labeledBlockInfo.isContinue], the block is an artificial | 526 // If [labeledBlockInfo.isContinue], the block is an artificial |
420 // block around the body of a loop with an update block, so that | 527 // block around the body of a loop with an update block, so that |
421 // continues of the loop can be written as breaks of the body | 528 // continues of the loop can be written as breaks of the body |
422 // block. | 529 // block. |
423 if (labeledBlockInfo.isContinue) { | 530 if (labeledBlockInfo.isContinue) { |
424 for (LabelElement label in labeledBlockInfo.labels) { | 531 for (LabelElement label in labeledBlockInfo.labels) { |
425 if (label.isContinueTarget) { | 532 if (label.isContinueTarget) { |
426 writeContinueLabel(label); | 533 writeContinueLabel(label); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 visitBasicBlock(labeledBlockInfo.joinBlock); | 574 visitBasicBlock(labeledBlockInfo.joinBlock); |
468 } | 575 } |
469 if (labeledBlockInfo.isContinue) { | 576 if (labeledBlockInfo.isContinue) { |
470 while (!continueOverrides.isEmpty()) { | 577 while (!continueOverrides.isEmpty()) { |
471 continueAction.remove(continueOverrides.head); | 578 continueAction.remove(continueOverrides.head); |
472 continueOverrides = continueOverrides.tail; | 579 continueOverrides = continueOverrides.tail; |
473 } | 580 } |
474 } else { | 581 } else { |
475 breakAction.remove(labeledBlockInfo.target); | 582 breakAction.remove(labeledBlockInfo.target); |
476 } | 583 } |
| 584 return true; |
477 } | 585 } |
478 | 586 |
479 void emitLogicalOperation(HPhi node, String operation) { | 587 void emitLogicalOperation(HPhi node, String operation) { |
480 JSBinaryOperatorPrecedence operatorPrecedence = | 588 JSBinaryOperatorPrecedence operatorPrecedence = |
481 JSPrecedence.binary[operation]; | 589 JSPrecedence.binary[operation]; |
482 beginExpression(operatorPrecedence.precedence); | 590 beginExpression(operatorPrecedence.precedence); |
483 use(node.inputs[0], operatorPrecedence.left); | 591 use(node.inputs[0], operatorPrecedence.left); |
484 buffer.add(" $operation "); | 592 buffer.add(" $operation "); |
485 use(node.inputs[1], operatorPrecedence.right); | 593 use(node.inputs[1], operatorPrecedence.right); |
486 endExpression(operatorPrecedence.precedence); | 594 endExpression(operatorPrecedence.precedence); |
(...skipping 25 matching lines...) Expand all Loading... |
512 if (label.isContinueTarget) { | 620 if (label.isContinueTarget) { |
513 continueAction.remove(label); | 621 continueAction.remove(label); |
514 } | 622 } |
515 } | 623 } |
516 } else { | 624 } else { |
517 // Loop body contains no continues, so we don't need a break target. | 625 // Loop body contains no continues, so we don't need a break target. |
518 visitSubGraph(info.body); | 626 visitSubGraph(info.body); |
519 } | 627 } |
520 } | 628 } |
521 | 629 |
522 bool handleLoop(HBasicBlock node) { | |
523 bool success = false; | |
524 assert(node.isLoopHeader()); | |
525 HLoopInformation info = node.loopInformation; | |
526 SubExpression condition = info.condition; | |
527 if (isCondition(condition)) { | |
528 switch (info.type) { | |
529 case HLoopInformation.WHILE_LOOP: | |
530 case HLoopInformation.FOR_IN_LOOP: { | |
531 addIndentation(); | |
532 for (LabelElement label in info.labels) { | |
533 writeLabel(label); | |
534 buffer.add(":"); | |
535 } | |
536 bool inlineUpdates = | |
537 info.updates !== null && isExpression(info.updates); | |
538 if (inlineUpdates) { | |
539 buffer.add("for (; "); | |
540 visitConditionGraph(condition); | |
541 buffer.add("; "); | |
542 visitExpressionGraph(info.updates); | |
543 buffer.add(") {\n"); | |
544 indent++; | |
545 // The body might be labeled. Ignore this when recursing on the | |
546 // subgraph. | |
547 // TODO(lrn): Remove this extra labeling when handling all loops | |
548 // using subgraphs. | |
549 HBlockInformation oldInfo = currentBlockInformation; | |
550 currentBlockInformation = info.body.start.labeledBlockInformation; | |
551 visitSubGraph(info.body); | |
552 currentBlockInformation = oldInfo; | |
553 | |
554 indent--; | |
555 } else { | |
556 buffer.add("while ("); | |
557 visitConditionGraph(condition); | |
558 buffer.add(") {\n"); | |
559 indent++; | |
560 wrapLoopBodyForContinue(info); | |
561 if (info.updates !== null) visitSubGraph(info.updates); | |
562 indent--; | |
563 } | |
564 addIndentation(); | |
565 buffer.add("}\n"); | |
566 success = true; | |
567 break; | |
568 } | |
569 case HLoopInformation.FOR_LOOP: { | |
570 // TODO(lrn): Find a way to put initialization into the for. | |
571 // It's currently handled before we reach the [HLoopInformation]. | |
572 addIndentation(); | |
573 for (LabelElement label in info.labels) { | |
574 if (label.isTarget) { | |
575 writeLabel(label); | |
576 buffer.add(":"); | |
577 } | |
578 } | |
579 buffer.add("for(;"); | |
580 visitConditionGraph(info.condition); | |
581 buffer.add(";"); | |
582 if (isExpression(info.updates)) { | |
583 visitExpressionGraph(info.updates); | |
584 buffer.add(") {\n"); | |
585 indent++; | |
586 | |
587 HBlockInformation oldInfo = currentBlockInformation; | |
588 currentBlockInformation = info.body.start.labeledBlockInformation; | |
589 visitSubGraph(info.body); | |
590 currentBlockInformation = oldInfo; | |
591 | |
592 indent--; | |
593 addIndentation(); | |
594 buffer.add("}\n"); | |
595 } else { | |
596 addIndentation(); | |
597 buffer.add(") {\n"); | |
598 indent++; | |
599 wrapLoopBodyForContinue(info); | |
600 visitSubGraph(info.updates); | |
601 indent--; | |
602 buffer.add("}\n"); | |
603 } | |
604 success = true; | |
605 break; | |
606 } | |
607 case HLoopInformation.DO_WHILE_LOOP: | |
608 // Currently unhandled. | |
609 default: | |
610 } | |
611 } | |
612 return success; | |
613 } | |
614 | |
615 void visitBasicBlock(HBasicBlock node) { | 630 void visitBasicBlock(HBasicBlock node) { |
616 // Abort traversal if we are leaving the currently active sub-graph. | 631 // Abort traversal if we are leaving the currently active sub-graph. |
617 if (!subGraph.contains(node)) return; | 632 if (!subGraph.contains(node)) return; |
618 | 633 |
619 // If this node has special behavior attached, handle it. | 634 // If this node has special behavior attached, handle it. |
620 // If we reach here again while handling the attached information, | 635 // If we reach here again while handling the attached information, |
621 // e.g., because we call visitSubGraph on a subgraph starting here, | 636 // e.g., because we call visitSubGraph on a subgraph starting here, |
622 // don't handle it again. | 637 // don't handle it again. |
623 if (node.hasLabeledBlockInformation() && | 638 if (node.blockInformation !== null && |
624 node.labeledBlockInformation !== currentBlockInformation) { | 639 node.blockInformation !== currentBlockInformation) { |
625 HBlockInformation oldBlockInformation = currentBlockInformation; | 640 HBlockInformation oldBlockInformation = currentBlockInformation; |
626 currentBlockInformation = node.labeledBlockInformation; | 641 currentBlockInformation = node.blockInformation; |
627 handleLabeledBlock(currentBlockInformation); | 642 bool success = currentBlockInformation.accept(this); |
628 currentBlockInformation = oldBlockInformation; | 643 currentBlockInformation = oldBlockInformation; |
629 return; | 644 if (success) return; |
| 645 |
| 646 // If our special handling didn't succeed, we have to emit a generic |
| 647 // version. This still requires special handling for loop-blocks |
| 648 if (node.isLoopHeader()) { |
| 649 beginLoop(node); |
| 650 } |
630 } | 651 } |
631 | |
632 if (node.isLoopHeader() && | |
633 node.loopInformation !== currentBlockInformation) { | |
634 HBlockInformation oldBlockInformation = currentBlockInformation; | |
635 currentBlockInformation = node.loopInformation; | |
636 bool prettyLoop = handleLoop(node); | |
637 currentBlockInformation = oldBlockInformation; | |
638 if (prettyLoop) { | |
639 visitBasicBlock(node.loopInformation.joinBlock); | |
640 return; | |
641 } | |
642 beginLoop(node); | |
643 } | |
644 | |
645 iterateBasicBlock(node); | 652 iterateBasicBlock(node); |
646 } | 653 } |
647 | 654 |
648 void iterateBasicBlock(HBasicBlock node) { | 655 void iterateBasicBlock(HBasicBlock node) { |
649 currentBlock = node; | 656 currentBlock = node; |
650 HInstruction instruction = node.first; | 657 HInstruction instruction = node.first; |
651 while (instruction != null) { | 658 while (instruction != null) { |
652 if (instruction === node.last) { | 659 if (instruction === node.last) { |
653 for (HBasicBlock successor in node.successors) { | 660 for (HBasicBlock successor in node.successors) { |
654 int index = successor.predecessors.indexOf(node); | 661 int index = successor.predecessors.indexOf(node); |
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1607 buffer.add(') '); | 1614 buffer.add(') '); |
1608 bailout(node, 'Not a string'); | 1615 bailout(node, 'Not a string'); |
1609 } else if (node.isMutableArray()) { | 1616 } else if (node.isMutableArray()) { |
1610 buffer.add('if ('); | 1617 buffer.add('if ('); |
1611 checkObject(input, '!=='); | 1618 checkObject(input, '!=='); |
1612 buffer.add('||'); | 1619 buffer.add('||'); |
1613 checkArray(input, '!=='); | 1620 checkArray(input, '!=='); |
1614 buffer.add('||'); | 1621 buffer.add('||'); |
1615 checkImmutableArray(input); | 1622 checkImmutableArray(input); |
1616 buffer.add(') '); | 1623 buffer.add(') '); |
1617 bailout(node, 'Not a mutable array'); | 1624 bailout(node, 'Not a mutable array'); |
1618 } else if (node.isArray()) { | 1625 } else if (node.isArray()) { |
1619 buffer.add('if ('); | 1626 buffer.add('if ('); |
1620 checkObject(input, '!=='); | 1627 checkObject(input, '!=='); |
1621 buffer.add('||'); | 1628 buffer.add('||'); |
1622 checkArray(input, '!=='); | 1629 checkArray(input, '!=='); |
1623 buffer.add(') '); | 1630 buffer.add(') '); |
1624 bailout(node, 'Not an array'); | 1631 bailout(node, 'Not an array'); |
1625 } else if (node.isStringOrArray()) { | 1632 } else if (node.isStringOrArray()) { |
1626 buffer.add('if ('); | 1633 buffer.add('if ('); |
1627 checkString(input, '!=='); | 1634 checkString(input, '!=='); |
1628 buffer.add(' && ('); | 1635 buffer.add(' && ('); |
1629 checkObject(input, '!=='); | 1636 checkObject(input, '!=='); |
1630 buffer.add('||'); | 1637 buffer.add('||'); |
1631 checkArray(input, '!=='); | 1638 checkArray(input, '!=='); |
1632 buffer.add(')) '); | 1639 buffer.add(')) '); |
1633 bailout(node, 'Not a string or array'); | 1640 bailout(node, 'Not a string or array'); |
1634 } else { | 1641 } else { |
1635 unreachable(); | 1642 unreachable(); |
1636 } | 1643 } |
1637 buffer.add(';\n'); | 1644 buffer.add(';\n'); |
1638 } | 1645 } |
1639 | 1646 |
1640 void beginLoop(HBasicBlock block) { | 1647 void beginLoop(HBasicBlock block) { |
1641 addIndentation(); | 1648 addIndentation(); |
1642 for (LabelElement label in block.loopInformation.labels) { | 1649 HLoopInformation info = block.blockInformation; |
| 1650 for (LabelElement label in info.labels) { |
1643 writeLabel(label); | 1651 writeLabel(label); |
1644 buffer.add(":"); | 1652 buffer.add(":"); |
1645 } | 1653 } |
1646 buffer.add('while (true) {\n'); | 1654 buffer.add('while (true) {\n'); |
1647 indent++; | 1655 indent++; |
1648 } | 1656 } |
1649 | 1657 |
1650 void endLoop(HBasicBlock block) { | 1658 void endLoop(HBasicBlock block) { |
1651 indent--; | 1659 indent--; |
1652 addIndentation(); | 1660 addIndentation(); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1751 HBoundsCheck instruction = argument; | 1759 HBoundsCheck instruction = argument; |
1752 return unwrap(instruction.index); | 1760 return unwrap(instruction.index); |
1753 } else if (argument is HTypeGuard) { | 1761 } else if (argument is HTypeGuard) { |
1754 HTypeGuard instruction = argument; | 1762 HTypeGuard instruction = argument; |
1755 return unwrap(instruction.guarded); | 1763 return unwrap(instruction.guarded); |
1756 } else { | 1764 } else { |
1757 return argument; | 1765 return argument; |
1758 } | 1766 } |
1759 } | 1767 } |
1760 | 1768 |
1761 bool handleLoop(HBasicBlock node) => false; | 1769 bool visitLoopInfo(HLoopInformation info) => false; |
1762 | 1770 |
1763 void visitTypeGuard(HTypeGuard node) { | 1771 void visitTypeGuard(HTypeGuard node) { |
1764 indent--; | 1772 indent--; |
1765 addIndentation(); | 1773 addIndentation(); |
1766 buffer.add('case ${node.state}:\n'); | 1774 buffer.add('case ${node.state}:\n'); |
1767 indent++; | 1775 indent++; |
1768 addIndentation(); | 1776 addIndentation(); |
1769 buffer.add('state = 0;\n'); | 1777 buffer.add('state = 0;\n'); |
1770 | 1778 |
1771 setup.add(' case ${node.state}:\n'); | 1779 setup.add(' case ${node.state}:\n'); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1803 indent++; | 1811 indent++; |
1804 } | 1812 } |
1805 | 1813 |
1806 void endBailoutSwitch() { | 1814 void endBailoutSwitch() { |
1807 indent--; // Close 'case'. | 1815 indent--; // Close 'case'. |
1808 indent--; | 1816 indent--; |
1809 addIndentation(); | 1817 addIndentation(); |
1810 buffer.add('}\n'); // Close 'switch'. | 1818 buffer.add('}\n'); // Close 'switch'. |
1811 } | 1819 } |
1812 | 1820 |
1813 | |
1814 void beginLoop(HBasicBlock block) { | 1821 void beginLoop(HBasicBlock block) { |
1815 // TODO(ngeoffray): Don't put labels on loops that don't bailout. | 1822 // TODO(ngeoffray): Don't put labels on loops that don't bailout. |
1816 String newLabel = pushLabel(); | 1823 String newLabel = pushLabel(); |
1817 if (block.hasGuards()) { | 1824 if (block.hasGuards()) { |
1818 startBailoutCase(block.guards, const <HTypeGuard>[]); | 1825 startBailoutCase(block.guards, const <HTypeGuard>[]); |
1819 } | 1826 } |
1820 | 1827 |
1821 addIndentation(); | 1828 addIndentation(); |
1822 for (LabelElement label in block.loopInformation.labels) { | 1829 HLoopInformation loopInformation = block.blockInformation; |
| 1830 for (LabelElement label in loopInformation.labels) { |
1823 writeLabel(label); | 1831 writeLabel(label); |
1824 buffer.add(":"); | 1832 buffer.add(":"); |
1825 } | 1833 } |
1826 buffer.add('$newLabel: while (true) {\n'); | 1834 buffer.add('$newLabel: while (true) {\n'); |
1827 indent++; | 1835 indent++; |
1828 | 1836 |
1829 if (block.hasGuards()) { | 1837 if (block.hasGuards()) { |
1830 startBailoutSwitch(); | 1838 startBailoutSwitch(); |
1831 } | 1839 } |
1832 } | 1840 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1905 startBailoutSwitch(); | 1913 startBailoutSwitch(); |
1906 } | 1914 } |
1907 } | 1915 } |
1908 | 1916 |
1909 void endElse(HIf node) { | 1917 void endElse(HIf node) { |
1910 if (node.elseBlock.hasGuards()) { | 1918 if (node.elseBlock.hasGuards()) { |
1911 endBailoutSwitch(); | 1919 endBailoutSwitch(); |
1912 } | 1920 } |
1913 } | 1921 } |
1914 } | 1922 } |
OLD | NEW |