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, HBlockInformationVisitor { | 83 class SsaCodeGenerator implements HVisitor { |
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 bool visitIfInfo(HIfBlockInformation info) { | 416 void handleLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
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) { | |
524 addIndentation(); | 417 addIndentation(); |
525 Link<Element> continueOverrides = const EmptyLink<Element>(); | 418 Link<Element> continueOverrides = const EmptyLink<Element>(); |
526 // If [labeledBlockInfo.isContinue], the block is an artificial | 419 // If [labeledBlockInfo.isContinue], the block is an artificial |
527 // block around the body of a loop with an update block, so that | 420 // block around the body of a loop with an update block, so that |
528 // continues of the loop can be written as breaks of the body | 421 // continues of the loop can be written as breaks of the body |
529 // block. | 422 // block. |
530 if (labeledBlockInfo.isContinue) { | 423 if (labeledBlockInfo.isContinue) { |
531 for (LabelElement label in labeledBlockInfo.labels) { | 424 for (LabelElement label in labeledBlockInfo.labels) { |
532 if (label.isContinueTarget) { | 425 if (label.isContinueTarget) { |
533 writeContinueLabel(label); | 426 writeContinueLabel(label); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 visitBasicBlock(labeledBlockInfo.joinBlock); | 467 visitBasicBlock(labeledBlockInfo.joinBlock); |
575 } | 468 } |
576 if (labeledBlockInfo.isContinue) { | 469 if (labeledBlockInfo.isContinue) { |
577 while (!continueOverrides.isEmpty()) { | 470 while (!continueOverrides.isEmpty()) { |
578 continueAction.remove(continueOverrides.head); | 471 continueAction.remove(continueOverrides.head); |
579 continueOverrides = continueOverrides.tail; | 472 continueOverrides = continueOverrides.tail; |
580 } | 473 } |
581 } else { | 474 } else { |
582 breakAction.remove(labeledBlockInfo.target); | 475 breakAction.remove(labeledBlockInfo.target); |
583 } | 476 } |
584 return true; | |
585 } | 477 } |
586 | 478 |
587 void emitLogicalOperation(HPhi node, String operation) { | 479 void emitLogicalOperation(HPhi node, String operation) { |
588 JSBinaryOperatorPrecedence operatorPrecedence = | 480 JSBinaryOperatorPrecedence operatorPrecedence = |
589 JSPrecedence.binary[operation]; | 481 JSPrecedence.binary[operation]; |
590 beginExpression(operatorPrecedence.precedence); | 482 beginExpression(operatorPrecedence.precedence); |
591 use(node.inputs[0], operatorPrecedence.left); | 483 use(node.inputs[0], operatorPrecedence.left); |
592 buffer.add(" $operation "); | 484 buffer.add(" $operation "); |
593 use(node.inputs[1], operatorPrecedence.right); | 485 use(node.inputs[1], operatorPrecedence.right); |
594 endExpression(operatorPrecedence.precedence); | 486 endExpression(operatorPrecedence.precedence); |
(...skipping 25 matching lines...) Expand all Loading... |
620 if (label.isContinueTarget) { | 512 if (label.isContinueTarget) { |
621 continueAction.remove(label); | 513 continueAction.remove(label); |
622 } | 514 } |
623 } | 515 } |
624 } else { | 516 } else { |
625 // Loop body contains no continues, so we don't need a break target. | 517 // Loop body contains no continues, so we don't need a break target. |
626 visitSubGraph(info.body); | 518 visitSubGraph(info.body); |
627 } | 519 } |
628 } | 520 } |
629 | 521 |
| 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 |
630 void visitBasicBlock(HBasicBlock node) { | 615 void visitBasicBlock(HBasicBlock node) { |
631 // Abort traversal if we are leaving the currently active sub-graph. | 616 // Abort traversal if we are leaving the currently active sub-graph. |
632 if (!subGraph.contains(node)) return; | 617 if (!subGraph.contains(node)) return; |
633 | 618 |
634 // If this node has special behavior attached, handle it. | 619 // If this node has special behavior attached, handle it. |
635 // If we reach here again while handling the attached information, | 620 // If we reach here again while handling the attached information, |
636 // e.g., because we call visitSubGraph on a subgraph starting here, | 621 // e.g., because we call visitSubGraph on a subgraph starting here, |
637 // don't handle it again. | 622 // don't handle it again. |
638 if (node.blockInformation !== null && | 623 if (node.hasLabeledBlockInformation() && |
639 node.blockInformation !== currentBlockInformation) { | 624 node.labeledBlockInformation !== currentBlockInformation) { |
640 HBlockInformation oldBlockInformation = currentBlockInformation; | 625 HBlockInformation oldBlockInformation = currentBlockInformation; |
641 currentBlockInformation = node.blockInformation; | 626 currentBlockInformation = node.labeledBlockInformation; |
642 bool success = currentBlockInformation.accept(this); | 627 handleLabeledBlock(currentBlockInformation); |
643 currentBlockInformation = oldBlockInformation; | 628 currentBlockInformation = oldBlockInformation; |
644 if (success) return; | 629 return; |
| 630 } |
645 | 631 |
646 // If our special handling didn't succeed, we have to emit a generic | 632 if (node.isLoopHeader() && |
647 // version. This still requires special handling for loop-blocks | 633 node.loopInformation !== currentBlockInformation) { |
648 if (node.isLoopHeader()) { | 634 HBlockInformation oldBlockInformation = currentBlockInformation; |
649 beginLoop(node); | 635 currentBlockInformation = node.loopInformation; |
| 636 bool prettyLoop = handleLoop(node); |
| 637 currentBlockInformation = oldBlockInformation; |
| 638 if (prettyLoop) { |
| 639 visitBasicBlock(node.loopInformation.joinBlock); |
| 640 return; |
650 } | 641 } |
| 642 beginLoop(node); |
651 } | 643 } |
| 644 |
652 iterateBasicBlock(node); | 645 iterateBasicBlock(node); |
653 } | 646 } |
654 | 647 |
655 void iterateBasicBlock(HBasicBlock node) { | 648 void iterateBasicBlock(HBasicBlock node) { |
656 currentBlock = node; | 649 currentBlock = node; |
657 HInstruction instruction = node.first; | 650 HInstruction instruction = node.first; |
658 while (instruction != null) { | 651 while (instruction != null) { |
659 if (instruction === node.last) { | 652 if (instruction === node.last) { |
660 for (HBasicBlock successor in node.successors) { | 653 for (HBasicBlock successor in node.successors) { |
661 int index = successor.predecessors.indexOf(node); | 654 int index = successor.predecessors.indexOf(node); |
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1614 buffer.add(') '); | 1607 buffer.add(') '); |
1615 bailout(node, 'Not a string'); | 1608 bailout(node, 'Not a string'); |
1616 } else if (node.isMutableArray()) { | 1609 } else if (node.isMutableArray()) { |
1617 buffer.add('if ('); | 1610 buffer.add('if ('); |
1618 checkObject(input, '!=='); | 1611 checkObject(input, '!=='); |
1619 buffer.add('||'); | 1612 buffer.add('||'); |
1620 checkArray(input, '!=='); | 1613 checkArray(input, '!=='); |
1621 buffer.add('||'); | 1614 buffer.add('||'); |
1622 checkImmutableArray(input); | 1615 checkImmutableArray(input); |
1623 buffer.add(') '); | 1616 buffer.add(') '); |
1624 bailout(node, 'Not a mutable array'); | 1617 bailout(node, 'Not a mutable array'); |
1625 } else if (node.isArray()) { | 1618 } else if (node.isArray()) { |
1626 buffer.add('if ('); | 1619 buffer.add('if ('); |
1627 checkObject(input, '!=='); | 1620 checkObject(input, '!=='); |
1628 buffer.add('||'); | 1621 buffer.add('||'); |
1629 checkArray(input, '!=='); | 1622 checkArray(input, '!=='); |
1630 buffer.add(') '); | 1623 buffer.add(') '); |
1631 bailout(node, 'Not an array'); | 1624 bailout(node, 'Not an array'); |
1632 } else if (node.isStringOrArray()) { | 1625 } else if (node.isStringOrArray()) { |
1633 buffer.add('if ('); | 1626 buffer.add('if ('); |
1634 checkString(input, '!=='); | 1627 checkString(input, '!=='); |
1635 buffer.add(' && ('); | 1628 buffer.add(' && ('); |
1636 checkObject(input, '!=='); | 1629 checkObject(input, '!=='); |
1637 buffer.add('||'); | 1630 buffer.add('||'); |
1638 checkArray(input, '!=='); | 1631 checkArray(input, '!=='); |
1639 buffer.add(')) '); | 1632 buffer.add(')) '); |
1640 bailout(node, 'Not a string or array'); | 1633 bailout(node, 'Not a string or array'); |
1641 } else { | 1634 } else { |
1642 unreachable(); | 1635 unreachable(); |
1643 } | 1636 } |
1644 buffer.add(';\n'); | 1637 buffer.add(';\n'); |
1645 } | 1638 } |
1646 | 1639 |
1647 void beginLoop(HBasicBlock block) { | 1640 void beginLoop(HBasicBlock block) { |
1648 addIndentation(); | 1641 addIndentation(); |
1649 HLoopInformation info = block.blockInformation; | 1642 for (LabelElement label in block.loopInformation.labels) { |
1650 for (LabelElement label in info.labels) { | |
1651 writeLabel(label); | 1643 writeLabel(label); |
1652 buffer.add(":"); | 1644 buffer.add(":"); |
1653 } | 1645 } |
1654 buffer.add('while (true) {\n'); | 1646 buffer.add('while (true) {\n'); |
1655 indent++; | 1647 indent++; |
1656 } | 1648 } |
1657 | 1649 |
1658 void endLoop(HBasicBlock block) { | 1650 void endLoop(HBasicBlock block) { |
1659 indent--; | 1651 indent--; |
1660 addIndentation(); | 1652 addIndentation(); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1759 HBoundsCheck instruction = argument; | 1751 HBoundsCheck instruction = argument; |
1760 return unwrap(instruction.index); | 1752 return unwrap(instruction.index); |
1761 } else if (argument is HTypeGuard) { | 1753 } else if (argument is HTypeGuard) { |
1762 HTypeGuard instruction = argument; | 1754 HTypeGuard instruction = argument; |
1763 return unwrap(instruction.guarded); | 1755 return unwrap(instruction.guarded); |
1764 } else { | 1756 } else { |
1765 return argument; | 1757 return argument; |
1766 } | 1758 } |
1767 } | 1759 } |
1768 | 1760 |
1769 bool visitLoopInfo(HLoopInformation info) => false; | 1761 bool handleLoop(HBasicBlock node) => false; |
1770 | 1762 |
1771 void visitTypeGuard(HTypeGuard node) { | 1763 void visitTypeGuard(HTypeGuard node) { |
1772 indent--; | 1764 indent--; |
1773 addIndentation(); | 1765 addIndentation(); |
1774 buffer.add('case ${node.state}:\n'); | 1766 buffer.add('case ${node.state}:\n'); |
1775 indent++; | 1767 indent++; |
1776 addIndentation(); | 1768 addIndentation(); |
1777 buffer.add('state = 0;\n'); | 1769 buffer.add('state = 0;\n'); |
1778 | 1770 |
1779 setup.add(' case ${node.state}:\n'); | 1771 setup.add(' case ${node.state}:\n'); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1811 indent++; | 1803 indent++; |
1812 } | 1804 } |
1813 | 1805 |
1814 void endBailoutSwitch() { | 1806 void endBailoutSwitch() { |
1815 indent--; // Close 'case'. | 1807 indent--; // Close 'case'. |
1816 indent--; | 1808 indent--; |
1817 addIndentation(); | 1809 addIndentation(); |
1818 buffer.add('}\n'); // Close 'switch'. | 1810 buffer.add('}\n'); // Close 'switch'. |
1819 } | 1811 } |
1820 | 1812 |
| 1813 |
1821 void beginLoop(HBasicBlock block) { | 1814 void beginLoop(HBasicBlock block) { |
1822 // TODO(ngeoffray): Don't put labels on loops that don't bailout. | 1815 // TODO(ngeoffray): Don't put labels on loops that don't bailout. |
1823 String newLabel = pushLabel(); | 1816 String newLabel = pushLabel(); |
1824 if (block.hasGuards()) { | 1817 if (block.hasGuards()) { |
1825 startBailoutCase(block.guards, const <HTypeGuard>[]); | 1818 startBailoutCase(block.guards, const <HTypeGuard>[]); |
1826 } | 1819 } |
1827 | 1820 |
1828 addIndentation(); | 1821 addIndentation(); |
1829 HLoopInformation loopInformation = block.blockInformation; | 1822 for (LabelElement label in block.loopInformation.labels) { |
1830 for (LabelElement label in loopInformation.labels) { | |
1831 writeLabel(label); | 1823 writeLabel(label); |
1832 buffer.add(":"); | 1824 buffer.add(":"); |
1833 } | 1825 } |
1834 buffer.add('$newLabel: while (true) {\n'); | 1826 buffer.add('$newLabel: while (true) {\n'); |
1835 indent++; | 1827 indent++; |
1836 | 1828 |
1837 if (block.hasGuards()) { | 1829 if (block.hasGuards()) { |
1838 startBailoutSwitch(); | 1830 startBailoutSwitch(); |
1839 } | 1831 } |
1840 } | 1832 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1913 startBailoutSwitch(); | 1905 startBailoutSwitch(); |
1914 } | 1906 } |
1915 } | 1907 } |
1916 | 1908 |
1917 void endElse(HIf node) { | 1909 void endElse(HIf node) { |
1918 if (node.elseBlock.hasGuards()) { | 1910 if (node.elseBlock.hasGuards()) { |
1919 endBailoutSwitch(); | 1911 endBailoutSwitch(); |
1920 } | 1912 } |
1921 } | 1913 } |
1922 } | 1914 } |
OLD | NEW |