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) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
53 parameterNames[element] = function.isNative() | 53 parameterNames[element] = function.isNative() |
54 ? element.name.slowToString() | 54 ? element.name.slowToString() |
55 : JsNames.getValid('${element.name.slowToString()}'); | 55 : JsNames.getValid('${element.name.slowToString()}'); |
56 }); | 56 }); |
57 return parameterNames; | 57 return parameterNames; |
58 } | 58 } |
59 } | 59 } |
60 | 60 |
61 typedef void ElementAction(Element element); | 61 typedef void ElementAction(Element element); |
62 | 62 |
63 class SsaCodeGenerator implements HVisitor { | 63 class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor { |
64 /** | 64 /** |
65 * Current state for generating simple (non-local-control) code. | 65 * Current state for generating simple (non-local-control) code. |
66 * It is generated as either statements (indented and ';'-terminated), | 66 * It is generated as either statements (indented and ';'-terminated), |
67 * expressions (comma separated) or declarations (also comma separated, | 67 * expressions (comma separated) or declarations (also comma separated, |
68 * but expected to be preceeded by a 'var' so it declares its variables); | 68 * but expected to be preceeded by a 'var' so it declares its variables); |
69 */ | 69 */ |
70 static final int STATE_STATEMENT = 0; | 70 static final int STATE_STATEMENT = 0; |
71 static final int STATE_FIRST_EXPRESSION = 1; | 71 static final int STATE_FIRST_EXPRESSION = 1; |
72 static final int STATE_FIRST_DECLARATION = 2; | 72 static final int STATE_FIRST_DECLARATION = 2; |
73 static final int STATE_EXPRESSION = 3; | 73 static final int STATE_EXPRESSION = 3; |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
386 buffer.add(";\n"); | 386 buffer.add(";\n"); |
387 } | 387 } |
388 | 388 |
389 void implicitBreakWithLabel(TargetElement target) { | 389 void implicitBreakWithLabel(TargetElement target) { |
390 addIndentation(); | 390 addIndentation(); |
391 buffer.add("break "); | 391 buffer.add("break "); |
392 writeImplicitLabel(target); | 392 writeImplicitLabel(target); |
393 buffer.add(";\n"); | 393 buffer.add(";\n"); |
394 } | 394 } |
395 | 395 |
396 void handleLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 396 bool visitIfInfo(HIfBlockInformation info) { |
397 return false; | |
398 } | |
399 | |
400 bool visitAndOrInfo(HAndOrBlockInformation info) { | |
401 return false; | |
402 } | |
403 | |
404 bool visitLoopInfo(HLoopInformation info) { | |
405 bool success = false; | |
406 SubExpression condition = info.condition; | |
407 void visitBodyIgnoreLabels() { | |
408 if (info.body.start.isLabeledBlock()) { | |
409 HBlockInformation oldInfo = currentBlockInformation; | |
410 currentBlockInformation = info.body.start.blockInformation; | |
411 visitSubGraph(info.body); | |
412 currentBlockInformation = oldInfo; | |
413 } else { | |
414 visitSubGraph(info.body); | |
415 } | |
416 } | |
417 if (isCondition(condition)) { | |
floitsch
2012/04/16 13:26:07
I would prefer bailing out here.
if (!isCondition
Lasse Reichstein Nielsen
2012/04/17 12:58:22
Done.
| |
418 switch (info.type) { | |
floitsch
2012/04/16 13:26:07
I would prefer 'kind' instead of 'type'.
Lasse Reichstein Nielsen
2012/04/17 12:58:22
Done.
| |
419 case HLoopInformation.WHILE_LOOP: | |
420 case HLoopInformation.FOR_IN_LOOP: { | |
floitsch
2012/04/16 13:26:07
Afaics there is almost no difference between while
Lasse Reichstein Nielsen
2012/04/17 12:58:22
It can have an update block that isn't just phis.
| |
421 addIndentation(); | |
422 for (LabelElement label in info.labels) { | |
423 writeLabel(label); | |
424 buffer.add(":"); | |
425 } | |
426 bool inlineUpdates = | |
427 info.updates !== null && isExpression(info.updates); | |
428 if (inlineUpdates) { | |
429 buffer.add("for (; "); | |
430 visitConditionGraph(condition); | |
431 buffer.add("; "); | |
432 visitExpressionGraph(info.updates); | |
433 buffer.add(") {\n"); | |
434 indent++; | |
435 // The body might be labeled. Ignore this when recursing on the | |
436 // subgraph. | |
437 // TODO(lrn): Remove this extra labeling when handling all loops | |
438 // using subgraphs. | |
439 visitBodyIgnoreLabels(); | |
440 | |
441 indent--; | |
442 } else { | |
443 buffer.add("while ("); | |
444 visitConditionGraph(condition); | |
445 buffer.add(") {\n"); | |
446 indent++; | |
447 wrapLoopBodyForContinue(info); | |
448 if (info.updates !== null) visitSubGraph(info.updates); | |
449 indent--; | |
450 } | |
451 addIndentation(); | |
452 buffer.add("}\n"); | |
453 success = true; | |
454 break; | |
455 } | |
456 case HLoopInformation.FOR_LOOP: { | |
457 // TODO(lrn): Find a way to put initialization into the for. | |
458 // It's currently handled before we reach the [HLoopInformation]. | |
459 addIndentation(); | |
460 for (LabelElement label in info.labels) { | |
461 if (label.isTarget) { | |
462 writeLabel(label); | |
463 buffer.add(":"); | |
464 } | |
465 } | |
466 buffer.add("for(;"); | |
467 visitConditionGraph(info.condition); | |
468 buffer.add(";"); | |
469 if (isExpression(info.updates)) { | |
470 visitExpressionGraph(info.updates); | |
471 buffer.add(") {\n"); | |
472 indent++; | |
473 | |
474 visitBodyIgnoreLabels(); | |
475 | |
476 indent--; | |
477 addIndentation(); | |
478 buffer.add("}\n"); | |
479 } else { | |
480 addIndentation(); | |
481 buffer.add(") {\n"); | |
482 indent++; | |
483 wrapLoopBodyForContinue(info); | |
484 visitSubGraph(info.updates); | |
485 indent--; | |
486 buffer.add("}\n"); | |
487 } | |
488 success = true; | |
489 break; | |
490 } | |
491 case HLoopInformation.DO_WHILE_LOOP: | |
492 // Currently unhandled. | |
floitsch
2012/04/16 13:26:07
We don't have fall-throughs. Why didn't this throu
Lasse Reichstein Nielsen
2012/04/17 12:58:22
It's an empty case, so it's joined with the follow
| |
493 default: | |
floitsch
2012/04/16 13:26:07
Is default an internal error?
Lasse Reichstein Nielsen
2012/04/17 12:58:22
Probably, yes. I'll make it an internal error, and
| |
494 } | |
495 } | |
496 if (success) { | |
floitsch
2012/04/16 13:26:07
Unless wrong you can merge while, for-in and for.
Lasse Reichstein Nielsen
2012/04/17 12:58:22
I'll keep it here, but without the if (I'll return
| |
497 visitBasicBlock(info.joinBlock); | |
498 return true; | |
499 } | |
500 return false; | |
501 } | |
502 | |
503 bool visitLabeledBlockInfo(HLabeledBlockInformation labeledBlockInfo) { | |
397 addIndentation(); | 504 addIndentation(); |
398 Link<Element> continueOverrides = const EmptyLink<Element>(); | 505 Link<Element> continueOverrides = const EmptyLink<Element>(); |
399 // If [labeledBlockInfo.isContinue], the block is an artificial | 506 // If [labeledBlockInfo.isContinue], the block is an artificial |
400 // block around the body of a loop with an update block, so that | 507 // block around the body of a loop with an update block, so that |
401 // continues of the loop can be written as breaks of the body | 508 // continues of the loop can be written as breaks of the body |
402 // block. | 509 // block. |
403 if (labeledBlockInfo.isContinue) { | 510 if (labeledBlockInfo.isContinue) { |
404 for (LabelElement label in labeledBlockInfo.labels) { | 511 for (LabelElement label in labeledBlockInfo.labels) { |
405 if (label.isContinueTarget) { | 512 if (label.isContinueTarget) { |
406 writeContinueLabel(label); | 513 writeContinueLabel(label); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 visitBasicBlock(labeledBlockInfo.joinBlock); | 554 visitBasicBlock(labeledBlockInfo.joinBlock); |
448 } | 555 } |
449 if (labeledBlockInfo.isContinue) { | 556 if (labeledBlockInfo.isContinue) { |
450 while (!continueOverrides.isEmpty()) { | 557 while (!continueOverrides.isEmpty()) { |
451 continueAction.remove(continueOverrides.head); | 558 continueAction.remove(continueOverrides.head); |
452 continueOverrides = continueOverrides.tail; | 559 continueOverrides = continueOverrides.tail; |
453 } | 560 } |
454 } else { | 561 } else { |
455 breakAction.remove(labeledBlockInfo.target); | 562 breakAction.remove(labeledBlockInfo.target); |
456 } | 563 } |
564 return true; | |
457 } | 565 } |
458 | 566 |
459 void emitLogicalOperation(HPhi node, String operation) { | 567 void emitLogicalOperation(HPhi node, String operation) { |
460 JSBinaryOperatorPrecedence operatorPrecedence = | 568 JSBinaryOperatorPrecedence operatorPrecedence = |
461 JSPrecedence.binary[operation]; | 569 JSPrecedence.binary[operation]; |
462 beginExpression(operatorPrecedence.precedence); | 570 beginExpression(operatorPrecedence.precedence); |
463 use(node.inputs[0], operatorPrecedence.left); | 571 use(node.inputs[0], operatorPrecedence.left); |
464 buffer.add(" $operation "); | 572 buffer.add(" $operation "); |
465 use(node.inputs[1], operatorPrecedence.right); | 573 use(node.inputs[1], operatorPrecedence.right); |
466 endExpression(operatorPrecedence.precedence); | 574 endExpression(operatorPrecedence.precedence); |
(...skipping 25 matching lines...) Expand all Loading... | |
492 if (label.isContinueTarget) { | 600 if (label.isContinueTarget) { |
493 continueAction.remove(label); | 601 continueAction.remove(label); |
494 } | 602 } |
495 } | 603 } |
496 } else { | 604 } else { |
497 // Loop body contains no continues, so we don't need a break target. | 605 // Loop body contains no continues, so we don't need a break target. |
498 visitSubGraph(info.body); | 606 visitSubGraph(info.body); |
499 } | 607 } |
500 } | 608 } |
501 | 609 |
502 bool handleLoop(HBasicBlock node) { | |
503 bool success = false; | |
504 assert(node.isLoopHeader()); | |
505 HLoopInformation info = node.loopInformation; | |
506 SubExpression condition = info.condition; | |
507 if (isCondition(condition)) { | |
508 switch (info.type) { | |
509 case HLoopInformation.WHILE_LOOP: | |
510 case HLoopInformation.FOR_IN_LOOP: { | |
511 addIndentation(); | |
512 for (LabelElement label in info.labels) { | |
513 writeLabel(label); | |
514 buffer.add(":"); | |
515 } | |
516 bool inlineUpdates = | |
517 info.updates !== null && isExpression(info.updates); | |
518 if (inlineUpdates) { | |
519 buffer.add("for (; "); | |
520 visitConditionGraph(condition); | |
521 buffer.add("; "); | |
522 visitExpressionGraph(info.updates); | |
523 buffer.add(") {\n"); | |
524 indent++; | |
525 // The body might be labeled. Ignore this when recursing on the | |
526 // subgraph. | |
527 // TODO(lrn): Remove this extra labeling when handling all loops | |
528 // using subgraphs. | |
529 HBlockInformation oldInfo = currentBlockInformation; | |
530 currentBlockInformation = info.body.start.labeledBlockInformation; | |
531 visitSubGraph(info.body); | |
532 currentBlockInformation = oldInfo; | |
533 | |
534 indent--; | |
535 } else { | |
536 buffer.add("while ("); | |
537 visitConditionGraph(condition); | |
538 buffer.add(") {\n"); | |
539 indent++; | |
540 wrapLoopBodyForContinue(info); | |
541 if (info.updates !== null) visitSubGraph(info.updates); | |
542 indent--; | |
543 } | |
544 addIndentation(); | |
545 buffer.add("}\n"); | |
546 success = true; | |
547 break; | |
548 } | |
549 case HLoopInformation.FOR_LOOP: { | |
550 // TODO(lrn): Find a way to put initialization into the for. | |
551 // It's currently handled before we reach the [HLoopInformation]. | |
552 addIndentation(); | |
553 for (LabelElement label in info.labels) { | |
554 if (label.isTarget) { | |
555 writeLabel(label); | |
556 buffer.add(":"); | |
557 } | |
558 } | |
559 buffer.add("for(;"); | |
560 visitConditionGraph(info.condition); | |
561 buffer.add(";"); | |
562 if (isExpression(info.updates)) { | |
563 visitExpressionGraph(info.updates); | |
564 buffer.add(") {\n"); | |
565 indent++; | |
566 | |
567 HBlockInformation oldInfo = currentBlockInformation; | |
568 currentBlockInformation = info.body.start.labeledBlockInformation; | |
569 visitSubGraph(info.body); | |
570 currentBlockInformation = oldInfo; | |
571 | |
572 indent--; | |
573 addIndentation(); | |
574 buffer.add("}\n"); | |
575 } else { | |
576 addIndentation(); | |
577 buffer.add(") {\n"); | |
578 indent++; | |
579 wrapLoopBodyForContinue(info); | |
580 visitSubGraph(info.updates); | |
581 indent--; | |
582 buffer.add("}\n"); | |
583 } | |
584 success = true; | |
585 break; | |
586 } | |
587 case HLoopInformation.DO_WHILE_LOOP: | |
588 // Currently unhandled. | |
589 default: | |
590 } | |
591 } | |
592 return success; | |
593 } | |
594 | |
595 void visitBasicBlock(HBasicBlock node) { | 610 void visitBasicBlock(HBasicBlock node) { |
596 // Abort traversal if we are leaving the currently active sub-graph. | 611 // Abort traversal if we are leaving the currently active sub-graph. |
597 if (!subGraph.contains(node)) return; | 612 if (!subGraph.contains(node)) return; |
598 | 613 |
599 // If this node has special behavior attached, handle it. | 614 // If this node has special behavior attached, handle it. |
600 // If we reach here again while handling the attached information, | 615 // If we reach here again while handling the attached information, |
601 // e.g., because we call visitSubGraph on a subgraph starting here, | 616 // e.g., because we call visitSubGraph on a subgraph starting here, |
602 // don't handle it again. | 617 // don't handle it again. |
603 if (node.hasLabeledBlockInformation() && | 618 if (node.blockInformation !== null && |
604 node.labeledBlockInformation !== currentBlockInformation) { | 619 node.blockInformation !== currentBlockInformation) { |
605 HBlockInformation oldBlockInformation = currentBlockInformation; | 620 HBlockInformation oldBlockInformation = currentBlockInformation; |
606 currentBlockInformation = node.labeledBlockInformation; | 621 currentBlockInformation = node.blockInformation; |
607 handleLabeledBlock(currentBlockInformation); | 622 bool success = currentBlockInformation.accept(this); |
608 currentBlockInformation = oldBlockInformation; | 623 currentBlockInformation = oldBlockInformation; |
609 return; | 624 if (success) return; |
625 | |
626 // Even if our special handling didn't succeed, loop blocks | |
floitsch
2012/04/16 13:26:07
If our special handling didn't succeed, we have to
Lasse Reichstein Nielsen
2012/04/17 12:58:22
Done.
| |
627 // have special treatement in the primitive traversal too. | |
628 if (node.isLoopHeader()) { | |
629 beginLoop(node); | |
630 } | |
610 } | 631 } |
611 | |
612 if (node.isLoopHeader() && | |
613 node.loopInformation !== currentBlockInformation) { | |
614 HBlockInformation oldBlockInformation = currentBlockInformation; | |
615 currentBlockInformation = node.loopInformation; | |
616 bool prettyLoop = handleLoop(node); | |
617 currentBlockInformation = oldBlockInformation; | |
618 if (prettyLoop) { | |
619 visitBasicBlock(node.loopInformation.joinBlock); | |
620 return; | |
621 } | |
622 beginLoop(node); | |
623 } | |
624 | |
625 iterateBasicBlock(node); | 632 iterateBasicBlock(node); |
626 } | 633 } |
627 | 634 |
628 void iterateBasicBlock(HBasicBlock node) { | 635 void iterateBasicBlock(HBasicBlock node) { |
629 currentBlock = node; | 636 currentBlock = node; |
630 HInstruction instruction = node.first; | 637 HInstruction instruction = node.first; |
631 while (instruction != null) { | 638 while (instruction != null) { |
632 if (instruction === node.last) { | 639 if (instruction === node.last) { |
633 for (HBasicBlock successor in node.successors) { | 640 for (HBasicBlock successor in node.successors) { |
634 int index = successor.predecessors.indexOf(node); | 641 int index = successor.predecessors.indexOf(node); |
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1584 buffer.add(') '); | 1591 buffer.add(') '); |
1585 bailout(node, 'Not a string'); | 1592 bailout(node, 'Not a string'); |
1586 } else if (node.isMutableArray()) { | 1593 } else if (node.isMutableArray()) { |
1587 buffer.add('if ('); | 1594 buffer.add('if ('); |
1588 checkObject(input, '!=='); | 1595 checkObject(input, '!=='); |
1589 buffer.add('||'); | 1596 buffer.add('||'); |
1590 checkArray(input, '!=='); | 1597 checkArray(input, '!=='); |
1591 buffer.add('||'); | 1598 buffer.add('||'); |
1592 checkImmutableArray(input); | 1599 checkImmutableArray(input); |
1593 buffer.add(') '); | 1600 buffer.add(') '); |
1594 bailout(node, 'Not a mutable array'); | 1601 bailout(node, 'Not a mutable array'); |
1595 } else if (node.isArray()) { | 1602 } else if (node.isArray()) { |
1596 buffer.add('if ('); | 1603 buffer.add('if ('); |
1597 checkObject(input, '!=='); | 1604 checkObject(input, '!=='); |
1598 buffer.add('||'); | 1605 buffer.add('||'); |
1599 checkArray(input, '!=='); | 1606 checkArray(input, '!=='); |
1600 buffer.add(') '); | 1607 buffer.add(') '); |
1601 bailout(node, 'Not an array'); | 1608 bailout(node, 'Not an array'); |
1602 } else if (node.isStringOrArray()) { | 1609 } else if (node.isStringOrArray()) { |
1603 buffer.add('if ('); | 1610 buffer.add('if ('); |
1604 checkString(input, '!=='); | 1611 checkString(input, '!=='); |
1605 buffer.add(' && ('); | 1612 buffer.add(' && ('); |
1606 checkObject(input, '!=='); | 1613 checkObject(input, '!=='); |
1607 buffer.add('||'); | 1614 buffer.add('||'); |
1608 checkArray(input, '!=='); | 1615 checkArray(input, '!=='); |
1609 buffer.add(')) '); | 1616 buffer.add(')) '); |
1610 bailout(node, 'Not a string or array'); | 1617 bailout(node, 'Not a string or array'); |
1611 } else { | 1618 } else { |
1612 unreachable(); | 1619 unreachable(); |
1613 } | 1620 } |
1614 buffer.add(';\n'); | 1621 buffer.add(';\n'); |
1615 } | 1622 } |
1616 | 1623 |
1617 void beginLoop(HBasicBlock block) { | 1624 void beginLoop(HBasicBlock block) { |
1618 addIndentation(); | 1625 addIndentation(); |
1619 for (LabelElement label in block.loopInformation.labels) { | 1626 HLoopInformation info = block.blockInformation; |
1627 for (LabelElement label in info.labels) { | |
1620 writeLabel(label); | 1628 writeLabel(label); |
1621 buffer.add(":"); | 1629 buffer.add(":"); |
1622 } | 1630 } |
1623 buffer.add('while (true) {\n'); | 1631 buffer.add('while (true) {\n'); |
1624 indent++; | 1632 indent++; |
1625 } | 1633 } |
1626 | 1634 |
1627 void endLoop(HBasicBlock block) { | 1635 void endLoop(HBasicBlock block) { |
1628 indent--; | 1636 indent--; |
1629 addIndentation(); | 1637 addIndentation(); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1728 HBoundsCheck instruction = argument; | 1736 HBoundsCheck instruction = argument; |
1729 return unwrap(instruction.index); | 1737 return unwrap(instruction.index); |
1730 } else if (argument is HTypeGuard) { | 1738 } else if (argument is HTypeGuard) { |
1731 HTypeGuard instruction = argument; | 1739 HTypeGuard instruction = argument; |
1732 return unwrap(instruction.guarded); | 1740 return unwrap(instruction.guarded); |
1733 } else { | 1741 } else { |
1734 return argument; | 1742 return argument; |
1735 } | 1743 } |
1736 } | 1744 } |
1737 | 1745 |
1738 bool handleLoop(HBasicBlock node) => false; | 1746 bool visitLoopInfo(HLoopInformation info) => false; |
1739 | 1747 |
1740 void visitTypeGuard(HTypeGuard node) { | 1748 void visitTypeGuard(HTypeGuard node) { |
1741 indent--; | 1749 indent--; |
1742 addIndentation(); | 1750 addIndentation(); |
1743 buffer.add('case ${node.state}:\n'); | 1751 buffer.add('case ${node.state}:\n'); |
1744 indent++; | 1752 indent++; |
1745 addIndentation(); | 1753 addIndentation(); |
1746 buffer.add('state = 0;\n'); | 1754 buffer.add('state = 0;\n'); |
1747 | 1755 |
1748 setup.add(' case ${node.state}:\n'); | 1756 setup.add(' case ${node.state}:\n'); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1780 indent++; | 1788 indent++; |
1781 } | 1789 } |
1782 | 1790 |
1783 void endBailoutSwitch() { | 1791 void endBailoutSwitch() { |
1784 indent--; // Close 'case'. | 1792 indent--; // Close 'case'. |
1785 indent--; | 1793 indent--; |
1786 addIndentation(); | 1794 addIndentation(); |
1787 buffer.add('}\n'); // Close 'switch'. | 1795 buffer.add('}\n'); // Close 'switch'. |
1788 } | 1796 } |
1789 | 1797 |
1790 | |
1791 void beginLoop(HBasicBlock block) { | 1798 void beginLoop(HBasicBlock block) { |
1792 // TODO(ngeoffray): Don't put labels on loops that don't bailout. | 1799 // TODO(ngeoffray): Don't put labels on loops that don't bailout. |
1793 String newLabel = pushLabel(); | 1800 String newLabel = pushLabel(); |
1794 if (block.hasGuards()) { | 1801 if (block.hasGuards()) { |
1795 startBailoutCase(block.guards, const <HTypeGuard>[]); | 1802 startBailoutCase(block.guards, const <HTypeGuard>[]); |
1796 } | 1803 } |
1797 | 1804 |
1798 addIndentation(); | 1805 addIndentation(); |
1799 for (SourceString label in block.loopInformation.labels) { | 1806 HLoopInformation info = block.blockInformation; |
1807 for (SourceString label in info.labels) { | |
1800 writeLabel(label); | 1808 writeLabel(label); |
1801 buffer.add(":"); | 1809 buffer.add(":"); |
1802 } | 1810 } |
1803 buffer.add('$newLabel: while (true) {\n'); | 1811 buffer.add('$newLabel: while (true) {\n'); |
1804 indent++; | 1812 indent++; |
1805 | 1813 |
1806 if (block.hasGuards()) { | 1814 if (block.hasGuards()) { |
1807 startBailoutSwitch(); | 1815 startBailoutSwitch(); |
1808 } | 1816 } |
1809 } | 1817 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1882 startBailoutSwitch(); | 1890 startBailoutSwitch(); |
1883 } | 1891 } |
1884 } | 1892 } |
1885 | 1893 |
1886 void endElse(HIf node) { | 1894 void endElse(HIf node) { |
1887 if (node.elseBlock.hasGuards()) { | 1895 if (node.elseBlock.hasGuards()) { |
1888 endBailoutSwitch(); | 1896 endBailoutSwitch(); |
1889 } | 1897 } |
1890 } | 1898 } |
1891 } | 1899 } |
OLD | NEW |