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

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

Issue 10139012: Refactor types in ssa nodes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: More fixes. 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 648 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 659
660 bool isValid() { 660 bool isValid() {
661 assert(isClosed()); 661 assert(isClosed());
662 HValidator validator = new HValidator(); 662 HValidator validator = new HValidator();
663 validator.visitBasicBlock(this); 663 validator.visitBasicBlock(this);
664 return validator.isValid; 664 return validator.isValid;
665 } 665 }
666 } 666 }
667 667
668 668
669 class HType {
670 final int flag;
671 const HType(int this.flag);
672
673 static final int FLAG_CONFLICTING = 0;
674 static final int FLAG_UNKNOWN = 1;
675 static final int FLAG_BOOLEAN = FLAG_UNKNOWN << 1;
676 static final int FLAG_INTEGER = FLAG_BOOLEAN << 1;
677 static final int FLAG_STRING = FLAG_INTEGER << 1;
678 static final int FLAG_READABLE_ARRAY = FLAG_STRING << 1;
679 // FLAG_WRITABLE_ARRAY implies FLAG_READABLE_ARRAY.
680 static final int FLAG_WRITEABLE_ARRAY = FLAG_READABLE_ARRAY << 1;
681 static final int FLAG_DOUBLE = FLAG_WRITEABLE_ARRAY << 1;
682 static final int FLAG_NON_PRIMITIVE = FLAG_DOUBLE << 1;
683
684 static final HType CONFLICTING = const HType(FLAG_CONFLICTING);
685 static final HType UNKNOWN = const HType(FLAG_UNKNOWN);
686 static final HType BOOLEAN = const HType(FLAG_BOOLEAN);
687 static final HType STRING = const HType(FLAG_STRING);
688 static final HType READABLE_ARRAY = const HType(FLAG_READABLE_ARRAY);
689 static final HType MUTABLE_ARRAY =
690 const HType(FLAG_READABLE_ARRAY | FLAG_WRITEABLE_ARRAY);
691 static final HType INTEGER = const HType(FLAG_INTEGER);
692 static final HType DOUBLE = const HType(FLAG_DOUBLE);
693 static final HType STRING_OR_ARRAY =
694 const HType(FLAG_STRING | FLAG_READABLE_ARRAY | FLAG_WRITEABLE_ARRAY);
695 static final HType NUMBER = const HType(FLAG_DOUBLE | FLAG_INTEGER);
696
697 bool isConflicting() => this === CONFLICTING;
698 bool isUnknown() => this === UNKNOWN;
699 bool isBoolean() => this === BOOLEAN;
700 bool isInteger() => this === INTEGER;
701 bool isDouble() => this === DOUBLE;
702 bool isString() => this === STRING;
703 bool isArray() => (this.flag & FLAG_READABLE_ARRAY) != 0;
704 bool isMutableArray() => this === MUTABLE_ARRAY;
705 bool isNumber() => (this.flag & (FLAG_INTEGER | FLAG_DOUBLE)) != 0;
706 bool isStringOrArray() =>
707 (this.flag & (FLAG_STRING | FLAG_READABLE_ARRAY)) != 0;
708 bool isNonPrimitive() => this.flag === FLAG_NON_PRIMITIVE;
709 /** A type is useful it is not unknown and not conflicting. */
710 bool isUseful() => this !== UNKNOWN && this !== CONFLICTING;
711
712 static HType getTypeFromFlag(int flag) {
713 if (flag === CONFLICTING.flag) return CONFLICTING;
714 if (flag === UNKNOWN.flag) return UNKNOWN;
715 if (flag === BOOLEAN.flag) return BOOLEAN;
716 if (flag === INTEGER.flag) return INTEGER;
717 if (flag === DOUBLE.flag) return DOUBLE;
718 if (flag === STRING.flag) return STRING;
719 if (flag === READABLE_ARRAY.flag) return READABLE_ARRAY;
720 if (flag === MUTABLE_ARRAY.flag) return MUTABLE_ARRAY;
721 if (flag === NUMBER.flag) return NUMBER;
722 if (flag === STRING_OR_ARRAY.flag) return STRING_OR_ARRAY;
723 unreachable();
724 }
725
726 String toString() {
727 if (isConflicting()) return 'conflicting';
728 if (isUnknown()) return 'unknown';
729 if (isBoolean()) return 'boolean';
730 if (isInteger()) return 'integer';
731 if (isDouble()) return 'double';
732 if (isString()) return 'string';
733 if (isMutableArray()) return 'mutable array';
734 if (isArray()) return 'array';
735 if (isNumber()) return 'number';
736 if (isStringOrArray()) return 'string or array';
737 unreachable();
738 }
739
740 HType combine(HType other) {
741 if (isUnknown()) return other;
742 if (other.isUnknown()) return this;
743 return getTypeFromFlag(this.flag & other.flag);
744 }
745 }
746
747 class HNonPrimitiveType extends HType {
748 final Type type;
749
750 // TODO(ngeoffray): Add a HPrimitiveType to get rid of the flag.
751 const HNonPrimitiveType(Type this.type) : super(HType.FLAG_NON_PRIMITIVE);
752
753 HType combine(HType other) {
754 if (other.isNonPrimitive()) {
755 HNonPrimitiveType temp = other;
756 if (this.type === temp.type) return this;
757 }
758 if (other.isUnknown()) return this;
759 return HType.CONFLICTING;
760 }
761
762 String toString() => type.toString();
763 Element lookupMember(SourceString name) {
764 ClassElement classElement = type.element;
765 return classElement.lookupMember(name);
766 }
767 }
768
769 class HInstruction implements Hashable { 669 class HInstruction implements Hashable {
770 Element sourceElement; 670 Element sourceElement;
771 671
772 final int id; 672 final int id;
773 static int idCounter; 673 static int idCounter;
774 674
775 final List<HInstruction> inputs; 675 final List<HInstruction> inputs;
776 final List<HInstruction> usedBy; 676 final List<HInstruction> usedBy;
777 677
778 HBasicBlock block; 678 HBasicBlock block;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); } 711 void setAllSideEffects() { flags |= ((1 << FLAG_CHANGES_COUNT) - 1); }
812 void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); } 712 void clearAllSideEffects() { flags &= ~((1 << FLAG_CHANGES_COUNT) - 1); }
813 713
814 bool useGvn() => getFlag(FLAG_USE_GVN); 714 bool useGvn() => getFlag(FLAG_USE_GVN);
815 void setUseGvn() { setFlag(FLAG_USE_GVN); } 715 void setUseGvn() { setFlag(FLAG_USE_GVN); }
816 // Does this node potentially affect control flow. 716 // Does this node potentially affect control flow.
817 bool isControlFlow() => false; 717 bool isControlFlow() => false;
818 718
819 // All isFunctions work on the propagated types. 719 // All isFunctions work on the propagated types.
820 bool isArray() => propagatedType.isArray(); 720 bool isArray() => propagatedType.isArray();
721 bool isReadableArray() => propagatedType.isReadableArray();
821 bool isMutableArray() => propagatedType.isMutableArray(); 722 bool isMutableArray() => propagatedType.isMutableArray();
723 bool isExtendableArray() => propagatedType.isExtendableArray();
822 bool isBoolean() => propagatedType.isBoolean(); 724 bool isBoolean() => propagatedType.isBoolean();
823 bool isInteger() => propagatedType.isInteger(); 725 bool isInteger() => propagatedType.isInteger();
824 bool isDouble() => propagatedType.isDouble(); 726 bool isDouble() => propagatedType.isDouble();
825 bool isNumber() => propagatedType.isNumber(); 727 bool isNumber() => propagatedType.isNumber();
826 bool isString() => propagatedType.isString(); 728 bool isString() => propagatedType.isString();
827 bool isTypeUnknown() => propagatedType.isUnknown(); 729 bool isTypeUnknown() => propagatedType.isUnknown();
828 bool isStringOrArray() => propagatedType.isStringOrArray(); 730 bool isIndexablePrimitive() => propagatedType.isIndexable();
ngeoffray 2012/04/25 11:41:13 I think both should be named isIndexablePrimitive
floitsch 2012/04/25 19:52:15 Done.
829 bool isNonPrimitive() => propagatedType.isNonPrimitive(); 731 bool isNonPrimitive() => propagatedType.isNonPrimitive();
830 732
831 /** 733 /**
832 * This is the type the instruction is guaranteed to have. It does not 734 * This is the type the instruction is guaranteed to have. It does not
833 * take any propagation into account. 735 * take any propagation into account.
834 */ 736 */
835 HType get guaranteedType() => HType.UNKNOWN; 737 HType get guaranteedType() => HType.UNKNOWN;
836 bool hasGuaranteedType() => !guaranteedType.isUnknown(); 738 bool hasGuaranteedType() => !guaranteedType.isUnknown();
837 739
838 /** 740 /**
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
1208 List<HInstruction> inputs) 1110 List<HInstruction> inputs)
1209 : super(selector, inputs); 1111 : super(selector, inputs);
1210 toString() => 'invoke interceptor: ${element.name}'; 1112 toString() => 'invoke interceptor: ${element.name}';
1211 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this); 1113 accept(HVisitor visitor) => visitor.visitInvokeInterceptor(this);
1212 1114
1213 bool isLengthGetter() { 1115 bool isLengthGetter() {
1214 return getter && name == const SourceString('length'); 1116 return getter && name == const SourceString('length');
1215 } 1117 }
1216 1118
1217 bool isLengthGetterOnStringOrArray() { 1119 bool isLengthGetterOnStringOrArray() {
1218 return isLengthGetter() 1120 return isLengthGetter() && inputs[1].isIndexablePrimitive();
1219 && inputs[1].isStringOrArray();
1220 } 1121 }
1221 1122
1222 String get builtinJsName() { 1123 String get builtinJsName() {
1223 if (isLengthGetterOnStringOrArray()) { 1124 if (isLengthGetterOnStringOrArray()) {
1224 return 'length'; 1125 return 'length';
1225 } else if (name == const SourceString('add') 1126 } else if (name == const SourceString('add')
1226 && inputs[1].isMutableArray()) { 1127 && inputs[1].isExtendableArray()) {
1227 return 'push'; 1128 return 'push';
1228 } else if (name == const SourceString('removeLast') 1129 } else if (name == const SourceString('removeLast')
1229 && inputs[1].isMutableArray()) { 1130 && inputs[1].isExtendableArray()) {
1230 return 'pop'; 1131 return 'pop';
1231 } 1132 }
1232 return null; 1133 return null;
1233 } 1134 }
1234 1135
1235 HType get guaranteedType() => HType.UNKNOWN; 1136 HType get guaranteedType() => HType.UNKNOWN;
1236 1137
1237 HType get likelyType() { 1138 HType get likelyType() {
1238 // In general a length getter or method returns an int. 1139 // In general a length getter or method returns an int.
1239 if (name == const SourceString('length')) return HType.INTEGER; 1140 if (name == const SourceString('length')) return HType.INTEGER;
1240 return HType.UNKNOWN; 1141 return HType.UNKNOWN;
1241 } 1142 }
1242 1143
1243 HType computeTypeFromInputTypes() { 1144 HType computeTypeFromInputTypes() {
1244 if (isLengthGetterOnStringOrArray()) return HType.INTEGER; 1145 if (isLengthGetterOnStringOrArray()) return HType.INTEGER;
1245 return HType.UNKNOWN; 1146 return HType.UNKNOWN;
1246 } 1147 }
1247 1148
1248 HType computeDesiredTypeForNonTargetInput(HInstruction input) { 1149 HType computeDesiredTypeForNonTargetInput(HInstruction input) {
1249 // If the first argument is a string or an array and we invoke methods 1150 // If the first argument is a string or an array and we invoke methods
1250 // on it that mutate it, then we want to restrict the incoming type to be 1151 // on it that mutate it, then we want to restrict the incoming type to be
1251 // a mutable array. 1152 // a mutable array.
1252 if (input == inputs[1] && input.isStringOrArray()) { 1153 if (input == inputs[1] && input.isIndexablePrimitive()) {
1253 if (name == const SourceString('add') 1154 if (name == const SourceString('add')
1254 || name == const SourceString('removeLast')) { 1155 || name == const SourceString('removeLast')) {
1255 return HType.MUTABLE_ARRAY; 1156 return HType.MUTABLE_ARRAY;
1256 } 1157 }
1257 } 1158 }
1258 return HType.UNKNOWN; 1159 return HType.UNKNOWN;
1259 } 1160 }
1260 1161
1261 void prepareGvn() { 1162 void prepareGvn() {
1262 if (isLengthGetterOnStringOrArray()) { 1163 if (isLengthGetterOnStringOrArray()) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 final DartString code; 1205 final DartString code;
1305 final HType foreignType; 1206 final HType foreignType;
1306 HForeign(this.code, DartString declaredType, List<HInstruction> inputs) 1207 HForeign(this.code, DartString declaredType, List<HInstruction> inputs)
1307 : foreignType = computeTypeFromDeclaredType(declaredType), 1208 : foreignType = computeTypeFromDeclaredType(declaredType),
1308 super(inputs); 1209 super(inputs);
1309 accept(HVisitor visitor) => visitor.visitForeign(this); 1210 accept(HVisitor visitor) => visitor.visitForeign(this);
1310 1211
1311 static HType computeTypeFromDeclaredType(DartString declaredType) { 1212 static HType computeTypeFromDeclaredType(DartString declaredType) {
1312 if (declaredType.slowToString() == 'bool') return HType.BOOLEAN; 1213 if (declaredType.slowToString() == 'bool') return HType.BOOLEAN;
1313 if (declaredType.slowToString() == 'int') return HType.INTEGER; 1214 if (declaredType.slowToString() == 'int') return HType.INTEGER;
1215 if (declaredType.slowToString() == 'double') return HType.DOUBLE;
1314 if (declaredType.slowToString() == 'num') return HType.NUMBER; 1216 if (declaredType.slowToString() == 'num') return HType.NUMBER;
1315 if (declaredType.slowToString() == 'String') return HType.STRING; 1217 if (declaredType.slowToString() == 'String') return HType.STRING;
1316 return HType.UNKNOWN; 1218 return HType.UNKNOWN;
1317 } 1219 }
1318 1220
1319 HType get guaranteedType() => foreignType; 1221 HType get guaranteedType() => foreignType;
1320 } 1222 }
1321 1223
1322 class HForeignNew extends HForeign { 1224 class HForeignNew extends HForeign {
1323 ClassElement element; 1225 ClassElement element;
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
1854 // different known types, we'll return a conflict -- otherwise we'll 1756 // different known types, we'll return a conflict -- otherwise we'll
1855 // simply return an unknown type. 1757 // simply return an unknown type.
1856 HType computeInputsType(bool unknownWins) { 1758 HType computeInputsType(bool unknownWins) {
1857 HType candidateType = inputs[0].propagatedType; 1759 HType candidateType = inputs[0].propagatedType;
1858 bool seenUnknown = candidateType.isUnknown(); 1760 bool seenUnknown = candidateType.isUnknown();
1859 for (int i = 1, length = inputs.length; i < length; i++) { 1761 for (int i = 1, length = inputs.length; i < length; i++) {
1860 HType inputType = inputs[i].propagatedType; 1762 HType inputType = inputs[i].propagatedType;
1861 if (inputType.isUnknown()) { 1763 if (inputType.isUnknown()) {
1862 seenUnknown = true; 1764 seenUnknown = true;
1863 } else { 1765 } else {
1864 candidateType = candidateType.combine(inputType); 1766 // Phis need to combine the incoming types using the union operation.
1767 // For example, if one incoming edge has type integer and the other has
1768 // type double, then the phi is either an integer or double and thus has
1769 // type number.
1770 candidateType = candidateType.union(inputType);
1865 if (candidateType.isConflicting()) return HType.CONFLICTING; 1771 if (candidateType.isConflicting()) return HType.CONFLICTING;
1866 } 1772 }
1867 } 1773 }
1868 if (seenUnknown && unknownWins) return HType.UNKNOWN; 1774 if (seenUnknown && unknownWins) return HType.UNKNOWN;
1869 return candidateType; 1775 return candidateType;
1870 } 1776 }
1871 1777
1872 HType computeTypeFromInputTypes() { 1778 HType computeTypeFromInputTypes() {
1873 HType inputsType = computeInputsType(true); 1779 HType inputsType = computeInputsType(true);
1874 if (inputsType.isConflicting()) return HType.UNKNOWN; 1780 if (inputsType.isConflicting()) return HType.UNKNOWN;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1929 HType computeTypeFromInputTypes() { 1835 HType computeTypeFromInputTypes() {
1930 if (left.isNumber()) return HType.BOOLEAN; 1836 if (left.isNumber()) return HType.BOOLEAN;
1931 return HType.UNKNOWN; 1837 return HType.UNKNOWN;
1932 } 1838 }
1933 1839
1934 HType computeDesiredTypeForNonTargetInput(HInstruction input) { 1840 HType computeDesiredTypeForNonTargetInput(HInstruction input) {
1935 // For all relational operations exept HEquals, we expect to get numbers 1841 // For all relational operations exept HEquals, we expect to get numbers
1936 // only. With numbers the outgoing type is a boolean. If something else 1842 // only. With numbers the outgoing type is a boolean. If something else
1937 // is desired, then numbers are incorrect, though. 1843 // is desired, then numbers are incorrect, though.
1938 if (propagatedType.isUnknown() || propagatedType.isBoolean()) { 1844 if (propagatedType.isUnknown() || propagatedType.isBoolean()) {
1939 if (left.isTypeUnknown() || left.isNumber()) return HType.NUMBER; 1845 if (left.isTypeUnknown() || left.isNumber()) {
1846 return HType.NUMBER;
1847 }
1940 } 1848 }
1941 return HType.UNKNOWN; 1849 return HType.UNKNOWN;
1942 } 1850 }
1943 1851
1944 HType get likelyType() => HType.BOOLEAN; 1852 HType get likelyType() => HType.BOOLEAN;
1945 1853
1946 bool get builtin() => left.isNumber() && right.isNumber(); 1854 bool get builtin() => left.isNumber() && right.isNumber();
1947 // TODO(1603): the class should be marked as abstract. 1855 // TODO(1603): the class should be marked as abstract.
1948 abstract BinaryOperation get operation(); 1856 abstract BinaryOperation get operation();
1949 } 1857 }
(...skipping 14 matching lines...) Expand all
1964 if (builtin) return HType.BOOLEAN; 1872 if (builtin) return HType.BOOLEAN;
1965 return HType.UNKNOWN; 1873 return HType.UNKNOWN;
1966 } 1874 }
1967 1875
1968 HType computeDesiredTypeForNonTargetInput(HInstruction input) { 1876 HType computeDesiredTypeForNonTargetInput(HInstruction input) {
1969 if (input == left && right.propagatedType.isUseful()) { 1877 if (input == left && right.propagatedType.isUseful()) {
1970 // All our useful types have === semantics. But we don't want to 1878 // All our useful types have === semantics. But we don't want to
1971 // speculatively test for all possible types. Therefore we try to match 1879 // speculatively test for all possible types. Therefore we try to match
1972 // the two types. That is, if we see x == 3, then we speculatively test 1880 // the two types. That is, if we see x == 3, then we speculatively test
1973 // if x is a number and bailout if it isn't. 1881 // if x is a number and bailout if it isn't.
1974 if (right.isNumber()) return HType.NUMBER; // No need to be more precise. 1882 // If right is a number we don't need more than a number (no need to match
1883 // the exact type of right).
1884 if (right.isNumber()) return HType.NUMBER;
1975 // String equality testing is much more common than array equality 1885 // String equality testing is much more common than array equality
1976 // testing. 1886 // testing.
1977 if (right.isStringOrArray()) return HType.STRING; 1887 if (right.isIndexablePrimitive()) return HType.STRING;
1978 return right.propagatedType; 1888 return right.propagatedType;
1979 } 1889 }
1980 // String equality testing is much more common than array equality testing. 1890 // String equality testing is much more common than array equality testing.
1981 if (input == left && left.isStringOrArray()) { 1891 if (input == left && left.isIndexablePrimitive()) {
1982 return HType.READABLE_ARRAY; 1892 return HType.READABLE_ARRAY;
1983 } 1893 }
1984 // String equality testing is much more common than array equality testing. 1894 // String equality testing is much more common than array equality testing.
1985 if (input == right && right.isStringOrArray()) { 1895 if (input == right && right.isIndexablePrimitive()) {
1986 return HType.STRING; 1896 return HType.STRING;
1987 } 1897 }
1988 return HType.UNKNOWN; 1898 return HType.UNKNOWN;
1989 } 1899 }
1990 1900
1991 EqualsOperation get operation() => const EqualsOperation(); 1901 EqualsOperation get operation() => const EqualsOperation();
1992 int typeCode() => 19; 1902 int typeCode() => 19;
1993 bool typeEquals(other) => other is HEquals; 1903 bool typeEquals(other) => other is HEquals;
1994 bool dataEquals(HInstruction other) => true; 1904 bool dataEquals(HInstruction other) => true;
1995 } 1905 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2124 } else { 2034 } else {
2125 setAllSideEffects(); 2035 setAllSideEffects();
2126 } 2036 }
2127 } 2037 }
2128 2038
2129 HInstruction get receiver() => inputs[1]; 2039 HInstruction get receiver() => inputs[1];
2130 HInstruction get index() => inputs[2]; 2040 HInstruction get index() => inputs[2];
2131 2041
2132 HType computeDesiredTypeForNonTargetInput(HInstruction input) { 2042 HType computeDesiredTypeForNonTargetInput(HInstruction input) {
2133 if (input == receiver && (index.isTypeUnknown() || index.isNumber())) { 2043 if (input == receiver && (index.isTypeUnknown() || index.isNumber())) {
2134 return HType.STRING_OR_ARRAY; 2044 return HType.INDEXABLE;
ngeoffray 2012/04/25 11:41:13 INDEXABLE_PRIMITIVE
floitsch 2012/04/25 19:52:15 Done.
2135 } 2045 }
2136 // The index should be an int when the receiver is a string or array. 2046 // The index should be an int when the receiver is a string or array.
2137 // However it turns out that inserting an integer check in the optimized 2047 // However it turns out that inserting an integer check in the optimized
2138 // version is cheaper than having another bailout case. This is true, 2048 // version is cheaper than having another bailout case. This is true,
2139 // because the integer check will simply throw if it fails. 2049 // because the integer check will simply throw if it fails.
2140 return HType.UNKNOWN; 2050 return HType.UNKNOWN;
2141 } 2051 }
2142 2052
2143 bool get builtin() => receiver.isStringOrArray() && index.isInteger(); 2053 bool get builtin() => receiver.isIndexablePrimitive() && index.isInteger();
2144 } 2054 }
2145 2055
2146 class HIndexAssign extends HInvokeStatic { 2056 class HIndexAssign extends HInvokeStatic {
2147 HIndexAssign(HStatic target, 2057 HIndexAssign(HStatic target,
2148 HInstruction receiver, 2058 HInstruction receiver,
2149 HInstruction index, 2059 HInstruction index,
2150 HInstruction value) 2060 HInstruction value)
2151 : super(Selector.INDEX_SET, 2061 : super(Selector.INDEX_SET,
2152 <HInstruction>[target, receiver, index, value]); 2062 <HInstruction>[target, receiver, index, value]);
2153 toString() => 'index assign operator'; 2063 toString() => 'index assign operator';
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
2316 final bool isAnd; 2226 final bool isAnd;
2317 final SubExpression left; 2227 final SubExpression left;
2318 final SubExpression right; 2228 final SubExpression right;
2319 final HBasicBlock joinBlock; 2229 final HBasicBlock joinBlock;
2320 HAndOrBlockInformation(this.isAnd, 2230 HAndOrBlockInformation(this.isAnd,
2321 this.left, 2231 this.left,
2322 this.right, 2232 this.right,
2323 this.joinBlock); 2233 this.joinBlock);
2324 bool accept(HBlockInformationVisitor visitor) => visitor.visitAndOrInfo(this); 2234 bool accept(HBlockInformationVisitor visitor) => visitor.visitAndOrInfo(this);
2325 } 2235 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698