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 |