Optimize `x + 0` pattern as early notNull coercion to speed up SDK loops
diff --git a/lib/runtime/dart/_interceptors.js b/lib/runtime/dart/_interceptors.js index bb2c84e..20e657f 100644 --- a/lib/runtime/dart/_interceptors.js +++ b/lib/runtime/dart/_interceptors.js
@@ -127,7 +127,8 @@ } [dartx.remove](element) { this[dartx.checkGrowable]('remove'); - for (let i = 0; i < dart.notNull(this[dartx.length]); i++) { + let length = dart.notNull(this[dartx.length]); + for (let i = 0; i < length; i++) { if (dart.equals(this[dartx.get](i), element)) { this.splice(i, 1); return true; @@ -162,8 +163,8 @@ } [dartx.forEach](f) { dart.as(f, dart.functionType(dart.void, [E])); - let length = this[dartx.length]; - for (let i = 0; i < dart.notNull(length); i++) { + let length = dart.notNull(this[dartx.length]); + for (let i = 0; i < length; i++) { f(dart.as(this[i], E)); if (length != this[dartx.length]) { dart.throw(new core.ConcurrentModificationError(this)); @@ -176,8 +177,9 @@ } [dartx.join](separator) { if (separator === void 0) separator = ""; - let list = core.List.new(this[dartx.length]); - for (let i = 0; i < dart.notNull(this[dartx.length]); i++) { + let length = dart.notNull(this[dartx.length]); + let list = core.List.new(length); + for (let i = 0; i < length; i++) { list[dartx.set](i, `${this[dartx.get](i)}`); } return list.join(separator); @@ -312,7 +314,8 @@ return _internal.IterableMixinWorkaround.lastIndexOfList(this, element, start); } [dartx.contains](other) { - for (let i = 0; i < dart.notNull(this[dartx.length]); i++) { + let length = dart.notNull(this[dartx.length]); + for (let i = 0; i < length; i++) { if (dart.equals(this[dartx.get](i), other)) return true; } return false; @@ -934,7 +937,8 @@ dart.throw(new core.RangeError.range(start, 0, string[dartx.length])); } if (dart.notNull(start) + dart.notNull(this[dartx.length]) > dart.notNull(string[dartx.length])) return null; - for (let i = 0; i < dart.notNull(this[dartx.length]); i++) { + let length = dart.notNull(this[dartx.length]); + for (let i = 0; i < length; i++) { if (string[dartx.codeUnitAt](dart.notNull(start) + i) != this[dartx.codeUnitAt](i)) { return null; }
diff --git a/lib/runtime/dart/_internal.js b/lib/runtime/dart/_internal.js index 4d761a9..3384998 100644 --- a/lib/runtime/dart/_internal.js +++ b/lib/runtime/dart/_internal.js
@@ -1785,8 +1785,8 @@ } forEach(f) { dart.as(f, dart.functionType(dart.void, [core.int, E])); - let length = this[_values][dartx.length]; - for (let i = 0; i < dart.notNull(length); i++) { + let length = dart.notNull(this[_values][dartx.length]); + for (let i = 0; i < length; i++) { f(i, this[_values][dartx.get](i)); if (length != this[_values][dartx.length]) { dart.throw(new core.ConcurrentModificationError(this[_values]));
diff --git a/lib/runtime/dart/_native_typed_data.js b/lib/runtime/dart/_native_typed_data.js index 418c77b..20b2e93 100644 --- a/lib/runtime/dart/_native_typed_data.js +++ b/lib/runtime/dart/_native_typed_data.js
@@ -130,7 +130,7 @@ this[_storage] = NativeFloat32List.new(dart.notNull(list[dartx.length]) * 4); for (let i = 0; i < dart.notNull(list[dartx.length]); i++) { let e = list[dartx.get](i); - this[_storage].set(i * 4 + 0, e.x); + this[_storage].set(i * 4, e.x); this[_storage].set(i * 4 + 1, e.y); this[_storage].set(i * 4 + 2, e.z); this[_storage].set(i * 4 + 3, e.w); @@ -185,7 +185,7 @@ } get(index) { this[_checkIndex](index, this.length); - let _x = this[_storage].get(dart.notNull(index) * 4 + 0); + let _x = this[_storage].get(dart.notNull(index) * 4); let _y = this[_storage].get(dart.notNull(index) * 4 + 1); let _z = this[_storage].get(dart.notNull(index) * 4 + 2); let _w = this[_storage].get(dart.notNull(index) * 4 + 3); @@ -193,7 +193,7 @@ } set(index, value) { this[_checkIndex](index, this.length); - this[_storage].set(dart.notNull(index) * 4 + 0, value.x); + this[_storage].set(dart.notNull(index) * 4, value.x); this[_storage].set(dart.notNull(index) * 4 + 1, value.y); this[_storage].set(dart.notNull(index) * 4 + 2, value.z); this[_storage].set(dart.notNull(index) * 4 + 3, value.w); @@ -236,7 +236,7 @@ this[_storage] = NativeInt32List.new(dart.notNull(list[dartx.length]) * 4); for (let i = 0; i < dart.notNull(list[dartx.length]); i++) { let e = list[dartx.get](i); - this[_storage].set(i * 4 + 0, e.x); + this[_storage].set(i * 4, e.x); this[_storage].set(i * 4 + 1, e.y); this[_storage].set(i * 4 + 2, e.z); this[_storage].set(i * 4 + 3, e.w); @@ -291,7 +291,7 @@ } get(index) { this[_checkIndex](index, this.length); - let _x = this[_storage].get(dart.notNull(index) * 4 + 0); + let _x = this[_storage].get(dart.notNull(index) * 4); let _y = this[_storage].get(dart.notNull(index) * 4 + 1); let _z = this[_storage].get(dart.notNull(index) * 4 + 2); let _w = this[_storage].get(dart.notNull(index) * 4 + 3); @@ -299,7 +299,7 @@ } set(index, value) { this[_checkIndex](index, this.length); - this[_storage].set(dart.notNull(index) * 4 + 0, value.x); + this[_storage].set(dart.notNull(index) * 4, value.x); this[_storage].set(dart.notNull(index) * 4 + 1, value.y); this[_storage].set(dart.notNull(index) * 4 + 2, value.z); this[_storage].set(dart.notNull(index) * 4 + 3, value.w); @@ -342,7 +342,7 @@ this[_storage] = NativeFloat64List.new(dart.notNull(list[dartx.length]) * 2); for (let i = 0; i < dart.notNull(list[dartx.length]); i++) { let e = list[dartx.get](i); - this[_storage].set(i * 2 + 0, e.x); + this[_storage].set(i * 2, e.x); this[_storage].set(i * 2 + 1, e.y); } } @@ -395,13 +395,13 @@ } get(index) { this[_checkIndex](index, this.length); - let _x = this[_storage].get(dart.notNull(index) * 2 + 0); + let _x = this[_storage].get(dart.notNull(index) * 2); let _y = this[_storage].get(dart.notNull(index) * 2 + 1); return typed_data.Float64x2.new(_x, _y); } set(index, value) { this[_checkIndex](index, this.length); - this[_storage].set(dart.notNull(index) * 2 + 0, value.x); + this[_storage].set(dart.notNull(index) * 2, value.x); this[_storage].set(dart.notNull(index) * 2 + 1, value.y); return value; }
diff --git a/lib/runtime/dart/collection.js b/lib/runtime/dart/collection.js index 5382f2b..f1a4d04 100644 --- a/lib/runtime/dart/collection.js +++ b/lib/runtime/dart/collection.js
@@ -1568,8 +1568,8 @@ } forEach(action) { dart.as(action, dart.functionType(dart.void, [E])); - let length = this.length; - for (let i = 0; i < dart.notNull(length); i++) { + let length = dart.notNull(this.length); + for (let i = 0; i < length; i++) { action(this.get(i)); if (length != this.length) { dart.throw(new core.ConcurrentModificationError(this)); @@ -1596,8 +1596,8 @@ return this.get(0); } contains(element) { - let length = this.length; - for (let i = 0; i < dart.notNull(this.length); i++) { + let length = dart.notNull(this.length); + for (let i = 0; i < length; i++) { if (dart.equals(this.get(i), element)) return true; if (length != this.length) { dart.throw(new core.ConcurrentModificationError(this)); @@ -1607,8 +1607,8 @@ } every(test) { dart.as(test, dart.functionType(core.bool, [E])); - let length = this.length; - for (let i = 0; i < dart.notNull(length); i++) { + let length = dart.notNull(this.length); + for (let i = 0; i < length; i++) { if (!dart.notNull(test(this.get(i)))) return false; if (length != this.length) { dart.throw(new core.ConcurrentModificationError(this)); @@ -1618,8 +1618,8 @@ } any(test) { dart.as(test, dart.functionType(core.bool, [E])); - let length = this.length; - for (let i = 0; i < dart.notNull(length); i++) { + let length = dart.notNull(this.length); + for (let i = 0; i < length; i++) { if (dart.notNull(test(this.get(i)))) return true; if (length != this.length) { dart.throw(new core.ConcurrentModificationError(this)); @@ -1631,8 +1631,8 @@ dart.as(test, dart.functionType(core.bool, [E])); let orElse = opts && 'orElse' in opts ? opts.orElse : null; dart.as(orElse, dart.functionType(E, [])); - let length = this.length; - for (let i = 0; i < dart.notNull(length); i++) { + let length = dart.notNull(this.length); + for (let i = 0; i < length; i++) { let element = this.get(i); if (dart.notNull(test(element))) return element; if (length != this.length) { @@ -1646,8 +1646,8 @@ dart.as(test, dart.functionType(core.bool, [E])); let orElse = opts && 'orElse' in opts ? opts.orElse : null; dart.as(orElse, dart.functionType(E, [])); - let length = this.length; - for (let i = dart.notNull(length) - 1; i >= 0; i--) { + let length = dart.notNull(this.length); + for (let i = length - 1; i >= 0; i--) { let element = this.get(i); if (dart.notNull(test(element))) return element; if (length != this.length) { @@ -1659,10 +1659,10 @@ } singleWhere(test) { dart.as(test, dart.functionType(core.bool, [E])); - let length = this.length; + let length = dart.notNull(this.length); let match = null; let matchFound = false; - for (let i = 0; i < dart.notNull(length); i++) { + for (let i = 0; i < length; i++) { let element = this.get(i); if (dart.notNull(test(element))) { if (matchFound) { @@ -1699,10 +1699,10 @@ } reduce(combine) { dart.as(combine, dart.functionType(E, [E, E])); - let length = this.length; + let length = dart.notNull(this.length); if (length == 0) dart.throw(_internal.IterableElementError.noElement()); let value = this.get(0); - for (let i = 1; i < dart.notNull(length); i++) { + for (let i = 1; i < length; i++) { value = combine(value, this.get(i)); if (length != this.length) { dart.throw(new core.ConcurrentModificationError(this)); @@ -1713,8 +1713,8 @@ fold(initialValue, combine) { dart.as(combine, dart.functionType(dart.dynamic, [dart.dynamic, E])); let value = initialValue; - let length = this.length; - for (let i = 0; i < dart.notNull(length); i++) { + let length = dart.notNull(this.length); + for (let i = 0; i < length; i++) { value = combine(value, this.get(i)); if (length != this.length) { dart.throw(new core.ConcurrentModificationError(this)); @@ -1738,21 +1738,23 @@ } toList(opts) { let growable = opts && 'growable' in opts ? opts.growable : true; + let length = dart.notNull(this.length); let result = null; if (dart.notNull(growable)) { result = core.List$(E).new(); - result[dartx.length] = this[dartx.length]; + result[dartx.length] = length; } else { - result = core.List$(E).new(this[dartx.length]); + result = core.List$(E).new(length); } - for (let i = 0; i < dart.notNull(this[dartx.length]); i++) { + for (let i = 0; i < length; i++) { result[dartx.set](i, this.get(i)); } return result; } toSet() { + let length = dart.notNull(this.length); let result = core.Set$(E).new(); - for (let i = 0; i < dart.notNull(this[dartx.length]); i++) { + for (let i = 0; i < length; i++) { result.add(this.get(i)); } return result; @@ -1776,10 +1778,11 @@ } } remove(element) { - for (let i = 0; i < dart.notNull(this.length); i++) { + let length = dart.notNull(this.length); + for (let i = 0; i < length; i++) { if (dart.equals(this.get(i), element)) { - this.setRange(i, dart.notNull(this.length) - 1, this, i + 1); - this.length = dart.notNull(this.length) - 1; + this.setRange(i, length - 1, this, i + 1); + this.length = length = length - 1; return true; } } @@ -1796,8 +1799,8 @@ static _filter(source, test, retainMatching) { dart.as(test, dart.functionType(core.bool, [dart.dynamic])); let retained = []; - let length = source[dartx.length]; - for (let i = 0; i < dart.notNull(length); i++) { + let length = dart.notNull(source[dartx.length]); + for (let i = 0; i < length; i++) { let element = source[dartx.get](i); if (dart.dcall(test, element) == retainMatching) { retained[dartx.add](element); @@ -1830,10 +1833,10 @@ shuffle(random) { if (random === void 0) random = null; if (random == null) random = math.Random.new(); - let length = this.length; - while (dart.notNull(length) > 1) { + let length = dart.notNull(this.length); + while (length > 1) { let pos = random.nextInt(length); - length = dart.notNull(length) - 1; + length = length - 1; let tmp = this.get(length); this.set(length, this.get(pos)); this.set(pos, tmp);
diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart index 7f9a743..716f039 100644 --- a/lib/src/codegen/js_codegen.dart +++ b/lib/src/codegen/js_codegen.dart
@@ -2443,6 +2443,15 @@ if (binaryOperationIsPrimitive(leftType, rightType) || leftType == _types.stringType && op.type == TokenType.PLUS) { + // special case for not-null coercion: `x + 0` becomes `dart.notNull(x)`. + // this pattern is used to speed up collection loops in the SDK, by + // coercing length to not-null outside the loop. + if (_isNumberInJS(leftType) && op.type == TokenType.PLUS) { + if (right is IntegerLiteral && right.value == 0 || + right is DoubleLiteral && right.value == 0.0) { + return notNull(left); + } + } // special cases where we inline the operation // these values are assumed to be non-null (determined by the checker) // TODO(jmesserly): it would be nice to just inline the method from core,
diff --git a/test/codegen/expect/notnull.js b/test/codegen/expect/notnull.js index bd94bc1..0595a69 100644 --- a/test/codegen/expect/notnull.js +++ b/test/codegen/expect/notnull.js
@@ -117,7 +117,7 @@ for (let i = 0, n = length(); i < dart.notNull(n); i++) { core.print(i + 1); } - for (let i = 0, n = dart.notNull(length()) + 0; i < n; i++) { + for (let i = 0, n = dart.notNull(length()); i < n; i++) { core.print(i + 1); } }
diff --git a/tool/input_sdk/lib/collection/list.dart b/tool/input_sdk/lib/collection/list.dart index c856de9..b0b10e2 100644 --- a/tool/input_sdk/lib/collection/list.dart +++ b/tool/input_sdk/lib/collection/list.dart
@@ -58,7 +58,7 @@ E elementAt(int index) => this[index]; void forEach(void action(E element)) { - int length = this.length; + int length = this.length + 0; for (int i = 0; i < length; i++) { action(this[i]); if (length != this.length) { @@ -88,8 +88,8 @@ } bool contains(Object element) { - int length = this.length; - for (int i = 0; i < this.length; i++) { + int length = this.length + 0; + for (int i = 0; i < length; i++) { if (this[i] == element) return true; if (length != this.length) { throw new ConcurrentModificationError(this); @@ -99,7 +99,7 @@ } bool every(bool test(E element)) { - int length = this.length; + int length = this.length + 0; for (int i = 0; i < length; i++) { if (!test(this[i])) return false; if (length != this.length) { @@ -110,7 +110,7 @@ } bool any(bool test(E element)) { - int length = this.length; + int length = this.length + 0; for (int i = 0; i < length; i++) { if (test(this[i])) return true; if (length != this.length) { @@ -121,7 +121,7 @@ } E firstWhere(bool test(E element), { E orElse() }) { - int length = this.length; + int length = this.length + 0; for (int i = 0; i < length; i++) { E element = this[i]; if (test(element)) return element; @@ -134,7 +134,7 @@ } E lastWhere(bool test(E element), { E orElse() }) { - int length = this.length; + int length = this.length + 0; for (int i = length - 1; i >= 0; i--) { E element = this[i]; if (test(element)) return element; @@ -147,7 +147,7 @@ } E singleWhere(bool test(E element)) { - int length = this.length; + int length = this.length + 0; E match = null; bool matchFound = false; for (int i = 0; i < length; i++) { @@ -181,7 +181,7 @@ new ExpandIterable<E, dynamic/*=T*/>(this, f); E reduce(E combine(E previousValue, E element)) { - int length = this.length; + int length = this.length + 0; if (length == 0) throw IterableElementError.noElement(); E value = this[0]; for (int i = 1; i < length; i++) { @@ -195,7 +195,7 @@ /*=T*/ fold/*<T>*/(var/*=T*/ initialValue, /*=T*/combine(var/*=T*/ previousValue, E element)) { var value = initialValue; - int length = this.length; + int length = this.length + 0; for (int i = 0; i < length; i++) { value = combine(value, this[i]); if (length != this.length) { @@ -218,6 +218,7 @@ } List<E> toList({ bool growable: true }) { + int length = this.length + 0; List<E> result; if (growable) { result = new List<E>()..length = length; @@ -231,6 +232,7 @@ } Set<E> toSet() { + int length = this.length + 0; Set<E> result = new Set<E>(); for (int i = 0; i < length; i++) { result.add(this[i]); @@ -250,10 +252,11 @@ } bool remove(Object element) { - for (int i = 0; i < this.length; i++) { + int length = this.length + 0; + for (int i = 0; i < length; i++) { if (this[i] == element) { - this.setRange(i, this.length - 1, this, i + 1); - this.length -= 1; + this.setRange(i, length - 1, this, i + 1); + this.length = length = length - 1; return true; } } @@ -272,7 +275,7 @@ bool test(var element), bool retainMatching) { List retained = []; - int length = source.length; + int length = source.length + 0; for (int i = 0; i < length; i++) { var element = source[i]; if (test(element) == retainMatching) { @@ -307,7 +310,7 @@ void shuffle([Random random]) { if (random == null) random = new Random(); - int length = this.length; + int length = this.length + 0; while (length > 1) { int pos = random.nextInt(length); length -= 1;
diff --git a/tool/input_sdk/lib/internal/list.dart b/tool/input_sdk/lib/internal/list.dart index 3e87762..fecca5a 100644 --- a/tool/input_sdk/lib/internal/list.dart +++ b/tool/input_sdk/lib/internal/list.dart
@@ -260,7 +260,7 @@ bool containsKey(Object key) => key is int && key >= 0 && key < length; void forEach(void f(int key, E value)) { - int length = _values.length; + int length = _values.length + 0; for (int i = 0; i < length; i++) { f(i, _values[i]); if (length != _values.length) {
diff --git a/tool/input_sdk/patch/collection_patch.dart b/tool/input_sdk/patch/collection_patch.dart index c06f552..b81a249 100644 --- a/tool/input_sdk/patch/collection_patch.dart +++ b/tool/input_sdk/patch/collection_patch.dart
@@ -252,7 +252,7 @@ for (int i = 0; i < entries; i++) { var key = JS('String', '#[#]', names, i); var bucket = JS('var', '#[#]', rest, key); - int length = JS('int', '#.length', bucket); + int length = JS('int', '#.length', bucket) + 0; for (int i = 0; i < length; i += 2) { var key = JS('var', '#[#]', bucket, i); JS('void', '#[#] = #', result, index, key); @@ -342,7 +342,7 @@ int _findBucketIndex(var bucket, var key) { if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); + int length = JS('int', '#.length', bucket) + 0; for (int i = 0; i < length; i += 2) { if (JS('var', '#[#]', bucket, i) == key) return i; } @@ -373,7 +373,7 @@ int _findBucketIndex(var bucket, var key) { if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); + int length = JS('int', '#.length', bucket) + 0; for (int i = 0; i < length; i += 2) { if (identical(JS('var', '#[#]', bucket, i), key)) return i; } @@ -417,7 +417,7 @@ int _findBucketIndex(var bucket, var key) { if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); + int length = JS('int', '#.length', bucket) + 0; for (int i = 0; i < length; i += 2) { if (_equals(JS('var', '#[#]', bucket, i), key)) return i; }
diff --git a/tool/input_sdk/private/js_array.dart b/tool/input_sdk/private/js_array.dart index de54d2f..64aafa4 100644 --- a/tool/input_sdk/private/js_array.dart +++ b/tool/input_sdk/private/js_array.dart
@@ -82,7 +82,8 @@ bool remove(Object element) { checkGrowable('remove'); - for (int i = 0; i < this.length; i++) { + int length = this.length + 0; + for (int i = 0; i < length; i++) { if (this[i] == element) { JS('var', r'#.splice(#, 1)', this, i); return true; @@ -120,7 +121,7 @@ } void forEach(void f(E element)) { - int length = this.length; + int length = this.length + 0; for (int i = 0; i < length; i++) { f(JS('', '#[#]', this, i)); if (length != this.length) { @@ -134,8 +135,9 @@ } String join([String separator = ""]) { - var list = new List(this.length); - for (int i = 0; i < this.length; i++) { + int length = this.length + 0; + var list = new List(length); + for (int i = 0; i < length; i++) { list[i] = "${this[i]}"; } return JS('String', "#.join(#)", list, separator); @@ -274,6 +276,7 @@ } bool contains(Object other) { + int length = this.length + 0; for (int i = 0; i < length; i++) { if (this[i] == other) return true; }
diff --git a/tool/input_sdk/private/js_string.dart b/tool/input_sdk/private/js_string.dart index 4007b2f..9492761 100644 --- a/tool/input_sdk/private/js_string.dart +++ b/tool/input_sdk/private/js_string.dart
@@ -36,7 +36,8 @@ } if (start + this.length > string.length) return null; // TODO(lrn): See if this can be optimized. - for (int i = 0; i < this.length; i++) { + int length = this.length + 0; + for (int i = 0; i < length; i++) { if (string.codeUnitAt(start + i) != this.codeUnitAt(i)) { return null; }
diff --git a/tool/sdk_expected_errors.txt b/tool/sdk_expected_errors.txt index 2412ff6..863f047 100644 --- a/tool/sdk_expected_errors.txt +++ b/tool/sdk_expected_errors.txt
@@ -4,12 +4,12 @@ warning: [DOWN_CAST_COMPOSITE] args (dynamic) will need runtime check to cast to type List<String> (dart:_isolate_helper, line 839, col 37) warning: [DOWN_CAST_COMPOSITE] msg['args'] (dynamic) will need runtime check to cast to type List<String> (dart:_isolate_helper, line 886, col 11) warning: [DOWN_CAST_COMPOSITE] JS('var', r'#.pop()', this) (dynamic) will need runtime check to cast to type E (dart:_interceptors/js_array.dart, line 80, col 12) -warning: [DOWN_CAST_COMPOSITE] JS('', '#[#]', this, i) (dynamic) will need runtime check to cast to type E (dart:_interceptors/js_array.dart, line 125, col 9) -warning: [DOWN_CAST_COMPOSITE] JS('var', '#[#]', this, index) (dynamic) will need runtime check to cast to type E (dart:_interceptors/js_array.dart, line 313, col 12) +warning: [DOWN_CAST_COMPOSITE] JS('', '#[#]', this, i) (dynamic) will need runtime check to cast to type E (dart:_interceptors/js_array.dart, line 126, col 9) +warning: [DOWN_CAST_COMPOSITE] JS('var', '#[#]', this, index) (dynamic) will need runtime check to cast to type E (dart:_interceptors/js_array.dart, line 316, col 12) warning: [DOWN_CAST_COMPOSITE] charCodes (dynamic) will need runtime check to cast to type List<int> (dart:_js_helper, line 265, col 31) warning: [DOWN_CAST_COMPOSITE] JS('', '#.value', ret) (dynamic) will need runtime check to cast to type E (dart:_js_helper, line 780, col 16) -warning: [DOWN_CAST_COMPOSITE] JS('JSExtendableArray', r'#.split(#)', this, pattern) (dynamic) will need runtime check to cast to type List<String> (dart:_interceptors/js_string.dart, line 86, col 14) -warning: [DOWN_CAST_COMPOSITE] JS('JSExtendableArray', r'#.split(#)', this, re) (dynamic) will need runtime check to cast to type List<String> (dart:_interceptors/js_string.dart, line 89, col 14) +warning: [DOWN_CAST_COMPOSITE] JS('JSExtendableArray', r'#.split(#)', this, pattern) (dynamic) will need runtime check to cast to type List<String> (dart:_interceptors/js_string.dart, line 87, col 14) +warning: [DOWN_CAST_COMPOSITE] JS('JSExtendableArray', r'#.split(#)', this, re) (dynamic) will need runtime check to cast to type List<String> (dart:_interceptors/js_string.dart, line 90, col 14) warning: [DOWN_CAST_COMPOSITE] JS('JSExtendableArray|Null', r'#.exec(#)', _nativeRegExp, checkString(string)) (dynamic) will need runtime check to cast to type List<String> (dart:_js_helper/regexp_helper.dart, line 108, col 22) warning: [DOWN_CAST_COMPOSITE] match (List<dynamic>) will need runtime check to cast to type List<String> (dart:_js_helper/regexp_helper.dart, line 140, col 43) warning: [DOWN_CAST_COMPOSITE] match (List<dynamic>) will need runtime check to cast to type List<String> (dart:_js_helper/regexp_helper.dart, line 152, col 43) @@ -147,10 +147,10 @@ warning: [DOWN_CAST_COMPOSITE] current (_LinkedListLink) will need runtime check to cast to type E (dart:collection/linked_list.dart, line 134, col 14) warning: [DOWN_CAST_COMPOSITE] _next (_LinkedListLink) will need runtime check to cast to type E (dart:collection/linked_list.dart, line 192, col 16) warning: [DOWN_CAST_COMPOSITE] _next (_LinkedListLink) will need runtime check to cast to type E (dart:collection/linked_list.dart, line 249, col 16) -warning: [DOWN_CAST_COMPOSITE] compare == null ? Comparable.compare : compare (Function) will need runtime check to cast to type (dynamic, dynamic) → int (dart:collection/list.dart, line 305, col 21) -warning: [DOWN_CAST_COMPOSITE] iterable (Iterable<E>) will need runtime check to cast to type List<dynamic> (dart:collection/list.dart, line 365, col 19) -warning: [DOWN_CAST_COMPOSITE] otherList[otherStart + i] (dynamic) will need runtime check to cast to type E (dart:collection/list.dart, line 377, col 27) -warning: [DOWN_CAST_COMPOSITE] otherList[otherStart + i] (dynamic) will need runtime check to cast to type E (dart:collection/list.dart, line 381, col 27) +warning: [DOWN_CAST_COMPOSITE] compare == null ? Comparable.compare : compare (Function) will need runtime check to cast to type (dynamic, dynamic) → int (dart:collection/list.dart, line 308, col 21) +warning: [DOWN_CAST_COMPOSITE] iterable (Iterable<E>) will need runtime check to cast to type List<dynamic> (dart:collection/list.dart, line 368, col 19) +warning: [DOWN_CAST_COMPOSITE] otherList[otherStart + i] (dynamic) will need runtime check to cast to type E (dart:collection/list.dart, line 380, col 27) +warning: [DOWN_CAST_COMPOSITE] otherList[otherStart + i] (dynamic) will need runtime check to cast to type E (dart:collection/list.dart, line 384, col 27) warning: [DOWN_CAST_COMPOSITE] _map[_map.keys.first] (dynamic) will need runtime check to cast to type V (dart:collection/maps.dart, line 122, col 18) warning: [DOWN_CAST_COMPOSITE] _map[_map.keys.single] (dynamic) will need runtime check to cast to type V (dart:collection/maps.dart, line 123, col 19) warning: [DOWN_CAST_COMPOSITE] _map[_map.keys.last] (dynamic) will need runtime check to cast to type V (dart:collection/maps.dart, line 124, col 17)