| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 abstract class HVisitor<R> { | 7 abstract class HVisitor<R> { |
| 8 R visitAdd(HAdd node); | 8 R visitAdd(HAdd node); |
| 9 R visitBitAnd(HBitAnd node); | 9 R visitBitAnd(HBitAnd node); |
| 10 R visitBitNot(HBitNot node); | 10 R visitBitNot(HBitNot node); |
| (...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 : id = idCounter++, usedBy = <HInstruction>[] { | 788 : id = idCounter++, usedBy = <HInstruction>[] { |
| 789 assert(inputs.every((e) => e != null)); | 789 assert(inputs.every((e) => e != null)); |
| 790 } | 790 } |
| 791 | 791 |
| 792 int get hashCode => id; | 792 int get hashCode => id; |
| 793 | 793 |
| 794 bool useGvn() => _useGvn; | 794 bool useGvn() => _useGvn; |
| 795 void setUseGvn() { _useGvn = true; } | 795 void setUseGvn() { _useGvn = true; } |
| 796 void clearUseGvn() { _useGvn = false; } | 796 void clearUseGvn() { _useGvn = false; } |
| 797 | 797 |
| 798 void updateInput(int i, HInstruction insn) { | |
| 799 assert(insn != null); | |
| 800 inputs[i] = insn; | |
| 801 } | |
| 802 | |
| 803 /** | 798 /** |
| 804 * A pure instruction is an instruction that does not have any side | 799 * A pure instruction is an instruction that does not have any side |
| 805 * effect, nor any dependency. They can be moved anywhere in the | 800 * effect, nor any dependency. They can be moved anywhere in the |
| 806 * graph. | 801 * graph. |
| 807 */ | 802 */ |
| 808 bool isPure() { | 803 bool isPure() { |
| 809 return !sideEffects.hasSideEffects() | 804 return !sideEffects.hasSideEffects() |
| 810 && !sideEffects.dependsOnSomething() | 805 && !sideEffects.dependsOnSomething() |
| 811 && !canThrow(); | 806 && !canThrow(); |
| 812 } | 807 } |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 974 * Type of the unstruction. | 969 * Type of the unstruction. |
| 975 */ | 970 */ |
| 976 TypeMask instructionType; | 971 TypeMask instructionType; |
| 977 | 972 |
| 978 Selector get selector => null; | 973 Selector get selector => null; |
| 979 HInstruction getDartReceiver(Compiler compiler) => null; | 974 HInstruction getDartReceiver(Compiler compiler) => null; |
| 980 bool onlyThrowsNSM() => false; | 975 bool onlyThrowsNSM() => false; |
| 981 | 976 |
| 982 bool isInBasicBlock() => block != null; | 977 bool isInBasicBlock() => block != null; |
| 983 | 978 |
| 984 String inputsToString() { | |
| 985 void addAsCommaSeparated(StringBuffer buffer, List<HInstruction> list) { | |
| 986 for (int i = 0; i < list.length; i++) { | |
| 987 if (i != 0) buffer.write(', '); | |
| 988 buffer.write("@${list[i].id}"); | |
| 989 } | |
| 990 } | |
| 991 | |
| 992 StringBuffer buffer = new StringBuffer(); | |
| 993 buffer.write('('); | |
| 994 addAsCommaSeparated(buffer, inputs); | |
| 995 buffer.write(') - used at ['); | |
| 996 addAsCommaSeparated(buffer, usedBy); | |
| 997 buffer.write(']'); | |
| 998 return buffer.toString(); | |
| 999 } | |
| 1000 | |
| 1001 bool gvnEquals(HInstruction other) { | 979 bool gvnEquals(HInstruction other) { |
| 1002 assert(useGvn() && other.useGvn()); | 980 assert(useGvn() && other.useGvn()); |
| 1003 // Check that the type and the sideEffects match. | 981 // Check that the type and the sideEffects match. |
| 1004 bool hasSameType = typeEquals(other); | 982 bool hasSameType = typeEquals(other); |
| 1005 assert(hasSameType == (typeCode() == other.typeCode())); | 983 assert(hasSameType == (typeCode() == other.typeCode())); |
| 1006 if (!hasSameType) return false; | 984 if (!hasSameType) return false; |
| 1007 if (sideEffects != other.sideEffects) return false; | 985 if (sideEffects != other.sideEffects) return false; |
| 1008 // Check that the inputs match. | 986 // Check that the inputs match. |
| 1009 final int inputsLength = inputs.length; | 987 final int inputsLength = inputs.length; |
| 1010 final List<HInstruction> otherInputs = other.inputs; | 988 final List<HInstruction> otherInputs = other.inputs; |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 | 1357 |
| 1380 class HInvokeDynamicMethod extends HInvokeDynamic { | 1358 class HInvokeDynamicMethod extends HInvokeDynamic { |
| 1381 HInvokeDynamicMethod(Selector selector, | 1359 HInvokeDynamicMethod(Selector selector, |
| 1382 List<HInstruction> inputs, | 1360 List<HInstruction> inputs, |
| 1383 TypeMask type, | 1361 TypeMask type, |
| 1384 [bool isIntercepted = false]) | 1362 [bool isIntercepted = false]) |
| 1385 : super(selector, null, inputs, type, isIntercepted); | 1363 : super(selector, null, inputs, type, isIntercepted); |
| 1386 | 1364 |
| 1387 String toString() => 'invoke dynamic method: $selector'; | 1365 String toString() => 'invoke dynamic method: $selector'; |
| 1388 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 1366 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); |
| 1389 | |
| 1390 bool isIndexOperatorOnIndexablePrimitive(Compiler compiler) { | |
| 1391 return isInterceptedCall | |
| 1392 && selector.kind == SelectorKind.INDEX | |
| 1393 && selector.name == '[]' | |
| 1394 && inputs[1].isIndexablePrimitive(compiler); | |
| 1395 } | |
| 1396 } | 1367 } |
| 1397 | 1368 |
| 1398 abstract class HInvokeDynamicField extends HInvokeDynamic { | 1369 abstract class HInvokeDynamicField extends HInvokeDynamic { |
| 1399 HInvokeDynamicField( | 1370 HInvokeDynamicField( |
| 1400 Selector selector, Element element, List<HInstruction> inputs, | 1371 Selector selector, Element element, List<HInstruction> inputs, |
| 1401 TypeMask type) | 1372 TypeMask type) |
| 1402 : super(selector, element, inputs, type); | 1373 : super(selector, element, inputs, type); |
| 1403 toString() => 'invoke dynamic field: $selector'; | 1374 toString() => 'invoke dynamic field: $selector'; |
| 1404 } | 1375 } |
| 1405 | 1376 |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1897 | 1868 |
| 1898 class HLoopBranch extends HConditionalBranch { | 1869 class HLoopBranch extends HConditionalBranch { |
| 1899 static const int CONDITION_FIRST_LOOP = 0; | 1870 static const int CONDITION_FIRST_LOOP = 0; |
| 1900 static const int DO_WHILE_LOOP = 1; | 1871 static const int DO_WHILE_LOOP = 1; |
| 1901 | 1872 |
| 1902 final int kind; | 1873 final int kind; |
| 1903 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP]) | 1874 HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP]) |
| 1904 : super(<HInstruction>[condition]); | 1875 : super(<HInstruction>[condition]); |
| 1905 toString() => 'loop-branch'; | 1876 toString() => 'loop-branch'; |
| 1906 accept(HVisitor visitor) => visitor.visitLoopBranch(this); | 1877 accept(HVisitor visitor) => visitor.visitLoopBranch(this); |
| 1907 | |
| 1908 bool isDoWhile() { | |
| 1909 return identical(kind, DO_WHILE_LOOP); | |
| 1910 } | |
| 1911 | |
| 1912 HBasicBlock computeLoopHeader() { | |
| 1913 HBasicBlock result; | |
| 1914 if (isDoWhile()) { | |
| 1915 // In case of a do/while, the successor is a block that avoids | |
| 1916 // a critical edge and branchs to the loop header. | |
| 1917 result = block.successors[0].successors[0]; | |
| 1918 } else { | |
| 1919 // For other loops, the loop header might be up the dominator | |
| 1920 // tree if the loop condition has control flow. | |
| 1921 result = block; | |
| 1922 while (!result.isLoopHeader()) result = result.dominator; | |
| 1923 } | |
| 1924 | |
| 1925 assert(result.isLoopHeader()); | |
| 1926 return result; | |
| 1927 } | |
| 1928 } | 1878 } |
| 1929 | 1879 |
| 1930 class HConstant extends HInstruction { | 1880 class HConstant extends HInstruction { |
| 1931 final Constant constant; | 1881 final Constant constant; |
| 1932 HConstant.internal(this.constant, TypeMask constantType) | 1882 HConstant.internal(this.constant, TypeMask constantType) |
| 1933 : super(<HInstruction>[], constantType); | 1883 : super(<HInstruction>[], constantType); |
| 1934 | 1884 |
| 1935 toString() => 'literal: $constant'; | 1885 toString() => 'literal: $constant'; |
| 1936 accept(HVisitor visitor) => visitor.visitConstant(this); | 1886 accept(HVisitor visitor) => visitor.visitConstant(this); |
| 1937 | 1887 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2017 HPhi.manyInputs(Element element, List<HInstruction> inputs, TypeMask type) | 1967 HPhi.manyInputs(Element element, List<HInstruction> inputs, TypeMask type) |
| 2018 : this(element, inputs, type); | 1968 : this(element, inputs, type); |
| 2019 | 1969 |
| 2020 void addInput(HInstruction input) { | 1970 void addInput(HInstruction input) { |
| 2021 assert(isInBasicBlock()); | 1971 assert(isInBasicBlock()); |
| 2022 inputs.add(input); | 1972 inputs.add(input); |
| 2023 assert(inputs.length <= block.predecessors.length); | 1973 assert(inputs.length <= block.predecessors.length); |
| 2024 input.usedBy.add(this); | 1974 input.usedBy.add(this); |
| 2025 } | 1975 } |
| 2026 | 1976 |
| 2027 bool isLogicalOperator() => logicalOperatorType != IS_NOT_LOGICAL_OPERATOR; | |
| 2028 | |
| 2029 String logicalOperator() { | |
| 2030 assert(isLogicalOperator()); | |
| 2031 if (logicalOperatorType == IS_AND) return "&&"; | |
| 2032 assert(logicalOperatorType == IS_OR); | |
| 2033 return "||"; | |
| 2034 } | |
| 2035 | |
| 2036 toString() => 'phi'; | 1977 toString() => 'phi'; |
| 2037 accept(HVisitor visitor) => visitor.visitPhi(this); | 1978 accept(HVisitor visitor) => visitor.visitPhi(this); |
| 2038 } | 1979 } |
| 2039 | 1980 |
| 2040 abstract class HRelational extends HInvokeBinary { | 1981 abstract class HRelational extends HInvokeBinary { |
| 2041 bool usesBoolifiedInterceptor = false; | 1982 bool usesBoolifiedInterceptor = false; |
| 2042 HRelational(left, right, selector, type) : super(left, right, selector, type); | 1983 HRelational(left, right, selector, type) : super(left, right, selector, type); |
| 2043 } | 1984 } |
| 2044 | 1985 |
| 2045 class HIdentity extends HRelational { | 1986 class HIdentity extends HRelational { |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2543 if (identical(parentHeader, header)) { | 2484 if (identical(parentHeader, header)) { |
| 2544 // Nothing to do in this case. | 2485 // Nothing to do in this case. |
| 2545 } else if (parentHeader != null) { | 2486 } else if (parentHeader != null) { |
| 2546 workQueue.add(parentHeader); | 2487 workQueue.add(parentHeader); |
| 2547 } else { | 2488 } else { |
| 2548 block.parentLoopHeader = header; | 2489 block.parentLoopHeader = header; |
| 2549 blocks.add(block); | 2490 blocks.add(block); |
| 2550 workQueue.addAll(block.predecessors); | 2491 workQueue.addAll(block.predecessors); |
| 2551 } | 2492 } |
| 2552 } | 2493 } |
| 2553 | |
| 2554 HBasicBlock getLastBackEdge() { | |
| 2555 int maxId = -1; | |
| 2556 HBasicBlock result = null; | |
| 2557 for (int i = 0, length = backEdges.length; i < length; i++) { | |
| 2558 HBasicBlock current = backEdges[i]; | |
| 2559 if (current.id > maxId) { | |
| 2560 maxId = current.id; | |
| 2561 result = current; | |
| 2562 } | |
| 2563 } | |
| 2564 return result; | |
| 2565 } | |
| 2566 } | 2494 } |
| 2567 | 2495 |
| 2568 | 2496 |
| 2569 /** | 2497 /** |
| 2570 * Embedding of a [HBlockInformation] for block-structure based traversal | 2498 * Embedding of a [HBlockInformation] for block-structure based traversal |
| 2571 * in a dominator based flow traversal by attaching it to a basic block. | 2499 * in a dominator based flow traversal by attaching it to a basic block. |
| 2572 * To go back to dominator-based traversal, a [HSubGraphBlockInformation] | 2500 * To go back to dominator-based traversal, a [HSubGraphBlockInformation] |
| 2573 * structure can be added in the block structure. | 2501 * structure can be added in the block structure. |
| 2574 */ | 2502 */ |
| 2575 class HBlockFlow { | 2503 class HBlockFlow { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2638 final SubGraph subGraph; | 2566 final SubGraph subGraph; |
| 2639 HSubGraphBlockInformation(this.subGraph); | 2567 HSubGraphBlockInformation(this.subGraph); |
| 2640 | 2568 |
| 2641 HBasicBlock get start => subGraph.start; | 2569 HBasicBlock get start => subGraph.start; |
| 2642 HBasicBlock get end => subGraph.end; | 2570 HBasicBlock get end => subGraph.end; |
| 2643 | 2571 |
| 2644 bool accept(HStatementInformationVisitor visitor) => | 2572 bool accept(HStatementInformationVisitor visitor) => |
| 2645 visitor.visitSubGraphInfo(this); | 2573 visitor.visitSubGraphInfo(this); |
| 2646 } | 2574 } |
| 2647 | 2575 |
| 2648 | |
| 2649 /** | 2576 /** |
| 2650 * Generic class wrapping a [SubExpression] as a block-information until | 2577 * Generic class wrapping a [SubExpression] as a block-information until |
| 2651 * expressions structures are handled properly. | 2578 * expressions structures are handled properly. |
| 2652 */ | 2579 */ |
| 2653 class HSubExpressionBlockInformation implements HExpressionInformation { | 2580 class HSubExpressionBlockInformation implements HExpressionInformation { |
| 2654 final SubExpression subExpression; | 2581 final SubExpression subExpression; |
| 2655 HSubExpressionBlockInformation(this.subExpression); | 2582 HSubExpressionBlockInformation(this.subExpression); |
| 2656 | 2583 |
| 2657 HBasicBlock get start => subExpression.start; | 2584 HBasicBlock get start => subExpression.start; |
| 2658 HBasicBlock get end => subExpression.end; | 2585 HBasicBlock get end => subExpression.end; |
| 2659 | 2586 |
| 2660 HInstruction get conditionExpression => subExpression.conditionExpression; | 2587 HInstruction get conditionExpression => subExpression.conditionExpression; |
| 2661 | 2588 |
| 2662 bool accept(HExpressionInformationVisitor visitor) => | 2589 bool accept(HExpressionInformationVisitor visitor) => |
| 2663 visitor.visitSubExpressionInfo(this); | 2590 visitor.visitSubExpressionInfo(this); |
| 2664 } | 2591 } |
| 2665 | 2592 |
| 2666 | |
| 2667 /** A sequence of separate statements. */ | 2593 /** A sequence of separate statements. */ |
| 2668 class HStatementSequenceInformation implements HStatementInformation { | 2594 class HStatementSequenceInformation implements HStatementInformation { |
| 2669 final List<HStatementInformation> statements; | 2595 final List<HStatementInformation> statements; |
| 2670 HStatementSequenceInformation(this.statements); | 2596 HStatementSequenceInformation(this.statements); |
| 2671 | 2597 |
| 2672 HBasicBlock get start => statements[0].start; | 2598 HBasicBlock get start => statements[0].start; |
| 2673 HBasicBlock get end => statements.last.end; | 2599 HBasicBlock get end => statements.last.end; |
| 2674 | 2600 |
| 2675 bool accept(HStatementInformationVisitor visitor) => | 2601 bool accept(HStatementInformationVisitor visitor) => |
| 2676 visitor.visitSequenceInfo(this); | 2602 visitor.visitSequenceInfo(this); |
| 2677 } | 2603 } |
| 2678 | 2604 |
| 2679 | |
| 2680 class HLabeledBlockInformation implements HStatementInformation { | 2605 class HLabeledBlockInformation implements HStatementInformation { |
| 2681 final HStatementInformation body; | 2606 final HStatementInformation body; |
| 2682 final List<LabelElement> labels; | 2607 final List<LabelElement> labels; |
| 2683 final TargetElement target; | 2608 final TargetElement target; |
| 2684 final bool isContinue; | 2609 final bool isContinue; |
| 2685 | 2610 |
| 2686 HLabeledBlockInformation(this.body, | 2611 HLabeledBlockInformation(this.body, |
| 2687 List<LabelElement> labels, | 2612 List<LabelElement> labels, |
| 2688 {this.isContinue: false}) : | 2613 {this.isContinue: false}) : |
| 2689 this.labels = labels, this.target = labels[0].target; | 2614 this.labels = labels, this.target = labels[0].target; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2759 if (kind == DO_WHILE_LOOP && condition != null) { | 2684 if (kind == DO_WHILE_LOOP && condition != null) { |
| 2760 return condition.end; | 2685 return condition.end; |
| 2761 } | 2686 } |
| 2762 return body.end; | 2687 return body.end; |
| 2763 } | 2688 } |
| 2764 | 2689 |
| 2765 static int loopType(Node node) { | 2690 static int loopType(Node node) { |
| 2766 return node.accept(const LoopTypeVisitor()); | 2691 return node.accept(const LoopTypeVisitor()); |
| 2767 } | 2692 } |
| 2768 | 2693 |
| 2769 bool isDoWhile() => kind == DO_WHILE_LOOP; | |
| 2770 | |
| 2771 bool accept(HStatementInformationVisitor visitor) => | 2694 bool accept(HStatementInformationVisitor visitor) => |
| 2772 visitor.visitLoopInfo(this); | 2695 visitor.visitLoopInfo(this); |
| 2773 } | 2696 } |
| 2774 | 2697 |
| 2775 class HIfBlockInformation implements HStatementInformation { | 2698 class HIfBlockInformation implements HStatementInformation { |
| 2776 final HExpressionInformation condition; | 2699 final HExpressionInformation condition; |
| 2777 final HStatementInformation thenGraph; | 2700 final HStatementInformation thenGraph; |
| 2778 final HStatementInformation elseGraph; | 2701 final HStatementInformation elseGraph; |
| 2779 HIfBlockInformation(this.condition, | 2702 HIfBlockInformation(this.condition, |
| 2780 this.thenGraph, | 2703 this.thenGraph, |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2840 HBasicBlock get start => expression.start; | 2763 HBasicBlock get start => expression.start; |
| 2841 HBasicBlock get end { | 2764 HBasicBlock get end { |
| 2842 // We don't create a switch block if there are no cases. | 2765 // We don't create a switch block if there are no cases. |
| 2843 assert(!statements.isEmpty); | 2766 assert(!statements.isEmpty); |
| 2844 return statements.last.end; | 2767 return statements.last.end; |
| 2845 } | 2768 } |
| 2846 | 2769 |
| 2847 bool accept(HStatementInformationVisitor visitor) => | 2770 bool accept(HStatementInformationVisitor visitor) => |
| 2848 visitor.visitSwitchInfo(this); | 2771 visitor.visitSwitchInfo(this); |
| 2849 } | 2772 } |
| OLD | NEW |