| 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 visitBailoutTarget(HBailoutTarget node); | 9   R visitBailoutTarget(HBailoutTarget node); | 
| 10   R visitBitAnd(HBitAnd node); | 10   R visitBitAnd(HBitAnd node); | 
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 254   } | 254   } | 
| 255 | 255 | 
| 256   visitInstruction(HInstruction instruction) {} | 256   visitInstruction(HInstruction instruction) {} | 
| 257 | 257 | 
| 258   visitBinaryArithmetic(HBinaryArithmetic node) => visitInvokeBinary(node); | 258   visitBinaryArithmetic(HBinaryArithmetic node) => visitInvokeBinary(node); | 
| 259   visitBinaryBitOp(HBinaryBitOp node) => visitBinaryArithmetic(node); | 259   visitBinaryBitOp(HBinaryBitOp node) => visitBinaryArithmetic(node); | 
| 260   visitInvoke(HInvoke node) => visitInstruction(node); | 260   visitInvoke(HInvoke node) => visitInstruction(node); | 
| 261   visitInvokeBinary(HInvokeBinary node) => visitInvokeStatic(node); | 261   visitInvokeBinary(HInvokeBinary node) => visitInvokeStatic(node); | 
| 262   visitInvokeDynamic(HInvokeDynamic node) => visitInvoke(node); | 262   visitInvokeDynamic(HInvokeDynamic node) => visitInvoke(node); | 
| 263   visitInvokeDynamicField(HInvokeDynamicField node) => visitInvokeDynamic(node); | 263   visitInvokeDynamicField(HInvokeDynamicField node) => visitInvokeDynamic(node); | 
| 264   visitInvokeUnary(HInvokeUnary node) => visitInvokeStatic(node); | 264   visitInvokeUnary(HInvokeUnary node) => visitInstruction(node); | 
| 265   visitConditionalBranch(HConditionalBranch node) => visitControlFlow(node); | 265   visitConditionalBranch(HConditionalBranch node) => visitControlFlow(node); | 
| 266   visitControlFlow(HControlFlow node) => visitInstruction(node); | 266   visitControlFlow(HControlFlow node) => visitInstruction(node); | 
| 267   visitFieldAccess(HFieldAccess node) => visitInstruction(node); | 267   visitFieldAccess(HFieldAccess node) => visitInstruction(node); | 
| 268   visitRelational(HRelational node) => visitInvokeBinary(node); | 268   visitRelational(HRelational node) => visitInvokeBinary(node); | 
| 269 | 269 | 
| 270   visitAdd(HAdd node) => visitBinaryArithmetic(node); | 270   visitAdd(HAdd node) => visitBinaryArithmetic(node); | 
| 271   visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); | 271   visitBailoutTarget(HBailoutTarget node) => visitInstruction(node); | 
| 272   visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); | 272   visitBitAnd(HBitAnd node) => visitBinaryBitOp(node); | 
| 273   visitBitNot(HBitNot node) => visitInvokeUnary(node); | 273   visitBitNot(HBitNot node) => visitInvokeUnary(node); | 
| 274   visitBitOr(HBitOr node) => visitBinaryBitOp(node); | 274   visitBitOr(HBitOr node) => visitBinaryBitOp(node); | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 286   visitFieldGet(HFieldGet node) => visitFieldAccess(node); | 286   visitFieldGet(HFieldGet node) => visitFieldAccess(node); | 
| 287   visitFieldSet(HFieldSet node) => visitFieldAccess(node); | 287   visitFieldSet(HFieldSet node) => visitFieldAccess(node); | 
| 288   visitForeign(HForeign node) => visitInstruction(node); | 288   visitForeign(HForeign node) => visitInstruction(node); | 
| 289   visitForeignNew(HForeignNew node) => visitForeign(node); | 289   visitForeignNew(HForeignNew node) => visitForeign(node); | 
| 290   visitGoto(HGoto node) => visitControlFlow(node); | 290   visitGoto(HGoto node) => visitControlFlow(node); | 
| 291   visitGreater(HGreater node) => visitRelational(node); | 291   visitGreater(HGreater node) => visitRelational(node); | 
| 292   visitGreaterEqual(HGreaterEqual node) => visitRelational(node); | 292   visitGreaterEqual(HGreaterEqual node) => visitRelational(node); | 
| 293   visitIdentity(HIdentity node) => visitRelational(node); | 293   visitIdentity(HIdentity node) => visitRelational(node); | 
| 294   visitIf(HIf node) => visitConditionalBranch(node); | 294   visitIf(HIf node) => visitConditionalBranch(node); | 
| 295   visitIndex(HIndex node) => visitInstruction(node); | 295   visitIndex(HIndex node) => visitInstruction(node); | 
| 296   visitIndexAssign(HIndexAssign node) => visitInvokeStatic(node); | 296   visitIndexAssign(HIndexAssign node) => visitInstruction(node); | 
| 297   visitIntegerCheck(HIntegerCheck node) => visitCheck(node); | 297   visitIntegerCheck(HIntegerCheck node) => visitCheck(node); | 
| 298   visitInterceptor(HInterceptor node) => visitInstruction(node); | 298   visitInterceptor(HInterceptor node) => visitInstruction(node); | 
| 299   visitInvokeClosure(HInvokeClosure node) | 299   visitInvokeClosure(HInvokeClosure node) | 
| 300       => visitInvokeDynamic(node); | 300       => visitInvokeDynamic(node); | 
| 301   visitInvokeDynamicMethod(HInvokeDynamicMethod node) | 301   visitInvokeDynamicMethod(HInvokeDynamicMethod node) | 
| 302       => visitInvokeDynamic(node); | 302       => visitInvokeDynamic(node); | 
| 303   visitInvokeDynamicGetter(HInvokeDynamicGetter node) | 303   visitInvokeDynamicGetter(HInvokeDynamicGetter node) | 
| 304       => visitInvokeDynamicField(node); | 304       => visitInvokeDynamicField(node); | 
| 305   visitInvokeDynamicSetter(HInvokeDynamicSetter node) | 305   visitInvokeDynamicSetter(HInvokeDynamicSetter node) | 
| 306       => visitInvokeDynamicField(node); | 306       => visitInvokeDynamicField(node); | 
| (...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1322 | 1322 | 
| 1323 class HInvokeDynamicMethod extends HInvokeDynamic { | 1323 class HInvokeDynamicMethod extends HInvokeDynamic { | 
| 1324   HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) | 1324   HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs) | 
| 1325     : super(selector, null, inputs); | 1325     : super(selector, null, inputs); | 
| 1326   String toString() => 'invoke dynamic method: $selector'; | 1326   String toString() => 'invoke dynamic method: $selector'; | 
| 1327   accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 1327   accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); | 
| 1328 | 1328 | 
| 1329   bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) { | 1329   bool isIndexOperatorOnIndexablePrimitive(HTypeMap types) { | 
| 1330     return isInterceptorCall | 1330     return isInterceptorCall | 
| 1331         && selector.kind == SelectorKind.INDEX | 1331         && selector.kind == SelectorKind.INDEX | 
|  | 1332         && selector.name == const SourceString('[]') | 
| 1332         && inputs[1].isIndexablePrimitive(types); | 1333         && inputs[1].isIndexablePrimitive(types); | 
| 1333   } | 1334   } | 
| 1334 | 1335 | 
| 1335   HType computeDesiredTypeForInput(HInstruction input, | 1336   HType computeDesiredTypeForInput(HInstruction input, | 
| 1336                                    HTypeMap types, | 1337                                    HTypeMap types, | 
| 1337                                    Compiler compiler) { | 1338                                    Compiler compiler) { | 
| 1338     // TODO(ngeoffray): Move this logic into a different class that | 1339     // TODO(ngeoffray): Move this logic into a different class that | 
| 1339     // will know what type it wants for a given selector. | 1340     // will know what type it wants for a given selector. | 
| 1340     if (selector.kind != SelectorKind.INDEX) return HType.UNKNOWN; |  | 
| 1341     if (!isInterceptorCall) return HType.UNKNOWN; | 1341     if (!isInterceptorCall) return HType.UNKNOWN; | 
| 1342 | 1342 | 
| 1343     HInstruction index = inputs[2]; | 1343     if (selector.kind == SelectorKind.INDEX) { | 
| 1344     if (input == inputs[1] && | 1344       HInstruction index = inputs[2]; | 
| 1345         (index.isTypeUnknown(types) || index.isNumber(types))) { | 1345       if (input == inputs[1] && | 
| 1346       return HType.INDEXABLE_PRIMITIVE; | 1346           (index.isTypeUnknown(types) || index.isNumber(types))) { | 
|  | 1347         return selector.name == const SourceString('[]') | 
|  | 1348             ? HType.INDEXABLE_PRIMITIVE | 
|  | 1349             : HType.MUTABLE_ARRAY; | 
|  | 1350       } | 
|  | 1351       // The index should be an int when the receiver is a string or array. | 
|  | 1352       // However it turns out that inserting an integer check in the optimized | 
|  | 1353       // version is cheaper than having another bailout case. This is true, | 
|  | 1354       // because the integer check will simply throw if it fails. | 
|  | 1355       return HType.UNKNOWN; | 
|  | 1356     } else if (selector.kind == SelectorKind.OPERATOR) { | 
|  | 1357       HType propagatedType = types[this]; | 
|  | 1358       if (selector.name == const SourceString('-') && input == inputs[1]) { | 
|  | 1359         // If the outgoing type should be a number (integer, double or both) we | 
|  | 1360         // want the outgoing type to be the input too. | 
|  | 1361         // If we don't know the outgoing type we try to make it a number. | 
|  | 1362         if (propagatedType.isNumber()) return propagatedType; | 
|  | 1363         if (propagatedType.isUnknown()) return HType.NUMBER; | 
|  | 1364       } else if (selector.name == const SourceString('~') | 
|  | 1365                  && input == inputs[1]) { | 
|  | 1366         if (propagatedType.isUnknown() || propagatedType.isNumber()) { | 
|  | 1367           return HType.INTEGER; | 
|  | 1368         } | 
|  | 1369       } | 
|  | 1370       return HType.UNKNOWN; | 
| 1347     } | 1371     } | 
| 1348     // The index should be an int when the receiver is a string or array. | 1372     return HType.UNKNOWN; | 
| 1349     // However it turns out that inserting an integer check in the optimized | 1373   } | 
| 1350     // version is cheaper than having another bailout case. This is true, | 1374 | 
| 1351     // because the integer check will simply throw if it fails. | 1375   HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { | 
|  | 1376     // TODO(ngeoffray): Move this logic into a different class that | 
|  | 1377     // will know what type it has for a given selector. | 
|  | 1378     if (!isInterceptorCall) return HType.UNKNOWN; | 
|  | 1379 | 
|  | 1380     if (selector.kind == SelectorKind.OPERATOR) { | 
|  | 1381       if (selector.name == const SourceString('-')) { | 
|  | 1382         HType operandType = types[inputs[1]]; | 
|  | 1383         if (operandType.isNumber()) return operandType; | 
|  | 1384       } else if (selector.name == const SourceString('~')) { | 
|  | 1385         // All bitwise operations on primitive types either produce an | 
|  | 1386         // integer or throw an error. | 
|  | 1387         if (inputs[1].isPrimitive(types)) return HType.INTEGER; | 
|  | 1388       } | 
|  | 1389     } | 
| 1352     return HType.UNKNOWN; | 1390     return HType.UNKNOWN; | 
| 1353   } | 1391   } | 
| 1354 } | 1392 } | 
| 1355 | 1393 | 
| 1356 abstract class HInvokeDynamicField extends HInvokeDynamic { | 1394 abstract class HInvokeDynamicField extends HInvokeDynamic { | 
| 1357   final bool isSideEffectFree; | 1395   final bool isSideEffectFree; | 
| 1358   HInvokeDynamicField( | 1396   HInvokeDynamicField( | 
| 1359       Selector selector, Element element, List<HInstruction> inputs, | 1397       Selector selector, Element element, List<HInstruction> inputs, | 
| 1360       this.isSideEffectFree) | 1398       this.isSideEffectFree) | 
| 1361       : super(selector, element, inputs); | 1399       : super(selector, element, inputs); | 
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1833       : super(target, left, right); | 1871       : super(target, left, right); | 
| 1834   accept(HVisitor visitor) => visitor.visitBitXor(this); | 1872   accept(HVisitor visitor) => visitor.visitBitXor(this); | 
| 1835 | 1873 | 
| 1836   BinaryOperation operation(ConstantSystem constantSystem) | 1874   BinaryOperation operation(ConstantSystem constantSystem) | 
| 1837       => constantSystem.bitXor; | 1875       => constantSystem.bitXor; | 
| 1838   int typeCode() => HInstruction.BIT_XOR_TYPECODE; | 1876   int typeCode() => HInstruction.BIT_XOR_TYPECODE; | 
| 1839   bool typeEquals(other) => other is HBitXor; | 1877   bool typeEquals(other) => other is HBitXor; | 
| 1840   bool dataEquals(HInstruction other) => true; | 1878   bool dataEquals(HInstruction other) => true; | 
| 1841 } | 1879 } | 
| 1842 | 1880 | 
| 1843 abstract class HInvokeUnary extends HInvokeStatic { | 1881 abstract class HInvokeUnary extends HInstruction { | 
| 1844   HInvokeUnary(HStatic target, HInstruction input) | 1882   HInvokeUnary(HInstruction input) : super(<HInstruction>[input]); | 
| 1845       : super(<HInstruction>[target, input]); |  | 
| 1846 | 1883 | 
| 1847   HInstruction get operand => inputs[1]; | 1884   HInstruction get operand => inputs[0]; | 
| 1848 | 1885 | 
| 1849   void prepareGvn(HTypeMap types) { | 1886   void prepareGvn(HTypeMap types) { | 
| 1850     clearAllSideEffects(); | 1887     clearAllSideEffects(); | 
| 1851     // A unary arithmetic expression can take part in global value | 1888     setUseGvn(); | 
| 1852     // numbering and does not have any side-effects if its input is a |  | 
| 1853     // number. |  | 
| 1854     if (isBuiltin(types)) { |  | 
| 1855       setUseGvn(); |  | 
| 1856     } else { |  | 
| 1857       setAllSideEffects(); |  | 
| 1858     } |  | 
| 1859   } | 1889   } | 
| 1860 | 1890 | 
| 1861   bool isBuiltin(HTypeMap types) => operand.isNumber(types); |  | 
| 1862 |  | 
| 1863   HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { |  | 
| 1864     HType operandType = types[operand]; |  | 
| 1865     if (operandType.isNumber()) return operandType; |  | 
| 1866     return HType.UNKNOWN; |  | 
| 1867   } |  | 
| 1868 |  | 
| 1869   HType computeDesiredTypeForNonTargetInput(HInstruction input, |  | 
| 1870                                             HTypeMap types, |  | 
| 1871                                             Compiler compiler) { |  | 
| 1872     HType propagatedType = types[this]; |  | 
| 1873     // If the outgoing type should be a number (integer, double or both) we |  | 
| 1874     // want the outgoing type to be the input too. |  | 
| 1875     // If we don't know the outgoing type we try to make it a number. |  | 
| 1876     if (propagatedType.isNumber()) return propagatedType; |  | 
| 1877     if (propagatedType.isUnknown()) return HType.NUMBER; |  | 
| 1878     return HType.UNKNOWN; |  | 
| 1879   } |  | 
| 1880 |  | 
| 1881   HType computeLikelyType(HTypeMap types, Compiler compiler) => HType.NUMBER; |  | 
| 1882 |  | 
| 1883   UnaryOperation operation(ConstantSystem constantSystem); | 1891   UnaryOperation operation(ConstantSystem constantSystem); | 
| 1884 } | 1892 } | 
| 1885 | 1893 | 
| 1886 class HNegate extends HInvokeUnary { | 1894 class HNegate extends HInvokeUnary { | 
| 1887   HNegate(HStatic target, HInstruction input) : super(target, input); | 1895   HNegate(HInstruction input) : super(input); | 
| 1888   accept(HVisitor visitor) => visitor.visitNegate(this); | 1896   accept(HVisitor visitor) => visitor.visitNegate(this); | 
| 1889 | 1897 | 
|  | 1898   HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { | 
|  | 1899     return types[operand]; | 
|  | 1900   } | 
|  | 1901 | 
| 1890   UnaryOperation operation(ConstantSystem constantSystem) | 1902   UnaryOperation operation(ConstantSystem constantSystem) | 
| 1891       => constantSystem.negate; | 1903       => constantSystem.negate; | 
| 1892   int typeCode() => HInstruction.NEGATE_TYPECODE; | 1904   int typeCode() => HInstruction.NEGATE_TYPECODE; | 
| 1893   bool typeEquals(other) => other is HNegate; | 1905   bool typeEquals(other) => other is HNegate; | 
| 1894   bool dataEquals(HInstruction other) => true; | 1906   bool dataEquals(HInstruction other) => true; | 
| 1895 } | 1907 } | 
| 1896 | 1908 | 
| 1897 class HBitNot extends HInvokeUnary { | 1909 class HBitNot extends HInvokeUnary { | 
| 1898   HBitNot(HStatic target, HInstruction input) : super(target, input); | 1910   HBitNot(HInstruction input) : super(input); | 
| 1899   accept(HVisitor visitor) => visitor.visitBitNot(this); | 1911   accept(HVisitor visitor) => visitor.visitBitNot(this); | 
| 1900 | 1912 | 
| 1901   HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) { | 1913   HType get guaranteedType => HType.INTEGER; | 
| 1902     // All bitwise operations on primitive types either produce an |  | 
| 1903     // integer or throw an error. |  | 
| 1904     if (operand.isPrimitive(types)) return HType.INTEGER; |  | 
| 1905     return HType.UNKNOWN; |  | 
| 1906   } |  | 
| 1907 |  | 
| 1908   HType computeDesiredTypeForNonTargetInput(HInstruction input, |  | 
| 1909                                             HTypeMap types, |  | 
| 1910                                             Compiler compiler) { |  | 
| 1911     HType propagatedType = types[this]; |  | 
| 1912     // Bit operations only work on integers. If there is no desired output |  | 
| 1913     // type or if it as a number we want to get an integer as input. |  | 
| 1914     if (propagatedType.isUnknown() || propagatedType.isNumber()) { |  | 
| 1915       return HType.INTEGER; |  | 
| 1916     } |  | 
| 1917     return HType.UNKNOWN; |  | 
| 1918   } |  | 
| 1919 |  | 
| 1920   UnaryOperation operation(ConstantSystem constantSystem) | 1914   UnaryOperation operation(ConstantSystem constantSystem) | 
| 1921       => constantSystem.bitNot; | 1915       => constantSystem.bitNot; | 
| 1922   int typeCode() => HInstruction.BIT_NOT_TYPECODE; | 1916   int typeCode() => HInstruction.BIT_NOT_TYPECODE; | 
| 1923   bool typeEquals(other) => other is HBitNot; | 1917   bool typeEquals(other) => other is HBitNot; | 
| 1924   bool dataEquals(HInstruction other) => true; | 1918   bool dataEquals(HInstruction other) => true; | 
| 1925 } | 1919 } | 
| 1926 | 1920 | 
| 1927 class HExit extends HControlFlow { | 1921 class HExit extends HControlFlow { | 
| 1928   HExit() : super(const <HInstruction>[]); | 1922   HExit() : super(const <HInstruction>[]); | 
| 1929   toString() => 'exit'; | 1923   toString() => 'exit'; | 
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2478   } | 2472   } | 
| 2479 | 2473 | 
| 2480   HInstruction get receiver => inputs[0]; | 2474   HInstruction get receiver => inputs[0]; | 
| 2481   HInstruction get index => inputs[1]; | 2475   HInstruction get index => inputs[1]; | 
| 2482 | 2476 | 
| 2483   int typeCode() => HInstruction.INDEX_TYPECODE; | 2477   int typeCode() => HInstruction.INDEX_TYPECODE; | 
| 2484   bool typeEquals(HInstruction other) => other is HIndex; | 2478   bool typeEquals(HInstruction other) => other is HIndex; | 
| 2485   bool dataEquals(HIndex other) => true; | 2479   bool dataEquals(HIndex other) => true; | 
| 2486 } | 2480 } | 
| 2487 | 2481 | 
| 2488 class HIndexAssign extends HInvokeStatic { | 2482 class HIndexAssign extends HInstruction { | 
| 2489   HIndexAssign(HStatic target, | 2483   HIndexAssign(HInstruction receiver, | 
| 2490                HInstruction receiver, |  | 
| 2491                HInstruction index, | 2484                HInstruction index, | 
| 2492                HInstruction value) | 2485                HInstruction value) | 
| 2493       : super(<HInstruction>[target, receiver, index, value]); | 2486       : super(<HInstruction>[receiver, index, value]); | 
| 2494   toString() => 'index assign operator'; | 2487   String toString() => 'index assign operator'; | 
| 2495   accept(HVisitor visitor) => visitor.visitIndexAssign(this); | 2488   accept(HVisitor visitor) => visitor.visitIndexAssign(this); | 
| 2496 | 2489 | 
| 2497   HInstruction get receiver => inputs[1]; | 2490   HInstruction get receiver => inputs[0]; | 
| 2498   HInstruction get index => inputs[2]; | 2491   HInstruction get index => inputs[1]; | 
| 2499   HInstruction get value => inputs[3]; | 2492   HInstruction get value => inputs[2]; | 
| 2500 | 2493 | 
| 2501   void prepareGvn(HTypeMap types) { | 2494   void prepareGvn(HTypeMap types) { | 
| 2502     clearAllSideEffects(); | 2495     clearAllSideEffects(); | 
| 2503     if (isBuiltin(types)) { | 2496     setChangesIndex(); | 
| 2504       setChangesIndex(); |  | 
| 2505     } else { |  | 
| 2506       setAllSideEffects(); |  | 
| 2507     } |  | 
| 2508   } | 2497   } | 
| 2509 |  | 
| 2510   // Note, that we don't have a computeTypeFromInputTypes, since [HIndexAssign] |  | 
| 2511   // is never used as input. |  | 
| 2512 |  | 
| 2513   HType computeDesiredTypeForNonTargetInput(HInstruction input, |  | 
| 2514                                             HTypeMap types, |  | 
| 2515                                             Compiler compiler) { |  | 
| 2516     if (input == receiver && |  | 
| 2517         (index.isTypeUnknown(types) || index.isNumber(types))) { |  | 
| 2518       return HType.MUTABLE_ARRAY; |  | 
| 2519     } |  | 
| 2520     // The index should be an int when the receiver is a string or array. |  | 
| 2521     // However it turns out that inserting an integer check in the optimized |  | 
| 2522     // version is cheaper than having another bailout case. This is true, |  | 
| 2523     // because the integer check will simply throw if it fails. |  | 
| 2524     return HType.UNKNOWN; |  | 
| 2525   } |  | 
| 2526 |  | 
| 2527   bool isBuiltin(HTypeMap types) |  | 
| 2528       => receiver.isMutableArray(types) && index.isInteger(types); |  | 
| 2529   bool isJsStatement(HTypeMap types) => !isBuiltin(types); |  | 
| 2530 } | 2498 } | 
| 2531 | 2499 | 
| 2532 class HIs extends HInstruction { | 2500 class HIs extends HInstruction { | 
| 2533   final DartType typeExpression; | 2501   final DartType typeExpression; | 
| 2534   final bool nullOk; | 2502   final bool nullOk; | 
| 2535 | 2503 | 
| 2536   HIs.withArgumentChecks(this.typeExpression, | 2504   HIs.withArgumentChecks(this.typeExpression, | 
| 2537                          HInstruction expression, | 2505                          HInstruction expression, | 
| 2538                          List<HInstruction> checks, | 2506                          List<HInstruction> checks, | 
| 2539                          [this.nullOk = false]) | 2507                          [this.nullOk = false]) | 
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2947   HBasicBlock get start => expression.start; | 2915   HBasicBlock get start => expression.start; | 
| 2948   HBasicBlock get end { | 2916   HBasicBlock get end { | 
| 2949     // We don't create a switch block if there are no cases. | 2917     // We don't create a switch block if there are no cases. | 
| 2950     assert(!statements.isEmpty); | 2918     assert(!statements.isEmpty); | 
| 2951     return statements.last.end; | 2919     return statements.last.end; | 
| 2952   } | 2920   } | 
| 2953 | 2921 | 
| 2954   bool accept(HStatementInformationVisitor visitor) => | 2922   bool accept(HStatementInformationVisitor visitor) => | 
| 2955       visitor.visitSwitchInfo(this); | 2923       visitor.visitSwitchInfo(this); | 
| 2956 } | 2924 } | 
| OLD | NEW | 
|---|