| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 interface HVisitor<R> { | 5 interface HVisitor<R> { |
| 6 R visitAdd(HAdd node); | 6 R visitAdd(HAdd node); |
| 7 R visitBitAnd(HBitAnd node); | 7 R visitBitAnd(HBitAnd node); |
| 8 R visitBitNot(HBitNot node); | 8 R visitBitNot(HBitNot node); |
| 9 R visitBitOr(HBitOr node); | 9 R visitBitOr(HBitOr node); |
| 10 R visitBitXor(HBitXor node); | 10 R visitBitXor(HBitXor node); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 blocks.add(block); | 131 blocks.add(block); |
| 132 assert(blocks[id] === block); | 132 assert(blocks[id] === block); |
| 133 } | 133 } |
| 134 | 134 |
| 135 HBasicBlock addNewBlock() { | 135 HBasicBlock addNewBlock() { |
| 136 HBasicBlock result = new HBasicBlock(); | 136 HBasicBlock result = new HBasicBlock(); |
| 137 addBlock(result); | 137 addBlock(result); |
| 138 return result; | 138 return result; |
| 139 } | 139 } |
| 140 | 140 |
| 141 HBasicBlock addNewLoopHeaderBlock(int kind, | 141 HBasicBlock addNewLoopHeaderBlock(int type, |
| 142 TargetElement target, | 142 TargetElement target, |
| 143 List<LabelElement> labels) { | 143 List<LabelElement> labels) { |
| 144 HBasicBlock result = addNewBlock(); | 144 HBasicBlock result = addNewBlock(); |
| 145 result.blockInformation = | 145 result.loopInformation = new HLoopInformation(type, result, target, labels); |
| 146 new HLoopInformation(kind, result, target, labels); | |
| 147 return result; | 146 return result; |
| 148 } | 147 } |
| 149 | 148 |
| 150 static HType mapConstantTypeToSsaType(Constant constant) { | 149 static HType mapConstantTypeToSsaType(Constant constant) { |
| 151 if (constant.isNull()) return HType.UNKNOWN; | 150 if (constant.isNull()) return HType.UNKNOWN; |
| 152 if (constant.isBool()) return HType.BOOLEAN; | 151 if (constant.isBool()) return HType.BOOLEAN; |
| 153 if (constant.isInt()) return HType.INTEGER; | 152 if (constant.isInt()) return HType.INTEGER; |
| 154 if (constant.isDouble()) return HType.DOUBLE; | 153 if (constant.isDouble()) return HType.DOUBLE; |
| 155 if (constant.isString()) return HType.STRING; | 154 if (constant.isString()) return HType.STRING; |
| 156 if (constant.isList()) return HType.READABLE_ARRAY; | 155 if (constant.isList()) return HType.READABLE_ARRAY; |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 // this [id]. The exception are back-edges. | 406 // this [id]. The exception are back-edges. |
| 408 int id; | 407 int id; |
| 409 | 408 |
| 410 static final int STATUS_NEW = 0; | 409 static final int STATUS_NEW = 0; |
| 411 static final int STATUS_OPEN = 1; | 410 static final int STATUS_OPEN = 1; |
| 412 static final int STATUS_CLOSED = 2; | 411 static final int STATUS_CLOSED = 2; |
| 413 int status = STATUS_NEW; | 412 int status = STATUS_NEW; |
| 414 | 413 |
| 415 HInstructionList phis; | 414 HInstructionList phis; |
| 416 | 415 |
| 417 HBlockInformation blockInformation = null; | 416 HLoopInformation loopInformation = null; |
| 417 HLabeledBlockInformation labeledBlockInformation = null; |
| 418 HBasicBlock parentLoopHeader = null; | 418 HBasicBlock parentLoopHeader = null; |
| 419 List<HTypeGuard> guards; | 419 List<HTypeGuard> guards; |
| 420 | 420 |
| 421 final List<HBasicBlock> predecessors; | 421 final List<HBasicBlock> predecessors; |
| 422 List<HBasicBlock> successors; | 422 List<HBasicBlock> successors; |
| 423 | 423 |
| 424 HBasicBlock dominator = null; | 424 HBasicBlock dominator = null; |
| 425 final List<HBasicBlock> dominatedBlocks; | 425 final List<HBasicBlock> dominatedBlocks; |
| 426 | 426 |
| 427 HBasicBlock() : this.withId(null); | 427 HBasicBlock() : this.withId(null); |
| 428 HBasicBlock.withId(this.id) | 428 HBasicBlock.withId(this.id) |
| 429 : phis = new HInstructionList(), | 429 : phis = new HInstructionList(), |
| 430 predecessors = <HBasicBlock>[], | 430 predecessors = <HBasicBlock>[], |
| 431 successors = const <HBasicBlock>[], | 431 successors = const <HBasicBlock>[], |
| 432 dominatedBlocks = <HBasicBlock>[], | 432 dominatedBlocks = <HBasicBlock>[], |
| 433 guards = <HTypeGuard>[]; | 433 guards = <HTypeGuard>[]; |
| 434 | 434 |
| 435 int hashCode() => id; | 435 int hashCode() => id; |
| 436 | 436 |
| 437 bool isNew() => status == STATUS_NEW; | 437 bool isNew() => status == STATUS_NEW; |
| 438 bool isOpen() => status == STATUS_OPEN; | 438 bool isOpen() => status == STATUS_OPEN; |
| 439 bool isClosed() => status == STATUS_CLOSED; | 439 bool isClosed() => status == STATUS_CLOSED; |
| 440 | 440 |
| 441 bool isLoopHeader() => blockInformation is HLoopInformation; | 441 bool isLoopHeader() => loopInformation !== null; |
| 442 bool isLabeledBlock() => blockInformation is HLabeledBlockInformation; | 442 bool hasLabeledBlockInformation() => labeledBlockInformation !== null; |
| 443 | 443 |
| 444 bool hasGuards() => !guards.isEmpty(); | 444 bool hasGuards() => !guards.isEmpty(); |
| 445 | 445 |
| 446 void open() { | 446 void open() { |
| 447 assert(isNew()); | 447 assert(isNew()); |
| 448 status = STATUS_OPEN; | 448 status = STATUS_OPEN; |
| 449 } | 449 } |
| 450 | 450 |
| 451 void close(HControlFlow end) { | 451 void close(HControlFlow end) { |
| 452 assert(isOpen()); | 452 assert(isOpen()); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 } else { | 541 } else { |
| 542 successors.add(block); | 542 successors.add(block); |
| 543 } | 543 } |
| 544 block.predecessors.add(this); | 544 block.predecessors.add(this); |
| 545 } | 545 } |
| 546 | 546 |
| 547 void postProcessLoopHeader() { | 547 void postProcessLoopHeader() { |
| 548 assert(isLoopHeader()); | 548 assert(isLoopHeader()); |
| 549 // Only the first entry into the loop is from outside the | 549 // Only the first entry into the loop is from outside the |
| 550 // loop. All other entries must be back edges. | 550 // loop. All other entries must be back edges. |
| 551 HLoopInformation loopInformation = this.blockInformation; | |
| 552 for (int i = 1, length = predecessors.length; i < length; i++) { | 551 for (int i = 1, length = predecessors.length; i < length; i++) { |
| 553 loopInformation.addBackEdge(predecessors[i]); | 552 loopInformation.addBackEdge(predecessors[i]); |
| 554 } | 553 } |
| 555 } | 554 } |
| 556 | 555 |
| 557 /** | 556 /** |
| 558 * Rewrites all uses of the [from] instruction to using the [to] | 557 * Rewrites all uses of the [from] instruction to using the [to] |
| 559 * instruction instead. | 558 * instruction instead. |
| 560 */ | 559 */ |
| 561 void rewrite(HInstruction from, HInstruction to) { | 560 void rewrite(HInstruction from, HInstruction to) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 } | 648 } |
| 650 | 649 |
| 651 bool isValid() { | 650 bool isValid() { |
| 652 assert(isClosed()); | 651 assert(isClosed()); |
| 653 HValidator validator = new HValidator(); | 652 HValidator validator = new HValidator(); |
| 654 validator.visitBasicBlock(this); | 653 validator.visitBasicBlock(this); |
| 655 return validator.isValid; | 654 return validator.isValid; |
| 656 } | 655 } |
| 657 } | 656 } |
| 658 | 657 |
| 658 interface HBlockInformation {} |
| 659 |
| 660 class HLabeledBlockInformation implements HBlockInformation { |
| 661 final SubGraph body; |
| 662 final HBasicBlock joinBlock; |
| 663 final List<LabelElement> labels; |
| 664 final TargetElement target; |
| 665 final bool isContinue; |
| 666 |
| 667 HLabeledBlockInformation(this.body, this.joinBlock, |
| 668 List<LabelElement> labels, |
| 669 [this.isContinue = false]) : |
| 670 this.labels = labels, this.target = labels[0].target; |
| 671 |
| 672 HLabeledBlockInformation.implicit(this.body, |
| 673 this.joinBlock, |
| 674 this.target, |
| 675 [this.isContinue = false]) |
| 676 : this.labels = const<LabelElement>[]; |
| 677 } |
| 678 |
| 679 class LoopTypeVisitor extends AbstractVisitor { |
| 680 const LoopTypeVisitor(); |
| 681 int visitNode(Node node) { |
| 682 unreachable(); |
| 683 } |
| 684 int visitWhile(While node) => HLoopInformation.WHILE_LOOP; |
| 685 int visitFor(For node) => HLoopInformation.FOR_LOOP; |
| 686 int visitDoWhile(DoWhile node) => HLoopInformation.DO_WHILE_LOOP; |
| 687 int visitForIn(ForIn node) => HLoopInformation.FOR_IN_LOOP; |
| 688 } |
| 689 |
| 690 class HLoopInformation implements HBlockInformation { |
| 691 static final int WHILE_LOOP = 0; |
| 692 static final int FOR_LOOP = 1; |
| 693 static final int DO_WHILE_LOOP = 2; |
| 694 static final int FOR_IN_LOOP = 3; |
| 695 |
| 696 final int type; |
| 697 final HBasicBlock header; |
| 698 final List<HBasicBlock> blocks; |
| 699 final List<HBasicBlock> backEdges; |
| 700 final List<LabelElement> labels; |
| 701 final TargetElement target; |
| 702 SubGraph initializer = null; |
| 703 SubExpression condition = null; |
| 704 SubGraph body = null; |
| 705 SubGraph updates = null; |
| 706 HBasicBlock joinBlock; |
| 707 |
| 708 HLoopInformation(this.type, this.header, this.target, this.labels) |
| 709 : blocks = new List<HBasicBlock>(), |
| 710 backEdges = new List<HBasicBlock>(); |
| 711 |
| 712 static int loopType(Node node) { |
| 713 return node.accept(const LoopTypeVisitor()); |
| 714 } |
| 715 |
| 716 void addBackEdge(HBasicBlock predecessor) { |
| 717 backEdges.add(predecessor); |
| 718 addBlock(predecessor); |
| 719 } |
| 720 |
| 721 // Adds a block and transitively all its predecessors in the loop as |
| 722 // loop blocks. |
| 723 void addBlock(HBasicBlock block) { |
| 724 if (block === header) return; |
| 725 HBasicBlock parentHeader = block.parentLoopHeader; |
| 726 if (parentHeader === header) { |
| 727 // Nothing to do in this case. |
| 728 } else if (parentHeader !== null) { |
| 729 addBlock(parentHeader); |
| 730 } else { |
| 731 block.parentLoopHeader = header; |
| 732 blocks.add(block); |
| 733 for (int i = 0, length = block.predecessors.length; i < length; i++) { |
| 734 addBlock(block.predecessors[i]); |
| 735 } |
| 736 } |
| 737 } |
| 738 |
| 739 HBasicBlock getLastBackEdge() { |
| 740 int maxId = -1; |
| 741 HBasicBlock result = null; |
| 742 for (int i = 0, length = backEdges.length; i < length; i++) { |
| 743 HBasicBlock current = backEdges[i]; |
| 744 if (current.id > maxId) { |
| 745 maxId = current.id; |
| 746 result = current; |
| 747 } |
| 748 } |
| 749 return result; |
| 750 } |
| 751 } |
| 659 | 752 |
| 660 class HType { | 753 class HType { |
| 661 final int flag; | 754 final int flag; |
| 662 const HType(int this.flag); | 755 const HType(int this.flag); |
| 663 | 756 |
| 664 static final int FLAG_CONFLICTING = 0; | 757 static final int FLAG_CONFLICTING = 0; |
| 665 static final int FLAG_UNKNOWN = 1; | 758 static final int FLAG_UNKNOWN = 1; |
| 666 static final int FLAG_BOOLEAN = FLAG_UNKNOWN << 1; | 759 static final int FLAG_BOOLEAN = FLAG_UNKNOWN << 1; |
| 667 static final int FLAG_INTEGER = FLAG_BOOLEAN << 1; | 760 static final int FLAG_INTEGER = FLAG_BOOLEAN << 1; |
| 668 static final int FLAG_STRING = FLAG_INTEGER << 1; | 761 static final int FLAG_STRING = FLAG_INTEGER << 1; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 * | 902 * |
| 810 * Note that the [propagatedType] may only be set to [HType.CONFLICTING] with | 903 * Note that the [propagatedType] may only be set to [HType.CONFLICTING] with |
| 811 * speculative types (as otherwise the instruction either sets the output | 904 * speculative types (as otherwise the instruction either sets the output |
| 812 * type to [HType.UNKNOWN] or a specific type. | 905 * type to [HType.UNKNOWN] or a specific type. |
| 813 */ | 906 */ |
| 814 HType propagatedType = HType.UNKNOWN; | 907 HType propagatedType = HType.UNKNOWN; |
| 815 | 908 |
| 816 /** | 909 /** |
| 817 * Some instructions have a good idea of their return type, but cannot | 910 * Some instructions have a good idea of their return type, but cannot |
| 818 * guarantee the type. The [likelyType] does not need to be more specialized | 911 * guarantee the type. The [likelyType] does not need to be more specialized |
| 819 * than the [propagatedType]. | 912 * than the [propagatedType]. |
| 820 * | 913 * |
| 821 * Examples: the [likelyType] of [:x == y:] is a boolean. In most cases this | 914 * Examples: the [likelyType] of [:x == y:] is a boolean. In most cases this |
| 822 * cannot be guaranteed, but when merging types we still want to use this | 915 * cannot be guaranteed, but when merging types we still want to use this |
| 823 * information. | 916 * information. |
| 824 * | 917 * |
| 825 * Similarily the [HAdd] instruction is likely a number. Note that, even if | 918 * Similarily the [HAdd] instruction is likely a number. Note that, even if |
| 826 * the [propagatedType] is already set to integer, the [likelyType] still | 919 * the [propagatedType] is already set to integer, the [likelyType] still |
| 827 * might just return the number type. | 920 * might just return the number type. |
| 828 */ | 921 */ |
| 829 HType get likelyType() => propagatedType; | 922 HType get likelyType() => propagatedType; |
| 830 | 923 |
| 831 /** | 924 /** |
| 832 * Compute the type of the instruction by propagating the input types through | 925 * Compute the type of the instruction by propagating the input types through |
| 833 * the instruction. | 926 * the instruction. |
| 834 * | 927 * |
| 835 * By default just copy the guaranteed type. | 928 * By default just copy the guaranteed type. |
| 836 */ | 929 */ |
| 837 HType computeTypeFromInputTypes() => guaranteedType; | 930 HType computeTypeFromInputTypes() => guaranteedType; |
| 838 | 931 |
| (...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1907 | 2000 |
| 1908 HType computeDesiredTypeForNonTargetInput(HInstruction input) { | 2001 HType computeDesiredTypeForNonTargetInput(HInstruction input) { |
| 1909 if (input == left && right.propagatedType.isUseful()) { | 2002 if (input == left && right.propagatedType.isUseful()) { |
| 1910 // All our useful types have === semantics. But we don't want to | 2003 // All our useful types have === semantics. But we don't want to |
| 1911 // speculatively test for all possible types. Therefore we try to match | 2004 // speculatively test for all possible types. Therefore we try to match |
| 1912 // the two types. That is, if we see x == 3, then we speculatively test | 2005 // the two types. That is, if we see x == 3, then we speculatively test |
| 1913 // if x is a number and bailout if it isn't. | 2006 // if x is a number and bailout if it isn't. |
| 1914 if (right.isNumber()) return HType.NUMBER; // No need to be more precise. | 2007 if (right.isNumber()) return HType.NUMBER; // No need to be more precise. |
| 1915 // String equality testing is much more common than array equality | 2008 // String equality testing is much more common than array equality |
| 1916 // testing. | 2009 // testing. |
| 1917 if (right.isStringOrArray()) return HType.STRING; | 2010 if (right.isStringOrArray()) return HType.STRING; |
| 1918 return right.propagatedType; | 2011 return right.propagatedType; |
| 1919 } | 2012 } |
| 1920 // String equality testing is much more common than array equality testing. | 2013 // String equality testing is much more common than array equality testing. |
| 1921 if (input == left && left.isStringOrArray()) { | 2014 if (input == left && left.isStringOrArray()) { |
| 1922 return HType.READABLE_ARRAY; | 2015 return HType.READABLE_ARRAY; |
| 1923 } | 2016 } |
| 1924 // String equality testing is much more common than array equality testing. | 2017 // String equality testing is much more common than array equality testing. |
| 1925 if (input == right && right.isStringOrArray()) { | 2018 if (input == right && right.isStringOrArray()) { |
| 1926 return HType.STRING; | 2019 return HType.STRING; |
| 1927 } | 2020 } |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2123 | 2216 |
| 2124 HInstruction get expression() => inputs[0]; | 2217 HInstruction get expression() => inputs[0]; |
| 2125 | 2218 |
| 2126 HType get guaranteedType() => HType.BOOLEAN; | 2219 HType get guaranteedType() => HType.BOOLEAN; |
| 2127 | 2220 |
| 2128 accept(HVisitor visitor) => visitor.visitIs(this); | 2221 accept(HVisitor visitor) => visitor.visitIs(this); |
| 2129 | 2222 |
| 2130 toString() => "$expression is $typeName"; | 2223 toString() => "$expression is $typeName"; |
| 2131 } | 2224 } |
| 2132 | 2225 |
| 2133 | 2226 class HIfBlockInformation { |
| 2134 interface HBlockInformation { | 2227 final HIf branch; |
| 2135 bool accept(HBlockInformationVisitor visitor); | |
| 2136 } | |
| 2137 | |
| 2138 interface HBlockInformationVisitor { | |
| 2139 bool visitLabeledBlockInfo(HLabeledBlockInformation info); | |
| 2140 bool visitLoopInfo(HLoopInformation info); | |
| 2141 bool visitIfInfo(HIfBlockInformation info); | |
| 2142 bool visitAndOrInfo(HAndOrBlockInformation info); | |
| 2143 } | |
| 2144 | |
| 2145 class HLabeledBlockInformation implements HBlockInformation { | |
| 2146 final SubGraph body; | |
| 2147 final HBasicBlock joinBlock; | |
| 2148 final List<LabelElement> labels; | |
| 2149 final TargetElement target; | |
| 2150 final bool isContinue; | |
| 2151 | |
| 2152 HLabeledBlockInformation(this.body, this.joinBlock, | |
| 2153 List<LabelElement> labels, | |
| 2154 [this.isContinue = false]) : | |
| 2155 this.labels = labels, this.target = labels[0].target; | |
| 2156 | |
| 2157 HLabeledBlockInformation.implicit(this.body, | |
| 2158 this.joinBlock, | |
| 2159 this.target, | |
| 2160 [this.isContinue = false]) | |
| 2161 : this.labels = const<LabelElement>[]; | |
| 2162 | |
| 2163 bool accept(HBlockInformationVisitor visitor) => | |
| 2164 visitor.visitLabeledBlockInfo(this); | |
| 2165 } | |
| 2166 | |
| 2167 class LoopTypeVisitor extends AbstractVisitor { | |
| 2168 const LoopTypeVisitor(); | |
| 2169 int visitNode(Node node) { | |
| 2170 unreachable(); | |
| 2171 } | |
| 2172 int visitWhile(While node) => HLoopInformation.WHILE_LOOP; | |
| 2173 int visitFor(For node) => HLoopInformation.FOR_LOOP; | |
| 2174 int visitDoWhile(DoWhile node) => HLoopInformation.DO_WHILE_LOOP; | |
| 2175 int visitForIn(ForIn node) => HLoopInformation.FOR_IN_LOOP; | |
| 2176 } | |
| 2177 | |
| 2178 class HLoopInformation implements HBlockInformation { | |
| 2179 static final int WHILE_LOOP = 0; | |
| 2180 static final int FOR_LOOP = 1; | |
| 2181 static final int DO_WHILE_LOOP = 2; | |
| 2182 static final int FOR_IN_LOOP = 3; | |
| 2183 | |
| 2184 final int kind; | |
| 2185 final HBasicBlock header; | |
| 2186 final List<HBasicBlock> blocks; | |
| 2187 final List<HBasicBlock> backEdges; | |
| 2188 final List<LabelElement> labels; | |
| 2189 final TargetElement target; | |
| 2190 SubGraph initializer = null; | |
| 2191 SubExpression condition = null; | |
| 2192 SubGraph body = null; | |
| 2193 SubGraph updates = null; | |
| 2194 HBasicBlock joinBlock; | |
| 2195 | |
| 2196 HLoopInformation(this.kind, this.header, this.target, this.labels) | |
| 2197 : blocks = new List<HBasicBlock>(), | |
| 2198 backEdges = new List<HBasicBlock>(); | |
| 2199 | |
| 2200 static int loopType(Node node) { | |
| 2201 return node.accept(const LoopTypeVisitor()); | |
| 2202 } | |
| 2203 | |
| 2204 void addBackEdge(HBasicBlock predecessor) { | |
| 2205 backEdges.add(predecessor); | |
| 2206 addBlock(predecessor); | |
| 2207 } | |
| 2208 | |
| 2209 // Adds a block and transitively all its predecessors in the loop as | |
| 2210 // loop blocks. | |
| 2211 void addBlock(HBasicBlock block) { | |
| 2212 if (block === header) return; | |
| 2213 HBasicBlock parentHeader = block.parentLoopHeader; | |
| 2214 if (parentHeader === header) { | |
| 2215 // Nothing to do in this case. | |
| 2216 } else if (parentHeader !== null) { | |
| 2217 addBlock(parentHeader); | |
| 2218 } else { | |
| 2219 block.parentLoopHeader = header; | |
| 2220 blocks.add(block); | |
| 2221 for (int i = 0, length = block.predecessors.length; i < length; i++) { | |
| 2222 addBlock(block.predecessors[i]); | |
| 2223 } | |
| 2224 } | |
| 2225 } | |
| 2226 | |
| 2227 HBasicBlock getLastBackEdge() { | |
| 2228 int maxId = -1; | |
| 2229 HBasicBlock result = null; | |
| 2230 for (int i = 0, length = backEdges.length; i < length; i++) { | |
| 2231 HBasicBlock current = backEdges[i]; | |
| 2232 if (current.id > maxId) { | |
| 2233 maxId = current.id; | |
| 2234 result = current; | |
| 2235 } | |
| 2236 } | |
| 2237 return result; | |
| 2238 } | |
| 2239 | |
| 2240 bool accept(HBlockInformationVisitor visitor) => visitor.visitLoopInfo(this); | |
| 2241 } | |
| 2242 | |
| 2243 class HIfBlockInformation implements HBlockInformation { | |
| 2244 final SubExpression condition; | |
| 2245 final SubGraph thenGraph; | 2228 final SubGraph thenGraph; |
| 2246 final SubGraph elseGraph; | 2229 final SubGraph elseGraph; |
| 2247 final HBasicBlock joinBlock; | 2230 final HBasicBlock joinBlock; |
| 2248 HIfBlockInformation(this.condition, | 2231 HIfBlockInformation(this.branch, |
| 2249 this.thenGraph, | 2232 this.thenGraph, |
| 2250 this.elseGraph, | 2233 this.elseGraph, |
| 2251 this.joinBlock); | 2234 this.joinBlock); |
| 2252 bool accept(HBlockInformationVisitor visitor) => visitor.visitIfInfo(this); | |
| 2253 } | 2235 } |
| 2254 | |
| 2255 class HAndOrBlockInformation implements HBlockInformation { | |
| 2256 final bool isAnd; | |
| 2257 final SubExpression left; | |
| 2258 final SubExpression right; | |
| 2259 final HBasicBlock joinBlock; | |
| 2260 HAndOrBlockInformation(this.isAnd, | |
| 2261 this.left, | |
| 2262 this.right, | |
| 2263 this.joinBlock); | |
| 2264 bool accept(HBlockInformationVisitor visitor) => visitor.visitAndOrInfo(this); | |
| 2265 } | |
| OLD | NEW |