| 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 |