Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: lib/compiler/implementation/ssa/nodes.dart

Issue 10119010: Start propagating non-primitive types in the backend, and fold instructions that know about the typ… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 {
kasperl 2012/04/19 06:46:19 Would it make sense to have a HPrimitiveType too s
ngeoffray 2012/04/19 08:09:33 Yes, added a TODO.
743 final Type type;
744
745 const HNonPrimitiveType(Type this.type) : super(FLAG_NON_PRIMITIVE);
746
747 HType combine(HType other) {
748 if (this === other) return this;
floitsch 2012/04/18 19:18:48 Why do you not look at the type? We could even hav
ngeoffray 2012/04/19 08:09:33 Well spotted. We don;t need to think about canonic
749 if (other.isUnknown()) return this;
750 return CONFLICTING;
751 }
752
753 String toString() => type.toString();
754 Element lookupMember(SourceString name) => type.element.lookupMember(name);
755 }
756
736 class HInstruction implements Hashable { 757 class HInstruction implements Hashable {
737 final int id; 758 final int id;
738 static int idCounter; 759 static int idCounter;
739 760
740 final List<HInstruction> inputs; 761 final List<HInstruction> inputs;
741 final List<HInstruction> usedBy; 762 final List<HInstruction> usedBy;
742 763
743 HBasicBlock block; 764 HBasicBlock block;
744 HInstruction previous = null; 765 HInstruction previous = null;
745 HInstruction next = null; 766 HInstruction next = null;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 // All isFunctions work on the propagated types. 805 // All isFunctions work on the propagated types.
785 bool isArray() => propagatedType.isArray(); 806 bool isArray() => propagatedType.isArray();
786 bool isMutableArray() => propagatedType.isMutableArray(); 807 bool isMutableArray() => propagatedType.isMutableArray();
787 bool isBoolean() => propagatedType.isBoolean(); 808 bool isBoolean() => propagatedType.isBoolean();
788 bool isInteger() => propagatedType.isInteger(); 809 bool isInteger() => propagatedType.isInteger();
789 bool isDouble() => propagatedType.isDouble(); 810 bool isDouble() => propagatedType.isDouble();
790 bool isNumber() => propagatedType.isNumber(); 811 bool isNumber() => propagatedType.isNumber();
791 bool isString() => propagatedType.isString(); 812 bool isString() => propagatedType.isString();
792 bool isTypeUnknown() => propagatedType.isUnknown(); 813 bool isTypeUnknown() => propagatedType.isUnknown();
793 bool isStringOrArray() => propagatedType.isStringOrArray(); 814 bool isStringOrArray() => propagatedType.isStringOrArray();
815 bool isNonPrimitive() => propagatedType.isNonPrimitive();
794 816
795 /** 817 /**
796 * This is the type the instruction is guaranteed to have. It does not 818 * This is the type the instruction is guaranteed to have. It does not
797 * take any propagation into account. 819 * take any propagation into account.
798 */ 820 */
799 HType get guaranteedType() => HType.UNKNOWN; 821 HType get guaranteedType() => HType.UNKNOWN;
800 bool hasGuaranteedType() => !guaranteedType.isUnknown(); 822 bool hasGuaranteedType() => !guaranteedType.isUnknown();
801 823
802 /** 824 /**
803 * The [propagatedType] is the type the instruction is assumed to have. 825 * The [propagatedType] is the type the instruction is assumed to have.
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 } 948 }
927 } 949 }
928 this.block = null; 950 this.block = null;
929 assert(isValid()); 951 assert(isValid());
930 } 952 }
931 953
932 bool isConstant() => false; 954 bool isConstant() => false;
933 bool isConstantNull() => false; 955 bool isConstantNull() => false;
934 bool isConstantNumber() => false; 956 bool isConstantNumber() => false;
935 bool isConstantString() => false; 957 bool isConstantString() => false;
958 bool isConstantList() => false;
959 bool isConstantMap() => false;
936 960
937 bool isValid() { 961 bool isValid() {
938 HValidator validator = new HValidator(); 962 HValidator validator = new HValidator();
939 validator.currentBlock = block; 963 validator.currentBlock = block;
940 validator.visitInstruction(this); 964 validator.visitInstruction(this);
941 return validator.isValid; 965 return validator.isValid;
942 } 966 }
943 967
944 /** 968 /**
945 * The code for computing a bailout environment, and the code 969 * The code for computing a bailout environment, and the code
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 */ 1075 */
1052 final Selector selector; 1076 final Selector selector;
1053 HInvoke(Selector this.selector, List<HInstruction> inputs) : super(inputs); 1077 HInvoke(Selector this.selector, List<HInstruction> inputs) : super(inputs);
1054 static final int ARGUMENTS_OFFSET = 1; 1078 static final int ARGUMENTS_OFFSET = 1;
1055 1079
1056 // TODO(floitsch): make class abstract instead of adding an abstract method. 1080 // TODO(floitsch): make class abstract instead of adding an abstract method.
1057 abstract accept(HVisitor visitor); 1081 abstract accept(HVisitor visitor);
1058 } 1082 }
1059 1083
1060 class HInvokeDynamic extends HInvoke { 1084 class HInvokeDynamic extends HInvoke {
1085 Element element;
1061 SourceString name; 1086 SourceString name;
1062 HInvokeDynamic(Selector selector, this.name, List<HInstruction> inputs) 1087 HInvokeDynamic(Selector selector, this.name, List<HInstruction> inputs)
1063 : super(selector, inputs); 1088 : super(selector, inputs);
1064 toString() => 'invoke dynamic: $name'; 1089 toString() => 'invoke dynamic: $name';
1065 HInstruction get receiver() => inputs[0]; 1090 HInstruction get receiver() => inputs[0];
1066 1091
1067 // TODO(floitsch): make class abstract instead of adding an abstract method. 1092 // TODO(floitsch): make class abstract instead of adding an abstract method.
1068 abstract accept(HVisitor visitor); 1093 abstract accept(HVisitor visitor);
1069 } 1094 }
1070 1095
1071 class HInvokeClosure extends HInvokeDynamic { 1096 class HInvokeClosure extends HInvokeDynamic {
1072 Element element;
1073 HInvokeClosure(Selector selector, List<HInstruction> inputs) 1097 HInvokeClosure(Selector selector, List<HInstruction> inputs)
1074 : super(selector, const SourceString('call'), inputs); 1098 : super(selector, const SourceString('call'), inputs);
1075 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); 1099 accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
1076 } 1100 }
1077 1101
1078 class HInvokeDynamicMethod extends HInvokeDynamic { 1102 class HInvokeDynamicMethod extends HInvokeDynamic {
1079 HInvokeDynamicMethod(Selector selector, 1103 HInvokeDynamicMethod(Selector selector,
1080 SourceString methodName, 1104 SourceString methodName,
1081 List<HInstruction> inputs) 1105 List<HInstruction> inputs)
1082 : super(selector, methodName, inputs); 1106 : super(selector, methodName, inputs);
1083 toString() => 'invoke dynamic method: $name'; 1107 toString() => 'invoke dynamic method: $name';
1084 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); 1108 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
1085 } 1109 }
1086 1110
1087 class HInvokeDynamicField extends HInvokeDynamic { 1111 class HInvokeDynamicField extends HInvokeDynamic {
1088 Element element;
1089 HInvokeDynamicField(Selector selector, 1112 HInvokeDynamicField(Selector selector,
1090 Element this.element, 1113 Element element,
1091 SourceString name, 1114 SourceString name,
1092 List<HInstruction>inputs) 1115 List<HInstruction>inputs)
1093 : super(selector, name, inputs); 1116 : super(selector, name, inputs) {
1117 this.element = element;
floitsch 2012/04/18 19:18:48 I would prefer passing the element in the super ca
ngeoffray 2012/04/19 08:09:33 Done.
1118 }
1094 toString() => 'invoke dynamic field: $name'; 1119 toString() => 'invoke dynamic field: $name';
1095 1120
1096 // TODO(floitsch): make class abstract instead of adding an abstract method. 1121 // TODO(floitsch): make class abstract instead of adding an abstract method.
1097 abstract accept(HVisitor visitor); 1122 abstract accept(HVisitor visitor);
1098 } 1123 }
1099 1124
1100 class HInvokeDynamicGetter extends HInvokeDynamicField { 1125 class HInvokeDynamicGetter extends HInvokeDynamicField {
1101 HInvokeDynamicGetter(selector, element, name, receiver) 1126 HInvokeDynamicGetter(selector, element, name, receiver)
1102 : super(selector, element, name, [receiver]); 1127 : super(selector, element, name, [receiver]);
1103 toString() => 'invoke dynamic getter: $name'; 1128 toString() => 'invoke dynamic getter: $name';
1104 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); 1129 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);
1105 } 1130 }
1106 1131
1107 class HInvokeDynamicSetter extends HInvokeDynamicField { 1132 class HInvokeDynamicSetter extends HInvokeDynamicField {
1108 HInvokeDynamicSetter(selector, element, name, receiver, value) 1133 HInvokeDynamicSetter(selector, element, name, receiver, value)
1109 : super(selector, element, name, [receiver, value]); 1134 : super(selector, element, name, [receiver, value]);
1110 toString() => 'invoke dynamic setter: $name'; 1135 toString() => 'invoke dynamic setter: $name';
1111 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this); 1136 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);
1112 } 1137 }
1113 1138
1114 class HInvokeStatic extends HInvoke { 1139 class HInvokeStatic extends HInvoke {
1140 final HType concreteType;
1115 /** The first input must be the target. */ 1141 /** The first input must be the target. */
1116 HInvokeStatic(selector, inputs) : super(selector, inputs); 1142 HInvokeStatic(selector, inputs, [this.concreteType = HType.UNKNOWN])
1143 : super(selector, inputs);
1117 toString() => 'invoke static: ${element.name}'; 1144 toString() => 'invoke static: ${element.name}';
1118 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); 1145 accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
1119 Element get element() => target.element; 1146 Element get element() => target.element;
1120 HStatic get target() => inputs[0]; 1147 HStatic get target() => inputs[0];
1121 1148
1122 bool isArrayConstructor() { 1149 HType get guaranteedType() => concreteType;
1123 // TODO(ngeoffray): This is not the right way to do the check,
1124 // nor the right place. We need to move it to a phase.
1125 return (element.isFactoryConstructor()
1126 && element.enclosingElement.name.slowToString() == 'List');
1127 }
1128
1129 HType get guaranteedType() {
1130 if (isArrayConstructor()) {
1131 return HType.MUTABLE_ARRAY;
1132 }
1133 return HType.UNKNOWN;
1134 }
1135 1150
1136 HType computeDesiredTypeForInput(HInstruction input) { 1151 HType computeDesiredTypeForInput(HInstruction input) {
1137 // TODO(floitsch): we want the target to be a function. 1152 // TODO(floitsch): we want the target to be a function.
1138 if (input == target) return HType.UNKNOWN; 1153 if (input == target) return HType.UNKNOWN;
1139 return computeDesiredTypeForNonTargetInput(input); 1154 return computeDesiredTypeForNonTargetInput(input);
1140 } 1155 }
1141 1156
1142 HType computeDesiredTypeForNonTargetInput(HInstruction input) { 1157 HType computeDesiredTypeForNonTargetInput(HInstruction input) {
1143 return HType.UNKNOWN; 1158 return HType.UNKNOWN;
1144 } 1159 }
(...skipping 12 matching lines...) Expand all
1157 final bool getter; 1172 final bool getter;
1158 1173
1159 HInvokeInterceptor(Selector selector, 1174 HInvokeInterceptor(Selector selector,
1160 SourceString this.name, 1175 SourceString this.name,
1161 bool this.getter, 1176 bool this.getter,
1162 List<HInstruction> inputs) 1177 List<HInstruction> inputs)
1163 : super(selector, inputs); 1178 : super(selector, inputs);
1164 toString() => 'invoke interceptor: ${element.name}'; 1179 toString() => 'invoke interceptor: ${element.name}';
1165 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this); 1180 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this);
1166 1181
1182 bool isLengthGetter() {
1183 return getter
floitsch 2012/04/18 19:18:48 one line.
kasperl 2012/04/19 06:46:19 Fits on one line?
ngeoffray 2012/04/19 08:09:33 Done.
1184 && name == const SourceString('length');
1185 }
1186
1167 bool isLengthGetterOnStringOrArray() { 1187 bool isLengthGetterOnStringOrArray() {
1168 return getter 1188 return isLengthGetter()
1169 && name == const SourceString('length')
1170 && inputs[1].isStringOrArray(); 1189 && inputs[1].isStringOrArray();
1171 } 1190 }
1172 1191
1173 String get builtinJsName() { 1192 String get builtinJsName() {
1174 if (isLengthGetterOnStringOrArray()) { 1193 if (isLengthGetterOnStringOrArray()) {
1175 return 'length'; 1194 return 'length';
1176 } else if (name == const SourceString('add') 1195 } else if (name == const SourceString('add')
1177 && inputs[1].isMutableArray()) { 1196 && inputs[1].isMutableArray()) {
1178 return 'push'; 1197 return 'push';
1179 } else if (name == const SourceString('removeLast') 1198 } else if (name == const SourceString('removeLast')
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
1715 toString() => 'literal: $constant'; 1734 toString() => 'literal: $constant';
1716 accept(HVisitor visitor) => visitor.visitConstant(this); 1735 accept(HVisitor visitor) => visitor.visitConstant(this);
1717 1736
1718 HType get guaranteedType() => constantType; 1737 HType get guaranteedType() => constantType;
1719 1738
1720 bool isConstant() => true; 1739 bool isConstant() => true;
1721 bool isConstantBoolean() => constant.isBool(); 1740 bool isConstantBoolean() => constant.isBool();
1722 bool isConstantNull() => constant.isNull(); 1741 bool isConstantNull() => constant.isNull();
1723 bool isConstantNumber() => constant.isNum(); 1742 bool isConstantNumber() => constant.isNum();
1724 bool isConstantString() => constant.isString(); 1743 bool isConstantString() => constant.isString();
1744 bool isConstantList() => constant.isList();
1745 bool isConstantMap() => constant.isMap();
1725 1746
1726 // Maybe avoid this if the literal is big? 1747 // Maybe avoid this if the literal is big?
1727 bool isCodeMotionInvariant() => true; 1748 bool isCodeMotionInvariant() => true;
1728 } 1749 }
1729 1750
1730 class HNot extends HInstruction { 1751 class HNot extends HInstruction {
1731 HNot(HInstruction value) : super(<HInstruction>[value]); 1752 HNot(HInstruction value) : super(<HInstruction>[value]);
1732 void prepareGvn() { 1753 void prepareGvn() {
1733 assert(!hasSideEffects()); 1754 assert(!hasSideEffects());
1734 setUseGvn(); 1755 setUseGvn();
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after
2256 final bool isAnd; 2277 final bool isAnd;
2257 final SubExpression left; 2278 final SubExpression left;
2258 final SubExpression right; 2279 final SubExpression right;
2259 final HBasicBlock joinBlock; 2280 final HBasicBlock joinBlock;
2260 HAndOrBlockInformation(this.isAnd, 2281 HAndOrBlockInformation(this.isAnd,
2261 this.left, 2282 this.left,
2262 this.right, 2283 this.right,
2263 this.joinBlock); 2284 this.joinBlock);
2264 bool accept(HBlockInformationVisitor visitor) => visitor.visitAndOrInfo(this); 2285 bool accept(HBlockInformationVisitor visitor) => visitor.visitAndOrInfo(this);
2265 } 2286 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698