| 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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 return result; | 147 return result; |
| 148 } | 148 } |
| 149 | 149 |
| 150 static HType mapConstantTypeToSsaType(Constant constant) { | 150 static HType mapConstantTypeToSsaType(Constant constant) { |
| 151 if (constant.isNull()) return HType.UNKNOWN; | 151 if (constant.isNull()) return HType.UNKNOWN; |
| 152 if (constant.isBool()) return HType.BOOLEAN; | 152 if (constant.isBool()) return HType.BOOLEAN; |
| 153 if (constant.isInt()) return HType.INTEGER; | 153 if (constant.isInt()) return HType.INTEGER; |
| 154 if (constant.isDouble()) return HType.DOUBLE; | 154 if (constant.isDouble()) return HType.DOUBLE; |
| 155 if (constant.isString()) return HType.STRING; | 155 if (constant.isString()) return HType.STRING; |
| 156 if (constant.isList()) return HType.READABLE_ARRAY; | 156 if (constant.isList()) return HType.READABLE_ARRAY; |
| 157 if (constant.isMap()) { |
| 158 MapConstant map = constant; |
| 159 return new HNonPrimitiveType(map.type); |
| 160 } |
| 157 return HType.UNKNOWN; | 161 return HType.UNKNOWN; |
| 158 } | 162 } |
| 159 | 163 |
| 160 HConstant addConstant(Constant constant) { | 164 HConstant addConstant(Constant constant) { |
| 161 HConstant result = constants[constant]; | 165 HConstant result = constants[constant]; |
| 162 if (result === null) { | 166 if (result === null) { |
| 163 HType type = mapConstantTypeToSsaType(constant); | 167 HType type = mapConstantTypeToSsaType(constant); |
| 164 result = new HConstant.internal(constant, type); | 168 result = new HConstant.internal(constant, type); |
| 165 entry.addAtExit(result); | 169 entry.addAtExit(result); |
| 166 constants[constant] = result; | 170 constants[constant] = result; |
| (...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 | 667 |
| 664 static final int FLAG_CONFLICTING = 0; | 668 static final int FLAG_CONFLICTING = 0; |
| 665 static final int FLAG_UNKNOWN = 1; | 669 static final int FLAG_UNKNOWN = 1; |
| 666 static final int FLAG_BOOLEAN = FLAG_UNKNOWN << 1; | 670 static final int FLAG_BOOLEAN = FLAG_UNKNOWN << 1; |
| 667 static final int FLAG_INTEGER = FLAG_BOOLEAN << 1; | 671 static final int FLAG_INTEGER = FLAG_BOOLEAN << 1; |
| 668 static final int FLAG_STRING = FLAG_INTEGER << 1; | 672 static final int FLAG_STRING = FLAG_INTEGER << 1; |
| 669 static final int FLAG_READABLE_ARRAY = FLAG_STRING << 1; | 673 static final int FLAG_READABLE_ARRAY = FLAG_STRING << 1; |
| 670 // FLAG_WRITABLE_ARRAY implies FLAG_READABLE_ARRAY. | 674 // FLAG_WRITABLE_ARRAY implies FLAG_READABLE_ARRAY. |
| 671 static final int FLAG_WRITEABLE_ARRAY = FLAG_READABLE_ARRAY << 1; | 675 static final int FLAG_WRITEABLE_ARRAY = FLAG_READABLE_ARRAY << 1; |
| 672 static final int FLAG_DOUBLE = FLAG_WRITEABLE_ARRAY << 1; | 676 static final int FLAG_DOUBLE = FLAG_WRITEABLE_ARRAY << 1; |
| 677 static final int FLAG_NON_PRIMITIVE = FLAG_DOUBLE << 1; |
| 673 | 678 |
| 674 static final HType CONFLICTING = const HType(FLAG_CONFLICTING); | 679 static final HType CONFLICTING = const HType(FLAG_CONFLICTING); |
| 675 static final HType UNKNOWN = const HType(FLAG_UNKNOWN); | 680 static final HType UNKNOWN = const HType(FLAG_UNKNOWN); |
| 676 static final HType BOOLEAN = const HType(FLAG_BOOLEAN); | 681 static final HType BOOLEAN = const HType(FLAG_BOOLEAN); |
| 677 static final HType STRING = const HType(FLAG_STRING); | 682 static final HType STRING = const HType(FLAG_STRING); |
| 678 static final HType READABLE_ARRAY = const HType(FLAG_READABLE_ARRAY); | 683 static final HType READABLE_ARRAY = const HType(FLAG_READABLE_ARRAY); |
| 679 static final HType MUTABLE_ARRAY = | 684 static final HType MUTABLE_ARRAY = |
| 680 const HType(FLAG_READABLE_ARRAY | FLAG_WRITEABLE_ARRAY); | 685 const HType(FLAG_READABLE_ARRAY | FLAG_WRITEABLE_ARRAY); |
| 681 static final HType INTEGER = const HType(FLAG_INTEGER); | 686 static final HType INTEGER = const HType(FLAG_INTEGER); |
| 682 static final HType DOUBLE = const HType(FLAG_DOUBLE); | 687 static final HType DOUBLE = const HType(FLAG_DOUBLE); |
| 683 static final HType STRING_OR_ARRAY = | 688 static final HType STRING_OR_ARRAY = |
| 684 const HType(FLAG_STRING | FLAG_READABLE_ARRAY | FLAG_WRITEABLE_ARRAY); | 689 const HType(FLAG_STRING | FLAG_READABLE_ARRAY | FLAG_WRITEABLE_ARRAY); |
| 685 static final HType NUMBER = const HType(FLAG_DOUBLE | FLAG_INTEGER); | 690 static final HType NUMBER = const HType(FLAG_DOUBLE | FLAG_INTEGER); |
| 686 | 691 |
| 687 bool isConflicting() => this === CONFLICTING; | 692 bool isConflicting() => this === CONFLICTING; |
| 688 bool isUnknown() => this === UNKNOWN; | 693 bool isUnknown() => this === UNKNOWN; |
| 689 bool isBoolean() => this === BOOLEAN; | 694 bool isBoolean() => this === BOOLEAN; |
| 690 bool isInteger() => this === INTEGER; | 695 bool isInteger() => this === INTEGER; |
| 691 bool isDouble() => this === DOUBLE; | 696 bool isDouble() => this === DOUBLE; |
| 692 bool isString() => this === STRING; | 697 bool isString() => this === STRING; |
| 693 bool isArray() => (this.flag & FLAG_READABLE_ARRAY) != 0; | 698 bool isArray() => (this.flag & FLAG_READABLE_ARRAY) != 0; |
| 694 bool isMutableArray() => this === MUTABLE_ARRAY; | 699 bool isMutableArray() => this === MUTABLE_ARRAY; |
| 695 bool isNumber() => (this.flag & (FLAG_INTEGER | FLAG_DOUBLE)) != 0; | 700 bool isNumber() => (this.flag & (FLAG_INTEGER | FLAG_DOUBLE)) != 0; |
| 696 bool isStringOrArray() => | 701 bool isStringOrArray() => |
| 697 (this.flag & (FLAG_STRING | FLAG_READABLE_ARRAY)) != 0; | 702 (this.flag & (FLAG_STRING | FLAG_READABLE_ARRAY)) != 0; |
| 703 bool isNonPrimitive() => this.flag === FLAG_NON_PRIMITIVE; |
| 698 /** A type is useful it is not unknown and not conflicting. */ | 704 /** A type is useful it is not unknown and not conflicting. */ |
| 699 bool isUseful() => this !== UNKNOWN && this !== CONFLICTING; | 705 bool isUseful() => this !== UNKNOWN && this !== CONFLICTING; |
| 700 | 706 |
| 701 static HType getTypeFromFlag(int flag) { | 707 static HType getTypeFromFlag(int flag) { |
| 702 if (flag === CONFLICTING.flag) return CONFLICTING; | 708 if (flag === CONFLICTING.flag) return CONFLICTING; |
| 703 if (flag === UNKNOWN.flag) return UNKNOWN; | 709 if (flag === UNKNOWN.flag) return UNKNOWN; |
| 704 if (flag === BOOLEAN.flag) return BOOLEAN; | 710 if (flag === BOOLEAN.flag) return BOOLEAN; |
| 705 if (flag === INTEGER.flag) return INTEGER; | 711 if (flag === INTEGER.flag) return INTEGER; |
| 706 if (flag === DOUBLE.flag) return DOUBLE; | 712 if (flag === DOUBLE.flag) return DOUBLE; |
| 707 if (flag === STRING.flag) return STRING; | 713 if (flag === STRING.flag) return STRING; |
| 708 if (flag === READABLE_ARRAY.flag) return READABLE_ARRAY; | 714 if (flag === READABLE_ARRAY.flag) return READABLE_ARRAY; |
| 709 if (flag === MUTABLE_ARRAY.flag) return MUTABLE_ARRAY; | 715 if (flag === MUTABLE_ARRAY.flag) return MUTABLE_ARRAY; |
| 710 if (flag === NUMBER.flag) return NUMBER; | 716 if (flag === NUMBER.flag) return NUMBER; |
| 711 if (flag === STRING_OR_ARRAY.flag) return STRING_OR_ARRAY; | 717 if (flag === STRING_OR_ARRAY.flag) return STRING_OR_ARRAY; |
| 712 assert(false); | 718 unreachable(); |
| 713 } | 719 } |
| 714 | 720 |
| 715 String toString() { | 721 String toString() { |
| 716 if (isConflicting()) return 'conflicting'; | 722 if (isConflicting()) return 'conflicting'; |
| 717 if (isUnknown()) return 'unknown'; | 723 if (isUnknown()) return 'unknown'; |
| 718 if (isBoolean()) return 'boolean'; | 724 if (isBoolean()) return 'boolean'; |
| 719 if (isInteger()) return 'integer'; | 725 if (isInteger()) return 'integer'; |
| 720 if (isDouble()) return 'double'; | 726 if (isDouble()) return 'double'; |
| 721 if (isString()) return 'string'; | 727 if (isString()) return 'string'; |
| 722 if (isMutableArray()) return 'mutable array'; | 728 if (isMutableArray()) return 'mutable array'; |
| 723 if (isArray()) return 'array'; | 729 if (isArray()) return 'array'; |
| 724 if (isNumber()) return 'number'; | 730 if (isNumber()) return 'number'; |
| 725 if (isStringOrArray()) return 'string or array'; | 731 if (isStringOrArray()) return 'string or array'; |
| 726 unreachable(); | 732 unreachable(); |
| 727 } | 733 } |
| 728 | 734 |
| 729 HType combine(HType other) { | 735 HType combine(HType other) { |
| 730 if (isUnknown()) return other; | 736 if (isUnknown()) return other; |
| 731 if (other.isUnknown()) return this; | 737 if (other.isUnknown()) return this; |
| 732 return getTypeFromFlag(this.flag & other.flag); | 738 return getTypeFromFlag(this.flag & other.flag); |
| 733 } | 739 } |
| 734 } | 740 } |
| 735 | 741 |
| 742 class HNonPrimitiveType extends HType { |
| 743 final Type type; |
| 744 |
| 745 // TODO(ngeoffray): Add a HPrimitiveType to get rid of the flag. |
| 746 const HNonPrimitiveType(Type this.type) : super(HType.FLAG_NON_PRIMITIVE); |
| 747 |
| 748 HType combine(HType other) { |
| 749 if (other.isNonPrimitive()) { |
| 750 HNonPrimitiveType temp = other; |
| 751 if (this.type === temp.type) return this; |
| 752 } |
| 753 if (other.isUnknown()) return this; |
| 754 return CONFLICTING; |
| 755 } |
| 756 |
| 757 String toString() => type.toString(); |
| 758 Element lookupMember(SourceString name) => type.element.lookupMember(name); |
| 759 } |
| 760 |
| 736 class HInstruction implements Hashable { | 761 class HInstruction implements Hashable { |
| 737 Element sourceElement; | 762 Element sourceElement; |
| 738 | 763 |
| 739 final int id; | 764 final int id; |
| 740 static int idCounter; | 765 static int idCounter; |
| 741 | 766 |
| 742 final List<HInstruction> inputs; | 767 final List<HInstruction> inputs; |
| 743 final List<HInstruction> usedBy; | 768 final List<HInstruction> usedBy; |
| 744 | 769 |
| 745 HBasicBlock block; | 770 HBasicBlock block; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 // All isFunctions work on the propagated types. | 811 // All isFunctions work on the propagated types. |
| 787 bool isArray() => propagatedType.isArray(); | 812 bool isArray() => propagatedType.isArray(); |
| 788 bool isMutableArray() => propagatedType.isMutableArray(); | 813 bool isMutableArray() => propagatedType.isMutableArray(); |
| 789 bool isBoolean() => propagatedType.isBoolean(); | 814 bool isBoolean() => propagatedType.isBoolean(); |
| 790 bool isInteger() => propagatedType.isInteger(); | 815 bool isInteger() => propagatedType.isInteger(); |
| 791 bool isDouble() => propagatedType.isDouble(); | 816 bool isDouble() => propagatedType.isDouble(); |
| 792 bool isNumber() => propagatedType.isNumber(); | 817 bool isNumber() => propagatedType.isNumber(); |
| 793 bool isString() => propagatedType.isString(); | 818 bool isString() => propagatedType.isString(); |
| 794 bool isTypeUnknown() => propagatedType.isUnknown(); | 819 bool isTypeUnknown() => propagatedType.isUnknown(); |
| 795 bool isStringOrArray() => propagatedType.isStringOrArray(); | 820 bool isStringOrArray() => propagatedType.isStringOrArray(); |
| 821 bool isNonPrimitive() => propagatedType.isNonPrimitive(); |
| 796 | 822 |
| 797 /** | 823 /** |
| 798 * This is the type the instruction is guaranteed to have. It does not | 824 * This is the type the instruction is guaranteed to have. It does not |
| 799 * take any propagation into account. | 825 * take any propagation into account. |
| 800 */ | 826 */ |
| 801 HType get guaranteedType() => HType.UNKNOWN; | 827 HType get guaranteedType() => HType.UNKNOWN; |
| 802 bool hasGuaranteedType() => !guaranteedType.isUnknown(); | 828 bool hasGuaranteedType() => !guaranteedType.isUnknown(); |
| 803 | 829 |
| 804 /** | 830 /** |
| 805 * The [propagatedType] is the type the instruction is assumed to have. | 831 * The [propagatedType] is the type the instruction is assumed to have. |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 } | 954 } |
| 929 } | 955 } |
| 930 this.block = null; | 956 this.block = null; |
| 931 assert(isValid()); | 957 assert(isValid()); |
| 932 } | 958 } |
| 933 | 959 |
| 934 bool isConstant() => false; | 960 bool isConstant() => false; |
| 935 bool isConstantNull() => false; | 961 bool isConstantNull() => false; |
| 936 bool isConstantNumber() => false; | 962 bool isConstantNumber() => false; |
| 937 bool isConstantString() => false; | 963 bool isConstantString() => false; |
| 964 bool isConstantList() => false; |
| 965 bool isConstantMap() => false; |
| 938 | 966 |
| 939 bool isValid() { | 967 bool isValid() { |
| 940 HValidator validator = new HValidator(); | 968 HValidator validator = new HValidator(); |
| 941 validator.currentBlock = block; | 969 validator.currentBlock = block; |
| 942 validator.visitInstruction(this); | 970 validator.visitInstruction(this); |
| 943 return validator.isValid; | 971 return validator.isValid; |
| 944 } | 972 } |
| 945 | 973 |
| 946 /** | 974 /** |
| 947 * The code for computing a bailout environment, and the code | 975 * The code for computing a bailout environment, and the code |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1061 */ | 1089 */ |
| 1062 final Selector selector; | 1090 final Selector selector; |
| 1063 HInvoke(Selector this.selector, List<HInstruction> inputs) : super(inputs); | 1091 HInvoke(Selector this.selector, List<HInstruction> inputs) : super(inputs); |
| 1064 static final int ARGUMENTS_OFFSET = 1; | 1092 static final int ARGUMENTS_OFFSET = 1; |
| 1065 | 1093 |
| 1066 // TODO(floitsch): make class abstract instead of adding an abstract method. | 1094 // TODO(floitsch): make class abstract instead of adding an abstract method. |
| 1067 abstract accept(HVisitor visitor); | 1095 abstract accept(HVisitor visitor); |
| 1068 } | 1096 } |
| 1069 | 1097 |
| 1070 class HInvokeDynamic extends HInvoke { | 1098 class HInvokeDynamic extends HInvoke { |
| 1099 Element element; |
| 1071 SourceString name; | 1100 SourceString name; |
| 1072 HInvokeDynamic(Selector selector, this.name, List<HInstruction> inputs) | 1101 HInvokeDynamic( |
| 1073 : super(selector, inputs); | 1102 Selector selector, this.element, this.name, List<HInstruction> inputs) |
| 1103 : super(selector, inputs); |
| 1074 toString() => 'invoke dynamic: $name'; | 1104 toString() => 'invoke dynamic: $name'; |
| 1075 HInstruction get receiver() => inputs[0]; | 1105 HInstruction get receiver() => inputs[0]; |
| 1076 | 1106 |
| 1077 // TODO(floitsch): make class abstract instead of adding an abstract method. | 1107 // TODO(floitsch): make class abstract instead of adding an abstract method. |
| 1078 abstract accept(HVisitor visitor); | 1108 abstract accept(HVisitor visitor); |
| 1079 } | 1109 } |
| 1080 | 1110 |
| 1081 class HInvokeClosure extends HInvokeDynamic { | 1111 class HInvokeClosure extends HInvokeDynamic { |
| 1082 Element element; | |
| 1083 HInvokeClosure(Selector selector, List<HInstruction> inputs) | 1112 HInvokeClosure(Selector selector, List<HInstruction> inputs) |
| 1084 : super(selector, const SourceString('call'), inputs); | 1113 : super(selector, null, const SourceString('call'), inputs); |
| 1085 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); | 1114 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); |
| 1086 } | 1115 } |
| 1087 | 1116 |
| 1088 class HInvokeDynamicMethod extends HInvokeDynamic { | 1117 class HInvokeDynamicMethod extends HInvokeDynamic { |
| 1089 HInvokeDynamicMethod(Selector selector, | 1118 HInvokeDynamicMethod(Selector selector, |
| 1090 SourceString methodName, | 1119 SourceString methodName, |
| 1091 List<HInstruction> inputs) | 1120 List<HInstruction> inputs) |
| 1092 : super(selector, methodName, inputs); | 1121 : super(selector, null, methodName, inputs); |
| 1093 toString() => 'invoke dynamic method: $name'; | 1122 toString() => 'invoke dynamic method: $name'; |
| 1094 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 1123 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); |
| 1095 } | 1124 } |
| 1096 | 1125 |
| 1097 class HInvokeDynamicField extends HInvokeDynamic { | 1126 class HInvokeDynamicField extends HInvokeDynamic { |
| 1098 Element element; | |
| 1099 HInvokeDynamicField(Selector selector, | 1127 HInvokeDynamicField(Selector selector, |
| 1100 Element this.element, | 1128 Element element, |
| 1101 SourceString name, | 1129 SourceString name, |
| 1102 List<HInstruction>inputs) | 1130 List<HInstruction>inputs) |
| 1103 : super(selector, name, inputs); | 1131 : super(selector, element, name, inputs); |
| 1104 toString() => 'invoke dynamic field: $name'; | 1132 toString() => 'invoke dynamic field: $name'; |
| 1105 | 1133 |
| 1106 // TODO(floitsch): make class abstract instead of adding an abstract method. | 1134 // TODO(floitsch): make class abstract instead of adding an abstract method. |
| 1107 abstract accept(HVisitor visitor); | 1135 abstract accept(HVisitor visitor); |
| 1108 } | 1136 } |
| 1109 | 1137 |
| 1110 class HInvokeDynamicGetter extends HInvokeDynamicField { | 1138 class HInvokeDynamicGetter extends HInvokeDynamicField { |
| 1111 HInvokeDynamicGetter(selector, element, name, receiver) | 1139 HInvokeDynamicGetter(selector, element, name, receiver) |
| 1112 : super(selector, element, name, [receiver]); | 1140 : super(selector, element, name, [receiver]); |
| 1113 toString() => 'invoke dynamic getter: $name'; | 1141 toString() => 'invoke dynamic getter: $name'; |
| 1114 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); | 1142 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); |
| 1115 } | 1143 } |
| 1116 | 1144 |
| 1117 class HInvokeDynamicSetter extends HInvokeDynamicField { | 1145 class HInvokeDynamicSetter extends HInvokeDynamicField { |
| 1118 HInvokeDynamicSetter(selector, element, name, receiver, value) | 1146 HInvokeDynamicSetter(selector, element, name, receiver, value) |
| 1119 : super(selector, element, name, [receiver, value]); | 1147 : super(selector, element, name, [receiver, value]); |
| 1120 toString() => 'invoke dynamic setter: $name'; | 1148 toString() => 'invoke dynamic setter: $name'; |
| 1121 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this); | 1149 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this); |
| 1122 } | 1150 } |
| 1123 | 1151 |
| 1124 class HInvokeStatic extends HInvoke { | 1152 class HInvokeStatic extends HInvoke { |
| 1153 final HType concreteType; |
| 1125 /** The first input must be the target. */ | 1154 /** The first input must be the target. */ |
| 1126 HInvokeStatic(selector, inputs) : super(selector, inputs); | 1155 HInvokeStatic(selector, inputs, [this.concreteType = HType.UNKNOWN]) |
| 1156 : super(selector, inputs); |
| 1127 toString() => 'invoke static: ${element.name}'; | 1157 toString() => 'invoke static: ${element.name}'; |
| 1128 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); | 1158 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); |
| 1129 Element get element() => target.element; | 1159 Element get element() => target.element; |
| 1130 HStatic get target() => inputs[0]; | 1160 HStatic get target() => inputs[0]; |
| 1131 | 1161 |
| 1132 bool isArrayConstructor() { | 1162 HType get guaranteedType() => concreteType; |
| 1133 // TODO(ngeoffray): This is not the right way to do the check, | |
| 1134 // nor the right place. We need to move it to a phase. | |
| 1135 return (element.isFactoryConstructor() | |
| 1136 && element.enclosingElement.name.slowToString() == 'List'); | |
| 1137 } | |
| 1138 | |
| 1139 HType get guaranteedType() { | |
| 1140 if (isArrayConstructor()) { | |
| 1141 return HType.MUTABLE_ARRAY; | |
| 1142 } | |
| 1143 return HType.UNKNOWN; | |
| 1144 } | |
| 1145 | 1163 |
| 1146 HType computeDesiredTypeForInput(HInstruction input) { | 1164 HType computeDesiredTypeForInput(HInstruction input) { |
| 1147 // TODO(floitsch): we want the target to be a function. | 1165 // TODO(floitsch): we want the target to be a function. |
| 1148 if (input == target) return HType.UNKNOWN; | 1166 if (input == target) return HType.UNKNOWN; |
| 1149 return computeDesiredTypeForNonTargetInput(input); | 1167 return computeDesiredTypeForNonTargetInput(input); |
| 1150 } | 1168 } |
| 1151 | 1169 |
| 1152 HType computeDesiredTypeForNonTargetInput(HInstruction input) { | 1170 HType computeDesiredTypeForNonTargetInput(HInstruction input) { |
| 1153 return HType.UNKNOWN; | 1171 return HType.UNKNOWN; |
| 1154 } | 1172 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1167 final bool getter; | 1185 final bool getter; |
| 1168 | 1186 |
| 1169 HInvokeInterceptor(Selector selector, | 1187 HInvokeInterceptor(Selector selector, |
| 1170 SourceString this.name, | 1188 SourceString this.name, |
| 1171 bool this.getter, | 1189 bool this.getter, |
| 1172 List<HInstruction> inputs) | 1190 List<HInstruction> inputs) |
| 1173 : super(selector, inputs); | 1191 : super(selector, inputs); |
| 1174 toString() => 'invoke interceptor: ${element.name}'; | 1192 toString() => 'invoke interceptor: ${element.name}'; |
| 1175 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this); | 1193 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this); |
| 1176 | 1194 |
| 1195 bool isLengthGetter() { |
| 1196 return getter && name == const SourceString('length'); |
| 1197 } |
| 1198 |
| 1177 bool isLengthGetterOnStringOrArray() { | 1199 bool isLengthGetterOnStringOrArray() { |
| 1178 return getter | 1200 return isLengthGetter() |
| 1179 && name == const SourceString('length') | |
| 1180 && inputs[1].isStringOrArray(); | 1201 && inputs[1].isStringOrArray(); |
| 1181 } | 1202 } |
| 1182 | 1203 |
| 1183 String get builtinJsName() { | 1204 String get builtinJsName() { |
| 1184 if (isLengthGetterOnStringOrArray()) { | 1205 if (isLengthGetterOnStringOrArray()) { |
| 1185 return 'length'; | 1206 return 'length'; |
| 1186 } else if (name == const SourceString('add') | 1207 } else if (name == const SourceString('add') |
| 1187 && inputs[1].isMutableArray()) { | 1208 && inputs[1].isMutableArray()) { |
| 1188 return 'push'; | 1209 return 'push'; |
| 1189 } else if (name == const SourceString('removeLast') | 1210 } else if (name == const SourceString('removeLast') |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1733 toString() => 'literal: $constant'; | 1754 toString() => 'literal: $constant'; |
| 1734 accept(HVisitor visitor) => visitor.visitConstant(this); | 1755 accept(HVisitor visitor) => visitor.visitConstant(this); |
| 1735 | 1756 |
| 1736 HType get guaranteedType() => constantType; | 1757 HType get guaranteedType() => constantType; |
| 1737 | 1758 |
| 1738 bool isConstant() => true; | 1759 bool isConstant() => true; |
| 1739 bool isConstantBoolean() => constant.isBool(); | 1760 bool isConstantBoolean() => constant.isBool(); |
| 1740 bool isConstantNull() => constant.isNull(); | 1761 bool isConstantNull() => constant.isNull(); |
| 1741 bool isConstantNumber() => constant.isNum(); | 1762 bool isConstantNumber() => constant.isNum(); |
| 1742 bool isConstantString() => constant.isString(); | 1763 bool isConstantString() => constant.isString(); |
| 1764 bool isConstantList() => constant.isList(); |
| 1765 bool isConstantMap() => constant.isMap(); |
| 1743 | 1766 |
| 1744 // Maybe avoid this if the literal is big? | 1767 // Maybe avoid this if the literal is big? |
| 1745 bool isCodeMotionInvariant() => true; | 1768 bool isCodeMotionInvariant() => true; |
| 1746 } | 1769 } |
| 1747 | 1770 |
| 1748 class HNot extends HInstruction { | 1771 class HNot extends HInstruction { |
| 1749 HNot(HInstruction value) : super(<HInstruction>[value]); | 1772 HNot(HInstruction value) : super(<HInstruction>[value]); |
| 1750 void prepareGvn() { | 1773 void prepareGvn() { |
| 1751 assert(!hasSideEffects()); | 1774 assert(!hasSideEffects()); |
| 1752 setUseGvn(); | 1775 setUseGvn(); |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2274 final bool isAnd; | 2297 final bool isAnd; |
| 2275 final SubExpression left; | 2298 final SubExpression left; |
| 2276 final SubExpression right; | 2299 final SubExpression right; |
| 2277 final HBasicBlock joinBlock; | 2300 final HBasicBlock joinBlock; |
| 2278 HAndOrBlockInformation(this.isAnd, | 2301 HAndOrBlockInformation(this.isAnd, |
| 2279 this.left, | 2302 this.left, |
| 2280 this.right, | 2303 this.right, |
| 2281 this.joinBlock); | 2304 this.joinBlock); |
| 2282 bool accept(HBlockInformationVisitor visitor) => visitor.visitAndOrInfo(this); | 2305 bool accept(HBlockInformationVisitor visitor) => visitor.visitAndOrInfo(this); |
| 2283 } | 2306 } |
| OLD | NEW |