Version 2.0.0-dev.32.0

Merge commit '0e48dce272ba37f25bf6d715861f99d770550d31' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba4829f..29e2bfd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -274,15 +274,22 @@
 * Pub will now automatically retry HTTP requests that fail with a 502, 503, of
   504 error code ([issue 1556][pub#1556]).
 
+* Pub now caches compiled packages and snapshots in the `.dart_tool/pub`
+  directory, rather than the `.pub` directory ([issue 1795][pub#1795]).
+
 * Emit exit code 66 when a path dependency doesn't exist ([issue 1747][pub#1747]).
 
 * `pub publish` throws a more explicit error if the `publish_to` field isn't an
   absolute URL ([issue 1769][pub#1769]).
 
+* `pub publish` provides more detailed information if the package is too large
+  to upload.
+
 [pub#1556]: https://github.com/dart-lang/pub/issues/1556
 [pub#1747]: https://github.com/dart-lang/pub/issues/1747
 [pub#1769]: https://github.com/dart-lang/pub/issues/1769
 [pub#1775]: https://github.com/dart-lang/pub/issues/1775
+[pub#1795]: https://github.com/dart-lang/pub/issues/1795
 
 ##### Bug Fixes
 
diff --git a/DEPS b/DEPS
index f7bafe3..07dc0fc 100644
--- a/DEPS
+++ b/DEPS
@@ -58,8 +58,8 @@
   "barback_tag" : "@0.15.2+14",
   "bazel_worker_tag": "@v0.1.9",
   "boolean_selector_tag" : "@1.0.2",
-  "boringssl_gen_rev": "@d2b56d1b7657e52eb5a1f075968c773aa3e53614",
-  "boringssl_rev" : "@d519bf6be0b447fb80fbc539d4bff4479b5482a2",
+  "boringssl_gen_rev": "@39762c7f9ee4d828ff212838fae79528b94d5443",
+  "boringssl_rev" : "@a62dbf88d8a3c04446db833a1eb80a620cb1514d",
   "charcode_tag": "@v1.1.1",
   "chrome_rev" : "@19997",
   "cli_util_tag" : "@0.1.2+1",
@@ -83,7 +83,7 @@
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
   "dart_style_tag": "@1.0.10",  # Please see the note above before updating.
 
-  "dartdoc_tag" : "@v0.16.0",
+  "dartdoc_tag" : "@v0.17.0",
   "fixnum_tag": "@0.10.5",
   "func_rev": "@25eec48146a58967d75330075ab376b3838b18a8",
   "glob_tag": "@1.1.5",
@@ -115,7 +115,7 @@
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "@1.3.4",
   "protobuf_tag": "@0.7.0",
-  "pub_rev": "@64c5f40adf6828da1b63320dd39bcedbef1354c6",
+  "pub_rev": "@73ff0d3d9f80f60d41e3135ac44597d011abb4f3",
   "pub_semver_tag": "@1.3.2",
   "quiver_tag": "@0.28.0",
   "resource_rev":"@af5a5bf65511943398146cf146e466e5f0b95cb9",
diff --git a/pkg/analysis_server/benchmark/perf/memory_tests.dart b/pkg/analysis_server/benchmark/perf/memory_tests.dart
index ed9a3d1..6803a4e 100644
--- a/pkg/analysis_server/benchmark/perf/memory_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/memory_tests.dart
@@ -34,9 +34,15 @@
   static const int vmServicePort = 12345;
 
   int getMemoryUsage() {
-    ProcessResult result = _run('curl', <String>[
-      'localhost:$vmServicePort/_getAllocationProfile\?isolateId=isolates/root\&gc=full'
-    ]);
+    String vmService =
+        'http://localhost:$vmServicePort/_getAllocationProfile\?isolateId=isolates/root\&gc=full';
+    ProcessResult result;
+    if (Platform.isWindows) {
+      result = _run(
+          'powershell', <String>['-Command', '(curl "$vmService").Content']);
+    } else {
+      result = _run('curl', <String>[vmService]);
+    }
     Map json = JSON.decode(result.stdout);
     Map heaps = json['result']['heaps'];
     int newSpace = heaps['new']['used'];
@@ -53,7 +59,7 @@
 
   /**
    * The server is automatically started before every test.
-   */
+  */
   @override
   Future setUp({bool useCFE: false}) {
     onAnalysisErrors.listen((AnalysisErrorsParams params) {
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index d9cad4b..cf044e0 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -208,6 +208,8 @@
 const String EXECUTION_RESPONSE_MAP_URI_URI = 'uri';
 const String FLUTTER_NOTIFICATION_OUTLINE = 'flutter.outline';
 const String FLUTTER_NOTIFICATION_OUTLINE_FILE = 'file';
+const String FLUTTER_NOTIFICATION_OUTLINE_INSTRUMENTATION_EDITS =
+    'instrumentationEdits';
 const String FLUTTER_NOTIFICATION_OUTLINE_OUTLINE = 'outline';
 const String FLUTTER_REQUEST_SET_SUBSCRIPTIONS = 'flutter.setSubscriptions';
 const String FLUTTER_REQUEST_SET_SUBSCRIPTIONS_SUBSCRIPTIONS = 'subscriptions';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 3616da5..78949dd 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -10959,6 +10959,10 @@
  *   "parentAssociationLabel": optional String
  *   "variableName": optional String
  *   "children": optional List<FlutterOutline>
+ *   "id": optional int
+ *   "renderConstructor": optional String
+ *   "stateOffset": optional int
+ *   "stateLength": optional int
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -10984,6 +10988,14 @@
 
   List<FlutterOutline> _children;
 
+  int _id;
+
+  String _renderConstructor;
+
+  int _stateOffset;
+
+  int _stateLength;
+
   /**
    * The kind of the node.
    */
@@ -11127,6 +11139,72 @@
     this._children = value;
   }
 
+  /**
+   * If the node is a widget, and it is instrumented, the unique identifier of
+   * this widget, that can be used to associate rendering information with this
+   * node.
+   */
+  int get id => _id;
+
+  /**
+   * If the node is a widget, and it is instrumented, the unique identifier of
+   * this widget, that can be used to associate rendering information with this
+   * node.
+   */
+  void set id(int value) {
+    this._id = value;
+  }
+
+  /**
+   * If the node is a widget class that can be rendered for IDE, the name of
+   * the constructor that should be used to instantiate the widget. Empty
+   * string for default constructor. Absent if the node is not a widget class
+   * that can be rendered.
+   */
+  String get renderConstructor => _renderConstructor;
+
+  /**
+   * If the node is a widget class that can be rendered for IDE, the name of
+   * the constructor that should be used to instantiate the widget. Empty
+   * string for default constructor. Absent if the node is not a widget class
+   * that can be rendered.
+   */
+  void set renderConstructor(String value) {
+    this._renderConstructor = value;
+  }
+
+  /**
+   * If the node is a StatefulWidget that can be rendered, and its State class
+   * is defined in the same file, the offset of the State class code in the
+   * file.
+   */
+  int get stateOffset => _stateOffset;
+
+  /**
+   * If the node is a StatefulWidget that can be rendered, and its State class
+   * is defined in the same file, the offset of the State class code in the
+   * file.
+   */
+  void set stateOffset(int value) {
+    this._stateOffset = value;
+  }
+
+  /**
+   * If the node is a StatefulWidget that can be rendered, and its State class
+   * is defined in the same file, the length of the State class code in the
+   * file.
+   */
+  int get stateLength => _stateLength;
+
+  /**
+   * If the node is a StatefulWidget that can be rendered, and its State class
+   * is defined in the same file, the length of the State class code in the
+   * file.
+   */
+  void set stateLength(int value) {
+    this._stateLength = value;
+  }
+
   FlutterOutline(FlutterOutlineKind kind, int offset, int length,
       {String label,
       Element dartElement,
@@ -11134,7 +11212,11 @@
       String className,
       String parentAssociationLabel,
       String variableName,
-      List<FlutterOutline> children}) {
+      List<FlutterOutline> children,
+      int id,
+      String renderConstructor,
+      int stateOffset,
+      int stateLength}) {
     this.kind = kind;
     this.offset = offset;
     this.length = length;
@@ -11145,6 +11227,10 @@
     this.parentAssociationLabel = parentAssociationLabel;
     this.variableName = variableName;
     this.children = children;
+    this.id = id;
+    this.renderConstructor = renderConstructor;
+    this.stateOffset = stateOffset;
+    this.stateLength = stateLength;
   }
 
   factory FlutterOutline.fromJson(
@@ -11214,6 +11300,25 @@
             (String jsonPath, Object json) =>
                 new FlutterOutline.fromJson(jsonDecoder, jsonPath, json));
       }
+      int id;
+      if (json.containsKey("id")) {
+        id = jsonDecoder.decodeInt(jsonPath + ".id", json["id"]);
+      }
+      String renderConstructor;
+      if (json.containsKey("renderConstructor")) {
+        renderConstructor = jsonDecoder.decodeString(
+            jsonPath + ".renderConstructor", json["renderConstructor"]);
+      }
+      int stateOffset;
+      if (json.containsKey("stateOffset")) {
+        stateOffset = jsonDecoder.decodeInt(
+            jsonPath + ".stateOffset", json["stateOffset"]);
+      }
+      int stateLength;
+      if (json.containsKey("stateLength")) {
+        stateLength = jsonDecoder.decodeInt(
+            jsonPath + ".stateLength", json["stateLength"]);
+      }
       return new FlutterOutline(kind, offset, length,
           label: label,
           dartElement: dartElement,
@@ -11221,7 +11326,11 @@
           className: className,
           parentAssociationLabel: parentAssociationLabel,
           variableName: variableName,
-          children: children);
+          children: children,
+          id: id,
+          renderConstructor: renderConstructor,
+          stateOffset: stateOffset,
+          stateLength: stateLength);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "FlutterOutline", json);
     }
@@ -11257,6 +11366,18 @@
       result["children"] =
           children.map((FlutterOutline value) => value.toJson()).toList();
     }
+    if (id != null) {
+      result["id"] = id;
+    }
+    if (renderConstructor != null) {
+      result["renderConstructor"] = renderConstructor;
+    }
+    if (stateOffset != null) {
+      result["stateOffset"] = stateOffset;
+    }
+    if (stateLength != null) {
+      result["stateLength"] = stateLength;
+    }
     return result;
   }
 
@@ -11280,7 +11401,11 @@
           parentAssociationLabel == other.parentAssociationLabel &&
           variableName == other.variableName &&
           listEqual(children, other.children,
-              (FlutterOutline a, FlutterOutline b) => a == b);
+              (FlutterOutline a, FlutterOutline b) => a == b) &&
+          id == other.id &&
+          renderConstructor == other.renderConstructor &&
+          stateOffset == other.stateOffset &&
+          stateLength == other.stateLength;
     }
     return false;
   }
@@ -11298,6 +11423,10 @@
     hash = JenkinsSmiHash.combine(hash, parentAssociationLabel.hashCode);
     hash = JenkinsSmiHash.combine(hash, variableName.hashCode);
     hash = JenkinsSmiHash.combine(hash, children.hashCode);
+    hash = JenkinsSmiHash.combine(hash, id.hashCode);
+    hash = JenkinsSmiHash.combine(hash, renderConstructor.hashCode);
+    hash = JenkinsSmiHash.combine(hash, stateOffset.hashCode);
+    hash = JenkinsSmiHash.combine(hash, stateLength.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
@@ -11605,6 +11734,7 @@
  * {
  *   "file": FilePath
  *   "outline": FlutterOutline
+ *   "instrumentationEdits": List<SourceEdit>
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -11614,6 +11744,8 @@
 
   FlutterOutline _outline;
 
+  List<SourceEdit> _instrumentationEdits;
+
   /**
    * The file with which the outline is associated.
    */
@@ -11640,9 +11772,28 @@
     this._outline = value;
   }
 
-  FlutterOutlineParams(String file, FlutterOutline outline) {
+  /**
+   * If the file has Flutter widgets that can be rendered, the list of edits
+   * that should be applied to the file to instrument widgets and associate
+   * them with outline nodes.
+   */
+  List<SourceEdit> get instrumentationEdits => _instrumentationEdits;
+
+  /**
+   * If the file has Flutter widgets that can be rendered, the list of edits
+   * that should be applied to the file to instrument widgets and associate
+   * them with outline nodes.
+   */
+  void set instrumentationEdits(List<SourceEdit> value) {
+    assert(value != null);
+    this._instrumentationEdits = value;
+  }
+
+  FlutterOutlineParams(String file, FlutterOutline outline,
+      List<SourceEdit> instrumentationEdits) {
     this.file = file;
     this.outline = outline;
+    this.instrumentationEdits = instrumentationEdits;
   }
 
   factory FlutterOutlineParams.fromJson(
@@ -11664,7 +11815,17 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "outline");
       }
-      return new FlutterOutlineParams(file, outline);
+      List<SourceEdit> instrumentationEdits;
+      if (json.containsKey("instrumentationEdits")) {
+        instrumentationEdits = jsonDecoder.decodeList(
+            jsonPath + ".instrumentationEdits",
+            json["instrumentationEdits"],
+            (String jsonPath, Object json) =>
+                new SourceEdit.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "instrumentationEdits");
+      }
+      return new FlutterOutlineParams(file, outline, instrumentationEdits);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "flutter.outline params", json);
     }
@@ -11680,6 +11841,8 @@
     Map<String, dynamic> result = {};
     result["file"] = file;
     result["outline"] = outline.toJson();
+    result["instrumentationEdits"] =
+        instrumentationEdits.map((SourceEdit value) => value.toJson()).toList();
     return result;
   }
 
@@ -11693,7 +11856,10 @@
   @override
   bool operator ==(other) {
     if (other is FlutterOutlineParams) {
-      return file == other.file && outline == other.outline;
+      return file == other.file &&
+          outline == other.outline &&
+          listEqual(instrumentationEdits, other.instrumentationEdits,
+              (SourceEdit a, SourceEdit b) => a == b);
     }
     return false;
   }
@@ -11703,6 +11869,7 @@
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, file.hashCode);
     hash = JenkinsSmiHash.combine(hash, outline.hashCode);
+    hash = JenkinsSmiHash.combine(hash, instrumentationEdits.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
index f526036..bf407e1 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
@@ -15,7 +15,7 @@
         new FlutterOutlineComputer(file, content, lineInfo, dartUnit);
     protocol.FlutterOutline outline = computer.compute();
     // send notification
-    var params = new protocol.FlutterOutlineParams(file, outline);
+    var params = new protocol.FlutterOutlineParams(file, outline, []);
     server.sendNotification(params.toNotification());
   });
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
index b8b7f58c..de77d4c 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
@@ -149,7 +149,15 @@
     }
     String uriPrefix = parentUri == '.' ? '' : parentUri;
 
-    String dirPath = resContext.normalize(parentUri);
+    // Only handle file uris in the format file:///xxx or /xxx
+    String parentUriScheme = Uri.parse(parentUri).scheme;
+    if (!parentUri.startsWith('file://') && parentUriScheme != '') {
+      return;
+    }
+
+    String dirPath = resProvider.pathContext.fromUri(parentUri);
+    dirPath = resContext.normalize(dirPath);
+
     if (resContext.isRelative(dirPath)) {
       String sourceDirPath = resContext.dirname(source.fullName);
       if (resContext.isAbsolute(sourceDirPath)) {
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 94c8884..57cd8ee 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -250,15 +250,18 @@
   }
 
   test_import_uri_with_trailing() {
-    newFile('/project/bin/testA.dart', content: 'library libA;');
+    final filePath = '/project/bin/testA.dart';
+    final incompleteImportText = convertPathForImport('/project/bin/t');
+    newFile(filePath, content: 'library libA;');
     addTestFile('''
-      import '/project/bin/t^.dart';
-      main() {}''');
+    import "$incompleteImportText^.dart";
+    main() {}''');
     return getSuggestions().then((_) {
-      expect(replacementOffset, equals(completionOffset - 14));
-      expect(replacementLength, equals(5 + 14));
+      expect(replacementOffset,
+          equals(completionOffset - incompleteImportText.length));
+      expect(replacementLength, equals(5 + incompleteImportText.length));
       assertHasResult(
-          CompletionSuggestionKind.IMPORT, '/project/bin/testA.dart');
+          CompletionSuggestionKind.IMPORT, convertPathForImport(filePath));
       assertNoResult('test');
     });
   }
@@ -664,7 +667,7 @@
   test_partFile() {
     newFile('/project/bin/testA.dart', content: '''
       library libA;
-      part "$testFile";
+      part "${convertPathForImport(testFile)}";
       import 'dart:html';
       class A { }
     ''');
@@ -687,7 +690,7 @@
       class A { }''');
     addTestFile('''
       library libA;
-      part "/testA.dart";
+      part "${convertPathForImport("/testA.dart")}";
       import 'dart:html';
       main() {^}
     ''');
diff --git a/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart b/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart
index ff147fc..c75655b 100644
--- a/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:path/path.dart' show join;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -35,7 +36,8 @@
     expect(lastAnalyzedFiles, isNotEmpty);
     expect(lastAnalyzedFiles, contains(pathname));
     expect(
-        lastAnalyzedFiles.any((String file) => file.endsWith('core/core.dart')),
+        lastAnalyzedFiles
+            .any((String file) => file.endsWith(join('core', 'core.dart'))),
         true);
   }
 }
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index ab48dde..33968b2 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -2168,6 +2168,12 @@
    * outline: FlutterOutline
    *
    *   The outline associated with the file.
+   *
+   * instrumentationEdits: List<SourceEdit>
+   *
+   *   If the file has Flutter widgets that can be rendered, the list of edits
+   *   that should be applied to the file to instrument widgets and associate
+   *   them with outline nodes.
    */
   Stream<FlutterOutlineParams> onFlutterOutline;
 
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 93cc065..aaaa3d9 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -484,6 +484,10 @@
  *   "parentAssociationLabel": optional String
  *   "variableName": optional String
  *   "children": optional List<FlutterOutline>
+ *   "id": optional int
+ *   "renderConstructor": optional String
+ *   "stateOffset": optional int
+ *   "stateLength": optional int
  * }
  */
 final Matcher isFlutterOutline =
@@ -498,7 +502,11 @@
           "className": isString,
           "parentAssociationLabel": isString,
           "variableName": isString,
-          "children": isListOf(isFlutterOutline)
+          "children": isListOf(isFlutterOutline),
+          "id": isInt,
+          "renderConstructor": isString,
+          "stateOffset": isInt,
+          "stateLength": isInt
         }));
 
 /**
@@ -2447,11 +2455,15 @@
  * {
  *   "file": FilePath
  *   "outline": FlutterOutline
+ *   "instrumentationEdits": List<SourceEdit>
  * }
  */
-final Matcher isFlutterOutlineParams = new LazyMatcher(() =>
-    new MatchesJsonObject("flutter.outline params",
-        {"file": isFilePath, "outline": isFlutterOutline}));
+final Matcher isFlutterOutlineParams =
+    new LazyMatcher(() => new MatchesJsonObject("flutter.outline params", {
+          "file": isFilePath,
+          "outline": isFlutterOutline,
+          "instrumentationEdits": isListOf(isSourceEdit)
+        }));
 
 /**
  * flutter.setSubscriptions params
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index f0c3285..40da511 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -227,7 +227,12 @@
   }
 
   CompletionSuggestion assertSuggestEnumConst(String completion,
-      {int relevance: DART_RELEVANCE_DEFAULT, bool isDeprecated: false}) {
+      {int relevance: DART_RELEVANCE_DEFAULT,
+      bool isDeprecated: false,
+      bool hasTypeBoost: false}) {
+    if (hasTypeBoost) {
+      relevance += DART_RELEVANCE_BOOST_TYPE;
+    }
     CompletionSuggestion suggestion = assertSuggest(completion,
         relevance: relevance, isDeprecated: isDeprecated);
     expect(suggestion.completion, completion);
diff --git a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
index 9c62da3..6ae7e6b 100644
--- a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
@@ -1866,10 +1866,8 @@
     await computeSuggestions();
 
     assertSuggestEnum('E');
-    assertSuggestEnumConst('E.one',
-        relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_TYPE);
-    assertSuggestEnumConst('E.two',
-        relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_TYPE);
+    assertSuggestEnumConst('E.one', hasTypeBoost: true);
+    assertSuggestEnumConst('E.two', hasTypeBoost: true);
 
     assertSuggestEnum('F');
     assertSuggestEnumConst('F.three');
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index 8650537..fb5a912 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -20,7 +20,14 @@
 class LocalReferenceContributorTest extends DartCompletionContributorTest {
   CompletionSuggestion assertSuggestLocalVariable(
       String name, String returnType,
-      {int relevance: DART_RELEVANCE_LOCAL_VARIABLE}) {
+      {int relevance: DART_RELEVANCE_LOCAL_VARIABLE,
+      bool hasTypeBoost: false,
+      bool hasSubtypeBoost: false}) {
+    if (hasTypeBoost) {
+      relevance += DART_RELEVANCE_BOOST_TYPE;
+    } else if (hasSubtypeBoost) {
+      relevance += DART_RELEVANCE_BOOST_SUBTYPE;
+    }
     // Local variables should only be suggested by LocalReferenceContributor
     CompletionSuggestion cs = assertSuggest(name,
         csKind: CompletionSuggestionKind.INVOCATION, relevance: relevance);
@@ -645,7 +652,7 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertSuggestLocalVariable('a', 'int');
+    assertSuggestLocalVariable('a', 'int', hasTypeBoost: true);
     assertSuggestFunction('main', null,
         relevance: DART_RELEVANCE_LOCAL_FUNCTION);
     assertSuggestClass('A');
@@ -790,7 +797,11 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertSuggestLocalVariable('a', 'int');
+    // We should not have the type boost, but we do.
+    // The reason is that coveringNode is VariableDeclaration, and the
+    // entity is BinaryExpression, so the expected type is int.
+    // It would be more correct to use BinaryExpression as coveringNode.
+    assertSuggestLocalVariable('a', 'int', hasTypeBoost: true);
     assertNotSuggested('Object');
     assertNotSuggested('b');
   }
@@ -803,8 +814,7 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertSuggestLocalVariable('a', 'int',
-        relevance: DART_RELEVANCE_LOCAL_VARIABLE + DART_RELEVANCE_BOOST_TYPE);
+    assertSuggestLocalVariable('a', 'int', hasSubtypeBoost: true);
     assertNotSuggested('Object');
     assertNotSuggested('b');
     assertNotSuggested('==');
@@ -2168,10 +2178,91 @@
     await computeSuggestions();
 
     assertSuggestEnum('E');
-    assertSuggestEnumConst('E.one',
-        relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_TYPE);
-    assertSuggestEnumConst('E.two',
-        relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_TYPE);
+    assertSuggestEnumConst('E.one', hasTypeBoost: true);
+    assertSuggestEnumConst('E.two', hasTypeBoost: true);
+
+    assertSuggestEnum('F');
+    assertSuggestEnumConst('F.three');
+    assertSuggestEnumConst('F.four');
+  }
+
+  test_enum_filter_assignment() async {
+    addTestSource('''
+enum E { one, two }
+enum F { three, four }
+
+main() {
+  E e;
+  e = ^;
+}
+''');
+    await computeSuggestions();
+
+    assertSuggestEnum('E');
+    assertSuggestEnumConst('E.one', hasTypeBoost: true);
+    assertSuggestEnumConst('E.two', hasTypeBoost: true);
+
+    assertSuggestEnum('F');
+    assertSuggestEnumConst('F.three');
+    assertSuggestEnumConst('F.four');
+  }
+
+  test_enum_filter_binaryEquals() async {
+    addTestSource('''
+enum E { one, two }
+enum F { three, four }
+
+main(E e) {
+  e == ^;
+}
+''');
+    await computeSuggestions();
+
+    assertSuggestEnum('E');
+    assertSuggestEnumConst('E.one', hasTypeBoost: true);
+    assertSuggestEnumConst('E.two', hasTypeBoost: true);
+
+    assertSuggestEnum('F');
+    assertSuggestEnumConst('F.three');
+    assertSuggestEnumConst('F.four');
+  }
+
+  test_enum_filter_switchCase() async {
+    addTestSource('''
+enum E { one, two }
+enum F { three, four }
+
+main(E e) {
+  switch (e) {
+    case ^
+  }
+}
+''');
+    await computeSuggestions();
+
+    assertSuggestEnum('E');
+    assertSuggestEnumConst('E.one', hasTypeBoost: true);
+    assertSuggestEnumConst('E.two', hasTypeBoost: true);
+
+    assertSuggestEnum('F');
+    assertSuggestEnumConst('F.three');
+    assertSuggestEnumConst('F.four');
+  }
+
+  test_enum_filter_variableDeclaration() async {
+    addTestSource('''
+enum E { one, two }
+enum F { three, four }
+
+main() {
+  E e = ^;
+}
+''');
+    await computeSuggestions();
+
+    assertSuggestEnum('E');
+    assertSuggestEnumConst('E.one', hasTypeBoost: true);
+    assertSuggestEnumConst('E.two', hasTypeBoost: true);
 
     assertSuggestEnum('F');
     assertSuggestEnumConst('F.three');
@@ -4197,11 +4288,9 @@
 
     assertSuggestFunction('g', 'dynamic',
         relevance: DART_RELEVANCE_LOCAL_FUNCTION);
-    assertSuggestLocalVariable('t', 'dynamic',
-        relevance: DART_RELEVANCE_LOCAL_VARIABLE);
+    assertSuggestLocalVariable('t', 'dynamic');
     assertSuggestParameter('x', 'int', relevance: DART_RELEVANCE_PARAMETER);
-    assertSuggestLocalVariable('bar', 'dynamic',
-        relevance: DART_RELEVANCE_LOCAL_VARIABLE);
+    assertSuggestLocalVariable('bar', 'dynamic');
     assertNotSuggested('String');
   }
 
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/FlutterOutline.java b/pkg/analysis_server/tool/spec/generated/java/types/FlutterOutline.java
index 9a18b64..8be67a3 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/FlutterOutline.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/FlutterOutline.java
@@ -93,9 +93,34 @@
   private final List<FlutterOutline> children;
 
   /**
+   * If the node is a widget, and it is instrumented, the unique identifier of this widget, that can
+   * be used to associate rendering information with this node.
+   */
+  private final Integer id;
+
+  /**
+   * If the node is a widget class that can be rendered for IDE, the name of the constructor that
+   * should be used to instantiate the widget. Empty string for default constructor. Absent if the
+   * node is not a widget class that can be rendered.
+   */
+  private final String renderConstructor;
+
+  /**
+   * If the node is a StatefulWidget that can be rendered, and its State class is defined in the same
+   * file, the offset of the State class code in the file.
+   */
+  private final Integer stateOffset;
+
+  /**
+   * If the node is a StatefulWidget that can be rendered, and its State class is defined in the same
+   * file, the length of the State class code in the file.
+   */
+  private final Integer stateLength;
+
+  /**
    * Constructor for {@link FlutterOutline}.
    */
-  public FlutterOutline(String kind, int offset, int length, String label, Element dartElement, List<FlutterOutlineAttribute> attributes, String className, String parentAssociationLabel, String variableName, List<FlutterOutline> children) {
+  public FlutterOutline(String kind, int offset, int length, String label, Element dartElement, List<FlutterOutlineAttribute> attributes, String className, String parentAssociationLabel, String variableName, List<FlutterOutline> children, Integer id, String renderConstructor, Integer stateOffset, Integer stateLength) {
     this.kind = kind;
     this.offset = offset;
     this.length = length;
@@ -106,6 +131,10 @@
     this.parentAssociationLabel = parentAssociationLabel;
     this.variableName = variableName;
     this.children = children;
+    this.id = id;
+    this.renderConstructor = renderConstructor;
+    this.stateOffset = stateOffset;
+    this.stateLength = stateLength;
   }
 
   @Override
@@ -122,7 +151,11 @@
         ObjectUtilities.equals(other.className, className) &&
         ObjectUtilities.equals(other.parentAssociationLabel, parentAssociationLabel) &&
         ObjectUtilities.equals(other.variableName, variableName) &&
-        ObjectUtilities.equals(other.children, children);
+        ObjectUtilities.equals(other.children, children) &&
+        ObjectUtilities.equals(other.id, id) &&
+        ObjectUtilities.equals(other.renderConstructor, renderConstructor) &&
+        ObjectUtilities.equals(other.stateOffset, stateOffset) &&
+        ObjectUtilities.equals(other.stateLength, stateLength);
     }
     return false;
   }
@@ -138,7 +171,11 @@
     String parentAssociationLabel = jsonObject.get("parentAssociationLabel") == null ? null : jsonObject.get("parentAssociationLabel").getAsString();
     String variableName = jsonObject.get("variableName") == null ? null : jsonObject.get("variableName").getAsString();
     List<FlutterOutline> children = jsonObject.get("children") == null ? null : FlutterOutline.fromJsonArray(jsonObject.get("children").getAsJsonArray());
-    return new FlutterOutline(kind, offset, length, label, dartElement, attributes, className, parentAssociationLabel, variableName, children);
+    Integer id = jsonObject.get("id") == null ? null : jsonObject.get("id").getAsInt();
+    String renderConstructor = jsonObject.get("renderConstructor") == null ? null : jsonObject.get("renderConstructor").getAsString();
+    Integer stateOffset = jsonObject.get("stateOffset") == null ? null : jsonObject.get("stateOffset").getAsInt();
+    Integer stateLength = jsonObject.get("stateLength") == null ? null : jsonObject.get("stateLength").getAsInt();
+    return new FlutterOutline(kind, offset, length, label, dartElement, attributes, className, parentAssociationLabel, variableName, children, id, renderConstructor, stateOffset, stateLength);
   }
 
   public static List<FlutterOutline> fromJsonArray(JsonArray jsonArray) {
@@ -185,6 +222,14 @@
   }
 
   /**
+   * If the node is a widget, and it is instrumented, the unique identifier of this widget, that can
+   * be used to associate rendering information with this node.
+   */
+  public Integer getId() {
+    return id;
+  }
+
+  /**
    * The kind of the node.
    */
   public String getKind() {
@@ -224,6 +269,31 @@
   }
 
   /**
+   * If the node is a widget class that can be rendered for IDE, the name of the constructor that
+   * should be used to instantiate the widget. Empty string for default constructor. Absent if the
+   * node is not a widget class that can be rendered.
+   */
+  public String getRenderConstructor() {
+    return renderConstructor;
+  }
+
+  /**
+   * If the node is a StatefulWidget that can be rendered, and its State class is defined in the same
+   * file, the length of the State class code in the file.
+   */
+  public Integer getStateLength() {
+    return stateLength;
+  }
+
+  /**
+   * If the node is a StatefulWidget that can be rendered, and its State class is defined in the same
+   * file, the offset of the State class code in the file.
+   */
+  public Integer getStateOffset() {
+    return stateOffset;
+  }
+
+  /**
    * If FlutterOutlineKind.VARIABLE, the name of the variable.
    */
   public String getVariableName() {
@@ -243,6 +313,10 @@
     builder.append(parentAssociationLabel);
     builder.append(variableName);
     builder.append(children);
+    builder.append(id);
+    builder.append(renderConstructor);
+    builder.append(stateOffset);
+    builder.append(stateLength);
     return builder.toHashCode();
   }
 
@@ -280,6 +354,18 @@
       }
       jsonObject.add("children", jsonArrayChildren);
     }
+    if (id != null) {
+      jsonObject.addProperty("id", id);
+    }
+    if (renderConstructor != null) {
+      jsonObject.addProperty("renderConstructor", renderConstructor);
+    }
+    if (stateOffset != null) {
+      jsonObject.addProperty("stateOffset", stateOffset);
+    }
+    if (stateLength != null) {
+      jsonObject.addProperty("stateLength", stateLength);
+    }
     return jsonObject;
   }
 
@@ -306,7 +392,15 @@
     builder.append("variableName=");
     builder.append(variableName + ", ");
     builder.append("children=");
-    builder.append(StringUtils.join(children, ", "));
+    builder.append(StringUtils.join(children, ", ") + ", ");
+    builder.append("id=");
+    builder.append(id + ", ");
+    builder.append("renderConstructor=");
+    builder.append(renderConstructor + ", ");
+    builder.append("stateOffset=");
+    builder.append(stateOffset + ", ");
+    builder.append("stateLength=");
+    builder.append(stateLength);
     builder.append("]");
     return builder.toString();
   }
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index cab50c6..0de9134 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -2699,6 +2699,16 @@
           The outline associated with the file.
         </p>
       </field>
+      <field name="instrumentationEdits">
+        <list>
+          <ref>SourceEdit</ref>
+        </list>
+        <p>
+          If the file has Flutter widgets that can be rendered, the list
+          of edits that should be applied to the file to instrument widgets and
+          associate them with outline nodes.
+        </p>
+      </field>
     </params>
   </notification>
 </domain>
@@ -3135,6 +3145,39 @@
           children.
         </p>
       </field>
+      <field name="id" optional="true">
+        <ref>int</ref>
+        <p>
+          If the node is a widget, and it is instrumented, the unique identifier
+          of this widget, that can be used to associate rendering information
+          with this node.
+        </p>
+      </field>
+      <field name="renderConstructor" optional="true">
+        <ref>String</ref>
+        <p>
+          If the node is a widget class that can be rendered for IDE, the name
+          of the constructor that should be used to instantiate the widget.
+          Empty string for default constructor. Absent if the node is not a
+          widget class that can be rendered.
+        </p>
+      </field>
+      <field name="stateOffset" optional="true">
+        <ref>int</ref>
+        <p>
+          If the node is a StatefulWidget that can be rendered, and its State
+          class is defined in the same file, the offset of the State class code
+          in the file.
+        </p>
+      </field>
+      <field name="stateLength" optional="true">
+        <ref>int</ref>
+        <p>
+          If the node is a StatefulWidget that can be rendered, and its State
+          class is defined in the same file, the length of the State class code
+          in the file.
+        </p>
+      </field>
     </object>
   </type>
   <type name="FlutterOutlineAttribute" experimental="true">
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index 4f0729c..69d76ad 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -172,6 +172,16 @@
    */
   DartType substitute2(
       List<DartType> argumentTypes, List<DartType> parameterTypes);
+
+  /// Indicates whether `this` represents a type that is equivalent to `dest`.
+  ///
+  /// This is different from `operator==`.  Consider for example:
+  ///
+  ///     typedef void F<T>(); // T not used!
+  ///
+  /// `operator==` would consider F<int> and F<bool> to be different types;
+  /// `isEquivalentTo` considers them to be equivalent.
+  bool isEquivalentTo(DartType dest);
 }
 
 /**
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 95df0b9..724bc66 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -172,6 +172,7 @@
   CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS,
   CompileTimeErrorCode.MIXIN_INFERENCE_INCONSISTENT_MATCHING_CLASSES,
   CompileTimeErrorCode.MIXIN_INFERENCE_NO_MATCHING_CLASS,
+  CompileTimeErrorCode.MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION,
   CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT,
   CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS,
   CompileTimeErrorCode.MIXIN_OF_ENUM,
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 67fe7c13..62345fc 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -774,6 +774,35 @@
   }
 
   @override
+  bool isEquivalentTo(DartType other) {
+    if (other is FunctionTypeImpl) {
+      if (typeFormals.length != other.typeFormals.length) {
+        return false;
+      }
+      // `<T>T -> T` should be equal to `<U>U -> U`
+      // To test this, we instantiate both types with the same (unique) type
+      // variables, and see if the result is equal.
+      if (typeFormals.isNotEmpty) {
+        List<DartType> freshVariables =
+            relateTypeFormals(this, other, (t, s, _, __) => t == s);
+        if (freshVariables == null) {
+          return false;
+        }
+        return instantiate(freshVariables)
+            .isEquivalentTo(other.instantiate(freshVariables));
+      }
+
+      return returnType.isEquivalentTo(other.returnType) &&
+          TypeImpl.equivalentArrays(
+              normalParameterTypes, other.normalParameterTypes) &&
+          TypeImpl.equivalentArrays(
+              optionalParameterTypes, other.optionalParameterTypes) &&
+          _equivalent(namedParameterTypes, other.namedParameterTypes);
+    }
+    return false;
+  }
+
+  @override
   bool operator ==(Object object) {
     if (object is FunctionTypeImpl) {
       if (typeFormals.length != object.typeFormals.length) {
@@ -1384,6 +1413,31 @@
     }
     return true;
   }
+
+  /**
+   * Return `true` if all of the name/type pairs in the first map ([firstTypes])
+   * are equivalent to the corresponding name/type pairs in the second map
+   * ([secondTypes]). The maps are expected to iterate over their entries in the
+   * same order in which those entries were added to the map.
+   */
+  static bool _equivalent(
+      Map<String, DartType> firstTypes, Map<String, DartType> secondTypes) {
+    if (secondTypes.length != firstTypes.length) {
+      return false;
+    }
+    Iterator<String> firstKeys = firstTypes.keys.iterator;
+    Iterator<String> secondKeys = secondTypes.keys.iterator;
+    while (firstKeys.moveNext() && secondKeys.moveNext()) {
+      String firstKey = firstKeys.current;
+      String secondKey = secondKeys.current;
+      TypeImpl firstType = firstTypes[firstKey];
+      TypeImpl secondType = secondTypes[secondKey];
+      if (firstKey != secondKey || !firstType.isEquivalentTo(secondType)) {
+        return false;
+      }
+    }
+    return true;
+  }
 }
 
 /**
@@ -1669,6 +1723,18 @@
   }
 
   @override
+  bool isEquivalentTo(DartType other) {
+    if (identical(other, this)) {
+      return true;
+    }
+    if (other is InterfaceTypeImpl) {
+      return (element == other.element) &&
+          TypeImpl.equivalentArrays(typeArguments, other.typeArguments);
+    }
+    return false;
+  }
+
+  @override
   void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes) {
     if (visitedTypes.add(this)) {
       buffer.write(name);
@@ -2521,6 +2587,9 @@
    */
   final Element _element;
 
+  @override
+  bool isEquivalentTo(DartType other) => this == other;
+
   /**
    * The name of this type, or `null` if the type does not have a name.
    */
@@ -2704,6 +2773,31 @@
   }
 
   /**
+   * Return `true` if corresponding elements of the [first] and [second] lists
+   * of type arguments are all equivalent.
+   */
+  static bool equivalentArrays(List<DartType> first, List<DartType> second) {
+    if (first.length != second.length) {
+      return false;
+    }
+    for (int i = 0; i < first.length; i++) {
+      if (first[i] == null) {
+        AnalysisEngine.instance.logger
+            .logInformation('Found null type argument in TypeImpl.equalArrays');
+        return second[i] == null;
+      } else if (second[i] == null) {
+        AnalysisEngine.instance.logger
+            .logInformation('Found null type argument in TypeImpl.equalArrays');
+        return false;
+      }
+      if (!first[i].isEquivalentTo(second[i])) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
    * Return a list containing the results of using the given [argumentTypes] and
    * [parameterTypes] to perform a substitution on all of the given [types].
    *
@@ -2772,6 +2866,24 @@
     return false;
   }
 
+  @override
+  bool isEquivalentTo(DartType other) {
+    if (other is TypeParameterTypeImpl && element == other.element) {
+      if (_comparingBounds) {
+        // If we're comparing bounds already, then we only need type variable
+        // equality.
+        return true;
+      }
+      _comparingBounds = true;
+      try {
+        return bound.isEquivalentTo(other.bound);
+      } finally {
+        _comparingBounds = false;
+      }
+    }
+    return false;
+  }
+
   /**
    * Append a textual representation of this type to the given [buffer]. The set
    * of [visitedTypes] is used to prevent infinite recursion.
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 29e93e1..c3cdad5 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -1701,6 +1701,13 @@
           "the base class does not implement the mixin's supertype "
           "constraint '{1}'");
 
+  static const CompileTimeErrorCode MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION =
+      const CompileTimeErrorCode(
+          'MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION',
+          "Type parameters could not be inferred for the mixin '{0}' because "
+          "no type parameter substitution could be found matching the mixin's "
+          "supertype constraints");
+
   /**
    * 9 Mixins: It is a compile-time error if a mixin is derived from a class
    * whose superclass is not Object.
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index a5e5ca7..e9fed4b 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -20,6 +20,7 @@
         optional,
         Parser;
 import 'package:front_end/src/fasta/scanner.dart' hide StringToken;
+import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
 import 'package:front_end/src/scanner/token.dart'
     show
         StringToken,
@@ -39,6 +40,7 @@
         messageDirectiveAfterDeclaration,
         messageFieldInitializerOutsideConstructor,
         messageIllegalAssignmentToNonAssignable,
+        messageInterpolationInUri,
         messageMissingAssignableSelector,
         messageNativeClauseShouldBeAnnotation,
         messageStaticConstructor;
@@ -1583,6 +1585,16 @@
 
     StringLiteral libraryUri = pop();
     StringLiteral value = popIfNotNull(equalSign);
+    if (value is StringInterpolation) {
+      for (var child in value.childEntities) {
+        if (child is InterpolationExpression) {
+          // This error is reported in OutlineBuilder.endLiteralString
+          handleRecoverableError(
+              messageInterpolationInUri, child.beginToken, child.endToken);
+          break;
+        }
+      }
+    }
     DottedName name = pop();
     push(ast.configuration(ifKeyword, leftParen, name, equalSign, value,
         leftParen?.endGroup, libraryUri));
@@ -1831,9 +1843,13 @@
       return;
     }
     debugEvent("Error: ${message.message}");
-    int offset = startToken.offset;
-    int length = endToken.end - offset;
-    addCompileTimeError(message, offset, length);
+    if (message.code.analyzerCode == null && startToken is ErrorToken) {
+      translateErrorToken(startToken, errorReporter.reportScannerError);
+    } else {
+      int offset = startToken.offset;
+      int length = endToken.end - offset;
+      addCompileTimeError(message, offset, length);
+    }
   }
 
   @override
@@ -2186,8 +2202,7 @@
       if (parameters?.parameters != null) {
         parameters.parameters.forEach((FormalParameter param) {
           if (param is FieldFormalParameter) {
-            // Added comment in OutlineBuilder.endMethod at the location
-            // where this error could be reported.
+            // This error is reported in the BodyBuilder.endFormalParameter.
             handleRecoverableError(messageFieldInitializerOutsideConstructor,
                 param.thisKeyword, param.thisKeyword);
           }
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index 81e09c5..df8586b 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -286,6 +286,10 @@
         errorReporter?.reportErrorForOffset(
             ScannerErrorCode.ILLEGAL_CHARACTER, offset, length);
         return;
+      case "INITIALIZED_VARIABLE_IN_FOR_EACH":
+        errorReporter?.reportErrorForOffset(
+            ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, offset, length);
+        return;
       case "INVALID_ASSIGNMENT":
         var type1 = arguments['type'];
         var type2 = arguments['type2'];
@@ -295,6 +299,10 @@
             length,
             [type1, type2]);
         return;
+      case "INVALID_LITERAL_IN_CONFIGURATION":
+        errorReporter?.reportErrorForOffset(
+            ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, offset, length);
+        return;
       case "INVALID_AWAIT_IN_FOR":
         errorReporter?.reportErrorForOffset(
             ParserErrorCode.INVALID_AWAIT_IN_FOR, offset, length);
@@ -610,6 +618,13 @@
     reportByCode(code.analyzerCode, offset, length, message);
   }
 
+  void reportScannerError(
+      ScannerErrorCode errorCode, int offset, List<Object> arguments) {
+    // TODO(danrubel): update client to pass length in addition to offset.
+    int length = 1;
+    errorReporter?.reportErrorForOffset(errorCode, offset, length, arguments);
+  }
+
   void _reportByCode(
       ErrorCode errorCode, Message message, int offset, int length) {
     if (errorReporter != null) {
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 41b1d43..abd1238 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -6206,6 +6206,7 @@
       NamedCompilationUnitMember node, WithClause withClause) {
     if (withClause == null) return;
     if (!_options.enableSuperMixins) return;
+    if (!_options.strongMode) return;
     ClassElement classElement = node.element;
     var type = classElement.type;
     var supertype = classElement.supertype;
@@ -6216,10 +6217,26 @@
       if (typeName.typeArguments != null) continue;
       var mixinElement = typeName.name.staticElement;
       if (mixinElement is ClassElement) {
-        var mixinSupertypeConstraint = mixinElement.supertype;
-        if (mixinSupertypeConstraint.element.typeParameters.isNotEmpty) {
-          _findInterfaceTypeForMixin(
-              typeName, mixinSupertypeConstraint, supertypesForMixinInference);
+        var mixinSupertypeConstraints =
+            _typeSystem.gatherMixinSupertypeConstraints(mixinElement);
+        if (mixinSupertypeConstraints.isNotEmpty) {
+          var matchingInterfaceTypes = _findInterfaceTypesForConstraints(
+              typeName, mixinSupertypeConstraints, supertypesForMixinInference);
+          if (matchingInterfaceTypes != null) {
+            // Try to pattern match matchingInterfaceType against
+            // mixinSupertypeConstraint to find the correct set of type
+            // parameters to apply to the mixin.
+            var matchedType = _typeSystem.matchSupertypeConstraints(
+                mixinElement,
+                mixinSupertypeConstraints,
+                matchingInterfaceTypes);
+            if (matchedType == null) {
+              _errorReporter.reportErrorForToken(
+                  CompileTimeErrorCode.MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION,
+                  typeName.name.beginToken,
+                  [typeName]);
+            }
+          }
         }
         ClassElementImpl.collectAllSupertypes(
             supertypesForMixinInference, mixinElement.type, type);
@@ -6343,7 +6360,25 @@
         isDeclarationCast: isDeclarationCast);
   }
 
-  void _findInterfaceTypeForMixin(TypeName mixin,
+  List<InterfaceType> _findInterfaceTypesForConstraints(
+      TypeName mixin,
+      List<InterfaceType> supertypeConstraints,
+      List<InterfaceType> interfaceTypes) {
+    var result = <InterfaceType>[];
+    for (var constraint in supertypeConstraints) {
+      var interfaceType =
+          _findInterfaceTypeForMixin(mixin, constraint, interfaceTypes);
+      if (interfaceType == null) {
+        // No matching interface type found, so inference fails.  The error has
+        // already been reported.
+        return null;
+      }
+      result.add(interfaceType);
+    }
+    return result;
+  }
+
+  InterfaceType _findInterfaceTypeForMixin(TypeName mixin,
       InterfaceType supertypeConstraint, List<InterfaceType> interfaceTypes) {
     var element = supertypeConstraint.element;
     InterfaceType foundInterfaceType;
@@ -6367,6 +6402,7 @@
           mixin.name.beginToken,
           [mixin, supertypeConstraint]);
     }
+    return foundInterfaceType;
   }
 
   MethodElement _findOverriddenMemberThatMustCallSuper(MethodDeclaration node) {
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index fb56381..d580ab9 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -9787,6 +9787,7 @@
     element.declaredReturnType = _computeReturnType(node.returnType);
     element.type = new FunctionTypeImpl(element);
     _inferSetterReturnType(element);
+    _inferOperatorReturnType(element);
     if (element is PropertyAccessorElement) {
       PropertyAccessorElement accessor = element as PropertyAccessorElement;
       PropertyInducingElementImpl variable =
@@ -10043,6 +10044,20 @@
   }
 
   /**
+   * In strong mode we infer "void" as the return type of operator []= (as void
+   * is the only legal return type for []=). This allows us to give better
+   * errors later if an invalid type is returned.
+   */
+  void _inferOperatorReturnType(ExecutableElementImpl element) {
+    if (_strongMode &&
+        element.isOperator &&
+        element.name == '[]=' &&
+        element.hasImplicitReturnType) {
+      element.declaredReturnType = VoidTypeImpl.instance;
+    }
+  }
+
+  /**
    * Record that the static type of the given node is the given type.
    *
    * @param expression the node whose type is to be recorded
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 41f0e15..a206cdf 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -1112,6 +1112,44 @@
    */
   bool get isStrong;
 
+  List<InterfaceType> gatherMixinSupertypeConstraints(
+      ClassElement mixinElement) {
+    var mixinSupertypeConstraints = <InterfaceType>[];
+    void addIfGeneric(InterfaceType type) {
+      if (type.element.typeParameters.isNotEmpty) {
+        mixinSupertypeConstraints.add(type);
+      }
+    }
+
+    addIfGeneric(mixinElement.supertype);
+    mixinElement.mixins.forEach(addIfGeneric);
+    return mixinSupertypeConstraints;
+  }
+
+  /// Attempts to find the appropriate substitution for [typeParameters] that can
+  /// be applied to [src] to make it equal to [dest].  If no such substitution can
+  /// be found, `null` is returned.
+  InterfaceType matchSupertypeConstraints(
+      ClassElement mixinElement, List<DartType> srcs, List<DartType> dests) {
+    var typeParameters = mixinElement.typeParameters;
+    var inferrer = new _GenericInferrer(typeProvider, this, typeParameters);
+    for (int i = 0; i < srcs.length; i++) {
+      inferrer.constrainReturnType(srcs[i], dests[i]);
+      inferrer.constrainReturnType(dests[i], srcs[i]);
+    }
+    var result = inferrer.infer(mixinElement.type, typeParameters,
+        considerExtendsClause: false);
+    for (int i = 0; i < srcs.length; i++) {
+      if (!srcs[i]
+          .substitute2(result.typeArguments, mixinElement.type.typeArguments)
+          .isEquivalentTo(dests[i])) {
+        // Failed to find an appropriate substitution
+        return null;
+      }
+    }
+    return result;
+  }
+
   /**
    * The provider of types for the system
    */
@@ -1711,7 +1749,8 @@
   /// including argument types, and must not conclude `?` for any type formal.
   T infer<T extends ParameterizedType>(
       T genericType, List<TypeParameterElement> typeFormals,
-      {ErrorReporter errorReporter,
+      {bool considerExtendsClause: true,
+      ErrorReporter errorReporter,
       AstNode errorNode,
       bool downwardsInferPhase: false}) {
     var fnTypeParams = TypeParameterTypeImpl.getTypes(typeFormals);
@@ -1731,7 +1770,7 @@
 
       var typeParamBound = typeParam.bound;
       _TypeConstraint extendsClause;
-      if (!typeParamBound.isDynamic) {
+      if (considerExtendsClause && !typeParamBound.isDynamic) {
         extendsClause = new _TypeConstraint.fromExtends(typeParam,
             typeParam.bound.substitute2(inferredTypes, fnTypeParams));
       }
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 6a75797..759c3b4 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -671,12 +671,15 @@
         var mixin = _computeInterfaceType(entity);
         var mixinElement = mixin.element;
         var slot = entity.refinedSlot;
-        if (slot != 0 && mixinElement.typeParameters.isNotEmpty) {
+        if (slot != 0 &&
+            mixinElement.typeParameters.isNotEmpty &&
+            library._linker.strongMode) {
           CompilationUnitElementForLink enclosingElement =
               this.enclosingElement;
           if (enclosingElement is CompilationUnitElementInBuildUnit) {
-            var mixinSupertypeConstraint = mixinElement.supertype;
-            if (mixinSupertypeConstraint.element.typeParameters.isNotEmpty) {
+            var mixinSupertypeConstraints = context.typeSystem
+                .gatherMixinSupertypeConstraints(mixinElement);
+            if (mixinSupertypeConstraints.isNotEmpty) {
               if (supertypesForMixinInference == null) {
                 supertypesForMixinInference = <InterfaceType>[];
                 ClassElementImpl.collectAllSupertypes(
@@ -686,33 +689,23 @@
                       supertypesForMixinInference, previousMixin, type);
                 }
               }
-              var matchingInterfaceType = _findInterfaceTypeForElement(
-                  mixinSupertypeConstraint.element,
-                  supertypesForMixinInference);
-              // TODO(paulberry): If matchingInterfaceType is null, that's an
-              // error.  Also, if there are multiple matching interface types
-              // that use different type parameters, that's also an error.  But
-              // we can't report errors from the linker, so we just use the
-              // first matching interface type (if there is one) and hope for
-              // the best.  The error detection logic will have to be
-              // implemented in the ErrorVerifier.
-              if (matchingInterfaceType != null) {
-                // TODO(paulberry): now we should pattern match
-                // matchingInterfaceType against mixinSupertypeConstraint to
-                // find the correct set of type parameters to apply to the
-                // mixin.  But as a quick hack, we assume that the mixin just
-                // passes its type parameters through to the supertype
-                // constraint (that is, each type in
-                // mixinSupertypeConstraint.typeParameters should be a
-                // TypeParameterType pointing to the corresponding element of
-                // mixinElement.typeParameters).  To avoid a complete disaster
-                // if this assumption is wrong, we only do the inference if the
-                // number of type arguments applied to mixinSupertypeConstraint
-                // matches the number of type parameters accepted by the mixin.
-                if (mixinSupertypeConstraint.typeArguments.length ==
-                    mixinElement.typeParameters.length) {
-                  mixin = mixinElement.type
-                      .instantiate(matchingInterfaceType.typeArguments);
+              var matchingInterfaceTypes = _findInterfaceTypesForConstraints(
+                  mixinSupertypeConstraints, supertypesForMixinInference);
+              // Note: if matchingInterfaceType is null, that's an error.  Also,
+              // if there are multiple matching interface types that use
+              // different type parameters, that's also an error.  But we can't
+              // report errors from the linker, so we just use the
+              // first matching interface type (if there is one).  The error
+              // detection logic is implemented in the ErrorVerifier.
+              if (matchingInterfaceTypes != null) {
+                // Try to pattern match matchingInterfaceTypes against
+                // mixinSupertypeConstraints to find the correct set of type
+                // parameters to apply to the mixin.
+                var inferredMixin = context.typeSystem
+                    .matchSupertypeConstraints(mixinElement,
+                        mixinSupertypeConstraints, matchingInterfaceTypes);
+                if (inferredMixin != null) {
+                  mixin = inferredMixin;
                   enclosingElement._storeLinkedType(slot, mixin, this);
                 }
               }
@@ -831,6 +824,21 @@
     return enclosingElement.enclosingElement._linker.typeProvider.objectType;
   }
 
+  List<InterfaceType> _findInterfaceTypesForConstraints(
+      List<InterfaceType> constraints, List<InterfaceType> interfaceTypes) {
+    var result = <InterfaceType>[];
+    for (var constraint in constraints) {
+      var interfaceType =
+          _findInterfaceTypeForElement(constraint.element, interfaceTypes);
+      if (interfaceType == null) {
+        // No matching interface type found, so inference fails.
+        return null;
+      }
+      result.add(interfaceType);
+    }
+    return result;
+  }
+
   InterfaceType _findInterfaceTypeForElement(
       ClassElement element, List<InterfaceType> interfaceTypes) {
     for (var interfaceType in interfaceTypes) {
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
index c901d70..4e73768 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
@@ -16,4 +16,8 @@
 class CompileTimeErrorCodeTest_Driver extends CompileTimeErrorCodeTest {
   @override
   bool get enableNewAnalysisDriver => true;
+
+  @override // Passes with driver
+  test_mixinInference_recursiveSubtypeCheck() =>
+      super.test_mixinInference_recursiveSubtypeCheck();
 }
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
index f766e7c..00619ba 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
@@ -1725,6 +1725,16 @@
 
   @override
   @failingTest
+  test_mixinInference_conflictingSubstitution() =>
+      super.test_mixinInference_conflictingSubstitution();
+
+  @override
+  @failingTest
+  test_mixinInference_impossibleSubstitution() =>
+      super.test_mixinInference_impossibleSubstitution();
+
+  @override
+  @failingTest
   test_mixinInference_noMatchingClass() =>
       super.test_mixinInference_noMatchingClass();
 
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 706e1c6..184d0e3 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -3955,9 +3955,40 @@
     verify([source]);
   }
 
+  test_mixinInference_conflictingSubstitution() async {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    options.strongMode = true;
+    resetWith(options: options);
+    Source source = addSource('''
+abstract class A<T> {}
+class M<T> extends A<Map<T, T>> {}
+class C extends A<Map<int, String>> with M {}
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source,
+        [CompileTimeErrorCode.MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION]);
+  }
+
+  test_mixinInference_impossibleSubstitution() async {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    options.strongMode = true;
+    resetWith(options: options);
+    Source source = addSource('''
+abstract class A<T> {}
+class M<T> extends A<Map<T, T>> {}
+class C extends A<List<int>> with M {}
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source,
+        [CompileTimeErrorCode.MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION]);
+  }
+
   test_mixinInference_matchingClass() async {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.enableSuperMixins = true;
+    options.strongMode = true;
     resetWith(options: options);
     Source source = addSource('''
 abstract class A<T> {}
@@ -3972,6 +4003,7 @@
   test_mixinInference_matchingClass_inPreviousMixin() async {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.enableSuperMixins = true;
+    options.strongMode = true;
     resetWith(options: options);
     Source source = addSource('''
 abstract class A<T> {}
@@ -3987,6 +4019,7 @@
   test_mixinInference_noMatchingClass() async {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.enableSuperMixins = true;
+    options.strongMode = true;
     resetWith(options: options);
     Source source = addSource('''
 abstract class A<T> {}
@@ -4002,6 +4035,7 @@
   test_mixinInference_noMatchingClass_constraintSatisfiedByImplementsClause() async {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.enableSuperMixins = true;
+    options.strongMode = true;
     resetWith(options: options);
     Source source = addSource('''
 abstract class A<T> {}
@@ -4017,6 +4051,7 @@
   test_mixinInference_noMatchingClass_namedMixinApplication() async {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.enableSuperMixins = true;
+    options.strongMode = true;
     resetWith(options: options);
     Source source = addSource('''
 abstract class A<T> {}
@@ -4032,6 +4067,7 @@
   test_mixinInference_noMatchingClass_noSuperclassConstraint() async {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.enableSuperMixins = true;
+    options.strongMode = true;
     resetWith(options: options);
     Source source = addSource('''
 abstract class A<T> {}
@@ -4046,6 +4082,7 @@
   test_mixinInference_noMatchingClass_typeParametersSupplied() async {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.enableSuperMixins = true;
+    options.strongMode = true;
     resetWith(options: options);
     Source source = addSource('''
 abstract class A<T> {}
@@ -4057,6 +4094,45 @@
     assertNoErrors(source);
   }
 
+  @failingTest // Does not work with old task model
+  test_mixinInference_recursiveSubtypeCheck() async {
+    // See dartbug.com/32353 for a detailed explanation.
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    options.strongMode = true;
+    resetWith(options: options);
+    Source source = addSource('''
+class ioDirectory implements ioFileSystemEntity {}
+
+class ioFileSystemEntity {}
+
+abstract class _LocalDirectory
+    extends _LocalFileSystemEntity<_LocalDirectory, ioDirectory>
+    with ForwardingDirectory, DirectoryAddOnsMixin {}
+
+abstract class _LocalFileSystemEntity<T extends FileSystemEntity,
+  D extends ioFileSystemEntity> extends ForwardingFileSystemEntity<T, D> {}
+
+abstract class FileSystemEntity implements ioFileSystemEntity {}
+
+abstract class ForwardingFileSystemEntity<T extends FileSystemEntity,
+  D extends ioFileSystemEntity> implements FileSystemEntity {}
+
+
+abstract class ForwardingDirectory<T extends Directory>
+    extends ForwardingFileSystemEntity<T, ioDirectory>
+    implements Directory {}
+
+abstract class Directory implements FileSystemEntity, ioDirectory {}
+
+abstract class DirectoryAddOnsMixin implements Directory {}
+''');
+    var analysisResult = await computeAnalysisResult(source);
+    assertNoErrors(source);
+    var mixins = analysisResult.unit.element.getType('_LocalDirectory').mixins;
+    expect(mixins[0].toString(), 'ForwardingDirectory<_LocalDirectory>');
+  }
+
   test_mixinInheritsFromNotObject_classDeclaration_extends() async {
     Source source = addSource(r'''
 class A {}
diff --git a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
index 7cfa206..d02bde0 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
@@ -19,4 +19,16 @@
 
   @override // Passes with driver
   test_infer_mixin() => super.test_infer_mixin();
+
+  @override // Passes with driver
+  test_infer_mixin_multiplyConstrained() =>
+      super.test_infer_mixin_multiplyConstrained();
+
+  @override // Passes with driver
+  test_infer_mixin_with_substitution() =>
+      super.test_infer_mixin_with_substitution();
+
+  @override // Passes with driver
+  test_infer_mixin_with_substitution_functionType() =>
+      super.test_infer_mixin_with_substitution_functionType();
 }
diff --git a/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart b/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
index aab1574..c52404a 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
@@ -191,6 +191,23 @@
     return super.test_genericTypeAlias_invalidGenericFunctionType();
   }
 
+  @override // passes with kernel
+  test_infer_mixin() => super.test_infer_mixin();
+
+  @override // Passes with kernel
+  test_infer_mixin_multiplyConstrained() =>
+      super.test_infer_mixin_multiplyConstrained();
+
+  @override
+  @failingTest
+  test_infer_mixin_with_substitution() =>
+      super.test_infer_mixin_with_substitution();
+
+  @override
+  @failingTest
+  test_infer_mixin_with_substitution_functionType() =>
+      super.test_infer_mixin_with_substitution_functionType();
+
   @override
   @failingTest
   @potentialAnalyzerProblem
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 23fd626..29f7980 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -2707,6 +2707,7 @@
   test_infer_mixin() async {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.enableSuperMixins = true;
+    options.strongMode = true;
     resetWith(options: options);
     Source source = addSource('''
 abstract class A<T> {}
@@ -2727,6 +2728,86 @@
     expect(classC.mixins[0].toString(), 'M<B>');
   }
 
+  @failingTest // Does not work with old task model
+  test_infer_mixin_multiplyConstrained() async {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    options.strongMode = true;
+    resetWith(options: options);
+    Source source = addSource('''
+abstract class A<T> {}
+
+abstract class B<U> {}
+
+class C {}
+
+class D {}
+
+class M<T, U> extends A<T> with B<U> {}
+
+class E extends A<C> implements B<D> {}
+
+class F extends E with M {}
+''');
+    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+    CompilationUnit unit = analysisResult.unit;
+    ClassElement classF =
+        resolutionMap.elementDeclaredByCompilationUnit(unit).getType('F');
+    expect(classF.mixins, hasLength(1));
+    expect(classF.mixins[0].toString(), 'M<C, D>');
+  }
+
+  @failingTest // Does not work with old task model
+  test_infer_mixin_with_substitution() async {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    options.strongMode = true;
+    resetWith(options: options);
+    Source source = addSource('''
+abstract class A<T> {}
+
+class B {}
+
+class M<T> extends A<List<T>> {}
+
+class C extends A<List<B>> with M {}
+''');
+    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+    CompilationUnit unit = analysisResult.unit;
+    ClassElement classC =
+        resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
+    expect(classC.mixins, hasLength(1));
+    expect(classC.mixins[0].toString(), 'M<B>');
+  }
+
+  @failingTest // Does not work with old task model
+  test_infer_mixin_with_substitution_functionType() async {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableSuperMixins = true;
+    options.strongMode = true;
+    resetWith(options: options);
+    Source source = addSource('''
+abstract class A<T> {}
+
+class B {}
+
+class M<T, U> extends A<T Function(U)> {}
+
+class C extends A<int Function(String)> with M {}
+''');
+    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+    assertNoErrors(source);
+    CompilationUnit unit = analysisResult.unit;
+    ClassElement classC =
+        resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
+    expect(classC.mixins, hasLength(1));
+    expect(classC.mixins[0].toString(), 'M<int, String>');
+  }
+
   test_initializingFormalForNonExistentField() async {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index b28d44d..5fe1d70 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -382,14 +382,6 @@
 
   @override
   @failingTest
-  void test_initializedVariableInForEach() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, found 0
-    super.test_initializedVariableInForEach();
-  }
-
-  @override
-  @failingTest
   void test_invalidCodePoint() {
     // TODO(brianwilkerson) Does not recover.
     //   Internal problem: Compiler cannot run without a compiler context.
@@ -512,14 +504,6 @@
 
   @override
   @failingTest
-  void test_invalidLiteralInConfiguration() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, found 0
-    super.test_invalidLiteralInConfiguration();
-  }
-
-  @override
-  @failingTest
   void test_invalidOperatorAfterSuper_primaryExpression() {
     // TODO(brianwilkerson) Does not recover.
     //   Expected: true
@@ -789,13 +773,9 @@
   }
 
   @override
-  @failingTest
   void test_method_invalidTypeParameterExtendsComment() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 2 errors of type ParserErrorCode.EXPECTED_TOKEN, found 0;
-    // 2 errors of type ParserErrorCode.MISSING_IDENTIFIER, found 0;
-    // 1 errors of type ParserErrorCode.MISSING_FUNCTION_BODY, found 0
-    super.test_method_invalidTypeParameterExtendsComment();
+    // Fasta no longer supports type comment based syntax
+    // super.test_method_invalidTypeParameterExtendsComment();
   }
 
   @override
@@ -950,22 +930,6 @@
 
   @override
   @failingTest
-  void test_missingTerminatorForParameterGroup_named() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ScannerErrorCode.EXPECTED_TOKEN, found 0
-    super.test_missingTerminatorForParameterGroup_named();
-  }
-
-  @override
-  @failingTest
-  void test_missingTerminatorForParameterGroup_optional() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ScannerErrorCode.EXPECTED_TOKEN, found 0
-    super.test_missingTerminatorForParameterGroup_optional();
-  }
-
-  @override
-  @failingTest
   void test_missingVariableInForEach() {
     // TODO(brianwilkerson) Does not recover.
     //   type 'BinaryExpressionImpl' is not a subtype of type 'VariableDeclarationStatement' in type cast where
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 9a03215..92e1c59 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -3570,8 +3570,8 @@
     parseCompilationUnit("void f(int Function(",
         errors: usingFastaParser
             ? [
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 6, 1),
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 19, 1),
+                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
+                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
                 expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 8),
                 expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
               ]
@@ -3829,7 +3829,7 @@
     Configuration configuration = parser.parseConfiguration();
     expectNotNullIfNoErrors(configuration);
     listener.assertErrors([
-      expectedError(ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, 9, 9)
+      expectedError(ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, 12, 2)
     ]);
   }
 
@@ -4563,8 +4563,8 @@
     FormalParameterList list = parser.parseFormalParameterList();
     expectNotNullIfNoErrors(list);
     if (fe.Scanner.useFasta) {
-      listener
-          .assertErrors([expectedError(ScannerErrorCode.EXPECTED_TOKEN, 9, 1)]);
+      listener.assertErrors(
+          [expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)]);
     } else {
       listener.assertErrorsWithCodes(
           [ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP]);
@@ -5296,7 +5296,7 @@
   var x = "''', errors: [
       expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1),
       fe.Scanner.useFasta
-          ? expectedError(ScannerErrorCode.EXPECTED_TOKEN, 12, 1)
+          ? expectedError(ScannerErrorCode.EXPECTED_TOKEN, 25, 1)
           : expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 1),
       expectedError(ParserErrorCode.EXPECTED_TOKEN, 25, 0)
     ]);
@@ -5548,8 +5548,10 @@
     expectNotNullIfNoErrors(list);
     // fasta scanner generates '(a, {b, c]})' where '}' is synthetic
     if (usingFastaParser) {
-      listener
-          .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
+      listener.assertErrors([
+        expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
+        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
+      ]);
     } else {
       listener.assertErrors([
         expectedError(ScannerErrorCode.EXPECTED_TOKEN, 9, 1),
@@ -5565,8 +5567,10 @@
     expectNotNullIfNoErrors(list);
     // fasta scanner generates '(a, [b, c}])' where ']' is synthetic
     if (usingFastaParser) {
-      listener
-          .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
+      listener.assertErrors([
+        expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
+        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
+      ]);
     } else {
       listener.assertErrors([
         expectedError(ScannerErrorCode.EXPECTED_TOKEN, 4, 1),
@@ -15669,22 +15673,10 @@
       for (Keyword keyword in Keyword.values) {
         if (keyword.isBuiltIn || keyword.isPseudo) {
           String lexeme = keyword.lexeme;
-          List<ExpectedError> expectedErrors = [];
-          if (lexeme == 'dynamic') {
-            expectedErrors = [
-              expectedError(
-                  ParserErrorCode.TYPE_ARGUMENTS_ON_TYPE_VARIABLE, 7, 1)
-            ];
-          }
-          parseCompilationUnit('$lexeme<T>(x) => 0;', errors: expectedErrors);
-          if (lexeme == 'dynamic') {
-            expectedErrors = [
-              expectedError(
-                  ParserErrorCode.TYPE_ARGUMENTS_ON_TYPE_VARIABLE, 16, 1)
-            ];
-          }
-          parseCompilationUnit('class C {$lexeme<T>(x) => 0;}',
-              errors: expectedErrors);
+          // The fasta type resolution phase will report an error
+          // on type arguments on `dynamic` (e.g. `dynamic<int>`).
+          parseCompilationUnit('$lexeme<T>(x) => 0;');
+          parseCompilationUnit('class C {$lexeme<T>(x) => 0;}');
         }
       }
     }
diff --git a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
index 3969217..33108c9 100644
--- a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
@@ -17,6 +17,7 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(Dart2InferenceTest);
+    defineReflectiveTests(Dart2InferenceTest_Task);
   });
 }
 
@@ -902,3 +903,9 @@
     }
   }
 }
+
+@reflectiveTest
+class Dart2InferenceTest_Task extends Dart2InferenceTest {
+  @override
+  bool get enableNewAnalysisDriver => false;
+}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index b9740ce..a0b7e60 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -182,20 +182,37 @@
    * Try to determine the required context type, and configure filters.
    */
   void _computeRequiredTypeAndFilters(CompletionTarget target) {
-    var node = target.containingNode;
-    if (node is Expression) {
-      AstNode parent = node.parent;
-      if (parent is VariableDeclaration) {
-        _requiredType = parent.element?.type;
-      } else if (parent is AssignmentExpression) {
-        _requiredType = parent.leftHandSide.staticType;
-      } else if (node.staticParameterElement != null) {
-        _requiredType = node.staticParameterElement.type;
-      } else if (parent is NamedExpression &&
-          parent.staticParameterElement != null) {
-        _requiredType = parent.staticParameterElement.type;
-      }
+    Object entity = target.entity;
+    AstNode node = target.containingNode;
+
+    if (node is InstanceCreationExpression &&
+        node.keyword != null &&
+        node.constructorName == entity) {
+      entity = node;
+      node = node.parent;
     }
+
+    if (node is AssignmentExpression &&
+        node.operator.type == TokenType.EQ &&
+        node.rightHandSide == entity) {
+      _requiredType = node.leftHandSide?.staticType;
+    } else if (node is BinaryExpression &&
+        node.operator.type == TokenType.EQ_EQ &&
+        node.rightOperand == entity) {
+      _requiredType = node.leftOperand?.staticType;
+    } else if (node is NamedExpression && node.expression == entity) {
+      _requiredType = node.staticParameterElement?.type;
+    } else if (node is SwitchCase && node.expression == entity) {
+      AstNode parent = node.parent;
+      if (parent is SwitchStatement) {
+        _requiredType = parent.expression?.staticType;
+      }
+    } else if (node is VariableDeclaration && node.initializer == entity) {
+      _requiredType = node.element?.type;
+    } else if (entity is Expression && entity.staticParameterElement != null) {
+      _requiredType = entity.staticParameterElement.type;
+    }
+
     if (_requiredType == null) {
       return;
     }
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 749c072..2b63cc3 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -40,6 +40,9 @@
 
   /// The name of the getter returning the size of containers and strings.
   static const String length = 'length';
+
+  /// The name of the signature function in closure classes.
+  static const String signature = 'signature';
 }
 
 /// [Name]s commonly used.
@@ -75,6 +78,9 @@
   static const Name runtimeType_ = const PublicName(Identifiers.runtimeType_);
 
   static const Name genericInstantiation = const PublicName('instantiate');
+
+  /// The name of the signature function in closure classes.
+  static const Name signature = const PublicName(Identifiers.signature);
 }
 
 /// [Selector]s commonly used.
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 0b7ac2b..831ff2c 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -33,6 +33,7 @@
 import '../../js_backend/js_interop_analysis.dart';
 import '../../js_backend/runtime_types.dart'
     show RuntimeTypesChecks, RuntimeTypesNeed, RuntimeTypesEncoder;
+import '../../js_model/elements.dart' show JSignatureMethod;
 import '../../native/enqueue.dart' show NativeCodegenEnqueuer;
 import '../../options.dart';
 import '../../universe/selector.dart' show Selector;
@@ -93,8 +94,8 @@
   /// Contains the collected information the program builder used to build
   /// the model.
   // The collector will be filled on the first call to `buildProgram`.
-  // It is stored and publicly exposed for backwards compatibility. New code
-  // (and in particular new emitters) should not use it.
+  // It is publicly exposed for backwards compatibility. New code
+  // (and in particular new emitters) should not access it outside this class.
   final Collector collector;
 
   final Registry _registry;
@@ -684,13 +685,15 @@
         _namer,
         _rtiChecks,
         _rtiEncoder,
-        _jsInteropAnalysis);
+        _jsInteropAnalysis,
+        _options.useKernel,
+        _options.strongMode,
+        _options.disableRtiOptimization);
 
     void visitMember(MemberEntity member) {
       if (member.isInstanceMember && !member.isAbstract && !member.isField) {
-        // TODO(herhut): Remove once _buildMethod can no longer return null.
         Method method = _buildMethod(member);
-        if (method != null) methods.add(method);
+        if (method != null && member is! JSignatureMethod) methods.add(method);
       }
       if (member.isGetter || member.isField) {
         Map<Selector, SelectorConstraints> selectors =
@@ -752,7 +755,8 @@
             visitStatics: true,
             isHolderInterceptedClass: isInterceptedClass);
 
-    TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(cls,
+    TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(
+        cls, _generatedCode,
         storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata);
 
     List<StubMethod> checkedSetters = <StubMethod>[];
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index bb68ca8..7a88ac1 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -109,6 +109,9 @@
   final RuntimeTypesChecks _rtiChecks;
   final RuntimeTypesEncoder _rtiEncoder;
   final JsInteropAnalysis _jsInteropAnalysis;
+  final bool _useKernel;
+  final bool _strongMode;
+  final bool _disableRtiOptimization;
 
   RuntimeTypeGenerator(
       this._elementEnvironment,
@@ -119,7 +122,10 @@
       this._namer,
       this._rtiChecks,
       this._rtiEncoder,
-      this._jsInteropAnalysis);
+      this._jsInteropAnalysis,
+      this._useKernel,
+      this._strongMode,
+      this._disableRtiOptimization);
 
   TypeTestRegistry get _typeTestRegistry => emitterTask.typeTestRegistry;
 
@@ -143,6 +149,7 @@
   /// the result. This is only possible for function types that do not contain
   /// type variables.
   TypeTestProperties generateIsTests(ClassEntity classElement,
+      Map<MemberEntity, jsAst.Expression> generatedCode,
       {bool storeFunctionTypeInMetadata: true}) {
     TypeTestProperties result = new TypeTestProperties();
 
@@ -173,8 +180,36 @@
         result.functionTypeIndex =
             emitterTask.metadataCollector.reifyType(type, outputUnit);
       } else {
-        jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding(
-            emitterTask.emitter, type, thisAccess);
+        jsAst.Expression encoding;
+        MemberEntity signature = _elementEnvironment.lookupLocalClassMember(
+            method.enclosingClass, Identifiers.signature);
+        if (_useKernel &&
+            signature != null &&
+            generatedCode[signature] != null) {
+          encoding = generatedCode[signature];
+        } else {
+          // With Dart 2, if disableRtiOptimization is true, then we might
+          // generate some code for classes that are not actually called,
+          // so following this path is "okay." Also, classes that have call
+          // methods are no longer a subtype of Function (and therefore we don't
+          // create a closure class), so this path is also acceptable.
+
+          // TODO(efortuna, johnniwinther): Verify that closures that use this
+          // path are in fact dead code. If this *not* actually dead code, we
+          // get to this point because TrivialRuntimeTypesChecksBuilder
+          // specifies that every subtype of Object and its types is "used"
+          // (ClassUse = true). However, on the codegen side, we only codegen
+          // entities that are actually reachable via treeshaking. To solve this
+          // issue, if disableRtiOptimization is turned on, we could literally
+          // in world_impact.dart loop through every subclass of Object and say
+          // that all types related to JClosureClasses are "used" so the go
+          // through the codegen queue and therefore we generate code for it.
+          // This seems not ideal though.
+          assert(!(_useKernel && _strongMode && !_disableRtiOptimization) ||
+              (_useKernel && _strongMode && !method.enclosingClass.isClosure));
+          encoding = _rtiEncoder.getSignatureEncoding(
+              emitterTask.emitter, type, thisAccess);
+        }
         jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
         result.addSignature(classElement, operatorSignature, encoding);
       }
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index d1792a6..c6e9710 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -540,7 +540,7 @@
 class JSignatureMethod extends JMethod {
   JSignatureMethod(LibraryEntity enclosingLibrary, ClassEntity enclosingClass,
       ParameterStructure parameterStructure, AsyncMarker asyncMarker)
-      : super(enclosingLibrary, enclosingClass, const PublicName('\$signature'),
+      : super(enclosingLibrary, enclosingClass, Names.signature,
             parameterStructure, asyncMarker,
             isStatic: false, isExternal: false, isAbstract: false);
 
diff --git a/pkg/dart_internal/README.md b/pkg/dart_internal/README.md
new file mode 100644
index 0000000..3ce15a1
--- /dev/null
+++ b/pkg/dart_internal/README.md
@@ -0,0 +1,15 @@
+**Scary warning: This package is experimental and may deprecated in a future
+version of Dart.**
+
+This package is not intended for wide use. It provides a temporary API to
+solve the problem: "Given an object some generic type A, how do I construct an
+instance of generic type B with the same type argument(s)?"
+
+This is necessary in a few rare places in order to migrate existing code to
+Dart 2's stronger type system. Eventually, the hope is to have direct
+language support for solving this problem but we don't have time to get that
+into 2.0, so this package is provided as a temporary workaround.
+
+We will very likely remove support for this in a later version of Dart. Please
+avoid using this if you can. If you feel you *do* need to use it, please reach
+out to @munificent or @leafpetersen and let us know.
diff --git a/pkg/dart_internal/pubspec.yaml b/pkg/dart_internal/pubspec.yaml
index 49cb8dac..945aaa1 100644
--- a/pkg/dart_internal/pubspec.yaml
+++ b/pkg/dart_internal/pubspec.yaml
@@ -1,18 +1,19 @@
 name: dart_internal
-version: 0.1.0-dev
+version: 0.1.1
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 description: >
-  This package is not intended for any external use. Basically, if you don't
-  personally know exactly what it's for, you're probably not the intended user.
+  This package is not intended for wide use. It provides a temporary API to
+  solve the problem: "Given an object some generic type A, how do I construct an
+  instance of generic type B with the same type argument(s)?"
 
-  It contains functionality to enable some internal Google code to transition
-  to strong mode before some anticipated language features are in place. In
-  particular, it provides an API to solve the problem: "Given an object some
-  generic type A, how do I construct an instance of generic type B with the
-  same type argument(s)?"
-publish_to:
-  # This package is not intended to be used externally (or, at least, not yet).
-  none
+  This is necessary in a few rare places in order to migrate existing code to
+  Dart 2's stronger type system. Eventually, the hope is to have direct
+  language support for solving this problem but we don't have time to get that
+  into 2.0, so this package is provided as a temporary workaround.
+
+  We will very likely remove support for this in a later version of Dart.
 environment:
-  sdk: ">=2.0.0 <2.0.0"
+  # Restrict the upper bound so that we can remove support for this in a later
+  # version of the SDK without it being a breaking change.
+  sdk: ">=2.0.0-dev.12.0 <2.1.0"
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 383507a..489c467 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -6039,6 +6039,7 @@
     if (type == null || type.isDynamic || type.isObject) {
       return isObjectMember(name);
     } else if (type is InterfaceType) {
+      type = getImplementationType(type) ?? type;
       var element = type.element;
       if (_extensionTypes.isNativeClass(element)) {
         var member = _lookupForwardedMember(element, name);
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 99b102e..c8047fa 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -183,6 +183,9 @@
   final _labelNames = new HashMap<Statement, String>.identity();
 
   final Class _jsArrayClass;
+  final Class _jsBoolClass;
+  final Class _jsNumberClass;
+  final Class _jsStringClass;
   final Class privateSymbolClass;
   final Class linkedHashMapImplClass;
   final Class identityHashMapImplClass;
@@ -219,6 +222,11 @@
         _constants = new ConstantVisitor(nativeTypes.coreTypes),
         _jsArrayClass =
             nativeTypes.sdk.getClass('dart:_interceptors', 'JSArray'),
+        _jsBoolClass = nativeTypes.sdk.getClass('dart:_interceptors', 'JSBool'),
+        _jsNumberClass =
+            nativeTypes.sdk.getClass('dart:_interceptors', 'JSNumber'),
+        _jsStringClass =
+            nativeTypes.sdk.getClass('dart:_interceptors', 'JSString'),
         _asyncStreamIteratorClass =
             nativeTypes.sdk.getClass('dart:async', 'StreamIterator'),
         privateSymbolClass =
@@ -2316,7 +2324,7 @@
         type == coreTypes.objectClass) {
       return isObjectMember(name);
     } else if (type is InterfaceType) {
-      var c = type.classNode;
+      var c = getImplementationClass(type) ?? type.classNode;
       if (_extensionTypes.isNativeClass(c)) {
         var member = _lookupForwardedMember(c, name);
 
@@ -4696,6 +4704,14 @@
     return null;
   }
 
+  Class getImplementationClass(DartType type) {
+    var t = _typeRep.typeFor(type);
+    if (t is JSNumber) return _jsNumberClass;
+    if (t is JSString) return _jsStringClass;
+    if (t is JSBoolean) return _jsBoolClass;
+    return null;
+  }
+
   @override
   visitAsExpression(AsExpression node) {
     Expression fromExpr = node.operand;
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
index 1d7790c..b78c49f 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
@@ -26,12 +26,14 @@
         namedArguments = _namedArgsToSymbols(namedArguments),
         typeArguments = typeArguments == null
             ? const []
-            : typeArguments.map(wrapType).toList();
+            : new List.unmodifiable(typeArguments.map(wrapType));
 
   static Map<Symbol, dynamic> _namedArgsToSymbols(namedArgs) {
-    if (namedArgs == null) return {};
-    return new Map.fromIterable(getOwnPropertyNames(namedArgs),
-        key: _dartSymbol, value: (k) => JS('', '#[#]', namedArgs, k));
+    if (namedArgs == null) return const {};
+    return new Map.unmodifiable(new Map.fromIterable(
+        getOwnPropertyNames(namedArgs),
+        key: _dartSymbol,
+        value: (k) => JS('', '#[#]', namedArgs, k)));
   }
 }
 
@@ -206,7 +208,7 @@
       // Names starting with _ are escaped names used to disambiguate Dart and
       // JS names.
       if ($name[0] === '_') {
-        // Inverse of 
+        // Inverse of
         switch($name) {
           case '_get':
             return '[]';
@@ -293,7 +295,7 @@
   // Apply type arguments
   if ($ftype instanceof $GenericFunctionType) {
     let formalCount = $ftype.formalCount;
-    
+
     if ($typeArgs == null) {
       $typeArgs = $ftype.instantiateDefaultBounds();
     } else if ($typeArgs.length != formalCount) {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_array.dart b/pkg/dev_compiler/tool/input_sdk/private/js_array.dart
index 714ad2a..69c90ff 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/js_array.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/js_array.dart
@@ -598,17 +598,10 @@
   Type get runtimeType =>
       dart.wrapType(JS('', '#(#)', dart.getGenericClass(List), E));
 
-  Iterable<E> followedBy(Iterable<E> other) sync* {
-    yield* this;
-    yield* other;
-  }
+  Iterable<E> followedBy(Iterable<E> other) =>
+      new FollowedByIterable<E>.firstEfficient(this, other);
 
-  Iterable<T> whereType<T>() sync* {
-    for (var i = 0; i < this.length; i++) {
-      var element = this[i];
-      if (element is T) yield element;
-    }
-  }
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
 
   List<E> operator +(List<E> other) {
     int totalLength = this.length + other.length;
diff --git a/pkg/dev_compiler/web/source_map_stack_trace.dart b/pkg/dev_compiler/web/source_map_stack_trace.dart
index d5c019a..8cdb4f1 100644
--- a/pkg/dev_compiler/web/source_map_stack_trace.dart
+++ b/pkg/dev_compiler/web/source_map_stack_trace.dart
@@ -56,6 +56,15 @@
       }
     }
 
+    if (!sourceUrl.startsWith('dart:') &&
+        !sourceUrl.startsWith('package:') &&
+        sourceUrl.contains('dart_sdk.js')) {
+      // This compresses the long dart_sdk URLs if SDK source maps are missing.
+      // It's no longer linkable, but neither are the properly mapped ones
+      // above.
+      sourceUrl = 'dart_sdk.js';
+    }
+
     return new Frame(Uri.parse(sourceUrl), span.start.line + 1,
         span.start.column + 1, _prettifyMember(frame.member));
   }).where((frame) => frame != null));
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index caab6a4..18161b7 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -2033,8 +2033,7 @@
     analyzerCode: "FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR",
     dart2jsCode: "*fatal*",
     message: r"""Field formal parameters can only be used in a constructor.""",
-    tip:
-        r"""Try replacing the field formal parameter with a normal parameter.""");
+    tip: r"""Try removing 'this.'.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeFinalAndCovariant = messageFinalAndCovariant;
@@ -2401,6 +2400,19 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInitializedVariableInForEach =
+    messageInitializedVariableInForEach;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInitializedVariableInForEach = const MessageCode(
+    "InitializedVariableInForEach",
+    analyzerCode: "INITIALIZED_VARIABLE_IN_FOR_EACH",
+    dart2jsCode: "*fatal*",
+    message: r"""The loop variable in a for-each loop can't be initialized.""",
+    tip:
+        r"""Try removing the initializer, or using a different kind of loop.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(Uri uri_)> templateInputFileNotFound =
     const Template<Message Function(Uri uri_)>(
         messageTemplate: r"""Input file not found: #uri.""",
@@ -2788,6 +2800,8 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageInterpolationInUri = const MessageCode(
     "InterpolationInUri",
+    analyzerCode: "INVALID_LITERAL_IN_CONFIGURATION",
+    dart2jsCode: "*fatal*",
     message: r"""Can't use string interpolation in a URI.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index 2f12afa..db948bc 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -45,7 +45,6 @@
 
 import '../messages.dart'
     show
-        messageInternalProblemBodyOnAbstractMethod,
         messageNonInstanceTypeVariableUse,
         messagePatchDeclarationMismatch,
         messagePatchDeclarationOrigin,
@@ -53,7 +52,7 @@
 
 import '../parser.dart' show noLength;
 
-import '../problems.dart' show internalProblem, unexpected;
+import '../problems.dart' show unexpected;
 
 import '../deprecated_problems.dart' show deprecated_inputError;
 
@@ -103,12 +102,13 @@
   KernelFunctionBuilder get actualOrigin;
 
   void set body(Statement newBody) {
-    if (newBody != null) {
-      if (isAbstract) {
-        return internalProblem(messageInternalProblemBodyOnAbstractMethod,
-            newBody.fileOffset, fileUri);
-      }
-    }
+//    if (newBody != null) {
+//      if (isAbstract) {
+//        // TODO(danrubel): Is this check needed?
+//        return internalProblem(messageInternalProblemBodyOnAbstractMethod,
+//            newBody.fileOffset, fileUri);
+//      }
+//    }
     actualBody = newBody;
     if (function != null) {
       // A forwarding semi-stub is a method that is abstract in the source code,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 568f3f9..0f9acb9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -112,7 +112,7 @@
 
   @override
   DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
-    inferrer.inferExpression(operand, null, false);
+    inferrer.inferExpression(operand, const UnknownType(), false);
     return type;
   }
 }
@@ -145,7 +145,7 @@
     inferrer.ensureAssignable(
         expectedType, actualType, condition, condition.fileOffset);
     if (message != null) {
-      inferrer.inferExpression(message, null, false);
+      inferrer.inferExpression(message, const UnknownType(), false);
     }
   }
 }
@@ -260,7 +260,8 @@
     }
     Let section = body;
     while (true) {
-      inferrer.inferExpression(section.variable.initializer, null, false);
+      inferrer.inferExpression(
+          section.variable.initializer, const UnknownType(), false);
       if (section.body is! Let) break;
       section = section.body;
     }
@@ -409,7 +410,7 @@
       } else {
         // Analyzer uses a null context for the RHS here.
         // TODO(paulberry): improve on this.
-        rhsType = inferrer.inferExpression(rhs, null, true);
+        rhsType = inferrer.inferExpression(rhs, const UnknownType(), true);
         // It's not necessary to call _storeLetType for [rhs] because the RHS
         // is always passed directly to the combiner; it's never stored in a
         // temporary variable first.
@@ -441,7 +442,8 @@
       }
       _storeLetType(inferrer, replacedCombiner, combinedType);
     } else {
-      var rhsType = inferrer.inferExpression(rhs, writeContext, true);
+      var rhsType = inferrer.inferExpression(
+          rhs, writeContext ?? const UnknownType(), true);
       var replacedRhs =
           inferrer.ensureAssignable(writeContext, rhsType, rhs, writeOffset);
       _storeLetType(inferrer, replacedRhs ?? rhs, rhsType);
@@ -495,7 +497,8 @@
 
   DartType _inferReceiver(ShadowTypeInferrer inferrer) {
     if (receiver != null) {
-      var receiverType = inferrer.inferExpression(receiver, null, true);
+      var receiverType =
+          inferrer.inferExpression(receiver, const UnknownType(), true);
       _storeLetType(inferrer, receiver, receiverType);
       return receiverType;
     } else if (isSuper) {
@@ -685,7 +688,7 @@
 
   @override
   void _inferStatement(ShadowTypeInferrer inferrer) {
-    inferrer.inferExpression(expression, null, false);
+    inferrer.inferExpression(expression, const UnknownType(), false);
   }
 }
 
@@ -910,7 +913,7 @@
           expectedType, conditionType, condition, condition.fileOffset);
     }
     for (var update in updates) {
-      inferrer.inferExpression(update, null, false);
+      inferrer.inferExpression(update, const UnknownType(), false);
     }
     inferrer.inferStatement(body);
   }
@@ -981,11 +984,12 @@
     if (inferrer.strongMode) {
       variable.type = lhsType;
     }
-    // - Let J = T0 if K is `_` else K.
-    var rhsContext = typeContext ?? lhsType;
+    // - Let J = T0 if K is `?` else K.
     // - Infer e1 in context J to get T1
-    bool useLub = _forceLub || typeContext == null;
-    var rhsType = inferrer.inferExpression(_rhs, rhsContext, useLub);
+    bool useLub = _forceLub || typeContext is UnknownType;
+    var rhsType = typeContext is UnknownType
+        ? inferrer.inferExpression(_rhs, lhsType, true)
+        : inferrer.inferExpression(_rhs, typeContext, _forceLub);
     // - Let T = greatest closure of K with respect to `?` if K is not `_`, else
     //   UP(t0, t1)
     // - Then the inferred type is T.
@@ -1029,7 +1033,7 @@
   @override
   DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
     if (write != null) {
-      inferrer.inferExpression(write, null, false);
+      inferrer.inferExpression(write, const UnknownType(), false);
     }
     _replaceWithDesugared();
     return const DynamicType();
@@ -1075,13 +1079,12 @@
     var calleeType =
         inferrer.getCalleeFunctionType(writeMember, receiverType, false);
     DartType expectedIndexTypeForWrite;
-    DartType indexContext;
+    DartType indexContext = const UnknownType();
     DartType writeContext;
     if (calleeType.positionalParameters.length >= 2) {
       // TODO(paulberry): we ought to get a context for the index expression
       // from the index formal parameter, but analyzer doesn't so for now we
       // replicate its behavior.
-      indexContext = null;
       expectedIndexTypeForWrite = calleeType.positionalParameters[0];
       writeContext = calleeType.positionalParameters[1];
     }
@@ -1151,7 +1154,7 @@
 
   @override
   void _inferInitializer(ShadowTypeInferrer inferrer) {
-    inferrer.inferExpression(variable.initializer, null, false);
+    inferrer.inferExpression(variable.initializer, const UnknownType(), false);
   }
 }
 
@@ -1161,7 +1164,7 @@
 
   @override
   DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
-    inferrer.inferExpression(operand, null, false);
+    inferrer.inferExpression(operand, const UnknownType(), false);
     return inferrer.coreTypes.boolClass.rawType;
   }
 }
@@ -1174,7 +1177,7 @@
   @override
   DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
     IsExpression isExpression = this.operand;
-    inferrer.inferExpression(isExpression.operand, null, false);
+    inferrer.inferExpression(isExpression.operand, const UnknownType(), false);
     return inferrer.coreTypes.boolClass.rawType;
   }
 }
@@ -1660,7 +1663,8 @@
         ? closureContext.returnOrYieldContext
         : null;
     var inferredType = expression != null
-        ? inferrer.inferExpression(expression, typeContext, true)
+        ? inferrer.inferExpression(
+            expression, typeContext ?? const UnknownType(), true)
         : const VoidType();
     // Analyzer treats bare `return` statements as having no effect on the
     // inferred type of the closure.  TODO(paulberry): is this what we want
@@ -1759,7 +1763,7 @@
   DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
     if (!inferrer.isTopLevel) {
       for (Expression expression in expressions) {
-        inferrer.inferExpression(expression, null, false);
+        inferrer.inferExpression(expression, const UnknownType(), false);
       }
     }
     return inferrer.coreTypes.stringClass.rawType;
@@ -1843,7 +1847,8 @@
 
   @override
   void _inferStatement(ShadowTypeInferrer inferrer) {
-    var expressionType = inferrer.inferExpression(expression, null, true);
+    var expressionType =
+        inferrer.inferExpression(expression, const UnknownType(), true);
     for (var switchCase in cases) {
       for (var caseExpression in switchCase.expressions) {
         inferrer.inferExpression(caseExpression, expressionType, false);
@@ -1939,7 +1944,7 @@
 
   @override
   DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
-    inferrer.inferExpression(expression, null, false);
+    inferrer.inferExpression(expression, const UnknownType(), false);
     return const BottomType();
   }
 }
@@ -2017,6 +2022,10 @@
   @override
   DartType inferExpression(
       Expression expression, DartType typeContext, bool typeNeeded) {
+    // `null` should never be used as the type context.  An instance of
+    // `UnknownType` should be used instead.
+    assert(typeContext != null);
+
     // It isn't safe to do type inference on an expression without a parent,
     // because type inference might cause us to have to replace one expression
     // with another, and we can only replace a node if it has a parent pointer.
@@ -2048,10 +2057,9 @@
   }
 
   @override
-  DartType inferFieldTopLevel(
-      ShadowField field, DartType type, bool typeNeeded) {
+  DartType inferFieldTopLevel(ShadowField field, bool typeNeeded) {
     if (field.initializer == null) return const DynamicType();
-    return inferExpression(field.initializer, type, typeNeeded);
+    return inferExpression(field.initializer, const UnknownType(), typeNeeded);
   }
 
   @override
@@ -2245,7 +2253,7 @@
 
   @override
   void _inferStatement(ShadowTypeInferrer inferrer) {
-    var declaredType = _implicitlyTyped ? null : type;
+    var declaredType = _implicitlyTyped ? const UnknownType() : type;
     DartType inferredType;
     DartType initializerType;
     if (initializer != null) {
@@ -2349,7 +2357,8 @@
               ? inferrer.coreTypes.streamClass
               : inferrer.coreTypes.iterableClass);
     }
-    var inferredType = inferrer.inferExpression(expression, typeContext, true);
+    var inferredType = inferrer.inferExpression(
+        expression, typeContext ?? const UnknownType(), true);
     closureContext.handleYield(
         inferrer, isYieldStar, inferredType, expression, fileOffset);
   }
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index cb8a1f9..dc3c99e 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -1367,7 +1367,7 @@
   /// as in `abstract<t> foo`. In situations such as this, return the last
   /// token in that type reference and assume the caller will report the error
   /// and recover.
-  Token skipTypeReferenceOpt(Token token) {
+  Token skipTypeReferenceOpt(Token token, bool inDeclaration) {
     final Token beforeStart = token;
     Token next = token.next;
 
@@ -1460,7 +1460,7 @@
     }
 
     return next.isIdentifier ||
-            (next.isOperator && !optional('=', next)) ||
+            (inDeclaration && next.isOperator && !optional('=', next)) ||
             looksLikeTypeRef
         ? token
         : beforeStart;
@@ -2658,14 +2658,6 @@
           throw new StateError("beforeName.next != name");
         return parseNamedFunctionRest(beforeName, begin, formals, true);
 
-      case TypeContinuation.VariablesDeclarationOrExpression:
-        if (looksLikeType && token.isIdentifier) {
-          // TODO(ahe): Generate type events and call
-          // parseVariablesDeclarationNoSemicolonRest instead.
-          return parseVariablesDeclarationNoSemicolon(beforeBegin);
-        }
-        return parseExpression(beforeBegin);
-
       case TypeContinuation.NormalFormalParameter:
       case TypeContinuation.NormalFormalParameterAfterVar:
         parameterKind = FormalParameterKind.mandatory;
@@ -2909,10 +2901,6 @@
       Function endStuff, Function handleNoStuff) {
     Token next = token.next;
     if (optional('<', next)) {
-      if (optional('dynamic', token)) {
-        reportRecoverableError(next,
-            fasta.templateTypeArgumentsOnTypeVariable.withArguments('dynamic'));
-      }
       BeginToken begin = next;
       rewriteLtEndGroupOpt(begin);
       beginStuff(begin);
@@ -2987,7 +2975,7 @@
     // TODO(danrubel): Consider changing the listener contract
     // so that the type reference can be parsed immediately
     // rather than skipped now and parsed later.
-    token = skipTypeReferenceOpt(token);
+    token = skipTypeReferenceOpt(token, true);
     if (token == beforeType) {
       // There is no type reference.
       beforeType = null;
@@ -3703,7 +3691,7 @@
     // TODO(danrubel): Consider changing the listener contract
     // so that the type reference can be parsed immediately
     // rather than skipped now and parsed later.
-    token = skipTypeReferenceOpt(token);
+    token = skipTypeReferenceOpt(token, true);
     if (token == beforeType) {
       // There is no type reference.
       beforeType = null;
@@ -4342,7 +4330,7 @@
     } else if (identical(value, 'await') && optional('for', token.next.next)) {
       return parseForStatement(token.next, token.next);
     } else if (identical(value, 'for')) {
-      return parseForStatement(null, token);
+      return parseForStatement(token, null);
     } else if (identical(value, 'rethrow')) {
       return parseRethrowStatement(token);
     } else if (identical(value, 'throw') && optional(';', token.next.next)) {
@@ -5538,6 +5526,7 @@
   }
 
   Token parseVariablesDeclaration(Token token) {
+    token = parseMetadataStar(token);
     return parseVariablesDeclarationMaybeSemicolon(token, true);
   }
 
@@ -5545,11 +5534,6 @@
     return parseVariablesDeclarationMaybeSemicolonRest(token, true);
   }
 
-  Token parseVariablesDeclarationNoSemicolon(Token token) {
-    // Only called when parsing a for loop, so this is for parsing locals.
-    return parseVariablesDeclarationMaybeSemicolon(token, false);
-  }
-
   Token parseVariablesDeclarationNoSemicolonRest(Token token) {
     // Only called when parsing a for loop, so this is for parsing locals.
     return parseVariablesDeclarationMaybeSemicolonRest(token, false);
@@ -5557,7 +5541,6 @@
 
   Token parseVariablesDeclarationMaybeSemicolon(
       Token token, bool endWithSemicolon) {
-    token = parseMetadataStar(token);
     Token next = token.next;
 
     MemberKind memberKind = MemberKind.Local;
@@ -5661,21 +5644,78 @@
   ///   declaredIdentifier 'in' expression |
   ///   identifier 'in' expression
   /// ;
+  ///
+  /// forInitializerStatement:
+  ///   localVariableDeclaration |
+  ///   expression? ';'
+  /// ;
   /// ```
-  Token parseForStatement(Token awaitToken, Token token) {
-    // TODO(brianwilkerson): Consider moving `token` to be the first parameter.
-    Token forKeyword = token.next;
+  Token parseForStatement(Token token, Token awaitToken) {
+    Token forKeyword = token = token.next;
     assert(awaitToken == null || optional('await', awaitToken));
+    assert(optional('for', token));
     listener.beginForStatement(forKeyword);
-    token = expect('for', forKeyword);
-    Token leftParenthesis = token;
-    expect('(', token);
-    token = parseVariablesDeclarationOrExpressionOpt(token);
+
+    Token leftParenthesis = forKeyword.next;
+    if (!optional('(', leftParenthesis)) {
+      // Recovery
+      reportRecoverableError(
+          leftParenthesis, fasta.templateExpectedButGot.withArguments('('));
+      int offset = leftParenthesis.offset;
+
+      BeginToken openParen =
+          token.setNext(new SyntheticBeginToken(TokenType.OPEN_PAREN, offset));
+      Token semicolon =
+          openParen.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
+      semicolon =
+          semicolon.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
+      Token closeParen =
+          semicolon.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
+      openParen.endGroup = closeParen;
+
+      closeParen.setNext(leftParenthesis);
+      leftParenthesis = openParen;
+    }
+    token = leftParenthesis;
+
+    Token beforeIdentifier;
+    final String stringValue = token.next.stringValue;
+    if (identical(stringValue, ';')) {
+      listener.handleNoExpression(token.next);
+    } else {
+      if (identical('@', stringValue) ||
+          identical('var', stringValue) ||
+          identical('final', stringValue) ||
+          identical('const', stringValue)) {
+        token = parseMetadataStar(token);
+        beforeIdentifier = skipTypeReferenceOpt(token, false);
+        // TODO(ahe, danrubel): Generate type events and call
+        // parseVariablesDeclarationNoSemicolonRest instead.
+        token = parseVariablesDeclarationMaybeSemicolon(token, false);
+      } else {
+        beforeIdentifier = skipTypeReferenceOpt(token, false);
+        if (token == beforeIdentifier) {
+          // No type found, just parse expression
+          token = parseExpression(token);
+        } else {
+          // TODO(ahe, danrubel): Generate type events and call
+          // parseVariablesDeclarationNoSemicolonRest instead.
+          token = parseMetadataStar(token);
+          token = parseVariablesDeclarationMaybeSemicolon(token, false);
+        }
+      }
+    }
+
     Token next = token.next;
     if (optional('in', next)) {
       if (awaitToken != null && !inAsync) {
         reportRecoverableError(next, fasta.messageAwaitForNotAsync);
       }
+      if (beforeIdentifier != null &&
+          optional('=', beforeIdentifier.next.next)) {
+        reportRecoverableError(beforeIdentifier.next.next,
+            fasta.messageInitializedVariableInForEach);
+      }
       return parseForInRest(awaitToken, forKeyword, leftParenthesis, token);
     } else if (optional(':', next)) {
       reportRecoverableError(next, fasta.messageColonInPlaceOfIn);
@@ -5691,24 +5731,6 @@
     }
   }
 
-  /// ```
-  /// forInitializerStatement:
-  ///   localVariableDeclaration |
-  ///   expression? ';'
-  /// ;
-  /// ```
-  Token parseVariablesDeclarationOrExpressionOpt(Token token) {
-    Token next = token.next;
-    final String value = next.stringValue;
-    if (identical(value, ';')) {
-      listener.handleNoExpression(next);
-      return token;
-    } else if (isOneOf4(next, '@', 'var', 'final', 'const')) {
-      return parseVariablesDeclarationNoSemicolon(token);
-    }
-    return parseType(token, TypeContinuation.VariablesDeclarationOrExpression);
-  }
-
   /// This method parses the portion of the forLoopParts that starts with the
   /// first semicolon (the one that terminates the forInitializerStatement).
   ///
diff --git a/pkg/front_end/lib/src/fasta/parser/type_continuation.dart b/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
index 300d819..165353e 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
@@ -43,10 +43,6 @@
   /// identifier.
   SendOrFunctionLiteral,
 
-  /// Indicates that the parser has just parsed `for '('` and is looking to
-  /// parse a variable declaration or expression.
-  VariablesDeclarationOrExpression,
-
   /// Indicates that an optional type followed by a normal formal parameter is
   /// expected.
   NormalFormalParameter,
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index ff5906f..a8f84fd 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -553,7 +553,7 @@
         modifiers.add(Const);
       }
     }
-    push(varFinalOrConst ?? NullValue.VarFinalOrConstToken);
+    push(varFinalOrConst?.charOffset ?? -1);
     push(modifiers);
     library.beginNestedDeclaration("#method", hasMembers: false);
   }
@@ -634,7 +634,8 @@
     if ((modifiers & externalMask) != 0) {
       modifiers &= ~abstractMask;
     }
-    Token varFinalOrConst = pop(NullValue.VarFinalOrConstToken);
+    bool isConst = (modifiers & constMask) != 0;
+    int varFinalOrConstOffset = pop();
     List<MetadataBuilder> metadata = pop();
     String documentationComment = getDocumentationComment(beginToken);
     library
@@ -645,14 +646,10 @@
             ? null
             : library.computeAndValidateConstructorName(name, charOffset);
     if (constructorName != null) {
-      if (varFinalOrConst != null) {
-        if (optional('const', varFinalOrConst) &&
-            (endToken != null && !optional(';', endToken))) {
-          handleRecoverableError(messageConstConstructorWithBody,
-              varFinalOrConst, varFinalOrConst);
-          varFinalOrConst = null;
-          modifiers &= ~constMask;
-        }
+      if (isConst && bodyKind != MethodBody.Abstract) {
+        addCompileTimeError(
+            messageConstConstructorWithBody, varFinalOrConstOffset, 5);
+        modifiers &= ~constMask;
       }
       if (returnType != null) {
         // TODO(danrubel): Report this error on the return type
@@ -674,16 +671,10 @@
           endToken.charOffset,
           nativeMethodName);
     } else {
-      if (varFinalOrConst != null) {
-        if (optional('const', varFinalOrConst)) {
-          handleRecoverableError(
-              messageConstMethod, varFinalOrConst, varFinalOrConst);
-          varFinalOrConst = null;
-          modifiers &= ~constMask;
-        }
+      if (isConst) {
+        addCompileTimeError(messageConstMethod, varFinalOrConstOffset, 5);
+        modifiers &= ~constMask;
       }
-      // TODO(danrubel): report messageFieldInitializerOutsideConstructor
-      // for any parameter of the form `this.fieldName`.
       library.addProcedure(
           documentationComment,
           metadata,
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 5c2b314..9e4d468 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -51,8 +51,8 @@
       // typeInferrer to be null.  If this happens, just skip type inference for
       // this field.
       if (typeInferrer != null) {
-        var inferredType = typeInferrer.inferDeclarationType(
-            typeInferrer.inferFieldTopLevel(field, null, true));
+        var inferredType = typeInferrer
+            .inferDeclarationType(typeInferrer.inferFieldTopLevel(field, true));
         if (isCircular) {
           // Report the appropriate error.
           _library.addCompileTimeError(
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index ae22062..9cbbcb7 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -83,7 +83,7 @@
 
 import '../parser.dart' show noLength;
 
-import '../problems.dart' show unhandled;
+import '../problems.dart' show unexpected, unhandled;
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
@@ -967,8 +967,8 @@
       BuilderHelper helper, DartType declaredType, Expression initializer) {
     assert(closureContext == null);
     this.helper = helper;
-    var actualType =
-        inferExpression(initializer, declaredType, declaredType != null);
+    var actualType = inferExpression(
+        initializer, declaredType ?? const UnknownType(), declaredType != null);
     if (declaredType != null) {
       ensureAssignable(
           declaredType, actualType, initializer, initializer.fileOffset);
@@ -980,8 +980,7 @@
   ///
   /// Derived classes should provide an implementation that calls
   /// [inferExpression] for the given [field]'s initializer expression.
-  DartType inferFieldTopLevel(
-      ShadowField field, DartType type, bool typeNeeded);
+  DartType inferFieldTopLevel(ShadowField field, bool typeNeeded);
 
   @override
   void inferFunctionBody(BuilderHelper helper, DartType returnType,
@@ -1287,7 +1286,7 @@
       // replaced during type inference.
       new ListLiteral(annotations);
       for (var annotation in annotations) {
-        inferExpression(annotation, null, false);
+        inferExpression(annotation, const UnknownType(), false);
       }
       this.helper = null;
     }
@@ -1303,8 +1302,9 @@
       Name methodName,
       Arguments arguments}) {
     // First infer the receiver so we can look up the method that was invoked.
-    var receiverType =
-        receiver == null ? thisType : inferExpression(receiver, null, true);
+    var receiverType = receiver == null
+        ? thisType
+        : inferExpression(receiver, const UnknownType(), true);
     if (strongMode) {
       receiverVariable?.type = receiverType;
     }
@@ -1369,8 +1369,9 @@
       Object interfaceMember,
       Name propertyName}) {
     // First infer the receiver so we can look up the getter that was invoked.
-    var receiverType =
-        receiver == null ? thisType : inferExpression(receiver, null, true);
+    var receiverType = receiver == null
+        ? thisType
+        : inferExpression(receiver, const UnknownType(), true);
     if (strongMode) {
       receiverVariable?.type = receiverType;
     }
@@ -1691,11 +1692,28 @@
       // where the type parameters of S0&M0 are the X0, ..., Xn that occured
       // free in S0 and M0.  Treat S0 and M0 as separate supertype constraints
       // by recursively calling this algorithm.
+      //
+      // In some back ends (e.g., the Dart VM) the mixin application classes
+      // themselves are all eliminated by translating them to normal classes.
+      // In that case, the mixin appears as the only interface in the
+      // introduced class:
+      //
+      // class S0&M0<...> extends S0 implements M0 {}
+      var mixinSuperclass = mixinSupertype.classNode;
+      if (mixinSuperclass.mixedInType == null &&
+          mixinSuperclass.implementedTypes.length != 1) {
+        unexpected(
+            'Compiler-generated mixin applications have a mixin or else '
+            'implement exactly one type',
+            '$mixinSuperclass implements '
+            '${mixinSuperclass.implementedTypes.length} types',
+            mixinSuperclass.fileOffset,
+            mixinSuperclass.fileUri);
+      }
       var substitution = Substitution.fromSupertype(mixinSupertype);
-      var s0 =
-          substitution.substituteSupertype(mixinSupertype.classNode.supertype);
-      var m0 = substitution
-          .substituteSupertype(mixinSupertype.classNode.mixedInType);
+      var s0 = substitution.substituteSupertype(mixinSuperclass.supertype);
+      var m0 = substitution.substituteSupertype(mixinSuperclass.mixedInType ??
+          mixinSuperclass.implementedTypes.first);
       generateConstraints(hierarchy, mixinClass, baseType, s0);
       generateConstraints(hierarchy, mixinClass, baseType, m0);
     } else {
diff --git a/pkg/front_end/lib/src/scanner/errors.dart b/pkg/front_end/lib/src/scanner/errors.dart
index 62756b7..0e77ee52 100644
--- a/pkg/front_end/lib/src/scanner/errors.dart
+++ b/pkg/front_end/lib/src/scanner/errors.dart
@@ -130,6 +130,7 @@
 
     default:
       if (errorCode == codeUnmatchedToken) {
+        charOffset = token.begin.endToken.charOffset;
         TokenType type = token.begin?.type;
         if (type == TokenType.OPEN_CURLY_BRACKET ||
             type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
new file mode 100644
index 0000000..b03c6fa
--- /dev/null
+++ b/pkg/front_end/messages.status
@@ -0,0 +1,392 @@
+# Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Please don't add more failures to this status file of the "analyzerCode" or
+# "example" varity.
+
+AbstractClassInstantiation/analyzerCode: Fail
+AbstractClassInstantiation/example: Fail
+AbstractNotSync/analyzerCode: Fail
+AbstractNotSync/example: Fail
+AbstractRedirectedClassInstantiation/analyzerCode: Fail
+AbstractRedirectedClassInstantiation/example: Fail
+AccessError/analyzerCode: Fail
+AccessError/example: Fail
+AmbiguousSupertypes/analyzerCode: Fail
+AmbiguousSupertypes/example: Fail
+AnnotationOnEnumConstant/example: Fail
+AssertAsExpression/analyzerCode: Fail
+AssertAsExpression/example: Fail
+AssertExtraneousArgument/analyzerCode: Fail
+AssertExtraneousArgument/example: Fail
+AsyncAsIdentifier/example: Fail
+AwaitAsIdentifier/example: Fail
+AwaitNotAsync/analyzerCode: Fail
+AwaitNotAsync/example: Fail
+BuiltInIdentifierAsType/example: Fail
+BuiltInIdentifierInDeclaration/example: Fail
+CandidateFound/analyzerCode: Fail
+CandidateFound/example: Fail
+CandidateFoundIsDefaultConstructor/analyzerCode: Fail
+CandidateFoundIsDefaultConstructor/example: Fail
+CannotReadPackagesFile/analyzerCode: Fail
+CannotReadPackagesFile/example: Fail
+CannotReadSdkSpecification/analyzerCode: Fail
+CannotReadSdkSpecification/example: Fail
+CantInferPackagesFromManyInputs/analyzerCode: Fail
+CantInferPackagesFromManyInputs/example: Fail
+CantInferPackagesFromPackageUri/analyzerCode: Fail
+CantInferPackagesFromPackageUri/example: Fail
+CantInferTypeDueToCircularity/analyzerCode: Fail
+CantInferTypeDueToCircularity/example: Fail
+CantInferTypeDueToInconsistentOverrides/analyzerCode: Fail
+CantInferTypeDueToInconsistentOverrides/example: Fail
+CantUseSuperBoundedTypeForInstanceCreation/analyzerCode: Fail
+CantUseSuperBoundedTypeForInstanceCreation/example: Fail
+CatchSyntax/analyzerCode: Fail
+CatchSyntax/example: Fail
+ColonInPlaceOfIn/example: Fail
+ConflictsWithConstructor/analyzerCode: Fail
+ConflictsWithConstructor/example: Fail
+ConflictsWithFactory/analyzerCode: Fail
+ConflictsWithFactory/example: Fail
+ConflictsWithMember/analyzerCode: Fail
+ConflictsWithMember/example: Fail
+ConflictsWithMemberWarning/analyzerCode: Fail
+ConflictsWithMemberWarning/example: Fail
+ConflictsWithSetter/analyzerCode: Fail
+ConflictsWithSetter/example: Fail
+ConflictsWithSetterWarning/analyzerCode: Fail
+ConflictsWithSetterWarning/example: Fail
+ConflictsWithTypeVariable/analyzerCode: Fail
+ConflictsWithTypeVariable/example: Fail
+ConflictsWithTypeVariableCause/analyzerCode: Fail
+ConflictsWithTypeVariableCause/example: Fail
+ConstConstructorNonFinalField/analyzerCode: Fail
+ConstConstructorNonFinalField/example: Fail
+ConstConstructorNonFinalFieldCause/analyzerCode: Fail
+ConstConstructorNonFinalFieldCause/example: Fail
+ConstFieldWithoutInitializer/example: Fail
+ConstructorHasNoSuchNamedParameter/analyzerCode: Fail
+ConstructorHasNoSuchNamedParameter/example: Fail
+ConstructorNotFound/analyzerCode: Fail
+ConstructorNotFound/example: Fail
+CouldNotParseUri/analyzerCode: Fail
+CouldNotParseUri/example: Fail
+CyclicClassHierarchy/analyzerCode: Fail
+CyclicClassHierarchy/example: Fail
+CyclicTypedef/analyzerCode: Fail
+CyclicTypedef/example: Fail
+DeferredAfterPrefix/example: Fail
+DeferredPrefixDuplicated/analyzerCode: Fail
+DeferredPrefixDuplicated/example: Fail
+DeferredPrefixDuplicatedCause/analyzerCode: Fail
+DeferredPrefixDuplicatedCause/example: Fail
+DeferredTypeAnnotation/example: Fail
+DillOutlineSummary/analyzerCode: Fail
+DillOutlineSummary/example: Fail
+DuplicateDeferred/example: Fail
+DuplicatePrefix/example: Fail
+DuplicatedDefinition/analyzerCode: Fail
+DuplicatedDefinition/example: Fail
+DuplicatedExport/example: Fail
+DuplicatedExportInType/analyzerCode: Fail
+DuplicatedExportInType/example: Fail
+DuplicatedImport/analyzerCode: Fail
+DuplicatedImport/example: Fail
+DuplicatedImportInType/analyzerCode: Fail
+DuplicatedImportInType/example: Fail
+DuplicatedName/analyzerCode: Fail
+DuplicatedName/example: Fail
+DuplicatedParameterName/analyzerCode: Fail
+DuplicatedParameterName/example: Fail
+DuplicatedParameterNameCause/analyzerCode: Fail
+DuplicatedParameterNameCause/example: Fail
+Encoding/analyzerCode: Fail
+EnumConstantSameNameAsEnclosing/analyzerCode: Fail
+EnumConstantSameNameAsEnclosing/example: Fail
+ExpectedClassBody/example: Fail
+ExpectedClassMember/example: Fail
+ExpectedDeclaration/example: Fail
+ExpectedFunctionBody/example: Fail
+ExpectedOpenParens/analyzerCode: Fail
+ExpectedOpenParens/example: Fail
+ExpectedString/example: Fail
+ExpectedToken/example: Fail
+ExpectedType/example: Fail
+ExpectedUri/analyzerCode: Fail
+ExpectedUri/example: Fail
+ExportHidesExport/analyzerCode: Fail
+ExportHidesExport/example: Fail
+ExpressionNotMetadata/analyzerCode: Fail
+ExpressionNotMetadata/example: Fail
+ExtendingEnum/analyzerCode: Fail
+ExtendingEnum/example: Fail
+ExtendingRestricted/example: Fail
+ExternalFactoryRedirection/example: Fail
+FactoryNotSync/analyzerCode: Fail
+FactoryNotSync/example: Fail
+FastaCLIArgumentRequired/analyzerCode: Fail
+FastaCLIArgumentRequired/example: Fail
+FastaUsageLong/analyzerCode: Fail
+FastaUsageLong/example: Fail
+FastaUsageShort/analyzerCode: Fail
+FastaUsageShort/example: Fail
+FinalFieldWithoutInitializer/example: Fail
+FinalInstanceVariableAlreadyInitialized/analyzerCode: Fail
+FinalInstanceVariableAlreadyInitialized/example: Fail
+FinalInstanceVariableAlreadyInitializedCause/analyzerCode: Fail
+FinalInstanceVariableAlreadyInitializedCause/example: Fail
+FunctionHasNoSuchNamedParameter/analyzerCode: Fail
+FunctionHasNoSuchNamedParameter/example: Fail
+FunctionTypeDefaultValue/example: Fail
+GeneratorReturnsValue/example: Fail
+GetterNotFound/analyzerCode: Fail
+GetterNotFound/example: Fail
+GetterWithFormals/example: Fail
+IllegalMethodName/analyzerCode: Fail
+IllegalMethodName/example: Fail
+IllegalMixin/analyzerCode: Fail
+IllegalMixin/example: Fail
+IllegalMixinDueToConstructors/analyzerCode: Fail
+IllegalMixinDueToConstructors/example: Fail
+IllegalMixinDueToConstructorsCause/analyzerCode: Fail
+IllegalMixinDueToConstructorsCause/example: Fail
+ImplicitCallOfNonMethod/analyzerCode: Fail
+ImplicitCallOfNonMethod/example: Fail
+ImportHidesImport/analyzerCode: Fail
+ImportHidesImport/example: Fail
+InputFileNotFound/analyzerCode: Fail
+InputFileNotFound/example: Fail
+IntegerLiteralIsOutOfRange/example: Fail
+InternalProblemAlreadyInitialized/analyzerCode: Fail
+InternalProblemAlreadyInitialized/example: Fail
+InternalProblemBodyOnAbstractMethod/analyzerCode: Fail
+InternalProblemBodyOnAbstractMethod/example: Fail
+InternalProblemConstructorNotFound/analyzerCode: Fail
+InternalProblemConstructorNotFound/example: Fail
+InternalProblemExtendingUnmodifiableScope/analyzerCode: Fail
+InternalProblemExtendingUnmodifiableScope/example: Fail
+InternalProblemMissingContext/analyzerCode: Fail
+InternalProblemMissingContext/example: Fail
+InternalProblemMissingSeverity/analyzerCode: Fail
+InternalProblemMissingSeverity/example: Fail
+InternalProblemNotFound/analyzerCode: Fail
+InternalProblemNotFound/example: Fail
+InternalProblemNotFoundIn/analyzerCode: Fail
+InternalProblemNotFoundIn/example: Fail
+InternalProblemPreviousTokenNotFound/analyzerCode: Fail
+InternalProblemPreviousTokenNotFound/example: Fail
+InternalProblemPrivateConstructorAccess/analyzerCode: Fail
+InternalProblemPrivateConstructorAccess/example: Fail
+InternalProblemProvidedBothCompileSdkAndSdkSummary/analyzerCode: Fail
+InternalProblemProvidedBothCompileSdkAndSdkSummary/example: Fail
+InternalProblemStackNotEmpty/analyzerCode: Fail
+InternalProblemStackNotEmpty/example: Fail
+InternalProblemSuperclassNotFound/analyzerCode: Fail
+InternalProblemSuperclassNotFound/example: Fail
+InternalProblemUnexpected/analyzerCode: Fail
+InternalProblemUnexpected/example: Fail
+InternalProblemUnhandled/analyzerCode: Fail
+InternalProblemUnhandled/example: Fail
+InternalProblemUnimplemented/analyzerCode: Fail
+InternalProblemUnimplemented/example: Fail
+InternalProblemUnsupported/analyzerCode: Fail
+InternalProblemUnsupported/example: Fail
+InternalProblemUriMissingScheme/analyzerCode: Fail
+InternalProblemUriMissingScheme/example: Fail
+InternalVerificationError/analyzerCode: Fail
+InternalVerificationError/example: Fail
+InterpolationInUri/example: Fail
+InvalidCastFunctionExpr/example: Fail
+InvalidCastLiteralList/example: Fail
+InvalidCastLiteralMap/example: Fail
+InvalidCastLocalFunction/example: Fail
+InvalidCastNewExpr/example: Fail
+InvalidCastStaticMethod/example: Fail
+InvalidCastTopLevelFunction/example: Fail
+InvalidInitializer/analyzerCode: Fail
+InvalidInitializer/example: Fail
+InvalidInlineFunctionType/analyzerCode: Fail
+InvalidPackageUri/analyzerCode: Fail
+InvalidPackageUri/example: Fail
+InvalidVoid/analyzerCode: Fail
+ListLiteralTooManyTypeArguments/analyzerCode: Fail
+ListLiteralTooManyTypeArguments/example: Fail
+ListLiteralTypeArgumentMismatch/analyzerCode: Fail
+ListLiteralTypeArgumentMismatch/example: Fail
+LoadLibraryHidesMember/analyzerCode: Fail
+LoadLibraryHidesMember/example: Fail
+LoadLibraryTakesNoArguments/analyzerCode: Fail
+LoadLibraryTakesNoArguments/example: Fail
+LocalDefinitionHidesExport/analyzerCode: Fail
+LocalDefinitionHidesExport/example: Fail
+LocalDefinitionHidesImport/analyzerCode: Fail
+LocalDefinitionHidesImport/example: Fail
+MemberWithSameNameAsClass/analyzerCode: Fail
+MemberWithSameNameAsClass/example: Fail
+MetadataTypeArguments/analyzerCode: Fail
+MetadataTypeArguments/example: Fail
+MethodHasNoSuchNamedParameter/analyzerCode: Fail
+MethodHasNoSuchNamedParameter/example: Fail
+MethodNotFound/analyzerCode: Fail
+MethodNotFound/example: Fail
+MissingInput/analyzerCode: Fail
+MissingInput/example: Fail
+MissingMain/analyzerCode: Fail
+MissingMain/example: Fail
+MissingPartOf/analyzerCode: Fail
+MissingPartOf/example: Fail
+MissingPrefixInDeferredImport/example: Fail
+MixinInferenceNoMatchingClass/analyzerCode: Fail
+MixinInferenceNoMatchingClass/example: Fail
+MultipleLibraryDirectives/example: Fail
+NamedFunctionExpression/example: Fail
+NativeClauseShouldBeAnnotation/example: Fail
+NoFormals/example: Fail
+NoUnnamedConstructorInObject/analyzerCode: Fail
+NoUnnamedConstructorInObject/example: Fail
+NonInstanceTypeVariableUse/analyzerCode: Fail
+NonInstanceTypeVariableUse/example: Fail
+NotAPrefixInTypeAnnotation/example: Fail
+NotAType/example: Fail
+NotAnLvalue/analyzerCode: Fail
+NotAnLvalue/example: Fail
+OperatorMinusParameterMismatch/analyzerCode: Fail
+OperatorMinusParameterMismatch/example: Fail
+OperatorParameterMismatch0/analyzerCode: Fail
+OperatorParameterMismatch0/example: Fail
+OperatorParameterMismatch1/analyzerCode: Fail
+OperatorParameterMismatch1/example: Fail
+OperatorParameterMismatch2/analyzerCode: Fail
+OperatorParameterMismatch2/example: Fail
+OperatorWithOptionalFormals/analyzerCode: Fail
+OperatorWithOptionalFormals/example: Fail
+OverriddenMethodCause/analyzerCode: Fail
+OverriddenMethodCause/example: Fail
+OverrideFewerNamedArguments/analyzerCode: Fail
+OverrideFewerNamedArguments/example: Fail
+OverrideFewerPositionalArguments/analyzerCode: Fail
+OverrideFewerPositionalArguments/example: Fail
+OverrideMismatchNamedParameter/analyzerCode: Fail
+OverrideMismatchNamedParameter/example: Fail
+OverrideMoreRequiredArguments/analyzerCode: Fail
+OverrideMoreRequiredArguments/example: Fail
+OverrideTypeMismatchParameter/example: Fail
+OverrideTypeMismatchReturnType/example: Fail
+OverrideTypeVariablesMismatch/analyzerCode: Fail
+OverrideTypeVariablesMismatch/example: Fail
+PackageNotFound/analyzerCode: Fail
+PackageNotFound/example: Fail
+PartOfLibraryNameMismatch/analyzerCode: Fail
+PartOfLibraryNameMismatch/example: Fail
+PartOfSelf/analyzerCode: Fail
+PartOfSelf/example: Fail
+PartOfUriMismatch/analyzerCode: Fail
+PartOfUriMismatch/example: Fail
+PartOfUseUri/analyzerCode: Fail
+PartOfUseUri/example: Fail
+PartTwice/analyzerCode: Fail
+PartTwice/example: Fail
+PatchClassOrigin/analyzerCode: Fail
+PatchClassOrigin/example: Fail
+PatchClassTypeVariablesMismatch/analyzerCode: Fail
+PatchClassTypeVariablesMismatch/example: Fail
+PatchDeclarationMismatch/analyzerCode: Fail
+PatchDeclarationMismatch/example: Fail
+PatchDeclarationOrigin/analyzerCode: Fail
+PatchDeclarationOrigin/example: Fail
+PatchInjectionFailed/analyzerCode: Fail
+PatchInjectionFailed/example: Fail
+PatchNonExternal/analyzerCode: Fail
+PatchNonExternal/example: Fail
+PlatformPrivateLibraryAccess/analyzerCode: Fail
+PlatformPrivateLibraryAccess/example: Fail
+PositionalAfterNamedArgument/example: Fail
+PrefixAfterCombinator/example: Fail
+PreviousUseOfName/analyzerCode: Fail
+PreviousUseOfName/example: Fail
+PrivateNamedParameter/analyzerCode: Fail
+PrivateNamedParameter/example: Fail
+RedirectionTargetNotFound/analyzerCode: Fail
+RedirectionTargetNotFound/example: Fail
+ReturnTypeFunctionExpression/analyzerCode: Fail
+ReturnTypeFunctionExpression/example: Fail
+SdkRootNotFound/analyzerCode: Fail
+SdkRootNotFound/example: Fail
+SdkSpecificationNotFound/analyzerCode: Fail
+SdkSpecificationNotFound/example: Fail
+SdkSummaryNotFound/analyzerCode: Fail
+SdkSummaryNotFound/example: Fail
+SetterNotFound/analyzerCode: Fail
+SetterNotFound/example: Fail
+SetterNotSync/example: Fail
+SetterWithWrongNumberOfFormals/example: Fail
+SourceBodySummary/analyzerCode: Fail
+SourceBodySummary/example: Fail
+SourceOutlineSummary/analyzerCode: Fail
+SourceOutlineSummary/example: Fail
+StackOverflow/analyzerCode: Fail
+StackOverflow/example: Fail
+SuperAsExpression/analyzerCode: Fail
+SuperAsExpression/example: Fail
+SuperAsIdentifier/analyzerCode: Fail
+SuperAsIdentifier/example: Fail
+SuperNullAware/example: Fail
+SuperclassHasNoDefaultConstructor/example: Fail
+SuperclassHasNoGetter/analyzerCode: Fail
+SuperclassHasNoGetter/example: Fail
+SuperclassHasNoMethod/example: Fail
+SuperclassHasNoSetter/analyzerCode: Fail
+SuperclassHasNoSetter/example: Fail
+SuperclassMethodArgumentMismatch/analyzerCode: Fail
+SuperclassMethodArgumentMismatch/example: Fail
+SupertypeIsFunction/analyzerCode: Fail
+SupertypeIsFunction/example: Fail
+SupertypeIsIllegal/analyzerCode: Fail
+SupertypeIsIllegal/example: Fail
+SupertypeIsTypeVariable/analyzerCode: Fail
+SupertypeIsTypeVariable/example: Fail
+SwitchCaseFallThrough/analyzerCode: Fail
+SwitchCaseFallThrough/example: Fail
+ThisAccessInFieldInitializer/analyzerCode: Fail
+ThisAccessInFieldInitializer/example: Fail
+ThisAsIdentifier/analyzerCode: Fail
+ThisAsIdentifier/example: Fail
+TooFewArgumentsToConstructor/analyzerCode: Fail
+TooFewArgumentsToConstructor/example: Fail
+TooFewArgumentsToFunction/analyzerCode: Fail
+TooFewArgumentsToFunction/example: Fail
+TooFewArgumentsToMethod/analyzerCode: Fail
+TooFewArgumentsToMethod/example: Fail
+TooManyArgumentsToConstructor/analyzerCode: Fail
+TooManyArgumentsToConstructor/example: Fail
+TooManyArgumentsToFunction/analyzerCode: Fail
+TooManyArgumentsToFunction/example: Fail
+TooManyArgumentsToMethod/analyzerCode: Fail
+TooManyArgumentsToMethod/example: Fail
+TypeAfterVar/example: Fail
+TypeArgumentMismatch/analyzerCode: Fail
+TypeArgumentMismatch/example: Fail
+TypeNotFound/analyzerCode: Fail
+TypeNotFound/example: Fail
+TypeVariableDuplicatedName/analyzerCode: Fail
+TypeVariableDuplicatedName/example: Fail
+TypeVariableDuplicatedNameCause/analyzerCode: Fail
+TypeVariableDuplicatedNameCause/example: Fail
+TypeVariableInStaticContext/analyzerCode: Fail
+TypeVariableInStaticContext/example: Fail
+TypeVariableSameNameAsEnclosing/analyzerCode: Fail
+TypeVariableSameNameAsEnclosing/example: Fail
+TypedefNotFunction/analyzerCode: Fail
+TypedefNotFunction/example: Fail
+UnexpectedDollarInString/analyzerCode: Fail
+UnmatchedToken/analyzerCode: Fail
+UnresolvedPrefixInTypeAnnotation/example: Fail
+Unspecified/analyzerCode: Fail
+Unspecified/example: Fail
+UnterminatedToken/analyzerCode: Fail
+UnterminatedToken/example: Fail
+YieldAsIdentifier/example: Fail
+YieldNotGenerator/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 0cb16f1c..edbcd7b 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -408,7 +408,7 @@
   analyzerCode: CONST_METHOD
   dart2jsCode: "*fatal*"
   script:
-    - "class C { const C() {} }"
+    - "class C { const m() {} }"
 
 CovariantAfterFinal:
   template: "The modifier 'covariant' should be before the modifier 'final'."
@@ -615,6 +615,14 @@
   script:
     - "main() { switch (x) {case 1: continue;} }"
 
+InitializedVariableInForEach:
+  template: "The loop variable in a for-each loop can't be initialized."
+  tip: "Try removing the initializer, or using a different kind of loop."
+  analyzerCode: INITIALIZED_VARIABLE_IN_FOR_EACH
+  dart2jsCode: "*fatal*"
+  statement:
+    - "for (int a = 0 in <int>[10]) {}"
+
 InvalidAwaitFor:
   template: "The keyword 'await' isn't allowed for a normal 'for' statement."
   tip: "Try removing the keyword, or use a for-each statement."
@@ -939,11 +947,11 @@
   analyzerCode: CONSTRUCTOR_WITH_RETURN_TYPE
   dart2jsCode: "*fatal*"
   script:
-    - "class C { T C() {} }"
+    - "class C { int C() {} }"
 
 FieldInitializerOutsideConstructor:
   template: "Field formal parameters can only be used in a constructor."
-  tip: "Try replacing the field formal parameter with a normal parameter."
+  tip: "Try removing 'this.'."
   analyzerCode: FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
   dart2jsCode: "*fatal*"
   script:
@@ -1831,6 +1839,8 @@
 
 InterpolationInUri:
   template: "Can't use string interpolation in a URI."
+  analyzerCode: INVALID_LITERAL_IN_CONFIGURATION
+  dart2jsCode: "*fatal*"
 
 IntegerLiteralIsOutOfRange:
   template: "The integer literal #lexeme can't be represented in 64 bits."
diff --git a/pkg/front_end/test/fasta/messages_test.dart b/pkg/front_end/test/fasta/messages_test.dart
index 7217879..9e46ca3 100644
--- a/pkg/front_end/test/fasta/messages_test.dart
+++ b/pkg/front_end/test/fasta/messages_test.dart
@@ -2,76 +2,299 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:io';
+import "dart:async" show Future, Stream;
 
-import 'package:front_end/src/testing/package_root.dart' as package_root;
-import 'package:path/path.dart' as path;
-import 'package:yaml/yaml.dart' show loadYaml;
+import "dart:convert" show utf8;
 
-main([List<String> arguments = const []]) async {
-  File file = new File(
-      path.join(package_root.packageRoot, 'front_end', 'messages.yaml'));
-  if (!await file.exists()) {
-    file = new File.fromUri(Uri.base.resolve('messages.yaml'));
-  }
-  Map yaml = loadYaml(await file.readAsString());
+import "dart:io" show File;
 
-  int untestedExampleCount = 0;
-  int missingExamplesCount = 0;
-  int missingAnalyzerCode = 0;
-  List<String> keysWithAnalyzerCodeButNoDart2JsCode = <String>[];
-  List<String> keys = yaml.keys.toList()..sort();
-  for (String name in keys) {
-    var description = yaml[name];
-    while (description is String) {
-      description = yaml[description];
-    }
-    Map map = description;
+import "dart:typed_data" show Uint8List;
 
-    int localUntestedExampleCount = countExamples(map, name, 'bytes');
-    localUntestedExampleCount += countExamples(map, name, 'declaration');
-    localUntestedExampleCount += countExamples(map, name, 'expression');
-    localUntestedExampleCount += countExamples(map, name, 'script');
-    localUntestedExampleCount += countExamples(map, name, 'statement');
-    if (localUntestedExampleCount == 0) ++missingExamplesCount;
-    untestedExampleCount += localUntestedExampleCount;
+import "package:testing/testing.dart"
+    show Chain, ChainContext, Result, Step, TestDescription, runMe;
 
-    if (map['analyzerCode'] == null) {
-      ++missingAnalyzerCode;
-    } else {
-      if (map['dart2jsCode'] == null) {
-        keysWithAnalyzerCodeButNoDart2JsCode.add(name);
+import "package:yaml/yaml.dart" show loadYaml;
+
+class MessageTestDescription extends TestDescription {
+  @override
+  final Uri uri;
+
+  @override
+  final String shortName;
+
+  final String name;
+
+  final Map data;
+
+  final Example example;
+
+  final String problem;
+
+  MessageTestDescription(this.uri, this.shortName, this.name, this.data,
+      this.example, this.problem);
+}
+
+class MessageTestSuite extends ChainContext {
+  final List<Step> steps = const <Step>[
+    const Validate(),
+    const Compile(),
+  ];
+
+  /// Convert all the examples found in `messages.yaml` to a test
+  /// description. In addition, for each problem found, create a test
+  /// description that has a problem. This problem will then be reported as a
+  /// failure by the [Validate] step that can be suppressed via the status
+  /// file.
+  Stream<MessageTestDescription> list(Chain suite) async* {
+    Uri uri = suite.uri.resolve("messages.yaml");
+    File file = new File.fromUri(uri);
+    Map yaml = loadYaml(await file.readAsString());
+    for (String name in yaml.keys) {
+      var data = yaml[name];
+      if (data is String) continue;
+
+      List<String> unknownKeys = <String>[];
+      List<Example> examples = <Example>[];
+      String analyzerCode;
+      String dart2jsCode;
+
+      for (String key in data.keys) {
+        var value = data[key];
+        switch (key) {
+          case "template":
+          case "tip":
+          case "severity":
+            break;
+
+          case "analyzerCode":
+            analyzerCode = value;
+            break;
+
+          case "dart2jsCode":
+            dart2jsCode = value;
+            break;
+
+          case "bytes":
+            if (value.first is List) {
+              for (List bytes in value) {
+                int i = 0;
+                examples.add(new BytesExample("bytes${++i}", name, bytes));
+              }
+            } else {
+              examples.add(new BytesExample("bytes", name, value));
+            }
+            break;
+
+          case "declaration":
+            if (value is List) {
+              int i = 0;
+              for (String declaration in value) {
+                examples.add(new DeclarationExample(
+                    "declaration${++i}", name, declaration));
+              }
+            } else {
+              examples.add(new DeclarationExample("declaration", name, value));
+            }
+            break;
+
+          case "expression":
+            if (value is List) {
+              int i = 0;
+              for (String expression in value) {
+                examples.add(new ExpressionExample(
+                    "expression${++i}", name, expression));
+              }
+            } else {
+              examples.add(new ExpressionExample("expression", name, value));
+            }
+            break;
+
+          case "script":
+            if (value is List) {
+              int i = 0;
+              for (String script in value) {
+                examples.add(new ScriptExample("script${++i}", name, script));
+              }
+            } else {
+              examples.add(new ScriptExample("script", name, value));
+            }
+            break;
+
+          case "statement":
+            if (value is List) {
+              int i = 0;
+              for (String statement in value) {
+                examples.add(
+                    new StatementExample("statement${++i}", name, statement));
+              }
+            } else {
+              examples.add(new StatementExample("statement", name, value));
+            }
+            break;
+
+          default:
+            unknownKeys.add(key);
+        }
+      }
+
+      MessageTestDescription createDescription(
+          String subName, Example example, String problem) {
+        String shortName = "$name/$subName";
+        if (problem != null) {
+          String base = "${Uri.base}";
+          String filename = "$uri";
+          if (filename.startsWith(base)) {
+            filename = filename.substring(base.length);
+          }
+          var location = data.span.start;
+          int line = location.line;
+          int column = location.column;
+          problem = "$filename:$line:$column: error:\n$problem";
+        }
+        return new MessageTestDescription(uri.resolve("#$shortName"), shortName,
+            name, data, example, problem);
+      }
+
+      for (Example example in examples) {
+        yield createDescription(example.name, example, null);
+      }
+
+      if (unknownKeys.isNotEmpty) {
+        yield createDescription(
+            "knownKeys", null, "Unknown keys: ${unknownKeys.join(' ')}");
+      }
+
+      if (examples.isEmpty) {
+        yield createDescription("example", null, "No example for $name");
+      }
+
+      if (analyzerCode == null) {
+        yield createDescription(
+            "analyzerCode", null, "No analyzer code for $name");
+      } else {
+        if (dart2jsCode == null) {
+          yield createDescription(
+              "dart2jsCode", null, "No dart2js code for $name");
+        }
       }
     }
   }
+}
 
-  if (keysWithAnalyzerCodeButNoDart2JsCode.isNotEmpty) {
-    print('${keysWithAnalyzerCodeButNoDart2JsCode.length}'
-        ' error codes have an analyzerCode but no dart2jsCode:');
-    for (String name in keysWithAnalyzerCodeButNoDart2JsCode) {
-      print('  $name');
-    }
-    print('');
+abstract class Example {
+  final String name;
+
+  final String expectedCode;
+
+  Example(this.name, this.expectedCode);
+
+  Uint8List get bytes;
+}
+
+class BytesExample extends Example {
+  @override
+  final Uint8List bytes;
+
+  BytesExample(String name, String code, List bytes)
+      : bytes = new Uint8List.fromList(bytes),
+        super(name, code);
+}
+
+class DeclarationExample extends Example {
+  final String declaration;
+
+  DeclarationExample(String name, String code, this.declaration)
+      : super(name, code);
+
+  @override
+  Uint8List get bytes {
+    return new Uint8List.fromList(utf8.encode("""
+$declaration
+
+main() {
+}
+"""));
   }
-  print('$untestedExampleCount examples not tested');
-  print('$missingExamplesCount error codes missing examples');
-  print('$missingAnalyzerCode error codes missing analyzer code');
-
-  // TODO(danrubel): Update this to assert each count == 0 and stays zero.
-  exit(keysWithAnalyzerCodeButNoDart2JsCode.isEmpty &&
-          untestedExampleCount > 0 &&
-          missingExamplesCount > 0 &&
-          missingAnalyzerCode > 0
-      ? 0
-      : 1);
 }
 
-int countExamples(Map map, String name, String key) {
-  var example = map[key];
-  if (example == null) return 0;
-  if (example is String) return 1;
-  if (example is List) return example.length;
-  if (example is Map) return example.length;
+class StatementExample extends Example {
+  final String statement;
 
-  throw 'Unknown value for $name $key --> ${example.runtimeType}\n  $example';
+  StatementExample(String name, String code, this.statement)
+      : super(name, code);
+
+  @override
+  Uint8List get bytes {
+    return new Uint8List.fromList(utf8.encode("""
+main() {
+  $statement
 }
+"""));
+  }
+}
+
+class ExpressionExample extends Example {
+  final String expression;
+
+  ExpressionExample(String name, String code, this.expression)
+      : super(name, code);
+
+  @override
+  Uint8List get bytes {
+    return new Uint8List.fromList(utf8.encode("""
+main() {
+  $expression;
+}
+"""));
+  }
+}
+
+class ScriptExample extends Example {
+  final String script;
+
+  ScriptExample(String name, String code, this.script) : super(name, code);
+
+  @override
+  Uint8List get bytes {
+    return new Uint8List.fromList(utf8.encode(script));
+  }
+}
+
+class Validate extends Step<MessageTestDescription, Example, MessageTestSuite> {
+  const Validate();
+
+  String get name => "validate";
+
+  Future<Result<Example>> run(
+      MessageTestDescription description, MessageTestSuite suite) async {
+    if (description.problem != null) {
+      return fail(null, description.problem);
+    } else {
+      return pass(description.example);
+    }
+  }
+}
+
+class Compile extends Step<Example, Null, MessageTestSuite> {
+  const Compile();
+
+  String get name => "compile";
+
+  Future<Result<Null>> run(Example example, MessageTestSuite suite) async {
+    // TODO(ahe): This is where I should actually compile the example and
+    // verify that only one message is reported, and it is the expected
+    // message.
+    if (example is! BytesExample) {
+      print(utf8.decode(example.bytes));
+    }
+    return pass(null);
+  }
+}
+
+Future<MessageTestSuite> createContext(
+    Chain suite, Map<String, String> environment) async {
+  return new MessageTestSuite();
+}
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, "../../testing.json");
diff --git a/pkg/front_end/test/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
index 99fe3f2..5236bed 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -22,17 +22,75 @@
 Directory outDir;
 
 main() async {
+  await runPassingTest(testDart2jsCompile);
+  await runPassingTest(testDisappearingLibrary);
+  await runPassingTest(testDeferredLibrary);
+  await runPassingTest(testStrongModeMixins);
+}
+
+void runFailingTest(dynamic test, String expectContains) async {
+  try {
+    await runPassingTest(test);
+    throw "Expected this to fail.";
+  } catch (e) {
+    if (e.toString().contains(expectContains)) {
+      print("got expected error as this test is currently failing");
+    } else {
+      rethrow;
+    }
+  }
+}
+
+void runPassingTest(dynamic test) async {
   outDir =
       Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
   try {
-    await testDart2jsCompile();
-    await testDisappearingLibrary();
-    await testDeferredLibrary();
+    await test();
+    print("----");
   } finally {
     outDir.deleteSync(recursive: true);
   }
 }
 
+/// Compile in strong mode. Invalidate a file so type inferrer starts
+/// on something compiled from source and (potentially) goes into
+/// something loaded from dill.
+void testStrongModeMixins() async {
+  final Uri a = outDir.uri.resolve("testStrongModeMixins_a.dart");
+  final Uri b = outDir.uri.resolve("testStrongModeMixins_b.dart");
+
+  Uri output = outDir.uri.resolve("testStrongModeMixins_full.dill");
+  Uri bootstrappedOutput =
+      outDir.uri.resolve("testStrongModeMixins_full_from_bootstrap.dill");
+
+  new File.fromUri(a).writeAsStringSync("""
+    import 'testStrongModeMixins_b.dart';
+    class A extends Object with B<Object>, C {}
+    """);
+  new File.fromUri(b).writeAsStringSync("""
+    abstract class C<T extends Object> extends Object with B<T> {}
+    abstract class B<ChildType extends Object> extends Object {}
+    """);
+
+  Stopwatch stopwatch = new Stopwatch()..start();
+  await normalCompile(a, output, options: getOptions()..strongMode = true);
+  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
+
+  stopwatch.reset();
+  bool bootstrapResult = await bootstrapCompile(
+      a, bootstrappedOutput, output, [a],
+      performSizeTests: false, options: getOptions()..strongMode = true);
+  print("Bootstrapped compile(s) from ${output.pathSegments.last} "
+      "took ${stopwatch.elapsedMilliseconds} ms");
+  Expect.isTrue(bootstrapResult);
+
+  // Compare the two files.
+  List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
+  List<int> bootstrappedDillData =
+      new File.fromUri(bootstrappedOutput).readAsBytesSync();
+  checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
+}
+
 /// Test loading from a dill file with a deferred library.
 /// This is done by bootstrapping with no changes.
 void testDeferredLibrary() async {
@@ -169,7 +227,9 @@
     options.sdkSummary = sdkSummary;
     IncrementalCompiler compiler =
         new IncrementalKernelGenerator(options, main);
+    Stopwatch stopwatch = new Stopwatch()..start();
     var program = await compiler.computeDelta();
+    print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
     libCount2 = serializeProgram(program);
     if (program.libraries.length != 2) {
       throw "Expected 2 libraries, got ${program.libraries.length}";
@@ -199,7 +259,9 @@
         new IncrementalKernelGenerator(options, b, bootstrap);
     compiler.invalidate(main);
     compiler.invalidate(b);
+    Stopwatch stopwatch = new Stopwatch()..start();
     var program = await compiler.computeDelta();
+    print("Bootstrapped compile took ${stopwatch.elapsedMilliseconds} ms");
     if (program.libraries.length != 1) {
       throw "Expected 1 library, got ${program.libraries.length}";
     }
@@ -215,8 +277,9 @@
   return options;
 }
 
-Future<bool> normalCompile(Uri input, Uri output) async {
-  CompilerOptions options = getOptions();
+Future<bool> normalCompile(Uri input, Uri output,
+    {CompilerOptions options}) async {
+  options ??= getOptions();
   IncrementalCompiler compiler = new IncrementalKernelGenerator(options, input);
   var y = await compiler.computeDelta();
   await writeProgramToFile(y, output);
@@ -225,8 +288,8 @@
 
 Future<bool> bootstrapCompile(
     Uri input, Uri output, Uri bootstrapWith, List<Uri> invalidateUris,
-    {bool performSizeTests: true}) async {
-  CompilerOptions options = getOptions();
+    {bool performSizeTests: true, CompilerOptions options}) async {
+  options ??= getOptions();
   IncrementalCompiler compiler =
       new IncrementalKernelGenerator(options, input, bootstrapWith);
   for (Uri invalidateUri in invalidateUris) {
diff --git a/pkg/front_end/test/scanner_fasta_test.dart b/pkg/front_end/test/scanner_fasta_test.dart
index 683f559..c21bdc9 100644
--- a/pkg/front_end/test/scanner_fasta_test.dart
+++ b/pkg/front_end/test/scanner_fasta_test.dart
@@ -299,8 +299,8 @@
     expect(openBrace.endToken, same(closeBrace));
     expect(openParen2.endToken, same(closeParen2));
     listener.assertErrors([
-      new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, [')']),
-      new TestError(5, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+      new TestError(6, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+      new TestError(7, ScannerErrorCode.EXPECTED_TOKEN, [')']),
     ]);
   }
 
@@ -335,9 +335,9 @@
     expect(openBracket.endToken, same(closeBracket));
     expect(openParen.endToken, same(closeParen));
     listener.assertErrors([
-      new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
-      new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [']']),
-      new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+      new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
+      new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, [']']),
+      new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, [')']),
     ]);
   }
 }
diff --git a/pkg/front_end/test/scanner_replacement_test.dart b/pkg/front_end/test/scanner_replacement_test.dart
index 824a1d3..9cfcb94 100644
--- a/pkg/front_end/test/scanner_replacement_test.dart
+++ b/pkg/front_end/test/scanner_replacement_test.dart
@@ -86,7 +86,7 @@
     expect(open.isSynthetic, isFalse);
     expect(close.isSynthetic, isTrue);
     listener.assertErrors([
-      new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, [expectedCloser]),
+      new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [expectedCloser]),
     ]);
   }
 
@@ -176,8 +176,8 @@
     expect(closeParen2.isSynthetic, isTrue);
     expect(eof.isEof, isTrue);
     listener.assertErrors([
-      new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, [')']),
-      new TestError(5, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+      new TestError(6, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+      new TestError(7, ScannerErrorCode.EXPECTED_TOKEN, [')']),
     ]);
   }
 
@@ -200,9 +200,9 @@
     expect(eof.isEof, true);
 
     listener.assertErrors([
-      new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, [')']),
-      new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [']']),
-      new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
+      new TestError(4, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+      new TestError(4, ScannerErrorCode.EXPECTED_TOKEN, [']']),
+      new TestError(4, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
     ]);
   }
 
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index d1ec614..861b2fd 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_test.dart
@@ -451,7 +451,7 @@
         new SyntheticStringToken(TokenType.STRING, "\"", 10, 0),
       ]);
       expectedErrors.addAll([
-        new TestError(5, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
+        new TestError(10, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
       ]);
     } else {
       expectedTokens.addAll([
@@ -823,7 +823,7 @@
       expect(openBracket.endToken, same(closeBracket));
       expect(openParen.endToken, same(closeParen));
       listener.assertErrors([
-        new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+        new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, [')']),
       ]);
     } else {
       var closeBracket = openParen.next;
@@ -855,7 +855,7 @@
       expect(openBracket.endToken, closeBracket);
       expect(openParen.endToken, closeParen);
       listener.assertErrors([
-        new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [']']),
+        new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, [']']),
       ]);
     } else {
       var closeParen = openBracket.next;
@@ -1095,7 +1095,7 @@
         new SyntheticStringToken(TokenType.STRING, "'''", 9, 0),
       ]);
       expectedErrors.addAll([
-        new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
+        new TestError(9, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
       ]);
     } else {
       expectedTokens.addAll([
@@ -1369,7 +1369,7 @@
         new SyntheticStringToken(TokenType.STRING, "'", 7, 0),
       ]);
       expectedErrors.addAll([
-        new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
+        new TestError(7, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
       ]);
     } else {
       expectedTokens.addAll([
diff --git a/pkg/front_end/testcases/inference/bug32291.dart b/pkg/front_end/testcases/inference/bug32291.dart
new file mode 100644
index 0000000..d3a62f5
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug32291.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*@testedFeatures=inference*/
+library test;
+
+void main() {
+  var /*@type=List<List<String>>*/ l = /*@typeArgs=List<String>*/ [
+    /*@typeArgs=String*/ ["hi", "world"]
+  ];
+  var /*@type=Iterable<List<String>>*/ i1 =
+      l. /*@target=Iterable::map*/ /*@typeArgs=List<String>*/ map(
+          /*@returnType=List<String>*/ (/*@type=List<String>*/ ll) =>
+              ll ?? /*@typeArgs=String*/ []);
+  var /*@type=Iterable<int>*/ i2 =
+      i1. /*@target=Iterable::map*/ /*@typeArgs=int*/ map(
+          /*@returnType=int*/ (List<String> l) =>
+              l. /*@target=List::length*/ length);
+  print(i2);
+}
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.direct.expect b/pkg/front_end/testcases/inference/bug32291.dart.direct.expect
new file mode 100644
index 0000000..f2dc0b2
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug32291.dart.direct.expect
@@ -0,0 +1,10 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static method main() → void {
+  dynamic l = <dynamic>[<dynamic>["hi", "world"]];
+  dynamic i1 = l.map((dynamic ll) → dynamic => let final dynamic #t1 = ll in #t1.==(null) ? <dynamic>[] : #t1);
+  dynamic i2 = i1.map((core::List<core::String> l) → dynamic => l.length);
+  core::print(i2);
+}
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.outline.expect b/pkg/front_end/testcases/inference/bug32291.dart.outline.expect
new file mode 100644
index 0000000..27b374a
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug32291.dart.outline.expect
@@ -0,0 +1,5 @@
+library test;
+import self as self;
+
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.strong.expect b/pkg/front_end/testcases/inference/bug32291.dart.strong.expect
new file mode 100644
index 0000000..6193515
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug32291.dart.strong.expect
@@ -0,0 +1,10 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static method main() → void {
+  core::List<core::List<core::String>> l = <core::List<core::String>>[<core::String>["hi", "world"]];
+  core::Iterable<core::List<core::String>> i1 = l.{core::Iterable::map}<core::List<core::String>>((core::List<core::String> ll) → core::List<core::String> => let final core::List<core::String> #t1 = ll in #t1.==(null) ?{core::List<core::String>} <core::String>[] : #t1);
+  core::Iterable<core::int> i2 = i1.{core::Iterable::map}<core::int>((core::List<core::String> l) → core::int => l.{core::List::length});
+  core::print(i2);
+}
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 8168094..b1fadda 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -6,6 +6,17 @@
   "packages": "../../.packages",
 
   "suites": [
+    {
+      "name": "messages",
+      "kind": "Chain",
+      "source": "test/fasta/messages_test.dart",
+      "path": "./",
+      "status": "messages.status",
+      "pattern": [
+      ],
+      "exclude": [
+      ]
+    },
 
     {
       "name": "scanner",
@@ -254,14 +265,16 @@
       "lib/",
       "tool/",
       "test/",
-      "../kernel/lib/"
+      "../kernel/lib/",
+      "../testing/"
     ],
 
     "git grep": {
       "pathspecs": [ "*.dart" ],
       "patterns": [
         "package:front_end/",
-        "package:kernel/"
+        "package:kernel/",
+        "package:testing/"
       ]
     },
 
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 95c0b5f..ab5b52f 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -188,7 +188,7 @@
 }
 
 abstract class FileUriNode extends TreeNode {
-  /// The uri of the source file this node was loaded from.
+  /// The URI of the source file this node was loaded from.
   Uri get fileUri;
 }
 
@@ -275,7 +275,7 @@
   /// If the URI has the `app` scheme, it is relative to the application root.
   Uri importUri;
 
-  /// The uri of the source file this library was loaded from.
+  /// The URI of the source file this library was loaded from.
   Uri fileUri;
 
   /// If true, the library is part of another build unit and its contents
@@ -575,7 +575,7 @@
 
 /// Declaration of a type alias.
 class Typedef extends NamedNode implements FileUriNode {
-  /// The uri of the source file that contains the declaration of this typedef.
+  /// The URI of the source file that contains the declaration of this typedef.
   Uri fileUri;
   List<Expression> annotations = const <Expression>[];
   String name;
@@ -717,7 +717,7 @@
   /// All X&Y classes are marked as synthetic.
   bool isSyntheticMixinImplementation;
 
-  /// The uri of the source file this class was loaded from.
+  /// The URI of the source file this class was loaded from.
   Uri fileUri;
 
   final List<TypeParameter> typeParameters;
@@ -938,7 +938,7 @@
 // ------------------------------------------------------------------------
 
 @coq
-abstract class Member extends NamedNode {
+abstract class Member extends NamedNode implements FileUriNode {
   /// End offset in the source file it comes from. Valid values are from 0 and
   /// up, or -1 ([TreeNode.noOffset]) if the file end offset is not available
   /// (this is the default if none is specifically set).
@@ -953,6 +953,9 @@
 
   Name name;
 
+  /// The URI of the source file this member was loaded from.
+  Uri fileUri;
+
   /// Flags summarizing the kinds of AST nodes contained in this member, for
   /// speeding up transformations that only affect certain types of nodes.
   ///
@@ -970,7 +973,7 @@
   // TODO(asgerf): It might be worthwhile to put this on classes as well.
   int transformerFlags = 0;
 
-  Member(this.name, Reference reference) : super(reference);
+  Member(this.name, this.fileUri, Reference reference) : super(reference);
 
   Class get enclosingClass => parent is Class ? parent : null;
   Library get enclosingLibrary => parent is Class ? parent.parent : parent;
@@ -1034,15 +1037,12 @@
 ///
 /// The implied getter and setter for the field are not represented explicitly,
 /// but can be made explicit if needed.
-class Field extends Member implements FileUriNode {
+class Field extends Member {
   DartType type; // Not null. Defaults to DynamicType.
   int flags = 0;
   int flags2 = 0;
   Expression initializer; // May be null.
 
-  /// The uri of the source file this field was loaded from.
-  Uri fileUri;
-
   Field(Name name,
       {this.type: const DynamicType(),
       this.initializer,
@@ -1053,9 +1053,9 @@
       bool hasImplicitGetter,
       bool hasImplicitSetter,
       int transformerFlags: 0,
-      this.fileUri,
+      Uri fileUri,
       Reference reference})
-      : super(name, reference) {
+      : super(name, fileUri, reference) {
     assert(type != null);
     initializer?.parent = this;
     this.isCovariant = isCovariant;
@@ -1222,14 +1222,11 @@
 /// invocation should be matched with the type parameters declared in the class.
 ///
 /// For unnamed constructors, the name is an empty string (in a [Name]).
-class Constructor extends Member implements FileUriNode {
+class Constructor extends Member {
   int flags = 0;
   FunctionNode function;
   List<Initializer> initializers;
 
-  /// The uri of the source file this field was loaded from.
-  Uri fileUri;
-
   Constructor(this.function,
       {Name name,
       bool isConst: false,
@@ -1237,10 +1234,10 @@
       bool isSynthetic: false,
       List<Initializer> initializers,
       int transformerFlags: 0,
-      this.fileUri,
+      Uri fileUri,
       Reference reference})
       : this.initializers = initializers ?? <Initializer>[],
-        super(name, reference) {
+        super(name, fileUri, reference) {
     function?.parent = this;
     setParents(this.initializers, this);
     this.isConst = isConst;
@@ -1326,12 +1323,9 @@
 ///
 /// Redirecting factory constructors can be unnamed.  In this case, the name is
 /// an empty string (in a [Name]).
-class RedirectingFactoryConstructor extends Member implements FileUriNode {
+class RedirectingFactoryConstructor extends Member {
   int flags = 0;
 
-  /// The uri of the source file this field was loaded from.
-  Uri fileUri;
-
   /// [RedirectingFactoryConstructor]s may redirect to constructors or factories
   /// of instantiated generic types, that is, generic types with supplied type
   /// arguments.  The supplied type arguments are stored in this field.
@@ -1367,7 +1361,7 @@
       List<VariableDeclaration> positionalParameters,
       List<VariableDeclaration> namedParameters,
       int requiredParameterCount,
-      this.fileUri,
+      Uri fileUri,
       Reference reference})
       : this.typeArguments = typeArguments ?? <DartType>[],
         this.typeParameters = typeParameters ?? <TypeParameter>[],
@@ -1376,7 +1370,7 @@
         this.namedParameters = namedParameters ?? <VariableDeclaration>[],
         this.requiredParameterCount =
             requiredParameterCount ?? positionalParameters?.length ?? 0,
-        super(name, reference) {
+        super(name, fileUri, reference) {
     setParents(this.typeParameters, this);
     setParents(this.positionalParameters, this);
     setParents(this.namedParameters, this);
@@ -1454,7 +1448,7 @@
 /// For operators, this is the token for the operator, e.g. `+` or `==`,
 /// except for the unary minus operator, whose name is `unary-`.
 @coq
-class Procedure extends Member implements FileUriNode {
+class Procedure extends Member {
   ProcedureKind kind;
   int flags = 0;
   // function is null if and only if abstract, external.
@@ -1483,9 +1477,6 @@
     super.transformerFlags = newValue;
   }
 
-  /// The uri of the source file this procedure was loaded from.
-  Uri fileUri;
-
   Reference forwardingStubSuperTargetReference;
   Reference forwardingStubInterfaceTargetReference;
 
@@ -1524,11 +1515,11 @@
       bool isForwardingStub: false,
       bool isForwardingSemiStub: false,
       int transformerFlags: 0,
-      this.fileUri,
+      Uri fileUri,
       Reference reference,
       this.forwardingStubSuperTargetReference,
       this.forwardingStubInterfaceTargetReference})
-      : super(name, reference) {
+      : super(name, fileUri, reference) {
     function?.parent = this;
     this.isAbstract = isAbstract;
     this.isStatic = isStatic;
@@ -5564,8 +5555,8 @@
 
   final List<Library> libraries;
 
-  /// Map from a source file uri to a line-starts table and source code.
-  /// Given a source file uri and a offset in that file one can translate
+  /// Map from a source file URI to a line-starts table and source code.
+  /// Given a source file URI and a offset in that file one can translate
   /// it to a line:column position in that file.
   final Map<Uri, Source> uriToSource;
 
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 2fa7f84..1fbd076 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -195,9 +195,9 @@
 unittest/*: Skip # Issue 21949
 
 [ $runtime == vm && $system == windows ]
-analysis_server/*: Skip # Issue 27557
 analysis_server/test/analysis/get_errors_test: Skip # runtime error, Issue 22180
-analysis_server/test/integration/analysis/analysis_options_test: RuntimeError # Issue 24796
+analysis_server/test/benchmarks_test: RuntimeError # Issue 32355
+analysis_server/test/integration/*: Skip # Issue 32356
 analyzer/test/generated/non_error_resolver_kernel_test: RuntimeError # Issue 30785
 analyzer/test/src/task/strong/checker_test: Pass, Slow
 analyzer/tool/task_dependency_graph/check_test: Slow, Pass
diff --git a/pkg/testing/lib/dart_vm_suite.dart b/pkg/testing/lib/dart_vm_suite.dart
index 37a1d24..09ed485 100644
--- a/pkg/testing/lib/dart_vm_suite.dart
+++ b/pkg/testing/lib/dart_vm_suite.dart
@@ -15,12 +15,13 @@
   final List<Step> steps = const <Step>[const DartVmStep()];
 }
 
-class DartVmStep extends Step<TestDescription, int, VmContext> {
+class DartVmStep extends Step<FileBasedTestDescription, int, VmContext> {
   const DartVmStep();
 
   String get name => "Dart VM";
 
-  Future<Result<int>> run(TestDescription input, VmContext context) async {
+  Future<Result<int>> run(
+      FileBasedTestDescription input, VmContext context) async {
     StdioProcess process = await StdioProcess.run("dart", [input.file.path]);
     return process.toResult();
   }
diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart
index 15d74ac..f93a31b 100644
--- a/pkg/testing/lib/src/chain.dart
+++ b/pkg/testing/lib/src/chain.dart
@@ -12,7 +12,7 @@
 
 import 'suite.dart' show Suite;
 
-import '../testing.dart' show TestDescription;
+import '../testing.dart' show FileBasedTestDescription, TestDescription;
 
 import 'test_dart/status_file_parser.dart'
     show ReadTestExpectations, TestExpectations;
@@ -247,7 +247,7 @@
         String path = entity.uri.path;
         if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
         if (suite.pattern.any((RegExp r) => path.contains(r))) {
-          yield new TestDescription(suite.uri, entity);
+          yield new FileBasedTestDescription(suite.uri, entity);
         }
       }
     } else {
@@ -257,7 +257,8 @@
 
   Result processTestResult(
       TestDescription description, Result result, bool last) {
-    if (description.multitestExpectations != null) {
+    if (description is FileBasedTestDescription &&
+        description.multitestExpectations != null) {
       if (isError(description.multitestExpectations)) {
         result =
             toNegativeTestResult(result, description.multitestExpectations);
diff --git a/pkg/testing/lib/src/discover.dart b/pkg/testing/lib/src/discover.dart
index edcbf03..9b82e8a 100644
--- a/pkg/testing/lib/src/discover.dart
+++ b/pkg/testing/lib/src/discover.dart
@@ -8,7 +8,7 @@
 
 import 'dart:async' show Future, Stream, StreamController, StreamSubscription;
 
-import '../testing.dart' show TestDescription;
+import '../testing.dart' show FileBasedTestDescription;
 
 final Uri packageConfig = computePackageConfig();
 
@@ -19,9 +19,10 @@
 List<String> get dartArguments =>
     <String>["-c", "--packages=${packageConfig.toFilePath()}"];
 
-Stream<TestDescription> listTests(List<Uri> testRoots, {Pattern pattern}) {
-  StreamController<TestDescription> controller =
-      new StreamController<TestDescription>();
+Stream<FileBasedTestDescription> listTests(List<Uri> testRoots,
+    {Pattern pattern}) {
+  StreamController<FileBasedTestDescription> controller =
+      new StreamController<FileBasedTestDescription>();
   Map<Uri, StreamSubscription> subscriptions = <Uri, StreamSubscription>{};
   for (Uri testRootUri in testRoots) {
     subscriptions[testRootUri] = null;
@@ -31,8 +32,8 @@
         Stream<FileSystemEntity> stream =
             testRoot.list(recursive: true, followLinks: false);
         var subscription = stream.listen((FileSystemEntity entity) {
-          TestDescription description =
-              TestDescription.from(testRootUri, entity, pattern: pattern);
+          FileBasedTestDescription description = FileBasedTestDescription
+              .from(testRootUri, entity, pattern: pattern);
           if (description != null) {
             controller.add(description);
           }
diff --git a/pkg/testing/lib/src/multitest.dart b/pkg/testing/lib/src/multitest.dart
index c87a654..b049210 100644
--- a/pkg/testing/lib/src/multitest.dart
+++ b/pkg/testing/lib/src/multitest.dart
@@ -10,7 +10,7 @@
 
 import 'log.dart' show splitLines;
 
-import 'test_description.dart' show TestDescription;
+import 'test_description.dart' show FileBasedTestDescription;
 
 bool isError(Set<String> expectations) {
   if (expectations.contains("compile-time error")) return true;
@@ -24,8 +24,8 @@
   return isError(expectations);
 }
 
-class MultitestTransformer
-    extends StreamTransformerBase<TestDescription, TestDescription> {
+class MultitestTransformer extends StreamTransformerBase<
+    FileBasedTestDescription, FileBasedTestDescription> {
   static RegExp multitestMarker = new RegExp(r"//[#/]");
   static int _multitestMarkerLength = 3;
 
@@ -42,7 +42,8 @@
   static final Set<String> validOutcomes =
       new Set<String>.from(validOutcomesList);
 
-  Stream<TestDescription> bind(Stream<TestDescription> stream) async* {
+  Stream<FileBasedTestDescription> bind(
+      Stream<FileBasedTestDescription> stream) async* {
     List<String> errors = <String>[];
     reportError(String error) {
       errors.add(error);
@@ -50,7 +51,7 @@
     }
 
     nextTest:
-    await for (TestDescription test in stream) {
+    await for (FileBasedTestDescription test in stream) {
       String contents = await test.file.readAsString();
       if (!contents.contains(multitestMarker)) {
         yield test;
@@ -124,8 +125,8 @@
       for (String name in testsAsLines.keys) {
         List<String> lines = testsAsLines[name];
         Uri uri = generated.uri.resolve("${name}_generated.dart");
-        TestDescription subtest =
-            new TestDescription(root, new File.fromUri(uri));
+        FileBasedTestDescription subtest =
+            new FileBasedTestDescription(root, new File.fromUri(uri));
         subtest.multitestExpectations = outcomes[name];
         await subtest.file.writeAsString(lines.join(""));
         yield subtest;
diff --git a/pkg/testing/lib/src/run.dart b/pkg/testing/lib/src/run.dart
index c5dc77c..c628a7a 100644
--- a/pkg/testing/lib/src/run.dart
+++ b/pkg/testing/lib/src/run.dart
@@ -14,13 +14,12 @@
 
 import 'test_root.dart' show TestRoot;
 
-import 'test_description.dart' show TestDescription;
-
 import 'error_handling.dart' show withErrorHandling;
 
 import 'chain.dart' show CreateContext;
 
-import '../testing.dart' show Chain, ChainContext, TestDescription, listTests;
+import '../testing.dart'
+    show Chain, ChainContext, FileBasedTestDescription, listTests;
 
 import 'analyze.dart' show Analyze;
 
@@ -164,7 +163,7 @@
     StringBuffer chain = new StringBuffer();
     bool hasRunnableTests = false;
 
-    await for (TestDescription description in listDescriptions()) {
+    await for (FileBasedTestDescription description in listDescriptions()) {
       hasRunnableTests = true;
       description.writeImportOn(imports);
       description.writeClosureOn(dart);
@@ -228,9 +227,9 @@
     return hasAnalyzerSuites;
   }
 
-  Stream<TestDescription> listDescriptions() async* {
+  Stream<FileBasedTestDescription> listDescriptions() async* {
     for (Dart suite in suites.where((Suite suite) => suite is Dart)) {
-      await for (TestDescription description
+      await for (FileBasedTestDescription description
           in listTests(<Uri>[suite.uri], pattern: "")) {
         testUris.add(await Isolate.resolvePackageUri(description.uri));
         if (shouldRunSuite(suite)) {
diff --git a/pkg/testing/lib/src/test_description.dart b/pkg/testing/lib/src/test_description.dart
index 12e0b03..7480ee0 100644
--- a/pkg/testing/lib/src/test_description.dart
+++ b/pkg/testing/lib/src/test_description.dart
@@ -6,7 +6,15 @@
 
 import 'dart:io' show File, FileSystemEntity;
 
-class TestDescription implements Comparable<TestDescription> {
+abstract class TestDescription implements Comparable<TestDescription> {
+  Uri get uri;
+
+  String get shortName;
+
+  int compareTo(TestDescription other) => "$uri".compareTo("${other.uri}");
+}
+
+class FileBasedTestDescription extends TestDescription {
   final Uri root;
   final File file;
   final Uri output;
@@ -15,10 +23,12 @@
   /// expected outcomes.
   Set<String> multitestExpectations;
 
-  TestDescription(this.root, this.file, {this.output});
+  FileBasedTestDescription(this.root, this.file, {this.output});
 
+  @override
   Uri get uri => file.uri;
 
+  @override
   String get shortName {
     String baseName = "$uri".substring("$root".length);
     return baseName.substring(0, baseName.length - ".dart".length);
@@ -42,7 +52,7 @@
     sink.writeln('.main,');
   }
 
-  static TestDescription from(Uri root, FileSystemEntity entity,
+  static FileBasedTestDescription from(Uri root, FileSystemEntity entity,
       {Pattern pattern}) {
     if (entity is! File) return null;
     pattern ??= "_test.dart";
@@ -53,11 +63,9 @@
     } else if (path.contains(pattern)) {
       hasMatch = true;
     }
-    return hasMatch ? new TestDescription(root, entity) : null;
+    return hasMatch ? new FileBasedTestDescription(root, entity) : null;
   }
 
-  int compareTo(TestDescription other) => "$uri".compareTo("${other.uri}");
-
   String formatError(String message) {
     String base = Uri.base.toFilePath();
     String path = uri.toFilePath();
diff --git a/pkg/testing/lib/testing.dart b/pkg/testing/lib/testing.dart
index 3934ef1..8c963a4 100644
--- a/pkg/testing/lib/testing.dart
+++ b/pkg/testing/lib/testing.dart
@@ -8,7 +8,8 @@
 
 export 'src/discover.dart';
 
-export 'src/test_description.dart';
+export 'src/test_description.dart'
+    show FileBasedTestDescription, TestDescription;
 
 export 'src/chain.dart' show Chain, ChainContext, Result, Step;
 
diff --git a/pkg/vm/bin/gen_kernel.dart b/pkg/vm/bin/gen_kernel.dart
index c7e6fad..c28e2fc 100644
--- a/pkg/vm/bin/gen_kernel.dart
+++ b/pkg/vm/bin/gen_kernel.dart
@@ -31,6 +31,10 @@
   ..addFlag('embed-sources',
       help: 'Embed source files in the generated kernel program',
       defaultsTo: true)
+  ..addFlag('tfa',
+      help:
+          'Enable global type flow analysis and related transformations in AOT mode.',
+      defaultsTo: false)
   ..addOption('entry-points',
       help: 'Path to JSON file with the list of entry points',
       allowMultiple: true);
@@ -69,12 +73,14 @@
   final bool strongMode = options['strong-mode'];
   final bool aot = options['aot'];
   final bool syncAsync = options['sync-async'];
+  final bool tfa = options['tfa'];
 
   final List<String> entryPoints = options['entry-points'] ?? <String>[];
   if (entryPoints.isEmpty) {
     entryPoints.addAll([
       'pkg/vm/lib/transformations/type_flow/entry_points.json',
       'pkg/vm/lib/transformations/type_flow/entry_points_extra.json',
+      'pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json',
     ]);
   }
 
@@ -95,7 +101,7 @@
 
   Program program = await compileToKernel(
       Uri.base.resolveUri(new Uri.file(filename)), compilerOptions,
-      aot: aot, entryPoints: entryPoints);
+      aot: aot, useGlobalTypeFlowAnalysis: tfa, entryPoints: entryPoints);
 
   if (errorDetector.hasCompilationErrors || (program == null)) {
     return _compileTimeErrorExitCode;
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 73e0ecd..e7c9030 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -24,16 +24,15 @@
 import 'transformations/type_flow/transformer.dart' as globalTypeFlow
     show transformProgram;
 
-// Flag to enable global type flow analysis and related transformations.
-const kUseGlobalTypeFlow = const bool.fromEnvironment('use.global.type.flow');
-
 /// Generates a kernel representation of the program whose main library is in
 /// the given [source]. Intended for whole program (non-modular) compilation.
 ///
 /// VM-specific replacement of [kernelForProgram].
 ///
 Future<Program> compileToKernel(Uri source, CompilerOptions options,
-    {bool aot: false, List<String> entryPoints}) async {
+    {bool aot: false,
+    bool useGlobalTypeFlowAnalysis: false,
+    List<String> entryPoints}) async {
   // Replace error handler to detect if there are compilation errors.
   final errorDetector =
       new ErrorDetector(previousErrorHandler: options.onError);
@@ -46,18 +45,19 @@
 
   // Run global transformations only if program is correct.
   if (aot && (program != null) && !errorDetector.hasCompilationErrors) {
-    _runGlobalTransformations(program, options.strongMode, entryPoints);
+    _runGlobalTransformations(
+        program, options.strongMode, useGlobalTypeFlowAnalysis, entryPoints);
   }
 
   return program;
 }
 
-_runGlobalTransformations(
-    Program program, bool strongMode, List<String> entryPoints) {
+_runGlobalTransformations(Program program, bool strongMode,
+    bool useGlobalTypeFlowAnalysis, List<String> entryPoints) {
   if (strongMode) {
     final coreTypes = new CoreTypes(program);
 
-    if (kUseGlobalTypeFlow) {
+    if (useGlobalTypeFlowAnalysis) {
       globalTypeFlow.transformProgram(coreTypes, program, entryPoints);
     } else {
       devirtualization.transformProgram(coreTypes, program);
diff --git a/pkg/vm/lib/metadata/procedure_attributes.dart b/pkg/vm/lib/metadata/procedure_attributes.dart
index 1e6acb8..5581074 100644
--- a/pkg/vm/lib/metadata/procedure_attributes.dart
+++ b/pkg/vm/lib/metadata/procedure_attributes.dart
@@ -8,20 +8,29 @@
 
 /// Metadata for annotating procedures with various attributes.
 class ProcedureAttributesMetadata {
-  final bool hasDynamicInvocations;
+  final bool hasDynamicUses;
+  final bool hasNonThisUses;
+  final bool hasTearOffUses;
 
-  const ProcedureAttributesMetadata({this.hasDynamicInvocations});
+  const ProcedureAttributesMetadata(
+      {this.hasDynamicUses, this.hasNonThisUses, this.hasTearOffUses});
 
-  const ProcedureAttributesMetadata.noDynamicInvocations()
-      : hasDynamicInvocations = false;
+  const ProcedureAttributesMetadata.noDynamicUses()
+      : this(hasDynamicUses: false, hasNonThisUses: true, hasTearOffUses: true);
 
   @override
-  String toString() => "hasDynamicInvocations:${hasDynamicInvocations}";
+  String toString() => "hasDynamicUses:$hasDynamicUses,"
+      "hasNonThisUses:$hasNonThisUses,"
+      "hasTearOffUses:$hasTearOffUses";
 }
 
 /// Repository for [ProcedureAttributesMetadata].
 class ProcedureAttributesMetadataRepository
     extends MetadataRepository<ProcedureAttributesMetadata> {
+  static const int kDynamicUsesBit = 1 << 0;
+  static const int kNonThisUsesBit = 1 << 1;
+  static const int kTearOffUsesBit = 1 << 2;
+
   @override
   final String tag = 'vm.procedure-attributes.metadata';
 
@@ -31,11 +40,30 @@
 
   @override
   void writeToBinary(ProcedureAttributesMetadata metadata, BinarySink sink) {
-    assert(!metadata.hasDynamicInvocations);
+    int flags = 0;
+    if (metadata.hasDynamicUses) {
+      flags |= kDynamicUsesBit;
+    }
+    if (metadata.hasNonThisUses) {
+      flags |= kNonThisUsesBit;
+    }
+    if (metadata.hasTearOffUses) {
+      flags |= kTearOffUsesBit;
+    }
+    sink.writeByte(flags);
   }
 
   @override
   ProcedureAttributesMetadata readFromBinary(BinarySource source) {
-    return const ProcedureAttributesMetadata.noDynamicInvocations();
+    final int flags = source.readByte();
+
+    final bool hasDynamicUses = (flags & kDynamicUsesBit) == kDynamicUsesBit;
+    final bool hasNonThisUses = (flags & kNonThisUsesBit) == kNonThisUsesBit;
+    final bool hasTearOffUses = (flags & kTearOffUsesBit) == kTearOffUsesBit;
+
+    return new ProcedureAttributesMetadata(
+        hasDynamicUses: hasDynamicUses,
+        hasNonThisUses: hasNonThisUses,
+        hasTearOffUses: hasTearOffUses);
   }
 }
diff --git a/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart b/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
index 95b11ce..a176469 100644
--- a/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
+++ b/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
@@ -12,7 +12,7 @@
 /// via dynamic invocation from anywhere then annotates it with appropriate
 /// [ProcedureAttributeMetadata] annotation.
 Program transformProgram(Program program) {
-  new NoDynamicInvocationsAnnotator(program).visitProgram(program);
+  new NoDynamicUsesAnnotator(program).visitProgram(program);
   return program;
 }
 
@@ -50,12 +50,14 @@
   }
 }
 
-class NoDynamicInvocationsAnnotator {
-  final Set<Selector> _dynamicSelectors;
+// TODO(kustermann): Try to extend the idea of tracking uses based on the 'this'
+// hierarchy.
+class NoDynamicUsesAnnotator {
+  final DynamicSelectorsCollector _selectors;
   final ProcedureAttributesMetadataRepository _metadata;
 
-  NoDynamicInvocationsAnnotator(Program program)
-      : _dynamicSelectors = DynamicSelectorsCollector.collect(program),
+  NoDynamicUsesAnnotator(Program program)
+      : _selectors = DynamicSelectorsCollector.collect(program),
         _metadata = new ProcedureAttributesMetadataRepository() {
     program.addMetadataRepository(_metadata);
   }
@@ -83,10 +85,19 @@
       return;
     }
 
-    if (!_dynamicSelectors.contains(new Selector.doSet(node.name))) {
-      _metadata.mapping[node] =
-          const ProcedureAttributesMetadata.noDynamicInvocations();
+    final selector = new Selector.doSet(node.name);
+    if (_selectors.dynamicSelectors.contains(selector)) {
+      return;
     }
+
+    ProcedureAttributesMetadata metadata;
+    if (!_selectors.nonThisSelectors.contains(selector)) {
+      metadata = const ProcedureAttributesMetadata(
+          hasDynamicUses: false, hasNonThisUses: true, hasTearOffUses: false);
+    } else {
+      metadata = const ProcedureAttributesMetadata.noDynamicUses();
+    }
+    _metadata.mapping[node] = metadata;
   }
 
   visitProcedure(Procedure node) {
@@ -103,28 +114,81 @@
       return;
     }
 
-    if (!_dynamicSelectors.contains(selector)) {
-      _metadata.mapping[node] =
-          const ProcedureAttributesMetadata.noDynamicInvocations();
+    if (_selectors.dynamicSelectors.contains(selector)) {
+      return;
     }
+
+    final bool hasNonThisUses = _selectors.nonThisSelectors.contains(selector);
+    final bool hasTearOffUses = _selectors.tearOffSelectors.contains(selector);
+    ProcedureAttributesMetadata metadata;
+    if (!hasNonThisUses && !hasTearOffUses) {
+      metadata = const ProcedureAttributesMetadata(
+          hasDynamicUses: false, hasNonThisUses: false, hasTearOffUses: false);
+    } else if (!hasNonThisUses && hasTearOffUses) {
+      metadata = const ProcedureAttributesMetadata(
+          hasDynamicUses: false, hasNonThisUses: false, hasTearOffUses: true);
+    } else if (hasNonThisUses && !hasTearOffUses) {
+      metadata = const ProcedureAttributesMetadata(
+          hasDynamicUses: false, hasNonThisUses: true, hasTearOffUses: false);
+    } else {
+      metadata = const ProcedureAttributesMetadata.noDynamicUses();
+    }
+    _metadata.mapping[node] = metadata;
   }
 }
 
 class DynamicSelectorsCollector extends RecursiveVisitor<Null> {
   final Set<Selector> dynamicSelectors = new Set<Selector>();
+  final Set<Selector> nonThisSelectors = new Set<Selector>();
+  final Set<Selector> tearOffSelectors = new Set<Selector>();
 
-  static Set<Selector> collect(Program program) {
+  static DynamicSelectorsCollector collect(Program program) {
     final v = new DynamicSelectorsCollector();
     v.visitProgram(program);
-    return v.dynamicSelectors;
+
+    // We only populate [nonThisSelectors] and [tearOffSelectors] inside the
+    // non-dynamic case (for efficiency reasons) while visiting the [Program].
+    //
+    // After the recursive visit of [Program] we complete the sets here.
+    for (final Selector selector in v.dynamicSelectors) {
+      // All dynamic getters can be tearoffs.
+      if (selector.action == Action.get) {
+        v.tearOffSelectors.add(new Selector.doInvoke(selector.target));
+      }
+
+      // All dynamic selectors are non-this selectors.
+      v.nonThisSelectors.add(selector);
+    }
+
+    return v;
   }
 
   @override
   visitMethodInvocation(MethodInvocation node) {
     super.visitMethodInvocation(node);
 
+    Selector selector;
     if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
       dynamicSelectors.add(new Selector.doInvoke(node.name));
+    } else {
+      if (node.receiver is! ThisExpression) {
+        nonThisSelectors.add(selector ??= new Selector.doInvoke(node.name));
+      }
+    }
+  }
+
+  @override
+  visitDirectMethodInvocation(DirectMethodInvocation node) {
+    super.visitDirectMethodInvocation(node);
+
+    Selector selector;
+    if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
+      dynamicSelectors.add(selector = new Selector.doInvoke(node.target.name));
+    } else {
+      if (node.receiver is! ThisExpression) {
+        nonThisSelectors
+            .add(selector ??= new Selector.doInvoke(node.target.name));
+      }
     }
   }
 
@@ -132,8 +196,36 @@
   visitPropertyGet(PropertyGet node) {
     super.visitPropertyGet(node);
 
+    Selector selector;
     if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
-      dynamicSelectors.add(new Selector.doGet(node.name));
+      dynamicSelectors.add(selector = new Selector.doGet(node.name));
+    } else {
+      if (node.receiver is! ThisExpression) {
+        nonThisSelectors.add(selector ??= new Selector.doGet(node.name));
+      }
+
+      final target = node.interfaceTarget;
+      if (target is Procedure && target.kind == ProcedureKind.Method) {
+        tearOffSelectors.add(new Selector.doInvoke(node.name));
+      }
+    }
+  }
+
+  @override
+  visitDirectPropertyGet(DirectPropertyGet node) {
+    super.visitDirectPropertyGet(node);
+
+    if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
+      dynamicSelectors.add(new Selector.doGet(node.target.name));
+    } else {
+      if (node.receiver is! ThisExpression) {
+        nonThisSelectors.add(new Selector.doGet(node.target.name));
+      }
+
+      final target = node.target;
+      if (target is Procedure && target.kind == ProcedureKind.Method) {
+        tearOffSelectors.add(new Selector.doInvoke(target.name));
+      }
     }
   }
 
@@ -141,8 +233,27 @@
   visitPropertySet(PropertySet node) {
     super.visitPropertySet(node);
 
+    Selector selector;
     if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
-      dynamicSelectors.add(new Selector.doSet(node.name));
+      dynamicSelectors.add(selector = new Selector.doSet(node.name));
+    } else {
+      if (node.receiver is! ThisExpression) {
+        nonThisSelectors.add(selector ??= new Selector.doSet(node.name));
+      }
+    }
+  }
+
+  @override
+  visitDirectPropertySet(DirectPropertySet node) {
+    super.visitDirectPropertySet(node);
+
+    Selector selector;
+    if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
+      dynamicSelectors.add(selector = new Selector.doSet(node.target.name));
+    } else {
+      if (node.receiver is! ThisExpression) {
+        nonThisSelectors.add(selector ??= new Selector.doSet(node.target.name));
+      }
     }
   }
 }
diff --git a/pkg/vm/lib/transformations/type_flow/entry_points_extra.json b/pkg/vm/lib/transformations/type_flow/entry_points_extra.json
index d45ef2a..892b058 100644
--- a/pkg/vm/lib/transformations/type_flow/entry_points_extra.json
+++ b/pkg/vm/lib/transformations/type_flow/entry_points_extra.json
@@ -68,11 +68,6 @@
       "action": "call"
     },
     {
-      "library": "dart:_builtin",
-      "name": "_resolveScriptUri",
-      "action": "call"
-    },
-    {
       "library": "dart:math",
       "class": "_Random",
       "name": "_A",
diff --git a/pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json b/pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json
new file mode 100644
index 0000000..8979143
--- /dev/null
+++ b/pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json
@@ -0,0 +1,9 @@
+{
+  "roots": [
+    {
+      "library": "dart:_builtin",
+      "name": "_resolveScriptUri",
+      "action": "call"
+    }
+  ]
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index aa44be5..b23ebd2 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -20,7 +20,7 @@
   }
   operator *([@vm.inferred-type.metadata=#lib::_Vector] self::_Vector a) → core::double {
     core::double result = 0.0;
-    for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
+    for (core::int i = 0; i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
       result = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] this.{self::_Vector::[]}(i).{core::double::*}([@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] a.{self::_Vector::[]}(i)));
     return result;
   }
@@ -29,7 +29,7 @@
 [@vm.inferred-type.metadata=dart.core::_Double]static field core::double x = 0.0;
 static method main(core::List<core::String> args) → dynamic {
   core::Stopwatch timer = let final core::Stopwatch #t1 = new core::Stopwatch::•() in let final dynamic #t2 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] #t1.{core::Stopwatch::start}() in #t1;
-  for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
+  for (core::int i = 0; i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
     self::x = [@vm.direct-call.metadata=dart.core::_Double::+] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=dart.core::_Double] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=#lib::_Vector] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector] self::v));
   }
   [@vm.direct-call.metadata=dart.core::Stopwatch::stop] timer.{core::Stopwatch::stop}();
diff --git a/pkg/vm/tool/precompiler2 b/pkg/vm/tool/precompiler2
index d0776cb..cd965fe 100755
--- a/pkg/vm/tool/precompiler2
+++ b/pkg/vm/tool/precompiler2
@@ -15,8 +15,8 @@
 set -e
 
 OPTIONS=()
+GEN_KERNEL_OPTIONS=()
 PACKAGES=
-SYNC_ASYNC=
 
 ARGV=()
 for arg in "$@"; do
@@ -24,8 +24,11 @@
     --packages=*)
     PACKAGES="$arg"
     ;;
-    --sync-async)
-    SYNC_ASYNC="--sync-async"
+    --sync-async | \
+    --no-sync-async | \
+    --tfa | \
+    --no-tfa )
+    GEN_KERNEL_OPTIONS+=("$arg")
     ;;
     --*)
     OPTIONS+=("$arg")
@@ -71,7 +74,8 @@
 BIN_DIR="$OUT_DIR/$DART_CONFIGURATION"
 
 ENTRY_POINTS="--entry-points ${BIN_DIR}/gen/runtime/bin/precompiler_entry_points.json \
-              --entry-points ${SDK_DIR}/pkg/vm/lib/transformations/type_flow/entry_points_extra.json"
+              --entry-points ${SDK_DIR}/pkg/vm/lib/transformations/type_flow/entry_points_extra.json \
+              --entry-points ${SDK_DIR}/pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json"
 
 # Step 1: Generate Kernel binary from the input Dart source.
 "$BIN_DIR"/dart                                                                \
@@ -79,7 +83,7 @@
      "${SDK_DIR}/pkg/vm/bin/gen_kernel.dart"                                   \
      --platform "${BIN_DIR}/vm_platform_strong.dill"                           \
      --aot                                                                     \
-     $SYNC_ASYNC                                                               \
+     "${GEN_KERNEL_OPTIONS[@]}"                                                \
      $PACKAGES                                                                 \
      $ENTRY_POINTS                                                             \
      -o "$SNAPSHOT_FILE.dill"                                                  \
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 410bde7..4442c92 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -6,6 +6,7 @@
 import("../../sdk/lib/_http/http_sources.gni")
 import("../../sdk/lib/io/io_sources.gni")
 import("../../sdk/lib/cli/cli_sources.gni")
+import("../../utils/generate_entry_points_json.gni")
 import("../runtime_args.gni")
 import("../vm/compiler/compiler_sources.gni")
 import("../vm/vm_sources.gni")
@@ -751,23 +752,30 @@
   deps = [
     ":isolate_snapshot_data_assembly",
     ":isolate_snapshot_instructions_assembly",
-    ":kernel_service_dill_cc",
-    ":platform_dill_cc",
-    ":platform_strong_dill_cc",
     ":vm_snapshot_data_assembly",
     ":vm_snapshot_instructions_assembly",
   ]
   sources = [
-    "$root_gen_dir/kernel_service.dill.cc",
     "$target_gen_dir/isolate_snapshot_data.S",
     "$target_gen_dir/isolate_snapshot_instructions.S",
-    "$target_gen_dir/vm_platform.dill.cc",
-    "$target_gen_dir/vm_platform_strong.dill.cc",
     "$target_gen_dir/vm_snapshot_data.S",
     "$target_gen_dir/vm_snapshot_instructions.S",
   ]
 }
 
+source_set("dart_kernel_platform_cc") {
+  deps = [
+    ":kernel_service_dill_cc",
+    ":platform_dill_cc",
+    ":platform_strong_dill_cc",
+  ]
+  sources = [
+    "$root_gen_dir/kernel_service.dill.cc",
+    "$target_gen_dir/vm_platform.dill.cc",
+    "$target_gen_dir/vm_platform_strong.dill.cc",
+  ]
+}
+
 template("dart_executable") {
   extra_configs = []
   if (defined(invoker.extra_configs)) {
@@ -872,6 +880,9 @@
   if (dart_runtime_mode != "release") {
     extra_deps += [ "../observatory:standalone_observatory_archive" ]
   }
+  if (dart_runtime_mode != "release") {
+    extra_deps += [ ":dart_kernel_platform_cc" ]
+  }
   extra_sources = [
     "builtin_nolib.cc",
     "dfe.cc",
@@ -931,6 +942,9 @@
     ":generate_web_sql_cc_file",
     "..:libdart_nosnapshot_with_precompiler",
   ]
+  if (dart_runtime_mode != "release") {
+    extra_deps += [ ":dart_kernel_platform_cc" ]
+  }
   extra_defines = [ "NO_OBSERVATORY" ]
   extra_sources = [
     "builtin.cc",
@@ -1108,6 +1122,7 @@
   }
 
   deps = [
+    ":dart_kernel_platform_cc",
     ":dart_snapshot_cc",
     ":generate_snapshot_test_dat_file",
     ":libdart_builtin",
@@ -1206,29 +1221,10 @@
   }
 }
 
-compiled_action("precompiler_entry_points_json") {
-  # Printing precompiler entry points is folded into precompilation, so dart_bootstrap is invoked
-  # with correct arguments to generate app-aot snapshot.
-
+generate_entry_points_json_with_dart_bootstrap(
+    "precompiler_entry_points_json") {
   # Dart script to precompile (any valid script would suffice).
-  input = "../vm/snapshot_test.dart"
-
-  # Output snapshot for precompilation.
-  snapshot = "$target_gen_dir/dummy.snapshot"
+  input = "../tests/vm/dart/hello_world_test.dart"
 
   output = "$target_gen_dir/precompiler_entry_points.json"
-  tool = ":dart_bootstrap"
-  inputs = [
-    input,
-  ]
-  outputs = [
-    output,
-  ]
-  args = [
-    "--print-precompiler-entry-points=" + rebase_path(output),
-    "--snapshot=" + rebase_path(snapshot),
-    "--snapshot-kind=app-aot",
-    "--use-blobs",
-    rebase_path(input),
-  ]
 }
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index d9fde37..c4c7d3d 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -197,7 +197,7 @@
   if (slash == NULL) {
     return strdup(url);
   } else {
-    return StringUtils::StrNDup(url, slash - url + 1);
+    return Utils::StrNDup(url, slash - url + 1);
   }
 }
 
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index df9750e..d80f237 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -13,12 +13,21 @@
 #include "vm/kernel.h"
 
 extern "C" {
+#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
 extern const uint8_t kKernelServiceDill[];
 extern intptr_t kKernelServiceDillSize;
 extern const uint8_t kPlatformDill[];
 extern intptr_t kPlatformDillSize;
 extern const uint8_t kPlatformStrongDill[];
 extern intptr_t kPlatformStrongDillSize;
+#else
+const uint8_t* kKernelServiceDill = NULL;
+intptr_t kKernelServiceDillSize = 0;
+const uint8_t* kPlatformDill = NULL;
+intptr_t kPlatformDillSize = 0;
+const uint8_t* kPlatformStrongDill = NULL;
+intptr_t kPlatformStrongDillSize = 0;
+#endif  // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
 }
 
 namespace dart {
@@ -59,7 +68,7 @@
     return strdup("");
   }
 
-  return StringUtils::StrNDup(name, i + 1);
+  return Utils::StrNDup(name, i + 1);
 }
 
 static void NoopRelease(uint8_t* buffer) {}
diff --git a/runtime/bin/extensions.cc b/runtime/bin/extensions.cc
index 9f8edfe..b4ba1e7 100644
--- a/runtime/bin/extensions.cc
+++ b/runtime/bin/extensions.cc
@@ -13,6 +13,7 @@
 #include "include/dart_api.h"
 #include "platform/assert.h"
 #include "platform/globals.h"
+#include "platform/utils.h"
 
 namespace dart {
 namespace bin {
@@ -65,7 +66,7 @@
 void* Extensions::ResolveAbsPathExtension(const char* extension_path) {
   const char* last_slash = strrchr(extension_path, PathSeparator()) + 1;
   char* name = strdup(last_slash);
-  char* dir = StringUtils::StrNDup(extension_path, last_slash - extension_path);
+  char* dir = Utils::StrNDup(extension_path, last_slash - extension_path);
   void* library_handle = MakePathAndResolve(dir, name);
   free(dir);
   free(name);
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index 9774833..9c05e0d 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -296,7 +296,7 @@
     }
 
     // Convert buffer buffer to NUL-terminated string.
-    (*dependencies)[i] = StringUtils::StrNDup(
+    (*dependencies)[i] = Utils::StrNDup(
         reinterpret_cast<const char*>(file_path), file_path_length);
     free(file_path);
     free(resolved_uri);
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 32aa820..a9e51c3 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -323,7 +323,7 @@
   return isolate;
 }
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
+#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
 // Returns newly created Kernel Isolate on success, NULL on failure.
 // For now we only support the kernel isolate coming up from an
 // application snapshot or from a .dill file.
@@ -382,7 +382,7 @@
   return IsolateSetupHelper(isolate, false, uri, package_root, packages_config,
                             true, isolate_run_app_snapshot, error, exit_code);
 }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+#endif  // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
 
 // Returns newly created Service Isolate on success, NULL on failure.
 // For now we only support the service isolate coming up from sources
@@ -609,13 +609,13 @@
   }
 
   int exit_code = 0;
-#if !defined(DART_PRECOMPILED_RUNTIME)
+#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
   if (strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0) {
     return CreateAndSetupKernelIsolate(script_uri, main, package_root,
                                        package_config, flags, error,
                                        &exit_code);
   }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+#endif  // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
   if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
     return CreateAndSetupServiceIsolate(script_uri, main, package_root,
                                         package_config, flags, error,
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 30f656b..bf1737a 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -63,15 +63,23 @@
 CB_OPTIONS_LIST(CB_OPTION_DEFINITION)
 #undef CB_OPTION_DEFINITION
 
+static void SetPreviewDart2Options(CommandLineOptions* vm_options) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  Options::dfe()->set_use_dfe();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  vm_options->AddArgument("--strong");
+  vm_options->AddArgument("--reify-generic-functions");
+  vm_options->AddArgument("--limit-ints-to-64-bits");
+}
+
+DEFINE_BOOL_OPTION_CB(preview_dart_2, { SetPreviewDart2Options(vm_options); });
+
 #if !defined(DART_PRECOMPILED_RUNTIME)
 DFE* Options::dfe_ = NULL;
 
-DEFINE_BOOL_OPTION_CB(preview_dart_2, { Options::dfe()->set_use_dfe(); });
-
 // TODO(sivachandra): Make it an error to specify --dfe without
 // specifying --preview_dart_2.
 DEFINE_STRING_OPTION_CB(dfe, { Options::dfe()->set_frontend_filename(value); });
-
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 DEFINE_BOOL_OPTION_CB(hot_reload_test_mode, {
diff --git a/runtime/bin/utils.h b/runtime/bin/utils.h
index b313ff1..234a969 100644
--- a/runtime/bin/utils.h
+++ b/runtime/bin/utils.h
@@ -78,9 +78,6 @@
                                    intptr_t len = -1,
                                    intptr_t* result_len = NULL);
 
-  // Not all platforms support strndup.
-  static char* StrNDup(const char* s, intptr_t n);
-
  private:
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(StringUtils);
diff --git a/runtime/bin/utils_android.cc b/runtime/bin/utils_android.cc
index 83bfcc7..a705997 100644
--- a/runtime/bin/utils_android.cc
+++ b/runtime/bin/utils_android.cc
@@ -69,10 +69,6 @@
   return NULL;
 }
 
-char* StringUtils::StrNDup(const char* s, intptr_t n) {
-  return strndup(s, n);
-}
-
 bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
   return false;
 }
diff --git a/runtime/bin/utils_fuchsia.cc b/runtime/bin/utils_fuchsia.cc
index b763016..e1f3dca 100644
--- a/runtime/bin/utils_fuchsia.cc
+++ b/runtime/bin/utils_fuchsia.cc
@@ -66,10 +66,6 @@
   return NULL;
 }
 
-char* StringUtils::StrNDup(const char* s, intptr_t n) {
-  return strndup(s, n);
-}
-
 bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
   return false;
 }
diff --git a/runtime/bin/utils_linux.cc b/runtime/bin/utils_linux.cc
index 766ccdb..3e27c0c 100644
--- a/runtime/bin/utils_linux.cc
+++ b/runtime/bin/utils_linux.cc
@@ -67,10 +67,6 @@
   return NULL;
 }
 
-char* StringUtils::StrNDup(const char* s, intptr_t n) {
-  return strndup(s, n);
-}
-
 bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
   return false;
 }
diff --git a/runtime/bin/utils_macos.cc b/runtime/bin/utils_macos.cc
index d4be9a8..bec7153 100644
--- a/runtime/bin/utils_macos.cc
+++ b/runtime/bin/utils_macos.cc
@@ -72,29 +72,6 @@
   return NULL;
 }
 
-char* StringUtils::StrNDup(const char* s, intptr_t n) {
-// strndup has only been added to Mac OS X in 10.7. We are supplying
-// our own copy here if needed.
-#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) ||                 \
-    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
-  intptr_t len = strlen(s);
-  if ((n < 0) || (len < 0)) {
-    return NULL;
-  }
-  if (n < len) {
-    len = n;
-  }
-  char* result = reinterpret_cast<char*>(malloc(len + 1));
-  if (result == NULL) {
-    return NULL;
-  }
-  result[len] = '\0';
-  return reinterpret_cast<char*>(memmove(result, s, len));
-#else   // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
-  return strndup(s, n);
-#endif  // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
-}
-
 bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
   return false;
 }
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index e06cb9b..99e9fb8 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -144,22 +144,6 @@
       StringUtilsWin::Utf8ToWide(const_cast<char*>(utf8), len, result_len));
 }
 
-char* StringUtils::StrNDup(const char* s, intptr_t n) {
-  intptr_t len = strlen(s);
-  if ((n < 0) || (len < 0)) {
-    return NULL;
-  }
-  if (n < len) {
-    len = n;
-  }
-  char* result = reinterpret_cast<char*>(malloc(len + 1));
-  if (result == NULL) {
-    return NULL;
-  }
-  result[len] = '\0';
-  return reinterpret_cast<char*>(memmove(result, s, len));
-}
-
 bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
   wchar_t* command_line = GetCommandLineW();
   int unicode_argc;
diff --git a/runtime/lib/array_patch.dart b/runtime/lib/array_patch.dart
index 820594a..27fc745 100644
--- a/runtime/lib/array_patch.dart
+++ b/runtime/lib/array_patch.dart
@@ -8,6 +8,9 @@
 // whether a parameter was passed.
 class _GrowableArrayMarker implements int {
   const _GrowableArrayMarker();
+  noSuchMethod(_) {
+    throw new UnimplementedError();
+  }
 }
 
 const _GROWABLE_ARRAY_MARKER = const _GrowableArrayMarker();
diff --git a/runtime/lib/bigint.dart b/runtime/lib/bigint.dart
index 03a4b70..b6a9db3 100644
--- a/runtime/lib/bigint.dart
+++ b/runtime/lib/bigint.dart
@@ -1863,7 +1863,7 @@
 }
 
 // Interface for modular reduction.
-class _Reduction {
+abstract class _Reduction {
   // Return the number of digits used by r_digits.
   int _convert(_Bigint x, Uint32List r_digits);
   int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used,
diff --git a/runtime/lib/bigint_patch.dart b/runtime/lib/bigint_patch.dart
index 05b37a1..7094f29 100644
--- a/runtime/lib/bigint_patch.dart
+++ b/runtime/lib/bigint_patch.dart
@@ -60,10 +60,13 @@
 int _max(int a, int b) => a > b ? a : b;
 int _min(int a, int b) => a < b ? a : b;
 
+/// Allocate a new digits list of even length.
+Uint32List _newDigits(int length) => new Uint32List(length + (length & 1));
+
 /**
  * An implementation for the arbitrarily large integer.
  *
- * The integer number is represented by a sign, an array of 16-bit unsigned
+ * The integer number is represented by a sign, an array of 32-bit unsigned
  * integers in little endian format, and a number of used digits in that array.
  */
 class _BigIntImpl implements BigInt {
@@ -81,6 +84,8 @@
   static final _BigIntImpl two = new _BigIntImpl._fromInt(2);
 
   static final _BigIntImpl _minusOne = -one;
+  static final _BigIntImpl _oneDigitMask = new _BigIntImpl._fromInt(_digitMask);
+  static final _BigIntImpl _twoDigitMask = (one << (2 * _digitBits)) - one;
   static final _BigIntImpl _oneBillion = new _BigIntImpl._fromInt(1000000000);
   static const int _minInt = -0x8000000000000000;
   static const int _maxInt = 0x7fffffffffffffff;
@@ -104,12 +109,22 @@
   /// The least significant digit is in slot 0.
   /// The list may have more digits than needed. That is, `_digits.length` may
   /// be strictly greater than `_used`.
+  /// Also, `_digits.length` must always be even, because intrinsics on 64-bit
+  /// platforms may process a digit pair as a 64-bit value.
   final Uint32List _digits;
 
   /// The number of used entries in [_digits].
   ///
   /// To avoid reallocating [Uint32List]s, lists that are too big are not
-  /// replaced.
+  /// replaced, but `_used` reflects the smaller number of digits actually used.
+  ///
+  /// Note that functions shortening an existing list of digits to a smaller
+  /// `_used` number of digits must ensure that the highermost pair of digits
+  /// is correct when read as a 64-bit value by intrinsics. Therefore, if the
+  /// smaller '_used' number is odd, the high digit of that pair must be
+  /// explicitly cleared, i.e. _digits[_used] = 0, which cannot result in an
+  /// out of bounds access, since the length of the list is guaranteed to be
+  /// even.
   final int _used;
 
   /**
@@ -197,34 +212,33 @@
   ///
   /// The [source] (substring) must be a valid hex literal.
   static _BigIntImpl _parseHex(String source, int startPos, bool isNegative) {
-    int hexDigitsPerChunk = _digitBits ~/ 4;
+    int hexCharsPerDigit = _digitBits ~/ 4;
     int sourceLength = source.length - startPos;
-    int chunkCount =
-        (sourceLength + hexDigitsPerChunk - 1) ~/ hexDigitsPerChunk;
-    var digits = new Uint32List(chunkCount);
+    int used = (sourceLength + hexCharsPerDigit - 1) ~/ hexCharsPerDigit;
+    var digits = _newDigits(used);
 
-    int lastDigitLength = sourceLength - (chunkCount - 1) * hexDigitsPerChunk;
-    int digitIndex = digits.length - 1;
+    int lastDigitLength = sourceLength - (used - 1) * hexCharsPerDigit;
+    int digitIndex = used - 1;
     int i = startPos;
-    int chunk = 0;
+    int digit = 0;
     for (int j = 0; j < lastDigitLength; j++) {
-      var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i++));
-      if (digitValue >= 16) return null;
-      chunk = chunk * 16 + digitValue;
+      var value = _codeUnitToRadixValue(source.codeUnitAt(i++));
+      if (value >= 16) return null;
+      digit = digit * 16 + value;
     }
-    digits[digitIndex--] = chunk;
+    digits[digitIndex--] = digit;
 
     while (i < source.length) {
-      chunk = 0;
-      for (int j = 0; j < hexDigitsPerChunk; j++) {
-        var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i++));
-        if (digitValue >= 16) return null;
-        chunk = chunk * 16 + digitValue;
+      digit = 0;
+      for (int j = 0; j < hexCharsPerDigit; j++) {
+        var value = _codeUnitToRadixValue(source.codeUnitAt(i++));
+        if (value >= 16) return null;
+        digit = digit * 16 + value;
       }
-      digits[digitIndex--] = chunk;
+      digits[digitIndex--] = digit;
     }
-    if (digits.length == 1 && digits[0] == 0) return zero;
-    return new _BigIntImpl._(isNegative, digits.length, digits);
+    if (used == 1 && digits[0] == 0) return zero;
+    return new _BigIntImpl._(isNegative, used, digits);
   }
 
   /// Parses the given [source] as a [radix] literal.
@@ -235,9 +249,9 @@
     var result = zero;
     var base = new _BigIntImpl._fromInt(radix);
     for (int i = 0; i < source.length; i++) {
-      var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i));
-      if (digitValue >= radix) return null;
-      result = result * base + new _BigIntImpl._fromInt(digitValue);
+      var value = _codeUnitToRadixValue(source.codeUnitAt(i));
+      if (value >= radix) return null;
+      result = result * base + new _BigIntImpl._fromInt(value);
     }
     if (isNegative) return -result;
     return result;
@@ -308,7 +322,10 @@
       : this._normalized(isNegative, _normalize(used, digits), digits);
 
   _BigIntImpl._normalized(bool isNegative, this._used, this._digits)
-      : _isNegative = _used == 0 ? false : isNegative;
+      : _isNegative = _used == 0 ? false : isNegative {
+    assert(_digits.length.isEven);
+    assert(_used.isEven || _digits[_used] == 0); // Leading zero for 64-bit.
+  }
 
   /// Whether this big integer is zero.
   bool get _isZero => _used == 0;
@@ -318,7 +335,7 @@
   /// digits.
   static Uint32List _cloneDigits(
       Uint32List digits, int from, int to, int length) {
-    var resultDigits = new Uint32List(length);
+    var resultDigits = _newDigits(length);
     var n = to - from;
     for (var i = 0; i < n; i++) {
       resultDigits[i] = digits[from + i];
@@ -341,22 +358,20 @@
   factory _BigIntImpl._fromInt(int value) {
     bool isNegative = value < 0;
     assert(_digitBits == 32);
+    var digits = _newDigits(2);
     if (isNegative) {
       // Handle the min 64-bit value differently, since its negation is not
       // positive.
       if (value == _minInt) {
-        var digits = new Uint32List(2);
         digits[1] = 0x80000000;
         return new _BigIntImpl._(true, 2, digits);
       }
       value = -value;
     }
     if (value < _digitBase) {
-      var digits = new Uint32List(1);
       digits[0] = value;
       return new _BigIntImpl._(isNegative, 1, digits);
     }
-    var digits = new Uint32List(2);
     digits[0] = value & _digitMask;
     digits[1] = value >> _digitBits;
     return new _BigIntImpl._(isNegative, 2, digits);
@@ -389,7 +404,7 @@
 
     assert(_digitBits == 32);
     // The significant bits are in 0 .. 52.
-    var unshiftedDigits = new Uint32List(2);
+    var unshiftedDigits = _newDigits(2);
     unshiftedDigits[0] =
         (bits[3] << 24) + (bits[2] << 16) + (bits[1] << 8) + bits[0];
     // Don't forget to add the hidden bit.
@@ -425,7 +440,7 @@
    */
   _BigIntImpl abs() => _isNegative ? -this : this;
 
-  /// Returns this << n *_DIGIT_BITS.
+  /// Returns this << n*_digitBits.
   _BigIntImpl _dlShift(int n) {
     final used = _used;
     if (used == 0) {
@@ -433,7 +448,7 @@
     }
     final resultUsed = used + n;
     final digits = _digits;
-    final resultDigits = new Uint32List(resultUsed);
+    final resultDigits = _newDigits(resultUsed);
     for (int i = used - 1; i >= 0; i--) {
       resultDigits[i + n] = digits[i];
     }
@@ -444,7 +459,7 @@
   ///
   /// Returns `resultUsed`.
   ///
-  /// `resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n*_DIGIT_BITS`.
+  /// `resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n*_digitBits`.
   static int _dlShiftDigits(
       Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
     if (xUsed == 0) {
@@ -454,16 +469,20 @@
       return xUsed;
     }
     final resultUsed = xUsed + n;
+    assert(resultDigits.length >= resultUsed + (resultUsed & 1));
     for (int i = xUsed - 1; i >= 0; i--) {
       resultDigits[i + n] = xDigits[i];
     }
     for (int i = n - 1; i >= 0; i--) {
       resultDigits[i] = 0;
     }
+    if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0;
+    }
     return resultUsed;
   }
 
-  /// Returns `this >> n*_DIGIT_BITS`.
+  /// Returns `this >> n*_digitBits`.
   _BigIntImpl _drShift(int n) {
     final used = _used;
     if (used == 0) {
@@ -474,7 +493,7 @@
       return _isNegative ? _minusOne : zero;
     }
     final digits = _digits;
-    final resultDigits = new Uint32List(resultUsed);
+    final resultDigits = _newDigits(resultUsed);
     for (var i = n; i < used; i++) {
       resultDigits[i - n] = digits[i];
     }
@@ -490,12 +509,35 @@
     return result;
   }
 
+  /// Same as [_drShift] but works on the decomposed big integers.
+  ///
+  /// Returns `resultUsed`.
+  ///
+  /// `resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n*_digitBits`.
+  static int _drShiftDigits(
+      Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+    final resultUsed = xUsed - n;
+    if (resultUsed <= 0) {
+      return 0;
+    }
+    assert(resultDigits.length >= resultUsed + (resultUsed & 1));
+    for (var i = n; i < xUsed; i++) {
+      resultDigits[i - n] = xDigits[i];
+    }
+    if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0;
+    }
+    return resultUsed;
+  }
+
   /// Shifts the digits of [xDigits] into the right place in [resultDigits].
   ///
-  /// `resultDigits[ds..xUsed+ds] = xDigits[0..xUsed-1] << (n % _DIGIT_BITS)`
-  ///   where `ds = ceil(n / _DIGIT_BITS)`
+  /// `resultDigits[ds..xUsed+ds] = xDigits[0..xUsed-1] << (n % _digitBits)`
+  ///   where `ds = ceil(n / _digitBits)`
   ///
   /// Does *not* clear digits below ds.
+  ///
+  /// Note: This function may be intrinsified.
   static void _lsh(
       Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
     final digitShift = n ~/ _digitBits;
@@ -525,21 +567,22 @@
    */
   _BigIntImpl operator <<(int shiftAmount) {
     if (shiftAmount < 0) {
-      throw new ArgumentError("shift-amount must be posititve $shiftAmount");
+      throw new ArgumentError("shift-amount must be positive $shiftAmount");
     }
     final digitShift = shiftAmount ~/ _digitBits;
     final bitShift = shiftAmount % _digitBits;
     if (bitShift == 0) {
       return _dlShift(digitShift);
     }
+    // Need one extra digit to hold bits shifted by bitShift.
     var resultUsed = _used + digitShift + 1;
-    var resultDigits = new Uint32List(resultUsed);
+    var resultDigits = _newDigits(resultUsed);
     _lsh(_digits, _used, shiftAmount, resultDigits);
     return new _BigIntImpl._(_isNegative, resultUsed, resultDigits);
   }
 
-  // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n.
-  // Returns resultUsed.
+  /// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n.
+  /// Returns resultUsed.
   static int _lShiftDigits(
       Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
     final digitsShift = n ~/ _digitBits;
@@ -547,7 +590,9 @@
     if (bitShift == 0) {
       return _dlShiftDigits(xDigits, xUsed, digitsShift, resultDigits);
     }
+    // Need one extra digit to hold bits shifted by bitShift.
     var resultUsed = xUsed + digitsShift + 1;
+    assert(resultDigits.length >= resultUsed + (resultUsed & 1));
     _lsh(xDigits, xUsed, n, resultDigits);
     var i = digitsShift;
     while (--i >= 0) {
@@ -555,11 +600,15 @@
     }
     if (resultDigits[resultUsed - 1] == 0) {
       resultUsed--; // Clamp result.
+    } else if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0;
     }
     return resultUsed;
   }
 
-  // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
+  /// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
+  ///
+  /// Note: This function may be intrinsified.
   static void _rsh(
       Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
     final digitsShift = n ~/ _digitBits;
@@ -587,7 +636,7 @@
    */
   _BigIntImpl operator >>(int shiftAmount) {
     if (shiftAmount < 0) {
-      throw new ArgumentError("shift-amount must be posititve $shiftAmount");
+      throw new ArgumentError("shift-amount must be positive $shiftAmount");
     }
     final digitShift = shiftAmount ~/ _digitBits;
     final bitShift = shiftAmount % _digitBits;
@@ -600,7 +649,7 @@
       return _isNegative ? _minusOne : zero;
     }
     final digits = _digits;
-    final resultDigits = new Uint32List(resultUsed);
+    final resultDigits = _newDigits(resultUsed);
     _rsh(digits, used, shiftAmount, resultDigits);
     final result = new _BigIntImpl._(_isNegative, resultUsed, resultDigits);
     if (_isNegative) {
@@ -617,6 +666,29 @@
     return result;
   }
 
+  /// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
+  /// Returns resultUsed.
+  static int _rShiftDigits(
+      Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+    final digitShift = n ~/ _digitBits;
+    final bitShift = n % _digitBits;
+    if (bitShift == 0) {
+      return _drShiftDigits(xDigits, xUsed, digitShift, resultDigits);
+    }
+    var resultUsed = xUsed - digitShift;
+    if (resultUsed <= 0) {
+      return 0;
+    }
+    assert(resultDigits.length >= resultUsed + (resultUsed & 1));
+    _rsh(xDigits, xUsed, n, resultDigits);
+    if (resultDigits[resultUsed - 1] == 0) {
+      resultUsed--; // Clamp result.
+    } else if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0;
+    }
+    return resultUsed;
+  }
+
   /// Compares this to [other] taking the absolute value of both operands.
   ///
   /// Returns 0 if abs(this) == abs(other); a positive number if
@@ -658,8 +730,10 @@
     return result;
   }
 
-  // resultDigits[0..used] = digits[0..used-1] + otherDigits[0..otherUsed-1].
-  // used >= otherUsed > 0.
+  /// resultDigits[0..used] = digits[0..used-1] + otherDigits[0..otherUsed-1].
+  /// used >= otherUsed > 0.
+  ///
+  /// Note: This function may be intrinsified.
   static void _absAdd(Uint32List digits, int used, Uint32List otherDigits,
       int otherUsed, Uint32List resultDigits) {
     assert(used >= otherUsed && otherUsed > 0);
@@ -677,12 +751,13 @@
     resultDigits[used] = carry;
   }
 
-  // resultDigits[0..used-1] = digits[0..used-1] - otherDigits[0..otherUsed-1].
-  // used >= otherUsed > 0.
+  /// resultDigits[0..used-1] = digits[0..used-1] - otherDigits[0..otherUsed-1].
+  /// used >= otherUsed > 0.
+  ///
+  /// Note: This function may be intrinsified.
   static void _absSub(Uint32List digits, int used, Uint32List otherDigits,
       int otherUsed, Uint32List resultDigits) {
     assert(used >= otherUsed && otherUsed > 0);
-
     var carry = 0;
     for (var i = 0; i < otherUsed; i++) {
       carry += digits[i] - otherDigits[i];
@@ -711,7 +786,7 @@
       return _isNegative == isNegative ? this : -this;
     }
     var resultUsed = used + 1;
-    var resultDigits = new Uint32List(resultUsed);
+    var resultDigits = _newDigits(resultUsed);
     _absAdd(_digits, used, other._digits, otherUsed, resultDigits);
     return new _BigIntImpl._(isNegative, resultUsed, resultDigits);
   }
@@ -730,7 +805,7 @@
     if (otherUsed == 0) {
       return _isNegative == isNegative ? this : -this;
     }
-    var resultDigits = new Uint32List(used);
+    var resultDigits = _newDigits(used);
     _absSub(_digits, used, other._digits, otherUsed, resultDigits);
     return new _BigIntImpl._(isNegative, used, resultDigits);
   }
@@ -740,7 +815,7 @@
     var resultUsed = _min(_used, other._used);
     var digits = _digits;
     var otherDigits = other._digits;
-    var resultDigits = new Uint32List(resultUsed);
+    var resultDigits = _newDigits(resultUsed);
     for (var i = 0; i < resultUsed; i++) {
       resultDigits[i] = digits[i] & otherDigits[i];
     }
@@ -752,7 +827,7 @@
     var resultUsed = _used;
     var digits = _digits;
     var otherDigits = other._digits;
-    var resultDigits = new Uint32List(resultUsed);
+    var resultDigits = _newDigits(resultUsed);
     var m = _min(resultUsed, other._used);
     for (var i = 0; i < m; i++) {
       resultDigits[i] = digits[i] & ~otherDigits[i];
@@ -770,7 +845,7 @@
     var resultUsed = _max(used, otherUsed);
     var digits = _digits;
     var otherDigits = other._digits;
-    var resultDigits = new Uint32List(resultUsed);
+    var resultDigits = _newDigits(resultUsed);
     var l, m;
     if (used < otherUsed) {
       l = other;
@@ -796,7 +871,7 @@
     var resultUsed = _max(used, otherUsed);
     var digits = _digits;
     var otherDigits = other._digits;
-    var resultDigits = new Uint32List(resultUsed);
+    var resultDigits = _newDigits(resultUsed);
     var l, m;
     if (used < otherUsed) {
       l = other;
@@ -983,23 +1058,33 @@
     return other._absSubSetSign(this, !isNegative);
   }
 
-  /// Multiplies [x] with [multiplicandDigits] and adds the result to
-  /// [accumulatorDigits].
+  /// Multiplies `xDigits[xIndex]` with `multiplicandDigits` and adds the result
+  /// to `accumulatorDigits`.
   ///
-  /// The [multiplicandDigits] in the range [i] to [i]+[n]-1 are the
+  /// The `multiplicandDigits` in the range `i` to `i`+`n`-1 are the
   /// multiplicand digits.
   ///
-  /// The [acculumatorDigits] in the range [j] to [j]+[n]-1 are the accumulator
+  /// The `acculumatorDigits` in the range `j` to `j`+`n`-1 are the accumulator
   /// digits.
   ///
-  /// Adds the result of the multiplicand-digits * [x] to the accumulator.
+  /// Concretely:
+  /// `accumulatorDigits[j..j+n] += xDigits[xIndex] * m_digits[i..i+n-1]`.
+  /// Returns 1.
   ///
-  /// Concretely: `accumulatorDigits[j..j+n] += x * m_digits[i..i+n-1]`.
-  static void _mulAdd(int x, Uint32List multiplicandDigits, int i,
-      Uint32List accumulatorDigits, int j, int n) {
+  /// Note: This function may be intrinsified. Intrinsics on 64-bit platforms
+  /// process digit pairs at even indices and returns 2.
+  static int _mulAdd(
+      Uint32List xDigits,
+      int xIndex,
+      Uint32List multiplicandDigits,
+      int i,
+      Uint32List accumulatorDigits,
+      int j,
+      int n) {
+    int x = xDigits[xIndex];
     if (x == 0) {
       // No-op if x is 0.
-      return;
+      return 1;
     }
     int carry = 0;
     int xl = x & _halfDigitMask;
@@ -1020,6 +1105,63 @@
       carry = l >> _digitBits;
       accumulatorDigits[j++] = l & _digitMask;
     }
+    return 1;
+  }
+
+  /// Multiplies `xDigits[i]` with `xDigits` and adds the result to
+  /// `accumulatorDigits`.
+  ///
+  /// The `xDigits` in the range `i` to `used`-1 are the multiplicand digits.
+  ///
+  /// The `acculumatorDigits` in the range 2*`i` to `i`+`used`-1 are the
+  /// accumulator digits.
+  ///
+  /// Concretely:
+  /// `accumulatorDigits[2*i..i+used-1] += xDigits[i]*xDigits[i] +
+  /// 2*xDigits[i]*xDigits[i+1..used-1]`.
+  /// Returns 1.
+  ///
+  /// Note: This function may be intrinsified. Intrinsics on 64-bit platforms
+  /// process digit pairs at even indices and returns 2.
+  static int _sqrAdd(
+      Uint32List xDigits, int i, Uint32List acculumatorDigits, int used) {
+    int x = xDigits[i];
+    if (x == 0) return 1;
+    int j = 2 * i;
+    int carry = 0;
+    int xl = x & _halfDigitMask;
+    int xh = x >> _halfDigitBits;
+    int ph = 2 * xh * xl;
+    int pl = xl * xl +
+        ((ph & _halfDigitMask) << _halfDigitBits) +
+        acculumatorDigits[j];
+    carry = (pl >> _digitBits) + (ph >> _halfDigitBits) + xh * xh;
+    acculumatorDigits[j] = pl & _digitMask;
+    x <<= 1;
+    xl = x & _halfDigitMask;
+    xh = x >> _halfDigitBits;
+    int n = used - i - 1;
+    int k = i + 1;
+    j++;
+    while (--n >= 0) {
+      int l = xDigits[k] & _halfDigitMask;
+      int h = xDigits[k++] >> _halfDigitBits;
+      int ph = xh * l + h * xl;
+      int pl = xl * l +
+          ((ph & _halfDigitMask) << _halfDigitBits) +
+          acculumatorDigits[j] +
+          carry;
+      carry = (pl >> _digitBits) + (ph >> _halfDigitBits) + xh * h;
+      acculumatorDigits[j++] = pl & _digitMask;
+    }
+    carry += acculumatorDigits[i + used];
+    if (carry >= _digitBase) {
+      acculumatorDigits[i + used] = carry - _digitBase;
+      acculumatorDigits[i + used + 1] = 1;
+    } else {
+      acculumatorDigits[i + used] = carry;
+    }
+    return 1;
   }
 
   /// Multiplication operator.
@@ -1033,44 +1175,91 @@
     var resultUsed = used + otherUsed;
     var digits = _digits;
     var otherDigits = other._digits;
-    var resultDigits = new Uint32List(resultUsed);
+    var resultDigits = _newDigits(resultUsed);
     var i = 0;
     while (i < otherUsed) {
-      _mulAdd(otherDigits[i], digits, 0, resultDigits, i, used);
-      i++;
+      i += _mulAdd(otherDigits, i, digits, 0, resultDigits, i, used);
     }
     return new _BigIntImpl._(
         _isNegative != other._isNegative, resultUsed, resultDigits);
   }
 
-  // r_digits[0..rUsed-1] = xDigits[0..xUsed-1]*otherDigits[0..otherUsed-1].
-  // Return resultUsed = xUsed + otherUsed.
+  // resultDigits[0..resultUsed-1] =
+  //     xDigits[0..xUsed-1]*otherDigits[0..otherUsed-1].
+  // Returns resultUsed = xUsed + otherUsed.
   static int _mulDigits(Uint32List xDigits, int xUsed, Uint32List otherDigits,
       int otherUsed, Uint32List resultDigits) {
     var resultUsed = xUsed + otherUsed;
-    var i = resultUsed;
+    var i = resultUsed + (resultUsed & 1);
     assert(resultDigits.length >= i);
     while (--i >= 0) {
       resultDigits[i] = 0;
     }
     i = 0;
     while (i < otherUsed) {
-      _mulAdd(otherDigits[i], xDigits, 0, resultDigits, i, xUsed);
-      i++;
+      i += _mulAdd(otherDigits, i, xDigits, 0, resultDigits, i, xUsed);
     }
     return resultUsed;
   }
 
-  /// Returns an estimate of `digits[i-1..i] ~/ topDigitDivisor`.
-  static int _estimateQuotientDigit(
-      int topDigitDivisor, Uint32List digits, int i) {
-    if (digits[i] == topDigitDivisor) return _digitMask;
-    // Chop off one bit, since a Mint cannot hold 2 digits.
-    var quotientDigit =
-        ((digits[i] << (_digitBits - 1)) | (digits[i - 1] >> 1)) ~/
-            (topDigitDivisor >> 1);
-    if (quotientDigit > _digitMask) return _digitMask;
-    return quotientDigit;
+  // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1]^2.
+  // Returns resultUsed = 2*xUsed.
+  static int _sqrDigits(
+      Uint32List xDigits, int xUsed, Uint32List resultDigits) {
+    var resultUsed = 2 * xUsed;
+    assert(resultDigits.length >= resultUsed);
+    // Since resultUsed is even, no need for a leading zero for
+    // 64-bit processing.
+    var i = resultUsed;
+    while (--i >= 0) {
+      resultDigits[i] = 0;
+    }
+    i = 0;
+    while (i < xUsed - 1) {
+      i += _sqrAdd(xDigits, i, resultDigits, xUsed);
+    }
+    // The last step is already done if digit pairs were processed above.
+    if (i < xUsed) {
+      _mulAdd(xDigits, i, xDigits, i, resultDigits, 2 * i, 1);
+    }
+    return resultUsed;
+  }
+
+  // Indices of the arguments of _estimateQuotientDigit.
+  // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair
+  // of the divisor is provided in the args array, and a 64-bit estimated
+  // quotient is returned. However, on 32-bit platforms, the low 32-bit digit is
+  // ignored and only one 32-bit digit is returned as the estimated quotient.
+  static const int _divisorLowTopDigit = 0; // Low digit of top pair of divisor.
+  static const int _divisorTopDigit = 1; // Top digit of divisor.
+  static const int _quotientDigit = 2; // Estimated quotient.
+  static const int _quotientHighDigit = 3; // High digit of estimated quotient.
+
+  /// Estimate `args[_quotientDigit] = digits[i-1..i] ~/ args[_divisorTopDigit]`
+  /// Returns 1.
+  ///
+  /// Note: This function may be intrinsified. Intrinsics on 64-bit platforms
+  /// process a digit pair (i always odd):
+  /// Estimate `args[_quotientDigit.._quotientHighDigit] = digits[i-3..i] ~/
+  /// args[_divisorLowTopDigit.._divisorTopDigit]`.
+  /// Returns 2.
+  static int _estimateQuotientDigit(Uint32List args, Uint32List digits, int i) {
+    // Verify that digit pairs are accessible for 64-bit processing.
+    assert(digits.length >= 4);
+    if (digits[i] == args[_divisorTopDigit]) {
+      args[_quotientDigit] = _digitMask;
+    } else {
+      // Chop off one bit, since a Mint cannot hold 2 digits.
+      var quotientDigit =
+          ((digits[i] << (_digitBits - 1)) | (digits[i - 1] >> 1)) ~/
+              (args[_divisorTopDigit] >> 1);
+      if (quotientDigit > _digitMask) {
+        args[_quotientDigit] = _digitMask;
+      } else {
+        args[_quotientDigit] = quotientDigit;
+      }
+    }
+    return 1;
   }
 
   /// Returns `trunc(this / other)`, with `other != 0`.
@@ -1134,32 +1323,43 @@
     assert(_used >= other._used);
 
     var nsh = _digitBits - other._digits[other._used - 1].bitLength;
+    // For 64-bit processing, make sure other has an even number of digits.
+    if (other._used.isOdd) {
+      nsh += _digitBits;
+    }
     // Concatenated positive quotient and normalized positive remainder.
     // The resultDigits can have at most one more digit than the dividend.
     Uint32List resultDigits;
     int resultUsed;
-    // Normalized positive divisor.
+    // Normalized positive divisor (referred to as 'y').
     // The normalized divisor has the most-significant bit of its most
     // significant digit set.
     // This makes estimating the quotient easier.
     Uint32List yDigits;
     int yUsed;
     if (nsh > 0) {
-      yDigits = new Uint32List(other._used + 5);
+      // Extra digits for normalization.
+      yDigits = _newDigits(other._used + (nsh % _digitBits) + 1);
       yUsed = _lShiftDigits(other._digits, other._used, nsh, yDigits);
-      resultDigits = new Uint32List(_used + 5);
+      // Extra digits for normalization, also used for possible _mulAdd carry.
+      resultDigits = _newDigits(_used + (nsh % _digitBits) + 1);
       resultUsed = _lShiftDigits(_digits, _used, nsh, resultDigits);
     } else {
       yDigits = other._digits;
       yUsed = other._used;
-      resultDigits = _cloneDigits(_digits, 0, _used, _used + 2);
+      // Extra digit to hold possible _mulAdd carry.
+      resultDigits = _cloneDigits(_digits, 0, _used, _used + 1);
       resultUsed = _used;
     }
-    var topDigitDivisor = yDigits[yUsed - 1];
-    var i = resultUsed;
+    Uint32List args = _newDigits(4);
+    args[_divisorLowTopDigit] = yDigits[yUsed - 2];
+    args[_divisorTopDigit] = yDigits[yUsed - 1];
+    // For 64-bit processing, make sure yUsed, i, and j are even.
+    assert(yUsed.isEven);
+    var i = resultUsed + (resultUsed & 1);
     var j = i - yUsed;
-    // tmpDigits is a temporary array of i (resultUsed) digits.
-    var tmpDigits = new Uint32List(i);
+    // tmpDigits is a temporary array of i (even resultUsed) digits.
+    var tmpDigits = _newDigits(i);
     var tmpUsed = _dlShiftDigits(yDigits, yUsed, j, tmpDigits);
     // Explicit first division step in case normalized dividend is larger or
     // equal to shifted normalized divisor.
@@ -1172,32 +1372,61 @@
       // Account for possible carry in _mulAdd step.
       resultDigits[resultUsed++] = 0;
     }
-
+    if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0; // Leading zero for 64-bit processing.
+    }
     // Negate y so we can later use _mulAdd instead of non-existent _mulSub.
-    var nyDigits = new Uint32List(yUsed + 2);
+    var nyDigits = _newDigits(yUsed + 2);
     nyDigits[yUsed] = 1;
     _absSub(nyDigits, yUsed + 1, yDigits, yUsed, nyDigits);
     // nyDigits is read-only and has yUsed digits (possibly including several
-    // leading zeros).
+    // leading zeros) plus a leading zero for 64-bit processing.
     // resultDigits is modified during iteration.
     // resultDigits[0..yUsed-1] is the current remainder.
     // resultDigits[yUsed..resultUsed-1] is the current quotient.
     --i;
-
     while (j > 0) {
-      var estimatedQuotientDigit =
-          _estimateQuotientDigit(topDigitDivisor, resultDigits, i);
-      j--;
-      _mulAdd(estimatedQuotientDigit, nyDigits, 0, resultDigits, j, yUsed);
-      if (resultDigits[i] < estimatedQuotientDigit) {
-        // Reusing the already existing tmpDigits array.
-        var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
-        _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
-        while (resultDigits[i] < --estimatedQuotientDigit) {
+      var d0 = _estimateQuotientDigit(args, resultDigits, i);
+      j -= d0;
+      var d1 =
+          _mulAdd(args, _quotientDigit, nyDigits, 0, resultDigits, j, yUsed);
+      // _estimateQuotientDigit and _mulAdd must agree on the number of digits
+      // to process.
+      assert(d0 == d1);
+      if (d0 == 1) {
+        if (resultDigits[i] < args[_quotientDigit]) {
+          // Reusing the already existing tmpDigits array.
+          var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
           _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          while (resultDigits[i] < --args[_quotientDigit]) {
+            _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          }
+        }
+      } else {
+        assert(d0 == 2);
+        assert(resultDigits[i] <= args[_quotientHighDigit]);
+        if (resultDigits[i] < args[_quotientHighDigit] ||
+            resultDigits[i - 1] < args[_quotientDigit]) {
+          // Reusing the already existing tmpDigits array.
+          var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+          _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          if (args[_quotientDigit] == 0) {
+            --args[_quotientHighDigit];
+          }
+          --args[_quotientDigit];
+          assert(resultDigits[i] <= args[_quotientHighDigit]);
+          while (resultDigits[i] < args[_quotientHighDigit] ||
+              resultDigits[i - 1] < args[_quotientDigit]) {
+            _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+            if (args[_quotientDigit] == 0) {
+              --args[_quotientHighDigit];
+            }
+            --args[_quotientDigit];
+            assert(resultDigits[i] <= args[_quotientHighDigit]);
+          }
         }
       }
-      i--;
+      i -= d0;
     }
     // Cache result.
     _lastDividendDigits = _digits;
@@ -1210,6 +1439,108 @@
     _lastRem_nsh = nsh;
   }
 
+  // Customized version of _rem() minimizing allocations for use in reduction.
+  // Input:
+  //   xDigits[0..xUsed-1]: positive dividend.
+  //   yDigits[0..yUsed-1]: normalized positive divisor.
+  //   nyDigits[0..yUsed-1]: negated yDigits.
+  //   nsh: normalization shift amount.
+  //   args: top y digit(s) and place holder for estimated quotient digit(s).
+  //   tmpDigits: temp array of 2*yUsed digits.
+  //   resultDigits: result digits array large enough to temporarily hold
+  //                 concatenated quotient and normalized remainder.
+  // Output:
+  //   resultDigits[0..resultUsed-1]: positive remainder.
+  // Returns resultUsed.
+  static int _remDigits(
+      Uint32List xDigits,
+      int xUsed,
+      Uint32List yDigits,
+      int yUsed,
+      Uint32List nyDigits,
+      int nsh,
+      Uint32List args,
+      Uint32List tmpDigits,
+      Uint32List resultDigits) {
+    // Initialize resultDigits to normalized positive dividend.
+    var resultUsed = _lShiftDigits(xDigits, xUsed, nsh, resultDigits);
+    // For 64-bit processing, make sure yUsed, i, and j are even.
+    assert(yUsed.isEven);
+    var i = resultUsed + (resultUsed & 1);
+    var j = i - yUsed;
+    var tmpUsed = _dlShiftDigits(yDigits, yUsed, j, tmpDigits);
+    // Explicit first division step in case normalized dividend is larger or
+    // equal to shifted normalized divisor.
+    if (_compareDigits(resultDigits, resultUsed, tmpDigits, tmpUsed) >= 0) {
+      assert(i == resultUsed);
+      resultDigits[resultUsed++] = 1; // Quotient = 1.
+      // Subtract divisor from remainder.
+      _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+    } else {
+      // Account for possible carry in _mulAdd step.
+      resultDigits[resultUsed++] = 0;
+    }
+    if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0; // Leading zero for 64-bit processing.
+    }
+    // Negated yDigits passed in nyDigits allow the use of _mulAdd instead of
+    // unimplemented _mulSub.
+    // nyDigits is read-only and has yUsed digits (possibly including several
+    // leading zeros) plus a leading zero for 64-bit processing.
+    // resultDigits is modified during iteration.
+    // resultDigits[0..yUsed-1] is the current remainder.
+    // resultDigits[yUsed..resultUsed-1] is the current quotient.
+    --i;
+    while (j > 0) {
+      var d0 = _estimateQuotientDigit(args, resultDigits, i);
+      j -= d0;
+      var d1 =
+          _mulAdd(args, _quotientDigit, nyDigits, 0, resultDigits, j, yUsed);
+      // _estimateQuotientDigit and _mulAdd must agree on the number of digits
+      // to process.
+      assert(d0 == d1);
+      if (d0 == 1) {
+        if (resultDigits[i] < args[_quotientDigit]) {
+          var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+          _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          while (resultDigits[i] < --args[_quotientDigit]) {
+            _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          }
+        }
+      } else {
+        assert(d0 == 2);
+        assert(resultDigits[i] <= args[_quotientHighDigit]);
+        if ((resultDigits[i] < args[_quotientHighDigit]) ||
+            (resultDigits[i - 1] < args[_quotientDigit])) {
+          var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+          _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          if (args[_quotientDigit] == 0) {
+            --args[_quotientHighDigit];
+          }
+          --args[_quotientDigit];
+          assert(resultDigits[i] <= args[_quotientHighDigit]);
+          while ((resultDigits[i] < args[_quotientHighDigit]) ||
+              (resultDigits[i - 1] < args[_quotientDigit])) {
+            _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+            if (args[_quotientDigit] == 0) {
+              --args[_quotientHighDigit];
+            }
+            --args[_quotientDigit];
+            assert(resultDigits[i] <= args[_quotientHighDigit]);
+          }
+        }
+      }
+      i -= d0;
+    }
+    // Return remainder, i.e. denormalized resultDigits[0..yUsed-1].
+    resultUsed = yUsed;
+    if (nsh > 0) {
+      // Denormalize remainder.
+      resultUsed = _rShiftDigits(resultDigits, resultUsed, nsh, resultDigits);
+    }
+    return resultUsed;
+  }
+
   int get hashCode {
     // This is the [Jenkins hash function][1] but using masking to keep
     // values in SMI range.
@@ -1239,8 +1570,8 @@
   /**
    * Test whether this value is numerically equal to `other`.
    *
-   * If [other] is a [_BigIntImpl] returns whether the two operands have the same
-   * value.
+   * If [other] is a [_BigIntImpl] returns whether the two operands have the
+   * same value.
    *
    * Returns false if `other` is not a [_BigIntImpl].
    */
@@ -1419,38 +1750,142 @@
     }
     if (exponent._isZero) return one;
 
-    final modulusUsed = modulus._used;
-    final modulusUsed2p4 = 2 * modulusUsed + 4;
     final exponentBitlen = exponent.bitLength;
     if (exponentBitlen <= 0) return one;
-    _BigIntReduction z = new _BigIntClassic(modulus);
-    var resultDigits = new Uint32List(modulusUsed2p4);
-    var result2Digits = new Uint32List(modulusUsed2p4);
-    var gDigits = new Uint32List(modulusUsed);
-    var gUsed = z.convert(this, gDigits);
-    // Initialize result with g.
-    // Copy leading zero if any.
-    for (int j = gUsed - 1; j >= 0; j--) {
-      resultDigits[j] = gDigits[j];
+    final bool cannotUseMontgomery = modulus.isEven || abs() >= modulus;
+    if (cannotUseMontgomery || exponentBitlen < 64) {
+      _BigIntReduction z = (cannotUseMontgomery || exponentBitlen < 8)
+          ? new _BigIntClassicReduction(modulus)
+          : new _BigIntMontgomeryReduction(modulus);
+      var resultDigits = _newDigits(2 * z._normModulusUsed + 2);
+      var result2Digits = _newDigits(2 * z._normModulusUsed + 2);
+      var gDigits = _newDigits(z._normModulusUsed);
+      var gUsed = z._convert(this, gDigits);
+      // Initialize result with g.
+      // Copy leading zero if any.
+      for (int j = gUsed + (gUsed & 1) - 1; j >= 0; j--) {
+        resultDigits[j] = gDigits[j];
+      }
+      var resultUsed = gUsed;
+      var result2Used;
+      for (int i = exponentBitlen - 2; i >= 0; i--) {
+        result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+        if (exponent._digits[i ~/ _digitBits] & (1 << (i % _digitBits)) != 0) {
+          resultUsed =
+              z._mul(result2Digits, result2Used, gDigits, gUsed, resultDigits);
+        } else {
+          // Swap result and result2.
+          var tmpDigits = resultDigits;
+          var tmpUsed = resultUsed;
+          resultDigits = result2Digits;
+          resultUsed = result2Used;
+          result2Digits = tmpDigits;
+          result2Used = tmpUsed;
+        }
+      }
+      return z._revert(resultDigits, resultUsed);
     }
-    var resultUsed = gUsed;
-    var result2Used;
-    for (int i = exponentBitlen - 2; i >= 0; i--) {
-      result2Used = z.sqr(resultDigits, resultUsed, result2Digits);
-      if (!(exponent & (one << i))._isZero) {
-        resultUsed =
-            z.mul(result2Digits, result2Used, gDigits, gUsed, resultDigits);
-      } else {
-        // Swap result and result2.
-        var tmpDigits = resultDigits;
-        var tmpUsed = resultUsed;
-        resultDigits = result2Digits;
-        resultUsed = result2Used;
-        result2Digits = tmpDigits;
-        result2Used = tmpUsed;
+    var k;
+    if (exponentBitlen < 18)
+      k = 1;
+    else if (exponentBitlen < 48)
+      k = 3;
+    else if (exponentBitlen < 144)
+      k = 4;
+    else if (exponentBitlen < 768)
+      k = 5;
+    else
+      k = 6;
+    _BigIntReduction z = new _BigIntMontgomeryReduction(modulus);
+    var n = 3;
+    final k1 = k - 1;
+    final km = (1 << k) - 1;
+    List gDigits = new List(km + 1);
+    List gUsed = new List(km + 1);
+    gDigits[1] = _newDigits(z._normModulusUsed);
+    gUsed[1] = z._convert(this, gDigits[1]);
+    if (k > 1) {
+      var g2Digits = _newDigits(2 * z._normModulusUsed + 2);
+      var g2Used = z._sqr(gDigits[1], gUsed[1], g2Digits);
+      while (n <= km) {
+        gDigits[n] = _newDigits(2 * z._normModulusUsed + 2);
+        gUsed[n] =
+            z._mul(g2Digits, g2Used, gDigits[n - 2], gUsed[n - 2], gDigits[n]);
+        n += 2;
       }
     }
-    return z.revert(resultDigits, resultUsed);
+    var w;
+    var isOne = true;
+    var resultDigits = one._digits;
+    var resultUsed = one._used;
+    var result2Digits = _newDigits(2 * z._normModulusUsed + 2);
+    var result2Used;
+    var exponentDigits = exponent._digits;
+    var j = exponent._used - 1;
+    var i = exponentDigits[j].bitLength - 1;
+    while (j >= 0) {
+      if (i >= k1) {
+        w = (exponentDigits[j] >> (i - k1)) & km;
+      } else {
+        w = (exponentDigits[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
+        if (j > 0) {
+          w |= exponentDigits[j - 1] >> (_digitBits + i - k1);
+        }
+      }
+      n = k;
+      while ((w & 1) == 0) {
+        w >>= 1;
+        --n;
+      }
+      if ((i -= n) < 0) {
+        i += _digitBits;
+        --j;
+      }
+      if (isOne) {
+        // r == 1, don't bother squaring or multiplying it.
+        resultDigits = _newDigits(2 * z._normModulusUsed + 2);
+        resultUsed = gUsed[w];
+        var gwDigits = gDigits[w];
+        var ri = resultUsed + (resultUsed & 1); // Copy leading zero if any.
+        while (--ri >= 0) {
+          resultDigits[ri] = gwDigits[ri];
+        }
+        isOne = false;
+      } else {
+        while (n > 1) {
+          result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+          resultUsed = z._sqr(result2Digits, result2Used, resultDigits);
+          n -= 2;
+        }
+        if (n > 0) {
+          result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+        } else {
+          var swapDigits = resultDigits;
+          var swapUsed = resultUsed;
+          resultDigits = result2Digits;
+          resultUsed = result2Used;
+          result2Digits = swapDigits;
+          result2Used = swapUsed;
+        }
+        resultUsed = z._mul(
+            result2Digits, result2Used, gDigits[w], gUsed[w], resultDigits);
+      }
+      while (j >= 0 && (exponentDigits[j] & (1 << i)) == 0) {
+        result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+        var swapDigits = resultDigits;
+        var swapUsed = resultUsed;
+        resultDigits = result2Digits;
+        resultUsed = result2Used;
+        result2Digits = swapDigits;
+        result2Used = swapUsed;
+        if (--i < 0) {
+          i = _digitBits - 1;
+          --j;
+        }
+      }
+    }
+    assert(!isOne);
+    return z._revert(resultDigits, resultUsed);
   }
 
   // If inv is false, returns gcd(x, y).
@@ -1461,10 +1896,10 @@
     var yDigits = y._digits;
     var xUsed = x._used;
     var yUsed = y._used;
-    var maxUsed = xUsed > yUsed ? xUsed : yUsed;
-    var unshiftedMaxUsed = maxUsed; // Keep
-    xDigits = _cloneDigits(xDigits, 0, xUsed, maxUsed);
-    yDigits = _cloneDigits(yDigits, 0, yUsed, maxUsed);
+    var maxUsed = _max(xUsed, yUsed);
+    final maxLen = maxUsed + (maxUsed & 1);
+    xDigits = _cloneDigits(xDigits, 0, xUsed, maxLen);
+    yDigits = _cloneDigits(yDigits, 0, yUsed, maxLen);
     int shiftAmount = 0;
     if (inv) {
       if ((yUsed == 1) && (yDigits[0] == 1)) return one;
@@ -1501,26 +1936,25 @@
         yUsed = tmpUsed;
       }
     }
-    var uDigits = _cloneDigits(xDigits, 0, xUsed, unshiftedMaxUsed);
-    var vDigits =
-        _cloneDigits(yDigits, 0, yUsed, unshiftedMaxUsed + 2); // +2 for lsh.
+    var uDigits = _cloneDigits(xDigits, 0, xUsed, maxLen);
+    var vDigits = _cloneDigits(yDigits, 0, yUsed, maxLen + 2); // +2 for lsh.
     final bool ac = (xDigits[0] & 1) == 0;
 
     // Variables a, b, c, and d require one more digit.
     final abcdUsed = maxUsed + 1;
-    final abcdLen = abcdUsed + 2; // +2 to satisfy _absAdd.
+    final abcdLen = abcdUsed + (abcdUsed & 1) + 2; // +2 to satisfy _absAdd.
     var aDigits, bDigits, cDigits, dDigits;
     bool aIsNegative, bIsNegative, cIsNegative, dIsNegative;
     if (ac) {
-      aDigits = new Uint32List(abcdLen);
+      aDigits = _newDigits(abcdLen);
       aIsNegative = false;
       aDigits[0] = 1;
-      cDigits = new Uint32List(abcdLen);
+      cDigits = _newDigits(abcdLen);
       cIsNegative = false;
     }
-    bDigits = new Uint32List(abcdLen);
+    bDigits = _newDigits(abcdLen);
     bIsNegative = false;
-    dDigits = new Uint32List(abcdLen);
+    dDigits = _newDigits(abcdLen);
     dIsNegative = false;
     dDigits[0] = 1;
 
@@ -2046,27 +2480,240 @@
 
 // Interface for modular reduction.
 abstract class _BigIntReduction {
-  // Return the number of digits used by r_digits.
-  int convert(_BigIntImpl x, Uint32List r_digits);
-  int mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
+  int get _normModulusUsed;
+  // Return the number of digits used by resultDigits.
+  int _convert(_BigIntImpl x, Uint32List resultDigits);
+  int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
       Uint32List resultDigits);
-  int sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits);
+  int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits);
 
   // Return x reverted to _BigIntImpl.
-  _BigIntImpl revert(Uint32List xDigits, int xUsed);
+  _BigIntImpl _revert(Uint32List xDigits, int xUsed);
+}
+
+// Montgomery reduction on _BigIntImpl.
+class _BigIntMontgomeryReduction implements _BigIntReduction {
+  final _BigIntImpl _modulus;
+  int _normModulusUsed; // Even if processing 64-bit (digit pairs).
+  Uint32List _modulusDigits;
+  Uint32List _args;
+  int _digitsPerStep; // Number of digits processed in one step. 1 or 2.
+  static const int _xDigit = 0; // Index of digit of x.
+  static const int _xHighDigit = 1; // Index of high digit of x (64-bit only).
+  static const int _rhoDigit = 2; // Index of digit of rho.
+  static const int _rhoHighDigit = 3; // Index of high digit of rho (64-bit).
+  static const int _muDigit = 4; // Index of mu.
+  static const int _muHighDigit = 5; // Index of high 32-bits of mu (64-bit).
+
+  _BigIntMontgomeryReduction(this._modulus) {
+    _modulusDigits = _modulus._digits;
+    _args = _newDigits(6);
+    // Determine if we can process digit pairs by calling an intrinsic.
+    _digitsPerStep = _mulMod(_args, _args, 0);
+    _args[_xDigit] = _modulusDigits[0];
+    if (_digitsPerStep == 1) {
+      _normModulusUsed = _modulus._used;
+      _invDigit(_args);
+    } else {
+      assert(_digitsPerStep == 2);
+      _normModulusUsed = _modulus._used + (_modulus._used & 1);
+      _args[_xHighDigit] = _modulusDigits[1];
+      _invDigitPair(_args);
+    }
+  }
+
+  // Calculates -1/x % _digitBase, x is 32-bit digit.
+  //         xy == 1 (mod m)
+  //         xy =  1+km
+  //   xy(2-xy) = (1+km)(1-km)
+  // x(y(2-xy)) = 1-k^2 m^2
+  // x(y(2-xy)) == 1 (mod m^2)
+  // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+  // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+  //
+  // Operation:
+  //   args[_rhoDigit] = 1/args[_xDigit] mod _digitBase.
+  static void _invDigit(Uint32List args) {
+    var x = args[_xDigit];
+    var y = x & 3; // y == 1/x mod 2^2
+    y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
+    y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
+    y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
+    y = (y * (2 - x * y % _BigIntImpl._digitBase)) % _BigIntImpl._digitBase;
+    // y == 1/x mod _digitBase
+    y = -y; // We really want the negative inverse.
+    args[_rhoDigit] = y & _BigIntImpl._digitMask;
+    assert(((x * y) & _BigIntImpl._digitMask) == _BigIntImpl._digitMask);
+  }
+
+  // Calculates -1/x % _digitBase^2, x is a pair of 32-bit digits.
+  // Operation:
+  //   args[_rhoDigit.._rhoHighDigit] =
+  //     1/args[_xDigit.._xHighDigit] mod _digitBase^2.
+  static void _invDigitPair(Uint32List args) {
+    var two = _BigIntImpl.two;
+    var mask32 = _BigIntImpl._oneDigitMask;
+    var mask64 = _BigIntImpl._twoDigitMask;
+    var xl = args[_xDigit]; // Lower 32-bit digit of x.
+    var y = xl & 3; // y == 1/x mod 2^2
+    y = (y * (2 - (xl & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
+    y = (y * (2 - (xl & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
+    y = (y * (2 - (((xl & 0xffff) * y) & 0xffff))) & 0xffff;
+    // y == 1/x mod 2^16
+    y = (y * (2 - ((xl * y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32
+    var x = (args[_xHighDigit] << _BigIntImpl._digitBits) | xl;
+    y *= 2 - x * y; // Masking with 2^64-1 is implied by 64-bit arithmetic.
+    // y == 1/x mod _digitBase^2
+    y = -y; // We really want the negative inverse.
+    args[_rhoDigit] = y & _BigIntImpl._digitMask;
+    args[_rhoHighDigit] =
+        (y >> _BigIntImpl._digitBits) & _BigIntImpl._digitMask;
+    assert(x * y == -1);
+  }
+
+  // Operation:
+  //   args[_muDigit] = args[_rhoDigit]*digits[i] mod _digitBase.
+  //   Returns 1.
+  // Note: Intrinsics on 64-bit platforms process digit pairs at even indices:
+  //   args[_muDigit.._muHighDigit] =
+  //     args[_rhoDigit.._rhoHighDigit] * digits[i..i+1] mod _digitBase^2.
+  //   Returns 2.
+  static int _mulMod(Uint32List args, Uint32List digits, int i) {
+    var rhol = args[_rhoDigit] & _BigIntImpl._halfDigitMask;
+    var rhoh = args[_rhoDigit] >> _BigIntImpl._halfDigitBits;
+    var dh = digits[i] >> _BigIntImpl._halfDigitBits;
+    var dl = digits[i] & _BigIntImpl._halfDigitMask;
+    args[_muDigit] = (dl * rhol +
+            (((dl * rhoh + dh * rhol) & _BigIntImpl._halfDigitMask) <<
+                _BigIntImpl._halfDigitBits)) &
+        _BigIntImpl._digitMask;
+    return 1;
+  }
+
+  // result = x*R mod _modulus.
+  // Returns resultUsed.
+  int _convert(_BigIntImpl x, Uint32List resultDigits) {
+    // Montgomery reduction only works if abs(x) < _modulus.
+    assert(x.abs() < _modulus);
+    assert(_digitsPerStep == 1 || _normModulusUsed.isEven);
+    var result = x.abs()._dlShift(_normModulusUsed)._rem(_modulus);
+    if (x._isNegative && !result._isNegative && result._used > 0) {
+      result = _modulus - result;
+    }
+    var used = result._used;
+    var digits = result._digits;
+    var i = used + (used & 1);
+    while (--i >= 0) {
+      resultDigits[i] = digits[i];
+    }
+    return used;
+  }
+
+  _BigIntImpl _revert(Uint32List xDigits, int xUsed) {
+    var resultDigits = _newDigits(2 * _normModulusUsed);
+    var i = xUsed + (xUsed & 1);
+    while (--i >= 0) {
+      resultDigits[i] = xDigits[i];
+    }
+    var resultUsed = _reduce(resultDigits, xUsed);
+    return new _BigIntImpl._(false, resultUsed, resultDigits);
+  }
+
+  // x = x/R mod _modulus.
+  // Returns xUsed.
+  int _reduce(Uint32List xDigits, int xUsed) {
+    while (xUsed < 2 * _normModulusUsed) {
+      // Pad x so _mulAdd has enough room later.
+      xDigits[xUsed++] = 0;
+    }
+    var i = 0;
+    while (i < _normModulusUsed) {
+      var d = _mulMod(_args, xDigits, i);
+      assert(d == _digitsPerStep);
+      d = _BigIntImpl._mulAdd(
+          _args, _muDigit, _modulusDigits, 0, xDigits, i, _normModulusUsed);
+      assert(d == _digitsPerStep);
+      i += d;
+    }
+    // Clamp x.
+    while (xUsed > 0 && xDigits[xUsed - 1] == 0) {
+      --xUsed;
+    }
+    xUsed = _BigIntImpl._drShiftDigits(xDigits, xUsed, i, xDigits);
+    if (_BigIntImpl._compareDigits(
+            xDigits, xUsed, _modulusDigits, _normModulusUsed) >=
+        0) {
+      _BigIntImpl._absSub(
+          xDigits, xUsed, _modulusDigits, _normModulusUsed, xDigits);
+    }
+    // Clamp x.
+    while (xUsed > 0 && xDigits[xUsed - 1] == 0) {
+      --xUsed;
+    }
+    return xUsed;
+  }
+
+  int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits) {
+    var resultUsed = _BigIntImpl._sqrDigits(xDigits, xUsed, resultDigits);
+    return _reduce(resultDigits, resultUsed);
+  }
+
+  int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
+      Uint32List resultDigits) {
+    var resultUsed =
+        _BigIntImpl._mulDigits(xDigits, xUsed, yDigits, yUsed, resultDigits);
+    return _reduce(resultDigits, resultUsed);
+  }
 }
 
 // Modular reduction using "classic" algorithm.
-class _BigIntClassic implements _BigIntReduction {
+class _BigIntClassicReduction implements _BigIntReduction {
   final _BigIntImpl _modulus; // Modulus.
-  final _BigIntImpl _normalizedModulus; // Normalized _modulus.
+  int _normModulusUsed;
+  _BigIntImpl _normModulus; // Normalized _modulus.
+  Uint32List _normModulusDigits;
+  Uint32List _negNormModulusDigits; // Negated _normModulus digits.
+  int _modulusNsh; // Normalization shift amount.
+  Uint32List _args; // Top _normModulus digit(s) and place holder for estimated
+  // quotient digit(s).
+  Uint32List _tmpDigits; // Temporary digits used during reduction.
 
-  _BigIntClassic(this._modulus)
-      : _normalizedModulus = _modulus <<
-            (_BigIntImpl._digitBits -
-                _modulus._digits[_modulus._used - 1].bitLength);
+  _BigIntClassicReduction(this._modulus) {
+    // Preprocess arguments to _remDigits.
+    var nsh =
+        _BigIntImpl._digitBits - _modulus._digits[_modulus._used - 1].bitLength;
+    // For 64-bit processing, make sure _negNormModulusDigits has an even number
+    // of digits.
+    if (_modulus._used.isOdd) {
+      nsh += _BigIntImpl._digitBits;
+    }
+    _modulusNsh = nsh;
+    _normModulus = _modulus << nsh;
+    _normModulusUsed = _normModulus._used;
+    _normModulusDigits = _normModulus._digits;
+    assert(_normModulusUsed.isEven);
+    _args = _newDigits(4);
+    _args[_BigIntImpl._divisorLowTopDigit] =
+        _normModulusDigits[_normModulusUsed - 2];
+    _args[_BigIntImpl._divisorTopDigit] =
+        _normModulusDigits[_normModulusUsed - 1];
+    // Negate _normModulus so we can use _mulAdd instead of
+    // unimplemented  _mulSub.
+    var negNormModulus =
+        _BigIntImpl.one._dlShift(_normModulusUsed) - _normModulus;
+    if (negNormModulus._used < _normModulusUsed) {
+      _negNormModulusDigits = _BigIntImpl._cloneDigits(
+          negNormModulus._digits, 0, _normModulusUsed, _normModulusUsed);
+    } else {
+      _negNormModulusDigits = negNormModulus._digits;
+    }
+    // _negNormModulusDigits is read-only and has _normModulusUsed digits (possibly
+    // including several leading zeros) plus a leading zero for 64-bit
+    // processing.
+    _tmpDigits = _newDigits(2 * _normModulusUsed);
+  }
 
-  int convert(_BigIntImpl x, Uint32List resultDigits) {
+  int _convert(_BigIntImpl x, Uint32List resultDigits) {
     var digits;
     var used;
     if (x._isNegative || x.compareTo(_modulus) >= 0) {
@@ -2081,14 +2728,14 @@
       used = x._used;
       digits = x._digits;
     }
-    var i = used; // Copy leading zero if any.
+    var i = used + (used & 1); // Copy leading zero if any.
     while (--i >= 0) {
       resultDigits[i] = digits[i];
     }
     return used;
   }
 
-  _BigIntImpl revert(Uint32List xDigits, int xUsed) {
+  _BigIntImpl _revert(Uint32List xDigits, int xUsed) {
     return new _BigIntImpl._(false, xUsed, xDigits);
   }
 
@@ -2096,24 +2743,27 @@
     if (xUsed < _modulus._used) {
       return xUsed;
     }
-    var reverted = revert(xDigits, xUsed);
-    var rem = reverted._rem(_normalizedModulus);
-    return convert(rem, xDigits);
+    // The function _BigIntImpl._remDigits(...) is optimized for reduction and
+    // equivalent to calling
+    // 'convert(revert(xDigits, xUsed)._rem(_normModulus), xDigits);'
+    return _BigIntImpl._remDigits(
+        xDigits,
+        xUsed,
+        _normModulusDigits,
+        _normModulusUsed,
+        _negNormModulusDigits,
+        _modulusNsh,
+        _args,
+        _tmpDigits,
+        xDigits);
   }
 
-  int sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits) {
-    var b = new _BigIntImpl._(false, xUsed, xDigits);
-    var b2 = b * b;
-    for (int i = 0; i < b2._used; i++) {
-      resultDigits[i] = b2._digits[i];
-    }
-    for (int i = b2._used; i < 2 * xUsed; i++) {
-      resultDigits[i] = 0;
-    }
-    return _reduce(resultDigits, 2 * xUsed);
+  int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits) {
+    var resultUsed = _BigIntImpl._sqrDigits(xDigits, xUsed, resultDigits);
+    return _reduce(resultDigits, resultUsed);
   }
 
-  int mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
+  int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
       Uint32List resultDigits) {
     var resultUsed =
         _BigIntImpl._mulDigits(xDigits, xUsed, yDigits, yUsed, resultDigits);
diff --git a/runtime/lib/compact_hash.dart b/runtime/lib/compact_hash.dart
index 742457a..7961370 100644
--- a/runtime/lib/compact_hash.dart
+++ b/runtime/lib/compact_hash.dart
@@ -115,6 +115,8 @@
   int get _checkSum => _usedData + _deletedKeys;
   bool _isModifiedSince(List oldData, int oldCheckSum) =>
       !identical(_data, oldData) || (_checkSum != oldCheckSum);
+
+  int get length;
 }
 
 class _OperatorEqualsAndHashCode {
@@ -144,7 +146,7 @@
   }
 }
 
-abstract class _LinkedHashMapMixin<K, V> implements _HashVMBase {
+abstract class _LinkedHashMapMixin<K, V> implements _HashBase {
   int _hashCode(e);
   bool _equals(e1, e2);
   int get _checkSum;
@@ -401,7 +403,7 @@
 // Iterates through _data[_offset + _step], _data[_offset + 2*_step], ...
 // and checks for concurrent modification.
 class _CompactIterable<E> extends Iterable<E> {
-  final _table;
+  final _HashBase _table;
   final List _data;
   final int _len;
   final int _offset;
@@ -419,7 +421,7 @@
 }
 
 class _CompactIterator<E> implements Iterator<E> {
-  final _table;
+  final _HashBase _table;
   final List _data;
   final int _len;
   int _offset;
diff --git a/runtime/lib/immutable_map.dart b/runtime/lib/immutable_map.dart
index 726a376..0417d71 100644
--- a/runtime/lib/immutable_map.dart
+++ b/runtime/lib/immutable_map.dart
@@ -5,12 +5,21 @@
 // part of "core_patch.dart";
 
 /// Immutable map class for compiler generated map literals.
+// TODO(lrn): Extend MapBase with UnmodifiableMapMixin when mixins
+// support forwarding const constructors.
 class _ImmutableMap<K, V> implements Map<K, V> {
   final _ImmutableList _kvPairs;
 
   const _ImmutableMap._create(_ImmutableList keyValuePairs)
       : _kvPairs = keyValuePairs;
 
+  Map<K2, V2> cast<K2, V2>() {
+    Map<Object, Object> self = this;
+    return (self is Map<K2, V2>) ? self : this.retype<K2, V2>();
+  }
+
+  Map<K2, V2> retype<K2, V2>() => Map.castFrom<K, V, K2, V2>(this);
+
   V operator [](Object key) {
     // To preserve the key-value order of the map literal, the keys are
     // not sorted. Need to do linear search or implement an additional
@@ -69,6 +78,10 @@
     throw new UnsupportedError("Cannot set value in unmodifiable Map");
   }
 
+  void addAll(Map<K, V> other) {
+    throw new UnsupportedError("Cannot set value in unmodifiable Map");
+  }
+
   V putIfAbsent(K key, V ifAbsent()) {
     throw new UnsupportedError("Cannot set value in unmodifiable Map");
   }
diff --git a/runtime/lib/typed_data_patch.dart b/runtime/lib/typed_data_patch.dart
index 5e2312c..4d6161c 100644
--- a/runtime/lib/typed_data_patch.dart
+++ b/runtime/lib/typed_data_patch.dart
@@ -12,6 +12,7 @@
         ClassID,
         CodeUnits,
         ExpandIterable,
+        FollowedByIterable,
         IterableElementError,
         ListMapView,
         Lists,
@@ -23,6 +24,7 @@
         SubListIterable,
         TakeWhileIterable,
         WhereIterable,
+        WhereTypeIterable,
         patch;
 
 import "dart:collection" show ListBase;
@@ -112,6 +114,11 @@
 
   List<int> _createList(int length);
 
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+  Iterable<int> followedBy(Iterable<int> other) =>
+      new FollowedByIterable<int>.firstEfficient(this, other);
+
   List<R> cast<R>() {
     List<Object> self = this;
     return self is List<R> ? self : List.castFrom<int, R>(this);
@@ -466,6 +473,11 @@
 
   List<double> _createList(int length);
 
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+  Iterable<double> followedBy(Iterable<double> other) =>
+      new FollowedByIterable<double>.firstEfficient(this, other);
+
   List<R> cast<R>() {
     List<Object> self = this;
     return self is List<R> ? self : List.castFrom<double, R>(this);
@@ -823,6 +835,11 @@
 
   List<Float32x4> _createList(int length);
 
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+  Iterable<Float32x4> followedBy(Iterable<Float32x4> other) =>
+      new FollowedByIterable<Float32x4>.firstEfficient(this, other);
+
   List<R> cast<R>() {
     List<Object> self = this;
     return self is List<R> ? self : List.castFrom<Float32x4, R>(this);
@@ -1184,6 +1201,11 @@
 
   List<Int32x4> _createList(int length);
 
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+  Iterable<Int32x4> followedBy(Iterable<Int32x4> other) =>
+      new FollowedByIterable<Int32x4>.firstEfficient(this, other);
+
   List<R> cast<R>() {
     List<Object> self = this;
     return self is List<R> ? self : List.castFrom<Int32x4, R>(this);
@@ -1544,6 +1566,11 @@
 
   List<Float64x2> _createList(int length);
 
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+  Iterable<Float64x2> followedBy(Iterable<Float64x2> other) =>
+      new FollowedByIterable<Float64x2>.firstEfficient(this, other);
+
   List<R> cast<R>() {
     List<Object> self = this;
     return self is List<R> ? self : List.castFrom<Float64x2, R>(this);
diff --git a/runtime/observatory/tests/service/external_service_asynchronous_invocation_test.dart b/runtime/observatory/tests/service/external_service_asynchronous_invocation_test.dart
index 3bb764c..a6860b9 100644
--- a/runtime/observatory/tests/service/external_service_asynchronous_invocation_test.dart
+++ b/runtime/observatory/tests/service/external_service_asynchronous_invocation_test.dart
@@ -8,7 +8,7 @@
 import 'test_helper.dart';
 import 'dart:io' show WebSocket;
 import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
 
 var tests = <IsolateTest>[
   (Isolate isolate) async {
@@ -23,8 +23,13 @@
     final socket = new StreamController();
 
     // Avoid to manually encode and decode messages from the stream
-    socket.stream.map(JSON.encode).pipe(_socket);
-    final client = _socket.map(JSON.decode).asBroadcastStream();
+    Stream<String> stream = socket.stream.map(JSON.encode);
+    stream.retype<Object>().pipe(_socket);
+    dynamic _decoder(dynamic obj) {
+      return JSON.decode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
 
     const successServiceName = 'successService';
     const errorServiceName = 'errorService';
@@ -145,7 +150,7 @@
           expect(false, isTrue, reason: 'shouldn\'t get here');
         }).catchError((e) => e);
       }));
-      errors.forEach((final ServerRpcException error) {
+      errors.forEach((dynamic error) {
         final iteration = errors.indexOf(error);
         final end = iteration.toString();
 
diff --git a/runtime/observatory/tests/service/external_service_disappear_test.dart b/runtime/observatory/tests/service/external_service_disappear_test.dart
index c30ea64..8199de2 100644
--- a/runtime/observatory/tests/service/external_service_disappear_test.dart
+++ b/runtime/observatory/tests/service/external_service_disappear_test.dart
@@ -8,7 +8,7 @@
 import 'test_helper.dart';
 import 'dart:io' show WebSocket;
 import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
 
 var tests = <IsolateTest>[
   (Isolate isolate) async {
@@ -23,8 +23,13 @@
     final socket = new StreamController();
 
     // Avoid to manually encode and decode messages from the stream
-    socket.stream.map(JSON.encode).pipe(_socket);
-    final client = _socket.map(JSON.decode).asBroadcastStream();
+    Stream<String> stream = socket.stream.map(JSON.encode);
+    stream.retype<Object>().pipe(_socket);
+    dynamic _decoder(dynamic obj) {
+      return JSON.decode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
 
     // Note: keep this in sync with sdk/lib/vmservice.dart
     const kServiceDisappeared = 111;
@@ -74,7 +79,8 @@
       await Future.wait(results.map((future) {
         return future.then((_) {
           expect(false, isTrue, reason: 'shouldn\'t get here');
-        }).catchError((ServerRpcException error) {
+        }).catchError((Object error_object) {
+          ServerRpcException error = error_object as ServerRpcException;
           expect(error, isNotNull);
           expect(error.code, equals(kServiceDisappeared));
           expect(error.message, equals(kServiceDisappeared_Msg));
diff --git a/runtime/observatory/tests/service/external_service_notification_invocation_test.dart b/runtime/observatory/tests/service/external_service_notification_invocation_test.dart
index 3eec32a..bba191a 100644
--- a/runtime/observatory/tests/service/external_service_notification_invocation_test.dart
+++ b/runtime/observatory/tests/service/external_service_notification_invocation_test.dart
@@ -8,7 +8,7 @@
 import 'test_helper.dart';
 import 'dart:io' show WebSocket;
 import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
 
 var tests = <IsolateTest>[
   (Isolate isolate) async {
@@ -26,10 +26,17 @@
     final socket_invoker = new StreamController<Map>();
 
     // Avoid to manually encode and decode messages from the stream
-    socket.stream.map(JSON.encode).pipe(_socket);
-    socket_invoker.stream.map(JSON.encode).pipe(_socket_invoker);
-    final client = _socket.map(JSON.decode).asBroadcastStream();
-    final client_invoker = _socket_invoker.map(JSON.decode).asBroadcastStream();
+    Stream<String> socket_stream = socket.stream.map(JSON.encode);
+    socket_stream.retype<Object>().pipe(_socket);
+    Stream<String> socket_invoker_stream =
+        socket_invoker.stream.map(JSON.encode);
+    socket_invoker_stream.retype<Object>().pipe(_socket_invoker);
+    dynamic _decoder(dynamic obj) {
+      return JSON.decode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
+    final client_invoker = _socket_invoker.map(_decoder).asBroadcastStream();
 
     const serviceName = 'successService';
     const serviceAlias = 'serviceAlias';
diff --git a/runtime/observatory/tests/service/external_service_registration_test.dart b/runtime/observatory/tests/service/external_service_registration_test.dart
index b66563b..c0dab2f 100644
--- a/runtime/observatory/tests/service/external_service_registration_test.dart
+++ b/runtime/observatory/tests/service/external_service_registration_test.dart
@@ -8,7 +8,7 @@
 import 'test_helper.dart';
 import 'dart:io' show WebSocket;
 import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
 
 var tests = <IsolateTest>[
   (Isolate isolate) async {
@@ -26,8 +26,13 @@
     final socket = new StreamController();
 
     // Avoid to manually encode and decode messages from the stream
-    socket.stream.map(JSON.encode).pipe(_socket);
-    final client = _socket.map(JSON.decode).asBroadcastStream();
+    Stream<String> socket_stream = socket.stream.map(JSON.encode);
+    socket_stream.retype<Object>().pipe(_socket);
+    dynamic _decoder(dynamic obj) {
+      return JSON.decode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
 
     // Note: keep this in sync with sdk/lib/vmservice.dart
     const kServiceAlreadyRegistered = 110;
diff --git a/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart b/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart
index 37027f8..74e258c 100644
--- a/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart
+++ b/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart
@@ -8,7 +8,7 @@
 import 'test_helper.dart';
 import 'dart:io' show WebSocket;
 import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
 
 var tests = <IsolateTest>[
   (Isolate isolate) async {
@@ -26,8 +26,13 @@
     final socket = new StreamController();
 
     // Avoid to manually encode and decode messages from the stream
-    socket.stream.map(JSON.encode).pipe(_socket);
-    final client = _socket.map(JSON.decode).asBroadcastStream();
+    Stream<String> stream = socket.stream.map(JSON.encode);
+    stream.retype<Object>().pipe(_socket);
+    dynamic _decoder(dynamic obj) {
+      return JSON.decode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
 
     // Note: keep this in sync with sdk/lib/vmservice.dart
     const kServiceAlreadyRegistered = 110;
diff --git a/runtime/observatory/tests/service/external_service_synchronous_invocation_test.dart b/runtime/observatory/tests/service/external_service_synchronous_invocation_test.dart
index 372ce1a..78091e1 100644
--- a/runtime/observatory/tests/service/external_service_synchronous_invocation_test.dart
+++ b/runtime/observatory/tests/service/external_service_synchronous_invocation_test.dart
@@ -8,7 +8,7 @@
 import 'test_helper.dart';
 import 'dart:io' show WebSocket;
 import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
 
 var tests = <IsolateTest>[
   (Isolate isolate) async {
@@ -23,8 +23,13 @@
     final socket = new StreamController();
 
     // Avoid to manually encode and decode messages from the stream
-    socket.stream.map(JSON.encode).pipe(_socket);
-    final client = _socket.map(JSON.decode).asBroadcastStream();
+    Stream<String> stream = socket.stream.map(JSON.encode);
+    stream.retype<Object>().pipe(_socket);
+    dynamic _decoder(dynamic obj) {
+      return JSON.decode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
 
     const successServiceName = 'successService';
     const errorServiceName = 'errorService';
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index a3d1244..baff3ed 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -44,9 +44,6 @@
 isolate_lifecycle_test: Skip # Flaky.
 pause_idle_isolate_test: Skip # Flaky
 
-[ $compiler == dartk && $mode == debug && $strong ]
-external_service_disappear_test: Crash # Issue 31587
-
 [ $compiler == dartk && $system == windows ]
 break_on_default_constructor_test: Skip # Issues 32137 and 32138.
 coverage_leaf_function_test: RuntimeError
@@ -108,12 +105,6 @@
 
 [ $compiler == dartk && $strong ]
 awaiter_async_stack_contents_test: RuntimeError
-external_service_asynchronous_invocation_test: CompileTimeError # Issue 31696
-external_service_disappear_test: CompileTimeError # Issue 31696
-external_service_notification_invocation_test: CompileTimeError # Issue 31696
-external_service_registration_test: CompileTimeError # Issue 31696
-external_service_registration_via_notification_test: CompileTimeError # Issue 31696
-external_service_synchronous_invocation_test: CompileTimeError # Issue 31696
 step_through_arithmetic_test: RuntimeError
 
 [ $compiler == dartk && $strong && ($arch == simarm || $arch == simarm64) ]
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index b87e9e3..09c0a81 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -146,6 +146,10 @@
 #define NOT_IN_PRECOMPILED(code) code
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
+#if defined(DART_PRECOMPILED_RUNTIME) || defined(PRODUCT)
+#define EXCLUDE_CFE_AND_KERNEL_PLATFORM 1
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+
 namespace dart {
 
 struct simd128_value_t {
diff --git a/runtime/platform/platform_sources.gni b/runtime/platform/platform_sources.gni
index e007ac3..f61930c 100644
--- a/runtime/platform/platform_sources.gni
+++ b/runtime/platform/platform_sources.gni
@@ -25,4 +25,9 @@
   "text_buffer.h",
   "utils.cc",
   "utils.h",
+  "utils_android.cc",
+  "utils_fuchsia.cc",
+  "utils_linux.cc",
+  "utils_macos.cc",
+  "utils_win.cc",
 ]
diff --git a/runtime/platform/text_buffer.cc b/runtime/platform/text_buffer.cc
index b4700ac..5717604 100644
--- a/runtime/platform/text_buffer.cc
+++ b/runtime/platform/text_buffer.cc
@@ -7,7 +7,6 @@
 #include "platform/assert.h"
 #include "platform/globals.h"
 #include "platform/utils.h"
-#include "vm/os.h"
 #include "vm/unicode.h"
 
 namespace dart {
@@ -59,7 +58,7 @@
   va_start(args, format);
   intptr_t remaining = buf_size_ - msg_len_;
   ASSERT(remaining >= 0);
-  intptr_t len = OS::VSNPrint(buf_ + msg_len_, remaining, format, args);
+  intptr_t len = Utils::VSNPrint(buf_ + msg_len_, remaining, format, args);
   va_end(args);
   if (len >= remaining) {
     EnsureCapacity(len);
@@ -67,7 +66,7 @@
     ASSERT(remaining > len);
     va_list args2;
     va_start(args2, format);
-    intptr_t len2 = OS::VSNPrint(buf_ + msg_len_, remaining, format, args2);
+    intptr_t len2 = Utils::VSNPrint(buf_ + msg_len_, remaining, format, args2);
     va_end(args2);
     ASSERT(len == len2);
   }
@@ -163,7 +162,8 @@
 void BufferFormatter::VPrint(const char* format, va_list args) {
   intptr_t available = size_ - position_;
   if (available <= 0) return;
-  intptr_t written = OS::VSNPrint(buffer_ + position_, available, format, args);
+  intptr_t written =
+      Utils::VSNPrint(buffer_ + position_, available, format, args);
   if (written >= 0) {
     position_ += (available <= written) ? available : written;
   }
diff --git a/runtime/platform/text_buffer.h b/runtime/platform/text_buffer.h
index 37376e8..23deeed 100644
--- a/runtime/platform/text_buffer.h
+++ b/runtime/platform/text_buffer.h
@@ -5,8 +5,8 @@
 #ifndef RUNTIME_PLATFORM_TEXT_BUFFER_H_
 #define RUNTIME_PLATFORM_TEXT_BUFFER_H_
 
-#include "vm/allocation.h"
-#include "vm/globals.h"
+#include "platform/allocation.h"
+#include "platform/globals.h"
 
 namespace dart {
 
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 69a615c..3b05c02 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -105,28 +105,29 @@
   static uintptr_t RoundUpToPowerOfTwo(uintptr_t x);
 
   static int CountOneBits32(uint32_t x) {
-#ifdef _MSC_VER
-    return __popcnt(x);
-#elif __GNUC__
+    // Apparently there are x64 chips without popcount.
+#if __GNUC__ && !defined(HOST_ARCH_IA32) && !defined(HOST_ARCH_X64)
     return __builtin_popcount(x);
 #else
-#error CountOneBits32 not implemented for this compiler
+    // Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
+    // figure 5-2, page 66, where the function is called pop.
+    x = x - ((x >> 1) & 0x55555555);
+    x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+    x = (x + (x >> 4)) & 0x0F0F0F0F;
+    x = x + (x >> 8);
+    x = x + (x >> 16);
+    return static_cast<int>(x & 0x0000003F);
 #endif
   }
 
   static int CountOneBits64(uint64_t x) {
-#ifdef _MSC_VER
-#ifdef ARCH_IS_64_BIT
-    return __popcnt64(x);
+    // Apparently there are x64 chips without popcount.
+#if __GNUC__ && !defined(HOST_ARCH_IA32) && !defined(HOST_ARCH_X64)
+    return __builtin_popcountll(x);
 #else
     return CountOneBits32(static_cast<uint32_t>(x)) +
            CountOneBits32(static_cast<uint32_t>(x >> 32));
 #endif
-#elif __GNUC__
-    return __builtin_popcountll(x);
-#else
-#error CountOneBits64 not implemented for this compiler
-#endif
   }
 
   static int CountOneBitsWord(uword x) {
@@ -320,6 +321,30 @@
   }
 
   static char* StrError(int err, char* buffer, size_t bufsize);
+
+  // Not all platforms support strndup.
+  static char* StrNDup(const char* s, intptr_t n);
+  static intptr_t StrNLen(const char* s, intptr_t n);
+
+  // Print formatted output info a buffer.
+  //
+  // Does not write more than size characters (including the trailing '\0').
+  //
+  // Returns the number of characters (excluding the trailing '\0')
+  // that would been written if the buffer had been big enough.  If
+  // the return value is greater or equal than the given size then the
+  // output has been truncated.  The return value is never negative.
+  //
+  // The buffer will always be terminated by a '\0', unless the buffer
+  // is of size 0.  The buffer might be NULL if the size is 0.
+  //
+  // This specification conforms to C99 standard which is implemented
+  // by glibc 2.1+ with one exception: the C99 standard allows a
+  // negative return value.  We will terminate the vm rather than let
+  // that occur.
+  static int SNPrint(char* str, size_t size, const char* format, ...)
+      PRINTF_ATTRIBUTE(3, 4);
+  static int VSNPrint(char* str, size_t size, const char* format, va_list args);
 };
 
 }  // namespace dart
diff --git a/runtime/platform/utils_android.cc b/runtime/platform/utils_android.cc
new file mode 100644
index 0000000..21c2e02
--- /dev/null
+++ b/runtime/platform/utils_android.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_ANDROID)
+
+#include "platform/utils.h"
+
+namespace dart {
+
+char* Utils::StrNDup(const char* s, intptr_t n) {
+  return strndup(s, n);
+}
+
+intptr_t Utils::StrNLen(const char* s, intptr_t n) {
+  return strnlen(s, n);
+}
+
+int Utils::SNPrint(char* str, size_t size, const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  int retval = VSNPrint(str, size, format, args);
+  va_end(args);
+  return retval;
+}
+
+int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
+  int retval = vsnprintf(str, size, format, args);
+  if (retval < 0) {
+    FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+  }
+  return retval;
+}
+
+}  // namespace dart
+
+#endif  // defined(HOST_OS_ANDROID)
diff --git a/runtime/platform/utils_fuchsia.cc b/runtime/platform/utils_fuchsia.cc
new file mode 100644
index 0000000..04e813a
--- /dev/null
+++ b/runtime/platform/utils_fuchsia.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_FUCHSIA)
+
+#include "platform/utils.h"
+
+namespace dart {
+
+char* Utils::StrNDup(const char* s, intptr_t n) {
+  return strndup(s, n);
+}
+
+intptr_t Utils::StrNLen(const char* s, intptr_t n) {
+  return strnlen(s, n);
+}
+
+int Utils::SNPrint(char* str, size_t size, const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  int retval = VSNPrint(str, size, format, args);
+  va_end(args);
+  return retval;
+}
+
+int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
+  int retval = vsnprintf(str, size, format, args);
+  if (retval < 0) {
+    FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+  }
+  return retval;
+}
+
+}  // namespace dart
+
+#endif  // defined(HOST_OS_FUCHSIA)
diff --git a/runtime/platform/utils_linux.cc b/runtime/platform/utils_linux.cc
new file mode 100644
index 0000000..4c3d617
--- /dev/null
+++ b/runtime/platform/utils_linux.cc
@@ -0,0 +1,39 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_LINUX)
+
+#include "platform/utils.h"
+
+namespace dart {
+
+char* Utils::StrNDup(const char* s, intptr_t n) {
+  return strndup(s, n);
+}
+
+intptr_t Utils::StrNLen(const char* s, intptr_t n) {
+  return strnlen(s, n);
+}
+
+int Utils::SNPrint(char* str, size_t size, const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  int retval = VSNPrint(str, size, format, args);
+  va_end(args);
+  return retval;
+}
+
+int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
+  MSAN_UNPOISON(str, size);
+  int retval = vsnprintf(str, size, format, args);
+  if (retval < 0) {
+    FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+  }
+  return retval;
+}
+
+}  // namespace dart
+
+#endif  // defined(HOST_OS_LINUX)
diff --git a/runtime/platform/utils_macos.cc b/runtime/platform/utils_macos.cc
new file mode 100644
index 0000000..eaab319
--- /dev/null
+++ b/runtime/platform/utils_macos.cc
@@ -0,0 +1,69 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_MACOS)
+
+#include "platform/utils.h"
+
+namespace dart {
+
+char* Utils::StrNDup(const char* s, intptr_t n) {
+// strndup has only been added to Mac OS X in 10.7. We are supplying
+// our own copy here if needed.
+#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) ||                 \
+    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
+  intptr_t len = strlen(s);
+  if ((n < 0) || (len < 0)) {
+    return NULL;
+  }
+  if (n < len) {
+    len = n;
+  }
+  char* result = reinterpret_cast<char*>(malloc(len + 1));
+  if (result == NULL) {
+    return NULL;
+  }
+  result[len] = '\0';
+  return reinterpret_cast<char*>(memmove(result, s, len));
+#else   // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
+  return strndup(s, n);
+#endif  // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
+}
+
+intptr_t Utils::StrNLen(const char* s, intptr_t n) {
+// strnlen has only been added to Mac OS X in 10.7. We are supplying
+// our own copy here if needed.
+#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) ||                 \
+    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
+  intptr_t len = 0;
+  while ((len <= n) && (*s != '\0')) {
+    s++;
+    len++;
+  }
+  return len;
+#else   // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
+  return strnlen(s, n);
+#endif  // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
+}
+
+int Utils::SNPrint(char* str, size_t size, const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  int retval = VSNPrint(str, size, format, args);
+  va_end(args);
+  return retval;
+}
+
+int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
+  int retval = vsnprintf(str, size, format, args);
+  if (retval < 0) {
+    FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+  }
+  return retval;
+}
+
+}  // namespace dart
+
+#endif  // defined(HOST_OS_MACOS)
diff --git a/runtime/platform/utils_win.cc b/runtime/platform/utils_win.cc
new file mode 100644
index 0000000..84f277c
--- /dev/null
+++ b/runtime/platform/utils_win.cc
@@ -0,0 +1,76 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_WINDOWS)
+
+#include "platform/utils.h"
+
+namespace dart {
+
+char* Utils::StrNDup(const char* s, intptr_t n) {
+  intptr_t len = strlen(s);
+  if ((n < 0) || (len < 0)) {
+    return NULL;
+  }
+  if (n < len) {
+    len = n;
+  }
+  char* result = reinterpret_cast<char*>(malloc(len + 1));
+  if (result == NULL) {
+    return NULL;
+  }
+  result[len] = '\0';
+  return reinterpret_cast<char*>(memmove(result, s, len));
+}
+
+intptr_t Utils::StrNLen(const char* s, intptr_t n) {
+  return strnlen(s, n);
+}
+
+int Utils::SNPrint(char* str, size_t size, const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  int retval = VSNPrint(str, size, format, args);
+  va_end(args);
+  return retval;
+}
+
+int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
+  if (str == NULL || size == 0) {
+    int retval = _vscprintf(format, args);
+    if (retval < 0) {
+      FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+    }
+    return retval;
+  }
+  va_list args_copy;
+  va_copy(args_copy, args);
+  int written = _vsnprintf(str, size, format, args_copy);
+  va_end(args_copy);
+  if (written < 0) {
+    // _vsnprintf returns -1 if the number of characters to be written is
+    // larger than 'size', so we call _vscprintf which returns the number
+    // of characters that would have been written.
+    va_list args_retry;
+    va_copy(args_retry, args);
+    written = _vscprintf(format, args_retry);
+    if (written < 0) {
+      FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+    }
+    va_end(args_retry);
+  }
+  // Make sure to zero-terminate the string if the output was
+  // truncated or if there was an error.
+  // The static cast is safe here as we have already determined that 'written'
+  // is >= 0.
+  if (static_cast<size_t>(written) >= size) {
+    str[size - 1] = '\0';
+  }
+  return written;
+}
+
+}  // namespace dart
+
+#endif  // defined(HOST_OS_WINDOWS)
diff --git a/runtime/tests/vm/dart/hello_world_test.dart b/runtime/tests/vm/dart/hello_world_test.dart
new file mode 100644
index 0000000..8c9c377
--- /dev/null
+++ b/runtime/tests/vm/dart/hello_world_test.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Classic "Hello, world!". Used in the VM build (runtime/bin/BUILD.gn) as
+// a tiny script for precompilation.
+
+main() {
+  print("Hello, world!");
+}
diff --git a/runtime/tests/vm/dart/optimized_stacktrace_line_and_column_test.dart b/runtime/tests/vm/dart/optimized_stacktrace_line_and_column_test.dart
index 4bcb31e..83dd0f7 100644
--- a/runtime/tests/vm/dart/optimized_stacktrace_line_and_column_test.dart
+++ b/runtime/tests/vm/dart/optimized_stacktrace_line_and_column_test.dart
@@ -21,9 +21,9 @@
     String s = stacktrace.toString();
     print(s);
     Expect.isFalse(s.contains("-1:-1"), "A");
-    Expect.isTrue(
-        s.contains("optimized_stacktrace_line_and_column_test.dart:11:18"),
-        "B");
+    RegExp regex = new RegExp(
+        "optimized_stacktrace_line_and_column_test(_none|_01)*\.dart:11(:18)*");
+    Expect.isTrue(regex.hasMatch(s), s);
   }
 
   // Optimized.
@@ -35,9 +35,9 @@
     String s = stacktrace.toString();
     print(s);
     Expect.isFalse(s.contains("-1:-1"), "C");
-    Expect.isTrue(
-        s.contains("optimized_stacktrace_line_and_column_test.dart:11:18"),
-        "D");
+    RegExp regex = new RegExp(
+        "optimized_stacktrace_line_and_column_test(_none|_01)*\.dart:11(:18)*");
+    Expect.isTrue(regex.hasMatch(s), "D");
   }
 }
 
@@ -45,9 +45,9 @@
 maximus(x) => moritz(x);
 
 moritz(x) {
-  if (x == 333) return 42 ? 0 : 1; // Throws in checked mode.
+  if (x == 333) return true ? 0 : 1;
   if (x == 777) {
-    bool b = x; // Throws in checked mode.
+    bool b = x;
     return b;
   }
 
diff --git a/runtime/tests/vm/dart/optimized_stacktrace_line_test.dart b/runtime/tests/vm/dart/optimized_stacktrace_line_test.dart
index abdbefa..43e5fde 100644
--- a/runtime/tests/vm/dart/optimized_stacktrace_line_test.dart
+++ b/runtime/tests/vm/dart/optimized_stacktrace_line_test.dart
@@ -21,7 +21,9 @@
     String s = stacktrace.toString();
     print(s);
     Expect.isFalse(s.contains("-1:-1"), "A");
-    Expect.isTrue(s.contains("optimized_stacktrace_line_test.dart:11"), "B");
+    RegExp regex =
+        new RegExp("optimized_stacktrace_line_test(_none|_01)*\.dart:11");
+    Expect.isTrue(regex.hasMatch(s), "B");
   }
 
   // Optimized.
@@ -33,7 +35,9 @@
     String s = stacktrace.toString();
     print(s);
     Expect.isFalse(s.contains("-1:-1"), "C");
-    Expect.isTrue(s.contains("optimized_stacktrace_line_test.dart:11"), "D");
+    RegExp regex =
+        new RegExp("optimized_stacktrace_line_test(_none|_01)*\.dart:11");
+    Expect.isTrue(regex.hasMatch(s), "D");
   }
 }
 
@@ -41,9 +45,9 @@
 maximus(x) => moritz(x);
 
 moritz(x) {
-  if (x == 333) return 42 ? 0 : 1; // Throws in checked mode.
+  if (x == 333) return (42 as bool) ? 0 : 1;
   if (x == 777) {
-    bool b = x; // Throws in checked mode.
+    bool b = x;
     return b;
   }
 
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 6d78dea..8553eca 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -39,14 +39,11 @@
 cc/IsolateReload_TypeIdentityParameter: Fail # Issue 28349
 
 [ $compiler == app_jit ]
-dart/optimized_stacktrace_line_and_column_test: RuntimeError, OK # app-jit lacks column information
 dart/snapshot_version_test: Fail, OK # Expects to find script snapshot relative to Dart source.
 
 [ $compiler == dart2analyzer ]
 dart/byte_array_optimized_test: CompileTimeError # int64
 dart/byte_array_test: CompileTimeError # int64
-dart/optimized_stacktrace_line_and_column_test: StaticWarning
-dart/optimized_stacktrace_line_test: StaticWarning
 dart/truncating_ints_test: CompileTimeError # int64
 
 [ $compiler == dart2js ]
@@ -296,8 +293,6 @@
 cc/IsolateReload_LibraryLookup: Crash # Issue 32190
 cc/Mixin_PrivateSuperResolutionCrossLibraryShouldFail: Fail, Crash # Issue 32190
 cc/StackMapGC: Crash # Issue 32190
-dart/optimized_stacktrace_line_and_column_test: CompileTimeError # Issue 31586
-dart/optimized_stacktrace_line_test: CompileTimeError # Issue 31586
 
 # Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
@@ -306,12 +301,7 @@
 dart/data_uri_spawn_test: Skip # Please triage.
 dart/snapshot_version_test: RuntimeError # Please triage.
 
-[ $compiler == dartkp && $strong ]
-dart/optimized_stacktrace_line_and_column_test: CompileTimeError
-dart/optimized_stacktrace_line_test: CompileTimeError
-
 [ $compiler == dartkp && !$strong ]
-dart/optimized_stacktrace_line_and_column_test: RuntimeError, OK # AOT lacks column information
 dart/truncating_ints_test: Skip # This test cannot be run in dartkp/legacy mode (gen_kernel does not pass --limit-ints-to-64-bits in legacy mode).
 
 [ $compiler == dartkp && ($runtime == dart_precompiled || $runtime == vm) ]
@@ -322,9 +312,6 @@
 [ $compiler == none && $runtime == drt ]
 dart/truncating_ints_test: Skip # Issue 14651
 
-[ $compiler == precompiler && $runtime == dart_precompiled ]
-dart/optimized_stacktrace_line_and_column_test: RuntimeError, OK # AOT lacks column information
-
 [ $mode == debug && $system == windows ]
 dart/spawn_shutdown_test: Skip # Flaky crashes unable to start thread; likely low memory on the bot.
 
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index 2d3c01b..e7e74bc 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -92,8 +92,8 @@
   Zone* zone = thread->zone();
   initializers_.Add(node);
   char name[64];
-  OS::SNPrint(name, sizeof(name), ":lt%s_%" Pd "", token_pos().ToCString(),
-              vars_.length());
+  Utils::SNPrint(name, sizeof(name), ":lt%s_%" Pd "", token_pos().ToCString(),
+                 vars_.length());
   LocalVariable* temp_var =
       new LocalVariable(TokenPosition::kNoSource, token_pos(),
                         String::ZoneHandle(zone, Symbols::New(thread, name)),
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 84b433b..4fc6436 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -40,8 +40,9 @@
   char* ptr = strrchr(dart2js_path, *path_separator);
   while (ptr != NULL) {
     *ptr = '\0';
-    OS::SNPrint(buffer, 2048, compiler_path, dart2js_path, path_separator,
-                path_separator, path_separator, path_separator, path_separator);
+    Utils::SNPrint(buffer, 2048, compiler_path, dart2js_path, path_separator,
+                   path_separator, path_separator, path_separator,
+                   path_separator);
     if (File::Exists(NULL, buffer)) {
       break;
     }
@@ -77,8 +78,8 @@
       strdup(File::GetCanonicalPath(NULL, Benchmark::Executable()));
   const char* packages_path = "%s%s..%spackages";
   const char* path_separator = File::PathSeparator();
-  OS::SNPrint(buffer, 2048, packages_path, executable_path, path_separator,
-              path_separator);
+  Utils::SNPrint(buffer, 2048, packages_path, executable_path, path_separator,
+                 path_separator);
   result = bin::DartUtils::SetupPackageRoot(buffer, NULL);
   DART_CHECK_VALID(result);
 }
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index fecad3a..ef85c3f 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -5278,9 +5278,9 @@
   if (PendingBytes() < version_len) {
     const intptr_t kMessageBufferSize = 128;
     char message_buffer[kMessageBufferSize];
-    OS::SNPrint(message_buffer, kMessageBufferSize,
-                "No full snapshot version found, expected '%s'",
-                expected_version);
+    Utils::SNPrint(message_buffer, kMessageBufferSize,
+                   "No full snapshot version found, expected '%s'",
+                   expected_version);
     // This can also fail while bringing up the VM isolate, so make sure to
     // allocate the error message in old space.
     const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
@@ -5292,11 +5292,11 @@
   if (strncmp(version, expected_version, version_len)) {
     const intptr_t kMessageBufferSize = 256;
     char message_buffer[kMessageBufferSize];
-    char* actual_version = OS::StrNDup(version, version_len);
-    OS::SNPrint(message_buffer, kMessageBufferSize,
-                "Wrong %s snapshot version, expected '%s' found '%s'",
-                (Snapshot::IsFull(kind_)) ? "full" : "script", expected_version,
-                actual_version);
+    char* actual_version = Utils::StrNDup(version, version_len);
+    Utils::SNPrint(message_buffer, kMessageBufferSize,
+                   "Wrong %s snapshot version, expected '%s' found '%s'",
+                   (Snapshot::IsFull(kind_)) ? "full" : "script",
+                   expected_version, actual_version);
     free(actual_version);
     // This can also fail while bringing up the VM isolate, so make sure to
     // allocate the error message in old space.
@@ -5312,17 +5312,17 @@
 
   const char* features = reinterpret_cast<const char*>(CurrentBufferAddress());
   ASSERT(features != NULL);
-  intptr_t buffer_len = OS::StrNLen(features, PendingBytes());
+  intptr_t buffer_len = Utils::StrNLen(features, PendingBytes());
   if ((buffer_len != expected_len) ||
       strncmp(features, expected_features, expected_len)) {
     const intptr_t kMessageBufferSize = 1024;
     char message_buffer[kMessageBufferSize];
     char* actual_features =
-        OS::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
-    OS::SNPrint(message_buffer, kMessageBufferSize,
-                "Snapshot not compatible with the current VM configuration: "
-                "the snapshot requires '%s' but the VM has '%s'",
-                actual_features, expected_features);
+        Utils::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
+    Utils::SNPrint(message_buffer, kMessageBufferSize,
+                   "Snapshot not compatible with the current VM configuration: "
+                   "the snapshot requires '%s' but the VM has '%s'",
+                   actual_features, expected_features);
     free(const_cast<char*>(expected_features));
     free(actual_features);
     // This can also fail while bringing up the VM isolate, so make sure to
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index bf90c32..6e912c6 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -1046,13 +1046,7 @@
       } else if (entry.IsInstance()) {
         // Const object, literal or args descriptor.
         instance ^= entry.raw();
-        if (entry.IsAbstractType()) {
-          AddType(AbstractType::Cast(entry));
-        } else if (entry.IsTypeArguments()) {
-          AddTypeArguments(TypeArguments::Cast(entry));
-        } else {
-          AddConstObject(instance);
-        }
+        AddConstObject(instance);
       } else if (entry.IsFunction()) {
         // Local closure function.
         target ^= entry.raw();
@@ -1199,6 +1193,15 @@
 }
 
 void Precompiler::AddConstObject(const Instance& instance) {
+  // Types and type arguments require special handling.
+  if (instance.IsAbstractType()) {
+    AddType(AbstractType::Cast(instance));
+    return;
+  } else if (instance.IsTypeArguments()) {
+    AddTypeArguments(TypeArguments::Cast(instance));
+    return;
+  }
+
   const Class& cls = Class::Handle(Z, instance.clazz());
   AddInstantiatedClass(cls);
 
@@ -1241,9 +1244,7 @@
     virtual void VisitPointers(RawObject** first, RawObject** last) {
       for (RawObject** current = first; current <= last; current++) {
         subinstance_ = *current;
-        if (subinstance_.IsTypeArguments()) {
-          precompiler_->AddTypeArguments(TypeArguments::Cast(subinstance_));
-        } else if (subinstance_.IsInstance()) {
+        if (subinstance_.IsInstance()) {
           precompiler_->AddConstObject(Instance::Cast(subinstance_));
         }
       }
diff --git a/runtime/vm/compiler/assembler/assembler.cc b/runtime/vm/compiler/assembler/assembler.cc
index c19a0d2..c2dc4e7 100644
--- a/runtime/vm/compiler/assembler/assembler.cc
+++ b/runtime/vm/compiler/assembler/assembler.cc
@@ -175,25 +175,25 @@
 // Shared macros are implemented here.
 void Assembler::Unimplemented(const char* message) {
   const char* format = "Unimplemented: %s";
-  const intptr_t len = OS::SNPrint(NULL, 0, format, message);
+  const intptr_t len = Utils::SNPrint(NULL, 0, format, message);
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
-  OS::SNPrint(buffer, len + 1, format, message);
+  Utils::SNPrint(buffer, len + 1, format, message);
   Stop(buffer);
 }
 
 void Assembler::Untested(const char* message) {
   const char* format = "Untested: %s";
-  const intptr_t len = OS::SNPrint(NULL, 0, format, message);
+  const intptr_t len = Utils::SNPrint(NULL, 0, format, message);
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
-  OS::SNPrint(buffer, len + 1, format, message);
+  Utils::SNPrint(buffer, len + 1, format, message);
   Stop(buffer);
 }
 
 void Assembler::Unreachable(const char* message) {
   const char* format = "Unreachable: %s";
-  const intptr_t len = OS::SNPrint(NULL, 0, format, message);
+  const intptr_t len = Utils::SNPrint(NULL, 0, format, message);
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
-  OS::SNPrint(buffer, len + 1, format, message);
+  Utils::SNPrint(buffer, len + 1, format, message);
   Stop(buffer);
 }
 
@@ -203,7 +203,7 @@
 
     va_list args;
     va_start(args, format);
-    OS::VSNPrint(buffer, sizeof(buffer), format, args);
+    Utils::VSNPrint(buffer, sizeof(buffer), format, args);
     va_end(args);
 
     comments_.Add(
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index fb53b11..c1b4c4d 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -76,11 +76,11 @@
 void DisassembleToJSONStream::Print(const char* format, ...) {
   va_list args;
   va_start(args, format);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
   va_end(args);
   char* p = reinterpret_cast<char*>(malloc(len + 1));
   va_start(args, format);
-  intptr_t len2 = OS::VSNPrint(p, len, format, args);
+  intptr_t len2 = Utils::VSNPrint(p, len, format, args);
   va_end(args);
   ASSERT(len == len2);
   for (intptr_t i = 0; i < len; i++) {
@@ -132,7 +132,7 @@
   }
   va_list args;
   va_start(args, format);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
   va_end(args);
   if (remaining_ < len + 100) {
     *buffer_++ = '.';
@@ -144,7 +144,7 @@
     return;
   }
   va_start(args, format);
-  intptr_t len2 = OS::VSNPrint(buffer_, len, format, args);
+  intptr_t len2 = Utils::VSNPrint(buffer_, len, format, args);
   va_end(args);
   ASSERT(len == len2);
   buffer_ += len;
diff --git a/runtime/vm/compiler/assembler/disassembler_arm.cc b/runtime/vm/compiler/assembler/disassembler_arm.cc
index 9c80fe9..5c718de 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm.cc
@@ -127,22 +127,22 @@
 void ARMDecoder::PrintSRegister(int reg) {
   ASSERT(0 <= reg);
   ASSERT(reg < kNumberOfSRegisters);
-  buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                             remaining_size_in_buffer(), "s%d", reg);
+  buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                remaining_size_in_buffer(), "s%d", reg);
 }
 
 void ARMDecoder::PrintDRegister(int reg) {
   ASSERT(0 <= reg);
   ASSERT(reg < kNumberOfDRegisters);
-  buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                             remaining_size_in_buffer(), "d%d", reg);
+  buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                remaining_size_in_buffer(), "d%d", reg);
 }
 
 void ARMDecoder::PrintQRegister(int reg) {
   ASSERT(0 <= reg);
   ASSERT(reg < kNumberOfQRegisters);
-  buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                             remaining_size_in_buffer(), "q%d", reg);
+  buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                remaining_size_in_buffer(), "q%d", reg);
 }
 
 // These shift names are defined in a way to match the native disassembler
@@ -171,14 +171,14 @@
       shift_amount = 32;
     }
     buffer_pos_ +=
-        OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
-                    ", %s #%d", shift_names[shift], shift_amount);
+        Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
+                       ", %s #%d", shift_names[shift], shift_amount);
   } else {
     // by register
     int rs = instr->RsField();
     buffer_pos_ +=
-        OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
-                    ", %s ", shift_names[shift]);
+        Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
+                       ", %s ", shift_names[shift]);
     PrintRegister(rs);
   }
 }
@@ -189,8 +189,8 @@
   int rotate = instr->RotateField() * 2;
   int immed8 = instr->Immed8Field();
   int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
-  buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                             remaining_size_in_buffer(), "#%d", imm);
+  buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                remaining_size_in_buffer(), "#%d", imm);
 }
 
 // Print PU formatting to reduce complexity of FormatOption.
@@ -406,8 +406,8 @@
         int off = (instr->SImmed24Field() << 2) + 8;
         uword destination = reinterpret_cast<uword>(instr) + off;
         buffer_pos_ +=
-            OS::SNPrint(current_position_in_buffer(),
-                        remaining_size_in_buffer(), "%#" Px "", destination);
+            Utils::SNPrint(current_position_in_buffer(),
+                           remaining_size_in_buffer(), "%#" Px "", destination);
         return 4;
       } else {
         return FormatDRegister(instr, format);
@@ -420,15 +420,15 @@
       uint16_t immed16;
       if (format[3] == 'f') {
         ASSERT(STRING_STARTS_WITH(format, "immf"));
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "%f",
-                                   instr->ImmFloatField());
+        buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                      remaining_size_in_buffer(), "%f",
+                                      instr->ImmFloatField());
         return 4;
       } else if (format[3] == 'd') {
         ASSERT(STRING_STARTS_WITH(format, "immd"));
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "%g",
-                                   instr->ImmDoubleField());
+        buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                      remaining_size_in_buffer(), "%g",
+                                      instr->ImmDoubleField());
         return 4;
       } else if (format[3] == '1') {
         ASSERT(STRING_STARTS_WITH(format, "imm12_4"));
@@ -445,16 +445,17 @@
             idx = imm4 >> 2;
           else if ((imm4 & 4) != 0)
             idx = imm4 >> 3;
-          buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                     remaining_size_in_buffer(), "%d", idx);
+          buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                        remaining_size_in_buffer(), "%d", idx);
           return 9;
         } else {
           ASSERT(STRING_STARTS_WITH(format, "imm4_12"));
           immed16 = instr->MovwField();
         }
       }
-      buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                 remaining_size_in_buffer(), "0x%x", immed16);
+      buffer_pos_ +=
+          Utils::SNPrint(current_position_in_buffer(),
+                         remaining_size_in_buffer(), "0x%x", immed16);
       return 7;
     }
     case 'l': {  // 'l: branch and link
@@ -478,23 +479,23 @@
       if (format[3] == '1') {
         if (format[4] == '0') {
           // 'off10: 10-bit offset for VFP load and store instructions
-          buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                     remaining_size_in_buffer(), "%d",
-                                     instr->Bits(0, 8) << 2);
+          buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                        remaining_size_in_buffer(), "%d",
+                                        instr->Bits(0, 8) << 2);
         } else {
           // 'off12: 12-bit offset for load and store instructions.
           ASSERT(STRING_STARTS_WITH(format, "off12"));
-          buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                     remaining_size_in_buffer(), "%d",
-                                     instr->Offset12Field());
+          buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                        remaining_size_in_buffer(), "%d",
+                                        instr->Offset12Field());
         }
         return 5;
       }
       // 'off8: 8-bit offset for extra load and store instructions.
       ASSERT(STRING_STARTS_WITH(format, "off8"));
       int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
-      buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                 remaining_size_in_buffer(), "%d", offs8);
+      buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                    remaining_size_in_buffer(), "%d", offs8);
       return 4;
     }
     case 'p': {  // 'pu: P and U bits for load and store instructions.
@@ -523,9 +524,9 @@
         }
       } else if (format[1] == 'v') {  // 'svc
         ASSERT(STRING_STARTS_WITH(format, "svc"));
-        buffer_pos_ +=
-            OS::SNPrint(current_position_in_buffer(),
-                        remaining_size_in_buffer(), "0x%x", instr->SvcField());
+        buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                      remaining_size_in_buffer(), "0x%x",
+                                      instr->SvcField());
         return 3;
       } else if (format[1] == 'z') {
         // 'sz: Size field of SIMD instructions.
@@ -548,8 +549,8 @@
             sz_str = "?";
             break;
         }
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "%s", sz_str);
+        buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                      remaining_size_in_buffer(), "%s", sz_str);
         return 2;
       } else if (format[1] == ' ') {
         // 's: S field of data processing instructions.
@@ -564,8 +565,8 @@
     case 't': {  // 'target: target of branch instructions.
       ASSERT(STRING_STARTS_WITH(format, "target"));
       int off = (instr->SImmed24Field() << 2) + 8;
-      buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                 remaining_size_in_buffer(), "%+d", off);
+      buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                    remaining_size_in_buffer(), "%+d", off);
       return 6;
     }
     case 'u': {  // 'u: signed or unsigned multiplies.
@@ -657,9 +658,9 @@
             if (instr->BkptField() == Instr::kStopMessageCode) {
               const char* message = *reinterpret_cast<const char**>(
                   reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
-              buffer_pos_ +=
-                  OS::SNPrint(current_position_in_buffer(),
-                              remaining_size_in_buffer(), " ; \"%s\"", message);
+              buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                            remaining_size_in_buffer(),
+                                            " ; \"%s\"", message);
             }
           } else {
             // Format(instr, "smc'cond");
@@ -1494,7 +1495,7 @@
   ARMDecoder decoder(human_buffer, human_size);
   decoder.InstructionDecode(pc);
   int32_t instruction_bits = Instr::At(pc)->InstructionBits();
-  OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
+  Utils::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
   if (out_instr_size) {
     *out_instr_size = Instr::kInstrSize;
   }
diff --git a/runtime/vm/compiler/assembler/disassembler_arm64.cc b/runtime/vm/compiler/assembler/disassembler_arm64.cc
index 64f2f15..06b9ad7 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm64.cc
@@ -104,8 +104,8 @@
 void ARM64Decoder::PrintVRegister(int reg) {
   ASSERT(0 <= reg);
   ASSERT(reg < kNumberOfVRegisters);
-  buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                             remaining_size_in_buffer(), "v%d", reg);
+  buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                remaining_size_in_buffer(), "v%d", reg);
 }
 
 // These shift names are defined in a way to match the native disassembler
@@ -165,20 +165,20 @@
       shift_amount = 32;
     }
     buffer_pos_ +=
-        OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
-                    " %s #%d", shift_names[shift], shift_amount);
+        Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
+                       " %s #%d", shift_names[shift], shift_amount);
   } else {
     ASSERT(instr->IsExtend());
     // by register
     buffer_pos_ +=
-        OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
-                    " %s", extend_names[extend]);
+        Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
+                       " %s", extend_names[extend]);
     if (((instr->SFField() == 1) && (extend == UXTX)) ||
         ((instr->SFField() == 0) && (extend == UXTW))) {
       // Shift amount.
-      buffer_pos_ +=
-          OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
-                      " %d", extend_shift_amount);
+      buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                    remaining_size_in_buffer(), " %d",
+                                    extend_shift_amount);
     }
   }
 }
@@ -193,8 +193,8 @@
     Print("[");
     PrintRegister(rn, R31IsSP);
     if (off != 0) {
-      buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                 remaining_size_in_buffer(), ", #%d", off);
+      buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                    remaining_size_in_buffer(), ", #%d", off);
     }
     Print("]");
   } else {
@@ -204,8 +204,9 @@
         const int32_t imm9 = instr->SImm9Field();
         Print("[");
         PrintRegister(rn, R31IsSP);
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), ", #%d", imm9);
+        buffer_pos_ +=
+            Utils::SNPrint(current_position_in_buffer(),
+                           remaining_size_in_buffer(), ", #%d", imm9);
         Print("]");
         break;
       }
@@ -215,8 +216,9 @@
         Print("[");
         PrintRegister(rn, R31IsSP);
         Print("]");
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), ", #%d !", imm9);
+        buffer_pos_ +=
+            Utils::SNPrint(current_position_in_buffer(),
+                           remaining_size_in_buffer(), ", #%d !", imm9);
         break;
       }
       case 2: {
@@ -227,9 +229,9 @@
         PrintRegister(rn, R31IsSP);
         Print(", ");
         PrintRegister(rm, R31IsZR);
-        buffer_pos_ +=
-            OS::SNPrint(current_position_in_buffer(),
-                        remaining_size_in_buffer(), " %s", extend_names[ext]);
+        buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                      remaining_size_in_buffer(), " %s",
+                                      extend_names[ext]);
         if (s == 1) {
           Print(" scaled");
         }
@@ -241,8 +243,9 @@
         // rn + signed 9-bit immediate, pre-index, writeback.
         Print("[");
         PrintRegister(rn, R31IsSP);
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), ", #%d", imm9);
+        buffer_pos_ +=
+            Utils::SNPrint(current_position_in_buffer(),
+                           remaining_size_in_buffer(), ", #%d", imm9);
         Print("] !");
         break;
       }
@@ -261,19 +264,20 @@
     case 1:
       // rn + (imm7 << (2 + B31)), post-index, writeback.
       buffer_pos_ +=
-          OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
-                      "], #%d !", offset);
+          Utils::SNPrint(current_position_in_buffer(),
+                         remaining_size_in_buffer(), "], #%d !", offset);
       break;
     case 2:
       // rn + (imm7 << (2 + B31)), pre-index, no writeback.
-      buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                 remaining_size_in_buffer(), ", #%d ]", offset);
+      buffer_pos_ +=
+          Utils::SNPrint(current_position_in_buffer(),
+                         remaining_size_in_buffer(), ", #%d ]", offset);
       break;
     case 3:
       // rn + (imm7 << (2 + B31)), pre-index, writeback.
       buffer_pos_ +=
-          OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
-                      ", #%d ]!", offset);
+          Utils::SNPrint(current_position_in_buffer(),
+                         remaining_size_in_buffer(), ", #%d ]!", offset);
       break;
     default:
       Print(", ???]");
@@ -348,14 +352,16 @@
       if (format[3] == 'i') {
         ASSERT(STRING_STARTS_WITH(format, "bitimm"));
         const uint64_t imm = instr->ImmLogical();
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "0x%" Px64, imm);
+        buffer_pos_ +=
+            Utils::SNPrint(current_position_in_buffer(),
+                           remaining_size_in_buffer(), "0x%" Px64, imm);
         return 6;
       } else {
         ASSERT(STRING_STARTS_WITH(format, "bitpos"));
         int bitpos = instr->Bits(19, 4) | (instr->Bit(31) << 5);
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "#%d", bitpos);
+        buffer_pos_ +=
+            Utils::SNPrint(current_position_in_buffer(),
+                           remaining_size_in_buffer(), "#%d", bitpos);
         return 6;
       }
     }
@@ -373,8 +379,8 @@
         } else if (imm5 & 0x8) {
           typ = "d";
         }
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "%s", typ);
+        buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                      remaining_size_in_buffer(), "%s", typ);
         return 3;
       } else {
         ASSERT(STRING_STARTS_WITH(format, "cond"));
@@ -394,23 +400,23 @@
         int64_t off = instr->SImm26Field() << 2;
         uword destination = reinterpret_cast<uword>(instr) + off;
         buffer_pos_ +=
-            OS::SNPrint(current_position_in_buffer(),
-                        remaining_size_in_buffer(), "%#" Px "", destination);
+            Utils::SNPrint(current_position_in_buffer(),
+                           remaining_size_in_buffer(), "%#" Px "", destination);
       } else {
         if (format[5] == '4') {
           ASSERT(STRING_STARTS_WITH(format, "dest14"));
           int64_t off = instr->SImm14Field() << 2;
           uword destination = reinterpret_cast<uword>(instr) + off;
-          buffer_pos_ +=
-              OS::SNPrint(current_position_in_buffer(),
-                          remaining_size_in_buffer(), "%#" Px "", destination);
+          buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                        remaining_size_in_buffer(), "%#" Px "",
+                                        destination);
         } else {
           ASSERT(STRING_STARTS_WITH(format, "dest19"));
           int64_t off = instr->SImm19Field() << 2;
           uword destination = reinterpret_cast<uword>(instr) + off;
-          buffer_pos_ +=
-              OS::SNPrint(current_position_in_buffer(),
-                          remaining_size_in_buffer(), "%#" Px "", destination);
+          buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                        remaining_size_in_buffer(), "%#" Px "",
+                                        destination);
         }
       }
       return 6;
@@ -440,16 +446,17 @@
           sz_str = "?";
           break;
       }
-      buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                 remaining_size_in_buffer(), "%s", sz_str);
+      buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                    remaining_size_in_buffer(), "%s", sz_str);
       return 3;
     }
     case 'h': {
       ASSERT(STRING_STARTS_WITH(format, "hw"));
       const int shift = instr->HWField() << 4;
       if (shift != 0) {
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "lsl %d", shift);
+        buffer_pos_ +=
+            Utils::SNPrint(current_position_in_buffer(),
+                           remaining_size_in_buffer(), "lsl %d", shift);
       }
       return 2;
     }
@@ -477,8 +484,8 @@
         } else if (imm5 & 0x8) {
           idx = imm >> (shift + 3);
         }
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "[%d]", idx);
+        buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                      remaining_size_in_buffer(), "[%d]", idx);
         return 4;
       } else if (format[3] == '1') {
         uint64_t imm;
@@ -499,27 +506,30 @@
           ASSERT(STRING_STARTS_WITH(format, "imm16"));
           imm = instr->Imm16Field();
         }
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "0x%" Px64, imm);
+        buffer_pos_ +=
+            Utils::SNPrint(current_position_in_buffer(),
+                           remaining_size_in_buffer(), "0x%" Px64, imm);
         return ret;
       } else {
         ASSERT(STRING_STARTS_WITH(format, "imm"));
         if (format[3] == 'd') {
           double dimm = bit_cast<double, int64_t>(
               Instr::VFPExpandImm(instr->Imm8Field()));
-          buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                     remaining_size_in_buffer(), "%f", dimm);
+          buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                        remaining_size_in_buffer(), "%f", dimm);
           return 4;
         } else if (format[3] == 'r') {
           int immr = instr->ImmRField();
-          buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                     remaining_size_in_buffer(), "#%d", immr);
+          buffer_pos_ +=
+              Utils::SNPrint(current_position_in_buffer(),
+                             remaining_size_in_buffer(), "#%d", immr);
           return 4;
         } else {
           ASSERT(format[3] == 's');
           int imms = instr->ImmSField();
-          buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                     remaining_size_in_buffer(), "#%d", imms);
+          buffer_pos_ +=
+              Utils::SNPrint(current_position_in_buffer(),
+                             remaining_size_in_buffer(), "#%d", imms);
           return 4;
         }
       }
@@ -539,16 +549,16 @@
           const int64_t pc = reinterpret_cast<int64_t>(instr);
           const int64_t dest = pc + off;
           buffer_pos_ +=
-              OS::SNPrint(current_position_in_buffer(),
-                          remaining_size_in_buffer(), "0x%" Px64, dest);
+              Utils::SNPrint(current_position_in_buffer(),
+                             remaining_size_in_buffer(), "0x%" Px64, dest);
         } else {
           ASSERT(STRING_STARTS_WITH(format, "pcldr"));
           const int64_t off = instr->SImm19Field() << 2;
           const int64_t pc = reinterpret_cast<int64_t>(instr);
           const int64_t dest = pc + off;
           buffer_pos_ +=
-              OS::SNPrint(current_position_in_buffer(),
-                          remaining_size_in_buffer(), "0x%" Px64, dest);
+              Utils::SNPrint(current_position_in_buffer(),
+                             remaining_size_in_buffer(), "0x%" Px64, dest);
         }
         return 5;
       } else {
@@ -589,8 +599,8 @@
               break;
           }
         }
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "%s", sz_str);
+        buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                      remaining_size_in_buffer(), "%s", sz_str);
         return 3;
       } else {
         return FormatVRegister(instr, format);
@@ -632,8 +642,8 @@
             sz_str = "?";
             break;
         }
-        buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
-                                   remaining_size_in_buffer(), "%s", sz_str);
+        buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+                                      remaining_size_in_buffer(), "%s", sz_str);
         return 2;
       } else if (format[1] == ' ') {
         if (instr->HasS()) {
@@ -881,8 +891,8 @@
       const char* message = *reinterpret_cast<const char**>(
           reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
       buffer_pos_ +=
-          OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
-                      " ; \"%s\"", message);
+          Utils::SNPrint(current_position_in_buffer(),
+                         remaining_size_in_buffer(), " ; \"%s\"", message);
     }
   } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
              (instr->Bits(21, 3) == 2)) {
@@ -1520,7 +1530,7 @@
   ARM64Decoder decoder(human_buffer, human_size);
   decoder.InstructionDecode(pc);
   int32_t instruction_bits = Instr::At(pc)->InstructionBits();
-  OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
+  Utils::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
   if (out_instr_size) {
     *out_instr_size = Instr::kInstrSize;
   }
diff --git a/runtime/vm/compiler/assembler/disassembler_dbc.cc b/runtime/vm/compiler/assembler/disassembler_dbc.cc
index 7947d9f..7a15129 100644
--- a/runtime/vm/compiler/assembler/disassembler_dbc.cc
+++ b/runtime/vm/compiler/assembler/disassembler_dbc.cc
@@ -34,7 +34,7 @@
                    intptr_t* size,
                    const char* fmt,
                    ValueType value) {
-  intptr_t written = OS::SNPrint(*buf, *size, fmt, value);
+  intptr_t written = Utils::SNPrint(*buf, *size, fmt, value);
   if (written < *size) {
     *buf += written;
     *size += written;
@@ -218,13 +218,13 @@
   const uint8_t opcode = instr & 0xFF;
   ASSERT(opcode < kOpcodeCount);
   size_t name_size =
-      OS::SNPrint(human_buffer, human_size, "%-10s\t", kOpcodeNames[opcode]);
+      Utils::SNPrint(human_buffer, human_size, "%-10s\t", kOpcodeNames[opcode]);
 
   human_buffer += name_size;
   human_size -= name_size;
   kFormatters[opcode](human_buffer, human_size, pc, instr);
 
-  OS::SNPrint(hex_buffer, hex_size, "%08x", instr);
+  Utils::SNPrint(hex_buffer, hex_size, "%08x", instr);
   if (out_instr_size) {
     *out_instr_size = sizeof(uint32_t);
   }
diff --git a/runtime/vm/compiler/assembler/disassembler_x86.cc b/runtime/vm/compiler/assembler/disassembler_x86.cc
index 459eb4c..bd9b2de 100644
--- a/runtime/vm/compiler/assembler/disassembler_x86.cc
+++ b/runtime/vm/compiler/assembler/disassembler_x86.cc
@@ -385,7 +385,7 @@
   char* buf = buffer_ + buffer_pos_;
   va_list args;
   va_start(args, format);
-  int length = OS::VSNPrint(buf, available, format, args);
+  int length = Utils::VSNPrint(buf, available, format, args);
   va_end(args);
   buffer_pos_ =
       (length >= available) ? (buffer_size_ - 1) : (buffer_pos_ + length);
@@ -1957,7 +1957,7 @@
   int hex_index = 0;
   int remaining_size = hex_size - hex_index;
   for (int i = 0; (i < instruction_length) && (remaining_size > 2); ++i) {
-    OS::SNPrint(&hex_buffer[hex_index], remaining_size, "%02x", pc_ptr[i]);
+    Utils::SNPrint(&hex_buffer[hex_index], remaining_size, "%02x", pc_ptr[i]);
     hex_index += 2;
     remaining_size -= 2;
   }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 7c10118..54cdc63 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -189,12 +189,12 @@
 
   const char* Name() const {
     const char* kFormat = "Deopt stub for id %d, reason: %s";
-    const intptr_t len = OS::SNPrint(NULL, 0, kFormat, deopt_id(),
-                                     DeoptReasonToCString(reason())) +
+    const intptr_t len = Utils::SNPrint(NULL, 0, kFormat, deopt_id(),
+                                        DeoptReasonToCString(reason())) +
                          1;
     char* chars = Thread::Current()->zone()->Alloc<char>(len);
-    OS::SNPrint(chars, len, kFormat, deopt_id(),
-                DeoptReasonToCString(reason()));
+    Utils::SNPrint(chars, len, kFormat, deopt_id(),
+                   DeoptReasonToCString(reason()));
     return chars;
   }
 
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 2362012..ef164ec 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -2055,7 +2055,12 @@
 }
 
 Definition* RedefinitionInstr::Canonicalize(FlowGraph* flow_graph) {
-  if (!HasUses()) {
+  // Must not remove Redifinitions without uses until LICM, even though
+  // Redefinition might not have any uses itself it can still be dominating
+  // uses of the value it redefines and must serve as a barrier for those
+  // uses. RenameUsesDominatedByRedefinitions would normalize the graph and
+  // route those uses through this redefinition.
+  if (!HasUses() && !flow_graph->is_licm_allowed()) {
     return NULL;
   }
   if ((constrained_type() != NULL) &&
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index dfbd141..cb60f6a3 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -714,15 +714,17 @@
       return type_;
     }
 
-    const Class& type_class =
-        Class::Handle(Isolate::Current()->class_table()->At(cid_));
-
+    Isolate* I = Isolate::Current();
+    const Class& type_class = Class::Handle(I->class_table()->At(cid_));
     if (type_class.NumTypeArguments() > 0) {
-      type_ = &Object::dynamic_type();
-      return type_;
+      if (I->strong()) {
+        type_ = &AbstractType::ZoneHandle(type_class.RareType());
+      } else {
+        type_ = &Object::dynamic_type();
+      }
+    } else {
+      type_ = &Type::ZoneHandle(Type::NewNonParameterizedType(type_class));
     }
-
-    type_ = &Type::ZoneHandle(Type::NewNonParameterizedType(type_class));
   }
 
   return type_;
@@ -1254,21 +1256,27 @@
   }
 
   const Isolate* isolate = Isolate::Current();
-  const AbstractType* abstract_type = NULL;
+  CompileType compile_type_annotation = CompileType::None();
   if ((isolate->strong() && FLAG_use_strong_mode_types) ||
       (isolate->type_checks() &&
        (type().IsFunctionType() || type().HasResolvedTypeClass()))) {
-    abstract_type = &type();
+    const AbstractType* abstract_type = abstract_type = &type();
     TraceStrongModeType(this, *abstract_type);
+    compile_type_annotation = CompileType::FromAbstractType(*abstract_type);
   }
 
+  CompileType compile_type_cid = CompileType::None();
   if ((field_ != NULL) && (field_->guarded_cid() != kIllegalCid)) {
     bool is_nullable = field_->is_nullable();
     intptr_t field_cid = field_->guarded_cid();
-    return CompileType(is_nullable, field_cid, abstract_type);
+
+    compile_type_cid = CompileType(is_nullable, field_cid, NULL);
+  } else {
+    compile_type_cid = CompileType::FromCid(result_cid_);
   }
 
-  return CompileType::Create(result_cid_, *abstract_type);
+  return *CompileType::ComputeRefinedType(&compile_type_cid,
+                                          &compile_type_annotation);
 }
 
 CompileType LoadCodeUnitsInstr::ComputeType() const {
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index 0de502c..f22532f 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -2112,7 +2112,7 @@
   ASSERT(value->definition()->temp_index() == (owner()->temp_count() - 1));
   intptr_t index = GetCurrentTempLocalIndex();
   char name[64];
-  OS::SNPrint(name, 64, ":tmp_local%" Pd, index);
+  Utils::SNPrint(name, 64, ":tmp_local%" Pd, index);
   LocalVariable* var =
       new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                             String::ZoneHandle(Z, Symbols::New(T, name)),
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index aa504d3..f1ec175 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -732,23 +732,35 @@
   return DirectCallMetadata(target, check_receiver_for_null);
 }
 
-bool ProcedureAttributesMetadataHelper::ReadMetadata(intptr_t node_offset,
-                                                     bool* has_dynamic_calls) {
+bool ProcedureAttributesMetadataHelper::ReadMetadata(
+    intptr_t node_offset,
+    ProcedureAttributesMetadata* metadata) {
   intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
   if (md_offset < 0) {
-    *has_dynamic_calls = true;
     return false;
   }
-  *has_dynamic_calls = false;
+
+  AlternativeReadingScope alt(builder_->reader_, &H.metadata_payloads(),
+                              md_offset - MetadataPayloadOffset);
+
+  const int kDynamicUsesBit = 1 << 0;
+  const int kNonThisUsesBit = 1 << 1;
+  const int kTearOffUsesBit = 1 << 2;
+
+  const uint8_t flags = builder_->ReadByte();
+  metadata->has_dynamic_invocations =
+      (flags & kDynamicUsesBit) == kDynamicUsesBit;
+  metadata->has_non_this_uses = (flags & kNonThisUsesBit) == kNonThisUsesBit;
+  metadata->has_tearoff_uses = (flags & kTearOffUsesBit) == kTearOffUsesBit;
   return true;
 }
 
 ProcedureAttributesMetadata
 ProcedureAttributesMetadataHelper::GetProcedureAttributes(
     intptr_t node_offset) {
-  bool has_dynamic_calls = true;
-  ReadMetadata(node_offset, &has_dynamic_calls);
-  return ProcedureAttributesMetadata(has_dynamic_calls);
+  ProcedureAttributesMetadata metadata;
+  ReadMetadata(node_offset, &metadata);
+  return metadata;
 }
 
 InferredTypeMetadata InferredTypeMetadataHelper::GetInferredType(
@@ -973,7 +985,7 @@
 
       // Continue reading FunctionNode:
       // read positional_parameters and named_parameters.
-      AddPositionalAndNamedParameters(pos, type_check_mode);
+      AddPositionalAndNamedParameters(pos, type_check_mode, attrs);
 
       // We generate a synthetic body for implicit closure functions - which
       // will forward the call to the real function.
@@ -1032,7 +1044,8 @@
           field_helper.ReadUntilIncluding(FieldHelper::kFlags);
 
           if (!field_helper.IsCovariant() &&
-              !field_helper.IsGenericCovariantImpl()) {
+              (!field_helper.IsGenericCovariantImpl() ||
+               (!attrs.has_non_this_uses && !attrs.has_tearoff_uses))) {
             result_->setter_value->set_type_check_mode(
                 LocalVariable::kTypeCheckedByCaller);
           }
@@ -2032,7 +2045,9 @@
   // read positional_parameters and named_parameters.
   function_node_helper.ReadUntilExcluding(
       FunctionNodeHelper::kPositionalParameters);
-  AddPositionalAndNamedParameters(0, kTypeCheckAllParameters);
+
+  ProcedureAttributesMetadata default_attrs;
+  AddPositionalAndNamedParameters(0, kTypeCheckAllParameters, default_attrs);
 
   // "Peek" is now done.
   builder_->SetOffset(offset);
@@ -2060,23 +2075,25 @@
 
 void StreamingScopeBuilder::AddPositionalAndNamedParameters(
     intptr_t pos,
-    ParameterTypeCheckMode type_check_mode /* = kTypeCheckAllParameters*/) {
+    ParameterTypeCheckMode type_check_mode /* = kTypeCheckAllParameters*/,
+    const ProcedureAttributesMetadata& attrs) {
   // List of positional.
   intptr_t list_length = builder_->ReadListLength();  // read list length.
   for (intptr_t i = 0; i < list_length; ++i) {
-    AddVariableDeclarationParameter(pos++, type_check_mode);
+    AddVariableDeclarationParameter(pos++, type_check_mode, attrs);
   }
 
   // List of named.
   list_length = builder_->ReadListLength();  // read list length.
   for (intptr_t i = 0; i < list_length; ++i) {
-    AddVariableDeclarationParameter(pos++, type_check_mode);
+    AddVariableDeclarationParameter(pos++, type_check_mode, attrs);
   }
 }
 
 void StreamingScopeBuilder::AddVariableDeclarationParameter(
     intptr_t pos,
-    ParameterTypeCheckMode type_check_mode) {
+    ParameterTypeCheckMode type_check_mode,
+    const ProcedureAttributesMetadata& attrs) {
   intptr_t kernel_offset = builder_->ReaderOffset();  // no tag.
   const InferredTypeMetadata parameter_type =
       builder_->inferred_type_metadata_helper_.GetInferredType(kernel_offset);
@@ -2096,14 +2113,16 @@
     variable->set_is_forced_stack();
   }
 
-  const bool is_covariant =
-      helper.IsGenericCovariantImpl() || helper.IsCovariant();
+  const bool needs_covariant_checke_in_method =
+      helper.IsCovariant() ||
+      (helper.IsGenericCovariantImpl() && attrs.has_non_this_uses);
+
   switch (type_check_mode) {
     case kTypeCheckAllParameters:
       variable->set_type_check_mode(LocalVariable::kDoTypeCheck);
       break;
     case kTypeCheckForTearOffOfNonDynamicallyInvokedMethod:
-      if (is_covariant) {
+      if (needs_covariant_checke_in_method) {
         // Don't type check covariant parameters - they will be checked by
         // a function we forward to. Their types however are not known.
         variable->set_type_check_mode(LocalVariable::kSkipTypeCheck);
@@ -2112,7 +2131,7 @@
       }
       break;
     case kTypeCheckForNonDynamicallyInvokedMethod:
-      if (is_covariant) {
+      if (needs_covariant_checke_in_method) {
         variable->set_type_check_mode(LocalVariable::kDoTypeCheck);
       } else {
         // Types of non-covariant parameters are guaranteed to match by
@@ -2271,7 +2290,7 @@
 const String& StreamingScopeBuilder::GenerateName(const char* prefix,
                                                   intptr_t suffix) {
   char name[64];
-  OS::SNPrint(name, 64, "%s%" Pd "", prefix, suffix);
+  Utils::SNPrint(name, 64, "%s%" Pd "", prefix, suffix);
   return H.DartSymbolObfuscate(name);
 }
 
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 80da18a..aac0ad34 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -605,9 +605,15 @@
 };
 
 struct ProcedureAttributesMetadata {
-  explicit ProcedureAttributesMetadata(bool has_dynamic_invocations)
-      : has_dynamic_invocations(has_dynamic_invocations) {}
-  const bool has_dynamic_invocations;
+  ProcedureAttributesMetadata(bool has_dynamic_invocations = true,
+                              bool has_non_this_uses = true,
+                              bool has_tearoff_uses = true)
+      : has_dynamic_invocations(has_dynamic_invocations),
+        has_non_this_uses(has_non_this_uses),
+        has_tearoff_uses(has_tearoff_uses) {}
+  bool has_dynamic_invocations;
+  bool has_non_this_uses;
+  bool has_tearoff_uses;
 };
 
 // Helper class which provides access to direct call metadata.
@@ -621,7 +627,8 @@
   ProcedureAttributesMetadata GetProcedureAttributes(intptr_t node_offset);
 
  private:
-  bool ReadMetadata(intptr_t node_offset, bool* has_dynamic_invocations);
+  bool ReadMetadata(intptr_t node_offset,
+                    ProcedureAttributesMetadata* metadata);
 };
 
 class StreamingDartTypeTranslator {
@@ -749,13 +756,17 @@
 
   // This assumes that the reader is at a FunctionNode,
   // about to read the positional parameters.
-  void AddPositionalAndNamedParameters(intptr_t pos,
-                                       ParameterTypeCheckMode type_check_mode);
+  void AddPositionalAndNamedParameters(
+      intptr_t pos,
+      ParameterTypeCheckMode type_check_mode,
+      const ProcedureAttributesMetadata& attrs);
 
   // This assumes that the reader is at a FunctionNode,
   // about to read a parameter (i.e. VariableDeclaration).
-  void AddVariableDeclarationParameter(intptr_t pos,
-                                       ParameterTypeCheckMode type_check_mode);
+  void AddVariableDeclarationParameter(
+      intptr_t pos,
+      ParameterTypeCheckMode type_check_mode,
+      const ProcedureAttributesMetadata& attrs);
 
   LocalVariable* MakeVariable(TokenPosition declaration_pos,
                               TokenPosition token_pos,
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index e8b7c6b..2e5356c 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1843,7 +1843,7 @@
 LocalVariable* BaseFlowGraphBuilder::MakeTemporary() {
   char name[64];
   intptr_t index = stack_->definition()->temp_index();
-  OS::SNPrint(name, 64, ":temp%" Pd, index);
+  Utils::SNPrint(name, 64, ":temp%" Pd, index);
   const String& symbol_name =
       String::ZoneHandle(Z, Symbols::New(thread_, name));
   LocalVariable* variable =
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index faa46ac..8d58ab9 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -470,13 +470,13 @@
 
   va_list args;
   va_start(args, format);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
   va_end(args);
 
   char* buffer = Z->Alloc<char>(len + 1);
   va_list args2;
   va_start(args2, format);
-  OS::VSNPrint(buffer, (len + 1), format, args2);
+  Utils::VSNPrint(buffer, (len + 1), format, args2);
   va_end(args2);
 
   const String& message = String::Handle(Z, String::New(buffer));
@@ -1080,9 +1080,9 @@
   }
 
   char* chars = NULL;
-  intptr_t len = OS::SNPrint(NULL, 0, "%s:%s()", script_uri, main) + 1;
+  intptr_t len = Utils::SNPrint(NULL, 0, "%s:%s()", script_uri, main) + 1;
   chars = reinterpret_cast<char*>(malloc(len));
-  OS::SNPrint(chars, len, "%s:%s()", script_uri, main);
+  Utils::SNPrint(chars, len, "%s:%s()", script_uri, main);
   return chars;
 }
 
@@ -1546,7 +1546,7 @@
   const char* features = version + version_len;
   ASSERT(features != NULL);
   intptr_t pending_len = snapshot_size - version_len;
-  intptr_t buffer_len = OS::StrNLen(features, pending_len);
+  intptr_t buffer_len = Utils::StrNLen(features, pending_len);
   // if buffer_len is less than pending_len it means we have a null terminated
   // string and we can safely execute 'strstr' on it.
   if ((buffer_len < pending_len)) {
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index d2507e8..2c6f781 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3610,7 +3610,7 @@
   // Use a unique expected value.
   static int counter = 0;
   char buffer[256];
-  OS::SNPrint(buffer, 256, "Expected%d", ++counter);
+  Utils::SNPrint(buffer, 256, "Expected%d", ++counter);
 
   // Try to change the field value.
   result = Dart_SetField(container, name, NewString(buffer));
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index a4948a1..bab0dff 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -395,7 +395,7 @@
     // Measure.
     va_list measure_args;
     va_copy(measure_args, args);
-    intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
+    intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
     va_end(measure_args);
 
     // Alloc.
@@ -407,8 +407,8 @@
     // Print.
     va_list print_args;
     va_copy(print_args, args);
-    OS::VSNPrint(reinterpret_cast<char*>(current_), len + 1, format,
-                 print_args);
+    Utils::VSNPrint(reinterpret_cast<char*>(current_), len + 1, format,
+                    print_args);
     va_end(print_args);
     current_ += len;  // Not len + 1 to swallow the terminating NUL.
   }
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 80e7a1b..ee069b2 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -417,8 +417,8 @@
     String& line_string = String::Handle(script.GetLine(line));
     THR_Print("  Function: %s\n", top_function.ToFullyQualifiedCString());
     char line_buffer[80];
-    OS::SNPrint(line_buffer, sizeof(line_buffer), "  Line %" Pd ": '%s'", line,
-                line_string.ToCString());
+    Utils::SNPrint(line_buffer, sizeof(line_buffer), "  Line %" Pd ": '%s'",
+                   line, line_string.ToCString());
     THR_Print("%s\n", line_buffer);
     THR_Print("  Deopt args: %" Pd "\n", deopt_arg_count);
   }
@@ -1401,7 +1401,7 @@
   // Compute the buffer size required.
   intptr_t len = 1;  // Trailing '\0'.
   for (intptr_t i = 0; i < deopt_instrs.length(); i++) {
-    len += OS::SNPrint(NULL, 0, FORMAT, deopt_instrs[i]->ToCString());
+    len += Utils::SNPrint(NULL, 0, FORMAT, deopt_instrs[i]->ToCString());
   }
 
   // Allocate the buffer.
@@ -1410,8 +1410,8 @@
   // Layout the fields in the buffer.
   intptr_t index = 0;
   for (intptr_t i = 0; i < deopt_instrs.length(); i++) {
-    index += OS::SNPrint((buffer + index), (len - index), FORMAT,
-                         deopt_instrs[i]->ToCString());
+    index += Utils::SNPrint((buffer + index), (len - index), FORMAT,
+                            deopt_instrs[i]->ToCString());
   }
 
   return buffer;
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
index 2d0e82f..0be5a94 100644
--- a/runtime/vm/find_code_object_test.cc
+++ b/runtime/vm/find_code_object_test.cc
@@ -46,14 +46,14 @@
   lib = Library::CoreLibrary();
 
   // Load up class A with 1024 functions.
-  int written = OS::SNPrint(scriptChars, kScriptSize, "class A {");
+  int written = Utils::SNPrint(scriptChars, kScriptSize, "class A {");
   for (int i = 0; i < kNumFunctions; i++) {
-    OS::SNPrint(buffer, 256,
-                "static foo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
-    written += OS::SNPrint((scriptChars + written), (kScriptSize - written),
-                           "%s", buffer);
+    Utils::SNPrint(buffer, 256,
+                   "static foo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
+    written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
+                              "%s", buffer);
   }
-  OS::SNPrint((scriptChars + written), (kScriptSize - written), "}");
+  Utils::SNPrint((scriptChars + written), (kScriptSize - written), "}");
   source = String::New(scriptChars);
   script = Script::New(url, source, RawScript::kScriptTag);
   EXPECT(CompilerTest::TestCompileScript(lib, script));
@@ -61,7 +61,7 @@
   EXPECT(!clsA.IsNull());
   ClassFinalizer::ProcessPendingClasses();
   for (int i = 0; i < kNumFunctions; i++) {
-    OS::SNPrint(buffer, 256, "foo%d", i);
+    Utils::SNPrint(buffer, 256, "foo%d", i);
     function_name = String::New(buffer);
     function = clsA.LookupStaticFunction(function_name);
     EXPECT(!function.IsNull());
@@ -72,28 +72,28 @@
   }
 
   // Now load up class B with 1024 functions.
-  written = OS::SNPrint(scriptChars, kScriptSize, "class B {");
+  written = Utils::SNPrint(scriptChars, kScriptSize, "class B {");
   // Create one large function.
-  OS::SNPrint(buffer, sizeof(buffer), "static moo0([var i=1]) { ");
-  written += OS::SNPrint((scriptChars + written), (kScriptSize - written), "%s",
-                         buffer);
+  Utils::SNPrint(buffer, sizeof(buffer), "static moo0([var i=1]) { ");
+  written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
+                            "%s", buffer);
   // Generate a large function so that the code for this function when
   // compiled will reside in a large page.
   for (int i = 0; i < kLoopCount; i++) {
-    OS::SNPrint(buffer, sizeof(buffer), "i = i+i;");
-    written += OS::SNPrint((scriptChars + written), (kScriptSize - written),
-                           "%s", buffer);
+    Utils::SNPrint(buffer, sizeof(buffer), "i = i+i;");
+    written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
+                              "%s", buffer);
   }
-  OS::SNPrint(buffer, sizeof(buffer), "return i; }");
-  written += OS::SNPrint((scriptChars + written), (kScriptSize - written), "%s",
-                         buffer);
+  Utils::SNPrint(buffer, sizeof(buffer), "return i; }");
+  written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
+                            "%s", buffer);
   for (int i = 1; i < kNumFunctions; i++) {
-    OS::SNPrint(buffer, 256,
-                "static moo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
-    written += OS::SNPrint((scriptChars + written), (kScriptSize - written),
-                           "%s", buffer);
+    Utils::SNPrint(buffer, 256,
+                   "static moo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
+    written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
+                              "%s", buffer);
   }
-  OS::SNPrint((scriptChars + written), (kScriptSize - written), "}");
+  Utils::SNPrint((scriptChars + written), (kScriptSize - written), "}");
   url = String::New("dart-test:FindCodeObject");
   source = String::New(scriptChars);
   script = Script::New(url, source, RawScript::kScriptTag);
@@ -102,7 +102,7 @@
   EXPECT(!clsB.IsNull());
   ClassFinalizer::ProcessPendingClasses();
   for (int i = 0; i < kNumFunctions; i++) {
-    OS::SNPrint(buffer, 256, "moo%d", i);
+    Utils::SNPrint(buffer, 256, "moo%d", i);
     function_name = String::New(buffer);
     function = clsB.LookupStaticFunction(function_name);
     EXPECT(!function.IsNull());
@@ -115,7 +115,7 @@
   // Now try and access these functions using the code index table.
   Code& code = Code::Handle();
   uword pc;
-  OS::SNPrint(buffer, 256, "foo%d", 123);
+  Utils::SNPrint(buffer, 256, "foo%d", 123);
   function_name = String::New(buffer);
   function = clsA.LookupStaticFunction(function_name);
   EXPECT(!function.IsNull());
@@ -124,7 +124,7 @@
   pc = code.PayloadStart() + 16;
   EXPECT(Code::LookupCode(pc) == code.raw());
 
-  OS::SNPrint(buffer, 256, "moo%d", 54);
+  Utils::SNPrint(buffer, 256, "moo%d", 54);
   function_name = String::New(buffer);
   function = clsB.LookupStaticFunction(function_name);
   EXPECT(!function.IsNull());
@@ -134,7 +134,7 @@
   EXPECT(Code::LookupCode(pc) == code.raw());
 
   // Lookup the large function
-  OS::SNPrint(buffer, 256, "moo%d", 0);
+  Utils::SNPrint(buffer, 256, "moo%d", 0);
   function_name = String::New(buffer);
   function = clsB.LookupStaticFunction(function_name);
   EXPECT(!function.IsNull());
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index da02f72..7468e02 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -528,7 +528,7 @@
     default:
       UNREACHABLE();
   }
-  OS::SNPrint(name, name_size, "dart-%s %s", space_name, isolate_name);
+  Utils::SNPrint(name, name_size, "dart-%s %s", space_name, isolate_name);
 }
 
 void Heap::AddRegionsToObjectSet(ObjectSet* set) const {
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 14f7506..da65506 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -163,13 +163,13 @@
     if (details_format != NULL) {
       va_list args;
       va_start(args, details_format);
-      intptr_t len = OS::VSNPrint(NULL, 0, details_format, args);
+      intptr_t len = Utils::VSNPrint(NULL, 0, details_format, args);
       va_end(args);
 
       char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
       va_list args2;
       va_start(args2, details_format);
-      OS::VSNPrint(buffer, (len + 1), details_format, args2);
+      Utils::VSNPrint(buffer, (len + 1), details_format, args2);
       va_end(args2);
 
       data.AddProperty("details", buffer);
diff --git a/runtime/vm/json_writer.cc b/runtime/vm/json_writer.cc
index c4e980c..4e7c98a 100644
--- a/runtime/vm/json_writer.cc
+++ b/runtime/vm/json_writer.cc
@@ -189,7 +189,7 @@
 
   va_list measure_args;
   va_copy(measure_args, args);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
   va_end(measure_args);
 
   MaybeOnStackBuffer mosb(len + 1);
@@ -197,7 +197,7 @@
 
   va_list print_args;
   va_copy(print_args, args);
-  intptr_t len2 = OS::VSNPrint(p, len + 1, format, print_args);
+  intptr_t len2 = Utils::VSNPrint(p, len + 1, format, print_args);
   va_end(print_args);
   ASSERT(len == len2);
 
@@ -265,7 +265,7 @@
 
   va_list measure_args;
   va_copy(measure_args, args);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
   va_end(measure_args);
 
   MaybeOnStackBuffer mosb(len + 1);
@@ -273,7 +273,7 @@
 
   va_list print_args;
   va_copy(print_args, args);
-  intptr_t len2 = OS::VSNPrint(p, len + 1, format, print_args);
+  intptr_t len2 = Utils::VSNPrint(p, len + 1, format, print_args);
   va_end(print_args);
   ASSERT(len == len2);
 
diff --git a/runtime/vm/log.cc b/runtime/vm/log.cc
index 23005a7..06a4263 100644
--- a/runtime/vm/log.cc
+++ b/runtime/vm/log.cc
@@ -63,14 +63,14 @@
   // Measure.
   va_list measure_args;
   va_copy(measure_args, args);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
   va_end(measure_args);
 
   // Print.
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
   va_list print_args;
   va_copy(print_args, args);
-  OS::VSNPrint(buffer, (len + 1), format, print_args);
+  Utils::VSNPrint(buffer, (len + 1), format, print_args);
   va_end(print_args);
 
   // Append.
diff --git a/runtime/vm/log_test.cc b/runtime/vm/log_test.cc
index c64fd21..f17c4d9 100644
--- a/runtime/vm/log_test.cc
+++ b/runtime/vm/log_test.cc
@@ -21,14 +21,14 @@
   // Measure.
   va_list args;
   va_start(args, format);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
   va_end(args);
 
   // Print string to buffer.
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
   va_list args2;
   va_start(args2, format);
-  OS::VSNPrint(buffer, (len + 1), format, args2);
+  Utils::VSNPrint(buffer, (len + 1), format, args2);
   va_end(args2);
 
   if (test_output_ != NULL) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 3a928b4..707af78 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2712,7 +2712,7 @@
   for (; i < desc.PositionalCount(); i++) {
     invocation.SetParameterTypeAt(i, Object::dynamic_type());
     char name[64];
-    OS::SNPrint(name, 64, ":p%" Pd, i);
+    Utils::SNPrint(name, 64, ":p%" Pd, i);
     invocation.SetParameterNameAt(
         i, String::Handle(zone, Symbols::New(thread, name)));
   }
@@ -6307,9 +6307,9 @@
     if (error_message != NULL) {
       const intptr_t kMessageBufferSize = 64;
       char message_buffer[kMessageBufferSize];
-      OS::SNPrint(message_buffer, kMessageBufferSize,
-                  "%" Pd " type arguments passed, but %" Pd " expected",
-                  num_type_arguments, NumTypeParameters());
+      Utils::SNPrint(message_buffer, kMessageBufferSize,
+                     "%" Pd " type arguments passed, but %" Pd " expected",
+                     num_type_arguments, NumTypeParameters());
       // Allocate in old space because it can be invoked in background
       // optimizing compilation.
       *error_message = String::New(message_buffer, Heap::kOld);
@@ -6320,9 +6320,9 @@
     if (error_message != NULL) {
       const intptr_t kMessageBufferSize = 64;
       char message_buffer[kMessageBufferSize];
-      OS::SNPrint(message_buffer, kMessageBufferSize,
-                  "%" Pd " named passed, at most %" Pd " expected",
-                  num_named_arguments, NumOptionalNamedParameters());
+      Utils::SNPrint(message_buffer, kMessageBufferSize,
+                     "%" Pd " named passed, at most %" Pd " expected",
+                     num_named_arguments, NumOptionalNamedParameters());
       // Allocate in old space because it can be invoked in background
       // optimizing compilation.
       *error_message = String::New(message_buffer, Heap::kOld);
@@ -6338,12 +6338,12 @@
       char message_buffer[kMessageBufferSize];
       // Hide implicit parameters to the user.
       const intptr_t num_hidden_params = NumImplicitParameters();
-      OS::SNPrint(message_buffer, kMessageBufferSize,
-                  "%" Pd "%s passed, %s%" Pd " expected",
-                  num_pos_args - num_hidden_params,
-                  num_opt_pos_params > 0 ? " positional" : "",
-                  num_opt_pos_params > 0 ? "at most " : "",
-                  num_pos_params - num_hidden_params);
+      Utils::SNPrint(message_buffer, kMessageBufferSize,
+                     "%" Pd "%s passed, %s%" Pd " expected",
+                     num_pos_args - num_hidden_params,
+                     num_opt_pos_params > 0 ? " positional" : "",
+                     num_opt_pos_params > 0 ? "at most " : "",
+                     num_pos_params - num_hidden_params);
       // Allocate in old space because it can be invoked in background
       // optimizing compilation.
       *error_message = String::New(message_buffer, Heap::kOld);
@@ -6356,12 +6356,12 @@
       char message_buffer[kMessageBufferSize];
       // Hide implicit parameters to the user.
       const intptr_t num_hidden_params = NumImplicitParameters();
-      OS::SNPrint(message_buffer, kMessageBufferSize,
-                  "%" Pd "%s passed, %s%" Pd " expected",
-                  num_pos_args - num_hidden_params,
-                  num_opt_pos_params > 0 ? " positional" : "",
-                  num_opt_pos_params > 0 ? "at least " : "",
-                  num_fixed_parameters() - num_hidden_params);
+      Utils::SNPrint(message_buffer, kMessageBufferSize,
+                     "%" Pd "%s passed, %s%" Pd " expected",
+                     num_pos_args - num_hidden_params,
+                     num_opt_pos_params > 0 ? " positional" : "",
+                     num_opt_pos_params > 0 ? "at least " : "",
+                     num_fixed_parameters() - num_hidden_params);
       // Allocate in old space because it can be invoked in background
       // optimizing compilation.
       *error_message = String::New(message_buffer, Heap::kOld);
@@ -6403,9 +6403,9 @@
       if (error_message != NULL) {
         const intptr_t kMessageBufferSize = 64;
         char message_buffer[kMessageBufferSize];
-        OS::SNPrint(message_buffer, kMessageBufferSize,
-                    "no optional formal parameter named '%s'",
-                    argument_name.ToCString());
+        Utils::SNPrint(message_buffer, kMessageBufferSize,
+                       "no optional formal parameter named '%s'",
+                       argument_name.ToCString());
         // Allocate in old space because it can be invoked in background
         // optimizing compilation.
         *error_message = String::New(message_buffer, Heap::kOld);
@@ -6448,9 +6448,9 @@
       if (error_message != NULL) {
         const intptr_t kMessageBufferSize = 64;
         char message_buffer[kMessageBufferSize];
-        OS::SNPrint(message_buffer, kMessageBufferSize,
-                    "no optional formal parameter named '%s'",
-                    argument_name.ToCString());
+        Utils::SNPrint(message_buffer, kMessageBufferSize,
+                       "no optional formal parameter named '%s'",
+                       argument_name.ToCString());
         // Allocate in old space because it can be invoked in background
         // optimizing compilation.
         *error_message = String::New(message_buffer, Heap::kOld);
@@ -6479,7 +6479,7 @@
     QualifiedFunctionLibKind lib_kind) {
   const char* name = String::Handle(function.name()).ToCString();
   const char* function_format = (reserve_len == 0) ? "%s" : "%s_";
-  reserve_len += OS::SNPrint(NULL, 0, function_format, name);
+  reserve_len += Utils::SNPrint(NULL, 0, function_format, name);
   const Function& parent = Function::Handle(function.parent_function());
   intptr_t written = 0;
   if (parent.IsNull()) {
@@ -6509,18 +6509,18 @@
       lib_class_format = "%s%s.";
     }
     reserve_len +=
-        OS::SNPrint(NULL, 0, lib_class_format, library_name, class_name);
+        Utils::SNPrint(NULL, 0, lib_class_format, library_name, class_name);
     ASSERT(chars != NULL);
     *chars = Thread::Current()->zone()->Alloc<char>(reserve_len + 1);
-    written = OS::SNPrint(*chars, reserve_len + 1, lib_class_format,
-                          library_name, class_name);
+    written = Utils::SNPrint(*chars, reserve_len + 1, lib_class_format,
+                             library_name, class_name);
   } else {
     written = ConstructFunctionFullyQualifiedCString(parent, chars, reserve_len,
                                                      with_lib, lib_kind);
   }
   ASSERT(*chars != NULL);
   char* next = *chars + written;
-  written += OS::SNPrint(next, reserve_len + 1, function_format, name);
+  written += Utils::SNPrint(next, reserve_len + 1, function_format, name);
   // Replace ":" with "_".
   while (true) {
     next = strchr(next, ':');
@@ -11443,8 +11443,8 @@
   char name_buffer[kNameLength];
   String& cls_name = String::Handle(zone);
   for (int fld_cnt = 1; fld_cnt <= kNumNativeWrappersClasses; fld_cnt++) {
-    OS::SNPrint(name_buffer, kNameLength, "%s%d", kNativeWrappersClass,
-                fld_cnt);
+    Utils::SNPrint(name_buffer, kNameLength, "%s%d", kNativeWrappersClass,
+                   fld_cnt);
     cls_name = Symbols::New(thread, name_buffer);
     Class::NewNativeWrapper(native_flds_lib, cls_name, fld_cnt);
   }
@@ -11549,8 +11549,8 @@
   intptr_t sequence_value = libs.Length();
 
   char private_key[32];
-  OS::SNPrint(private_key, sizeof(private_key), "%c%" Pd "%06" Pd "",
-              kPrivateKeySeparator, sequence_value, hash_value);
+  Utils::SNPrint(private_key, sizeof(private_key), "%c%" Pd "%06" Pd "",
+                 kPrivateKeySeparator, sequence_value, hash_value);
   const String& key =
       String::Handle(zone, String::New(private_key, Heap::kOld));
   key.Hash();  // This string may end up in the VM isolate.
@@ -12653,9 +12653,9 @@
   {
     Iterator iter(*this, RawPcDescriptors::kAnyKind);
     while (iter.MoveNext()) {
-      len += OS::SNPrint(NULL, 0, FORMAT, addr_width, iter.PcOffset(),
-                         KindAsStr(iter.Kind()), iter.DeoptId(),
-                         iter.TokenPos().ToCString(), iter.TryIndex());
+      len += Utils::SNPrint(NULL, 0, FORMAT, addr_width, iter.PcOffset(),
+                            KindAsStr(iter.Kind()), iter.DeoptId(),
+                            iter.TokenPos().ToCString(), iter.TryIndex());
     }
   }
   // Allocate the buffer.
@@ -12665,9 +12665,9 @@
   Iterator iter(*this, RawPcDescriptors::kAnyKind);
   while (iter.MoveNext()) {
     index +=
-        OS::SNPrint((buffer + index), (len - index), FORMAT, addr_width,
-                    iter.PcOffset(), KindAsStr(iter.Kind()), iter.DeoptId(),
-                    iter.TokenPos().ToCString(), iter.TryIndex());
+        Utils::SNPrint((buffer + index), (len - index), FORMAT, addr_width,
+                       iter.PcOffset(), KindAsStr(iter.Kind()), iter.DeoptId(),
+                       iter.TokenPos().ToCString(), iter.TryIndex());
   }
   return buffer;
 #undef FORMAT
@@ -12839,7 +12839,7 @@
   if (IsNull()) {
     return "{null}";
   } else {
-    intptr_t fixed_length = OS::SNPrint(NULL, 0, FORMAT, PcOffset()) + 1;
+    intptr_t fixed_length = Utils::SNPrint(NULL, 0, FORMAT, PcOffset()) + 1;
     Thread* thread = Thread::Current();
     // Guard against integer overflow in the computation of alloc_size.
     //
@@ -12850,7 +12850,7 @@
     }
     intptr_t alloc_size = fixed_length + Length();
     char* chars = thread->zone()->Alloc<char>(alloc_size);
-    intptr_t index = OS::SNPrint(chars, alloc_size, FORMAT, PcOffset());
+    intptr_t index = Utils::SNPrint(chars, alloc_size, FORMAT, PcOffset());
     for (intptr_t i = 0; i < Length(); i++) {
       chars[index++] = IsObject(i) ? '1' : '0';
     }
@@ -12889,15 +12889,15 @@
   const RawLocalVarDescriptors::VarInfoKind kind = info.kind();
   const int32_t index = info.index();
   if (kind == RawLocalVarDescriptors::kContextLevel) {
-    return OS::SNPrint(buffer, len,
-                       "%2" Pd
-                       " %-13s level=%-3d"
-                       " begin=%-3d end=%d\n",
-                       i, LocalVarDescriptors::KindToCString(kind), index,
-                       static_cast<int>(info.begin_pos.value()),
-                       static_cast<int>(info.end_pos.value()));
+    return Utils::SNPrint(buffer, len,
+                          "%2" Pd
+                          " %-13s level=%-3d"
+                          " begin=%-3d end=%d\n",
+                          i, LocalVarDescriptors::KindToCString(kind), index,
+                          static_cast<int>(info.begin_pos.value()),
+                          static_cast<int>(info.end_pos.value()));
   } else if (kind == RawLocalVarDescriptors::kContextVar) {
-    return OS::SNPrint(
+    return Utils::SNPrint(
         buffer, len,
         "%2" Pd
         " %-13s level=%-3d index=%-3d"
@@ -12906,7 +12906,7 @@
         static_cast<int>(info.begin_pos.Pos()),
         static_cast<int>(info.end_pos.Pos()), var_name.ToCString());
   } else {
-    return OS::SNPrint(
+    return Utils::SNPrint(
         buffer, len,
         "%2" Pd
         " %-13s scope=%-3d index=%-3d"
@@ -13129,13 +13129,13 @@
     handled_types = GetHandledTypes(i);
     const intptr_t num_types =
         handled_types.IsNull() ? 0 : handled_types.Length();
-    len += OS::SNPrint(NULL, 0, FORMAT1, i, info.handler_pc_offset, num_types,
-                       info.outer_try_index,
-                       info.is_generated ? "(generated)" : "");
+    len += Utils::SNPrint(NULL, 0, FORMAT1, i, info.handler_pc_offset,
+                          num_types, info.outer_try_index,
+                          info.is_generated ? "(generated)" : "");
     for (int k = 0; k < num_types; k++) {
       type ^= handled_types.At(k);
       ASSERT(!type.IsNull());
-      len += OS::SNPrint(NULL, 0, FORMAT2, k, type.ToCString());
+      len += Utils::SNPrint(NULL, 0, FORMAT2, k, type.ToCString());
     }
   }
   // Allocate the buffer.
@@ -13148,13 +13148,13 @@
     const intptr_t num_types =
         handled_types.IsNull() ? 0 : handled_types.Length();
     num_chars +=
-        OS::SNPrint((buffer + num_chars), (len - num_chars), FORMAT1, i,
-                    info.handler_pc_offset, num_types, info.outer_try_index,
-                    info.is_generated ? "(generated)" : "");
+        Utils::SNPrint((buffer + num_chars), (len - num_chars), FORMAT1, i,
+                       info.handler_pc_offset, num_types, info.outer_try_index,
+                       info.is_generated ? "(generated)" : "");
     for (int k = 0; k < num_types; k++) {
       type ^= handled_types.At(k);
-      num_chars += OS::SNPrint((buffer + num_chars), (len - num_chars), FORMAT2,
-                               k, type.ToCString());
+      num_chars += Utils::SNPrint((buffer + num_chars), (len - num_chars),
+                                  FORMAT2, k, type.ToCString());
     }
   }
   return buffer;
@@ -18315,11 +18315,12 @@
         "TypeParameter: name %s; index: %d; function: %s; bound: %s";
     const Function& function = Function::Handle(parameterized_function());
     const char* fun_cstr = String::Handle(function.name()).ToCString();
-    intptr_t len =
-        OS::SNPrint(NULL, 0, format, name_cstr, index(), fun_cstr, bound_cstr) +
-        1;
+    intptr_t len = Utils::SNPrint(NULL, 0, format, name_cstr, index(), fun_cstr,
+                                  bound_cstr) +
+                   1;
     char* chars = Thread::Current()->zone()->Alloc<char>(len);
-    OS::SNPrint(chars, len, format, name_cstr, index(), fun_cstr, bound_cstr);
+    Utils::SNPrint(chars, len, format, name_cstr, index(), fun_cstr,
+                   bound_cstr);
     return chars;
   } else {
     const char* format =
@@ -18327,11 +18328,12 @@
     const Class& cls = Class::Handle(parameterized_class());
     const char* cls_cstr =
         cls.IsNull() ? " null" : String::Handle(cls.Name()).ToCString();
-    intptr_t len =
-        OS::SNPrint(NULL, 0, format, name_cstr, index(), cls_cstr, bound_cstr) +
-        1;
+    intptr_t len = Utils::SNPrint(NULL, 0, format, name_cstr, index(), cls_cstr,
+                                  bound_cstr) +
+                   1;
     char* chars = Thread::Current()->zone()->Alloc<char>(len);
-    OS::SNPrint(chars, len, format, name_cstr, index(), cls_cstr, bound_cstr);
+    Utils::SNPrint(chars, len, format, name_cstr, index(), cls_cstr,
+                   bound_cstr);
     return chars;
   }
 }
@@ -18564,12 +18566,12 @@
   const char* type_param_cstr = String::Handle(type_param.name()).ToCString();
   const Class& cls = Class::Handle(type_param.parameterized_class());
   const char* cls_cstr = String::Handle(cls.Name()).ToCString();
-  intptr_t len = OS::SNPrint(NULL, 0, format, type_cstr, bound_cstr,
-                             type_param_cstr, cls_cstr) +
+  intptr_t len = Utils::SNPrint(NULL, 0, format, type_cstr, bound_cstr,
+                                type_param_cstr, cls_cstr) +
                  1;
   char* chars = Thread::Current()->zone()->Alloc<char>(len);
-  OS::SNPrint(chars, len, format, type_cstr, bound_cstr, type_param_cstr,
-              cls_cstr);
+  Utils::SNPrint(chars, len, format, type_cstr, bound_cstr, type_param_cstr,
+                 cls_cstr);
   return chars;
 }
 
@@ -18592,9 +18594,10 @@
   const char* first_mixin_type_cstr =
       String::Handle(AbstractType::Handle(MixinTypeAt(0)).Name()).ToCString();
   intptr_t len =
-      OS::SNPrint(NULL, 0, format, super_type_cstr, first_mixin_type_cstr) + 1;
+      Utils::SNPrint(NULL, 0, format, super_type_cstr, first_mixin_type_cstr) +
+      1;
   char* chars = Thread::Current()->zone()->Alloc<char>(len);
-  OS::SNPrint(chars, len, format, super_type_cstr, first_mixin_type_cstr);
+  Utils::SNPrint(chars, len, format, super_type_cstr, first_mixin_type_cstr);
   return chars;
 }
 
@@ -20785,12 +20788,12 @@
                                  Heap::Space space) {
   va_list args_copy;
   va_copy(args_copy, args);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, args_copy);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, args_copy);
   va_end(args_copy);
 
   Zone* zone = Thread::Current()->zone();
   char* buffer = zone->Alloc<char>(len + 1);
-  OS::VSNPrint(buffer, (len + 1), format, args);
+  Utils::VSNPrint(buffer, (len + 1), format, args);
 
   return String::New(buffer, space);
 }
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 056a349..0dd75a3 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -1807,7 +1807,7 @@
   // Make sure to cause symbol table overflow.
   for (int i = 0; i < 1024; i++) {
     char buf[256];
-    OS::SNPrint(buf, sizeof(buf), "%d", i);
+    Utils::SNPrint(buf, sizeof(buf), "%d", i);
     Symbols::New(thread, buf);
   }
   eins = Symbols::New(thread, "Eins");
@@ -1911,20 +1911,20 @@
 
 static void TestIllegalArrayLength(intptr_t length) {
   char buffer[1024];
-  OS::SNPrint(buffer, sizeof(buffer),
-              "main() {\n"
-              "  new List(%" Pd
-              ");\n"
-              "}\n",
-              length);
+  Utils::SNPrint(buffer, sizeof(buffer),
+                 "main() {\n"
+                 "  new List(%" Pd
+                 ");\n"
+                 "}\n",
+                 length);
   Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
   EXPECT_VALID(lib);
   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  OS::SNPrint(buffer, sizeof(buffer),
-              "Unhandled exception:\n"
-              "RangeError (length): Invalid value: "
-              "Not in range 0..%" Pd ", inclusive: %" Pd,
-              Array::kMaxElements, length);
+  Utils::SNPrint(buffer, sizeof(buffer),
+                 "Unhandled exception:\n"
+                 "RangeError (length): Invalid value: "
+                 "Not in range 0..%" Pd ", inclusive: %" Pd,
+                 Array::kMaxElements, length);
   EXPECT_ERROR(result, buffer);
 }
 
@@ -1942,12 +1942,12 @@
 
 TEST_CASE(ArrayLengthMaxElements) {
   char buffer[1024];
-  OS::SNPrint(buffer, sizeof(buffer),
-              "main() {\n"
-              "  return new List(%" Pd
-              ");\n"
-              "}\n",
-              Array::kMaxElements);
+  Utils::SNPrint(buffer, sizeof(buffer),
+                 "main() {\n"
+                 "  return new List(%" Pd
+                 ");\n"
+                 "}\n",
+                 Array::kMaxElements);
   Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
   EXPECT_VALID(lib);
   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
@@ -1964,17 +1964,17 @@
 static void TestIllegalTypedDataLength(const char* class_name,
                                        intptr_t length) {
   char buffer[1024];
-  OS::SNPrint(buffer, sizeof(buffer),
-              "import 'dart:typed_data';\n"
-              "main() {\n"
-              "  new %s(%" Pd
-              ");\n"
-              "}\n",
-              class_name, length);
+  Utils::SNPrint(buffer, sizeof(buffer),
+                 "import 'dart:typed_data';\n"
+                 "main() {\n"
+                 "  new %s(%" Pd
+                 ");\n"
+                 "}\n",
+                 class_name, length);
   Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
   EXPECT_VALID(lib);
   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  OS::SNPrint(buffer, sizeof(buffer), "%" Pd, length);
+  Utils::SNPrint(buffer, sizeof(buffer), "%" Pd, length);
   EXPECT_ERROR(result, "Invalid argument(s)");
   EXPECT_ERROR(result, buffer);
 }
@@ -1995,13 +1995,13 @@
 TEST_CASE(Int8ListLengthMaxElements) {
   const intptr_t max_elements = TypedData::MaxElements(kTypedDataInt8ArrayCid);
   char buffer[1024];
-  OS::SNPrint(buffer, sizeof(buffer),
-              "import 'dart:typed_data';\n"
-              "main() {\n"
-              "  return new Int8List(%" Pd
-              ");\n"
-              "}\n",
-              max_elements);
+  Utils::SNPrint(buffer, sizeof(buffer),
+                 "import 'dart:typed_data';\n"
+                 "main() {\n"
+                 "  return new Int8List(%" Pd
+                 ");\n"
+                 "}\n",
+                 max_elements);
   Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
   EXPECT_VALID(lib);
   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index ee37e15..1fde4da 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -91,33 +91,10 @@
   // Returns the current program counter.
   static uintptr_t GetProgramCounter();
 
-  // Not all platform support strndup.
-  static char* StrNDup(const char* s, intptr_t n);
-  static intptr_t StrNLen(const char* s, intptr_t n);
-
   // Print formatted output to stdout/stderr for debugging.
   static void Print(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
   static void PrintErr(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
   static void VFPrint(FILE* stream, const char* format, va_list args);
-  // Print formatted output info a buffer.
-  //
-  // Does not write more than size characters (including the trailing '\0').
-  //
-  // Returns the number of characters (excluding the trailing '\0')
-  // that would been written if the buffer had been big enough.  If
-  // the return value is greater or equal than the given size then the
-  // output has been truncated.  The return value is never negative.
-  //
-  // The buffer will always be terminated by a '\0', unless the buffer
-  // is of size 0.  The buffer might be NULL if the size is 0.
-  //
-  // This specification conforms to C99 standard which is implemented
-  // by glibc 2.1+ with one exception: the C99 standard allows a
-  // negative return value.  We will terminate the vm rather than let
-  // that occur.
-  static int SNPrint(char* str, size_t size, const char* format, ...)
-      PRINTF_ATTRIBUTE(3, 4);
-  static int VSNPrint(char* str, size_t size, const char* format, va_list args);
 
   // Allocate a string and print formatted output into the buffer.
   // Uses the zone for allocation if one if provided, and otherwise uses
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 01e4000..0b796ff 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -248,14 +248,6 @@
       __builtin_extract_return_addr(__builtin_return_address(0)));
 }
 
-char* OS::StrNDup(const char* s, intptr_t n) {
-  return strndup(s, n);
-}
-
-intptr_t OS::StrNLen(const char* s, intptr_t n) {
-  return strnlen(s, n);
-}
-
 uint16_t HostToBigEndian16(uint16_t value) {
   return htobe16(value);
 }
@@ -293,22 +285,6 @@
   fflush(stream);
 }
 
-int OS::SNPrint(char* str, size_t size, const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  int retval = VSNPrint(str, size, format, args);
-  va_end(args);
-  return retval;
-}
-
-int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
-  int retval = vsnprintf(str, size, format, args);
-  if (retval < 0) {
-    FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
-  }
-  return retval;
-}
-
 char* OS::SCreate(Zone* zone, const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -321,7 +297,7 @@
   // Measure.
   va_list measure_args;
   va_copy(measure_args, args);
-  intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
   va_end(measure_args);
 
   char* buffer;
@@ -335,7 +311,7 @@
   // Print.
   va_list print_args;
   va_copy(print_args, args);
-  VSNPrint(buffer, len + 1, format, print_args);
+  Utils::VSNPrint(buffer, len + 1, format, print_args);
   va_end(print_args);
   return buffer;
 }
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index abdae63..24a5608 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -176,14 +176,6 @@
       __builtin_extract_return_addr(__builtin_return_address(0)));
 }
 
-char* OS::StrNDup(const char* s, intptr_t n) {
-  return strndup(s, n);
-}
-
-intptr_t OS::StrNLen(const char* s, intptr_t n) {
-  return strnlen(s, n);
-}
-
 void OS::Print(const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -196,22 +188,6 @@
   fflush(stream);
 }
 
-int OS::SNPrint(char* str, size_t size, const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  int retval = VSNPrint(str, size, format, args);
-  va_end(args);
-  return retval;
-}
-
-int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
-  int retval = vsnprintf(str, size, format, args);
-  if (retval < 0) {
-    FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
-  }
-  return retval;
-}
-
 char* OS::SCreate(Zone* zone, const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -224,7 +200,7 @@
   // Measure.
   va_list measure_args;
   va_copy(measure_args, args);
-  intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
   va_end(measure_args);
 
   char* buffer;
@@ -238,7 +214,7 @@
   // Print.
   va_list print_args;
   va_copy(print_args, args);
-  VSNPrint(buffer, len + 1, format, print_args);
+  Utils::VSNPrint(buffer, len + 1, format, print_args);
   va_end(print_args);
   return buffer;
 }
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index e1b1621..4a4bf3d 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -258,14 +258,6 @@
       __builtin_extract_return_addr(__builtin_return_address(0)));
 }
 
-char* OS::StrNDup(const char* s, intptr_t n) {
-  return strndup(s, n);
-}
-
-intptr_t OS::StrNLen(const char* s, intptr_t n) {
-  return strnlen(s, n);
-}
-
 void OS::Print(const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -278,23 +270,6 @@
   fflush(stream);
 }
 
-int OS::SNPrint(char* str, size_t size, const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  int retval = VSNPrint(str, size, format, args);
-  va_end(args);
-  return retval;
-}
-
-int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
-  MSAN_UNPOISON(str, size);
-  int retval = vsnprintf(str, size, format, args);
-  if (retval < 0) {
-    FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
-  }
-  return retval;
-}
-
 char* OS::SCreate(Zone* zone, const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -307,7 +282,7 @@
   // Measure.
   va_list measure_args;
   va_copy(measure_args, args);
-  intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
   va_end(measure_args);
 
   char* buffer;
@@ -321,7 +296,7 @@
   // Print.
   va_list print_args;
   va_copy(print_args, args);
-  VSNPrint(buffer, len + 1, format, print_args);
+  Utils::VSNPrint(buffer, len + 1, format, print_args);
   va_end(print_args);
   return buffer;
 }
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index 36660e3..0d52e03 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -212,44 +212,6 @@
       __builtin_extract_return_addr(__builtin_return_address(0)));
 }
 
-char* OS::StrNDup(const char* s, intptr_t n) {
-// strndup has only been added to Mac OS X in 10.7. We are supplying
-// our own copy here if needed.
-#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) ||                 \
-    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
-  intptr_t len = strlen(s);
-  if ((n < 0) || (len < 0)) {
-    return NULL;
-  }
-  if (n < len) {
-    len = n;
-  }
-  char* result = reinterpret_cast<char*>(malloc(len + 1));
-  if (result == NULL) {
-    return NULL;
-  }
-  result[len] = '\0';
-  return reinterpret_cast<char*>(memmove(result, s, len));
-#else   // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
-  return strndup(s, n);
-#endif  // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
-}
-
-intptr_t OS::StrNLen(const char* s, intptr_t n) {
-// strnlen has only been added to Mac OS X in 10.7. We are supplying
-// our own copy here if needed.
-#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) ||                 \
-    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
-  intptr_t len = 0;
-  while ((len <= n) && (*s != '\0')) {
-    s++;
-    len++;
-  }
-  return len;
-#else   // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
-  return strnlen(s, n);
-#endif  // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
-}
 
 void OS::Print(const char* format, ...) {
 #if HOST_OS_IOS
@@ -270,22 +232,6 @@
   fflush(stream);
 }
 
-int OS::SNPrint(char* str, size_t size, const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  int retval = VSNPrint(str, size, format, args);
-  va_end(args);
-  return retval;
-}
-
-int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
-  int retval = vsnprintf(str, size, format, args);
-  if (retval < 0) {
-    FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
-  }
-  return retval;
-}
-
 char* OS::SCreate(Zone* zone, const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -298,7 +244,7 @@
   // Measure.
   va_list measure_args;
   va_copy(measure_args, args);
-  intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
   va_end(measure_args);
 
   char* buffer;
@@ -312,7 +258,7 @@
   // Print.
   va_list print_args;
   va_copy(print_args, args);
-  VSNPrint(buffer, len + 1, format, print_args);
+  Utils::VSNPrint(buffer, len + 1, format, print_args);
   va_end(print_args);
   return buffer;
 }
diff --git a/runtime/vm/os_test.cc b/runtime/vm/os_test.cc
index 3967bf0..d8be0f7 100644
--- a/runtime/vm/os_test.cc
+++ b/runtime/vm/os_test.cc
@@ -24,16 +24,16 @@
 VM_UNIT_TEST_CASE(SNPrint) {
   char buffer[256];
   int length;
-  length = OS::SNPrint(buffer, 10, "%s", "foo");
+  length = Utils::SNPrint(buffer, 10, "%s", "foo");
   EXPECT_EQ(3, length);
   EXPECT_STREQ("foo", buffer);
-  length = OS::SNPrint(buffer, 3, "%s", "foo");
+  length = Utils::SNPrint(buffer, 3, "%s", "foo");
   EXPECT_EQ(3, length);
   EXPECT_STREQ("fo", buffer);
-  length = OS::SNPrint(buffer, 256, "%s%c%d", "foo", 'Z', 42);
+  length = Utils::SNPrint(buffer, 256, "%s%c%d", "foo", 'Z', 42);
   EXPECT_EQ(6, length);
   EXPECT_STREQ("fooZ42", buffer);
-  length = OS::SNPrint(NULL, 0, "foo");
+  length = Utils::SNPrint(NULL, 0, "foo");
   EXPECT_EQ(3, length);
 }
 
@@ -41,7 +41,7 @@
 VM_UNIT_TEST_CASE(SNPrint_BadArgs) {
   int width = kMaxInt32;
   int num = 7;
-  OS::SNPrint(NULL, 0, "%*d%*d", width, num, width, num);
+  Utils::SNPrint(NULL, 0, "%*d%*d", width, num, width, num);
 }
 
 VM_UNIT_TEST_CASE(OsFuncs) {
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index 75c2245..d8a0a9a 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -237,26 +237,6 @@
   return reinterpret_cast<uintptr_t>(_ReturnAddress());
 }
 
-char* OS::StrNDup(const char* s, intptr_t n) {
-  intptr_t len = strlen(s);
-  if ((n < 0) || (len < 0)) {
-    return NULL;
-  }
-  if (n < len) {
-    len = n;
-  }
-  char* result = reinterpret_cast<char*>(malloc(len + 1));
-  if (result == NULL) {
-    return NULL;
-  }
-  result[len] = '\0';
-  return reinterpret_cast<char*>(memmove(result, s, len));
-}
-
-intptr_t OS::StrNLen(const char* s, intptr_t n) {
-  return strnlen(s, n);
-}
-
 void OS::Print(const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -269,48 +249,6 @@
   fflush(stream);
 }
 
-int OS::SNPrint(char* str, size_t size, const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  int retval = VSNPrint(str, size, format, args);
-  va_end(args);
-  return retval;
-}
-
-int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
-  if (str == NULL || size == 0) {
-    int retval = _vscprintf(format, args);
-    if (retval < 0) {
-      FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
-    }
-    return retval;
-  }
-  va_list args_copy;
-  va_copy(args_copy, args);
-  int written = _vsnprintf(str, size, format, args_copy);
-  va_end(args_copy);
-  if (written < 0) {
-    // _vsnprintf returns -1 if the number of characters to be written is
-    // larger than 'size', so we call _vscprintf which returns the number
-    // of characters that would have been written.
-    va_list args_retry;
-    va_copy(args_retry, args);
-    written = _vscprintf(format, args_retry);
-    if (written < 0) {
-      FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
-    }
-    va_end(args_retry);
-  }
-  // Make sure to zero-terminate the string if the output was
-  // truncated or if there was an error.
-  // The static cast is safe here as we have already determined that 'written'
-  // is >= 0.
-  if (static_cast<size_t>(written) >= size) {
-    str[size - 1] = '\0';
-  }
-  return written;
-}
-
 char* OS::SCreate(Zone* zone, const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -323,7 +261,7 @@
   // Measure.
   va_list measure_args;
   va_copy(measure_args, args);
-  intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
   va_end(measure_args);
 
   char* buffer;
@@ -337,7 +275,7 @@
   // Print.
   va_list print_args;
   va_copy(print_args, args);
-  VSNPrint(buffer, len + 1, format, print_args);
+  Utils::VSNPrint(buffer, len + 1, format, print_args);
   va_end(print_args);
   return buffer;
 }
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index a144a86..7568b96 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -1752,7 +1752,7 @@
   for (; i < desc.PositionalCount(); ++i) {
     ParamDesc p;
     char name[64];
-    OS::SNPrint(name, 64, ":p%" Pd, i);
+    Utils::SNPrint(name, 64, ":p%" Pd, i);
     p.name = &String::ZoneHandle(Z, Symbols::New(T, name));
     p.type = &Object::dynamic_type();
     params.parameters->Add(p);
@@ -11120,7 +11120,7 @@
 LocalVariable* Parser::CreateTempConstVariable(TokenPosition token_pos,
                                                const char* s) {
   char name[64];
-  OS::SNPrint(name, 64, ":%s%" Pd "", s, token_pos.value());
+  Utils::SNPrint(name, 64, ":%s%" Pd "", s, token_pos.value());
   LocalVariable* temp = new (Z) LocalVariable(
       token_pos, token_pos, String::ZoneHandle(Z, Symbols::New(T, name)),
       Object::dynamic_type());
diff --git a/runtime/vm/parser_test.cc b/runtime/vm/parser_test.cc
index 02c0854..bd06546 100644
--- a/runtime/vm/parser_test.cc
+++ b/runtime/vm/parser_test.cc
@@ -219,8 +219,8 @@
     const char* function_str =
         String::Handle(frame->function().QualifiedUserVisibleName())
             .ToCString();
-    pos += OS::SNPrint(pos, (kBufferLen - (pos - buffer)), "%s\n%s",
-                       function_str, var_str);
+    pos += Utils::SNPrint(pos, (kBufferLen - (pos - buffer)), "%s\n%s",
+                          function_str, var_str);
     delete[] var_str;
   }
   pos[0] = '\0';
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 7e2e787..9cdfa47 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -339,8 +339,8 @@
 void ProfileCode::GenerateAndSetSymbolName(const char* prefix) {
   const intptr_t kBuffSize = 512;
   char buff[kBuffSize];
-  OS::SNPrint(&buff[0], kBuffSize - 1, "%s [%" Px ", %" Px ")", prefix, start(),
-              end());
+  Utils::SNPrint(&buff[0], kBuffSize - 1, "%s [%" Px ", %" Px ")", prefix,
+                 start(), end());
   SetName(buff);
 }
 
diff --git a/runtime/vm/resolver_test.cc b/runtime/vm/resolver_test.cc
index a6f5597..7df722a 100644
--- a/runtime/vm/resolver_test.cc
+++ b/runtime/vm/resolver_test.cc
@@ -24,17 +24,17 @@
 
   // Setup a dart class and function.
   char script_chars[1024];
-  OS::SNPrint(script_chars, sizeof(script_chars),
-              "class Base {\n"
-              "  dynCall() { return 3; }\n"
-              "  static statCall() { return 4; }\n"
-              "\n"
-              "}\n"
-              "class %s extends Base {\n"
-              "  %s %s(String s, int i) { return i; }\n"
-              "}\n",
-              test_class_name, is_static ? "static" : "",
-              test_static_function_name);
+  Utils::SNPrint(script_chars, sizeof(script_chars),
+                 "class Base {\n"
+                 "  dynCall() { return 3; }\n"
+                 "  static statCall() { return 4; }\n"
+                 "\n"
+                 "}\n"
+                 "class %s extends Base {\n"
+                 "  %s %s(String s, int i) { return i; }\n"
+                 "}\n",
+                 test_class_name, is_static ? "static" : "",
+                 test_static_function_name);
 
   String& url = String::Handle(
       zone, is_static ? String::New("dart-test:DartStaticResolve")
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index 1b146cb..80d6add 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -838,8 +838,9 @@
           char utf8_char[5];
           int len = Utf8::Encode(c0_, utf8_char);
           utf8_char[len] = '\0';
-          OS::SNPrint(msg, sizeof(msg), "unexpected character: '%s' (U+%04X)\n",
-                      utf8_char, c0_);
+          Utils::SNPrint(msg, sizeof(msg),
+                         "unexpected character: '%s' (U+%04X)\n", utf8_char,
+                         c0_);
           ErrorMsg(msg);
           ReadChar();
         }
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 46424c7..3a53ad4 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -99,13 +99,13 @@
 static RawArray* EvalF(Dart_Handle lib, const char* fmt, ...) {
   va_list args;
   va_start(args, fmt);
-  intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, fmt, args);
   va_end(args);
 
   char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
   va_list args2;
   va_start(args2, fmt);
-  OS::VSNPrint(buffer, (len + 1), fmt, args2);
+  Utils::VSNPrint(buffer, (len + 1), fmt, args2);
   va_end(args2);
 
   return Eval(lib, buffer);
@@ -280,9 +280,9 @@
     // Only perform a partial match.
     const intptr_t kBufferSize = 512;
     char buffer[kBufferSize];
-    OS::SNPrint(buffer, kBufferSize - 1,
-                "\"fixedId\":true,\"id\":\"code\\/%" Px64 "-%" Px "\",",
-                compile_timestamp, entry);
+    Utils::SNPrint(buffer, kBufferSize - 1,
+                   "\"fixedId\":true,\"id\":\"code\\/%" Px64 "-%" Px "\",",
+                   compile_timestamp, entry);
     EXPECT_SUBSTRING(buffer, handler.msg());
   }
 
@@ -601,12 +601,12 @@
     uword addr = start_addr + offset;
     char buf[1024];
     bool ref = offset % 2 == 0;
-    OS::SNPrint(buf, sizeof(buf),
-                (ref ? "[0, port, '0', '_getObjectByAddress', "
-                       "['address', 'ref'], ['%" Px "', 'true']]"
-                     : "[0, port, '0', '_getObjectByAddress', "
-                       "['address'], ['%" Px "']]"),
-                addr);
+    Utils::SNPrint(buf, sizeof(buf),
+                   (ref ? "[0, port, '0', '_getObjectByAddress', "
+                          "['address', 'ref'], ['%" Px "', 'true']]"
+                        : "[0, port, '0', '_getObjectByAddress', "
+                          "['address'], ['%" Px "']]"),
+                   addr);
     service_msg = Eval(lib, buf);
     HandleIsolateMessage(isolate, service_msg);
     EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index a03d79f..a906dd7 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -616,9 +616,9 @@
     if (!obj_.IsError()) {
       const intptr_t kMessageBufferSize = 128;
       char message_buffer[kMessageBufferSize];
-      OS::SNPrint(message_buffer, kMessageBufferSize,
-                  "Invalid object %s found in script snapshot",
-                  obj_.ToCString());
+      Utils::SNPrint(message_buffer, kMessageBufferSize,
+                     "Invalid object %s found in script snapshot",
+                     obj_.ToCString());
       const String& msg = String::Handle(String::New(message_buffer));
       obj_ = ApiError::New(msg);
     }
@@ -636,9 +636,9 @@
   if (PendingBytes() < version_len) {
     const intptr_t kMessageBufferSize = 128;
     char message_buffer[kMessageBufferSize];
-    OS::SNPrint(message_buffer, kMessageBufferSize,
-                "No full snapshot version found, expected '%s'",
-                expected_version);
+    Utils::SNPrint(message_buffer, kMessageBufferSize,
+                   "No full snapshot version found, expected '%s'",
+                   expected_version);
     // This can also fail while bringing up the VM isolate, so make sure to
     // allocate the error message in old space.
     const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
@@ -650,11 +650,11 @@
   if (strncmp(version, expected_version, version_len)) {
     const intptr_t kMessageBufferSize = 256;
     char message_buffer[kMessageBufferSize];
-    char* actual_version = OS::StrNDup(version, version_len);
-    OS::SNPrint(message_buffer, kMessageBufferSize,
-                "Wrong %s snapshot version, expected '%s' found '%s'",
-                (Snapshot::IsFull(kind_)) ? "full" : "script", expected_version,
-                actual_version);
+    char* actual_version = Utils::StrNDup(version, version_len);
+    Utils::SNPrint(message_buffer, kMessageBufferSize,
+                   "Wrong %s snapshot version, expected '%s' found '%s'",
+                   (Snapshot::IsFull(kind_)) ? "full" : "script",
+                   expected_version, actual_version);
     free(actual_version);
     // This can also fail while bringing up the VM isolate, so make sure to
     // allocate the error message in old space.
@@ -669,17 +669,17 @@
 
   const char* features = reinterpret_cast<const char*>(CurrentBufferAddress());
   ASSERT(features != NULL);
-  intptr_t buffer_len = OS::StrNLen(features, PendingBytes());
+  intptr_t buffer_len = Utils::StrNLen(features, PendingBytes());
   if ((buffer_len != expected_len) ||
       strncmp(features, expected_features, expected_len)) {
     const intptr_t kMessageBufferSize = 256;
     char message_buffer[kMessageBufferSize];
     char* actual_features =
-        OS::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
-    OS::SNPrint(message_buffer, kMessageBufferSize,
-                "Snapshot not compatible with the current VM configuration: "
-                "the snapshot requires '%s' but the VM has '%s'",
-                actual_features, expected_features);
+        Utils::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
+    Utils::SNPrint(message_buffer, kMessageBufferSize,
+                   "Snapshot not compatible with the current VM configuration: "
+                   "the snapshot requires '%s' but the VM has '%s'",
+                   actual_features, expected_features);
     free(const_cast<char*>(expected_features));
     free(actual_features);
     // This can also fail while bringing up the VM isolate, so make sure to
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index f14c39b..2e8c7db 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -654,12 +654,12 @@
                                   va_list args) {
   va_list args_copy;
   va_copy(args_copy, args);
-  intptr_t len = OS::VSNPrint(NULL, 0, format, args_copy);
+  intptr_t len = Utils::VSNPrint(NULL, 0, format, args_copy);
   va_end(args_copy);
 
   Zone* zone = Thread::Current()->zone();
   char* buffer = zone->Alloc<char>(len + 1);
-  OS::VSNPrint(buffer, (len + 1), format, args);
+  Utils::VSNPrint(buffer, (len + 1), format, args);
 
   return Symbols::New(thread, buffer);
 }
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 492e26d..b00cd0a 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -502,17 +502,17 @@
   const intptr_t kLoopCount = 1234567890;
 #endif  // USING_SIMULATOR
   char buffer[1024];
-  OS::SNPrint(buffer, sizeof(buffer),
-              "import 'dart:developer';\n"
-              "int dummy = 0;\n"
-              "main() {\n"
-              "  new UserTag('foo').makeCurrent();\n"
-              "  for (dummy = 0; dummy < %" Pd
-              "; ++dummy) {\n"
-              "    dummy += (dummy & 1);\n"
-              "  }\n"
-              "}\n",
-              kLoopCount);
+  Utils::SNPrint(buffer, sizeof(buffer),
+                 "import 'dart:developer';\n"
+                 "int dummy = 0;\n"
+                 "main() {\n"
+                 "  new UserTag('foo').makeCurrent();\n"
+                 "  for (dummy = 0; dummy < %" Pd
+                 "; ++dummy) {\n"
+                 "    dummy += (dummy & 1);\n"
+                 "  }\n"
+                 "}\n",
+                 kLoopCount);
   Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
   EXPECT_VALID(lib);
   Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index ce1530a..be11b0e 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -355,11 +355,11 @@
   ASSERT(i < length_);
   va_list args2;
   va_copy(args2, args);
-  intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
+  intptr_t len = Utils::VSNPrint(NULL, 0, fmt, args);
   va_end(args);
 
   char* buffer = reinterpret_cast<char*>(malloc(len + 1));
-  OS::VSNPrint(buffer, (len + 1), fmt, args2);
+  Utils::VSNPrint(buffer, (len + 1), fmt, args2);
   va_end(args2);
 
   SetArgument(i, name, buffer);
diff --git a/runtime/vm/timeline_android.cc b/runtime/vm/timeline_android.cc
index 44e1cb0..b43c508 100644
--- a/runtime/vm/timeline_android.cc
+++ b/runtime/vm/timeline_android.cc
@@ -49,17 +49,17 @@
   int64_t pid = OS::ProcessId();
   switch (event->event_type()) {
     case TimelineEvent::kBegin: {
-      length = OS::SNPrint(buffer, buffer_size, "B|%" Pd64 "|%s", pid,
-                           event->label());
+      length = Utils::SNPrint(buffer, buffer_size, "B|%" Pd64 "|%s", pid,
+                              event->label());
     } break;
     case TimelineEvent::kEnd: {
-      length = OS::SNPrint(buffer, buffer_size, "E");
+      length = Utils::SNPrint(buffer, buffer_size, "E");
     } break;
     case TimelineEvent::kCounter: {
       if (event->arguments_length() > 0) {
         // We only report the first counter value.
-        length = OS::SNPrint(buffer, buffer_size, "C|%" Pd64 "|%s|%s", pid,
-                             event->label(), event->arguments()[0].value);
+        length = Utils::SNPrint(buffer, buffer_size, "C|%" Pd64 "|%s|%s", pid,
+                                event->label(), event->arguments()[0].value);
       }
     }
     default:
diff --git a/runtime/vm/timeline_linux.cc b/runtime/vm/timeline_linux.cc
index 0ced816..b244ecd 100644
--- a/runtime/vm/timeline_linux.cc
+++ b/runtime/vm/timeline_linux.cc
@@ -49,17 +49,17 @@
   int64_t pid = OS::ProcessId();
   switch (event->event_type()) {
     case TimelineEvent::kBegin: {
-      length = OS::SNPrint(buffer, buffer_size, "B|%" Pd64 "|%s", pid,
-                           event->label());
+      length = Utils::SNPrint(buffer, buffer_size, "B|%" Pd64 "|%s", pid,
+                              event->label());
     } break;
     case TimelineEvent::kEnd: {
-      length = OS::SNPrint(buffer, buffer_size, "E");
+      length = Utils::SNPrint(buffer, buffer_size, "E");
     } break;
     case TimelineEvent::kCounter: {
       if (event->arguments_length() > 0) {
         // We only report the first counter value.
-        length = OS::SNPrint(buffer, buffer_size, "C|%" Pd64 "|%s|%s", pid,
-                             event->label(), event->arguments()[0].value);
+        length = Utils::SNPrint(buffer, buffer_size, "C|%" Pd64 "|%s|%s", pid,
+                                event->label(), event->arguments()[0].value);
       }
     }
     default:
diff --git a/runtime/vm/uri.cc b/runtime/vm/uri.cc
index 0e93b57..67fbcbf 100644
--- a/runtime/vm/uri.cc
+++ b/runtime/vm/uri.cc
@@ -100,7 +100,7 @@
         buffer[buffer_pos] = escaped_value;
         buffer_pos++;
       } else {
-        OS::SNPrint(buffer + buffer_pos, 4, "%%%02X", escaped_value);
+        Utils::SNPrint(buffer + buffer_pos, 4, "%%%02X", escaped_value);
         buffer_pos += 3;
       }
       pos += 3;
@@ -114,7 +114,7 @@
         buffer_pos++;
       } else {
         // Escape funky characters.
-        OS::SNPrint(buffer + buffer_pos, 4, "%%%02X", c);
+        Utils::SNPrint(buffer + buffer_pos, 4, "%%%02X", c);
         buffer_pos += 3;
       }
       pos++;
diff --git a/runtime/vm/zone_text_buffer.cc b/runtime/vm/zone_text_buffer.cc
index 43a90e7..5754b11 100644
--- a/runtime/vm/zone_text_buffer.cc
+++ b/runtime/vm/zone_text_buffer.cc
@@ -25,7 +25,7 @@
   va_start(args, format);
   intptr_t remaining = capacity_ - length_;
   ASSERT(remaining >= 0);
-  intptr_t len = OS::VSNPrint(buffer_ + length_, remaining, format, args);
+  intptr_t len = Utils::VSNPrint(buffer_ + length_, remaining, format, args);
   va_end(args);
   if (len >= remaining) {
     EnsureCapacity(len);
@@ -33,7 +33,8 @@
     ASSERT(remaining > len);
     va_list args2;
     va_start(args2, format);
-    intptr_t len2 = OS::VSNPrint(buffer_ + length_, remaining, format, args2);
+    intptr_t len2 =
+        Utils::VSNPrint(buffer_ + length_, remaining, format, args2);
     va_end(args2);
     ASSERT(len == len2);
   }
diff --git a/samples/sample_extension/test/sample_extension_test_helper.dart b/samples/sample_extension/test/sample_extension_test_helper.dart
index 08d5191..6141a88 100644
--- a/samples/sample_extension/test/sample_extension_test_helper.dart
+++ b/samples/sample_extension/test/sample_extension_test_helper.dart
@@ -33,7 +33,7 @@
   }
 }
 
-Future run(String program, List arguments) async {
+Future run(String program, List<String> arguments) async {
   print("+ $program ${arguments.join(' ')}");
   ProcessResult result = await Process.run(program, arguments);
   if (result.exitCode != 0) {
diff --git a/samples/samples.status b/samples/samples.status
index f72813e..3e8b4db 100644
--- a/samples/samples.status
+++ b/samples/samples.status
@@ -28,11 +28,6 @@
 [ $compiler == dart2js && $runtime == none ]
 *: Fail, Pass # TODO(ahe): Triage these tests.
 
-[ $compiler == dartk && $strong ]
-sample_extension/test/sample_extension_app_snapshot_test: RuntimeError
-sample_extension/test/sample_extension_script_snapshot_test: RuntimeError
-sample_extension/test/sample_extension_test: RuntimeError
-
 [ $compiler == none && $mode == debug && $runtime == vm && $system == windows ]
 sample_extension/test/sample_extension_app_snapshot_test: Pass, RuntimeError # Issue 28842
 
diff --git a/sdk/api_readme.md b/sdk/api_readme.md
index c723990..3e5990dd 100644
--- a/sdk/api_readme.md
+++ b/sdk/api_readme.md
@@ -1,31 +1,32 @@
-Welcome to the Dart API reference documentation, covering the official Dart API
+Welcome to the Dart API reference documentation, covering the core Dart API
 libraries. Some of the most fundamental Dart libraries include:
    
-  * [dart:core](dart-core/dart-core-library.html): Core functionality such as strings, numbers, collections, errors, dates, and URIs.
-  * [dart:html](dart-html/dart-html-library.html): DOM manipulation for web apps.
-  * [dart:io](dart-io/dart-io-library.html): I/O for command-line apps.
+  * [dart:core](dart-core/dart-core-library.html): Core functionality such as
+    strings, numbers, collections, errors, dates, and URIs.
+  * [dart:html](dart-html/dart-html-library.html): DOM manipulation for web apps
+    (available only to web apps).
+  * [dart:io](dart-io/dart-io-library.html): I/O for non-web apps.
   
 Except for `dart:core`, you must import a library before you can use it. Here's
-an example of importing `dart:html` and `dart:math`:
+an example of importing `dart:async` and `dart:math`:
 
 ```dart
-import 'dart:html';
+import 'dart:async';
 import 'dart:math';
 ```
 
-You can install more libraries using the pub package manager. For information
-on finding, using, and publishing libraries with pub, see 
-[pub.dartlang.org](https://pub.dartlang.org).
+You can install more libraries using the
+[pub package manager](https://www.dartlang.org/tools/pub).
   
 The main site for learning and using Dart is
-[www.dartlang.org](https://www.dartlang.org). Check out these additional pages:
+[www.dartlang.org](https://www.dartlang.org). Check out these pages:
   
-  * [Tutorials](https://www.dartlang.org/docs/tutorials/)
-  * [Programmer's Guide](https://www.dartlang.org/docs/)
-  * [Samples](https://www.dartlang.org/samples/)
-  * [A Tour of the Dart Libraries](https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html)
+  * [Get started](https://www.dartlang.org/guides/get-started)
+  * [Language tour](https://www.dartlang.org/guides/language/language-tour)
+  * [Library tour](https://www.dartlang.org/guides/libraries/library-tour)
+  * [Sample code](https://www.dartlang.org/samples)
   
-This API reference is automatically generated from the source code in the
-[Dart project](https://github.com/dart-lang/sdk). If you'd like to contribute to
-this documentation, see
+This API reference is automatically generated from source code in the [Dart
+SDK project](https://github.com/dart-lang/sdk).
+If you'd like to give feedback or edit this documentation, see
 [Contributing](https://github.com/dart-lang/sdk/wiki/Contributing).
diff --git a/sdk/lib/_internal/js_runtime/lib/js_array.dart b/sdk/lib/_internal/js_runtime/lib/js_array.dart
index e8dbab7..563297a 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_array.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_array.dart
@@ -635,17 +635,10 @@
     return new ListMapView<E>(this);
   }
 
-  Iterable<E> followedBy(Iterable<E> other) sync* {
-    yield* this;
-    yield* other;
-  }
+  Iterable<E> followedBy(Iterable<E> other) =>
+      new FollowedByIterable<E>.firstEfficient(this, other);
 
-  Iterable<T> whereType<T>() sync* {
-    for (var i = 0; i < this.length; i++) {
-      var element = this[i];
-      if (element is T) yield element;
-    }
-  }
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
 
   List<E> operator +(List<E> other) {
     int totalLength = this.length + other.length;
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 9d06d03..e564c8c 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1273,9 +1273,12 @@
    * If an error occurs, or if this stream ends without finding a match and
    * with no [orElse] function provided,
    * the returned future is completed with an error.
+   *
+   * The [defaultValue] parameter is deprecated, and [orElse] should be used
+   * instead.
    */
   Future<T> firstWhere(bool test(T element),
-      {dynamic defaultValue(), T orElse()}) {
+      {@deprecated dynamic defaultValue(), T orElse()}) {
     _Future<T> future = new _Future();
     StreamSubscription subscription;
     subscription = this.listen(
@@ -1315,9 +1318,12 @@
    * instead of the first.
    * That means that a non-error result cannot be provided before this stream
    * is done.
+   *
+   * The [defaultValue] parameter is deprecated, and [orElse] should be used
+   * instead.
    */
   Future<T> lastWhere(bool test(T element),
-      {dynamic defaultValue(), T orElse()}) {
+      {@deprecated dynamic defaultValue(), T orElse()}) {
     _Future<T> future = new _Future();
     T result = null;
     bool foundResult = false;
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index 7d028a4..67bfdd8 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.dart
@@ -26,18 +26,19 @@
 
   Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
 
-  Iterable<T> whereType<T>() sync* {
-    for (Object element in this) if (element is T) yield element;
-  }
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
 
   Iterable<T> expand<T>(Iterable<T> f(E element)) =>
       new ExpandIterable<E, T>(this, f);
 
-  Iterable<E> followedBy(Iterable<E> other) sync* {
-    // TODO(lrn): Optimize this (some operations can be more efficient,
-    // and the concatenation has efficient length if the source iterables do).
-    yield* this;
-    yield* other;
+  Iterable<E> followedBy(Iterable<E> other) {
+    // Type workaround because IterableMixin<E> doesn't promote
+    // to EfficientLengthIterable<E>.
+    Iterable<E> self = this;
+    if (self is EfficientLengthIterable<E>) {
+      return new FollowedByIterable<E>.firstEfficient(self, other);
+    }
+    return new FollowedByIterable<E>(this, other);
   }
 
   bool contains(Object element) {
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index 57e5ef4..2a5792d 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -59,12 +59,8 @@
 
   E elementAt(int index) => this[index];
 
-  Iterable<E> followedBy(Iterable<E> other) sync* {
-    for (var i = 0; i < length; i++) {
-      yield this[i];
-    }
-    yield* other;
-  }
+  Iterable<E> followedBy(Iterable<E> other) =>
+      new FollowedByIterable<E>.firstEfficient(this, other);
 
   void forEach(void action(E element)) {
     int length = this.length;
@@ -195,9 +191,7 @@
 
   Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test);
 
-  Iterable<T> whereType<T>() sync* {
-    for (var element in this) if (element is T) yield (element as T);
-  }
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
 
   Iterable<T> map<T>(T f(E element)) => new MappedListIterable<E, T>(this, f);
 
diff --git a/sdk/lib/collection/set.dart b/sdk/lib/collection/set.dart
index 5d51dff..71bf718 100644
--- a/sdk/lib/collection/set.dart
+++ b/sdk/lib/collection/set.dart
@@ -58,16 +58,10 @@
 
   Set<R> retype<R>() => Set.castFrom<E, R>(this);
 
-  Iterable<E> followedBy(Iterable<E> other) sync* {
-    // TODO(lrn): Optimize this (some operations can be more efficient,
-    // and the concatenation has efficient length if the source iterables do).
-    yield* this;
-    yield* other;
-  }
+  Iterable<E> followedBy(Iterable<E> other) =>
+      new FollowedByIterable<E>.firstEfficient(this, other);
 
-  Iterable<T> whereType<T>() sync* {
-    for (Object element in this) if (element is T) yield element;
-  }
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
 
   void clear() {
     removeAll(toList());
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index d3cc85b..410b57d 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -186,11 +186,11 @@
    * and, after that, the elements of [other], in the same order as in the
    * original iterables.
    */
-  Iterable<E> followedBy(Iterable<E> other) sync* {
-    // TODO(lrn): Optimize this (some operations can be more efficient,
-    // and the concatenation has efficient length if the source iterables do).
-    yield* this;
-    yield* other;
+  Iterable<E> followedBy(Iterable<E> other) {
+    if (this is EfficientLengthIterable<E>) {
+      return new FollowedByIterable<E>.firstEfficient(this, other);
+    }
+    return new FollowedByIterable<E>(this, other);
   }
 
   /**
@@ -236,9 +236,7 @@
    * the returned [Iterable] may yield different results,
    * if the underlying elements change between iterations.
    */
-  Iterable<T> whereType<T>() sync* {
-    for (var element in this) if (element is T) yield (element as T);
-  }
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
 
   /**
    * Expands each element of this [Iterable] into zero or more elements.
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index b3d29f9..82e2175 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -29,7 +29,6 @@
 import 'dart:_internal' hide Symbol;
 import 'dart:html_common';
 import 'dart:indexed_db';
-import 'dart:isolate';
 import "dart:convert";
 import 'dart:math';
 import 'dart:_native_typed_data';
@@ -115,18 +114,6 @@
   HtmlElement.created() : super.created();
 }
 
-/**
- * Spawn a DOM isolate using the given URI in the same window.
- * This isolate is not concurrent.  It runs on the browser thread
- * with full access to the DOM.
- * Note: this API is still evolving and may move to dart:isolate.
- */
-@Experimental()
-Future<Isolate> spawnDomUri(Uri uri, List<String> args, message) {
-  // TODO(17738): Implement this.
-  throw new UnimplementedError();
-}
-
 createCustomUpgrader(Type customElementClass, $this) => $this;
 
 /**
diff --git a/sdk/lib/internal/iterable.dart b/sdk/lib/internal/iterable.dart
index d8941c9..1c11e53 100644
--- a/sdk/lib/internal/iterable.dart
+++ b/sdk/lib/internal/iterable.dart
@@ -767,6 +767,125 @@
   E get current => null;
 }
 
+class FollowedByIterable<E> extends Iterable<E> {
+  final Iterable<E> _first;
+  final Iterable<E> _second;
+  FollowedByIterable(this._first, this._second);
+
+  factory FollowedByIterable.firstEfficient(
+      EfficientLengthIterable<E> first, Iterable<E> second) {
+    if (second is EfficientLengthIterable<E>) {
+      return new EfficientLengthFollowedByIterable<E>(first, second);
+    }
+    return new FollowedByIterable<E>(first, second);
+  }
+
+  Iterator<E> get iterator => new FollowedByIterator(_first, _second);
+
+  int get length => _first.length + _second.length;
+  bool get isEmpty => _first.isEmpty && _second.isEmpty;
+  bool get isNotEmpty => _first.isNotEmpty || _second.isNotEmpty;
+
+  // May be more efficient if either iterable is a Set.
+  bool contains(Object value) =>
+      _first.contains(value) || _second.contains(value);
+
+  E get first {
+    var iterator = _first.iterator;
+    if (iterator.moveNext()) return iterator.current;
+    return _second.first;
+  }
+
+  E get last {
+    var iterator = _second.iterator;
+    if (iterator.moveNext()) {
+      E last = iterator.current;
+      while (iterator.moveNext()) last = iterator.current;
+      return last;
+    }
+    return _first.last;
+  }
+
+  // If linear sequences of `followedBy` becomes an issue, we can flatten
+  // into a list of iterables instead of a tree or spine.
+}
+
+class EfficientLengthFollowedByIterable<E> extends FollowedByIterable<E>
+    implements EfficientLengthIterable<E> {
+  EfficientLengthFollowedByIterable(
+      EfficientLengthIterable<E> first, EfficientLengthIterable<E> second)
+      : super(first, second);
+
+  Iterable<E> skip(int count) {
+    int firstLength = _first.length;
+    if (count >= firstLength) return _second.skip(count - firstLength);
+    return new EfficientLengthFollowedByIterable<E>(
+        _first.skip(count), _second);
+  }
+
+  Iterable<E> take(int count) {
+    int firstLength = _first.length;
+    if (count <= firstLength) return _first.take(count);
+    return new EfficientLengthFollowedByIterable<E>(
+        _first, _second.take(count - firstLength));
+  }
+
+  E elementAt(int index) {
+    int firstLength = _first.length;
+    if (index < firstLength) return _first.elementAt(index);
+    return _second.elementAt(index - firstLength);
+  }
+
+  E get first {
+    if (_first.isNotEmpty) return _first.first;
+    return _second.first;
+  }
+
+  E get last {
+    if (_second.isNotEmpty) return _second.last;
+    return _first.last;
+  }
+}
+
+class FollowedByIterator<E> implements Iterator<E> {
+  Iterator<E> _currentIterator;
+  Iterable<E> _nextIterable;
+
+  FollowedByIterator(Iterable<E> first, this._nextIterable)
+      : _currentIterator = first.iterator;
+
+  bool moveNext() {
+    if (_currentIterator.moveNext()) return true;
+    if (_nextIterable != null) {
+      _currentIterator = _nextIterable.iterator;
+      _nextIterable = null;
+      return _currentIterator.moveNext();
+    }
+    return false;
+  }
+
+  E get current => _currentIterator.current;
+}
+
+class WhereTypeIterable<T> extends Iterable<T> {
+  final Iterable<Object> _source;
+  WhereTypeIterable(this._source);
+  Iterator<T> get iterator => new WhereTypeIterator<T>(_source.iterator);
+}
+
+class WhereTypeIterator<T> implements Iterator<T> {
+  final Iterator<Object> _source;
+  WhereTypeIterator(this._source);
+  bool moveNext() {
+    while (_source.moveNext()) {
+      if (_source.current is T) return true;
+    }
+    return false;
+  }
+
+  T get current => _source.current;
+}
+
 /**
  * Creates errors throw by [Iterable] when the element count is wrong.
  */
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index ad7e28d..0feb4ba 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -3,22 +3,25 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /**
- * File, socket, HTTP, and other I/O support for server applications.
+ * File, socket, HTTP, and other I/O support for non-web applications.
  *
- * The I/O library is used for Dart server applications,
- * which run on a stand-alone Dart VM from the command line.
- * *This library does not work in browser-based applications.*
+ * **Important:** Browser-based applications can't use this library.
+ * Only servers, command-line scripts, and Flutter mobile apps can import
+ * and use dart:io.
  *
  * This library allows you to work with files, directories,
  * sockets, processes, HTTP servers and clients, and more.
+ * Many operations related to input and output are asynchronous
+ * and are handled using [Future]s or [Stream]s, both of which
+ * are defined in the [dart:async
+ * library](../dart-async/dart-async-library.html).
  *
- * To use this library in your code:
+ * To use the dart:io library in your code:
  *
  *     import 'dart:io';
  *
- * *Note:* Many operations related to input and output are asynchronous
- * and are handled using [Future]s or [Stream]s, both of which
- * are defined in the `dart:async` library.
+ * For an introduction to I/O in Dart, see the [dart:io library
+ * tour](https://www.dartlang.org/dart-vm/io-library-tour).
  *
  * ## File, Directory, and Link
  *
@@ -182,14 +185,6 @@
  * (the program blocks waiting for user to type information):
  *
  *      String inputText = stdin.readLineSync();
- *
- * ## Other resources
- *
- * For an introduction to I/O in Dart, see the [dart:io section of the library
- * tour](https://www.dartlang.org/docs/dart-up-and-running/ch03.html#dartio---io-for-command-line-apps).
- *
- * To learn more about I/O in Dart, refer to the [tutorial about writing
- * command-line apps](https://www.dartlang.org/docs/tutorials/cmdline/).
  */
 library dart.io;
 
diff --git a/sdk/lib/vmservice/message.dart b/sdk/lib/vmservice/message.dart
index e6083aa..83432dd 100644
--- a/sdk/lib/vmservice/message.dart
+++ b/sdk/lib/vmservice/message.dart
@@ -127,7 +127,7 @@
   }
 
   dynamic forwardToJson([Map overloads]) {
-    var json = {'jsonrpc': '2.0', 'id': serial};
+    Map<dynamic, dynamic> json = {'jsonrpc': '2.0', 'id': serial};
     switch (type) {
       case MessageType.Request:
       case MessageType.Notification:
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index e4570b3..5b34f75 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -2,19 +2,6 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-[ $compiler == dartk ]
-Language/Expressions/Instance_Creation/Const/canonicalized_t05: RuntimeError
-Language/Expressions/Object_Identity/string_t01: RuntimeError
-Language/Expressions/Strings/adjacent_strings_t02: RuntimeError
-Language/Metadata/before_type_param_t01: RuntimeError
-LibTest/isolate/Isolate/spawnUri_A01_t03: Pass, Timeout
-
-[ $compiler == dartkp ]
-Language/Classes/definition_t23: RuntimeError # New entries after going from kernel-service to batch-mode compilation. Please investigate.
-Language/Mixins/Mixin_Application/syntax_t16: RuntimeError # New entries after going from kernel-service to batch-mode compilation. Please investigate.
-Language/Overview/Scoping/hiding_declaration_t11: Crash, Pass
-Language/Overview/Scoping/hiding_declaration_t12: Crash, Pass
-
 [ $compiler == fasta ]
 Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t01: MissingCompileTimeError
 Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t02: MissingCompileTimeError
@@ -202,101 +189,6 @@
 LibTest/typed_data/Uint64List/Uint64List.view_A01_t01: CompileTimeError
 LibTest/typed_data/Uint64List/Uint64List.view_A01_t02: CompileTimeError
 
-[ $arch == simarm && $compiler == dartkp ]
-LibTest/typed_data/Float32x4/operator_division_A01_t02: RuntimeError
-
-# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
-# are to be triaged.  Isolate tests are skipped on purpose due to the usage of
-# batch mode.
-[ $arch == simarm64 && $compiler == dartk && $mode == debug ]
-LibTest/core/DateTime/parse_A01_t02: Crash # Please triage.
-LibTest/core/DateTime/parse_A01_t03: Crash # Please triage.
-LibTest/core/DateTime/parse_A03_t01: Crash # Please triage.
-
-[ $compiler == dartk && $mode == debug ]
-LibTest/isolate/Isolate/spawnUri_A01_t04: Pass, Slow, Timeout
-
-[ $compiler == dartk && $system == windows ]
-Language/Libraries_and_Scripts/top_level_syntax_t06: Pass, Timeout
-Language/Reference/Operator_Precedence/precedence_t03: Pass, Timeout
-
-[ $compiler == dartk && $strong ]
-*: SkipByDesign
-
-# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
-# are to be triaged.  Isolate tests are skipped on purpose due to the usage of
-# batch mode.
-[ $compiler == dartk && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
-Language/Classes/definition_t23: RuntimeError # Please triaage.
-Language/Expressions/Spawning_an_Isolate/*: Skip
-Language/Mixins/Mixin_Application/syntax_t16: RuntimeError # Please triaage.
-LibTest/isolate/*/*: Skip
-
-[ $compiler == dartkp && $mode == debug ]
-Language/Functions/External_Functions/not_connected_to_a_body_t01: Crash
-
-[ $compiler == dartkp && $minified ]
-Language/Expressions/Property_Extraction/Getter_Access_and_Method_Extraction/no_such_method_t01: RuntimeError # Compares new Symbol with noSuchMethod actual name.
-
-[ $compiler == dartkp && $strong ]
-*: SkipByDesign
-
-[ $mode == debug && ($compiler == dartk || $compiler == dartkp) ]
-Language/Classes/Constructors/Generative_Constructors/execution_t04: Crash
-Language/Classes/Instance_Variables/constant_t01: Crash
-
-[ $checked && ($compiler == dartk || $compiler == dartkp) ]
-Language/Classes/Constructors/Factories/arguments_type_t01: RuntimeError
-Language/Classes/Constructors/Factories/function_type_t02: Fail # dartbug.com/30527
-Language/Expressions/Constants/exception_t04: Pass
-Language/Expressions/Function_Expressions/static_type_dynamic_async_t03: RuntimeError # dartbgug.com/30667
-Language/Expressions/Function_Expressions/static_type_dynamic_asyncs_t03: RuntimeError # dartbgug.com/30667
-Language/Expressions/Function_Expressions/static_type_dynamic_syncs_t03: RuntimeError # dartbug.com/30667
-Language/Expressions/Function_Expressions/static_type_form_3_async_t03: RuntimeError # dartbgug.com/30667
-Language/Expressions/Function_Expressions/static_type_form_3_asyncs_t03: RuntimeError # dartbgug.com/30667
-Language/Expressions/Function_Expressions/static_type_form_3_syncs_t03: RuntimeError # dartbgug.com/30667
-Language/Generics/malformed_t02: RuntimeError
-Language/Statements/Return/runtime_type_t04: RuntimeError
-Language/Statements/Switch/execution_t01: RuntimeError
-Language/Statements/Switch/type_t01: RuntimeError
-Language/Types/Dynamic_Type_System/malbounded_type_error_t01: RuntimeError
-Language/Types/Parameterized_Types/malbounded_t06: RuntimeError
-Language/Types/Static_Types/malformed_type_t04: RuntimeError
-
 [ $compiler == dartk || $compiler == dartkp ]
-Language/Classes/definition_t23: CompileTimeError
-Language/Expressions/Constants/bitwise_operators_t02: Crash
-Language/Expressions/Constants/bitwise_operators_t03: Crash
-Language/Expressions/Constants/bitwise_operators_t04: Crash
-Language/Expressions/Constants/bitwise_operators_t06: Crash
-Language/Expressions/Constants/depending_on_itself_t03: Crash
-Language/Expressions/Constants/math_operators_t04: Crash
-Language/Expressions/Constants/math_operators_t05: Crash
-Language/Expressions/Instance_Creation/New/evaluation_t19: RuntimeError # Issue 31938
-Language/Expressions/Instance_Creation/New/evaluation_t20: RuntimeError # Issue 31938
-Language/Functions/External_Functions/not_connected_to_a_body_t01: RuntimeError # Dartk Issue 28565
-Language/Libraries_and_Scripts/Imports/deferred_import_t01: RuntimeError # Deferred loading kernel issue 28335.
-Language/Libraries_and_Scripts/Imports/same_name_t10: RuntimeError
-Language/Libraries_and_Scripts/Imports/static_type_t01: Skip # No support for deferred libraries.
-Language/Metadata/before_export_t01: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_import_t01: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_library_t01: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t01: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t02: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t03: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t04: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t05: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t06: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t07: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t08: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t09: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_typedef_t01: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Mixins/Mixin_Application/syntax_t16: CompileTimeError # Issue 25765
-Language/Types/Type_Void/syntax_t01: Pass # Issue 30470
-LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: Skip # No support for deferred libraries.
-LibTest/isolate/Isolate/spawnUri_A01_t06: Skip
-
-[ $compiler == dartkp || $compiler == fasta ]
-Language/Classes/Superinterfaces/more_than_once_t01: MissingCompileTimeError
-Language/Classes/Superinterfaces/superclass_as_superinterface_t01: MissingCompileTimeError
+*: SkipByDesign
 
diff --git a/tests/compiler/dart2js/generic_methods/generic_method_test.dart b/tests/compiler/dart2js/generic_methods/generic_method_test.dart
index 668e99c..4138e44 100644
--- a/tests/compiler/dart2js/generic_methods/generic_method_test.dart
+++ b/tests/compiler/dart2js/generic_methods/generic_method_test.dart
@@ -92,6 +92,13 @@
   }
 }
 
+class Class4<T> {
+  Function method7<Q>() {
+    foo(T t, Q q) => '';
+    return foo;
+  }
+}
+
 // Nested generic local function.
 outside<T>() {
   nested<T>(T t) => '';
@@ -115,6 +122,8 @@
     print('noSuchMethod: Class2.method6<int>');
     print('');
   }
+  var c = new Class4<bool>();
+  print((c.method7<int>()).runtimeType);
   outside();
 }
 ''';
@@ -160,6 +169,7 @@
 
 noSuchMethod: Class2.method6<int>
 
+(bool, int) => String
 ''';
 
 main(List<String> args) {
diff --git a/tests/compiler/dart2js/old_frontend/analyze_api_test.dart b/tests/compiler/dart2js/old_frontend/analyze_api_test.dart
index c74aee2..458824e 100644
--- a/tests/compiler/dart2js/old_frontend/analyze_api_test.dart
+++ b/tests/compiler/dart2js/old_frontend/analyze_api_test.dart
@@ -18,25 +18,7 @@
  * the error/warning message in the list of white-listings for each file.
  */
 // TODO(johnniwinther): Support canonical URIs as keys.
-const Map<String, List<String>> WHITE_LIST = const {
-  "sdk/lib/_internal/js_runtime/lib/js_array.dart": const [
-    "Method type variables do not have a runtime value.",
-  ],
-  "sdk/lib/collection/iterable.dart": const [
-    "Method type variables do not have a runtime value.",
-  ],
-  "sdk/lib/collection/list.dart": const [
-    "Method type variables do not have a runtime value.",
-    "Method type variables are treated as `dynamic` in `as` expressions.",
-  ],
-  "sdk/lib/collection/set.dart": const [
-    "Method type variables do not have a runtime value.",
-  ],
-  "sdk/lib/core/iterable.dart": const [
-    "Method type variables do not have a runtime value.",
-    "Method type variables are treated as `dynamic` in `as` expressions.",
-  ],
-};
+const Map<String, List<String>> WHITE_LIST = const {};
 
 void main() {
   var uriList = new List<Uri>();
diff --git a/tests/compiler/dart2js/old_frontend/diagnose_ambiguous_test.dart b/tests/compiler/dart2js/old_frontend/diagnose_ambiguous_test.dart
index 8af9a96..53538ed 100644
--- a/tests/compiler/dart2js/old_frontend/diagnose_ambiguous_test.dart
+++ b/tests/compiler/dart2js/old_frontend/diagnose_ambiguous_test.dart
@@ -28,12 +28,6 @@
           "memory:library.dart:41:47:'hest' is defined here.:info",
       "MessageKind.DUPLICATE_IMPORT:"
           "memory:main.dart:86:92:Duplicate import of 'hest'.:warning",
-      "MessageKind.HIDDEN_WARNINGS:"
-          "null:null:null:1 warning(s) suppressed in dart:_interceptors.:hint",
-      "MessageKind.HIDDEN_WARNINGS_HINTS:"
-          "null:null:null:1 warning(s) and 1 hint(s) suppressed in dart:core.:hint",
-      "MessageKind.HIDDEN_WARNINGS_HINTS:"
-          "null:null:null:3 warning(s) and 1 hint(s) suppressed in dart:collection.:hint",
       "MessageKind.IMPORTED_HERE:"
           "memory:main.dart:0:22:'hest' is imported here.:info",
       "MessageKind.IMPORTED_HERE:"
diff --git a/tests/compiler/dart2js/old_frontend/duplicate_library_test.dart b/tests/compiler/dart2js/old_frontend/duplicate_library_test.dart
index 44c81c8..0f10f25 100644
--- a/tests/compiler/dart2js/old_frontend/duplicate_library_test.dart
+++ b/tests/compiler/dart2js/old_frontend/duplicate_library_test.dart
@@ -14,7 +14,7 @@
 
 void check(String kind, Iterable<CollectedMessage> messages,
     List<MessageKind> expectedMessageKinds) {
-  Expect.equals(messages.length, expectedMessageKinds.length,
+  Expect.equals(expectedMessageKinds.length, messages.length,
       "Unexpected $kind count: $messages");
   int i = 0;
   messages.forEach((CollectedMessage message) {
@@ -56,11 +56,7 @@
 """
   }, warnings: [
     MessageKind.DUPLICATED_LIBRARY_RESOURCE
-  ], hints: [
-    MessageKind.HIDDEN_WARNINGS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-  ]);
+  ], hints: []);
 
   await test({
     'main.dart': """
@@ -79,11 +75,7 @@
 """
   }, warnings: [
     MessageKind.DUPLICATED_LIBRARY_RESOURCE
-  ], hints: [
-    MessageKind.HIDDEN_WARNINGS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-  ]);
+  ], hints: []);
 
   await test({
     'main.dart': """
@@ -102,11 +94,7 @@
 """
   }, warnings: [
     MessageKind.DUPLICATED_LIBRARY_RESOURCE
-  ], hints: [
-    MessageKind.HIDDEN_WARNINGS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-  ]);
+  ], hints: []);
 
   await test({
     'main.dart': """
@@ -130,11 +118,7 @@
 """
   }, warnings: [
     MessageKind.DUPLICATED_LIBRARY_RESOURCE
-  ], hints: [
-    MessageKind.HIDDEN_WARNINGS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-  ]);
+  ], hints: []);
 
   await test({
     'main.dart': """
@@ -148,9 +132,6 @@
 """
   }, hints: [
     MessageKind.DUPLICATED_RESOURCE,
-    MessageKind.HIDDEN_WARNINGS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
   ]);
 
   await test({
@@ -169,9 +150,5 @@
   }, warnings: [
     MessageKind.DUPLICATED_LIBRARY_NAME,
     MessageKind.DUPLICATED_LIBRARY_NAME
-  ], hints: [
-    MessageKind.HIDDEN_WARNINGS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-    MessageKind.HIDDEN_WARNINGS_HINTS,
-  ]);
+  ], hints: []);
 }
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index e0bcaf1..5384ab4 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -8,6 +8,9 @@
 iterable_element_at_test/static: Pass
 num_sign_test: Crash, Pass # Issue 31768
 
+[ $compiler == dart2js ]
+iterable_where_type_test: RuntimeError # issue 31718
+
 [ $compiler != dartdevc ]
 error_stack_trace_test/static: MissingCompileTimeError
 
@@ -364,7 +367,15 @@
 symbol_test/none: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
 unicode_test: RuntimeError # Issue 18061: German double S.
 
+# ===== dartkp + dart_precompiled + debug status lines =====
+[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
+null_nosuchmethod_test/01: Crash # dartbug.com/32377
+null_nosuchmethod_test/none: Crash # dartbug.com/32377
+
 # ===== dartkp + dart_precompiled status lines =====
+[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
+null_nosuchmethod_test: Crash
+
 [ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
 apply_test: RuntimeError, OK
 iterable_fold_test/02: RuntimeError
diff --git a/tests/corelib_2/iterable_followed_by_test.dart b/tests/corelib_2/iterable_followed_by_test.dart
new file mode 100644
index 0000000..5edf0e3
--- /dev/null
+++ b/tests/corelib_2/iterable_followed_by_test.dart
@@ -0,0 +1,102 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:collection" show Queue;
+import "dart:typed_data" show Int32List;
+
+import "package:expect/expect.dart";
+
+// Tests behavior of result of an operation on a followedBy iterable.
+test(List expects, Iterable iterable, [String name]) {
+  try {
+    Expect.isFalse(iterable is List, "$name is! List");
+    Expect.isFalse(iterable is Set, "$name is! Set");
+    Expect.isFalse(iterable is Queue, "$name is! Queue");
+    if (expects.isNotEmpty) {
+      Expect.equals(expects.first, iterable.first, "$name: first");
+      Expect.equals(expects.last, iterable.last, "$name: last");
+    } else {
+      Expect.throwsStateError(() => iterable.first, "$name: first");
+      Expect.throwsStateError(() => iterable.last, "$name: last");
+    }
+    var it = iterable.iterator;
+    for (int index = 0; index < expects.length; index++) {
+      Expect.isTrue(it.moveNext(), "$name: has element $index");
+      var expect = expects[index];
+      Expect.equals(expect, it.current, "$name at $index");
+      Expect.equals(
+          expect, iterable.elementAt(index), "$name: elementAt($index)");
+      Expect.isTrue(iterable.contains(expect), "$name:contains $index");
+    }
+    Expect.isFalse(it.moveNext(),
+        "$name: extra element at ${expects.length}: ${it.current}");
+  } on Error {
+    print("Failed during: $name");
+    rethrow;
+  }
+}
+
+// Tests various operations on the a followedBy iterable.
+tests(List<int> expects, Iterable<int> follow, [String name]) {
+  int length = expects.length;
+  test(expects, follow, name);
+  for (int i = 0; i <= length; i++) {
+    test(expects.sublist(i), follow.skip(i), "$name.skip($i)");
+  }
+  for (int i = 0; i <= length; i++) {
+    test(expects.sublist(0, i), follow.take(i), "$name.take($i)");
+  }
+  for (int i = 0; i <= length; i++) {
+    for (int j = 0; j <= length - i; j++) {
+      test(expects.sublist(i, i + j), follow.skip(i).take(j),
+          "$name.skiptake($i,${i+j})");
+      test(expects.sublist(i, i + j), follow.take(i + j).skip(i),
+          "$name.takeskip($i,${i+j})");
+    }
+  }
+}
+
+// Tests various different types of iterables as first and second operand.
+types(List expects, List<int> first, List<int> second, [String name]) {
+  var conversions = <String, Iterable<int> Function(List<int>)>{
+    "const": toConst,
+    "list": toList,
+    "unmod": toUnmodifiable,
+    "set": toSet,
+    "queue": toQueue,
+    "eff-len-iter": toELIter,
+    "non-eff-iter": toNEIter,
+    "typed": toTyped,
+    "keys": toKeys,
+    "values": toValues,
+  };
+  conversions.forEach((n1, c1) {
+    conversions.forEach((n2, c2) {
+      tests(expects, c1(first).followedBy(c2(second)), "$name:$n1/$n2");
+    });
+  });
+}
+
+List<int> toConst(List<int> elements) => elements;
+List<int> toList(List<int> elements) => elements.toList();
+List<int> toUnmodifiable(List<int> elements) =>
+    new List<int>.unmodifiable(elements);
+Set<int> toSet(List<int> elements) => elements.toSet();
+Queue<int> toQueue(List<int> elements) => new Queue<int>.from(elements);
+// Creates an efficient-length iterable.
+Iterable<int> toELIter(List<int> elements) => elements.map<int>((x) => x);
+// Creates a non-efficient-length iterable.
+Iterable<int> toNEIter(List<int> elements) => elements.where((x) => true);
+List<int> toTyped(List<int> elements) => new Int32List.fromList(elements);
+Iterable<int> toKeys(List<int> elements) =>
+    new Map<int, int>.fromIterables(elements, elements).keys;
+Iterable<int> toValues(List<int> elements) =>
+    new Map<int, int>.fromIterables(elements, elements).values;
+
+main() {
+  types(<int>[], const <int>[], const <int>[], "0+0");
+  types(<int>[1, 2, 3, 4], const <int>[], const <int>[1, 2, 3, 4], "0+4");
+  types(<int>[1, 2, 3, 4], const <int>[1, 2], const <int>[3, 4], "2+2");
+  types(<int>[1, 2, 3, 4], const <int>[1, 2, 3, 4], const <int>[], "4+0");
+}
diff --git a/tests/corelib_2/iterable_where_type_test.dart b/tests/corelib_2/iterable_where_type_test.dart
new file mode 100644
index 0000000..8715149
--- /dev/null
+++ b/tests/corelib_2/iterable_where_type_test.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:collection" show Queue;
+import "dart:typed_data" show Int32List;
+
+import "package:expect/expect.dart";
+
+// Tests behavior of result of an operation on a followedBy iterable.
+test(List expects, Iterable iterable, [String name]) {
+  try {
+    Expect.isFalse(iterable is List, "$name is! List");
+    Expect.isFalse(iterable is Set, "$name is! Set");
+    Expect.isFalse(iterable is Queue, "$name is! Queue");
+    if (expects.isNotEmpty) {
+      Expect.equals(expects.first, iterable.first, "$name: first");
+      Expect.equals(expects.last, iterable.last, "$name: last");
+    } else {
+      Expect.throwsStateError(() => iterable.first, "$name: first");
+      Expect.throwsStateError(() => iterable.last, "$name: last");
+    }
+    var it = iterable.iterator;
+    for (int index = 0; index < expects.length; index++) {
+      Expect.isTrue(it.moveNext(), "$name: has element $index");
+      var expect = expects[index];
+      Expect.equals(expect, it.current, "$name at $index");
+      Expect.equals(
+          expect, iterable.elementAt(index), "$name: elementAt($index)");
+      Expect.isTrue(iterable.contains(expect), "$name:contains $index");
+    }
+    Expect.isFalse(it.moveNext(),
+        "$name: extra element at ${expects.length}: ${it.current}");
+  } on Error {
+    print("Failed during: $name");
+    rethrow;
+  }
+}
+
+main() {
+  var conversions = <String, Iterable<int> Function(List<int>)>{
+    "const": toConst,
+    "list": toList,
+    "unmod": toUnmodifiable,
+    "set": toSet,
+    "queue": toQueue,
+    "eff-len-iter": toELIter,
+    "non-eff-iter": toNEIter,
+    "typed": toTyped,
+    "keys": toKeys,
+    "values": toValues,
+  };
+  for (var data in [
+    const <int>[],
+    const <int>[1],
+    const <int>[1, 2, 3]
+  ]) {
+    conversions.forEach((name, c) {
+      test(data, c(data).whereType<int>(), "$name#${data.length}.wt<int>");
+      test(data, c(data).whereType<num>(), "$name#${data.length}.wt<num>");
+      test([], c(data).whereType<Null>(), "$name#${data.length}.wt<Null>");
+    });
+  }
+
+  test([1, 0.1], ["a", 1, new Object(), 0.1, null].whereType<num>(), "mixed");
+
+  var o = new Object();
+  var a = new A();
+  var b = new B();
+  var c = new C();
+  var d = new D();
+  var n = null;
+  test([o, a, b, c, d, n], [o, a, b, c, d, n].whereType<Object>(), "Object");
+  test([a, b, c, d], [o, a, b, c, d, n].whereType<A>(), "A");
+  test([b, d], [o, a, b, c, d, n].whereType<B>(), "B");
+  test([c, d], [o, a, b, c, d, n].whereType<C>(), "C");
+  test([d], [o, a, b, c, d, n].whereType<D>(), "D");
+  test([n], [o, a, b, c, d, n].whereType<Null>(), "Null");
+
+  test([d], <B>[d].whereType<C>(), "Unrelated");
+}
+
+class A {}
+
+class B implements A {}
+
+class C implements A {}
+
+class D implements B, C {}
+
+List<int> toConst(List<int> elements) => elements; // Argument is const.
+List<int> toList(List<int> elements) => elements.toList();
+List<int> toUnmodifiable(List<int> elements) =>
+    new List<int>.unmodifiable(elements);
+Set<int> toSet(List<int> elements) => elements.toSet();
+Queue<int> toQueue(List<int> elements) => new Queue<int>.from(elements);
+// Creates an efficient-length iterable.
+Iterable<int> toELIter(List<int> elements) => elements.map<int>((x) => x);
+// Creates a non-efficient-length iterable.
+Iterable<int> toNEIter(List<int> elements) => elements.where((x) => true);
+List<int> toTyped(List<int> elements) => new Int32List.fromList(elements);
+Iterable<int> toKeys(List<int> elements) =>
+    new Map<int, int>.fromIterables(elements, elements).keys;
+Iterable<int> toValues(List<int> elements) =>
+    new Map<int, int>.fromIterables(elements, elements).values;
diff --git a/tests/corelib_2/map_unmodifiable_cast_test.dart b/tests/corelib_2/map_unmodifiable_cast_test.dart
index 9c1e19b..3091337 100644
--- a/tests/corelib_2/map_unmodifiable_cast_test.dart
+++ b/tests/corelib_2/map_unmodifiable_cast_test.dart
@@ -8,45 +8,76 @@
 import 'dart:collection';
 
 void main() {
-  test(const {1: 37});
-  test(new UnmodifiableMapView({1: 37}));
+  testNum(const {1: 37}, "const");
+  testNum(const <num, num>{1: 37}.cast<int, int>(), "const.cast");
+  testNum(const <num, num>{1: 37}.retype<int, int>(), "const.retype");
 
-  test(new UnmodifiableMapView<num, num>(<num, num>{1: 37}));
-  test(new UnmodifiableMapView<num, num>(<int, int>{1: 37}));
+  testNum(new UnmodifiableMapView({1: 37}), "unmod");
+  testNum(new UnmodifiableMapView<num, num>(<num, num>{1: 37}), "unmod.cast");
+  testNum(new UnmodifiableMapView<num, num>(<int, int>{1: 37}), "unmod.retype");
 
-  test(new UnmodifiableMapView<num, num>(<num, num>{1: 37}).cast<int, int>());
-  test(new UnmodifiableMapView<num, num>(<int, int>{1: 37}).cast<int, int>());
-  test(new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
-      .cast<int, int>());
-  test(new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
-      .cast<num, num>());
+  testNum(new UnmodifiableMapView<num, num>(<num, num>{1: 37}).cast<int, int>(),
+      "unmodView<num>.cast<int>");
+  testNum(new UnmodifiableMapView<num, num>(<int, int>{1: 37}).cast<int, int>(),
+      "unmodView<int>.cast<int>");
+  testNum(
+      new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
+          .cast<int, int>(),
+      "unmodView<Object>(num).cast<int>");
+  testNum(
+      new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
+          .cast<num, num>(),
+      "unmodView<Object>(int).cast<num>");
 
-  test(new UnmodifiableMapView<num, num>(<num, num>{1: 37}).retype<int, int>());
-  test(new UnmodifiableMapView<num, num>(<int, int>{1: 37}).retype<int, int>());
-  test(new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
-      .retype<int, int>());
-  test(new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
-      .retype<num, num>());
+  testNum(
+      new UnmodifiableMapView<num, num>(<num, num>{1: 37}).retype<int, int>(),
+      "unmodView<num>(num).retype<int>");
+  testNum(
+      new UnmodifiableMapView<num, num>(<int, int>{1: 37}).retype<int, int>(),
+      "unmodView<num>(int).retype<int>");
+  testNum(
+      new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
+          .retype<int, int>(),
+      "unmodView<Object>(num).retype<int>");
+  testNum(
+      new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
+          .retype<num, num>(),
+      "unmodView<Object>(int).retype<num>");
 
   var m2 = new Map<num, num>.unmodifiable({1: 37});
-  test(m2);
-  test(m2.cast<int, int>());
+  testNum(m2, "Map<num>.unmod");
+  testNum(m2.cast<int, int>(), "Map<num>.unmod.cast<int>");
+
+  Map<Symbol, dynamic> nsm = new NsmMap().foo(a: 0);
+  test(nsm, #a, 0, "nsm");
+  test(nsm.cast<Object, int>(), #a, 0, "nsm.cast");
+  test(nsm.retype<Object, int>(), #a, 0, "nsm.retype");
 }
 
-void test(Map map) {
-  Expect.isTrue(map.containsKey(1));
-  Expect.equals(1, map.length);
-  Expect.equals(1, map.keys.first);
-  Expect.equals(37, map.values.first);
+void testNum(Map<Object, Object> map, String name) {
+  test(map, 1, 37, name);
+}
 
-  Expect.throws(map.clear);
-  Expect.throws(() {
-    map.remove(1);
-  });
-  Expect.throws(() {
-    map[2] = 42;
-  });
-  Expect.throws(() {
-    map.addAll(<int, int>{2: 42});
-  });
+void test(
+    Map<Object, Object> map, Object firstKey, Object firstValue, String name) {
+  Expect.isTrue(map.containsKey(firstKey), "$name.containsKey");
+  Expect.equals(1, map.length, "$name.length");
+  Expect.equals(firstKey, map.keys.first, "$name.keys.first");
+  Expect.equals(firstValue, map.values.first, "$name.values.first");
+
+  Expect.throwsUnsupportedError(map.clear, "$name.clear");
+  Expect.throwsUnsupportedError(() {
+    map.remove(firstKey);
+  }, "$name.remove");
+  Expect.throwsUnsupportedError(() {
+    map[null] = null;
+  }, "$name[]=");
+  Expect.throwsUnsupportedError(() {
+    map.addAll(<Null, Null>{null: null});
+  }, "$name.addAll");
+}
+
+class NsmMap {
+  noSuchMethod(i) => i.namedArguments;
+  foo({a, b, c, d});
 }
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index c97a6b0..2d33902 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -116,52 +116,12 @@
 [ $compiler == dart2js && ($runtime == chrome || $runtime == chromeOnAndroid || $runtime == drt || $runtime == ff || $runtime == safari) ]
 isolate_stress_test: Pass, Slow # Issue 10697
 
-# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
-# are to be triaged.  Isolate tests are skipped on purpose due to the usage of
-# batch mode.
-[ $compiler == dartk && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
-checked_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-count_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-cross_isolate_message_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-error_at_spawnuri_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-error_exit_at_spawnuri_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-exit_at_spawnuri_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-illegal_msg_function_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-illegal_msg_mirror_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-isolate_complex_messages_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-issue_21398_parent_isolate1_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-issue_21398_parent_isolate_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-issue_24243_parent_isolate_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-mandel_isolate_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-message2_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-message_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-mint_maker_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-nested_spawn2_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-nested_spawn_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-raw_port_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-request_reply_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_function_custom_class_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_function_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_exported_main_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_missing_from_isolate_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_missing_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_multi_test/01: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_multi_test/none: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_nested_vm_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_vm_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-static_function_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-unresolved_ports_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-
 [ $compiler == none && $runtime == vm && $system == fuchsia ]
 *: Skip # Not yet triaged.
 
 [ $compiler == none && ($runtime == flutter || $runtime == vm) ]
 scenarios/short_package/short_package_test: Fail, OK # We do not plan to support the tested behavior anyway.
 
-[ $mode == debug && ($compiler == dartk || $compiler == dartkp) ]
-static_function_test: Skip # Times out. Issue 31855
-
 [ $compiler == app_jit || $compiler == none || $compiler == precompiler ]
 compile_time_error_test/01: Skip # Issue 12587
 kill3_test: Pass, Fail # Bad test: expects total message order
@@ -172,12 +132,7 @@
 checked_test: Skip # Unsupported.
 
 [ $compiler == dartk || $compiler == dartkp ]
-deferred_in_isolate2_test: Skip # Timeout. Deferred loading kernel issue 28335.
-deferred_in_isolate_test: Skip # Timeout. Deferred loading kernel issue 28335.
-issue_21398_parent_isolate2_test/01: Skip # Timeout. Deferred loading kernel issue 28335.
-ping_pause_test: Pass, Timeout
-spawn_function_custom_class_test: Pass, Timeout
-spawn_uri_nested_vm_test: Pass, Timeout
+*: Skip # This directory has only Dart1 tests (Dart2 tests are in lib_2/isolate).
 
 [ $compiler != none || $runtime != vm ]
 package_config_test: SkipByDesign # Uses Isolate.packageConfig
diff --git a/tests/kernel/kernel.status b/tests/kernel/kernel.status
index d79e280..6d9eea4 100644
--- a/tests/kernel/kernel.status
+++ b/tests/kernel/kernel.status
@@ -12,32 +12,14 @@
 [ !$fasta ]
 unsorted/loop_test: Skip # This test uses optional new/const.
 
-[ !$strong ]
-unsorted/invocation_errors_test: RuntimeError
-
-[ $arch == simarm && $compiler == dartkp && $strong ]
-unsorted/invocation_errors_test: CompileTimeError
-unsorted/nsm_dispatcher_test: CompileTimeError
-unsorted/super_mixin_test: CompileTimeError
-unsorted/types_test: RuntimeError
-
-[ $arch == simarm64 && $compiler == dartkp && $strong ]
-unsorted/invocation_errors_test: CompileTimeError
-unsorted/nsm_dispatcher_test: CompileTimeError
-unsorted/super_mixin_test: CompileTimeError
-unsorted/types_test: RuntimeError
-
 [ $compiler == dart2analyzer && $runtime == none ]
-unsorted/invocation_errors_test: StaticWarning
 unsorted/super_mixin_test: CompileTimeError
 
 [ $compiler == dart2analyzer && $strong ]
 *: Skip # Issue 28649
 
-[ $compiler == dartk && $strong ]
-unsorted/invocation_errors_test: CompileTimeError
-unsorted/nsm_dispatcher_test: CompileTimeError
-unsorted/super_mixin_test: CompileTimeError
+[ $compiler != dartk && $compiler != dartkp ]
+unsorted/invocation_errors_test/00: MissingCompileTimeError # This test has been tuned for dart 2.
 unsorted/types_test: RuntimeError
 
 [ $runtime == dart_precompiled && $minified ]
diff --git a/tests/kernel/unsorted/invocation_errors_test.dart b/tests/kernel/unsorted/invocation_errors_test.dart
index 9c9c516..95e3106 100644
--- a/tests/kernel/unsorted/invocation_errors_test.dart
+++ b/tests/kernel/unsorted/invocation_errors_test.dart
@@ -11,6 +11,5 @@
 }
 
 main() {
-  // Incorrect number of arguments, should be NoSuchMethodError but crashes.
-  test0(0, 1);
+  test0(0, 1); //# 00: compile-time error
 }
diff --git a/tests/kernel/unsorted/nsm_dispatcher_test.dart b/tests/kernel/unsorted/nsm_dispatcher_test.dart
index add1ece..8a0722a 100644
--- a/tests/kernel/unsorted/nsm_dispatcher_test.dart
+++ b/tests/kernel/unsorted/nsm_dispatcher_test.dart
@@ -19,7 +19,7 @@
 }
 
 main() {
-  var o = new A();
+  dynamic o = new A();
   Expect.isTrue(o.fun() == '|${#fun}|');
   Expect.isTrue(o.fun(1) == '|${#fun}|1|');
   Expect.isTrue(o.fun(1, 2) == '|${#fun}|1|2|');
diff --git a/tests/kernel/unsorted/super_mixin_test.dart b/tests/kernel/unsorted/super_mixin_test.dart
index 8c04aab..f70b888 100644
--- a/tests/kernel/unsorted/super_mixin_test.dart
+++ b/tests/kernel/unsorted/super_mixin_test.dart
@@ -4,6 +4,17 @@
 
 import 'package:expect/expect.dart';
 
+class BaseMixin {
+  method(x) {
+    print(x);
+    return x + 'error';
+  }
+
+  set setter(x) {
+    print(x);
+  }
+}
+
 class Base {
   var field;
 
@@ -18,7 +29,7 @@
   }
 }
 
-class Mixin {
+class Mixin extends BaseMixin {
   method(x) {
     return super.method(x + 'Mixin');
   }
diff --git a/tests/kernel/unsorted/types_test.dart b/tests/kernel/unsorted/types_test.dart
index 0a41f1d..0b989a1 100644
--- a/tests/kernel/unsorted/types_test.dart
+++ b/tests/kernel/unsorted/types_test.dart
@@ -45,13 +45,14 @@
 testConstantLiteralTypes() {
   Expect.isTrue(const [1] is List);
   Expect.isTrue(const [1] is List<int>);
-  Expect.isTrue(const [1] is List<String>);
+  Expect.isTrue(const ["1"] is List<String>);
+  Expect.isTrue(!(const [1] is List<String>));
   Expect.isTrue(const <int>[1] is List);
   Expect.isTrue(const <int>[1] is List<int>);
   Expect.isTrue(!(const <int>[1] is List<String>));
   Expect.isTrue(const {"a": 1} is Map);
   Expect.isTrue(const {"a": 1} is Map<String, int>);
-  Expect.isTrue(const {"a": 1} is Map<int, String>);
+  Expect.isTrue(const {1: "a"} is Map<int, String>);
   Expect.isTrue(const <String, int>{"a": 1} is Map);
   Expect.isTrue(const <String, int>{"a": 1} is Map<String, int>);
   Expect.isTrue(!(const <String, int>{"a": 1} is Map<int, String>));
@@ -60,7 +61,8 @@
 testNonConstantLiteralTypes() {
   Expect.isTrue([1] is List);
   Expect.isTrue([1] is List<int>);
-  Expect.isTrue([1] is List<String>);
+  Expect.isTrue(["1"] is List<String>);
+  Expect.isTrue(!([1] is List<String>));
   Expect.isTrue(<int>[1] is List);
   Expect.isTrue(<int>[1] is List<int>);
   Expect.isTrue(!(<int>[1] is List<String>));
@@ -163,8 +165,15 @@
 
 testFunctionTypes() {
   fun(int x, String y) => "${x}${y}";
-  Expect.isTrue(fun is FunctionType);
-  Expect.isTrue(nan is FunctionType);
+  Expect.isTrue(!(fun is FunctionType));
+
+  fun1(num x, Pattern y) => 123;
+  Expect.isTrue(fun1 is FunctionType);
+
+  fun2(num x, String y) => 123;
+  Expect.isTrue(!(fun2 is FunctionType));
+
+  Expect.isTrue(!(nan is FunctionType));
   Expect.isTrue(nan is Function);
 }
 
diff --git a/tests/language_2/bug32353_test.dart b/tests/language_2/bug32353_test.dart
new file mode 100644
index 0000000..3284e51
--- /dev/null
+++ b/tests/language_2/bug32353_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// SharedOptions=--supermixin
+
+import 'dart:io' as io;
+
+import "package:expect/expect.dart";
+
+class _LocalDirectory
+    extends _LocalFileSystemEntity<_LocalDirectory, io.Directory>
+    with ForwardingDirectory, DirectoryAddOnsMixin {
+  noSuchMethod(invocation) => null;
+}
+
+abstract class _LocalFileSystemEntity<T extends FileSystemEntity,
+    D extends io.FileSystemEntity> extends ForwardingFileSystemEntity<T, D> {}
+
+abstract class FileSystemEntity implements io.FileSystemEntity {}
+
+abstract class ForwardingFileSystemEntity<T extends FileSystemEntity,
+    D extends io.FileSystemEntity> implements FileSystemEntity {}
+
+abstract class ForwardingDirectory<T extends Directory>
+    extends ForwardingFileSystemEntity<T, io.Directory> implements Directory {
+  get t => T;
+}
+
+abstract class Directory implements FileSystemEntity, io.Directory {}
+
+abstract class DirectoryAddOnsMixin implements Directory {}
+
+main() {
+  var x = new _LocalDirectory();
+  Expect.equals(x.t, _LocalDirectory);
+}
diff --git a/tests/language_2/call_method_implicit_invoke_instance_test.dart b/tests/language_2/call_method_implicit_invoke_instance_test.dart
index aa176fa..fdcb12b 100644
--- a/tests/language_2/call_method_implicit_invoke_instance_test.dart
+++ b/tests/language_2/call_method_implicit_invoke_instance_test.dart
@@ -34,13 +34,13 @@
 main() {
   new D().test();
   // Implicitly invokes D.c1.call(1)
-  Expect.equals(new D().c1(1), 2); //# 09: ok
+  Expect.equals(new D().c1(1), 2); //# 05: ok
   // Implicitly invokes D.d1.call(1)
-  Expect.equals(new D().d1(1), 2); //# 10: ok
+  Expect.equals(new D().d1(1), 2); //# 06: ok
   // Implicitly invokes D.c2.call(1)
-  Expect.equals(new D().c2(1), 2); //# 11: ok
+  Expect.equals(new D().c2(1), 2); //# 07: ok
   // Implicitly invokes D.d2.call(1)
-  Expect.equals(new D().d2(1), 2); //# 12: ok
+  Expect.equals(new D().d2(1), 2); //# 08: ok
   D d = new D();
   // Implicitly invokes d.c1.call(1)
   Expect.equals(d.c1(1), 2); //# 09: ok
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index bf6f7d9..c8f9a3e 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -1559,6 +1559,10 @@
 malformed_test/23: MissingCompileTimeError
 malformed_test/24: MissingCompileTimeError
 malformed_type_test: MissingCompileTimeError
+mixin_type_parameter_inference_error_test/01: MissingCompileTimeError
+mixin_type_parameter_inference_error_test/02: MissingCompileTimeError
+mixin_type_parameter_inference_error_test/03: MissingCompileTimeError
+mixin_type_parameter_inference_error_test/04: MissingCompileTimeError
 mixin_type_parameter_inference_previous_mixin_test/03: MissingCompileTimeError
 mixin_type_parameter_inference_previous_mixin_test/04: MissingCompileTimeError
 mixin_type_parameter_inference_test/04: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 18de4de..9841b1f 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -35,6 +35,7 @@
 
 [ $compiler == dart2js && $runtime == d8 && $dart2js_with_kernel ]
 assertion_test: RuntimeError
+bug32353_test: CompileTimeError
 implicit_creation/implicit_new_constructor_generic_test: Pass
 
 [ $compiler == dart2js && $runtime == d8 && !$dart2js_with_kernel ]
@@ -2857,7 +2858,9 @@
 bad_override_test/06: MissingCompileTimeError
 bad_typedef_test/00: Crash # Issue 28214
 bug31436_test: RuntimeError
+bug32353_test: CompileTimeError
 built_in_identifier_prefix_test: CompileTimeError
+built_in_identifier_type_annotation_test/22: MissingCompileTimeError # Error only in strong mode
 call_constructor_on_unresolvable_class_test/01: MissingCompileTimeError
 call_constructor_on_unresolvable_class_test/02: MissingCompileTimeError
 call_constructor_on_unresolvable_class_test/03: MissingCompileTimeError
@@ -3207,6 +3210,10 @@
 integer_division_by_zero_test: RuntimeError # Issue 8301
 interface_test/00: MissingCompileTimeError
 invalid_override_in_mixin_test/01: MissingCompileTimeError
+invalid_type_argument_count_test/01: MissingCompileTimeError
+invalid_type_argument_count_test/02: MissingCompileTimeError
+invalid_type_argument_count_test/03: MissingCompileTimeError
+invalid_type_argument_count_test/04: MissingCompileTimeError
 invocation_mirror2_test: RuntimeError # Issue 6490 (wrong retval).
 issue31596_override_test/05: MissingCompileTimeError
 issue31596_override_test/06: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index e41601c..35e3b0a 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -21,6 +21,7 @@
 await_future_test: Pass, Timeout # Issue 29920
 bit_operations_test: RuntimeError # No bigints on web.
 black_listed_test/none: Fail # Issue 14228
+bug32353_test: RuntimeError
 built_in_identifier_prefix_test: CompileTimeError
 built_in_identifier_type_annotation_test/22: MissingCompileTimeError # Issue 28816
 call_method_as_cast_test/01: RuntimeError
@@ -334,6 +335,7 @@
 bad_override_test/03: MissingCompileTimeError
 bad_override_test/04: MissingCompileTimeError
 bad_override_test/05: MissingCompileTimeError
+bug32353_test: Crash # Issue 32353
 built_in_identifier_type_annotation_test/05: RuntimeError # Issue 32194
 built_in_identifier_type_annotation_test/none: RuntimeError # Issue 32194
 call_method_as_cast_test/01: RuntimeError
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index d5d228a..9b0ad47 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -11,6 +11,7 @@
 # to add them.
 
 [ $compiler == dartkp ]
+bug32353_test: DartkCrash # Issue 32353
 class_cycle_test/02: MissingCompileTimeError
 class_cycle_test/03: MissingCompileTimeError
 duplicate_implements_test/01: MissingCompileTimeError
@@ -20,6 +21,7 @@
 mock_writable_final_field_test: RuntimeError # Issue 31424
 no_such_method_subtype_test: RuntimeError # Issue 31424
 
+
 [ $fasta ]
 abstract_factory_constructor_test/00: MissingCompileTimeError # Issue 32013.
 abstract_getter_test/01: MissingCompileTimeError # Issue 32013.
@@ -578,6 +580,7 @@
 async_star_cancel_while_paused_test: RuntimeError
 async_star_pause_test: Fail, OK
 async_star_test/02: RuntimeError # Issue 31402 (Invocation arguments)
+bug32353_test: DartkCrash # Issue 32353
 built_in_identifier_prefix_test: CompileTimeError
 call_method_must_not_be_field_test/03: RuntimeError # Issue 32265
 call_method_must_not_be_getter_test/03: RuntimeError # Issue 32265
@@ -1105,6 +1108,7 @@
 super_operator_index8_test: CompileTimeError
 super_test: Fail, OK
 syntax_test/00: MissingCompileTimeError
+tearoff_dynamic_test: Crash
 type_literal_test: RuntimeError
 type_promotion_functions_test/02: CompileTimeError # Issue 31537
 type_promotion_functions_test/03: CompileTimeError # Issue 31537
diff --git a/tests/language_2/language_2_precompiled.status b/tests/language_2/language_2_precompiled.status
index b9ea3dc..57a932d 100644
--- a/tests/language_2/language_2_precompiled.status
+++ b/tests/language_2/language_2_precompiled.status
@@ -87,6 +87,7 @@
 bool_check_test: RuntimeError
 bool_condition_check_test: RuntimeError
 bug31436_test: RuntimeError
+bug32353_test: RuntimeError
 built_in_identifier_prefix_test: CompileTimeError
 call_constructor_on_unresolvable_class_test/01: MissingCompileTimeError
 call_constructor_on_unresolvable_class_test/02: MissingCompileTimeError
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index 726711c..13af2f9 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -177,6 +177,7 @@
 bad_override_test/02: MissingCompileTimeError
 bad_override_test/06: MissingCompileTimeError
 bug31436_test: RuntimeError
+bug32353_test: RuntimeError
 built_in_identifier_prefix_test: CompileTimeError
 call_constructor_on_unresolvable_class_test/01: MissingCompileTimeError
 call_constructor_on_unresolvable_class_test/02: MissingCompileTimeError
diff --git a/tests/language_2/vm/regress_32322_test.dart b/tests/language_2/vm/regress_32322_test.dart
new file mode 100644
index 0000000..61415d7
--- /dev/null
+++ b/tests/language_2/vm/regress_32322_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify that optimizing compiler does not perform an illegal code motion
+// past CheckNull instruction.
+
+import "package:expect/expect.dart";
+
+class C {
+  final String padding = "";
+  final String field = "1"; // Note: need padding to hit an object header
+  // of the next object after [null] object when
+  // doing illegal null.field read. Need to hit
+  // object header to cause crash.
+}
+
+int foofoo(C p) {
+  int sum = 0;
+  for (var i = 0; i < 10; i++) {
+    // Note: need redundant instructions in the loop to trigger Canonicalize
+    // after CSE. Canonicalize then would illegally remove the Redefinition.
+    sum += p.field.length;
+    sum += p.field.length;
+  }
+  return sum;
+}
+
+void main() {
+  Expect.equals(20, foofoo(new C()));
+  Expect.throwsNoSuchMethodError(() => foofoo(null));
+}
diff --git a/tests/language_2/vm/regress_flutter_14891_test.dart b/tests/language_2/vm/regress_flutter_14891_test.dart
new file mode 100644
index 0000000..1f410df
--- /dev/null
+++ b/tests/language_2/vm/regress_flutter_14891_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test verifying that type literals hidden within other constant objects
+// are correctly handled by the AOT compiler.
+
+import "package:expect/expect.dart";
+
+class _ClassOnlyUsedAsTypeLiteral {}
+
+void main() {
+  Expect
+      .isTrue((const [_ClassOnlyUsedAsTypeLiteral]).toString().startsWith('['));
+}
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 8249747..927f9a0 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -66,7 +66,7 @@
 [ $compiler == dartk && $strong && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
 io/directory_list_sync_test: Timeout, Pass # Please triage.
 io/file_blocking_lock_test: Pass, Crash # Please triage.
-io/file_lock_test: RuntimeError # Please triage.
+io/file_lock_test: Slow, Pass
 io/platform_resolved_executable_test/05: Pass, RuntimeError # Issue 32134
 io/platform_test: RuntimeError # Please triage.
 io/test_extension_fail_test: RuntimeError # Please traige.
@@ -81,6 +81,7 @@
 *: SkipByDesign
 
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
+io/compile_all_test: Crash # Issue 32373
 io/raw_socket_test: Crash
 io/skipping_dart2js_compilations_test: Crash
 io/socket_exception_test: Pass, Crash
diff --git a/tools/VERSION b/tools/VERSION
index 9bcd14c..862960b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 0
 PATCH 0
-PRERELEASE 31
+PRERELEASE 32
 PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/lib/update_homebrew.dart b/tools/apps/update_homebrew/lib/update_homebrew.dart
index 49e8da7..350c779 100644
--- a/tools/apps/update_homebrew/lib/update_homebrew.dart
+++ b/tools/apps/update_homebrew/lib/update_homebrew.dart
@@ -170,13 +170,13 @@
   end
 
   def shim_script(target)
-    <<-EOS.undent
+    <<~EOS
       #!/usr/bin/env bash
       exec "#{prefix}/#{target}" "\$@"
     EOS
   end
 
-  def caveats; <<-EOS.undent
+  def caveats; <<~EOS
     Please note the path to the Dart SDK:
       #{opt_libexec}
 
@@ -187,7 +187,7 @@
   end
 
   test do
-    (testpath/"sample.dart").write <<-EOS.undent
+    (testpath/"sample.dart").write <<~EOS
       void main() {
         print(r"test message");
       }
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index fda892d..473c023 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -823,7 +823,6 @@
         "dart2js-linux-x64-chrome",
         "dart2js-linux-x64-drt",
         "dart2js-linux-x64-ff",
-        "dart2js-linux-x64-jsshell",
         "dart2js-mac-x64-chrome",
         "dart2js-mac-x64-safari",
         "dart2js-win-x64-chrome",
@@ -1303,28 +1302,27 @@
           "arguments": ["--compiler=dart2analyzer", "--use-sdk"]
         },
         {
-          "name": "analyze tests checked",
-          "arguments": ["--compiler=dart2analyzer", "--use-sdk", "--checked"]
-        },
-        {
           "name": "analyze pkg tests",
           "arguments": ["--compiler=dart2analyzer", "--use-sdk", "pkg"]
         },
         {
+          "name": "analyze tests checked",
+          "arguments": ["--checked", "--compiler=dart2analyzer", "--use-sdk"]
+        },
+        {
           "name": "analyze pkg tests checked",
           "arguments": [
+            "--checked",
             "--compiler=dart2analyzer",
             "--use-sdk",
-            "--checked",
             "pkg"
           ]
         },
         {
-          "name": "analyze unit tests",
+          "name": "analyzer unit tests",
           "arguments": [
-            "--compiler=none",
-            "--runtime=vm",
             "--checked",
+            "--compiler=none",
             "--use-sdk",
             "pkg/analyzer"
           ]
@@ -1332,29 +1330,132 @@
         {
           "name": "analysis_server unit tests",
           "arguments": [
-            "--compiler=none",
-            "--runtime=vm",
             "--checked",
+            "--compiler=none",
             "--use-sdk",
             "pkg/analysis_server"
           ]
         },
         {
-          "name": "analysis_cli unit tests",
+          "name": "analyzer_cli unit tests",
           "arguments": [
-            "--compiler=none",
-            "--runtime=vm",
             "--checked",
+            "--compiler=none",
             "--use-sdk",
             "pkg/analyzer_cli"
           ]
         },
         {
+          "name": "analyzer_plugin unit tests",
+          "arguments": [
+            "--checked",
+            "--compiler=none",
+            "--use-sdk",
+            "pkg/analyzer_plugin"
+          ]
+        },
+        {
           "name": "front end unit tests",
           "arguments": [
-            "--compiler=none",
-            "--runtime=vm",
             "--checked",
+            "--compiler=none",
+            "--timeout=120",
+            "--use-sdk",
+            "pkg/front_end"
+          ]
+        }
+      ]
+    },
+    {
+      "builders": [
+        "analyzer-linux-release-strong-hostchecked"
+      ],
+      "meta": {
+        "description": "This configuration is used by the analyzer CQ builder running in strong and hostchecked mode."
+      },
+      "steps": [
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": ["create_sdk"]
+        },
+        {
+          "name": "analyze tests",
+          "arguments": [
+            "--compiler=dart2analyzer",
+            "--host-checked",
+            "--strong"
+          ]
+        },
+        {
+          "name": "analyze pkg tests",
+          "arguments": [
+            "--compiler=dart2analyzer",
+            "--host-checked",
+            "--strong",
+            "pkg"
+          ]
+        },
+        {
+          "name": "analyze tests checked",
+          "arguments": [
+            "--checked",
+            "--compiler=dart2analyzer",
+            "--host-checked",
+            "--strong"
+          ]
+        },
+        {
+          "name": "analyze pkg tests checked",
+          "arguments": [
+            "--checked",
+            "--compiler=dart2analyzer",
+            "--host-checked",
+            "--strong",
+            "pkg"
+          ]
+        },
+        {
+          "name": "analyzer unit tests",
+          "arguments": [
+            "--checked",
+            "--compiler=none",
+            "--use-sdk",
+            "pkg/analyzer"
+          ]
+        },
+        {
+          "name": "analysis_server unit tests",
+          "arguments": [
+            "--checked",
+            "--compiler=none",
+            "--use-sdk",
+            "pkg/analysis_server"
+          ]
+        },
+        {
+          "name": "analyzer_cli unit tests",
+          "arguments": [
+            "--checked",
+            "--compiler=none",
+            "--use-sdk",
+            "pkg/analyzer_cli"
+          ]
+        },
+        {
+          "name": "analyzer_plugin unit tests",
+          "arguments": [
+            "--checked",
+            "--compiler=none",
+            "--use-sdk",
+            "pkg/analyzer_plugin"
+          ]
+        },
+        {
+          "name": "front end unit tests",
+          "arguments": [
+            "--checked",
+            "--compiler=none",
             "--timeout=120",
             "--use-sdk",
             "pkg/front_end"
@@ -1378,13 +1479,32 @@
           "arguments": ["create_sdk"]
         },
         {
-          "name": "analyze tests strong",
-          "arguments": ["--compiler=dart2analyzer", "--use-sdk", "--strong"]
+          "name": "analyze tests",
+          "arguments": ["--compiler=dart2analyzer", "--strong", "--use-sdk"]
         },
         {
           "name": "analyze pkg tests",
           "arguments": [
             "--compiler=dart2analyzer",
+            "--strong",
+            "--use-sdk",
+            "pkg"
+          ]
+        },
+        {
+          "name": "analyze tests checked",
+          "arguments": [
+            "--checked",
+            "--compiler=dart2analyzer",
+            "--strong",
+            "--use-sdk"
+          ]
+        },
+        {
+          "name": "analyze pkg tests checked",
+          "arguments": [
+            "--checked",
+            "--compiler=dart2analyzer",
             "--use-sdk",
             "--strong",
             "pkg"
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 380bece..dfb08cb 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -37,7 +37,6 @@
 import 'dart:_internal' hide Symbol;
 import 'dart:html_common';
 import 'dart:indexed_db';
-import 'dart:isolate';
 import "dart:convert";
 import 'dart:math';
 import 'dart:_native_typed_data';
@@ -133,18 +132,6 @@
   HtmlElement.created() : super.created();
 }
 
-/**
- * Spawn a DOM isolate using the given URI in the same window.
- * This isolate is not concurrent.  It runs on the browser thread
- * with full access to the DOM.
- * Note: this API is still evolving and may move to dart:isolate.
- */
-@Experimental()
-Future<Isolate> spawnDomUri(Uri uri, List<String> args, message) {
-  // TODO(17738): Implement this.
-  throw new UnimplementedError();
-}
-
 createCustomUpgrader(Type customElementClass, $this) => $this;
 
 /**
diff --git a/tools/gardening/bin/results_list.dart b/tools/gardening/bin/results_list.dart
index 688d2b3..b90bb6f 100644
--- a/tools/gardening/bin/results_list.dart
+++ b/tools/gardening/bin/results_list.dart
@@ -18,6 +18,7 @@
   argParser.addFlag("csp", negatable: false);
   argParser.addFlag("fasta", negatable: false);
   argParser.addFlag("dart2js-with-kernel", negatable: false);
+  argParser.addFlag("dart2js-old-frontend", negatable: false);
   argParser.addFlag("dart2js-with-kernel-in-ssa", negatable: false);
   argParser.addFlag("enable-asserts", negatable: false);
   argParser.addFlag("fast-startup", negatable: false);
@@ -53,6 +54,7 @@
       argResults["fast-startup"],
       0,
       argResults["dart2js-with-kernel"],
+      argResults["dart2js-old-frontend"],
       argResults["enable-asserts"],
       argResults["hot-reload"],
       argResults["hot-reload-rollback"],
diff --git a/tools/gardening/lib/src/results/configuration_environment.dart b/tools/gardening/lib/src/results/configuration_environment.dart
index 2640ae3..e2da3fb 100644
--- a/tools/gardening/lib/src/results/configuration_environment.dart
+++ b/tools/gardening/lib/src/results/configuration_environment.dart
@@ -28,6 +28,7 @@
   "compiler": new _Variable((c) => c.compiler, Compiler.names),
   "csp": new _Variable.bool((c) => c.csp),
   "dart2js_with_kernel": new _Variable.bool((c) => c.dart2JsWithKernel),
+  "dart2js_old_frontend": new _Variable.bool((c) => c.dart2JsOldFrontend),
   "fasta": new _Variable.bool((c) => c.fasta),
   "fast_startup": new _Variable.bool((c) => c.fastStartup),
   "enable_asserts": new _Variable.bool((c) => c.enableAsserts),
diff --git a/tools/gardening/lib/src/results/result_json_models.dart b/tools/gardening/lib/src/results/result_json_models.dart
index 5d82d62..9f96d48 100644
--- a/tools/gardening/lib/src/results/result_json_models.dart
+++ b/tools/gardening/lib/src/results/result_json_models.dart
@@ -24,6 +24,7 @@
   final bool fastStartup;
   final int timeout;
   final bool dart2JsWithKernel;
+  final bool dart2JsOldFrontend;
   final bool enableAsserts;
   final bool hotReload;
   final bool hotReloadRollback;
@@ -48,6 +49,7 @@
       this.fastStartup,
       this.timeout,
       this.dart2JsWithKernel,
+      this.dart2JsOldFrontend,
       this.enableAsserts,
       this.hotReload,
       this.hotReloadRollback,
@@ -73,6 +75,7 @@
         json["fast_startup"],
         json["timeout"],
         json["dart2js_with_kernel"] ?? false,
+        json["dart2js_old_frontend"] ?? false,
         json["enable_asserts"] ?? false,
         json["hot_reload"] ?? false,
         json["hot_reload_rollback"] ?? false,
@@ -100,6 +103,7 @@
       _stringToArg("builder-tag", builderTag),
       _boolToArg("fast-startup", fastStartup),
       _boolToArg("dart2js-with-kernel", dart2JsWithKernel),
+      _boolToArg("dart2js-old-frontend", dart2JsOldFrontend),
       _boolToArg("enable-asserts", enableAsserts),
       _boolToArg("hot-reload", hotReload),
       _boolToArg("hot-reload-rollback", hotReloadRollback),
@@ -114,7 +118,7 @@
   String toCsvString() {
     return "$mode;$arch;$compiler;$runtime;$checked;$strong;$hostChecked;"
         "$minified;$csp;$fasta;$system;$vmOptions;$useSdk;$builderTag;$fastStartup;"
-        "$dart2JsWithKernel;$enableAsserts;$hotReload;"
+        "$dart2JsWithKernel;$dart2JsOldFrontend;$enableAsserts;$hotReload;"
         "$hotReloadRollback;$previewDart2;$selectors";
   }
 
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index a6d9f5f..d362670 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -245,11 +245,7 @@
       List<String> originalArguments,
       CommandArtifact artifact) {
     var args = <String>[];
-    if (_isStrong) {
-      args.add('--strong');
-      args.add('--reify-generic-functions');
-      args.add('--limit-ints-to-64-bits');
-    }
+    args.add('--preview-dart-2');
     if (_isChecked) {
       args.add('--enable_asserts');
       args.add('--enable_type_checks');
@@ -760,6 +756,7 @@
       args.add('--strong');
     }
     if (useDfe) {
+      args.add('--preview-dart-2');
       args.addAll(_replaceDartFiles(arguments, tempKernelFile(tempDir)));
     } else {
       args.addAll(arguments);
@@ -883,8 +880,8 @@
       args.add('--enable_asserts');
       args.add('--enable_type_checks');
     }
-    if (_isStrong) {
-      args.add('--strong');
+    if (useDfe) {
+      args.add('--preview-dart-2');
     }
     var dir = artifact.filename;
     if (runtimeConfiguration is DartPrecompiledAdbRuntimeConfiguration) {
@@ -1070,15 +1067,16 @@
         ? '${_configuration.buildDirectory}/dart-sdk/lib/_internal'
         : '${_configuration.buildDirectory}';
 
-    final vmPlatform = _isStrong
-        ? '$kernelBinariesFolder/vm_platform_strong.dill'
-        : '$kernelBinariesFolder/vm_platform.dill';
+    // Always use strong platform as preview_dart_2 implies strong.
+    final vmPlatform = '$kernelBinariesFolder/vm_platform_strong.dill';
 
     final dillFile = tempKernelFile(tempDir);
 
     final args = [
       _isAot ? '--aot' : '--no-aot',
-      _isStrong ? '--strong-mode' : '--no-strong-mode',
+      // Specify strong mode irrespective of the value of _isStrong
+      // as preview_dart_2 implies strong mode anyway.
+      '--strong-mode',
       _isStrong ? '--sync-async' : '--no-sync-async',
       '--platform=$vmPlatform',
       '-o',
@@ -1086,12 +1084,10 @@
     ];
     args.add(arguments.where((name) => name.endsWith('.dart')).single);
 
-    if (_isStrong) {
-      // Pass environment variable to the gen_kernel script as
-      // arguments are not passed if gen_kernel runs in batch mode.
-      environmentOverrides = new Map.from(environmentOverrides);
-      environmentOverrides['DART_VM_FLAGS'] = '--limit-ints-to-64-bits';
-    }
+    // Pass environment variable to the gen_kernel script as
+    // arguments are not passed if gen_kernel runs in batch mode.
+    environmentOverrides = new Map.from(environmentOverrides);
+    environmentOverrides['DART_VM_FLAGS'] = '--limit-ints-to-64-bits';
 
     return Command.vmKernelCompilation(dillFile, true, bootstrapDependencies(),
         genKernel, args, environmentOverrides);
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index 0791d9d..ed47086 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -51,6 +51,7 @@
       this.useFastStartup,
       this.useEnableAsserts,
       this.useDart2JSWithKernel,
+      this.useDart2JSOldFrontend,
       this.writeDebugLog,
       this.writeTestOutcomeLog,
       this.writeResultLog,
@@ -124,6 +125,7 @@
   final bool useFastStartup;
   final bool useEnableAsserts;
   final bool useDart2JSWithKernel;
+  final bool useDart2JSOldFrontend;
   final bool writeDebugLog;
   final bool writeTestOutcomeLog;
   final bool writeResultLog;
@@ -253,6 +255,7 @@
     if (useFastStartup) args.add("--fast-startup");
     if (useEnableAsserts) args.add("--enable-asserts");
     if (useDart2JSWithKernel) args.add("--use-kernel");
+    if (useDart2JSOldFrontend) args.add("--use-old-frontend");
     if (isStrong) args.add("--strong");
     return args;
   }
@@ -473,6 +476,7 @@
         'timeout': timeout,
         'preview_dart_2': previewDart2,
         'dart2js_with_kernel': useDart2JSWithKernel,
+        'dart2js_old_frontend': useDart2JSOldFrontend,
         'enable_asserts': useEnableAsserts,
         'hot_reload': hotReload,
         'hot_reload_rollback': hotReloadRollback,
diff --git a/tools/testing/dart/environment.dart b/tools/testing/dart/environment.dart
index 1b9dc2d..47abfea 100644
--- a/tools/testing/dart/environment.dart
+++ b/tools/testing/dart/environment.dart
@@ -20,6 +20,7 @@
   "compiler": new _Variable((c) => c.compiler.name, Compiler.names),
   "csp": new _Variable.bool((c) => c.isCsp),
   "dart2js_with_kernel": new _Variable.bool((c) => c.useDart2JSWithKernel),
+  "dart2js_old_frontend": new _Variable.bool((c) => c.useDart2JSOldFrontend),
   "enable_asserts": new _Variable.bool((c) => c.useEnableAsserts),
   "fast_startup": new _Variable.bool((c) => c.useFastStartup),
   "fasta": new _Variable.bool((c) => c.usesFasta),
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index 03fe413..4b3eac5 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -173,6 +173,9 @@
     new _Option.bool(
         'dart2js_with_kernel', 'Pass the --use-kernel flag to dart2js.',
         hide: true),
+    new _Option.bool(
+        'dart2js_old_frontend', 'Pass the --use-old-frontend flag to dart2js.',
+        hide: true),
     new _Option.bool('hot_reload', 'Run hot reload stress tests.', hide: true),
     new _Option.bool(
         'hot_reload_rollback', 'Run hot reload rollback stress tests.',
@@ -649,6 +652,7 @@
                 useFastStartup: data["fast_startup"] as bool,
                 useEnableAsserts: data["enable_asserts"] as bool,
                 useDart2JSWithKernel: data["dart2js_with_kernel"] as bool,
+                useDart2JSOldFrontend: data["dart2js_old_frontend"] as bool,
                 writeDebugLog: data["write_debug_log"] as bool,
                 writeTestOutcomeLog: data["write_test_outcome_log"] as bool,
                 writeResultLog: data["write_result_log"] as bool,
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 8d9b5df..71d70d4 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -727,6 +727,24 @@
   }
 
   void enqueueFile(String filename, FutureGroup group) {
+    bool match = false;
+    for (var regex in configuration.selectors.values) {
+      String pattern = regex.pattern;
+      if (pattern.contains("/")) {
+        String lastPart = pattern.substring(pattern.lastIndexOf("/") + 1);
+        if (int.parse(lastPart, onError: (_) => -1) >= 0 ||
+            lastPart.toLowerCase() == "none") {
+          pattern = pattern.substring(0, pattern.lastIndexOf("/"));
+        }
+      }
+      if (pattern != regex.pattern) {
+        regex = new RegExp(pattern);
+      }
+      if (regex.hasMatch(filename)) match = true;
+      if (match) break;
+    }
+    if (!match) return;
+
     if (isHtmlTestFile(filename)) {
       var info = html_test.getInformation(filename);
       if (info == null) {
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index 23c945c..8838af5 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -214,7 +214,6 @@
     rebase_path(sdk_summary),
     "--source-map",
     "--source-map-comment",
-    "--inline-source-map",
     "--modules=amd",
     "-o",
     rebase_path("$target_gen_dir/js/amd/dart_sdk.js"),
diff --git a/utils/generate_entry_points_json.gni b/utils/generate_entry_points_json.gni
new file mode 100644
index 0000000..63684c9
--- /dev/null
+++ b/utils/generate_entry_points_json.gni
@@ -0,0 +1,109 @@
+# Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+import("../build/compiled_action.gni")
+import("../build/dart_host_sdk_toolchain.gni")
+
+_dart_root = get_path_info("..", "abspath")
+
+# Template to generate entry points JSON file using dart_bootstrap tool.
+# List of entry points is generated as a by-product while doing precompilation.
+#
+# This template expects the following arguments:
+#  - input: Name of the input dart script for precompilation.
+#  - output: Name of the output entry points JSON file.
+#  - extra_args: Extra arguments to pass to dart_bootstrap (optional).
+#
+template("generate_entry_points_json_with_dart_bootstrap") {
+  assert(defined(invoker.input), "Must define input dart script")
+  assert(defined(invoker.output), "Must define output json file")
+  extra_args = []
+  if (defined(invoker.extra_args)) {
+    extra_args += invoker.extra_args
+  }
+  compiled_action(target_name) {
+    # Printing precompiler entry points is folded into precompilation, so dart_bootstrap is invoked
+    # with correct arguments to generate app-aot snapshot.
+
+    input = invoker.input
+    output = invoker.output
+
+    tool = "$_dart_root/runtime/bin:dart_bootstrap"
+    inputs = [
+      input,
+    ]
+    outputs = [
+      output,
+    ]
+    args = [
+      "--print-precompiler-entry-points=" + rebase_path(output),
+      "--snapshot=" + rebase_path("$target_gen_dir/dummy.snapshot"),
+      "--snapshot-kind=app-aot",
+      "--use-blobs",
+      "--snapshot-kind=app-aot",
+    ] + extra_args + [
+      rebase_path(input),
+    ]
+  }
+}
+
+# Template to generate entry points JSON file using gen_snapshot tool.
+# List of entry points is generated as a by-product while doing precompilation.
+#
+# This template expects the following arguments:
+#  - input: Name of the input dart script for precompilation.
+#  - output: Name of the output entry points JSON file.
+#  - extra_args: Extra arguments to pass to dart_bootstrap (optional).
+#  - extra_inputs: Extra input dependencies (optional).
+#
+template("generate_entry_points_json_with_gen_snapshot") {
+  assert(defined(invoker.input), "Must define input dart script")
+  assert(defined(invoker.output), "Must define output json file")
+  extra_args = []
+  if (defined(invoker.extra_args)) {
+    extra_args += invoker.extra_args
+  }
+  extra_inputs = []
+  if (defined(invoker.extra_inputs)) {
+    extra_inputs += invoker.extra_inputs
+  }
+  compiled_action(target_name) {
+    # Printing precompiler entry points is folded into precompilation, so gen_snapshot is invoked
+    # with correct arguments to generate app-aot snapshot.
+
+    input = invoker.input
+    output = invoker.output
+
+    tool = "$_dart_root/runtime/bin:gen_snapshot"
+    inputs = [
+      input,
+    ] + extra_inputs
+    outputs = [
+      output,
+    ]
+    args = [
+      "--print-precompiler-entry-points=" + rebase_path(output),
+      "--snapshot-kind=app-aot-blobs",
+      "--vm_snapshot_data=" + rebase_path("$target_gen_dir/dummy.vm_data.snapshot"),
+      "--vm_snapshot_instructions=" + rebase_path("$target_gen_dir/dummy.vm_instr.snapshot"),
+      "--isolate_snapshot_data=" + rebase_path("$target_gen_dir/dummy.isolate_data.snapshot"),
+      "--isolate_snapshot_instructions=" + rebase_path("$target_gen_dir/dummy.isolate_instr.snapshot"),
+    ] + extra_args + [
+      rebase_path(input),
+    ]
+  }
+}
+
+# Template to copy checked-in extra entry points JSON file.
+#
+# This template expects the following argument:
+#  - output: Target destination for the extra entry points JSON file.
+#
+template("copy_entry_points_extra_json") {
+  assert(defined(invoker.output), "Must define output json file")
+  copy(target_name) {
+    sources = [ "$_dart_root/pkg/vm/lib/transformations/type_flow/entry_points_extra.json" ]
+    outputs = [ invoker.output ]
+  }
+}