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)